I work in large TV/Feature FX templates a lot. They often have multiple matching FX BUCKETS (routing folders of tracks) to keep the FX seperate and organized and/or cut for perspective.
I've created a very simple cut and paste between FX BUCKETS which has worked great with some limitations, and I'm wondering if somebody can help me level it up?
Currently it's fast but not intelligent. It very simply cut's what you have selected, seleects and opens a folder track and pastes the matieral into there, then scrolls it into view.
const folderName = event.props.folderName
//Activate Pro Tools
sf.ui.proTools.appActivate();
sf.ui.proTools.invalidate()
//Cut Selection
sf.ui.proTools.menuClick({
menuPath: ["Edit", "Cut"],
});
//Open Desination Folder Track
sf.ui.proTools.trackGetByName({ name: folderName, makeVisible: true }).track.trackSelect();
//sf.ui.proTools.selectedTrack.folderTrackSetOpen();
sf.ui.proTools.menuClick({
menuPath: ["Edit", "Paste"],
});
sf.ui.proTools.trackGetByName({ name: folderName, makeVisible: true }).track.trackScrollToView();
However obviously this means that the track count of the highlighted selection needs to match the desination exaclty. I'm wondering how one would go about having the script instead look at the names of the tracks and move it to those named tracks in a diffrent FX BUCKET, since the track names are consistient across Buckets.
Similar to this script @samuel_henriques built. Copy region to .LFE track That pastes a copy to the current groups .LFE how would you get a script look at the track names and then cut and paste the material to the matching track number in a diffrent FX BUCKET

For example : I'd like to be able to make a selection like the above picture and the script be able to Cut and Paste those into their matching tracks in the 8 FX bucket tracks 8.4 8.5 8.6 8.9 8.10 8.11
I don't know if this will be annoyingly slow though? It may take SF too much though to process it track by track?
Thoughts ideas?
As always,
Thanks so much
Owen
- samuel henriques @samuel_henriques
Hello Owen,
I think this is a good starting point. When you run the script it will show all the visible folder tracks so you can choose one, then it will paste the clips on the same track names matching the chosen folder.
Let me know how it goes.function prompt(item) { let prompt = sf.interaction.popupSearch({ items: item.map(x => ({ name: x.normalizedTrackName, header: x })) }).item return prompt }; function main() { sf.ui.proTools.appActivateMainWindow() sf.ui.proTools.invalidate() const selectedTracks = sf.ui.proTools.selectedTrackNames const folderTracks = sf.ui.proTools.visibleTrackHeaders.filter(x => x.title.value.endsWith("Folder Track ")) const folderToMove = prompt(folderTracks) sf.ui.proTools.appActivateMainWindow() folderToMove["header"].folderTrackSetOpen({ targetValue: "Enable" }); sf.ui.proTools.invalidate() const destFolder = sf.ui.proTools.trackGetByName({ name: folderToMove["name"] }).track.children.whoseRole.is("AXDisclosureTriangle").whoseTitle.is("Close Folder").first destFolder.elementWaitFor({}, "Folder didn't open.") //Cut Selection sf.ui.proTools.menuClick({ menuPath: ["Edit", "Cut"] }); const destTracks = selectedTracks.map(tr => folderToMove["name"].split(" ")[1] + "." + tr.split(".")[1]) sf.ui.proTools.trackSelectByName({ names: destTracks }) // Paste Selection sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"] }); // Scroll to view const selectedDestTracks = sf.ui.proTools.selectedTrackHeaders selectedDestTracks[0].trackScrollToView() const trackToScroll = selectedDestTracks[0].popupButtons.first.elementWaitFor().element trackToScroll.mouseClickElement({ isControl: true, isShift: true }) sf.ui.proTools.trackSelectByName({ names: destTracks }) }; main()
- OOwen Granich-Young @Owen_Granich_Young
Wow that was fast bud!
It seems to not work if the destinaton folder is not open. Is the script moving faster then the folder track can open at line 16?
Otherwise it's crazy fast and snappy!
How would I correctly add a
sf.ui.proTools.selectedTrack.trackScrollToView(destTracks);
at the end? I know that's not right as I tired it.samuel henriques @samuel_henriques
UPDATED ABOVE.
You have the scroll to view as well. But for me the best way is the behaviour of when you shift+ctrl click the name of the track on the track list.
Do you keep the track list open?- OOwen Granich-Young @Owen_Granich_Young
This works perfectly! You're a rockstar.
As far as track list open, not always. You're saying you feel that Shift+Ctrl Click is snappier navigation for you?
Bests,
Owensamuel henriques @samuel_henriques
Not snappier, but always places the track on the top of screen.
The way you have now, if the first destination track is visible, even if really down in the screen it won't move. And if it's really down, out of screen, all you'll see is the first track, that's the only that will be schooled. It only works well if the destination tracks are out of screen further in the top.
But try it for a bit, and let me know how you feel.
- OOwen Granich-Young @Owen_Granich_Young
Ohhh I see, I have run into that problem before with other session navigation scripts I've built. For experimentation sake is it easy to put the code in the above script and
///comment
it out so I can experimetn swapping between the two?Thanks!
Owensamuel henriques @samuel_henriques
UPDATED ABOVE.
Keep the track list open for now. If this is the solution for you, I'll add the open/close track list. It changes a bit the script
- In reply tosamuel_henriques⬆:
samuel henriques @samuel_henriques
I have a script that uses the track list and it you want I can make it open track list if closed, scroll, and close if it was closed. That's how I use it.
- OOwen Granich-Young @Owen_Granich_Young
Thanks man! TBH I'm only hiding track list now because soundflow has giving me the option to thin down my views quickly, for over a decade before that it was always open.
samuel henriques @samuel_henriques
Cool. It's the end of day for me here. In the morning I'll add a bit to open it if closed and close it in the end.
samuel henriques @samuel_henriques
UPDATED ABOVE,
Added the tracks list open/close bit.
Enjoy!
- OOwen Granich-Young @Owen_Granich_Young
Just wanted to say I'm using the HELL out of this. In fact I've even jacked the function to help with a persepctive cut script as well!
Of note, for some reason the track list aspect really wasn't working consitently on my system. Not sure if it was a folder track issue or just the sheer size of my session and the track not being visible in the track list or what? I messed around for a while to see if I could figure out exaclty why it wasn't working but it was really really inconsisitent and I had to get back to work. Which is a bummer becuase I do really like the idea of the selected track always jumping to the top of the screen not just whever it's shown.
Just thinking outloud is there an easy mouse simulation to tack onto the end of the
/// Scroll to view // const selectedDestTracks = sf.ui.proTools.selectedTrackHeaders // selectedDestTracks[0].trackScrollToView()
Version of the script that Ctrl+Shift+Click's the track to get the same desired effect or is that too unstable?
Bests,
Owensamuel henriques @samuel_henriques
Is there a chance the destination track is not visible in the track list when it's failing?
- OOwen Granich-Young @Owen_Granich_Young
Absolutley! The session is massive so there's no way all the tracks are visible in the track list all the time. I tired testing this being the cause by scrolling in the track list so the destination track was visiible when I triggered the script but still a little funky.
samuel henriques @samuel_henriques
Your idea looks good.
Just Updated the script with it. Also, in the end it will select the destination tracks.
Let me know
samuel henriques @samuel_henriques
This way we don't need to use the track list. Just a minute and I'll remove it
samuel henriques @samuel_henriques
UPDATED again.
- OOwen Granich-Young @Owen_Granich_Young
So snappy so good! I'm gonna steal that little part of the script for general navigation too! By far my new favorite way of scrolling to view.
samuel henriques @samuel_henriques
Awesome!!
samuel henriques @samuel_henriques
Hello Owen,
I made another version.
This lineconst trackToScroll = selectedDestTracks[0].popupButtons.first.elementWaitFor().element
was meant to wait for the track header to be visible an then ctrl+shift click , since I expect in same cases, the area it needs to click wont be there, because pro tools takes tame to scroll to view. Specially if you have giant sessions.
Hence this wait. But I've tested it more and this is not a solution for this problem. The header is always there, so waiting for it doesn't do anything.In this version, the script will scroll the same way, but then will check if the track is in view. If it isn't it will scroll again.
function scrollToTop() { const selectedDestTracks = sf.ui.proTools.selectedTrackHeaders if (selectedDestTracks[0]) { //Scroll to Top selectedDestTracks[0].trackScrollToView() selectedDestTracks[0].popupButtons.first.mouseClickElement({ isControl: true, isShift: true }) // Double-ckeck if the track is in view const minY = sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Edit Window View selector").first.frame.y const maxY = sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Track List Show/Hide").first.frame.y if (selectedDestTracks[0].popupButtons.first.frame.y < minY || selectedDestTracks[0].popupButtons.first.frame.y > maxY) { scrollToTop() } } else { log("No Track Selected to Paste. Track Names Might Not Match.") } }; function prompt(item) { let prompt = sf.interaction.popupSearch({ items: item.map(x => ({ name: x.normalizedTrackName, header: x })) }).item return prompt }; function main() { sf.ui.proTools.appActivateMainWindow() sf.ui.proTools.invalidate() const selectedTracks = sf.ui.proTools.selectedTrackNames const folderTracks = sf.ui.proTools.visibleTrackHeaders.filter(x => x.title.value.endsWith("Folder Track ")) const folderToMove = prompt(folderTracks) sf.ui.proTools.appActivateMainWindow() folderToMove.header.folderTrackSetOpen({ targetValue: "Enable" }, function () { // If folder size is too small, use popup menu to open folder const destFolderTrack = sf.ui.proTools.trackGetByName({ name: folderToMove.name }).track; destFolderTrack.trackScrollToView() destFolderTrack.popupButtons.whoseTitle.is("Track options").first.popupMenuSelect({ menuPath: ["Open Folder"], }); }); sf.ui.proTools.invalidate() //Cut Selection sf.ui.proTools.menuClick({ menuPath: ["Edit", "Cut"] }); const destTracks = selectedTracks.map(tr => folderToMove.name.split(" ")[1] + "." + tr.split(".")[1]) sf.ui.proTools.trackSelectByName({ names: destTracks }) // Paste Selection sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"] }); scrollToTop() sf.ui.proTools.trackSelectByName({ names: destTracks }) }; main()
- OOwen Granich-Young @Owen_Granich_Young
Very cool! Thanks bud!
- In reply tosamuel_henriques⬆:OOwen Granich-Young @Owen_Granich_Young
This script has started bugging out if the folder is closed... I've just taken to leaving all my folders open but it's weird and irksome.
Tried both the most recent and previous same error. (Diffrent line Obviously.)
samuel henriques @samuel_henriques
Hello Owen,
I'm sorry I can't recreate the error.Could you do a screen recording when it happens so I could find any leads for the error?
You can send the link to my email if the session shows information you don't want to share in the forum.
samuelhenriques@me.com- OOwen Granich-Young @Owen_Granich_Young
Yeah will do when I have a free moment.
I do have the folder IN a Folder - that could be the problem, the root folder is always open.
samuel henriques @samuel_henriques
ahh, is the folder size like in the picture, so the folder icon to open/close is not visible?
- OOwen Granich-Young @Owen_Granich_Young
oh yeah, for sure... lemme try making all the folder med... I'm sure that's it.
- OOwen Granich-Young @Owen_Granich_Young
YEP that solved it! Thanks boss!
'Feature not a bug' :P
Noted small is the smallest it should go. I can work around that.
- In reply toOwen_Granich_Young⬆:
samuel henriques @samuel_henriques
Cool. That was it. Just updated with a fix for when the folder is too small
- OOwen Granich-Young @Owen_Granich_Young
oh Sick!
- In reply tosamuel_henriques⬆:
samuel henriques @samuel_henriques
The script needs to see the folder icon, where you click to open/close.
What I added is, in case it's not visible, instead of calling an error, scroll to folder and use the popup to open.samuel henriques @samuel_henriques
BTW, if you close that parent folder, the script wont work, because he can't find the destination folder. So far pro tools doesn't show the tracks inside closed folder tracks
- OOwen Granich-Young @Owen_Granich_Young
Good to know, never an issue in this session the bFX Parent is always open. But I have another template I've been toying with that's a bit deeper on folder tracks in folder tracks, that that would be an issue.
Thanks again for everything, I use this script ALL THE TIME.
samuel henriques @samuel_henriques
Awesome. I'm sure we can figure something to make it work on that other template. When you need, let me know the workflow and I'll think about it.
- OOwen Granich-Young @Owen_Granich_Young
Hey @samuel_henriques I'm working on a new show with a new mixer with a different naming convention for his tracks, do you have the time to possible adapt this script to his naming convention? I still haven't really wrapped my head around the
.split
and filter action in thedestTracks
const.This mixers layout is duplicates of this in each folder group
So the split at the . won't work anymore....
No worries if you're too busy, but if it's an easy 'o yeah no problem'....
Thanks!
Owensamuel henriques @samuel_henriques
Hey Owen, let me see if I can figure this fast.
So he adds an F to each bucket of tracks?
bucket one: FX F
bucket two: FX FF
bucket three: FX FFFAnd we only need to figure the destination track names, I don't remember anymore how it was all working.
- OOwen Granich-Young @Owen_Granich_Young
No, each group is a diffrent letter and F is mono and FF is Stereo. Here's G for example:
- OOwen Granich-Young @Owen_Granich_Young
samuel henriques @samuel_henriques
Here you go.
Try it for a bit to see if I missed something.
I made an improvement, in case there aro no destination tracks, now it wont cut and you'll get a warning.
I kept your original naming lines o you can use this script instead, just comment the "New naming" lines and uncomment the "Original Naming" line.function scrollToTop() { const selectedDestTracks = sf.ui.proTools.selectedTrackHeaders if (selectedDestTracks[0]) { //Scroll to Top selectedDestTracks[0].trackScrollToView() selectedDestTracks[0].popupButtons.first.mouseClickElement({ isControl: true, isShift: true }) // Double-ckeck if the track is in view const minY = sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Edit Window View selector").first.frame.y const maxY = sf.ui.proTools.mainWindow.buttons.whoseTitle.is("Track List Show/Hide").first.frame.y if (selectedDestTracks[0].popupButtons.first.frame.y < minY || selectedDestTracks[0].popupButtons.first.frame.y > maxY) { scrollToTop() }; }; }; function prompt(item) { const formatItems = item.map(tr => ({ header: tr, name: tr.normalizedTrackName, comment: tr.textFields.first.value.value })) let prompt = sf.interaction.popupSearch({ items: formatItems, title: 'Select', columns: [ { name: 'FX Name', key: 'name', width: 50 }, { name: 'Comment', key: 'comment', width: 50 }, ], }).item; return prompt }; function forceTrackViewWaveform(selectedTracks) { // Set waveform view if not const hasViewNotWaveform = () => selectedTracks.find(th => th.displaySelectorButton.value.invalidate().value !== "waveform") === undefined ? false : true; while (hasViewNotWaveform()) { sf.ui.proTools.trackVolumeToggle(); }; } function main() { sf.ui.proTools.appActivateMainWindow() sf.ui.proTools.invalidate() const selectedTrackHeaders = sf.ui.proTools.selectedTrackHeaders; forceTrackViewWaveform(selectedTrackHeaders); const selectedTracks = selectedTrackHeaders.map(th => th.normalizedTrackName); const folderTracks = sf.ui.proTools.visibleTrackHeaders.filter(x => x.title.value.endsWith("Folder Track ")); const folderToMove = prompt(folderTracks) sf.ui.proTools.appActivateMainWindow(); folderToMove.header.folderTrackSetOpen({ targetValue: "Enable" }, function () { // If folder size is too small, use popup menu to open folder const destFolderTrack = sf.ui.proTools.trackGetByName({ name: folderToMove.name }).track; destFolderTrack.trackScrollToView() destFolderTrack.popupButtons.whoseTitle.is("Track options").first.popupMenuSelect({ menuPath: ["Open Folder"], }); }); sf.ui.proTools.invalidate() const trackTypeSymbol = folderToMove.name.split(" ")[1]; //Original Naming // const destTracks = selectedTracks.map(tr => folderToMove.name.split(" ")[1] + "." + tr.split(".")[1]) /// //New Naming const destTracks = selectedTracks.map(tr => { const [fxTrack, type, n] = tr.split(" "); return `${fxTrack} ${type.split("").map(ch => ch.replace(ch, trackTypeSymbol)).join("")} ${n}` }); ///// let tracksExist = sf.ui.proTools.visibleTrackNames.filter(trackName => destTracks.includes(trackName)).length === selectedTracks.length if (!tracksExist) { log("No Track Found to Paste. Track Names Might Not Match."); return; } //Cut Selection sf.ui.proTools.menuClick({ menuPath: ["Edit", "Cut"] }); // Select destination tracks sf.ui.proTools.trackSelectByName({ names: destTracks }); // Paste Selection sf.ui.proTools.menuClick({ menuPath: ["Edit", "Paste"] }); scrollToTop() sf.ui.proTools.trackSelectByName({ names: destTracks }) }; main();
- OOwen Granich-Young @Owen_Granich_Young
Sick, you're a rockstar. I'll run it through it's paces and let you know if anything gets funky.
THANKS!
Owen - In reply tosamuel_henriques⬆:OOwen Granich-Young @Owen_Granich_Young
Only a few moves so far but it's working nicely. (I just have to remember to be in waveform view not VOL sometimes)
I wanted to ask how hard it would be to implement a feature in the prompt where in addition to the names of the folder tracks it also showed a 2nd column with the comments of those folder tracks?
We often name the groups in the comments for example :
Would be a nice bonus to see the comments in a 2nd column on the prompt window.
samuel henriques @samuel_henriques
UPDATED above.
Added,- change all selected tracks to waveform
- added comments column
Daniel Perez @daniel_perez
i want to use a part of this script for my navigation script. i'm not smart enough to decode what's going on here.
my macro is the simple
sf.ui.proTools.trackGetByName({ name: "DX BUS", makeVisible: true }).track.trackScrollToView();
line.
what can i add to this script, to not only scroll into view, but make the track the topmost?