All,
Is it possible for SF to search through the markers and perform an action every time it runs into a marker with a given name?
In promo work, I have sessions that sometimes have 20+ versions that need to be laid out with the same/similar audio (5.1/2.0 PM, 2/0 MnE/, 1.0 DX, etc).
Because of the help I have received here, all of the versions that I need to deliver have markers at the FFOP with a name that is formatted : TYPE VERSION NUMBER (i.e. Airmaster .12).
If I were to create a clip group called airmaster, could I get SF to paste it every time it sees an 'Airmaster' marker?
Thanks,
Randall
- samuel henriques @samuel_henriques
hey @Randall_Smith,
this will go thru all memory locations with the word "Airmaster" on the name and paste
function paste(memoryLocations){ sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }) sf.ui.proTools.menuClick({menuPath:["Edit", "Paste"]}) } const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x=>x.name.match("Airmaster")) memoryLocations.forEach(paste)
Hope it helps!
- RRandall Smith @Randall_Smith
Works like a champ. Thanks.
- In reply tosamuel_henriques⬆:OOwen Granich-Young @Owen_Granich_Young
Here it is now with a Prompt searching your memory locations instead of a fixed text. @samuel_henriques wrote the search prompt too, thought I'd just share it here.
function paste(memoryLocations) { sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }) sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"] }) } function prompt(item) { let prompt = sf.interaction.popupSearch({ items: item.map(x => ({ name: x["Name"] })) }).item.name return prompt }; function main() { const isMemLocWinOpened = sf.ui.proTools.getMenuItem('Window', 'Memory Locations').isMenuChecked // // Open mem loc win sf.ui.proTools.memoryLocationsShowWindow() let selectedMemoryLocations = sf.proTools.memoryLocationsFetch().collection['List'] let promptValue = prompt(selectedMemoryLocations) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match(promptValue)) memoryLocations.forEach(paste) // Set initial state of Mem Loc Win if (!isMemLocWinOpened) { sf.ui.proTools.menuClick({ menuPath: ['Window', 'Memory Locations'], targetValue: "Disable" }) }; } main()
- RIn reply toRandall_Smith⬆:Randall Smith @Randall_Smith
Sam/All,
I have been using this script for a bit and it works wonderfully. It takes our countdown leader for submasters and textless masters, adds it to the correct clips, consolidates and then copies the audio to the correct video based on the marker names.
Here it is:
const subClipGroup = "SUB - 12 Channel" const genClipGroup = "GEN - 6 CH" const currentTimecode = sf.ui.proTools.selectionGet().mainCounter.trim(); const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("Airmaster")) sf.ui.proTools.menuClick({ menuPath: ["View", "Other Displays", "Clip List"], targetValue: "Enable", }); sf.ui.proTools.memoryLocationsTempCreate({ tempNumber: 1, }); //alert(currentTimecode); //alert(subClipGroup); sf.ui.proTools.appActivateMainWindow(); //set timeline drop order //sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({ // menuPath: ["Timeline Drop Order", "Top to Bottom"], //}); function paste(memoryLocations) { sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }) sf.keyboard.press({ keys: "numpad minus", }); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"] }) } function chopEndPage(memoryLocations) { sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }) sf.ui.proTools.nudgeSet({ value: "00:00:00:10.00", }); sf.keyboard.press({ keys: "down", }); //sf.keyboard.press({ keys: "numpad minus", }); sf.keyboard.press({ keys: "s", }); sf.keyboard.press({ keys: "numpad minus", }); sf.keyboard.press({ keys: "g", }); } // sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"] }) function copyClipToPlayHead(name) { sf.keyboard.press({ keys: "cmd+shift+d", }); sf.keyboard.press({ keys: "cmd+shift+f", }); sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.checkBoxes.whoseTitle.is('By name').first.checkboxSet({ targetValue: "Enable", }); sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: name, }); sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.buttons.whoseTitle.is('OK').first.elementClick(); sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({ menuPath: ["Select", "All"], targetValue: "Enable", }); const row = sf.ui.proTools.mainWindow.clipListView.childrenByRole("AXRow").first; row.children.allItems[1].children.first.popupMenuSelect({ isRightClick: true, menuPath: ['Object Select in Edit Window'], onError: "Continue", }); //copy selected clip sf.keyboard.press({ keys: "cmd+c", }); sf.ui.proTools.memoryLocationsTempGoto({ tempNumber: 1, }); //nudge the clip back sf.ui.proTools.nudgeSet({ value: "00:00:10:00.00", }); sf.keyboard.press({ keys: "numpad minus", }); sf.keyboard.press({ keys: "cmd+v", }); //sf.ui.proTools.menuClick({ // menuPath: ["Edit","Consolidate Clip"], //}); //sf.ui.proTools.waitForNoModals(); //clean search sf.keyboard.press({ keys: "cmd+shift+d", }); sf.keyboard.press({ keys: "shift+tab", }); sf.ui.proTools.menuClick({ menuPath: ["Clip", "Group"], }); // sf.ui.proTools.menuClick({ // menuPath: ["Clip", "Rename..."], // }); // sf.wait({ // intervalMs: 200, // }); //alert(name); // sf.ui.proTools.windows.whoseTitle.is('Name').first.groups.whoseTitle.is('Name').first.textFields.whoseTitle.is('').first.elementSetTextAreaValue({ // value: name, // }); // sf.wait({ // intervalMs: 200, // }); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Copy"], }); // sf.ui.proTools.nudgeSet({ value: "00:00:00:01.00", }); } copyClipToPlayHead(subClipGroup); memoryLocations.forEach(paste) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("EP Out")) memoryLocations.forEach(chopEndPage) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("Texted")) memoryLocations.forEach(paste) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("Submaster")) memoryLocations.forEach(paste) copyClipToPlayHead(genClipGroup); const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("Textless")) memoryLocations.forEach(paste) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("Generic")) memoryLocations.forEach(paste) sf.ui.proTools.nudgeSet({ value: "00:00:00:01.00", }); //clean search sf.keyboard.press({ keys: "cmd+shift+d", });
My question is, is there a way to make this only work/serach markers/paste, etc based on markers in a given selection? I ask, because there are times where we get new versions added to an existing project and this will replace all of the old audio.
Thanks,
Randallsamuel henriques @samuel_henriques
Hello @Randall_Smith,
Awesome to know its been useful.
Here's a version that will only process the markers within the user selection on the timeline.
let me know if tis is what you asked for.
sf.ui.proTools.appActivate(); function doSomething(memoryLocations) { sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }) //do stuff here } const userSelection = sf.ui.proTools.selectionGetInSamples() sf.ui.proTools.mainCounterSetValue({ targetValue: "Samples" }) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.mainCounterValue >= userSelection.selectionStart && x.mainCounterValue <= userSelection.selectionEnd && x.name.match("Airmaster") || x.name.match("Location 5") //You can add more markers to the process by using || "or" ) memoryLocations.forEach(doSomething)
samuel henriques @samuel_henriques
UPDATE: made a nicer, cleaner version.
samuel henriques @samuel_henriques
I think this is even cleaner for you:
sf.ui.proTools.appActivate(); function findLocationNameInSelection(locationName) { sf.ui.proTools.mainCounterSetValue({ targetValue: "Samples" }) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.mainCounterValue >= userSelection.selectionStart && x.mainCounterValue <= userSelection.selectionEnd && x.name.match(locationName)); return memoryLocations } function doSomething(memoryLocations) { sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }); //do stuff here } const userSelection = sf.ui.proTools.selectionGetInSamples() findLocationNameInSelection("Airmaster").forEach(doSomething) findLocationNameInSelection("Location 8").forEach(doSomething)
- RRandall Smith @Randall_Smith
Samuel,
Thank you. It works well. I am running into an issue though. One of my commands, the 'chopEndPage' no longer functions. Instead of going to each EP Out maker and chooping the audio and adding a fade, stays at the last 'Airmaster' marker and loops for the number of times that the 'EP Out' marker is in the marker window.
Here is what I have:
const subClipGroup = "SUB - 12 Channel" const genClipGroup = "GEN - 6 CH" const currentTimecode = sf.ui.proTools.selectionGet().mainCounter.trim(); const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("Airmaster")) sf.ui.proTools.appActivate(); function findLocationName(locationName){ sf.ui.proTools.mainCounterSetValue({ targetValue: "Samples" }) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.mainCounterValue >= userSelection.selectionStart && x.mainCounterValue <= userSelection.selectionEnd && x.name.match(locationName)) return memoryLocations } function doSomething(memoryLocations) { sf.ui.proTools.nudgeSet({ value: "480480", }); sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }) //do stuff here sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number }) sf.keyboard.press({ keys: "numpad minus", }); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"] }) } function chopEndPage(memoryLocations) { sf.ui.proTools.nudgeSet({ value: "20020", }); sf.keyboard.press({ keys: "down", }); //sf.keyboard.press({ keys: "numpad minus", }); sf.keyboard.press({ keys: "s", }); sf.keyboard.press({ keys: "numpad minus", }); sf.keyboard.press({ keys: "g", }); } function copyClipToPlayHead(name) { sf.keyboard.press({ keys: "cmd+shift+d", }); sf.keyboard.press({ keys: "cmd+shift+f", }); sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.checkBoxes.whoseTitle.is('By name').first.checkboxSet({ targetValue: "Enable", }); sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.textFields.whoseTitle.is('').first.elementSetTextFieldWithAreaValue({ value: name, }); sf.ui.proTools.windows.whoseTitle.is('Find Clips').first.buttons.whoseTitle.is('OK').first.elementClick(); sf.ui.proTools.mainWindow.popupButtons.whoseTitle.is('Clip List').first.popupMenuSelect({ menuPath: ["Select", "All"], targetValue: "Enable", }); const row = sf.ui.proTools.mainWindow.clipListView.childrenByRole("AXRow").first; row.children.allItems[1].children.first.popupMenuSelect({ isRightClick: true, menuPath: ['Object Select in Edit Window'], onError: "Continue", }); //copy selected clip sf.keyboard.press({ keys: "cmd+c", }); sf.wait({ intervalMs: 200, }); sf.ui.proTools.memoryLocationsTempGoto({ tempNumber: 1, }); sf.keyboard.press({ keys: "numpad minus", }); sf.keyboard.press({ keys: "cmd+v", }); sf.keyboard.press({ keys: "cmd+shift+d", }); sf.keyboard.press({ keys: "shift+tab", }); sf.ui.proTools.menuClick({ menuPath: ["Clip", "Group"], }); sf.ui.proTools.menuClick({ menuPath: ["Edit", "Copy"], }); // sf.ui.proTools.nudgeSet({ value: "00:00:00:01.00", }); } const userSelection = sf.ui.proTools.selectionGetInSamples() sf.ui.proTools.menuClick({ menuPath: ["View", "Other Displays", "Clip List"], targetValue: "Enable", }); sf.ui.proTools.memoryLocationsTempCreate({ tempNumber: 1, }); sf.ui.proTools.appActivateMainWindow(); copyClipToPlayHead(subClipGroup); findLocationName("Airmaster").forEach(doSomething) findLocationName("EP Out").forEach(chopEndPage) //const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("EP Out")) //memoryLocations.forEach(chopEndPage) findLocationName("Texted").forEach(doSomething) findLocationName("Submaster").forEach(doSomething) sf.ui.proTools.mainCounterSetValue({ targetValue: "Timecode" }) copyClipToPlayHead(genClipGroup); findLocationName("Textless").forEach(doSomething) findLocationName("Generic").forEach(doSomething) //findLocationName("Location 8").forEach(doSomething) sf.ui.proTools.mainCounterSetValue({ targetValue: "Timecode" }) sf.ui.proTools.nudgeSet({ value: "00:00:00:01.00", });
samuel henriques @samuel_henriques
I think you need to add
sf.ui.proTools.memoryLocationsGoto({ memoryLocationNumber: memoryLocations.number })
on that function
and the
doSomething(memoryLocations)
function I sent already had thememoryLocationsGoto
on it and you are repeating itI don't think you need to change the
sf.ui.proTools.nudgeSet({ value: "480480", });
from time code to samples. The main counter is changing to samples but not the nudge settings.
If you need the main counter in timecode, you could add that line in the function like this:
function findLocationName(locationName) { sf.ui.proTools.mainCounterSetValue({ targetValue: "Samples" }) const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.mainCounterValue >= userSelection.selectionStart && x.mainCounterValue <= userSelection.selectionEnd && x.name.match(locationName)); sf.ui.proTools.mainCounterSetValue({ targetValue: "Timecode" }) return memoryLocations }
also, you should remove the line
const memoryLocations = sf.proTools.memoryLocationsFetchFromGui().collection.list.filter(x => x.name.match("Airmaster"))
since you are using it as a function now.
let me know how it goes
samuel henriques @samuel_henriques
after this is working, you should work on replacing the possible keyboard press with menus, it'll help with stability