Hi all, music editor here. I've got a bunch of score files, formatted like this:
TN 419. 3M2. 01.20.30.21. stereo.wav
And I'm trying to capture the timecodes and enter them into the transport so I can quickly create a marker for each file.
I've used key press commands to copy "01.20.30.21" to the clipboard, but when I switch to Pro Tools and have it press * then command V, it doesn't enter. I have a feeling it may have to do with the periods, and that this might require a script rather than key press macros. What do you recommend?
- Raphael Sepulveda @raphaelsepulveda2022-03-23 17:26:23.640Z
Hey @Nick_Norton1,
Try this, it will take the contents of the clipboard and replace any “.” with “:”, which should allow you to paste it into the main counter. Put it after the command that copies the timecode to the clipboard.
const clipboardContents = sf.clipboard.getText().text; sf.clipboard.setText({ text: clipboardContents.split('.').join(':') });
Nick Norton @notNickNorton
Thanks! Time to give Javascript a shot...
Nick Norton @notNickNorton
Wow did that ever work!
My full script, in case you see any room for improvement. It also goes back to the finder and gets the cue number and types that in for the marker name.
sf.keyboard.press({ keys: "return, right, alt+left, left, left, alt+shift+left, cmd+c, return", }); const clipboardContents = sf.clipboard.getText().text; sf.clipboard.setText({ text: clipboardContents.split('.').join(':') }); sf.ui.proTools.appActivate(); sf.keyboard.press({ keys: "numpad multiply", }); sf.keyboard.press({ keys: "cmd+v", }); sf.keyboard.press({ keys: "return", }); sf.ui.finder.appActivate(); sf.keyboard.press({ keys: "return, right, alt+left, alt+left, left, left, alt+shift+left, cmd+c, return", }); sf.ui.proTools.appActivate(); sf.keyboard.press({ keys: "numpad enter", }); sf.keyboard.press({ keys: "cmd+v", }); sf.keyboard.press({ keys: "numpad enter", }); sf.ui.finder.appActivate(); sf.keyboard.press({ keys: "down", });
Raphael Sepulveda @raphaelsepulveda2022-03-24 02:30:33.009Z2022-03-25 01:07:17.707Z
That's great!
With SoundFlow, scripts are more robust if we avoid using keyboard shortcuts as much as possible. I've reviewed your script and optimized it for ya!
Now all you have to do is select as many files as you like on Finder and run this. The script will identify which files within the selection follow your naming convention and filter out the rest. It will then extract the cue number and timecode and create memory locations for those using that data.
Give it a try and let me know if it works on your end!
function finderGetSelectedFileNames() { sf.ui.finder.appActivate(); const selectedPaths = sf.ui.finder.selectedPaths; if (!selectedPaths.length) throw 'No files selected in Finder.' const fileNames = selectedPaths.map(path => path.split('/').filter(Boolean).slice(-1)[0]); return { fileNames }; } /** @param {string[]} fileNames - Array containing file names. */ function getScoreDataFromFileNames(fileNames) { const scoreData = fileNames.reduce((acc, fileName) => { // Check if filename contains both "xMx." and "xx.xx.xx.xx" patterns (x are numbers) const match = fileName.match(/(\dM\d+)|(\d\d\.\d\d\.\d\d\.\d\d)/g); if (match && match.length === 2) { // If there's a match, extract data from filename let [cueNumber, timecode] = match; // Format timecode by replacing periods with colons timecode = timecode.split('.').join(':'); acc.push({ cueNumber, timecode }); } return acc; }, []); if (!scoreData.length) throw 'No file names with format pattern detected.' return { scoreData }; } /** @param {{ timecode: string }} arg */ function mainCounterGoToTimecode({ timecode }) { sf.clipboard.setText({ text: timecode }); sf.ui.proTools.mainWindow.counterDisplay.textFields.whoseTitle.is("Main Counter").first.elementClick(); sf.keyboard.press({ keys: "cmd+v, return", }); } /** Simple Create Memory Location * @param {{ name: string }} arg */ function createMemoryLocation({ name }) { const memoryLocationDialog = sf.ui.proTools.newMemoryLocationDialog; sf.ui.proTools.appActivateMainWindow(); sf.keyboard.press({ keys: "numpad enter" }); memoryLocationDialog.elementWaitFor(); memoryLocationDialog.textFields.allItems[1].elementSetTextFieldWithAreaValue({ value: name }); memoryLocationDialog.buttons.whoseTitle.is("OK").first.elementClick(); memoryLocationDialog.elementWaitFor({ waitType: "Disappear" }); } function main() { const { fileNames } = finderGetSelectedFileNames(); const { scoreData } = getScoreDataFromFileNames(fileNames); sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.mainCounterDoWithValue({ targetValue: "Timecode", action: () => { for (const data of scoreData) { mainCounterGoToTimecode({ timecode: data.timecode }); createMemoryLocation({ name: data.cueNumber }); } } }); } main();
Nick Norton @notNickNorton
Damn did that ever work! Thank you!!
Nick Norton @notNickNorton
This is actually begging two new questions:
-
What if the format is slightly different? Is there a way for JS to detect strings of xx.xx.xx.xx and xMx if they, for instance, don't have the dot right next to them, or have a different number of spaces?
-
Is there a way to do this from folder names too? Sometimes I get stereo tracks, sometimes I get folders of stems. In that case, question 1 would apply because folders don't have the word "stereo" at the end.
Thank you!
Raphael Sepulveda @raphaelsepulveda2022-03-24 19:55:19.547Z
Yeah, I can adjust the algorithm so that if the filename contains a "xMx" and a "xx.xx.xx.xx" (x being numbers) then that will qualify to be put in the session. Do you think that'll be enough? Or are there any other variations? If so, showing me a few examples would help a ton!
Oh and yes, the method I'm mentioning here will work with any file including folders since it's just looking for those two specific string patterns.
Nick Norton @notNickNorton
Sweet! Here are a few examples:
SnS.404.5M3.01.40.11.04.Master.wav
SS 601. 1M1. 01.02.19.13. stereo.wav
TPF 107. 0M1. V2. 01.00.00.00. stereo.wav
RHOH 1. 0M15. 01.04.19.19. stereo.wav. (that one has a double digit after the M)
Raphael Sepulveda @raphaelsepulveda2022-03-25 01:13:56.965Z
Perfect, I've updated the code above to handle all these cases!
This should work as expected, as long as there aren't cases in which you have an additional combination of words that resemble "xMx" besides the actual cue number. Currently, those would end up getting filtered out.
-