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();
- 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- JJosh Bowman @Josh_Bowman
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?
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?
- JJosh Bowman @Josh_Bowman
openWin.getElement('AXDefaultButton').elementClick();
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
- JJosh Bowman @Josh_Bowman
AHHHHH!!! Seems to be working.
Thank you so much!! You just saved me about 8 hours of printing stems tomorrow.
Kitch Membery @Kitch2021-05-20 18:15:02.050Z
Awesome!!!! Enjoy :-)
- Ttom Carmichael @tom_Carmichael
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 !