No internet connection
  1. Home
  2. Support

PT Bounce Script / Set output stuck

By olafnoise @olafnoise
    2021-09-03 13:35:38.097Z

    Desired Workflow

    I try to adapt Kitch script "stem bouncing" to get it to work with a whole movie in reels.
    "My" script is working ok except when I want to add the Set output command ...

    Question

    I changed "Bounce" to Bounce Mix" fro PT 2021 but something is blocking there ..

    Here is the part of the script
    //Set Output
    if (sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.popupButtons.first.value.invalidate().value != '5.1 bus.C (Mono)') {
    sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.popupButtons.first.popupMenuSelect({
    menuPath: ["bus", "5.1 bus.C (Mono)"],
    useWildcards: true,
    });
    }

    and the log

    03.09.2021 15:27:33.98 [Backend]: !! Command Error: gu PT bounce bobines Directs [user:default:ckt380su7000avj10ztd8t1id]:
    Could not click popup menu item (gu PT bounce bobines Directs: Line 51)
    Could not find menu item with name: bus -> 5.1 bus.C (Mono)

    Thanks in advance for any help

    Jean

    Command Info

    ID: user:default:ckt380su7000avj10ztd8t1id
    Name: gu PT bounce bobines Directs
    

    Source

    
    sf.ui.proTools.appActivateMainWindow();
    
    //Loop 7 times
    for(let i=0; i<7; i++) {
    
    
    
    sf.keyboard.press({
        keys: "ctrl+tab",
    });
    
    sf.ui.proTools.menuClick({
        menuPath: ["Clip","Rename..."],
    });
    
    sf.ui.proTools.menuClick({
        menuPath: ["Edit","Copy"],
    });
    
    sf.keyboard.press({
        keys: "return",
    });
    
    sf.ui.proTools.menuClick({
        menuPath: ["File","Bounce Mix..."],
    });
    
    //Wait for the 'Bounce' dialog to appear and assign it to the bounceDlg variable
    var bounceDlg = sf.ui.proTools.dialogWaitForManual({
        dialogTitle: 'Bounce Mix'
    }).dialog;
    
    sf.ui.proTools.menuClick({
        menuPath: ["Edit","Paste"],
    });
    
    sf.keyboard.type({
        text: " DIRECTS",
    });
     
    let popupButtons = bounceDlg.getElements("AXChildren").filter(function (e) { return e.fullRole == "AXPopUpButton" }).slice(-4);
    
        let fileTypeBtn = popupButtons[0];
        let formatBtn = popupButtons[1];
        let bitDepthBtn = popupButtons[2];
        let sampleRateBtn = popupButtons[3];
    
    //Set Output
        if (sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.popupButtons.first.value.invalidate().value != '5.1 bus.C (Mono)') {
        sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.popupButtons.first.popupMenuSelect({
            menuPath: ["bus", "5.1 bus.C (Mono)"],
            useWildcards: true,
        });
    }
    
    //File Type
    if (fileTypeBtn.value.invalidate().value != 'WAV')
        fileTypeBtn.popupMenuSelect({ menuPath: ['WAV'] });
    
    //File Format
    if (formatBtn.value.value != 'Multiple mono')
        formatBtn.popupMenuSelect({ menuPath: ['Multiple mono'] });
    
    //Bit Depth
    if (bitDepthBtn.value.invalidate().value != '24 Bit')
        bitDepthBtn.popupMenuSelect({ menuPath: ['24 Bit'] });
    //Sample Rate
    if (sampleRateBtn.value.invalidate().value != '48 kHz')
        sampleRateBtn.popupMenuSelect({ menuPath: ['48 kHz']
       
    });
    
    sf.keyboard.press({
        keys: "return",
    });
    
    sf.ui.proTools.waitForNoModals();
    
    }
    second: any;
    

    Links

    User UID: e3y3S4pzUNdudPkANFsS9ZxGd8q2

    Feedback Key: sffeedback:e3y3S4pzUNdudPkANFsS9ZxGd8q2:-MifrnNHMDbog1H8a9WG

    Feedback ZIP

    • 17 replies

    There are 17 replies. Estimated reading time: 45 minutes

    1. Kitch Membery @Kitch2021-09-03 19:11:28.516Z

      Hi @olafnoise,

      I will look into this when I find a moment :-)

      Rock on!

      1. O
        In reply toolafnoise:
        olafnoise @olafnoise
          2021-09-03 20:49:21.306Z

          Thanks Kitch
          waiting till you have a moment ;-)

          1. Kitch Membery @Kitch2021-09-04 23:15:11.267Z2021-09-05 21:06:48.190Z

            Hi @olafnoise,

            Ignore my previous questions... I worked out what you were trying to do and adapted it to my personal 2021 bounce script.

            Simply select the clips you want to bounce and then run the script. (Note if at any time you need to cancel the script use Ctrl+Shift+Esc.)

            You will need to change two lines in the bounce settings object to reflect the Mix Source button title and the Mix Source Output path that you need.

            Mine look like this in Pro Tools;

            mixSourceButtonTitle:

            mixSourcePath:

            So I changed the following two lines in the bounceSettings object to reflect the above;

                mixSourceButtonTitle: 'Playback 1-2 (Stereo)',
                mixSourcePath: ['output', 'Playback 1-2 (Stereo) -> Playback 1-2'],
            

            (EDITED: I edited the mixSourcePath above 09/05/21)

            Here it is;

            const bounceSettings = {
                presetNumber: undefined,
                libraryPresetName: undefined,
                //fileName: "", // Commented out as the file name as it is being created in the clipDoForEachSelectedClip() loop.
                clipSuffix:'DIRECTS',
                fileType: "WAV (BWF)",
                mixSourceButtonTitle: 'Playback 1-2 (Stereo)',
                mixSourcePath: ['output', 'Playback 1-2 (Stereo) -> Playback 1-2'],
                mp3TargetValue: 'Disable',
                fileFormat: 'Multiple mono',
                bitDepth: '24 Bit',
                sampleRate: '48 kHz',
                padToFrameBoundary: 'Disable',
                importAfterBounce: 'Disable',
                fileDestination: 'Session Folder', //Options: 'Session Folder'|'Prompt For Location'|'Directory'
                sessionFolderPath: 'Bounced Files',
                onlineOffline: 'Enable',
            };
            
            const bounceMixWin = sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first;
            
            function openBounceMixWindow() {
                //Open Bounce Mix Window
                sf.ui.proTools.menuClick({
                    menuPath: ["File", "Bounce Mix..."],
                });
            
                bounceMixWin.elementWaitFor();
            }
            
            function maximiseBounceWindow() {
                //Open all Bounce Mix Panels
                bounceMixWin.groups.forEach(group => {
                    if (group.frame.h === 22) {
                        if (group.buttons.whoseTitle.is('Collapser').first.exists) {
                            group.buttons.whoseTitle.is('Collapser').first.elementClick();
                        }
                    }
                })
            }
            
            function setText(panel, text, index) {
                if (panel.textFields.allItems[index].value.invalidate().value !== text) {
                    panel.textFields.allItems[index].elementSetTextFieldWithAreaValue({
                        value: text,
                    }, `ERROR: ${text} ${index}`);
                }
            }
            
            function setPopupMenu(panel, path, index) {
                if (panel.popupButtons.allItems[index].value.invalidate().value !== path) {
                    panel.popupButtons.allItems[index].popupMenuSelect({
                        menuPath: [path],
                    }, `ERROR: ${path} ${index}`);
                }
            }
            
            function setBouncePreset(preset) {
                //Preset Buttons - mouseClickElement();
                const presetButtons = bounceMixWin.children.filter(b => b.fullRole === "AXButton:AXToggle");
            
                presetButtons[preset - 1].elementClick();
            }
            
            function setLibraryPreset(preset) {
                const libraryMenu = bounceMixWin.children.whoseRole.is("AXMenuButton").whoseTitle.is("Librarian menu").first;
            
                //Librarian menu
                if (libraryMenu.value.invalidate().value !== preset) {
                    libraryMenu.popupMenuSelect({
                        menuPath: [preset],
                    });
                }
            }
            
            function setTopPanel(settings) {
                const { fileName, fileType, mixSourceButtonTitle, mixSourcePath } = settings;
            
                //File Name - Text Field
                setText(bounceMixWin, fileName, 0);
            
                //File Type - Popup Menu
                setPopupMenu(bounceMixWin, fileType, 0);
            
                //Mix Source - Popup Menu
                if (bounceMixWin.popupButtons.allItems[1].value.invalidate().value !== mixSourceButtonTitle) {
                    bounceMixWin.popupButtons.allItems[1].popupMenuSelect({
                        menuPath: mixSourcePath,
                    });
                }
            }
            
            function setAudioPanel(settings) {
                const { mp3TargetValue, fileFormat, bitDepth, sampleRate, padToFrameBoundary } = settings;
            
                const audioPanel = bounceMixWin.groups.whoseTitle.is("Audio").first
            
                //MP3 - Checkbox
                audioPanel.checkBoxes.whoseTitle.is("Add MP3").first.checkboxSet({
                    targetValue: mp3TargetValue,
                });
            
                //File Format - Popup Menu
                setPopupMenu(audioPanel, fileFormat, 1);
            
                //Bit Depth - Popup Menu
                setPopupMenu(audioPanel, bitDepth, 2);
            
                //Sample Rate - Popup Menu (Have not yet implementedsupport Pull up/down sample rates )
                setPopupMenu(audioPanel, sampleRate, 3);
            
                //Pad To Frame Boundary - Checkbox
                audioPanel.checkBoxes.whoseTitle.is("Pad To Frame Boundary").first.checkboxSet({
                    targetValue: padToFrameBoundary,
                });
            }
            
            function setLocationPanel(settings) {
                let { importAfterBounce, fileDestination, sessionFolderPath, onlineOffline } = settings;
            
                const locationPanel = bounceMixWin.groups.whoseTitle.is("Location").first
            
                //Import After Bounce - Checkbox
                locationPanel.checkBoxes.whoseTitle.is("Import After Bounce").first.checkboxSet({
                    targetValue: importAfterBounce,
                });
            
                //Session Folder - Radio Button
                if (fileDestination === 'Session Folder') {
            
                    //Session Folder - Radio Button
                    locationPanel.radioButtons.whoseTitle.is("Session Folder:").first.elementClick();
            
                    //Session Folder - Text Field
                    setText(locationPanel, sessionFolderPath, 0);
                } else if (fileDestination === 'Prompt For Location') {
            
                    //Prompt For Location - Radio Button
                    locationPanel.radioButtons.whoseTitle.is("Prompt For Location").first.elementClick();
                } else if (fileDestination === 'Directory') {
            
                    //Directory: - Radio Button
                    locationPanel.radioButtons.whoseTitle.is("Directory:").first.elementClick();
            
                    //Choose... - Button
                    locationPanel.buttons.whoseTitle.is("Choose...").first.elementClick();
                }
            
                //Offline - Checkbox
                bounceMixWin.checkBoxes.whoseTitle.is("Offline").first.checkboxSet({
                    targetValue: onlineOffline,
                });
            }
            
            function doBounce(settings) {
                const { presetNumber, libraryPresetName } = settings;
            
                sf.ui.proTools.appActivateMainWindow();
            
                openBounceMixWindow();
            
                maximiseBounceWindow();
            
                if (presetNumber !== undefined)
                    setBouncePreset(presetNumber);
            
                if (libraryPresetName !== undefined)
                    setLibraryPreset(libraryPresetName);
            
                setTopPanel(settings);
            
                setAudioPanel(settings);
            
                setLocationPanel(settings);
            
                //Click Bounce
                bounceMixWin.buttons.whoseTitle.is('Bounce').first.elementClick();
            
                //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                sf.wait({ intervalMs: 4000 });
                sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
            }
            
            function getSelectedClipNamesFromClipList() {
                const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
            
                const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                    row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
            
                const clipNames = selectedClips.map(c => c.split('"')[1]);
            
                return clipNames
            };
            
            function bounceClip(bounceSettings) {
                const selectedClipName = getSelectedClipNamesFromClipList()[0];
                const newFileName = `${selectedClipName} ${bounceSettings.clipSuffix}`
            
                bounceSettings.fileName = newFileName;
                doBounce(bounceSettings);
            }
            
            function bounceClips(bounceSettings) {
                sf.ui.proTools.clipDoForEachSelectedClip({ action: () => bounceClip(bounceSettings) });
            }
            
            bounceClips(bounceSettings);
            

            If you are using this to bounce really short clips you may want to adjust the wait on line 180 to sf.wait({ intervalMs: 500 });

            Let me know how it goes for you, mate. :-)

            1. Oolafnoise @olafnoise
                2021-09-05 08:28:02.623Z

                Wow !! thanks a lot Kitch !!!

                I tested it as it is (with my own output settings) and it works fine
                I'll try later to put again my loop (7 reels on the feature I'm working on at the moment to answer your former question) and naming settings and let you know
                Thanks again
                Jean

                1. Kitch Membery @Kitch2021-09-05 09:21:31.803Z

                  Nice!

                  You shouldn’t need to re-add the loop though, as I have already set it up so all you have to do is select the clips in the guide track that you were grabbing the clip names from and it will bounce for each selected clip’s range one by one

                  This way you can bounce one section at a time if you want.

                  Also it grabs the clip name from the clips list rather than from the clip rename window which is a bit faster :-)

                  Enjoy.

                  1. Oolafnoise @olafnoise
                      2021-09-05 18:01:49.762Z

                      Yes! it seems to be brilliant !!
                      But I get an error when selecting the next clip
                      I tried to select all the reels guide clips (I tried normally and in object mode with the same result)

                      here is the log

                      05.09.2021 19:55:40.64 [Backend]: #StreamDeck: KeyDown (5,4) -> bounce Kitch test
                      Validating command... user:default:ckt6xozz70000iy101sv133xl
                      Invoking command...user:default:ckt6xozz70000iy101sv133xl

                      05.09.2021 19:55:40.64 [Backend]: >> Command: bounce Kitch test [user:default:ckt6xozz70000iy101sv133xl]

                      05.09.2021 19:55:40.96 [Backend]: Clicking with mouse here: 773, 86

                      05.09.2021 19:55:41.05 [Backend]: Succesfully set selection to: MainCounter: Sel Start: Sel End: Sel Length: 0

                      05.09.2021 19:55:41.11 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                      05.09.2021 19:55:42.97 [Backend]: Clicking with mouse here: 72, 30

                      05.09.2021 19:55:43.93 [Backend]: Clicking with mouse here: 838, 348

                      05.09.2021 19:55:43.98 [Backend]: PopupMenu full role:AXMenu

                      05.09.2021 19:55:43.98 [Backend]: Logging error in action (01) ClickPopupMenuAction: Could not find menu item with name: bus -> 5.1 bus #1 C (Mono)

                      05.09.2021 19:55:44.18 [Backend]: Clicking with mouse here: 820, 203

                      05.09.2021 19:55:44.20 [Backend]: Logging error in action (01) PopupMenuSelectAction: Could not click popup menu item

                      05.09.2021 19:55:44.20 [Backend]: Error running Js Callback: 'PopupMenuSelectAction' ( line 87)

                      05.09.2021 19:55:44.29 [Backend]: Clicking with mouse here: 773, 74

                      05.09.2021 19:55:50.37 [Backend]: Clicking with mouse here: 773, 74

                      05.09.2021 19:55:55.83 [Backend]: Clicking with mouse here: 773, 74

                      05.09.2021 19:56:02.76 [Backend]: Clicking with mouse here: 773, 74

                      05.09.2021 19:56:03.25 [Backend]: Succesfully set selection to: MainCounter: Sel Start: 517296000 Sel End: 749574000 Sel Length:

                      05.09.2021 19:56:03.31 [Backend]: Pressing key: kVK_LeftArrow. Flags: Zero

                      05.09.2021 19:56:03.42 [Backend]: Logging unknown error in action (02) DoMainCounterAction: bounce Kitch test: Line 87
                      Logging unknown error in action (02) DoForEachClipAction: bounce Kitch test: Line 87
                      Logging unknown error in action (02) DoForEachSelectedClipAction: bounce Kitch test: Line 87

                      05.09.2021 19:56:03.42 [Backend]: JavaScript error with InnerException: Could not click popup menu item (bounce Kitch test: Line 87)
                      !! Command Error: bounce Kitch test [user:default:ckt6xozz70000iy101sv133xl]:
                      Error: bounce Kitch test: Line 87
                      (bounce Kitch test line 204)

                      << Command: bounce Kitch test [user:default:ckt6xozz70000iy101sv133xl]

                      1. Kitch Membery @Kitch2021-09-05 19:48:06.154Z

                        Hi @olafnoise,

                        The error seems to be something to do with selecting the output path. The bounce Mix window may have been changed again.

                        I'll take a look today. :-)

                        Rock on.

                        1. In reply toolafnoise:
                          Kitch Membery @Kitch2021-09-05 21:29:09.801Z

                          I think I worked it out... I made an adjustment to the output selector as I believe the bus that you are trying to select may be indented within the Mix Source menu where Pro Tools adds some leading spaces before the bus name.

                          Note: that this won't perform as expected if you are trying to use the Object grabber tool while selecting clips with unselected clips between them. It will process every clip between the start of the first selected clip and the end of the last selected clip. This could be done but It would require a little extra scripting.

                          I also added an alert to the end so you know when it's done.

                          Below is the updated script; Remember to update the mixSourceButtonTitle & mixSourcePath before trying it out. :-)

                          const bounceSettings = {
                              presetNumber: undefined,
                              libraryPresetName: undefined,
                              //fileName: "", // Commented out as the file name as it is being created in the clipDoForEachSelectedClip() loop.
                              clipSuffix: 'DIRECTS',
                              fileType: "WAV (BWF)",
                              mixSourceButtonTitle: 'Playback 1-2 (Stereo)',
                              mixSourcePath: ['output', 'Playback 1-2 (Stereo) -> Playback 1-2'],
                              mp3TargetValue: 'Disable',
                              fileFormat: 'Multiple mono',
                              bitDepth: '24 Bit',
                              sampleRate: '48 kHz',
                              padToFrameBoundary: 'Disable',
                              importAfterBounce: 'Disable',
                              fileDestination: 'Session Folder', //Options: 'Session Folder'|'Prompt For Location'|'Directory'
                              sessionFolderPath: 'Bounced Files',
                              onlineOffline: 'Enable',
                          };
                          
                          const bounceMixWin = sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first;
                          
                          function openBounceMixWindow() {
                              //Open Bounce Mix Window
                              sf.ui.proTools.menuClick({
                                  menuPath: ["File", "Bounce Mix..."],
                              });
                          
                              bounceMixWin.elementWaitFor();
                          }
                          
                          function maximiseBounceWindow() {
                              //Open all Bounce Mix Panels
                              bounceMixWin.groups.forEach(group => {
                                  if (group.frame.h === 22) {
                                      if (group.buttons.whoseTitle.is('Collapser').first.exists) {
                                          group.buttons.whoseTitle.is('Collapser').first.elementClick();
                                      }
                                  }
                              })
                          }
                          
                          function setText(panel, text, index) {
                              if (panel.textFields.allItems[index].value.invalidate().value !== text) {
                                  panel.textFields.allItems[index].elementSetTextFieldWithAreaValue({
                                      value: text,
                                  }, `ERROR: ${text} ${index}`);
                              }
                          }
                          
                          function setPopupMenu(panel, path, index) {
                              if (panel.popupButtons.allItems[index].value.invalidate().value !== path) {
                                  panel.popupButtons.allItems[index].popupMenuSelect({
                                      menuPath: [path],
                                  }, `ERROR: ${path} ${index}`);
                              }
                          }
                          
                          function setBouncePreset(preset) {
                              //Preset Buttons - mouseClickElement();
                              const presetButtons = bounceMixWin.children.filter(b => b.fullRole === "AXButton:AXToggle");
                          
                              presetButtons[preset - 1].elementClick();
                          }
                          
                          function setLibraryPreset(preset) {
                              const libraryMenu = bounceMixWin.children.whoseRole.is("AXMenuButton").whoseTitle.is("Librarian menu").first;
                          
                              //Librarian menu
                              if (libraryMenu.value.invalidate().value !== preset) {
                                  libraryMenu.popupMenuSelect({
                                      menuPath: [preset],
                                  });
                              }
                          }
                          
                          function setTopPanel(settings) {
                              const { fileName, fileType, mixSourceButtonTitle, mixSourcePath } = settings;
                          
                              //File Name - Text Field
                              setText(bounceMixWin, fileName, 0);
                          
                              //File Type - Popup Menu
                              setPopupMenu(bounceMixWin, fileType, 0);
                          
                              //Mix Source - Popup Menu
                              if (bounceMixWin.popupButtons.allItems[1].value.invalidate().value !== mixSourceButtonTitle) {
                                  bounceMixWin.popupButtons.allItems[1].popupMenuSelect({
                                      menuSelector: items => items.filter(item =>
                                          item.path[0].endsWith(mixSourcePath[0]) &&
                                          item.path[1].endsWith(mixSourcePath[1]))[0]
                                  });
                              }
                          }
                          
                          function setAudioPanel(settings) {
                              const { mp3TargetValue, fileFormat, bitDepth, sampleRate, padToFrameBoundary } = settings;
                          
                              const audioPanel = bounceMixWin.groups.whoseTitle.is("Audio").first
                          
                              //MP3 - Checkbox
                              audioPanel.checkBoxes.whoseTitle.is("Add MP3").first.checkboxSet({
                                  targetValue: mp3TargetValue,
                              });
                          
                              //File Format - Popup Menu
                              setPopupMenu(audioPanel, fileFormat, 1);
                          
                              //Bit Depth - Popup Menu
                              setPopupMenu(audioPanel, bitDepth, 2);
                          
                              //Sample Rate - Popup Menu (Have not yet implementedsupport Pull up/down sample rates )
                              setPopupMenu(audioPanel, sampleRate, 3);
                          
                              //Pad To Frame Boundary - Checkbox
                              audioPanel.checkBoxes.whoseTitle.is("Pad To Frame Boundary").first.checkboxSet({
                                  targetValue: padToFrameBoundary,
                              });
                          }
                          
                          function setLocationPanel(settings) {
                              let { importAfterBounce, fileDestination, sessionFolderPath, onlineOffline } = settings;
                          
                              const locationPanel = bounceMixWin.groups.whoseTitle.is("Location").first
                          
                              //Import After Bounce - Checkbox
                              locationPanel.checkBoxes.whoseTitle.is("Import After Bounce").first.checkboxSet({
                                  targetValue: importAfterBounce,
                              });
                          
                              //Session Folder - Radio Button
                              if (fileDestination === 'Session Folder') {
                          
                                  //Session Folder - Radio Button
                                  locationPanel.radioButtons.whoseTitle.is("Session Folder:").first.elementClick();
                          
                                  //Session Folder - Text Field
                                  setText(locationPanel, sessionFolderPath, 0);
                              } else if (fileDestination === 'Prompt For Location') {
                          
                                  //Prompt For Location - Radio Button
                                  locationPanel.radioButtons.whoseTitle.is("Prompt For Location").first.elementClick();
                              } else if (fileDestination === 'Directory') {
                          
                                  //Directory: - Radio Button
                                  locationPanel.radioButtons.whoseTitle.is("Directory:").first.elementClick();
                          
                                  //Choose... - Button
                                  locationPanel.buttons.whoseTitle.is("Choose...").first.elementClick();
                              }
                          
                              //Offline - Checkbox
                              bounceMixWin.checkBoxes.whoseTitle.is("Offline").first.checkboxSet({
                                  targetValue: onlineOffline,
                              });
                          }
                          
                          function doBounce(settings) {
                              const { presetNumber, libraryPresetName } = settings;
                          
                              sf.ui.proTools.appActivateMainWindow();
                          
                              openBounceMixWindow();
                          
                              maximiseBounceWindow();
                          
                              if (presetNumber !== undefined)
                                  setBouncePreset(presetNumber);
                          
                              if (libraryPresetName !== undefined)
                                  setLibraryPreset(libraryPresetName);
                          
                              setTopPanel(settings);
                          
                              setAudioPanel(settings);
                          
                              setLocationPanel(settings);
                          
                              //Click Bounce
                              bounceMixWin.buttons.whoseTitle.is('Bounce').first.elementClick();
                          
                              //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                              sf.wait({ intervalMs: 4000 });
                              sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                          }
                          
                          function getSelectedClipNamesFromClipList() {
                              const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
                          
                              const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                                  row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
                          
                              const clipNames = selectedClips.map(c => c.split('"')[1]);
                          
                              return clipNames
                          };
                          
                          function bounceClip(bounceSettings) {
                              const selectedClipName = getSelectedClipNamesFromClipList()[0];
                              const newFileName = `${selectedClipName} ${bounceSettings.clipSuffix}`
                          
                              bounceSettings.fileName = newFileName;
                              doBounce(bounceSettings);
                          }
                          
                          function bounceClips(bounceSettings) {
                              sf.ui.proTools.appActivateMainWindow();
                              sf.ui.proTools.clipDoForEachSelectedClip({ action: () => bounceClip(bounceSettings) });
                          
                              alert('Done!');
                          }
                          
                          bounceClips(bounceSettings);
                          
                          1. Oolafnoise @olafnoise
                              2021-09-06 07:33:11.737Z

                              Great !! Thank you so much ....
                              A lot of time saved now ....
                              all the best Kitch

                              1. Kitch Membery @Kitch2021-09-06 07:34:09.679Z

                                Awesome. Have a great week. :-)

                                1. Oolafnoise @olafnoise
                                    2021-09-10 09:43:14.285Z

                                    Hi Kitch
                                    I just try your script on another machine (Mac 5.1 running Mojave instead of Catalina on a Dustbin)
                                    Same version of PT 2021.7 but HDX
                                    And the script doesn"t work anymore
                                    First the counters changes to samples (weird) then select the reels then get stuck OR bounce the first reel and then stop (ultra weird)
                                    at the beginning I tought that it could be a waiting time issue (the offline bounce process is longer to start on this machine (may be due to HDX ...)

                                    here is the log:

                                    10.09.2021 11:36:12.58 [Backend]: #StreamDeck: KeyDown (5,4) -> bounce Kitch test
                                    Validating command... user:default:ckt6xozz70000iy101sv133xl
                                    Invoking command...user:default:ckt6xozz70000iy101sv133xl

                                    10.09.2021 11:36:12.58 [Backend]: >> Command: bounce Kitch test [user:default:ckt6xozz70000iy101sv133xl]

                                    10.09.2021 11:36:12.68 [Backend]: Clicking with mouse here: 74, 33

                                    10.09.2021 11:36:13.06 [Backend]: Clicking with mouse here: 775, 89

                                    10.09.2021 11:36:13.18 [Backend]: Succesfully set selection to: MainCounter: Sel Start: Sel End: Sel Length: 0

                                    10.09.2021 11:36:13.24 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:13.60 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:13.74 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:14.14 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:14.27 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:14.71 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:14.84 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:15.26 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:15.39 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:15.82 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:15.95 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:16.38 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:16.52 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:16.94 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:17.07 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:17.48 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:17.62 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:18.05 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: Zero

                                    10.09.2021 11:36:18.18 [Backend]: Pressing key: kVK_ANSI_Quote. Flags: kCGEventFlagMaskShift

                                    10.09.2021 11:36:18.60 [Backend]: Clicking with mouse here: 775, 65

                                    10.09.2021 11:36:18.88 [Backend]: Clicking with mouse here: 775, 77

                                    10.09.2021 11:36:19.08 [Backend]: Succesfully set selection to: MainCounter: Sel Start: 172704000 Sel End: 924772000 Sel Length:

                                    10.09.2021 11:36:19.14 [Backend]: Pressing key: kVK_LeftArrow. Flags: Zero

                                    10.09.2021 11:36:19.29 [Backend]: Logging error in action (01) DoMainCounterAction: Selecting a full clip failed
                                    Error in action (00) DoForEachClipAction: DoMainCounterAction
                                    Error in action (00) DoForEachSelectedClipAction: DoMainCounterAction

                                    10.09.2021 11:36:19.29 [Backend]: !! Command Error: bounce Kitch test [user:default:ckt6xozz70000iy101sv133xl]:
                                    Selecting a full clip failed (bounce Kitch test: Line 207)

                                    << Command: bounce Kitch test [user:default:ckt6xozz70000iy101sv133xl]

                                    10.09.2021 11:36:23.92 [Backend]: [SF_FIREBASE_WS]: Sending keep-alive

                                    10.09.2021 11:36:29.36 [Backend]: #Key: mouse button 3 (-4) -> Show/Hide Track Volume For Selected Track [proTools_track_volume_toggle_selectedTrack:1]
                                    Validating command... proTools.track.volume.toggle.selectedTrack
                                    Invoking command...proTools.track.volume.toggle.selectedTrack

                                    Command: Show/Hide Track Volume For Selected Track [proTools.track.volume.toggle.selectedTrack]

                                    10.09.2021 11:36:29.41 [Backend]: Pressing key: kClearCharCode. Flags: Zero

                                    10.09.2021 11:36:29.65 [Backend]: << Command: Show/Hide Track Volume For Selected Track [proTools.track.volume.toggle.selectedTrack]

                                    1. Oolafnoise @olafnoise
                                        2021-09-10 10:07:30.360Z

                                        When the first reel bounce is working ok here is the message I get in the middle of bounce:
                                        "counld not restore selection bounce Kitch test line 207"

                                        1. In reply toolafnoise:
                                          Kitch Membery @Kitch2021-09-10 19:18:46.073Z

                                          Hi @olafnoise,

                                          Sorry it's not working. I think you may be right about the bounce wait time. I'll have to trouble shoot it over the weekend and see if I can make it break.

                                          If you could upload a screen recording of it failing it may give me some insight into where/why the script is not behaving as expected.

                                          Note: Regarding the switching to samples weirdness. This is expected behavior as it it inbuilt into the clipDoForEachSelectedClip() method.

                                          Rock on!

                                          1. Oolafnoise @olafnoise
                                              2021-09-11 16:39:45.307Z

                                              Hi Kitch
                                              sorry I didn't reply earlier ...too busy
                                              Actually, today I tried your script on my little test sesssion I was using earlier (20 tracks or something)
                                              ..... and it still work fine ... so, it's not machine nor OS issue
                                              But when I run it on a whole feature editing session (about 200 tracks and complex routings) I'm getting the "could not restore selection bounce Kitch test line 207" error
                                              With a big session, the offline bounce takes a much longer time to start
                                              I'll try to make a screen capture asap

                                              many thanks for your time
                                              all the best
                                              Jean

                                              1. Oolafnoise @olafnoise
                                                  2021-09-11 17:13:01.131Z
                                                  1. Kitch Membery @Kitch2021-09-11 21:15:07.732Z

                                                    Thanks for the Screen recording @olafnoise.

                                                    Due to the nature of the issue (ie. attempting it on my system, the bounce runs too fast to replicate what is happening on yours), I have added a few lines, to wait for Pro Tools main window before continuing.

                                                    Here is the new script. Hopefully it works. (Oh... and remember to customize your bounceSettings in the code :-)

                                                    const bounceSettings = {
                                                        presetNumber: undefined,
                                                        libraryPresetName: undefined,
                                                        //fileName: "", // Commented out as the file name as it is being created in the clipDoForEachSelectedClip() loop.
                                                        clipSuffix: 'DIRECTS',
                                                        fileType: "WAV (BWF)",
                                                        mixSourceButtonTitle: 'Playback 1-2 (Stereo)',
                                                        mixSourcePath: ['output', 'Playback 1-2 (Stereo) -> Playback 1-2'],
                                                        mp3TargetValue: 'Disable',
                                                        fileFormat: 'Multiple mono',
                                                        bitDepth: '24 Bit',
                                                        sampleRate: '48 kHz',
                                                        padToFrameBoundary: 'Disable',
                                                        importAfterBounce: 'Disable',
                                                        fileDestination: 'Session Folder', //Options: 'Session Folder'|'Prompt For Location'|'Directory'
                                                        sessionFolderPath: 'Bounced Files',
                                                        onlineOffline: 'Enable',
                                                    };
                                                    
                                                    const bounceMixWin = sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first;
                                                    
                                                    function openBounceMixWindow() {
                                                        //Open Bounce Mix Window
                                                        sf.ui.proTools.menuClick({
                                                            menuPath: ["File", "Bounce Mix..."],
                                                        });
                                                    
                                                        bounceMixWin.elementWaitFor();
                                                    }
                                                    
                                                    function maximiseBounceWindow() {
                                                        //Open all Bounce Mix Panels
                                                        bounceMixWin.groups.forEach(group => {
                                                            if (group.frame.h === 22) {
                                                                if (group.buttons.whoseTitle.is('Collapser').first.exists) {
                                                                    group.buttons.whoseTitle.is('Collapser').first.elementClick();
                                                                }
                                                            }
                                                        })
                                                    }
                                                    
                                                    function setText(panel, text, index) {
                                                        if (panel.textFields.allItems[index].value.invalidate().value !== text) {
                                                            panel.textFields.allItems[index].elementSetTextFieldWithAreaValue({
                                                                value: text,
                                                            }, `ERROR: ${text} ${index}`);
                                                        }
                                                    }
                                                    
                                                    function setPopupMenu(panel, path, index) {
                                                        if (panel.popupButtons.allItems[index].value.invalidate().value !== path) {
                                                            panel.popupButtons.allItems[index].popupMenuSelect({
                                                                menuPath: [path],
                                                            }, `ERROR: ${path} ${index}`);
                                                        }
                                                    }
                                                    
                                                    function setBouncePreset(preset) {
                                                        //Preset Buttons - mouseClickElement();
                                                        const presetButtons = bounceMixWin.children.filter(b => b.fullRole === "AXButton:AXToggle");
                                                    
                                                        presetButtons[preset - 1].elementClick();
                                                    }
                                                    
                                                    function setLibraryPreset(preset) {
                                                        const libraryMenu = bounceMixWin.children.whoseRole.is("AXMenuButton").whoseTitle.is("Librarian menu").first;
                                                    
                                                        //Librarian menu
                                                        if (libraryMenu.value.invalidate().value !== preset) {
                                                            libraryMenu.popupMenuSelect({
                                                                menuPath: [preset],
                                                            });
                                                        }
                                                    }
                                                    
                                                    function setTopPanel(settings) {
                                                        const { fileName, fileType, mixSourceButtonTitle, mixSourcePath } = settings;
                                                    
                                                        //File Name - Text Field
                                                        setText(bounceMixWin, fileName, 0);
                                                    
                                                        //File Type - Popup Menu
                                                        setPopupMenu(bounceMixWin, fileType, 0);
                                                    
                                                        //Mix Source - Popup Menu
                                                        if (bounceMixWin.popupButtons.allItems[1].value.invalidate().value !== mixSourceButtonTitle) {
                                                            bounceMixWin.popupButtons.allItems[1].popupMenuSelect({
                                                                menuSelector: items => items.filter(item =>
                                                                    item.path[0].endsWith(mixSourcePath[0]) &&
                                                                    item.path[1].endsWith(mixSourcePath[1]))[0]
                                                            });
                                                        }
                                                    }
                                                    
                                                    function setAudioPanel(settings) {
                                                        const { mp3TargetValue, fileFormat, bitDepth, sampleRate, padToFrameBoundary } = settings;
                                                    
                                                        const audioPanel = bounceMixWin.groups.whoseTitle.is("Audio").first
                                                    
                                                        //MP3 - Checkbox
                                                        audioPanel.checkBoxes.whoseTitle.is("Add MP3").first.checkboxSet({
                                                            targetValue: mp3TargetValue,
                                                        });
                                                    
                                                        //File Format - Popup Menu
                                                        setPopupMenu(audioPanel, fileFormat, 1);
                                                    
                                                        //Bit Depth - Popup Menu
                                                        setPopupMenu(audioPanel, bitDepth, 2);
                                                    
                                                        //Sample Rate - Popup Menu (Have not yet implementedsupport Pull up/down sample rates )
                                                        setPopupMenu(audioPanel, sampleRate, 3);
                                                    
                                                        //Pad To Frame Boundary - Checkbox
                                                        audioPanel.checkBoxes.whoseTitle.is("Pad To Frame Boundary").first.checkboxSet({
                                                            targetValue: padToFrameBoundary,
                                                        });
                                                    }
                                                    
                                                    function setLocationPanel(settings) {
                                                        let { importAfterBounce, fileDestination, sessionFolderPath, onlineOffline } = settings;
                                                    
                                                        const locationPanel = bounceMixWin.groups.whoseTitle.is("Location").first
                                                    
                                                        //Import After Bounce - Checkbox
                                                        locationPanel.checkBoxes.whoseTitle.is("Import After Bounce").first.checkboxSet({
                                                            targetValue: importAfterBounce,
                                                        });
                                                    
                                                        //Session Folder - Radio Button
                                                        if (fileDestination === 'Session Folder') {
                                                    
                                                            //Session Folder - Radio Button
                                                            locationPanel.radioButtons.whoseTitle.is("Session Folder:").first.elementClick();
                                                    
                                                            //Session Folder - Text Field
                                                            setText(locationPanel, sessionFolderPath, 0);
                                                        } else if (fileDestination === 'Prompt For Location') {
                                                    
                                                            //Prompt For Location - Radio Button
                                                            locationPanel.radioButtons.whoseTitle.is("Prompt For Location").first.elementClick();
                                                        } else if (fileDestination === 'Directory') {
                                                    
                                                            //Directory: - Radio Button
                                                            locationPanel.radioButtons.whoseTitle.is("Directory:").first.elementClick();
                                                    
                                                            //Choose... - Button
                                                            locationPanel.buttons.whoseTitle.is("Choose...").first.elementClick();
                                                        }
                                                    
                                                        //Offline - Checkbox
                                                        bounceMixWin.checkBoxes.whoseTitle.is("Offline").first.checkboxSet({
                                                            targetValue: onlineOffline,
                                                        });
                                                    }
                                                    
                                                    function doBounce(settings) {
                                                        const { presetNumber, libraryPresetName } = settings;
                                                    
                                                        sf.ui.proTools.appActivateMainWindow();
                                                    
                                                        openBounceMixWindow();
                                                    
                                                        maximiseBounceWindow();
                                                    
                                                        if (presetNumber !== undefined)
                                                            setBouncePreset(presetNumber);
                                                    
                                                        if (libraryPresetName !== undefined)
                                                            setLibraryPreset(libraryPresetName);
                                                    
                                                        setTopPanel(settings);
                                                    
                                                        setAudioPanel(settings);
                                                    
                                                        setLocationPanel(settings);
                                                    
                                                        //Click Bounce
                                                        bounceMixWin.buttons.whoseTitle.is('Bounce').first.elementClick();
                                                    
                                                        //Wait for bounce to finish (Wait for bounce dialog to appear, then to disappear)
                                                        sf.ui.proTools.confirmationDialog.elementWaitFor({ timeout: 100000 });
                                                        sf.ui.proTools.confirmationDialog.elementWaitFor({ waitType: 'Disappear', timeout: -1 }); //-1 is endless timeout (cancel by Ctrl+Shift+Esc)
                                                    
                                                        while (sf.ui.frontmostApp.title.value !== "Pro Tools") {
                                                            sf.wait({ intervalMs: 500 });
                                                        }
                                                    }
                                                    
                                                    function getSelectedClipNamesFromClipList() {
                                                        const clipsTable = sf.ui.proTools.mainWindow.tables.whoseTitle.is('CLIPS').first;
                                                    
                                                        const selectedClips = clipsTable.children.whoseRole.is("AXRow").allItems.map(row =>
                                                            row.children[1].children.first.value.value).filter(c => c.startsWith('Selected. '));
                                                    
                                                        const clipNames = selectedClips.map(c => c.split('"')[1]);
                                                    
                                                        return clipNames
                                                    };
                                                    
                                                    function bounceClip(bounceSettings) {
                                                        const selectedClipName = getSelectedClipNamesFromClipList()[0];
                                                        const newFileName = `${selectedClipName} ${bounceSettings.clipSuffix}`
                                                    
                                                        bounceSettings.fileName = newFileName;
                                                        doBounce(bounceSettings);
                                                    }
                                                    
                                                    function bounceClips(bounceSettings) {
                                                        sf.ui.proTools.appActivateMainWindow();
                                                        sf.ui.proTools.clipDoForEachSelectedClip({ action: () => bounceClip(bounceSettings) });
                                                    
                                                        alert('Done!');
                                                    }
                                                    
                                                    bounceClips(bounceSettings);
                                                    

                                                    Rock on!

                                                    1. Oolafnoise @olafnoise
                                                        2021-09-11 21:37:29.004Z

                                                        YES!

                                                        I gived it a quick try tonight on a heavy sesiion and it's working ok !!!
                                                        I'll try to understand the diference between the two scripts tomorrow ...
                                                        Thousands thanks again Kitch
                                                        I owe you hundred of pints when you come to Paris
                                                        all the best
                                                        Jean