During mixing i'm using save copy in with the current timecode as an indiciator to where this session is progressed. Very usefull when restoring lost data. ("the write to all nightmare") I want to automate this. At the moment i tried a lot of key press actions. With no succes.
This should be the workflow:
- Get current timecode
- Save a session copy with the timecode as text at the end (and lose the "Copy of" prefix)
The "save a new version" macro comes close.
Any ideas how to tackle this one?
The solution got a bonus feature. It is now a template. You can choose whether to add the timecode or a user value to the end of your saved session name.
- Danny @Danny_van_Spreuwel
What could help if the "Copy of .. session" name can be changed. The new alterted name can then be pasted into the text field of the Save Copy In window. What the new name need to be is strip of the "Copy Of [space]" prefix, add TC t the end and add the copied TC from the clipboard.
- In reply toDanny_van_Spreuwel⬆:Raphael Sepulveda @raphaelsepulveda2022-02-11 20:10:42.721Z2022-02-12 19:11:49.701Z
@Danny_van_Spreuwel, give this a try.
Change the
savePath
at the end of the script to whatever you'd like, in this example, I'm just putting it in the Downloads folder.Also, I'm not sure what settings you prefer to have on the Save Copy In window, so I just enabled the Audio Files checkbox. Let me know if you need help customizing that more.
Finally, since ":" are not supported in macOS filenames, you'll notice they'll get replaced with "-" in the timecode part of the filename.
Hopefully, that helps!
/** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { const saveCopyInWin = sf.ui.proTools.windows.whoseTitle.is('Save Copy In...').first; sf.ui.proTools.menuClick({ menuPath: ['File', 'Save Copy In...'] }); saveCopyInWin.elementWaitFor({ waitType: "Appear", }); 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 saveWinSheet.comboBoxes.first.value.value = savePath; // Click 'Go' saveWinSheet.buttons.whoseTitle.is("Go").first.elementClick(); 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 saveCopyInAndAppendTimecodeInFilename() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); 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]; let currentTimecode; sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => currentTimecode = sf.ui.proTools.getCurrentTimecode().stringValue }); saveCopyIn({ savePath: function () { const savePath = `${sessionParentPath}/Session File Snapshots`; if (!sf.file.directoryExists({ path: savePath }).exists) { sf.file.directoryCreate({ path: savePath }); } return savePath; }(), newSessionName: `${sessionName}_TC${currentTimecode}`, }); } saveCopyInAndAppendTimecodeInFilename();
Danny @Danny_van_Spreuwel
Like magic! Raphael, thank you for your code (again). This is a great start. Would you convert the script with these changes:
- The savePath is the same as the current Pro Tools session with a folder called "Session File Snapshots". Extra bonus: if the folder does not exist it needs to be created.
- The included Audio Files checkbox can be unchecked. Just the Pro Tools session will be saved.
- The new name ends "_TChh-mm-ss-ff" (e.g. TC01-34-00-12).
Update: With my little knowledge of JavaScript I converted the naming:
return `${sessionName}_TC${currentTimecode}
Raphael Sepulveda @raphaelsepulveda2022-02-12 19:12:27.982Z
No problem! Just updated the script above with the changes.
Danny @Danny_van_Spreuwel
Absolutely loving this. Another time saving script. Thank you for all your work and helping me out with this!
Raphael Sepulveda @raphaelsepulveda2022-02-12 20:10:34.469Z
My pleasure!
- In reply toraphaelsepulveda⬆:
Danny @Danny_van_Spreuwel
@raphaelsepulveda I like to take the script a bit further. An option to have a suffix as a template.
Property:
SuffixValues:
TC
User valueI know how to make the template. I'm missing some JavaScript programming to decide witch suffix naming to use.
If event.props.suffix = "TC" then sessionName + "TC {currentTimecode} else sessionName + "{event.props.suffix}"
Can you help me out to write this peace of code?
Raphael Sepulveda @raphaelsepulveda2022-03-11 17:21:32.415Z
Yeah! I'll have some time later in the weekend to get this done for ya. I'll report back when I do!
Raphael Sepulveda @raphaelsepulveda2022-03-12 23:02:00.903Z
@Danny_van_Spreuwel, this should do!
Set up your template to look like this and the code below takes care of the rest:
const { suffix, userValue } = event.props; /** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { const saveCopyInWin = sf.ui.proTools.windows.whoseTitle.is('Save Copy In...').first; sf.ui.proTools.menuClick({ menuPath: ['File', 'Save Copy In...'] }); saveCopyInWin.elementWaitFor({ waitType: "Appear", }); 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 saveWinSheet.comboBoxes.first.value.value = savePath; // Click 'Go' saveWinSheet.buttons.whoseTitle.is("Go").first.elementClick(); 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 main() { if (suffix === "User Value" && userValue === undefined) throw 'No User Value was passed in template.' sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainWindow.invalidate(); 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 newSessionName = function () { if (suffix === 'TC') { let currentTimecode; sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => currentTimecode = sf.ui.proTools.getCurrentTimecode().stringValue }); return `${sessionName}_TC${currentTimecode}`; } if (suffix === 'User Value') { return `${sessionName}_${userValue}`; } }(); saveCopyIn({ savePath: function () { const savePath = `${sessionParentPath}/Session File Snapshots`; if (!sf.file.directoryExists({ path: savePath }).exists) { sf.file.directoryCreate({ path: savePath }); } return savePath; }(), newSessionName, }); } main();
Danny @Danny_van_Spreuwel
YES YES YES! Thank you so much. It looks like an ease when you do this. I tried it myself but didn't work out. You even added an error handler. You use be a pro coder.
Raphael Sepulveda @raphaelsepulveda2022-03-13 17:08:28.480Z
Awesome!
Thanks for the kind words. Definitely not a pro coder but have learned a lot from the great people in this forum!
- In reply toDanny_van_Spreuwel⬆:Danny @Danny_van_Spreuwel
Hi Raphael,
I switched to a M1 machine with Monterey. Now our nice macro got stuck on the target path. I think that element has been changed in this new OS. See log output in the image. Do you have Monterey to be able to fix this element?
Raphael Sepulveda @raphaelsepulveda2022-05-27 19:17:25.522Z
Hey @Danny_van_Spreuwel!
Ah yes, I know that in Monterey they changed that window completely. Unfortunately, I'm still in Catalina.
@Kitch, is one of your computers in Monterey? If so, could you take a look at this? This post seems to have a way to deal with it but I can't test it to make sure it works in this context. The full script for Danny is the one marked as the solution in this thread.
Kitch Membery @Kitch2022-05-27 19:54:52.847Z
- In reply toraphaelsepulveda⬆:
Kitch Membery @Kitch2022-05-27 20:16:07.908Z
@Danny_van_Spreuwel & @raphaelsepulveda,
Try replacing the
saveCopyIn
function with this one, legends;/** @param {{ savePath: string, newSessionName: string }} args */ function saveCopyIn({ savePath, newSessionName }) { const saveCopyInWin = sf.ui.proTools.windows.whoseTitle.is('Save Copy In...').first; sf.ui.proTools.menuClick({ menuPath: ['File', 'Save Copy In...'] }); saveCopyInWin.elementWaitFor({ waitType: "Appear", }); 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(); }
Note: @raphaelsepulveda I have not checked it on my non Monterey rig but let me know if this new function works for you also. (The logic looks sound and has not changed but I've not tested it.)
Rock on!
Raphael Sepulveda @raphaelsepulveda2022-05-27 20:23:49.547Z
Yessir, still works in Catalina! Thank you!!
Kitch Membery @Kitch2022-05-27 20:26:27.915Z
Wooo!!! Hopefully it works for @Danny_van_Spreuwel!
Danny @Danny_van_Spreuwel
Thank you Kitch for your time and repair!
The "done" version works. When using the "TC" workflow it got stuck on Line 38 (counting in the full script, see screenshot).
Danny @Danny_van_Spreuwel
Strange. I tried after awhile and now it works. I'll keep on using this function and w'll see if it was an unlucky shot at the beginning.
Kitch Membery @Kitch2022-05-30 19:06:23.891Z
Great to hear! :-)