Grabbing data out of marker
I am wondering if there's a way to goto a marker and open the marker to copy it's name. I want to use this inside of a doalltoclip. Basically go to a clip, open the marker that is at the same place as the clip and then grab that name etc.
Is this possible? The only way I know to do would be clicking on the marker. Is opening a marker to edit possible in a script??
- samuel henriques @samuel_henriques
Hey @ChipSloan,
This will
clipDoForEachSelectedClip
, get first memory location name from selection and rename the clip with its name.Hope it helps:
function getMemLocName() { // Get current main counter const currentCounter = sf.ui.proTools.getMenuItem("View", "Main Counter").children.first.children .filter(x => x.isMenuChecked)[0].title.invalidate().value // Change counter to samples sf.ui.proTools.mainCounterSetValue({ targetValue: "Samples" }) // filter mem locs within selection const memoryLocations = sf.ui.proTools.selectionGetInSamples() const memLocFromSelection = sf.proTools.memoryLocationsFetch().collection['list'].filter(m => m.mainCounterValue >= memoryLocations.selectionStart && m.mainCounterValue <= memoryLocations.selectionEnd ); // Change counter back to original sf.ui.proTools.mainCounterSetValue({ targetValue: currentCounter }) // return first memory location within selection return memLocFromSelection[0] } function renameClip() { // Get First Memory Location Name from selection const memLocName = getMemLocName() if (memLocName != undefined) { //Open Rename window sf.ui.proTools.menuClick({ menuPath: ['Clip', 'Rename...'] }); //Reference for Rename Window const renameWin = sf.ui.proTools.windows.whoseTitle.is('Name').first.elementWaitFor({ waitType: "Appear" }).element const nameClipOnlyButton = renameWin.groups.first.radioButtons.first /// Set Clip Name Only if (nameClipOnlyButton.exists) renameWin.groups.first.radioButtons.first.checkboxSet({ targetValue: "Enable" }); // Set the clip name to Track name renameWin.groups.first.textFields.first.elementSetTextFieldWithAreaValue({ value: memLocName.Name }); // Click OK renameWin.buttons.whoseTitle.is('OK').first.elementClick() // Wait for window to cloce renameWin.elementWaitFor({ waitType: "Disappear" }) } } function main() { // Acivate Pro Tools sf.ui.proTools.appActivateMainWindow() // Do For Each sf.ui.proTools.clipDoForEachSelectedClip({ action: renameClip, onError: "Continue" }) } main()
Chip Sloan @ChipSloan
Brilliant. Thank you.
- In reply tosamuel_henriques⬆:DDylan Furrow @Dylan_Furrow
Hey @Kitch this is the script i was using for the clip rename
- In reply toChipSloan⬆:Chip Sloan @ChipSloan
Okay one more. Once I have that name copied I want to open the Bounce to Disk window and use that name as the text entry in that. What is that command to enter the text into that field.
I actually want to do a similar thing in another script to the rename clip text field. So maybe can you tell me how to do both? I can't seem to get it right...
samuel henriques @samuel_henriques
okok,
this is the part of the code that returns the marker name:
function getMemLocName() { // Get current main counter const currentCounter = sf.ui.proTools.getMenuItem("View", "Main Counter").children.first.children .filter(x => x.isMenuChecked)[0].title.invalidate().value // Change counter to samples sf.ui.proTools.mainCounterSetValue({ targetValue: "Samples" }) // filter mem locs within selection const memoryLocations = sf.ui.proTools.selectionGetInSamples() const memLocFromSelection = sf.proTools.memoryLocationsFetch().collection['list'].filter(m => m.mainCounterValue >= memoryLocations.selectionStart && m.mainCounterValue <= memoryLocations.selectionEnd ); // Change counter back to original sf.ui.proTools.mainCounterSetValue({ targetValue: currentCounter }) // return first memory location within selection return memLocFromSelection[0] } // Get First Memory Location Name from selection const memLocName = getMemLocName() log(memLocName)
on the next step you will use
memLocName
on the text fieldthis will help you set text on the text field:
How to enter text into a Pro Tools text fieldlet me know if this makes sense or you get stuck
- VVanessa Garde @Vanessa_Garde
How would you adapt it to the "new" table marker format on 2023.06 or 2023.09?
Trying this without luck...
Thank you!
function getMemLocName() { // Ensure Memory Locations window is open if (!sf.ui.proTools.getMenuItem('Window', 'Memory Locations').isMenuChecked) sf.ui.proTools.memoryLocationsShowWindow(); const table = sf.ui.proTools.memoryLocationsWindow.invalidate().tables[1]; // Get current main counter const currentCounter = sf.ui.proTools.getMenuItem("View", "Main Counter").children.first.children .filter(x => x.isMenuChecked)[0].title.invalidate().value // Change counter to samples sf.ui.proTools.mainCounterSetValue({ targetValue: "Samples" }) // filter mem locs within selection const memoryLocations = sf.ui.proTools.selectionGetInSamples() const memLocFromSelection = table.childrenByRole("AXRow").filter(m => m.mainCounterValue >= memoryLocations.selectionStart && m.mainCounterValue <= memoryLocations.selectionEnd ); // Change counter back to original sf.ui.proTools.mainCounterSetValue({ targetValue: currentCounter }) // return first memory location within selection return memLocFromSelection[0] }
- BIn reply toChipSloan⬆:Brandon Jiaconia @Brandon_Jiaconia
@samuel_henriques - Could you show me how I could modify this script? I have been trying to sort it out on my own, but I am not really a programmer. It's a smaller part of a larger script involved with preparing my stems for delivery. If I have a clip selected and there is a marker on the first frame of the clip I'd like to select the marker. The marker and the start of the clip have the same timecode. Do you think this is possible ?
samuel henriques @samuel_henriques
Hello Brandon,
this script will return the first memory location name from a selection. But had an error that I just fixed.
You would like to select it instead?- BBrandon Jiaconia @Brandon_Jiaconia
I figured it out, thanks though!
- DIn reply toChipSloan⬆:Dylan Furrow @Dylan_Furrow
Hey guys, I've been trying to use this script and it doesn't seem to be renaming the clips. Everything else seems fine though
Kitch Membery @Kitch2024-09-04 20:34:31.706Z
Hi @Dylan_Furrow,
As requested in the Hangout, this should work. :-)
@raphaelsepulveda & @Chris_Shaw good call this suggested method!
function matchMemoryLocations({ selectedClips, memoryLocations }) { return selectedClips.reduce((result, clip) => { const matchingLocation = memoryLocations.find(location => location.startTime === clip.startTime); if (matchingLocation) { result.push({ oldClipName: clip.name, newClipName: matchingLocation.name, startTime: clip.startTime }); } return result; }, []); } function renameSelectedClipsByMarkers() { sf.ui.proTools.appActivate(); sf.app.proTools.invalidate(); const selection = sf.app.proTools.getTimelineSelection(); const selectionInTime = selection.inTime; const selectionOutTime = selection.outTime; // Get selected clips omitting preceding and following clip(s) const selectedClips = sf.app.proTools.getSelectedClipInfo().clips .filter(clip => clip.endTime !== Number(selectionInTime) && clip.startTime !== Number(selectionOutTime)) //Omit connected clips .map(clip => ({ name: clip.clipName, startTime: clip.startTime })); const memoryLocations = sf.app.proTools.memoryLocations.allItems.map(ml => ({ name: ml.name, startTime: ml.startTimeInSamples, })); const matchingLocations = matchMemoryLocations({ selectedClips, memoryLocations, }); matchingLocations.forEach(match => { sf.app.proTools.renameClip({ clipName: match.oldClipName, newName: match.newClipName, renameFile: true, }); }); } renameSelectedClipsByMarkers();
- DDylan Furrow @Dylan_Furrow
Doesn't seem to work, keeps returning this error...
Rename failed
Can't found clip: Audio 1_01.R
(PT_InvalidParameter) (Rename: Line 41)Kitch Membery @Kitch2024-09-04 21:12:26.437Z
Thanks @Dylan_Furrow
I'll take a look at this this afternoon.
- In reply toDylan_Furrow⬆:
Kitch Membery @Kitch2024-09-05 08:03:09.256Z
Hi @Dylan_Furrow,
This should work. However, if there are fades on any of the clips, it will not work as expected.
function matchMemoryLocations({ selectedClips, memoryLocations }) { const locationMap = new Map(memoryLocations.map(location => [location.startTime, location.name])); return selectedClips .filter(clip => locationMap.has(clip.startTime)) .map(clip => ({ oldClipName: clip.name, newClipName: locationMap.get(clip.startTime), startTime: clip.startTime })); } function getUniqueObjects(arr) { return arr.filter((item, index, self) => index === self.findIndex((t) => ( t.name === item.name && t.startTime === item.startTime )) ); } function renameSelectedClipsByMarkers() { sf.ui.proTools.appActivate(); const selection = sf.app.proTools.invalidate().getTimelineSelection(); const selectionInTime = selection.inTime; const selectionOutTime = selection.outTime; // Get selected clips omitting preceding and following clip(s) const selectedClips = sf.app.proTools.invalidate().getSelectedClipInfo().clips .filter(clip => clip.endTime !== Number(selectionInTime) && clip.startTime !== Number(selectionOutTime)) //Omit connected clips .map(clip => ({ name: clip.clipName.replace(/\.L$|\.R$/, ""), startTime: clip.startTime })); const uniqueSelectedClips = getUniqueObjects(selectedClips); const memoryLocations = sf.app.proTools.memoryLocations.allItems.map(ml => ({ name: ml.name, startTime: ml.startTimeInSamples, })); const matchingLocations = matchMemoryLocations({ selectedClips: uniqueSelectedClips, memoryLocations, }); matchingLocations.forEach(match => { sf.app.proTools.renameClip({ clipName: match.oldClipName, newName: match.newClipName, renameFile: true, }); sf.wait({ intervalMs: 100 }); }); } renameSelectedClipsByMarkers();
- DDylan Furrow @Dylan_Furrow
Sweet, works amazing! Thanks so much @Kitch
- DDylan Furrow @Dylan_Furrow
Hey @Kitch, i'm just wondering if theres a way this script can be modified sp that it does multiple clips per marker and incrementally numbers them.
Kitch Membery @Kitch2024-10-08 00:02:45.316Z
Hi @Dylan_Furrow,
Quite possibly... Can you tell me more about how this workflow looks?
What would be the manual steps that you'd take to perform the workflow?
Thanks in advance!
- DDylan Furrow @Dylan_Furrow
Hey @Kitch, heres a video explaining the workflow.
Kitch Membery @Kitch2024-10-09 01:39:17.260Z
Thanks for the video, @Dylan_Furrow. That workflow makes sense but requires a different approach to the one above. I'll see if I can whip something up later this week. :-)
- DDylan Furrow @Dylan_Furrow
Sweet, thanks!
Kitch Membery @Kitch2024-10-09 23:59:57.701Z
Hi @Dylan_Furrow,
Try this script...
Be sure to have the Clip List visible (I did not account for that.)
sf.app.proTools.invalidate(); sf.ui.proTools.mainWindow.invalidate(); function getPreceedingMemoryLocation(positionInSamples) { const memoryLocations = sf.app.proTools.memoryLocations.allItems; const memoryLocationsInfo = memoryLocations.map(ml => ({ name: ml.name, startTimeInSamples: Number(ml.startTimeInSamples), })); return memoryLocationsInfo.filter(ml => ml.startTimeInSamples <= positionInSamples).slice(-1)[0].name; } function getSelectedClips() { const selection = sf.app.proTools.invalidate().getTimelineSelection(); const selectionInTime = selection.inTime; const selectionOutTime = selection.outTime; // Get selected clips omitting preceding and following clip(s) const selectedClips = sf.app.proTools.invalidate().getSelectedClipInfo().clips .filter(clip => clip.endTime !== Number(selectionInTime) && clip.startTime !== Number(selectionOutTime)) //Omit connected clips .map(clip => ({ name: clip.clipName.replace(/\.L$|\.R$/, ""), startTime: clip.startTime, endTime: clip.endTime, preceedingMemoryLocationName: getPreceedingMemoryLocation(clip.startTime), })); return selectedClips; } function batchRenameClips(baseName) { sf.ui.proTools.mainWindow.getFirstWithTitle("Clip List").popupMenuSelect({ menuPath: ["Batch Rename..."], }); const batchClipRenameWindow = sf.ui.proTools.windows.whoseTitle.is("Batch Clip Rename").first.invalidate(); batchClipRenameWindow.elementWaitFor(); // Restore factory default preset batchClipRenameWindow.getFirstWithTitle("Librarian menu").popupMenuSelect({ menuPath: ["<factory default>"] }); // Clear existing name batchClipRenameWindow.checkBoxes.whoseTitle.is("Clear Existing Name").first.checkboxSet({ targetValue: "Enable" }); // Enable Numbering Checkbox batchClipRenameWindow.checkBoxes.whoseTitle.is("Numbering").first.checkboxSet({ targetValue: "Enable" }); // Set Add "Insert" field batchClipRenameWindow.textFields.allItems[7].elementSetTextFieldWithAreaValue({ value: baseName }); // Set "Separate With" field batchClipRenameWindow.textFields.allItems[14].elementSetTextFieldWithAreaValue({ value: "_" }); // Click OK batchClipRenameWindow.buttons.whoseTitle.is("OK").first.elementClick(); // Wait for Window to Disappear batchClipRenameWindow.elementWaitFor({ waitType: "Disappear" }); } function main() { const clips = getSelectedClips(); let selections = clips.reduce((acc, clip) => { let location = clip.preceedingMemoryLocationName; if (!acc[location]) { acc[location] = { startTime: clip.startTime, endTime: clip.endTime, }; } else { acc[location].endTime = Math.max(acc[location].endTime, Number(clip.endTime)); } return acc; }, {}); for (let memoryLocationName in selections) { if (selections.hasOwnProperty(memoryLocationName)) { sf.ui.proTools.appActivate(); sf.app.proTools.setTimelineSelection({ inTime: String(selections[memoryLocationName].startTime), outTime: String(selections[memoryLocationName].endTime), }); // Hack to ensure the clip selection gets updated in the clips list const selectedTrackNames = sf.ui.proTools.selectedTrackNames; sf.ui.proTools.trackSelectByName({ names: selectedTrackNames }); batchRenameClips(memoryLocationName); } } } main();
Let me know how it goes for you.
- DDylan Furrow @Dylan_Furrow
Works great @Kitch, thank you so much for all your help!
Kitch Membery @Kitch2024-10-10 22:56:49.272Z
Awesome! Glad it works. :-)
Thanks for reporting back!