No internet connection
  1. Home
  2. How to

change sample rate in Dante Controller

By Drew Jurecka @Drew_Jurecka
    2021-06-15 20:21:58.795Z

    Hi there,
    I've got a script that sort of works, and I'm hoping for some help!

    I'm successfully reading the sample rate of the open ProTools session, and the script also works to load the presets in Dante Controller (to change the sample rate of the devices on my network to match the sample rate) and dismiss the billion stupid popup windows it generates.

    However, my syntax is wrong somewhere, because the "if" command doesn't stop running once it's set the correct sample rate, and ALSO runs the scripts to set the OTHER sample rates as well.

    Here's the script:

    `// functions to load sample rate presets in Dante Controller and dismiss a billion windows

    function setDante44() {

    sf.ui.app('com.audinate.dante.DanteController').appEnsureIsRunningAndActive();
    
    sf.ui.app('com.audinate.dante.DanteController').appWaitForActive();
    
    sf.keyboard.press({
        keys: "cmd+l",
    });
    
    sf.keyboard.press({
        keys: "down",
    });
    
    sf.keyboard.press({
        keys: "return",
    });
    
    sf.keyboard.press({
        keys: "tab, tab, tab, tab, tab, tab, tab, tab",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.ui.app("com.audinate.dante.DanteController").windows.whoseTitle.is("Preset Progress").first.windowClose();
    
    sf.keyboard.press({
        keys: "cmd+h",
    });
    

    }

    function setDante48() {

    sf.ui.app('com.audinate.dante.DanteController').appEnsureIsRunningAndActive();
    
    sf.ui.app('com.audinate.dante.DanteController').appWaitForActive();
    
    sf.keyboard.press({
        keys: "cmd+l",
    });
    
    sf.keyboard.press({
        keys: "down, down",
    });
    
    sf.keyboard.press({
        keys: "return",
    });
    
    sf.keyboard.press({
        keys: "tab, tab, tab, tab, tab, tab, tab, tab",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.ui.app("com.audinate.dante.DanteController").windows.whoseTitle.is("Preset Progress").first.windowClose();
    
    sf.keyboard.press({
        keys: "cmd+h",
    });
    

    }

    function setDante88() {

    sf.ui.app('com.audinate.dante.DanteController').appEnsureIsRunningAndActive();
    
    sf.ui.app('com.audinate.dante.DanteController').appWaitForActive();
    
    sf.keyboard.press({
        keys: "cmd+l",
    });
    
    sf.keyboard.press({
        keys: "down, down, down",
    });
    
    sf.keyboard.press({
        keys: "return",
    });
    
    sf.keyboard.press({
        keys: "tab, tab, tab, tab, tab, tab, tab, tab",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.ui.app("com.audinate.dante.DanteController").windows.whoseTitle.is("Preset Progress").first.windowClose();
    
    sf.keyboard.press({
        keys: "cmd+h",
    });
    

    }

    function setDante96() {

    sf.ui.app('com.audinate.dante.DanteController').appEnsureIsRunningAndActive();
    
    sf.ui.app('com.audinate.dante.DanteController').appWaitForActive();
    
    sf.keyboard.press({
        keys: "cmd+l",
    });
    
    sf.keyboard.press({
        keys: "down, down, down, down",
    });
    
    sf.keyboard.press({
        keys: "return",
    });
    
    sf.keyboard.press({
        keys: "tab, tab, tab, tab, tab, tab, tab, tab",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.keyboard.press({
        keys: "space",
    });
    
    sf.ui.app("com.audinate.dante.DanteController").windows.whoseTitle.is("Preset Progress").first.windowClose();
    
    sf.keyboard.press({
        keys: "cmd+h",
    });
    

    }
    // function to check session sample rate

    function getSessionSampleRate() {
    if (!sf.ui.proTools.windows.whoseTitle.is('Session Setup').first.exists) {
    sf.ui.proTools.menuClick({
    menuPath: ["Setup", "Session"],
    });
    }

    const win = sf.ui.proTools.windows.whoseTitle.is('Session Setup').first;
    const sessionFormatPanel = win.groups.whoseTitle.is('Session Format').first;
    const sampleRateString = sessionFormatPanel.children.whoseRole.is("AXStaticText").allItems[2].value.invalidate().value;
    
    sf.ui.proTools.menuClick({
        menuPath: ["Setup", "Session"],
    });
    
    const sampleRate = Number(sampleRateString.split(' ')[0]) * 1000;
    
    return sampleRate;
    

    }

    // check the rate

    var sampleRate = getSessionSampleRate();

    // Set Dante Controller Rates Appropriately

    if (sampleRate = 44100) {

    setDante44();
    

    };

    if (sampleRate = 48000) {

    setDante48();
    

    };

    if (sampleRate = 88200) {

    setDante88();
    

    };

    if (sampleRate = 96000) {

    setDante96();
    

    };
    `

    I'd also love advice on whether or not it's possible to have this script trigger automatically when opening or creating a new session in ProTools instead of needing a trigger.

    Thanks!

    Solved in post #2, click to view
    • 12 replies
    1. Dustin Harris @Dustin_Harris
        2021-06-16 11:34:59.998Z

        With (sampleRate = 48000) you’re assigning the variable a new value. To check equality, use two or three equal signs.
        If (sampleRate === 48000) {//do some code}

        Cheers!

        ReplySolution
        1. DDrew Jurecka @Drew_Jurecka
            2021-06-16 14:03:34.886Z

            Thank you! I knew it must be something simple like that, but for some reason I couldn't figure out out.

            Now that this script is working, does anyone have any idea on how to make it run automatically when ProTools starts a new session, or is that even possible?

            1. Dustin Harris @Dustin_Harris
                2021-06-17 03:11:56.938Z

                I think the only reason not to do that is because you’d have to have a script running in the background all the time checking if pro tools as changed. Maybe a good middle ground is to set it to a window trigger of the session setup window, so that any time you open that window sound flow will run the script…

                1. In reply toDrew_Jurecka:
                  Dustin Harris @Dustin_Harris
                    2021-06-17 03:17:38.646Z

                    Also, there might be a cool way to simplify the function so that there is only one function that pressed down the appropriate amount of times for a given sample rate… let me think about it :)

                    1. In reply toDrew_Jurecka:
                      Dustin Harris @Dustin_Harris
                        2021-06-18 01:09:55.252Z

                        I can't test this as I don't have Dante, but I think I might have been able to simplify the script a bit. Let me know if this works:

                        function getSessionSampleRate() {
                            if (!sf.ui.proTools.windows.whoseTitle.is('Session Setup').first.exists) {
                                sf.ui.proTools.menuClick({
                                    menuPath: ["Setup", "Session"],
                                });
                            }
                        
                            const win = sf.ui.proTools.windows.whoseTitle.is('Session Setup').first;
                            const sessionFormatPanel = win.groups.whoseTitle.is('Session Format').first;
                            const sampleRateAsString = sessionFormatPanel.children.whoseRole.is("AXStaticText").allItems[2].value.invalidate().value;
                        
                            sf.ui.proTools.menuClick({
                                menuPath: ["Setup", "Session"],
                            });
                        
                            return sampleRateAsString
                        }
                        
                        
                        
                        /**
                        * @param {string} sampleRate - sample rate as it appears in Pro Tools Session setup window
                        */
                        function setDante(sampleRate) {
                        
                            let sampleRateChoice = {
                                "44.1 kHz": "down",
                                "48 kHz": "down, down",
                                "88.2 kHz": "down, down,  down",
                                "96 kHz": "down, down, down, down",
                            }
                        
                            sf.ui.app('com.audinate.dante.DanteController').appEnsureIsRunningAndActive();
                            sf.ui.app('com.audinate.dante.DanteController').appWaitForActive();
                        
                            sf.keyboard.press({
                                keys: "cmd+l",
                            });
                        
                            sf.keyboard.press({
                                keys: sampleRateChoice[sampleRate],
                            });
                        
                            sf.keyboard.press({
                                keys: "return",
                            });
                        
                            sf.keyboard.press({
                                keys: "tab, tab, tab, tab, tab, tab, tab, tab",
                            });
                        
                            sf.keyboard.press({
                                keys: "space",
                            });
                        
                            sf.keyboard.press({
                                keys: "space",
                            });
                        
                            sf.ui.app("com.audinate.dante.DanteController").windows.whoseTitle.is("Preset Progress").first.windowClose();
                        
                            sf.keyboard.press({
                                keys: "cmd+h",
                            });
                        }
                        
                        setDante(getSessionSampleRate());
                        
                        1. DDrew Jurecka @Drew_Jurecka
                            2021-06-19 05:52:45.601Z

                            wow! I'm relatively new to JavaScript, but I love how you wrote everything into the functions and the actual command is just one line!

                            I think I'm going to try your earlier suggestion of a window trigger, perhaps followed by a timer. The stuff on my dante network are preamps and satellite devices, so even if I set a relatively long timer (say, one minute) before it tries to check the session window I think I'll be in business.

                            Thanks so much for the scripting masterclass!

                            1. DDrew Jurecka @Drew_Jurecka
                                2021-06-19 15:28:01.504Z

                                Well, your streamlined script works great. Thanks!
                                One more question -
                                I've now successfully got this script triggered by the "Dashboard" and "Open" windows, with a 40,000 millisecond timer using sf.wait(), but I was trying to make it a bit more elegant by dong this instead:

                                `sf.ui.proTools.mainWindow.elementWaitFor();

                                sf.ui.proTools.waitForNoModals();`

                                but it times out at 2000 ms, which is usually not enough time to navigate the session open or new session dialogue.

                                Is there a way to change the timeout on elementWaitFor() to extend the amount of time that SoundFlow will wait for the specificed element before cancelling the script?

                                The truly ridiculous thing of course is that this would be unnecessary if Dante Controller would simply add a function that changes the sample rate of specificed devices on a network to match the sample rate of whichever device is clock master but they seem to disagree that this is useful... Ah well!

                                Thanks!

                                1. Dustin Harris @Dustin_Harris
                                    2021-06-19 15:42:45.482Z

                                    with those window triggers, I'm wondering if it's something as simple as waiting for the session setup window to be available?

                                    function main() {
                                        while (!sf.ui.proTools.getMenuItem('Setup', 'Session').isEnabled) sf.wait({ intervalMs: 200 });
                                        setDante(getSessionSampleRate());
                                    }
                                    
                                    main();
                                    
                                    1. DDrew Jurecka @Drew_Jurecka
                                        2021-06-19 15:50:31.543Z

                                        I'll have to test this more, but so far I've opened two sessions and created one new one and this has workd like a charm. thanks!
                                        Just so I can understand what's happening here, is the difference that the "getMenuItem()" doesn't time out the way that "elementWaitFor()" does? Or is it the "while" loop that makes it possible?

                                        Thanks!

                                        1. Dustin Harris @Dustin_Harris
                                            2021-06-19 16:07:08.565Z

                                            Yeah, elementWaitfor() will wait a default of 2 seconds, which you can override like this elementWaitFor({timeout: 40000}); (which is 40 seconds). And you're right the approach i've taken here is: Since the trigger is either the window opening or a new session being created, the script then enters a while loop that checks if the session setup menu option is available (enabled). If it discovers the session setup window option is not enabled, it waits 200ms, then checks again. Once the session window option IS enabled (aka, can be accessed by the user and the program isn't busy still loading the session) the while loop breaks and the script continues.
                                            Now, to be most correct, I'm checking if the menu item is NOT enabled. In javascript you can make any boolean value the opposite by adding a "!" at the beginning. Since we can test if something IS enabled, but not test if it's NOT enabled, we can reverse it like this: something.isEnabled becomes !something.isEnabled. The most distilled version of this is !true === false. Hopefully that all makes sense, I kind of just wrote off of the top of my head...

                                            1. DDrew Jurecka @Drew_Jurecka
                                                2021-06-19 16:12:24.333Z

                                                amazing! You wrote it off the top of your head, but you're clearly bilingual.

                                                I'm still at the "mas cerveza por favor" stage in my JavaScript language comprehension!

                                                Thanks again for all of your help

                                                1. Dustin Harris @Dustin_Harris
                                                    2021-06-19 16:20:50.625Z

                                                    Honestly, I learned everything I know about javascript from using soundFlow, studying other people's scripts, following the recommended tutorials / links on the soundFlow 'Learn' page, and of course a ton of help from the true gurus in the forum. I still have a ton to learn :)