Hey @Kitch I found this great little function you built here
Select and Delete All Inactive Tracks
function dismissDialog(dialogText, buttonName) {
const dlg = sf.ui.proTools.confirmationDialog;
//Wait 100ms for dialog box to appear
dlg.elementWaitFor({
timeout: 100,
pollingInterval: 10,
onError: 'Continue'
});
if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) {
dlg.buttons.whoseTitle.is(buttonName).first.elementClick();
dlg.elementWaitFor({
waitType: 'Disappear',
timeout: 100,
pollingInterval: 10,
onError: 'Continue'
});
}
}
It's working great on this one:

dismissDialog("is a member", "No");
But I can't for the LIFE of me get it to work with this one

Tried the whole block of text, tried single words tried all sorts of combinations it will not go to save my life. Is there an alternate solution for this particular box? Or am I just doing it wrong?
I also tried this on a whim but it didn't take either.
if (sf.ui.proTools.confirmationDialog.exists) {
sf.ui.proTools.confirmationDialog.buttons.whoseTitle.is("OK").first.elementClick
};
Bests,
Owen
- Kitch Membery @Kitch2022-10-31 18:35:01.496Z
Hi Owen,
function dismissDialog(dialogText, buttonName) { const dlg = sf.ui.proTools.confirmationDialog; //Wait 100ms for dialog box to appear dlg.elementWaitFor({ timeout: 100, pollingInterval: 10, onError: 'Continue' }); if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) { dlg.buttons.whoseTitle.is(buttonName).first.elementClick(); dlg.elementWaitFor({ waitType: 'Disappear', timeout: 100, pollingInterval: 10, onError: 'Continue' }); } }
The above is a reusable function so it only needs to be in your script once.
You'll need to call the function with the following arguments.
dismissDialog("Some automation parameteres in the clipboard do not match the paste destination.", "OK");
Let me know if that works for you. :-)
- OOwen Granich-Young @Owen_Granich_Young
Yeah I tried this exactly, but I'll copy paste yours and see if it works any better....
Kitch Membery @Kitch2022-10-31 18:42:22.232Z
I've not tested it, so let me know how it goes.
If it fails let me know how to reproduce the dialog and I'll take a look and see if there is anything that's different with the dialog or button.
Rock on!
- OOwen Granich-Young @Owen_Granich_Young
Yeah still bugging out... Here's my full script, it only shows when automations do not match on a paste destination. I've been working on a super useful 'STAGE FIXES' Script. I'm really happy so far but when I headed into one of my mixers mixed session instead of my edit sessions it started throwing these two errors when pulling off his tracks.
So create a track and place a Plugin on it, in touch mode automate said plugin and write to seleciton,
Then create another track without a plugin and copy paste the files to that track you should get the dialog popup./** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { sf.ui.proTools.menuClick({ menuPath: ["File", "Export", "Selected Tracks as New Session..."], }); sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first.elementWaitFor(); sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first.checkBoxes.whoseTitle.is("Audio Files").first.checkboxSet({ targetValue: "Enable", }); sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first.checkBoxes.whoseTitle.is("Convert to Specified Format").first.checkboxSet({ targetValue: "Enable", }); sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first.buttons.whoseTitle.is("OK").first.elementClick(); // Save Window const saveWin = sf.ui.proTools.windows.whoseTitle.is("Save").first; const saveWinSheet = saveWin.sheets.first; saveWin.elementWaitFor(); // Open the "Go to the folder" sheet sf.keyboard.press({ keys: 'slash' }); saveWinSheet.elementWaitFor(); // Set the path to the sessions folder if (saveWinSheet.comboBoxes.first.exists) { saveWinSheet.comboBoxes.first.value.value = savePath; // Click 'Go' saveWinSheet.buttons.whoseTitle.is("Go").first.elementClick(); } else { saveWinSheet.textFields.first.value.value = savePath; sf.keyboard.press({ keys: 'return' }); } saveWinSheet.elementWaitFor({ waitType: 'Disappear' }); // Set name of Save Copy In Session saveWin.textFields.first.elementSetTextFieldWithAreaValue({ value: newSessionName }); // Click 'Save' and wait for window to dissapear saveWin.buttons.whoseTitle.is("Save").first.elementClick(); saveWin.elementWaitFor({ waitType: 'Disappear' }); sf.ui.proTools.waitForNoModals(); } function extendEditDown(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Extend Edit Down"], }); } } function extendEditup(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Extend Edit Up"], }); } } function removeEditTop(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Remove Edit from Top"], }); } } function removeEditBottom(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Remove Edit from Bottom"], }); } } function cutToClipboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Copy"], }); } function pasteCliboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"], }); } function selectUp() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; //Activate Pro Tools main window; // sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); extendEditup(originalSelectedTrackCount) removeEditBottom(originalSelectedTrackCount) } function dismissDialog(dialogText, buttonName) { const dlg = sf.ui.proTools.confirmationDialog; //Wait 100ms for dialog box to appear dlg.elementWaitFor({ timeout: 100, pollingInterval: 10, onError: 'Continue' }); if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) { dlg.buttons.whoseTitle.is(buttonName).first.elementClick(); dlg.elementWaitFor({ waitType: 'Disappear', timeout: 100, pollingInterval: 10, onError: 'Continue' }); } } function clipDown() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; cutToClipboard() extendEditDown(originalSelectedTrackCount) removeEditTop(originalSelectedTrackCount) dismissDialog("Some automation parameters in the clipboard do not match the paste destination.", "Ok") pasteCliboard() } function main() { var fixName = prompt(`Name the Fix`); const sessionPath = sf.ui.proTools.mainWindow.invalidate().sessionPath; const sessionParentPath = sessionPath.split("/").slice(0, -1).join("/"); const sessionName = sessionPath.split("/").slice(-1)[0].split(".")[0]; const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; sf.ui.proTools.trackDuplicateSelected({ duplicateActivePlaylist: false, duplicateAlternatePlaylists: false, duplicateAutomation: false, duplicateInserts: false, duplicateSends: false, duplicateGroupAssignments: false, }); dismissDialog("do you want to", "No"); selectUp(); cutToClipboard() extendEditDown(originalSelectedTrackCount) removeEditTop(originalSelectedTrackCount) dismissDialog("Some automation parameteres in the clipboard do not match the paste destination.", "OK"); pasteCliboard() const newSessionName = function () { let currentTimecode; sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => currentTimecode = sf.ui.proTools.getCurrentTimecode().stringValue }); return `${sessionName}_${fixName}_TC${currentTimecode}`; }(); saveCopyIn({ savePath: function () { const savePath = `${sessionParentPath}/Fixes`; if (!sf.file.directoryExists({ path: savePath }).exists) { sf.file.directoryCreate({ path: savePath }); } return savePath; }(), newSessionName, }); sf.ui.proTools.trackHideAndMakeInactiveSelected(); } main();
- OOwen Granich-Young @Owen_Granich_Young
PS the Clip down function is not in the MAIN script currently I just took the pieces and broke it out in an attempt to see if it being a nested function was messing up the dismissDialog Function... it was not.
Kitch Membery @Kitch2022-10-31 21:03:02.721Z
Hi Owen!
It looks like you may have a couple of lines in the wrong order... The paste operation(s) needs to be before the
dismissDialog
function call, otherwise, the dialog will not exist yet.I've not tested it, but try this :-)
/** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { sf.ui.proTools.menuClick({ menuPath: ["File", "Export", "Selected Tracks as New Session..."], }); const saveCopyInWin = sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first; saveCopyInWin.elementWaitFor(); saveCopyInWin.checkBoxes.whoseTitle.is("Audio Files").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.checkBoxes.whoseTitle.is("Convert to Specified Format").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.buttons.whoseTitle.is("OK").first.elementClick(); saveCopyInWin.elementWaitFor({ waitType: "Disappear" }); // Save Window const saveWin = sf.ui.proTools.windows.whoseTitle.is("Save").first; const saveWinSheet = saveWin.sheets.first; saveWin.elementWaitFor(); // Open the "Go to the folder" sheet sf.keyboard.press({ keys: 'slash' }); saveWinSheet.elementWaitFor(); // Set the path to the sessions folder if (saveWinSheet.comboBoxes.first.exists) { saveWinSheet.comboBoxes.first.value.value = savePath; // Click 'Go' saveWinSheet.buttons.whoseTitle.is("Go").first.elementClick(); } else { saveWinSheet.textFields.first.value.value = savePath; sf.keyboard.press({ keys: 'return' }); } saveWinSheet.elementWaitFor({ waitType: 'Disappear' }); // Set name of Save Copy In Session saveWin.textFields.first.elementSetTextFieldWithAreaValue({ value: newSessionName }); // Click 'Save' and wait for window to dissapear saveWin.buttons.whoseTitle.is("Save").first.elementClick(); saveWin.elementWaitFor({ waitType: 'Disappear' }); sf.ui.proTools.waitForNoModals(); } function extendEditDown(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Extend Edit Down"], }); } } function extendEditup(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Extend Edit Up"], }); } } function removeEditTop(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Remove Edit from Top"], }); } } function removeEditBottom(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Remove Edit from Bottom"], }); } } function cutToClipboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Copy"], }); } function pasteCliboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"], }); } function selectUp() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; //Activate Pro Tools main window; // sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); extendEditup(originalSelectedTrackCount) removeEditBottom(originalSelectedTrackCount) } function dismissDialog(dialogText, buttonName) { const dlg = sf.ui.proTools.confirmationDialog; //Wait 100ms for dialog box to appear dlg.elementWaitFor({ timeout: 100, pollingInterval: 10, onError: 'Continue' }); if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) { dlg.buttons.whoseTitle.is(buttonName).first.elementClick(); dlg.elementWaitFor({ waitType: 'Disappear', timeout: 100, pollingInterval: 10, onError: 'Continue' }); } } function clipDown() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; cutToClipboard(); extendEditDown(originalSelectedTrackCount); removeEditTop(originalSelectedTrackCount); pasteCliboard(); dismissDialog("Some automation parameters in the clipboard do not match the paste destination.", "Ok"); } function main() { var fixName = prompt(`Name the Fix`); const sessionPath = sf.ui.proTools.mainWindow.invalidate().sessionPath; const sessionParentPath = sessionPath.split("/").slice(0, -1).join("/"); const sessionName = sessionPath.split("/").slice(-1)[0].split(".")[0]; const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; sf.ui.proTools.trackDuplicateSelected({ duplicateActivePlaylist: false, duplicateAlternatePlaylists: false, duplicateAutomation: false, duplicateInserts: false, duplicateSends: false, duplicateGroupAssignments: false, }); dismissDialog("do you want to", "No"); selectUp(); cutToClipboard(); extendEditDown(originalSelectedTrackCount); removeEditTop(originalSelectedTrackCount); pasteCliboard(); dismissDialog("Some automation parameteres in the clipboard do not match the paste destination.", "OK"); const newSessionName = function () { let currentTimecode; sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => currentTimecode = sf.ui.proTools.getCurrentTimecode().stringValue }); return `${sessionName}_${fixName}_TC${currentTimecode}`; }(); saveCopyIn({ savePath: function () { const savePath = `${sessionParentPath}/Fixes`; if (!sf.file.directoryExists({ path: savePath }).exists) { sf.file.directoryCreate({ path: savePath }); } return savePath; }(), newSessionName, }); sf.ui.proTools.trackHideAndMakeInactiveSelected(); } main();
- OOwen Granich-Young @Owen_Granich_Young
ahahahah of course it was that simple. Will try now.
Kitch Membery @Kitch2022-10-31 21:25:01.379Z
Here's a little refactor untested :-)
/** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { sf.ui.proTools.menuClick({ menuPath: ["File", "Export", "Selected Tracks as New Session..."], }); const saveCopyInWin = sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first; saveCopyInWin.elementWaitFor(); saveCopyInWin.checkBoxes.whoseTitle.is("Audio Files").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.checkBoxes.whoseTitle.is("Convert to Specified Format").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.buttons.whoseTitle.is("OK").first.elementClick(); saveCopyInWin.elementWaitFor({ waitType: "Disappear" }); // Save Window const saveWin = sf.ui.proTools.windows.whoseTitle.is("Save").first; const saveWinSheet = saveWin.sheets.first; saveWin.elementWaitFor(); // Open the "Go to the folder" sheet sf.keyboard.press({ keys: 'slash' }); saveWinSheet.elementWaitFor(); // Set the path to the sessions folder if (saveWinSheet.comboBoxes.first.exists) { saveWinSheet.comboBoxes.first.value.value = savePath; // Click 'Go' saveWinSheet.buttons.whoseTitle.is("Go").first.elementClick(); } else { saveWinSheet.textFields.first.value.value = savePath; sf.keyboard.press({ keys: 'return' }); } saveWinSheet.elementWaitFor({ waitType: 'Disappear' }); // Set name of Save Copy In Session saveWin.textFields.first.elementSetTextFieldWithAreaValue({ value: newSessionName }); // Click 'Save' and wait for window to dissapear saveWin.buttons.whoseTitle.is("Save").first.elementClick(); saveWin.elementWaitFor({ waitType: 'Disappear' }); sf.ui.proTools.waitForNoModals(); } function navigateTrack({ direction, repetitions }) { for (let i = 0; i < repetitions; i++) { if (direction === 'Up') { sf.ui.proTools.getMenuItem("Edit", "Selection", "Extend Edit Up").elementClick(); sf.ui.proTools.getMenuItem("Edit", "Selection", "Remove Edit from Bottom").elementClick(); } if (direction === 'Down') { sf.ui.proTools.getMenuItem("Edit", "Selection", "Extend Edit Down").elementClick(); sf.ui.proTools.getMenuItem("Edit", "Selection", "Remove Edit from Top").elementClick(); } } } function cutToClipboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Copy"], }); } function pasteCliboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"], }); } function dismissDialog({ dialogText, buttonName }) { const dlg = sf.ui.proTools.confirmationDialog; //Wait 100ms for dialog box to appear dlg.elementWaitFor({ timeout: 100, pollingInterval: 10, onError: 'Continue' }); if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) { dlg.buttons.whoseTitle.is(buttonName).first.elementClick(); dlg.elementWaitFor({ waitType: 'Disappear', timeout: 100, pollingInterval: 10, onError: 'Continue' }); } } function clipDown() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; cutToClipboard(); navigateTrack({ direction: "Down", repetitions: originalSelectedTrackCount }) pasteCliboard(); dismissDialog({ dialogText: "Some automation parameteres in the clipboard do not match the paste destination.", buttonName: "OK" }); } function main() { const fixName = sf.interaction.displayDialog({ buttons: ["Ok", "Cancel"], defaultButton: "Ok", cancelButton: "Cancel", title: "Stage Fixes", defaultAnswer: "", prompt: "Please name the fix:", onCancel: "Abort" }).text; const sessionPath = sf.ui.proTools.mainWindow.invalidate().sessionPath; const sessionParentPath = sessionPath.split("/").slice(0, -1).join("/"); const sessionName = sessionPath.split("/").slice(-1)[0].split(".")[0]; const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; sf.ui.proTools.trackDuplicateSelected({ duplicateActivePlaylist: false, duplicateAlternatePlaylists: false, duplicateAutomation: false, duplicateInserts: false, duplicateSends: false, duplicateGroupAssignments: false, }); dismissDialog({ dialogText: "do you want to", buttonName: "No" }); navigateTrack({ direction: "Up", repetitions: originalSelectedTrackCount }); cutToClipboard(); navigateTrack({ direction: "Down", repetitions: originalSelectedTrackCount }); pasteCliboard(); dismissDialog({ dialogText: "Some automation parameteres in the clipboard do not match the paste destination.", buttonName: "OK" }); const newSessionName = function () { let currentTimecode; sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => currentTimecode = sf.ui.proTools.getCurrentTimecode().stringValue }); return `${sessionName}_${fixName}_TC${currentTimecode}`; }(); saveCopyIn({ savePath: function () { const savePath = `${sessionParentPath}/Fixes`; if (!sf.file.directoryExists({ path: savePath }).exists) { sf.file.directoryCreate({ path: savePath }); } return savePath; }(), newSessionName, }); sf.ui.proTools.trackHideAndMakeInactiveSelected(); } main();
- OOwen Granich-Young @Owen_Granich_Young
So strange, neither of these worked either.
Kitch Membery @Kitch2022-11-01 01:37:44.968Z
Is it failing in the same spot each time?
You may need to add a manual wait after the paste function so that the popup dialog has time to show.
FWIW I tested the
dismissDialog
function and it works.- OOwen Granich-Young @Owen_Granich_Young
Added some waits on either side, worked the last time I tried!
/** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { sf.ui.proTools.menuClick({ menuPath: ["File", "Export", "Selected Tracks as New Session..."], }); const saveCopyInWin = sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first; saveCopyInWin.elementWaitFor(); saveCopyInWin.checkBoxes.whoseTitle.is("Audio Files").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.checkBoxes.whoseTitle.is("Convert to Specified Format").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.buttons.whoseTitle.is("OK").first.elementClick(); saveCopyInWin.elementWaitFor({ waitType: "Disappear" }); // Save Window const saveWin = sf.ui.proTools.windows.whoseTitle.is("Save").first; const saveWinSheet = saveWin.sheets.first; saveWin.elementWaitFor(); // Open the "Go to the folder" sheet sf.keyboard.press({ keys: 'slash' }); saveWinSheet.elementWaitFor(); // Set the path to the sessions folder if (saveWinSheet.comboBoxes.first.exists) { saveWinSheet.comboBoxes.first.value.value = savePath; // Click 'Go' saveWinSheet.buttons.whoseTitle.is("Go").first.elementClick(); } else { saveWinSheet.textFields.first.value.value = savePath; sf.keyboard.press({ keys: 'return' }); } saveWinSheet.elementWaitFor({ waitType: 'Disappear' }); // Set name of Save Copy In Session saveWin.textFields.first.elementSetTextFieldWithAreaValue({ value: newSessionName }); // Click 'Save' and wait for window to dissapear saveWin.buttons.whoseTitle.is("Save").first.elementClick(); saveWin.elementWaitFor({ waitType: 'Disappear' }); sf.ui.proTools.waitForNoModals(); } function extendEditDown(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Extend Edit Down"], }); } } function extendEditup(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Extend Edit Up"], }); } } function removeEditTop(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Remove Edit from Top"], }); } } function removeEditBottom(repetitions) { for (let i = 0; i < repetitions; i++) { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Selection", "Remove Edit from Bottom"], }); } } function cutToClipboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Copy"], }); } function pasteCliboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"], }); } function selectUp() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; //Activate Pro Tools main window; // sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); extendEditup(originalSelectedTrackCount) removeEditBottom(originalSelectedTrackCount) } function dismissDialog(dialogText, buttonName) { const dlg = sf.ui.proTools.confirmationDialog; //Wait 100ms for dialog box to appear dlg.elementWaitFor({ timeout: 100, pollingInterval: 10, onError: 'Continue' }); if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) { dlg.buttons.whoseTitle.is(buttonName).first.elementClick(); dlg.elementWaitFor({ waitType: 'Disappear', timeout: 100, pollingInterval: 10, onError: 'Continue' }); } } function clipDown() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; cutToClipboard(); extendEditDown(originalSelectedTrackCount); removeEditTop(originalSelectedTrackCount); pasteCliboard(); sf.wait({ intervalMs: 100, }); dismissDialog("Some automation parameters in the clipboard do not match the paste destination.", "Ok"); } function main() { var fixName = prompt(`Name the Fix`); const sessionPath = sf.ui.proTools.mainWindow.invalidate().sessionPath; const sessionParentPath = sessionPath.split("/").slice(0, -1).join("/"); const sessionName = sessionPath.split("/").slice(-1)[0].split(".")[0]; const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; sf.ui.proTools.trackDuplicateSelected({ duplicateActivePlaylist: false, duplicateAlternatePlaylists: false, duplicateAutomation: false, duplicateInserts: false, duplicateSends: false, duplicateGroupAssignments: false, }); dismissDialog("do you want to", "No"); selectUp(); clipDown(); sf.wait({ intervalMs: 100, }); const newSessionName = function () { let currentTimecode; sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => currentTimecode = sf.ui.proTools.getCurrentTimecode().stringValue }); return `${sessionName}_${fixName}_TC${currentTimecode}`; }(); saveCopyIn({ savePath: function () { const savePath = `${sessionParentPath}/Fixes`; if (!sf.file.directoryExists({ path: savePath }).exists) { sf.file.directoryCreate({ path: savePath }); } return savePath; }(), newSessionName, }); sf.ui.proTools.trackHideAndMakeInactiveSelected(); } main();
Now to build the 2nd half where it saves it to the mixers Fixes folder !
Kitch Membery @Kitch2022-11-01 21:53:40.296Z
Nice one @Owen_Granich_Young,
Be sure to check out my last refactor, and add the waits to that. :-)
Fix them mixes.
- OOwen Granich-Young @Owen_Granich_Young
Oh yeah missed that, i'll try that one
- OOwen Granich-Young @Owen_Granich_Young
Weird had to reset Soundflow for it work, but here's yours working as well.
/** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { sf.ui.proTools.menuClick({ menuPath: ["File", "Export", "Selected Tracks as New Session..."], }); const saveCopyInWin = sf.ui.proTools.windows.whoseTitle.is("Save Copy In...").first; saveCopyInWin.elementWaitFor(); saveCopyInWin.checkBoxes.whoseTitle.is("Audio Files").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.checkBoxes.whoseTitle.is("Convert to Specified Format").first.checkboxSet({ targetValue: "Enable", }); saveCopyInWin.buttons.whoseTitle.is("OK").first.elementClick(); saveCopyInWin.elementWaitFor({ waitType: "Disappear" }); // Save Window const saveWin = sf.ui.proTools.windows.whoseTitle.is("Save").first; const saveWinSheet = saveWin.sheets.first; saveWin.elementWaitFor(); // Open the "Go to the folder" sheet sf.keyboard.press({ keys: 'slash' }); saveWinSheet.elementWaitFor(); // Set the path to the sessions folder if (saveWinSheet.comboBoxes.first.exists) { saveWinSheet.comboBoxes.first.value.value = savePath; // Click 'Go' saveWinSheet.buttons.whoseTitle.is("Go").first.elementClick(); } else { saveWinSheet.textFields.first.value.value = savePath; sf.keyboard.press({ keys: 'return' }); } saveWinSheet.elementWaitFor({ waitType: 'Disappear' }); // Set name of Save Copy In Session saveWin.textFields.first.elementSetTextFieldWithAreaValue({ value: newSessionName }); // Click 'Save' and wait for window to dissapear saveWin.buttons.whoseTitle.is("Save").first.elementClick(); saveWin.elementWaitFor({ waitType: 'Disappear' }); sf.ui.proTools.waitForNoModals(); } function navigateTrack({ direction, repetitions }) { for (let i = 0; i < repetitions; i++) { if (direction === 'Up') { sf.ui.proTools.getMenuItem("Edit", "Selection", "Extend Edit Up").elementClick(); sf.ui.proTools.getMenuItem("Edit", "Selection", "Remove Edit from Bottom").elementClick(); } if (direction === 'Down') { sf.ui.proTools.getMenuItem("Edit", "Selection", "Extend Edit Down").elementClick(); sf.ui.proTools.getMenuItem("Edit", "Selection", "Remove Edit from Top").elementClick(); } } } function cutToClipboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Copy"], }); } function pasteCliboard() { sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"], }); } function dismissDialog({ dialogText, buttonName }) { const dlg = sf.ui.proTools.confirmationDialog; //Wait 100ms for dialog box to appear dlg.elementWaitFor({ timeout: 100, pollingInterval: 10, onError: 'Continue' }); if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) { dlg.buttons.whoseTitle.is(buttonName).first.elementClick(); dlg.elementWaitFor({ waitType: 'Disappear', timeout: 100, pollingInterval: 10, onError: 'Continue' }); } } function clipDown() { //Get the original selected track count const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; cutToClipboard(); navigateTrack({ direction: "Down", repetitions: originalSelectedTrackCount }) pasteCliboard(); sf.wait({ intervalMs: 100, }); dismissDialog({ dialogText: "Some automation parameteres in the clipboard do not match the paste destination.", buttonName: "OK" }); } function main() { const fixName = sf.interaction.displayDialog({ buttons: ["Ok", "Cancel"], defaultButton: "Ok", cancelButton: "Cancel", title: "Stage Fixes", defaultAnswer: "", prompt: "Please name the fix:", onCancel: "Abort" }).text; const sessionPath = sf.ui.proTools.mainWindow.invalidate().sessionPath; const sessionParentPath = sessionPath.split("/").slice(0, -1).join("/"); const sessionName = sessionPath.split("/").slice(-1)[0].split(".")[0]; const originalSelectedTrackCount = sf.ui.proTools.selectedTrackCount; sf.ui.proTools.trackDuplicateSelected({ duplicateActivePlaylist: false, duplicateAlternatePlaylists: false, duplicateAutomation: false, duplicateInserts: false, duplicateSends: false, duplicateGroupAssignments: false, }); dismissDialog({ dialogText: "do you want to", buttonName: "No" }); navigateTrack({ direction: "Up", repetitions: originalSelectedTrackCount }); clipDown(); sf.wait({ intervalMs: 100, }); const newSessionName = function () { let currentTimecode; sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => currentTimecode = sf.ui.proTools.getCurrentTimecode().stringValue }); return `${sessionName}_${fixName}_TC${currentTimecode}`; }(); saveCopyIn({ savePath: function () { const savePath = `${sessionParentPath}/Fixes`; if (!sf.file.directoryExists({ path: savePath }).exists) { sf.file.directoryCreate({ path: savePath }); } return savePath; }(), newSessionName, }); sf.ui.proTools.trackHideAndMakeInactiveSelected(); } main();
- OOwen Granich-Young @Owen_Granich_Young
And in case anybody's wondering here it is in action. I'm doing a lot of stage fixes on my current show and am tired of exporting and naming.
Highlight your fix press button, Prompts for fix name - creates dupe tracks move selection to them exports them as session with audio to a FIXES folder (will create the folder if there’s none there) with session name _ Fix Name _ start TC as the name of the session then hides and makes inactive the dupe tracks
No more worrying if you accidentally left something else on the tracks.
Have fun stage editors!
Kitch Membery @Kitch2022-11-01 22:21:00.086Z
Love it!
- OOwen Granich-Young @Owen_Granich_Young
So weird yours stopped working again... changing solution for now, tired of trouble shooting lol.
Kitch Membery @Kitch2022-11-02 00:51:06.440Z
What was the error message?
- OOwen Granich-Young @Owen_Granich_Young
So weirdly inconsistent just set it up again on key press and it's working again, Throughly confused at it's inconsistency
Kitch Membery @Kitch2022-11-02 01:40:28.584Z
Hmm could be some invalidation needed somewhere in the script. If it happens again let me know what the error message is. :-)
- OOwen Granich-Young @Owen_Granich_Young
Hey @Kitch wonder if this was causing the error.
For curiosity I added it into your dismiss dialog script for future use.
function dismissDialog(dialogText, buttonName) { const dlg = sf.ui.proTools.confirmationDialog; //Wait 100ms for dialog box to appear dlg.elementWaitFor({ timeout: 100, pollingInterval: 10, onError: 'Continue' }); if (dlg.children.whoseRole.is("AXStaticText").whoseValue.contains(dialogText).first.exists) { dlg.elementWaitFor({ waitType: "Appear", }); dlg.buttons.whoseTitle.is(buttonName).first.elementClick(); dlg.elementWaitFor({ waitType: 'Disappear', timeout: 100, pollingInterval: 10, onError: 'Continue' }); } }