No internet connection
  1. Home
  2. How to

Waiting for the bounce dialog to complete/close

By Andrew Scheps @Andrew_Scheps
    2020-02-16 12:37:59.987Z

    I'm trying to automate bouncing mixes and it's all going very well but I have a question. At the moment the script knows that a bounce is finished by waiting for the audio import dialog to appear. At the moment I have had to put a ridiculously long timeout value on that line of the script so that it doesn't matter how long it takes to bounce. This works fine as long as everything goes as planned, but if I cancel the bounce, that means that the audio import dialog never appears and the script is stuck waiting for it and no other scripts can run. The only way to clear the hung state I've found is quitting and restarting SoundFlow. There must be a more elegant way to do this.

    Solved in post #9, click to view
    • 36 replies

    There are 36 replies. Estimated reading time: 45 minutes

    1. S
      Sreejesh Nair @Sreejesh_Nair
        2020-02-16 13:46:27.981Z

        One idea is you could check to see if the bounce dialog has dissappeared after or before the import dialog appears. If it is before then the script can exit.

        1. Andrew Scheps @Andrew_Scheps
            2020-02-16 20:37:02.133Z

            Unfortunately the Bounce dialog goes away as soon as the bounce starts. What I really ned to do is wait for the progress window to disappear, but I can't seem to get to it with SoundFLow or Accessibility Inspector so I can't tell the script to wait for it.

            1. Hi Andrew. I have a long script that works with the Bounce dialog and is very stable. I'll see if I can get it up here asap.

              1. Andrew Scheps @Andrew_Scheps
                  2020-02-16 20:46:49.182Z

                  Thanks Christian. I thought I could use sf.ui.proTools.waitForNoModals(); Unfortunately this treats the entire sequence of bounce dialog->progress wondow->Audio Import dialog as all one modal so it never goes on to automate the audio import dialog. The script works great as long as I don't cancel the bounce. If I do SoundFlow gets confused and has to be relaunched.

                • In reply toAndrew_Scheps:
                  SSreejesh Nair @Sreejesh_Nair
                    2020-02-17 03:28:32.476Z

                    Sure Andrew. Thats what I meant. My bad! I have added a code below modified from Christians code. Maybe it may help?

                • In reply toAndrew_Scheps:
                  Andrew Scheps @Andrew_Scheps
                    2020-02-16 20:48:10.777Z

                    And in case I wasn't clear, all of my automation of the bounce dialog and the audio import dialog works great and is absolutely bullet-proof, as long as I don't cancel the bounce. I'm needing to put a ridiculously long wait time on the audio import appearance.

                    1. Nice yea I just re-read your question. What you need here is essentially some logic that says wait for the audio import dialog to appear OR for all modal windows to be gone (in the event of a cancelled bounce).
                      That should be doable, it just requires a little more tweaking. Can you share the code you use to wait for the Audio Import dialog? Then I should be able to tweak it for you.

                      Note - you can also always cancel all running SF commands by hitting Ctrl+Shift+Esc (if you use default SoundFlow triggers). If you don't, you can assign your own shortcut to cancelling all running commands in the SoundFlow System package: "Stop All Running Commands" command:

                      1. Andrew Scheps @Andrew_Scheps
                          2020-02-16 20:54:06.623Z2020-02-16 20:54:32.102Z

                          Ah, very good to know! Here's the part of the script that waits for the audio import to appear (note the long wait time).

                          //Start bounce
                          sf.ui.proTools.windows.whoseTitle.is('Bounce').first.buttons.whoseTitle.is('Bounce').first.elementClick();
                          sf.ui.proTools.windows.whoseTitle.is('Bounce').first.elementWaitFor({
                              waitType: "Disappear",
                              timeout: 10000, //This can take a while to start sometimes
                          });
                          //Wait for bounce to finish
                          
                          
                          sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first.elementWaitFor({
                              waitType: "Appear",
                              timeout: 1000000,
                          });
                          
                          1. I think you should be able to do this:

                            //Start bounce
                            sf.ui.proTools.windows.whoseTitle.is('Bounce').first.buttons.whoseTitle.is('Bounce').first.elementClick();
                            sf.ui.proTools.windows.whoseTitle.is('Bounce').first.elementWaitFor({
                                waitType: "Disappear",
                                timeout: 10000, //This can take a while to start sometimes
                            });
                            
                            //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                            sf.ui.proTools.confirmationDialog.elementWaitFor({ timeout: 10000 });
                            sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                            
                            //Now that we know the bounce is either cancelled or finished, no need for a long wait time for the Audio Import Options to appear
                            //Let's keep it short. Then the 2nd parameter is the error handling function - it will be called if there's a timeout, which indicates this bounce was cancelled.
                            sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first.elementWaitFor({
                                timeout: 2000,
                            }, () => {
                                //Error - so, we timed out. Likely this is due to cancel of bounce
                                log('Bounce cancelled');
                                //Abort the script silently
                                throw 0;
                            });
                            
                            ReplySolution
                            1. Oops wait - this had the wrong dialog (I was testing with a consolidate).

                              Try this instead:

                              //Start bounce
                              sf.ui.proTools.windows.whoseTitle.is('Bounce').first.buttons.whoseTitle.is('Bounce').first.elementClick();
                              sf.ui.proTools.windows.whoseTitle.is('Bounce').first.elementWaitFor({
                                  waitType: "Disappear",
                                  timeout: 10000, //This can take a while to start sometimes
                              });
                              
                              //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                              var bouncingLabel = sf.ui.proTools.windows.whoseTitle.is('').first.children.whoseRole.is("AXStaticText").whoseValue.is('Bouncing...').first;
                              bouncingLabel.elementWaitFor({ timeout: 10000 });
                              bouncingLabel.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                              
                              //Now that we know the bounce is either cancelled or finished, no need for a long wait time for the Audio Import Options to appear
                              
                              var success = sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first.elementWaitFor({
                                  timeout: 2000,
                                  onError: 'Continue'
                              }).success;
                              if (!success) {
                                  log('Bounce cancelled');
                                  throw 0;
                              }
                              
                              //Now do something with the Audio Import Options dialog
                              
                              1. Andrew Scheps @Andrew_Scheps
                                  2020-02-16 23:06:10.151Z

                                  Actually, the second one doesn't work. I get an error waiting for bouncingLabel to disappear. First one works fine.

                                • In reply tochrscheuer:
                                  Andrew Scheps @Andrew_Scheps
                                    2020-02-16 21:31:49.885Z

                                    This seems to work! Basically, if you cancel then it continues the script, exiting after the unsuccessful 2 second wait for the Audio Import dialog. Thanks!

                            2. In reply toAndrew_Scheps:
                              Andrew Scheps @Andrew_Scheps
                                2020-02-19 10:24:41.788Z

                                Well, I've been using the script and neither of these solutions work. The first one works in the sense that SoundFlow doesn't get stuck waiting for the Audio Import Dialog if I cancel the bounce, but if I let the bounce go ahead the script never continues when the Audio Import Options dialog appears. So, whether Pro Tools doesn't let you know that the bounce dialog has come up or something else weird is happening. If I go back to my original script everything works fine as long as I don't cancel the bounce.

                                1. In reply toAndrew_Scheps:
                                  Andrew Scheps @Andrew_Scheps
                                    2020-02-20 17:12:40.215Z

                                    I think I still don't quite get it and would love a generic way to test for the opening and closing of the Pro Tools progress windows. This comes up on anything that takes a while (bouncing, exporting, consolidating, AS processing etc) and it seems very clumsy to use long wait times. I've tried using the code above and it doesn't work reliably.

                                    1. I think the different processes need different solutions unfortunately (right now). The best way to get to a solution that works for all processes would be to take them one step at a time and look very specifically on why and when they break (preferably send us script examples and a step-by-step on exactly when in the process it fails). This will eventually help us figure out the corner case scenarios which will lead to more stability, and then ultimately from that we can derive a function that could work across all scenarios.
                                      But right now I'm afraid there's no one-solution-fits-all without getting more into the details first.

                                      1. Andrew Scheps @Andrew_Scheps
                                          2020-02-21 10:19:57.837Z

                                          Here are the two that I'm stuck on at the moment.

                                          1. Bounce to Disk:
                                            As detailed above, when bouncing to disk it can take quite a while. I am always importing the bounce after it finishes so I can have the script wait for the Audio Import dialog to appear but you have to use a wait time of -1 (or at least longer than the bounce will ever take). As we've discussed above, if you cancel the bounce the dialog never appears and SoundFlow is left waiting forever. The code you put above to fix it above doesn't work reliably for me for some reason.
                                            One workaround would be to estimate the bounce time based on the selection length and then adjust a variable wait time to be just long enough that it should work. Not elegant, but I suppose I should try it.

                                          2. Export Clips as Files:
                                            This one is trickier because there is no dialog that comes up afterwards, the end of the process is when the progress dialog disappears. You either have to make sure it is the last step in your script so the script has finished before the export, or you would have to put an arbitrarily long wait time that would allow for the longest export you think you would ever do. But of course this approach means you would have to wait that long every time you used the script, even if exporting a short file. Again, I suppose a probable wait time could be calculated based on clip length and source and destination sample rate, but not an ideal solution.

                                          I think what I was saying in my last comment was the "generic" part is that Pro Tools seems to "lock up" while the progress dialogs are on the screen so SoundFLow doesn't actually seem to know about them. You can see how problematic they are if you initiate either a very long bounce or export, then while it is running use the the "choose" function in any action that allows you to click on a UI element to get its ID and you'll see that you can't even select the progress window in most cases. If we can fix this visibility issue with PTs progress windows then this would all be moot.

                                          Let me know if you'd like any more info or code, though I think my code is simplistic enough when it comes to initiating the processes.

                                          Thanks!

                                          1. Kitch Membery @Kitch2020-02-22 05:45:03.503Z

                                            @chrscheuer & @Andrew_Scheps

                                            I've just been perusing over the thread and assuming I understand correctly what you are trying to figure out with the “1. Bounce to disk” issue… the following script sequence may work (I’d have to have a think about how to implement it as it may be above my current javascript knowledge);

                                            1. When starting the bounce set up a loop to check if the main window of Pro Tools has regained focus.
                                            2. Once the main window of Pro Tools regains focus, have the script check to see if the new bounced file exists in the Bounces folder.
                                            3. If the new bounce does not exist have the script terminate.

                                            With this scenario, if the bounce was canceled midway through, the script would see that there is no bounced file created, the script would terminate and therefore not continue to look for the Audio Import dialogue.

                                            If I’m way off the mark… Please ignore these ramblings :-)

                                            1. Andrew Scheps @Andrew_Scheps
                                                2020-02-22 10:49:32.739Z

                                                That sounds like an approach that might work! It's WAY over my programming level though.

                                                1. Kitch Membery @Kitch2020-02-23 01:38:09.236Z

                                                  Me too Andrew... although part 3 would look something like this. Assuming you are using the variable "newPlaylistName" from your script.

                                                  //Get the directory (folder) of the currently open PT session
                                                  var sessionDir = sf.ui.proTools.mainWindow.sessionPath.split('/').slice(0, -1).join('/');
                                                  //Name of Folder within session directory
                                                  var folderName = "Bounced Files"
                                                  
                                                  //Check to see if the file with variable "newPlaylistName" exists
                                                  var file = sf.file.exists({path: sessionDir+"/"+folderName+"/"+newPlaylistName+".wav"});
                                                  if(!file.exists){
                                                      log("File does not exist!")
                                                      throw("Script Terminated")
                                                  }
                                                  else{
                                                      log("File exist!")
                                                  };
                                                  

                                                  As for part 1 and 2... possibly using a javascript "while (false)" loop, that waits for the main window of Pro Tools to be in focus would work.

                                                  Back in July, Christian created a post on "How to run a script in background and check for a state" that may be the key to getting it all working. Here is the link.

                                                  https://forum.soundflow.org/-824/how-to-run-a-script-in-background-and-check-for-a-state

                                                  Unfortunately I'm on a project with a tight deadline at the moment so won't be able attempt a solution for the next week or so.

                                                  1. Andrew Scheps @Andrew_Scheps
                                                      2020-02-23 10:06:03.411Z

                                                      Thanks Kitch, this looks like the way to go about it. And I suppose the wait loop shouldn't actually be a background task, but foreground and then check for the bounced file. I have the path and name of the bounced file in variable so that check is very easy to make. Nice one!

                                                      This thread might have the skeleton of what I need, I'll report back if I get it working.
                                                      https://forum.soundflow.org/-1159/how-to-wait-for-rx7-audio-editor-to-open-before-proceeding

                                                      1. Kitch Membery @Kitch2020-02-23 10:20:06.016Z

                                                        That looks really promising! Keep me posted Andrew.

                                                      2. In reply toKitch:
                                                        Andrew Scheps @Andrew_Scheps
                                                          2020-02-23 11:43:40.361Z2020-02-23 12:06:40.673Z

                                                          This works perfectly with the code Christian did earlier to track the progress window appearing and disappearing.

                                                          //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                                                          sf.ui.proTools.confirmationDialog.elementWaitFor({ timeout: 10000 });
                                                          sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                                                          
                                                          // See if bounce completed normally or was cancelled by checking for the existence of the bounced file
                                                          //Check to see if the file with variable "newPlaylistName" exists
                                                          var file = sf.file.exists({path: bounceDir+"/"+newPlaylistName+".wav"});
                                                          if(!file.exists){
                                                              log("File does not exist, bounce cancelled!");
                                                              throw(0);
                                                          };
                                                          

                                                          It waits for the progress bar to appear and disappear and then checks to see if the file exists. If it doesn't the bounce must have been cancelled so abort the script, otherwise continue.

                                                          The only issue this has is if the bounce happens so fast that the progress dialog doesn't appear, then the script times out waiting for it. In real life there's nothing I bounce that doesn't take long enough for the dialog to appear so it won't come up, but I suppose it's a bit messy.

                                                          I've added the same code to watch out for the Export Selected as Files progress dialog to appear and disappear and that works fine. I don't need to test for cancellation on that because nothing else relies on it.

                                                          I suppose the real takeaway here is that the simple lines waiting for progress dialog to appear and disappear are the perfect 'generic' code for long processes, it's the testing for whether they were cancelled or not that will have to be specific to each function.

                                                          Thanks!

                                                          1. Kitch Membery @Kitch2020-02-23 18:46:53.871Z

                                                            Nice work mate! I'd love to see the full script on this one.

                                                            1. Andrew Scheps @Andrew_Scheps
                                                                2020-02-23 20:42:49.863Z

                                                                You asked for it...

                                                                There is a lot of stuff specific to my workflow and there's a lot that should be tightened up code-wise but it works! I have a variant of this that lets me specify a name and does it slightly differently for printing other types of mixes. Saving me so much time, and I can hit the button and walk away!

                                                                // This script prints the next reference mix for a session given some rather stringent parameters:
                                                                //  1) The Print Track has to be the bottom-most track in the session, including hidden tracks
                                                                //  2) There has to already be a playlist on the Print track that ends in a revision number that can be incremented.
                                                                //  3) There has to a clip on the print track that represents the bounce selection, and it has to be the first clip on the track
                                                                //          note: I satisfy 2 and 3 for the first ref by making a playlist whos name ends in "R0" that has a clip group for the desired bounce selection
                                                                //  4) I always want the mix bounced into the local Bounced Files directory
                                                                //  5) I always want to export a 44.1/16 bit copy to a folder called " Refs" one level above the session folder
                                                                //  6) I am always printing a bus called "Print"
                                                                
                                                                // I'm sure there is a lot of this that should be separated into functions and made neater, but it does actually work and is pretty bullet proof.
                                                                
                                                                sf.ui.proTools.appActivateMainWindow();
                                                                
                                                                // Dialog to remind me which button I just hit on the Stream Deck
                                                                if (!confirm(`This Script will increment the Print Track playist, bounce and export a ref\nDo you want to continue?`))
                                                                    throw 0;
                                                                
                                                                
                                                                //Get and Increment Last Number - We'll use this for the new playlist name
                                                                function getAndIncrementLastNumber(str) {
                                                                    return str.replace(/\d+$/, function (s) {
                                                                        return ++s;
                                                                    });
                                                                }
                                                                
                                                                // Set variables so Bounce directory can be set back to default if it has been changed
                                                                var sessionDir = sf.ui.proTools.mainWindow.sessionPath.split('/').slice(0, -1).join('/');
                                                                var bounceDir = `${sessionDir}/Bounced Files`;
                                                                //Make sure our new bounce dir exists
                                                                sf.system.exec({ commandLine: 'mkdir -p "' + bounceDir + '"' });
                                                                
                                                                // Get name of last track (which has to be the print track)
                                                                var lastTrackName = sf.ui.proTools.trackNames.slice(-1)[0];
                                                                
                                                                // Scroll the track into view
                                                                sf.ui.proTools.trackSelectByName({ deselectOthers: true, names: [lastTrackName] });
                                                                sf.ui.proTools.selectedTrack.trackScrollToView();
                                                                
                                                                // Select the existing mix
                                                                if (sf.ui.proTools.getMenuItem('Options', 'Tab to Transient').isMenuChecked)
                                                                {
                                                                    //Tab to Transient is enabled - disable it
                                                                    sf.ui.proTools.menuClick({
                                                                    menuPath: ["Options","Tab to Transient"],
                                                                });
                                                                }
                                                                else 
                                                                {
                                                                    //Tab to Transient is not enabled - good!
                                                                };
                                                                // Select first clip on teh track
                                                                sf.keyboard.press({
                                                                    keys: "return, tab, shift+tab",
                                                                });
                                                                
                                                                // Create name of playlist
                                                                var newPlaylistName = getAndIncrementLastNumber(lastTrackName);
                                                                
                                                                //Duplicate the current playlist
                                                                sf.ui.proTools.selectedTrack.popupButtons.whoseTitle.is('Playlist selector').first.popupMenuSelect({
                                                                    menuPath: ["Duplicate..."],
                                                                });
                                                                
                                                                //Wait for Duplicate Playlist window to appear
                                                                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: "Appear", });
                                                                
                                                                // Put in new playlist name
                                                                sf.ui.proTools.confirmationDialog.textFields.first.elementSetTextFieldWithAreaValue({ value: newPlaylistName });
                                                                
                                                                //Click OK in Duplicate Playlist window
                                                                sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is('OK').first.elementClick();
                                                                
                                                                //Wait for Duplicate Playlist window to disappear
                                                                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: "Disappear", });
                                                                
                                                                // ------------- Get current session smaple rate -----------
                                                                // See if the Session Setup window is open and if not, open it
                                                                var sessionSetupWin = sf.ui.proTools.windows.whoseTitle.is('Session Setup');
                                                                if (sessionSetupWin && sessionSetupWin.exists) {
                                                                    //audio suite window is open
                                                                } else {
                                                                    sf.ui.proTools.menuClick({
                                                                    menuPath: ["Setup", "Session"],
                                                                });
                                                                var sessionSetupDlg = sf.ui.proTools.dialogWaitForManual({
                                                                    dialogTitle: 'Session Setup'
                                                                }).dialog;
                                                                };
                                                                
                                                                // Get the current session sample rate
                                                                var currentSampleRate = sf.ui.proTools.windows.whoseTitle.is('Session Setup').first.groups.whoseTitle.is('Session Format').first.children.whoseRole.is("AXStaticText").allItems[2].value.value;
                                                                
                                                                // Close the Session Setup window
                                                                sf.ui.proTools.menuClick({
                                                                    menuPath: ["Setup", "Session"],
                                                                })
                                                                
                                                                //Wait for 'Session Setup' window to disappear
                                                                sf.ui.proTools.windows.whoseTitle.is('Session Setup').first.elementWaitFor({
                                                                    waitType: "Disappear",
                                                                });
                                                                
                                                                
                                                                //----------------------------------------------------------|
                                                                //                  Set up bounce!                          |
                                                                //----------------------------------------------------------|
                                                                
                                                                
                                                                // Open bounce to disk dialog
                                                                sf.ui.proTools.menuClick({
                                                                    menuPath: ["File", "Bounce to", "Disk..."],
                                                                    looseMatch: true,
                                                                });
                                                                
                                                                //Wait for the 'Bounce' dialog to appear and assign it to the bounceDlg variable
                                                                var bounceDlg = sf.ui.proTools.dialogWaitForManual({
                                                                    dialogTitle: 'Bounce'
                                                                }).dialog;
                                                                
                                                                // The next bit is stolen and adapted from Marco, thanks Marco!
                                                                //Special code for now (this will change and be made easier)
                                                                //What this does is get the Children of the bounceDialog, filter them so we only get the popupbuttons,
                                                                //and then slice the resulting array so the we only get the last 5.
                                                                //This is needed since there are no names/titles/labels on the 4 buttons used to set up file type, format, bit depth and samplerate
                                                                //and you don't know how many bounce sources there might be when you open the dialog
                                                                
                                                                var popupButtons = bounceDlg.getElements("AXChildren").filter(function (e) { return e.fullRole == "AXPopUpButton" }).slice(-5);
                                                                
                                                                //Assign the five buttons coming out of the previous instruction to individual variables
                                                                var bounceSource = popupButtons[0];
                                                                var fileTypeBtn = popupButtons[1];
                                                                var formatBtn = popupButtons[2];
                                                                var bitDepthBtn = popupButtons[3];
                                                                var sampleRateBtn = popupButtons[4];
                                                                var deliverFormat = popupButtons[5];
                                                                
                                                                //If the source is not already Print, use the popupMenuSelect action to select it
                                                                if (bounceSource.value.value != 'Print (Stereo)')
                                                                    sf.ui.proTools.windows.whoseTitle.is('Bounce').first.popupButtons.first.popupMenuSelect({
                                                                        menuPath: ["bus", "Print*"],
                                                                        useWildcards: true,
                                                                    });
                                                                
                                                                // Set the resot of the bounce parameters
                                                                if (fileTypeBtn.value.value != 'WAV')
                                                                    fileTypeBtn.popupMenuSelect({ menuPath: ['WAV'] });
                                                                
                                                                if (sampleRateBtn.value.value != currentSampleRate)
                                                                    sampleRateBtn.popupMenuSelect({ menuPath: [currentSampleRate] });
                                                                
                                                                if (formatBtn.value.value != 'Interleaved')
                                                                    formatBtn.popupMenuSelect({ menuPath: ['Interleaved'] });
                                                                
                                                                if (bitDepthBtn.value.value != '24 Bit')
                                                                    bitDepthBtn.popupMenuSelect({ menuPath: ['24 Bit'] });
                                                                
                                                                //Make sure offline and import after bounce are selected
                                                                sf.ui.proTools.windows.whoseTitle.is('Bounce').first.checkBoxes.whoseTitle.is('Import After Bounce').first.checkboxSet({
                                                                    targetValue: "Enable",
                                                                });
                                                                sf.ui.proTools.windows.whoseTitle.is('Bounce').first.checkBoxes.whoseTitle.is('Offline').first.checkboxSet({
                                                                    targetValue: "Enable",
                                                                });
                                                                
                                                                //--------------------------------------- Set the path to default----------------------------
                                                                // again, stolen code, I think from Fokke, thanks!
                                                                
                                                                function navigateToInDialog(win, path) {
                                                                    //Open the Go to... sheet
                                                                    sf.keyboard.type({ text: '/' });
                                                                
                                                                    //Wait for the sheet to appear
                                                                    var sheet = win.sheets.first.elementWaitFor({ timeout: 500 }, 'Could not find "Go to" sheet in the Save/Open dialog').element;
                                                                
                                                                    //Set the value of the combo box
                                                                    sheet.comboBoxes.first.value.value = path;
                                                                
                                                                    //Press OK
                                                                    sheet.buttons.whoseTitle.is('Go').first.elementClick({}, 'Could not click "Go"');
                                                                
                                                                    //Wait for sheet to close
                                                                    win.sheets.first.elementWaitFor({ waitForNoElement: true, timeout: 500 }, '"Go to" sheet didn\'t close in time');
                                                                }
                                                                
                                                                
                                                                function openDialogFolder(folder) {
                                                                    var openDlg = sf.ui.proTools.windows.whoseTitle.is('Open').first;
                                                                
                                                                    navigateToInDialog(openDlg, folder);
                                                                
                                                                    //Click OK
                                                                    openDlg.buttons.whoseTitle.is('Open').first.elementClick();
                                                                
                                                                    //Wait for the Open dialog to close
                                                                    openDlg.elementWaitFor({ waitForNoElement: true });
                                                                }
                                                                
                                                                //Set the bounce directory if necessary
                                                                
                                                                var existingDirectory = sf.ui.proTools.windows.whoseTitle.is('Bounce').first.children.whoseRole.is("AXStaticText").allItems[6].value.value;
                                                                if (existingDirectory !== bounceDir + "/") {
                                                                    sf.ui.proTools.windows.whoseTitle.is('Bounce').first.buttons.whoseTitle.is('Choose...').first.elementClick();
                                                                
                                                                    openDialogFolder(bounceDir);
                                                                
                                                                }
                                                                //----------------------------------------------------------------------------
                                                                
                                                                // Use our new playlist name for the file name
                                                                sf.ui.proTools.windows.whoseTitle.is('Bounce').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({
                                                                    value: newPlaylistName,
                                                                });
                                                                
                                                                //Start bounce
                                                                sf.ui.proTools.windows.whoseTitle.is('Bounce').first.buttons.whoseTitle.is('Bounce').first.elementClick();
                                                                sf.ui.proTools.windows.whoseTitle.is('Bounce').first.elementWaitFor({
                                                                    waitType: "Disappear",
                                                                    timeout: 10000, //This can take a while to start sometimes
                                                                });
                                                                //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                                                                sf.ui.proTools.confirmationDialog.elementWaitFor({ timeout: 10000 });
                                                                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                                                                
                                                                // See if bounce completed normally or was cancelled by checking for the existence of the bounced file
                                                                //Check to see if the file with variable "newPlaylistName" exists
                                                                var file = sf.file.exists({path: bounceDir+"/"+newPlaylistName+".wav"});
                                                                if(!file.exists){
                                                                    log("File does not exist, bounce cancelled!");
                                                                    throw(0);
                                                                };
                                                                
                                                                // Import mix to session in Clip list
                                                                
                                                                var win = sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first;
                                                                win.radioButtons.whoseTitle.startsWith('Clip List').first.elementClick();
                                                                sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first.buttons.whoseTitle.is('OK').first.elementClick();
                                                                sf.ui.proTools.windows.whoseTitle.is('Audio Import Options').first.elementWaitFor({
                                                                    waitType: "Disappear",
                                                                });
                                                                
                                                                //----------------------------------------------------------|
                                                                //                  Bounce Finished!                        |
                                                                //   Export ref and get bounced Mix onto Print Track        |
                                                                //----------------------------------------------------------|
                                                                
                                                                //Make sure clip list is showing
                                                                sf.ui.proTools.menuClick({
                                                                    menuPath: ["View", "Other Displays", "Clip List"],
                                                                    targetValue: 'Enable'  //or 'Enable' or 'Toggle'
                                                                });
                                                                
                                                                
                                                                //----------------------------------------------------------|
                                                                //                     Export Mix                           |
                                                                //----------------------------------------------------------|
                                                                
                                                                //Reselect mix on Print Track
                                                                //There was code here to re-select it but it never gets deselected in this order of operations...
                                                                
                                                                sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                                                                    menuPath: ["Export Clips as Files..."],
                                                                });
                                                                
                                                                
                                                                var exportDlg = sf.ui.proTools.dialogWaitForManual({
                                                                    dialogTitle: "Export Selected"
                                                                }).dialog;
                                                                
                                                                //Get the Children of the Export Selected dialog, filter them so we only get the popupbuttons,
                                                                
                                                                var popupButtons = exportDlg.getElements("AXChildren").filter(function (e) { return e.fullRole == "AXPopUpButton" });
                                                                
                                                                //Assign thefourthree buttons coming out of the previous instruction to individual variables
                                                                var sampleRate = popupButtons[0];
                                                                var bitDepth = popupButtons[1];
                                                                var fileFormat = popupButtons[2];
                                                                var fileTypeBtn = popupButtons[3];
                                                                
                                                                //Change any options that aren't right
                                                                if (fileTypeBtn.value.value != 'WAV')
                                                                    fileTypeBtn.popupMenuSelect({ menuPath: ['WAV'] });
                                                                
                                                                if (fileFormat.value.value != 'Interleaved')
                                                                    fileFormat.popupMenuSelect({ menuPath: ['Interleaved'] });
                                                                
                                                                if (bitDepth.value.value != '16 Bit')
                                                                    bitDepth.popupMenuSelect({ menuPath: ['16 Bit'] });
                                                                
                                                                if (sampleRate.value.value != '44.1 kHz')
                                                                    sampleRate.popupMenuSelect({ menuPath: ['44.1 kHz'] });
                                                                
                                                                //--------------------------------
                                                                // Set the export directory to the refs folder - I probably didn't need to copy these and rename them but I haven't gone back to see if anything changed so better safe than sorry
                                                                //--------------------------------
                                                                
                                                                function navigateToInDialog2(win, path) {
                                                                    //Open the Go to... sheet
                                                                    sf.keyboard.type({ text: '/' });
                                                                
                                                                    //Wait for the sheet to appear
                                                                    var sheet = win.sheets.first.elementWaitFor({ timeout: 500 }, 'Could not find "Go to" sheet in the Save/Open dialog').element;
                                                                
                                                                    //Set the value of the combo box
                                                                    sheet.comboBoxes.first.value.value = path;
                                                                
                                                                    //Press OK
                                                                    sheet.buttons.whoseTitle.is('Go').first.elementClick({}, 'Could not click "Go"');
                                                                
                                                                    //Wait for sheet to close
                                                                    win.sheets.first.elementWaitFor({ waitForNoElement: true, timeout: 500 }, '"Go to" sheet didn\'t close in time');
                                                                }
                                                                
                                                                
                                                                function openDialogFolder2(folder) {
                                                                    var openDlg = sf.ui.proTools.windows.whoseTitle.is('Open').first;
                                                                
                                                                    navigateToInDialog2(openDlg, folder);
                                                                
                                                                    //Click OK
                                                                    openDlg.buttons.whoseTitle.is('Open').first.elementClick();
                                                                
                                                                    //Wait for the Open dialog to close
                                                                    openDlg.elementWaitFor({ waitForNoElement: true });
                                                                };
                                                                
                                                                // Set a variable to the desired refs directory in the sessions parent folder
                                                                var exportDirectory = sf.ui.proTools.mainWindow.sessionPath.split('/').slice(0, -2).join('/') + "/ Refs";
                                                                
                                                                //Make sure our desired export dir exists
                                                                sf.system.exec({ commandLine: 'mkdir -p "' + exportDirectory + '"' });
                                                                
                                                                //Get the current export directory - I'm sure this can all be done one line but, well, newbie
                                                                var existingDirectory = sf.ui.proTools.windows.whoseTitle.is('Export Selected').first.children.whoseRole.is("AXStaticText").allItems[5].value.value;
                                                                var modifiedDirectory = "/"+ existingDirectory.substring(0, existingDirectory.length - 1).split(":").slice (1).join('/');
                                                                
                                                                if (modifiedDirectory !== exportDirectory) { 
                                                                    sf.ui.proTools.windows.whoseTitle.is('Export Selected').first.buttons.whoseTitle.is('Choose...').first.elementClick();
                                                                
                                                                    openDialogFolder2(exportDirectory);
                                                                }
                                                                
                                                                // Start the Export
                                                                sf.ui.proTools.windows.whoseTitle.is('Export Selected').first.buttons.whoseTitle.is('Export...').first.elementClick();
                                                                
                                                                sf.ui.proTools.windows.whoseTitle.is('Export Selected').first.elementWaitFor({
                                                                    waitType: "Disappear",
                                                                });
                                                                
                                                                //Wait for export to finish (Wait for progress dialog to appear, then to disappear)
                                                                sf.ui.proTools.confirmationDialog.elementWaitFor({ timeout: 10000 });
                                                                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                                                                // No need to check if I cancelled or not, it's just an external file that nothing else relies on
                                                                
                                                                // Get the bounced mix onto the Print track
                                                                // Use the clip list search function to make it the only displayed clip so we know where it is
                                                                sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                                                                    menuPath: ["Find..."],
                                                                });
                                                                sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.elementWaitFor({
                                                                    waitType: "Appear",
                                                                });
                                                                
                                                                sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({
                                                                    value: newPlaylistName,
                                                                });
                                                                
                                                                sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.buttons.whoseTitle.is('OK').first.elementClick();
                                                                
                                                                sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.elementWaitFor({
                                                                    waitType: "Disappear",
                                                                });
                                                                
                                                                // Place clip on the print track
                                                                
                                                                // Open Replace Clip dialog for first clip
                                                                
                                                                sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first.children.whoseRole.is("AXRow").whoseValue.is('').allItems[0].children.whoseRole.is("AXCell").allItems[1].children.whoseRole.is("AXStaticText").first.popupMenuSelect({
                                                                    isRightClick: true,
                                                                    menuPath: ["Replace Clip..."],
                                                                });
                                                                
                                                                sf.ui.proTools.replaceClipDialog.elementWaitFor({
                                                                    waitType: "Appear",
                                                                });
                                                                
                                                                // Make sure we're only replacing the previous mix
                                                                sf.ui.proTools.replaceClipDialog.radioButtons.whoseTitle.is('original clip only').first.elementClick();
                                                                sf.ui.proTools.replaceClipDialog.radioButtons.whoseTitle.is('replacement clip length').first.elementClick();
                                                                
                                                                // Do it
                                                                sf.ui.proTools.replaceClipDialog.buttons.whoseTitle.is('OK').first.elementClick();
                                                                sf.ui.proTools.replaceClipDialog.elementWaitFor({
                                                                    waitType: "Disappear",
                                                                });
                                                                // Clear the Find in the clip bin
                                                                sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({
                                                                    menuPath: ["Clear Find"],
                                                                });
                                                                // That's it!
                                                                
                                                                1. Kitch Membery @Kitch2020-02-23 20:52:10.009Z

                                                                  Awesome! But why would you walk away when you can sit back and watch all this cool automation. Well for the first bunch of times at least. :-)

                                                                  1. Andrew Scheps @Andrew_Scheps
                                                                      2020-02-23 20:54:10.428Z

                                                                      Oh believe me, I’ve watched it plenty!

                                                                      1. Kitch Membery @Kitch2020-02-23 20:54:56.060Z

                                                                        Hahahaha!

                                                                        1. Holy ####, guys. I love seeing what you're building here together! That script is insane haha.

                                                                          1. Kitch Membery @Kitch2020-02-23 21:39:28.666Z

                                                                            Team work makes the dream work! Now we just have to write a SoundFlow script that edits audio/mixes albums/pays bills & cashes checks for us while we sip on Pina colada's in Fiji :-)

                                                                    • In reply toAndrew_Scheps:

                                                                      Wow, this is god-level scripting.

                                                    • In reply toAndrew_Scheps:
                                                      Andrew Scheps @Andrew_Scheps
                                                        2020-05-19 11:05:30.529Z

                                                        Soooo, I'm cleaning up this script into functions etc and have decided to fix a few things along the way.

                                                        The only real issue with the script (other than not being flexible enough) is this code (courtesy of Christian in a post in this thread) that waits for the bounce to complete before continuing:

                                                         //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                                                            sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Appear', timeout: 10000 });
                                                            sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                                                        

                                                        The problem is that if the bounce doesn't take more than about 10 seconds the code fails waiting for the bounce dialog to disappear.

                                                        If I get rid of the first line of code and only wait for it to disappear it seems to work on shorter bounces but I worry that it isn't very robust to wait for something to disappear that we haven't checked for in the first place. Any thoughts?

                                                        1. S
                                                          In reply toAndrew_Scheps:
                                                          Sebastian @Sebastian
                                                            2022-02-28 13:32:12.646Z

                                                            Hi, I loved this script but since Pro Tools changed some names and places in the Bounce Mix Window the script is not working anymore. Is there someone who updated this script? My scipting is unfortunatly not good enough to get this going.

                                                            1. Andrew Scheps @Andrew_Scheps
                                                                2022-02-28 15:51:38.033Z

                                                                Hi @Sebastian , unfortunately a ton has changed in the Bounce Dialog (well basically, everything), so updating this script isn't a small job.

                                                                The good news is that I've written an app that does nothing but print mixes and is pretty powerful. We're almost done beta testing it and it should be in the SF store before too long...

                                                                1. SSebastian @Sebastian
                                                                    2022-03-01 08:36:47.129Z

                                                                    That is good news :) Looking forward to it. Thanks.

                                                                2. In reply toAndrew_Scheps:
                                                                  Win Winstanley @Win_Winstanley
                                                                    2022-06-06 09:11:39.386Z

                                                                    HI, is there any chance we could get a "Wait For Bounce Dialogue To Close" action added to the menu?
                                                                    My understanding of coding is minimal/poor at best and inserting this into a Macro would be awesome for my workflow.
                                                                    Very best. Win

                                                                    1. Kitch Membery @Kitch2022-06-06 19:06:43.740Z

                                                                      Hi @Win_Winstanley,

                                                                      Thanks for the great suggestion. For any Ideas and suggestions like this please create a thread in the Ideas Section of the forum, that way it will be logged and considered for future updates of SoundFlow :-)

                                                                      Thanks in advance.