Hey everyone,
I've been using this script that helps me sort the order of tracks based on which one has transient information first.
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 + 15 },
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: "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()
Before triggering, however, I find myself changing the track size from Medium to Mini and then back to Medium after it's done sorting. So I'd like to add these actions to the script.
Once I have a track selection, the order of action would be:
- Change track size from X to Mini
- Perform the sorting
- Change the track size from Mini to X
I saw that Andrew Scheps has a package called "Screen Layout Helper Functions" and this could possibly help me in the portion of creating and recalling a snapshot of the original track sizes but I don't know how to connect all these pieces together.
I would highly appreciate the help on this!!
@Kitch this is what we briefly talked about today!
PS.: These are some posts I've found in the forum that could also help in finding pieces of this puzzle
- samuel henriques @samuel_henriques
Hello Hendrick,
try this
/** * @param {any[]} selectedTracks * @param {string | any[]} trackNames */ function moveTracksToTop(selectedTracks, trackNames) { // Safety deselect all sf.ui.proTools.trackDeselectAll() // Get position 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() } } /** * @param {string | any[]} selectedTracks */ 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.trackDeselectAll() sf.ui.proTools.trackSelectByName({ names: [selectedTracks[i]] }) sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.keyboard.press({ keys: "tab" }); startTime = sf.ui.proTools.selectionGetInSamples().selectionStart trackList[i] = { trackName: selectedTracks[i], startTime: +startTime } } return trackList } /** * @param {number} h */ function getCurrentTrackHeight(h) { let originalTrackHeight; switch (true) { case (h <= 16): originalTrackHeight = 'micro'; break; case (h === 23): originalTrackHeight = 'mini'; break; case (h >= 43 && h <= 61): originalTrackHeight = 'small'; break; case (h >= 79 && h <= 116): originalTrackHeight = 'medium'; break; case (h >= 135 && h <= 235): originalTrackHeight = 'large'; break; case (h >= 257 && h <= 420): originalTrackHeight = 'jumbo'; break; case (h > 440): originalTrackHeight = 'extreme'; break; }; return originalTrackHeight }; /** * @param {string} size */ function setTrackSize(size) { const selectedTrackNames = sf.ui.proTools.selectedTrackNames const firstSelected = sf.ui.proTools.trackGetByName({ name: selectedTrackNames[0] }).track firstSelected.trackScrollToView() sf.ui.proTools.trackSelectByName({ names: selectedTrackNames }) const f = sf.ui.proTools.selectedTrack.frame if (getCurrentTrackHeight(f.h) != size) { const popupMenu = sf.ui.proTools.selectedTrack.popupMenuOpenFromElement({ relativePosition: { x: f.w - 10, y: 5 }, isOption: true, isShift: true, }).popupMenu; popupMenu.menuClickPopupMenu({ menuPath: [size] }); } } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate() const originalTrackHeight = getCurrentTrackHeight(sf.ui.proTools.selectedTrack.frame.h) setTrackSize("micro") 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) try { moveTracksToTop(selectedTracks, tracksToMove) sf.ui.proTools.trackSelectByName({ names: selectedTracks }) // Check if order is correct, if not, repeat. if (sf.ui.proTools.selectedTrackNames.join(",") != tracksToMove.reverse().toString()) { main() } } catch (err) { log("An error occurred trying to sort tracks.") } setTrackSize(originalTrackHeight) alert("Sorted!") } main()
- HHendrick Valera @Hendrick_Valera
This is perfect!! Thank you so much Samuel!! you are the best :)
Since the resulting size before sorting is now micro I changed the code a little because the place where it clicks to drag happens to open a menu, so I just moved the X-axis a little to the right so it clicks on the track name when dragging.
/** * @param {any[]} selectedTracks * @param {string | any[]} trackNames */ function moveTracksToTop(selectedTracks, trackNames) { // Safety deselect all sf.ui.proTools.trackDeselectAll() // Get position 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 + 40, "y": elementPosition.y + 10 }, endPosition: { "x": elementPosition.x + 40, "y": firstTrackPosition.y }, }); sf.ui.proTools.invalidate() } } /** * @param {string | any[]} selectedTracks */ 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.trackDeselectAll() sf.ui.proTools.trackSelectByName({ names: [selectedTracks[i]] }) sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.keyboard.press({ keys: "tab" }); startTime = sf.ui.proTools.selectionGetInSamples().selectionStart trackList[i] = { trackName: selectedTracks[i], startTime: +startTime } } return trackList } /** * @param {number} h */ function getCurrentTrackHeight(h) { let originalTrackHeight; switch (true) { case (h <= 16): originalTrackHeight = 'micro'; break; case (h === 23): originalTrackHeight = 'mini'; break; case (h >= 43 && h <= 61): originalTrackHeight = 'small'; break; case (h >= 79 && h <= 116): originalTrackHeight = 'medium'; break; case (h >= 135 && h <= 235): originalTrackHeight = 'large'; break; case (h >= 257 && h <= 420): originalTrackHeight = 'jumbo'; break; case (h > 440): originalTrackHeight = 'extreme'; break; }; return originalTrackHeight }; /** * @param {string} size */ function setTrackSize(size) { const selectedTrackNames = sf.ui.proTools.selectedTrackNames const firstSelected = sf.ui.proTools.trackGetByName({ name: selectedTrackNames[0] }).track firstSelected.trackScrollToView() sf.ui.proTools.trackSelectByName({ names: selectedTrackNames }) const f = sf.ui.proTools.selectedTrack.frame if (getCurrentTrackHeight(f.h) != size) { const popupMenu = sf.ui.proTools.selectedTrack.popupMenuOpenFromElement({ relativePosition: { x: f.w - 10, y: 5 }, isOption: true, isShift: true, }).popupMenu; popupMenu.menuClickPopupMenu({ menuPath: [size] }); } } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate() const originalTrackHeight = getCurrentTrackHeight(sf.ui.proTools.selectedTrack.frame.h) setTrackSize("micro") 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) try { moveTracksToTop(selectedTracks, tracksToMove) sf.ui.proTools.trackSelectByName({ names: selectedTracks }) // Check if order is correct, if not, repeat. if (sf.ui.proTools.selectedTrackNames.join(",") != tracksToMove.reverse().toString()) { main() } } catch (err) { log("An error occurred trying to sort tracks.") } setTrackSize(originalTrackHeight) alert("Sorted!") } main()
Kitch Membery @Kitch2021-12-03 21:46:28.456Z
@Hendrick_Valera & @samuel_henriques,
I'd love a video of this script in action for social media if you have some time to make one. (If so email me a link at support@SoundFlow.org). No worries if you are too busy though :-)
Cool workflow!
samuel henriques @samuel_henriques
@Hendrick_Valera if you could do it in a real session would be really cool.
- In reply toKitch⬆:HHendrick Valera @Hendrick_Valera
I don't have a deck to record with my phone so I just used the phone app and screen recorded the action! Here it is @Kitch @samuel_henriques
https://drive.google.com/file/d/12tuuAz2WTtJjB3xwkoGItVQUR1YKjPzj/view?usp=sharing
samuel henriques @samuel_henriques
I managed to do one as well.
I kept the track size just so its easier to see it workinghttps://drive.google.com/file/d/1OBX1nUfptRVN6msbs347ss3DvhT1_pub/view?usp=sharing
- In reply tosamuel_henriques⬆:
Kitch Membery @Kitch2021-12-03 21:40:23.283Z
Nice one @samuel_henriques!
- In reply toHendrick_Valera⬆:Chris Shaw @Chris_Shaw2021-12-08 19:49:10.794Z2021-12-08 23:34:23.037Z
LOVE THIS SCRIPT!
I made an addition to ask the user which order they'd prefer which then inverts the sort order with a -1 multiplier:
(change the default button to whatever you like)/** * @param {any[]} selectedTracks * @param {string | any[]} trackNames */ function moveTracksToTop(selectedTracks, trackNames) { // Safety deselect all sf.ui.proTools.trackDeselectAll() // Get position 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() } } /** * @param {string | any[]} selectedTracks */ 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.trackDeselectAll() sf.ui.proTools.trackSelectByName({ names: [selectedTracks[i]] }) sf.ui.proTools.menuClick({ menuPath: ["Edit", "Select All"] }); sf.keyboard.press({ keys: "tab" }); startTime = sf.ui.proTools.selectionGetInSamples().selectionStart trackList[i] = { trackName: selectedTracks[i], startTime: +startTime } } return trackList } /** * @param {number} h */ function getCurrentTrackHeight(h) { let originalTrackHeight; switch (true) { case (h <= 16): originalTrackHeight = 'micro'; break; case (h === 23): originalTrackHeight = 'mini'; break; case (h >= 43 && h <= 61): originalTrackHeight = 'small'; break; case (h >= 79 && h <= 116): originalTrackHeight = 'medium'; break; case (h >= 135 && h <= 235): originalTrackHeight = 'large'; break; case (h >= 257 && h <= 420): originalTrackHeight = 'jumbo'; break; case (h > 440): originalTrackHeight = 'extreme'; break; }; return originalTrackHeight }; /** * @param {string} size */ function setTrackSize(size) { const selectedTrackNames = sf.ui.proTools.selectedTrackNames const firstSelected = sf.ui.proTools.trackGetByName({ name: selectedTrackNames[0] }).track firstSelected.trackScrollToView() sf.ui.proTools.trackSelectByName({ names: selectedTrackNames }) const f = sf.ui.proTools.selectedTrack.frame if (getCurrentTrackHeight(f.h) != size) { const popupMenu = sf.ui.proTools.selectedTrack.popupMenuOpenFromElement({ relativePosition: { x: f.w - 10, y: 5 }, isOption: true, isShift: true, }).popupMenu; popupMenu.menuClickPopupMenu({ menuPath: [size] }); } } function main() { sf.ui.proTools.appActivateMainWindow(); sf.ui.proTools.invalidate() var sortAnswer = sf.interaction.displayDialog({ title: 'Select display order', prompt: "Where do want the first entrance to be?", buttons: ["Cancel", "Top", "Bottom"], defaultButton: "Top" }).button var sortInverter = (sortAnswer == "Top") ? -1 : 1; const originalTrackHeight = getCurrentTrackHeight(sf.ui.proTools.selectedTrack.frame.h) setTrackSize("micro") 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 * sortInverter : -1 * sortInverter).map(track => track.trackName) try { moveTracksToTop(selectedTracks, tracksToMove) sf.ui.proTools.trackSelectByName({ names: selectedTracks }) // Check if order is correct, if not, repeat. if (sf.ui.proTools.selectedTrackNames.join(",") != tracksToMove.reverse().toString()) { main() } } catch (err) { log("An error occurred trying to sort tracks.") } setTrackSize(originalTrackHeight) alert("Sorted!") } main()
- MIn reply toHendrick_Valera⬆:Matt Neveu @Matt_Neveu
I am having issues with line 115 not being able to execute. I think it might be something with that popup menu not being found any ideas o how to fix this Thanks so much!
Chris Shaw @Chris_Shaw2024-05-02 22:09:19.781Z
try inserting this at line 116:
anchor: "TopLeft",
Don't forget the comma at the end
- DIn reply toHendrick_Valera⬆:Dave Weingarten @Dave_Weingarten
@Chris_Shaw I can't get this to work for some reason. Also stuck at line 115 and tried the script you suggested at line 116. Maybe I'm dealing with too many tracks at once? Thank you!