Hey everyone,
I've been wanting to create a macro that organizes the order of tracks based on which has audio information first.
Usually, I like to organize my tracks in the Edit window prioritizing the ones that have audio throughout the whole song at the bottom and the ones that appear at the end at the top.
If I think of the order of actions it would be something like this
- Recognize selected tracks, let's say 3 tracks
- Use the Tab key to pinpoint the first transient from the selection
- Drag to the bottom the track that has that information
- Drag to the top the track that has information last
The first script to create would be the one for step 2 but I'm having a hard time getting this done. Does anyone have any good ideas?
Thanks!
- samuel henriques @samuel_henriques
Hello Hendrick Valera ,
I made one of these some time ago and just noticed it could be improved.
First you need to select the tracks you want sorted, then run the script.
It will select each, then menu click "Select All" and take the start time.
Then it will move the tracks so they are ordered by starting clip in timeline.
On mine, for some reason, (witch I think it's my computer being annoying), it might not do it on first go.
So I added a bit to keep trying until the order is correct.It will do it for any amount of tracks you select.
Be aware that using mouse simulate is not the most stable thing, but that's the way to move tracks.
Let me know if this is it.
function moveTracksToTop(selectedTracks, trackNames) { // Safety deselect all sf.ui.proTools.trackDeselectAll() // Get possition of first track let firstTrackPosition = sf.ui.proTools.trackGetByName({ name: selectedTracks[0] }).track.frame // Safety deselect all sf.ui.proTools.trackDeselectAll() for (let i = 0; i < trackNames.length; i++) { sf.ui.proTools.trackGetByName({ name: trackNames[i] }).track.trackScrollToView() const elementPosition = sf.ui.proTools.trackGetByName({ name: trackNames[i] }).track.frame sf.mouse.simulateDrag({ startPosition: { "x": elementPosition.x + 20, "y": elementPosition.y + 10 }, endPosition: { "x": elementPosition.x + 20, "y": firstTrackPosition.y }, }); sf.ui.proTools.invalidate() } } function getTrackNameStartTime(selectedTracks) { let startTime let trackList = [] for (let i = 0; i < selectedTracks.length; i++) { sf.ui.proTools.trackSelectByName({ names: [selectedTracks[i]] }) sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); startTime = sf.ui.proTools.selectionGetInSamples().selectionStart trackList[i] = { trackName: selectedTracks[i], startTime: +startTime } } return trackList } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate() const selectedTracks = sf.ui.proTools.selectedTrackNames const trackList = getTrackNameStartTime(selectedTracks) /// Sort array of objects by property. ? 1:-1 ascending / ? -1:1 descending const tracksToMove = trackList.sort((a, b) => (a.startTime > b.startTime) ? -1 : 1).map(track => track.trackName) moveTracksToTop(selectedTracks, tracksToMove) sf.ui.proTools.trackSelectByName({ names: selectedTracks }) if (sf.ui.proTools.selectedTrackNames.join(",") != tracksToMove.reverse().toString()) { main() } else { alert("Sorted") } } main()
Chris Shaw @Chris_Shaw2021-11-06 18:25:33.757Z
Nice one!
Chris Shaw @Chris_Shaw2021-11-06 18:41:48.623Z
I tweaked your main slightly to save and restore the original selection:
function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate(); // Get original selection var origSelection = sf.ui.proTools.selectionGet(); const selectedTracks = sf.ui.proTools.selectedTrackNames; const trackList = getTrackNameStartTime(selectedTracks) /// Sort array of objects by property. ? 1:-1 ascending / ? -1:1 descending const tracksToMove = trackList.sort((a, b) => (a.startTime > b.startTime) ? -1 : 1).map(track => track.trackName) moveTracksToTop(selectedTracks, tracksToMove) sf.ui.proTools.trackSelectByName({ names: selectedTracks }) if (sf.ui.proTools.selectedTrackNames.join(",") != tracksToMove.reverse().toString()) { main() } else { //Restore original selection sf.ui.proTools.selectionSet({ selectionStart: origSelection.selectionStart, selectionLength: origSelection.selectionLength }); alert("Sorted") }; };
Thanks for this - I've added it to my session prep deck!
samuel henriques @samuel_henriques
Cool, thank you, really happy it's useful!
- In reply toChris_Shaw⬆:HHendrick Valera @Hendrick_Valera
Thank you @samuel_henriques and @Chris_Shaw !
I tried to run the script but it didn't work for me... For example, I made a selection of 4 tracks with sound starting at different parts and when I run the script it just switches the position of the tracks disregarding the audio information... Something like this
Track 1
Track 2
Track 3
Track 4run script
Track 4
Track 3
Track 2
Track 1Maybe I'm missing something?
samuel henriques @samuel_henriques
It should order by the start of clips in the timeline.
re-reading your first post, could it be that the clip start is not relevant, but instead you want the order of the first transient inside a clip selection?
Witch seams exactly what you wrote, my apologies.
- HHendrick Valera @Hendrick_Valera
Exaaactly that's what I meant!
However, if you think something like this isn't possible, perhaps I could use this script in combination with the "strip silence" macro which would ultimately get to the same result.
What do you think?
samuel henriques @samuel_henriques
I'm going to try and let you know.
And would you like this from the start of the clip or within your initial selection?
- In reply tosamuel_henriques⬆:
samuel henriques @samuel_henriques
could you make a screen recording with you doing the actions to what you expect?
- HHendrick Valera @Hendrick_Valera
I'm going to record a short video explaining what I mean in a few minutes! Thank you for your help Samuel!!
- In reply tosamuel_henriques⬆:HHendrick Valera @Hendrick_Valera
Here you go!
https://drive.google.com/file/d/1zpYAL3v_mIrdEDsa_9nheQr_qmnJ4X8t/view?usp=sharing
Also, I just tried running your script after applying "strip silence" and it works flawlessly! Although I see it works the opposite of how I organize tracks. However I assume it's not hard to make it work in reverse right?
thank you!
samuel henriques @samuel_henriques
cool, thank you for the video.
to change the order, I left instructions on the script, in this comment:
/// Sort array of objects by property. ? 1:-1 ascending / ? -1:1 descending const tracksToMove = trackList.sort((a, b) => (a.startTime > b.startTime) ? -1 : 1).map(track => track.trackName)
So you need to change the part
? -1 : 1
with? 1:-1
, the minus symbol needs to move from the first 1 to the second.Try this and let me know.
I'm trying something with the tab to transient and hope to post it in a bit.
samuel henriques @samuel_henriques
Here you go, this seamed to fast for me, I might be missing something! 😂😂
Let me know how it goes.
function moveTracksToTop(selectedTracks, trackNames) { // Safety deselect all sf.ui.proTools.trackDeselectAll() // Get possition of first track let firstTrackPosition = sf.ui.proTools.trackGetByName({ name: selectedTracks[0] }).track.frame // Safety deselect all sf.ui.proTools.trackDeselectAll() for (let i = 0; i < trackNames.length; i++) { sf.ui.proTools.trackGetByName({ name: trackNames[i] }).track.trackScrollToView() const elementPosition = sf.ui.proTools.trackGetByName({ name: trackNames[i] }).track.frame sf.mouse.simulateDrag({ startPosition: { "x": elementPosition.x + 20, "y": elementPosition.y + 10 }, endPosition: { "x": elementPosition.x + 20, "y": firstTrackPosition.y }, }); sf.ui.proTools.invalidate() } } function getTrackNameTransientTime(selectedTracks) { let startTime let trackList = [] sf.ui.proTools.menuClick({ menuPath: ["Options", "Tab to Transient"], targetValue: "Enable" }) for (let i = 0; i < selectedTracks.length; i++) { sf.ui.proTools.trackSelectByName({ names: [selectedTracks[i]] }) sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.keyboard.press({ keys: "alt+tab" }); startTime = sf.ui.proTools.selectionGetInSamples().selectionStart trackList[i] = { trackName: selectedTracks[i], startTime: +startTime } } return trackList } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate() const selectedTracks = sf.ui.proTools.selectedTrackNames const trackList = getTrackNameTransientTime(selectedTracks) // /// Sort array of objects by property. ? 1:-1 ascending / ? -1:1 descending const tracksToMove = trackList.sort((a, b) => (a.startTime > b.startTime) ? 1 : -1).map(track => track.trackName) moveTracksToTop(selectedTracks, tracksToMove) sf.ui.proTools.trackSelectByName({ names: selectedTracks }) if (sf.ui.proTools.selectedTrackNames.join(",") != tracksToMove.reverse().toString()) { main() } else { alert("Sorted!") } } main()
- HHendrick Valera @Hendrick_Valera
Ooohh I missed that part in the script! I will try it.
For now, your new script works very well!! Thank you so much!!!
For some reason, it missed the spot on a few tracks, why do you think it did? Check out the pic!
samuel henriques @samuel_henriques
is this with the latest script?
It should oder the other way round, the sam way you made on the video. I had changed the 1:-1 thing on this version.- HHendrick Valera @Hendrick_Valera
Yes, this is with the latest script!
- In reply tosamuel_henriques⬆:
samuel henriques @samuel_henriques
Another thing, It should try again if the order the script initially calculated isn't the same as the final order,
so wait for the alert in the end.If it keeps failing, make a video so I can see it and try to figure it out.
samuel henriques @samuel_henriques
And another thing, this will be very hard to do if the tracks are not visible in the edit window. Not saying it's impossible though.
- In reply tosamuel_henriques⬆:HHendrick Valera @Hendrick_Valera
Here's a video running both scripts!
and yes, I'm always making sure all the tracks are visible in the edit window!
https://drive.google.com/file/d/1FYKafJuqzTbWS1dKZ_IThHsgSgWoYvxY/view?usp=sharing
samuel henriques @samuel_henriques
Thank you. It's ordering by the end time of the clips, instead of the transient. The alt+tab is moving to the first transient ignoring the start of clip, on my machine, but on yours it selecting the end of the clip.
Let me try to figure this.
- In reply toHendrick_Valera⬆:
samuel henriques @samuel_henriques
Could you double check is you select all on the failed tracks and the press alt+tab, if pro tools detects the correct transient?
- HHendrick Valera @Hendrick_Valera
Yes PT detects the correct transient!
Although I think there's a misunderstanding! What I think the script is doing is going to the end of the clip and by doing alt+tab it selects the first transient it picks up from the end of such clip.
What I'm looking to do is sort it by transient information from the beginning to the first transient, instead of from the end of the clip to the first transient it picks up from the end. Does that make sense?
So the script is working perfectly, it's just doing it differently from what I had intended!
- In reply tosamuel_henriques⬆:HHendrick Valera @Hendrick_Valera
I got it!!
All I had to do was replace "alt+tab" for "tab" in the script and it does it just how I wanna!
Thank you sooooo much Samuel!!
samuel henriques @samuel_henriques
Cool. My test session had one clip with audio too close to the start (less than a frame) and the only way I could make it select the start was with alt+tab. But if I place it further away from the start, just Tap will work for all tracks.
Excellent its working for you.
- In reply toChris_Shaw⬆:DDave Weingarten @Dave_Weingarten
@samuel_henriques Would it be possible to drag the tracks around from the TRACKS menu on the left hand side of the screen? That way, I imagine you could reorder more tracks in one go. I'm hitting a limit with how many tracks I can do at once as it stands now. Thanks again for your help!! This is a big time game changer for my session setup workflow.