No internet connection
  1. Home
  2. How to

Pro tools stems script error

By Josh Bowman @Josh_Bowman
    2021-05-20 17:10:57.575Z

    Hi!

    Ive been using this amazing script to solo and bounce out track stems in PT that i grabbed from another post, i believe it was made by @Tristan_Hoogland and @Kitch !

    It recently starting hanging on line 54, and im a bit out of my depth trying to figure out whats happening (this the point in the script when its trying to select the bounce destination folder).

    The exact error is "Command Error: Export selected as stems Mar4th Copy [user:ckchpxcak0001rf109o4dvmrm:ckot6dfww0000zb10wm1j2ssr]:
    ClickButtonAction requires UIElement (Export selected as stems Mar4th Copy: Line 54)"

    It seems like its not able to find the "open" button to select the bounce destination? is that right? Anyone?

    Thanks in advance!

    /script
    var sessionPath = sf.ui.proTools.mainWindow.invalidate().sessionPath;
    var sessionDirectory = sessionPath.split('/').slice(0, -1).join('/');
    var sessionName = sessionPath.split('/').slice(-1)[0].split('.').slice(0, -1).join('.');
    
    function makeNewDirectory({ templatePath }) {
        const parentDirectory = templatePath.split('/').slice(0, -1).join('/');
        const directoryTemplateName = templatePath.split('/').slice(-1)[0];
    
        for (let i = 1; ; i++) {
            let directoryName = `${directoryTemplateName}${i}`;
            let directoryPath = parentDirectory + '/' + directoryName;
    
            if (!sf.file.directoryExists({ path: directoryPath }).exists) {
                sf.file.directoryCreate({ path: directoryPath });
                return directoryPath;
            }
        }
    }
    
        function bounceStem(stemName, directory, versionNumber, firstRun) {
        sf.ui.proTools.menuClick({
            menuPath: ["File", "Bounce Mix..."],
        });
    
        let bounceDlg = sf.ui.proTools.dialogWaitForManual({
            dialogTitle: 'Bounce Mix'
        }).dialog;
    
        sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').waitFor();
    
        let stemFolder = directory;
    
        if (firstRun === true) {
            sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Location').first.radioButtons.whoseTitle.is('Directory:').first.elementClick();
    
            sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Location').first.buttons.whoseTitle.is('Choose...').first.elementClick();
    
            const openWin = sf.ui.proTools.windows.whoseTitle.is('Open').first;
    
            openWin.elementWaitFor();
    
            sf.keyboard.press({ keys: "slash" });
    
            openWin.sheets.first.comboBoxes.whoseValue.is('/').first.elementWaitFor();
    
            openWin.sheets.first.comboBoxes.first.elementSetTextFieldWithAreaValue({
                value: stemFolder,
            });
    
            openWin.sheets.first.buttons.whoseTitle.is('Go').first.elementClick();
    
            openWin.sheets.first.comboBoxes.first.elementWaitFor({ waitType: 'Disappear' });
    
            openWin.getElement('AXDefaultButton').elementClick();
    
            openWin.elementWaitFor({ waitType: 'Disappear' });
        }
    
            function maximiseBounceWindow() {
        const bounceWin = sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first;
        bounceWin.groups.forEach(g => {
            if (g.frame.h === 22) {
                if (g.buttons.whoseTitle.is('Collapser').first.exists) {
                    g.buttons.whoseTitle.is('Collapser').first.elementClick();
                }
            }
        })
    }
    
        //Maximise 'Bounce Mix' Window
        maximiseBounceWindow();
    
        const bounceCheckboxes = sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.checkBoxes;
    
        sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Audio').first.checkBoxes.whoseTitle.is('Add MP3').first.checkboxSet({
            targetValue: "Disable",
        });
    
        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];
    
        //File Name
        sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({
            value: stemName + versionNumber,
        });
    
        sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Location').first.checkBoxes.whoseTitle.is('Import After Bounce').first.checkboxSet({
            targetValue: "Disable",
        });
    
        //Offline Bounce
        bounceCheckboxes.whoseTitle.is('Offline').first.checkboxSet({
            targetValue: 'Enable',
        });
    
        sf.wait({ intervalMs: 200 });
    
        sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.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 soloModeXOr() {
        sf.ui.proTools.menuClick({
            menuPath: ["Options", "Solo Mode", "X-OR (Cancels Previous Solo)"],
            targetValue: "Enable",
        });
    }
    
    function main() {
        sf.ui.proTools.appActivateMainWindow();
        sf.ui.proTools.mainWindow.invalidate();
    
        const newDirectory = makeNewDirectory({
            templatePath: `${sessionDirectory}/Bounced Files/${sessionName}_JBMixStems V`
        });
    
        const versionNumber = '_JBMixStem_' + newDirectory.split(" ").slice(-1);
    
        sf.ui.proTools.groupsEnsureGroupListIsVisible();
    
        var groupListPopup = sf.ui.proTools.groupsOpenListPopupMenu().popupMenu;
        groupListPopup.menuClickPopupMenu({
        menuPath: ["Suspend All Groups"],
        targetValue: 'Enable'
    });
    
    sf.ui.proTools.appActivateMainWindow();
    
        soloModeXOr();
    
        let firstLoop = true;
    
        sf.ui.proTools.selectedTracks.trackHeaders.slice().map(track => {
    
            track.trackSetSolo({
                targetValue: "Enable",
            });
    
            let stemName = track.title.value.split(" - ")[0];
    
            bounceStem(stemName, newDirectory, versionNumber, firstLoop);
    
            firstLoop = false;
        });
    
        sf.system.exec({ commandLine: `open "${newDirectory}"` });
    }
    
    main();
    
    
    Solved in post #6, click to view
    • 8 replies
    1. Kitch Membery @Kitch2021-05-20 17:44:31.854Z

      Hi @Josh_Bowman

      I tweaked a few things... Try this;

      
      const sessionPath = sf.ui.proTools.mainWindow.invalidate().sessionPath;
      const sessionDirectory = sessionPath.split('/').slice(0, -1).join('/');
      const sessionName = sessionPath.split('/').slice(-1)[0].split('.').slice(0, -1).join('.');
      
      function makeNewDirectory({ templatePath }) {
          const parentDirectory = templatePath.split('/').slice(0, -1).join('/');
          const directoryTemplateName = templatePath.split('/').slice(-1)[0];
      
          for (let i = 1; ; i++) {
              let directoryName = `${directoryTemplateName}${i}`;
              let directoryPath = parentDirectory + '/' + directoryName;
      
              if (!sf.file.directoryExists({ path: directoryPath }).exists) {
                  sf.file.directoryCreate({ path: directoryPath });
                  return directoryPath;
              }
          }
      }
      
      function bounceStem(stemName, directory, versionNumber, firstRun) {
          sf.ui.proTools.menuClick({
              menuPath: ["File", "Bounce Mix..."],
          });
      
          let bounceDlg = sf.ui.proTools.dialogWaitForManual({
              dialogTitle: 'Bounce Mix'
          }).dialog;
      
          sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').waitFor();
      
          let stemFolder = directory;
      
          if (firstRun === true) {
              sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Location').first.radioButtons.whoseTitle.is('Directory:').first.elementClick();
      
              sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Location').first.buttons.whoseTitle.is('Choose...').first.elementClick();
      
              const openWin = sf.ui.proTools.windows.whoseTitle.is('Open').first;
      
              openWin.elementWaitFor();
      
              sf.keyboard.press({ keys: "cmd+shift+g", });
      
              openWin.sheets.first.comboBoxes.first.elementWaitFor();
      
              openWin.sheets.first.comboBoxes.first.elementSetTextFieldWithAreaValue({
                  value: stemFolder,
              });
      
              openWin.sheets.first.buttons.whoseTitle.is('Go').first.elementClick();
      
              openWin.sheets.first.comboBoxes.first.elementWaitFor({ waitType: 'Disappear' });
      
              openWin.getElement('AXDefaultButton').elementClick();
      
              openWin.elementWaitFor({ waitType: 'Disappear' });
          }
      
          function maximiseBounceWindow() {
              const bounceWin = sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first;
              bounceWin.groups.forEach(g => {
                  if (g.frame.h === 22) {
                      if (g.buttons.whoseTitle.is('Collapser').first.exists) {
                          g.buttons.whoseTitle.is('Collapser').first.elementClick();
                      }
                  }
              })
          }
      
          //Maximise 'Bounce Mix' Window
          maximiseBounceWindow();
      
          const bounceCheckboxes = sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.checkBoxes;
      
          sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Audio').first.checkBoxes.whoseTitle.is('Add MP3').first.checkboxSet({
              targetValue: "Disable",
          });
      
          //File Name
          sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({
              value: stemName + versionNumber,
          });
      
          sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.groups.whoseTitle.is('Location').first.checkBoxes.whoseTitle.is('Import After Bounce').first.checkboxSet({
              targetValue: "Disable",
          });
      
          //Offline Bounce
          bounceCheckboxes.whoseTitle.is('Offline').first.checkboxSet({
              targetValue: 'Enable',
          });
      
          sf.wait({ intervalMs: 200 });
      
          sf.ui.proTools.windows.whoseTitle.is('Bounce Mix').first.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)
      
      
          while (sf.ui.frontmostApp.title.value !== "Pro Tools") {
              sf.wait({ intervalMs: 500 });
          }
      }
      
      function soloModeXOr() {
          sf.ui.proTools.menuClick({
              menuPath: ["Options", "Solo Mode", "X-OR (Cancels Previous Solo)"],
              targetValue: "Enable",
          });
      }
      
      function main() {
          sf.ui.proTools.appActivateMainWindow();
          sf.ui.proTools.mainWindow.invalidate();
      
          const newDirectory = makeNewDirectory({
              templatePath: `${sessionDirectory}/Bounced Files/${sessionName}_JBMixStems V`
          });
      
          const versionNumber = '_JBMixStem_' + newDirectory.split(" ").slice(-1);
      
          sf.ui.proTools.groupsEnsureGroupListIsVisible();
      
          let groupListPopup = sf.ui.proTools.groupsOpenListPopupMenu().popupMenu;
          groupListPopup.menuClickPopupMenu({
              menuPath: ["Suspend All Groups"],
              targetValue: 'Enable'
          });
      
          sf.ui.proTools.appActivateMainWindow();
      
          soloModeXOr();
      
          let firstLoop = true;
      
          sf.ui.proTools.selectedTracks.trackHeaders.slice().map(track => {
      
              track.trackSetSolo({
                  targetValue: "Enable",
              });
      
              let stemName = track.title.value.split(" - ")[0];
      
              bounceStem(stemName, newDirectory, versionNumber, firstLoop);
      
              firstLoop = false;
          });
      
          sf.system.exec({ commandLine: `open "${newDirectory}"` });
      }
      
      main();
      

      Hope that helps :-)

      Rock on
      Kitch

      1. JJosh Bowman @Josh_Bowman
          2021-05-20 17:58:34.366Z

          Thanks for the quick reply Kitch!! Appreciate you.

          Seems to still be hanging at the same place though,

          DId a screen record, incase that helps?

          1. Kitch Membery @Kitch2021-05-20 18:04:53.213Z

            Ahh I see... thanks for the screen recording.

            Can you copy and paste the code of line 54 in your script for me?

            1. JJosh Bowman @Josh_Bowman
                2021-05-20 18:08:36.915Z

                openWin.getElement('AXDefaultButton').elementClick();

                1. Kitch Membery @Kitch2021-05-20 18:10:34.347Z

                  Can you try replacing that line with the following three lines of code?

                          const openButton = sf.ui.proTools.windows.whoseTitle.is("Open").first.buttons.whoseTitle.is("Open").first;
                          
                          openButton.elementWaitFor();
                  
                          openButton.elementClick();
                  

                  Let me know if that works

                  ReplySolution
                  1. JJosh Bowman @Josh_Bowman
                      2021-05-20 18:13:46.449Z

                      AHHHHH!!! Seems to be working.

                      Thank you so much!! You just saved me about 8 hours of printing stems tomorrow.

                      1. Kitch Membery @Kitch2021-05-20 18:15:02.050Z

                        Awesome!!!! Enjoy :-)

                        1. Ttom Carmichael @tom_Carmichael
                            2022-01-18 16:02:17.085Z

                            Heya @Kitch , I wondered if I can request your help in modifying this script so it will work for me in Pro Tools 2018.1.0 ? Thank you !