I have a list of colors someone gives me, for instance:
Track 1 - RED
Track 2 - BLUE
Track 3 - GREEN
And i haven't been able to come up with a good script to select each track, change the color, and move on to the next track.
I can get SoundFlow to read the list, like a JSON file, but i can't make it actually change the colors with any sort of rhyme or reason. In some cases i've gotten it to change ALL tracks to one color, or some random one to purple.
I thought this would be simple but maybe it's much more complex than i'm giving it credit for? Thanks in advance for any insight!
- KIn reply toKenneth_Vasko⬆:Kenneth Vasko @Kenneth_Vasko
const exportFile = '/Users/Shared/SessionSync/latest_export.json'; try { const data = sf.file.readJson({ path: exportFile }).json; if (data && data.tracks) { // Rename first (this works) const selectedNames = Array.from(sf.ui.proTools.selectedTrackNames); selectedNames.forEach((oldName, index) => { if (index < data.tracks.length) { sf.app.proTools.renameTrack({ oldName: oldName, newName: data.tracks[index].name }); } }); // Apply colors one by one setTimeout(() => { // Try alternative activation methods try { // Method 1: Use app bundle ID sf.ui.app('com.avid.ProTools').appActivateMainWindow(); } catch (e) { // Method 2: Use menu click to ensure focus sf.ui.proTools.menuClick({ menuPath: ['Window', 'Edit'] }); } // Add wait for activation sf.wait({ intervalMs: 200 }); // Process each track sequentially let currentIndex = 0; function processNextTrack() { if (currentIndex < data.tracks.length) { const track = data.tracks[currentIndex]; if (track.colorParams) { // Select the track sf.ui.proTools.trackSelectByName({ names: [track.name] }); // Wait before applying color sf.wait({ intervalMs: 100 }); // Apply color sf.ui.proTools.colorsSelect({ colorBrightness: track.colorParams.colorBrightness, colorNumber: track.colorParams.colorNumber }); // Move to next track currentIndex++; setTimeout(processNextTrack, 300); } else { // Skip tracks without color currentIndex++; processNextTrack(); } } } // Start processing processNextTrack(); }, 2000); } } catch (error) { // Error } '''
Chris Shaw @Chris_Shaw2025-07-24 15:20:52.266ZIt would be much easier to fix / refactor your script if you could provide an example of the
/Users/Shared/SessionSync/latest_export.jsonfile or thedata.tracksobject.
Thanks!
In reply toKenneth_Vasko⬆:Matt Friedman @Matt_FriedmanThat is super over the top. You could just update your existing foreach loop at the top into this:
const selectedNames = Array.from(sf.ui.proTools.selectedTrackNames); selectedNames.forEach((oldName, index) => { if (index < data.tracks.length) { const newName = data.tracks[index].name; const colorBrightness = data.tracks[index].colorParams.colorBrightness; const colorNumber = data.tracks[index].colorParams.colorNumber; // Select the track sf.app.proTools.selectTracksByName({ selectionMode: "Replace", trackNames: [oldName] }) // Rename the track sf.app.proTools.renameTrack({ oldName, newName, }); // Wait for name to complete (may not be needed) sf.waitFor({ callback: () => sf.ui.proTools.selectedTrackNames[0] === newName, timeout: 2000 }) // Change track color sf.ui.proTools.colorsSelect({ colorBrightness, colorNumber, }); // Wait for color to complete (may not be needed) sf.ui.proTools.colorPaletteWindow.elementWaitFor({waitForNoElement: true}) } });- KIn reply toKenneth_Vasko⬆:Kenneth Vasko @Kenneth_Vasko
For anyone else looking, here's a version that works pretty consistently! Thanks all for your contribution/insight.
if (data && data.tracks) {
// Ensure Pro Tools has focus
sf.ui.proTools.appActivateMainWindow();
sf.wait({ intervalMs: 2000 });// FOOLPROOF SELECTION: Simplified approach function selectAllVisibleTracks() { // First deselect all sf.ui.proTools.trackDeselectAll(); sf.wait({ intervalMs: 300 }); // Get all visible track headers const visibleTracks = sf.ui.proTools.visibleTrackHeaders; if (visibleTracks && visibleTracks.length > 0) { // Option+click on the first visible track to select all visibleTracks[0].titleButton.mouseClickElement({ isOption: true }); } } // Select all tracks selectAllVisibleTracks(); sf.wait({ intervalMs: 1000 }); // Now get the names of ALL selected tracks const selectedNames = Array.from(sf.ui.proTools.selectedTrackNames); // Process each track one by one selectedNames.forEach((oldName, index) => { if (index < data.tracks.length) { const track = data.tracks[index]; // Skip if no color parameters if (!track.colorParams) return; // Select the track by its current name sf.app.proTools.selectTracksByName({ selectionMode: "Replace", trackNames: [oldName] }); sf.wait({ intervalMs: 200 }); // Rename if needed if (oldName !== track.name) { sf.app.proTools.renameTrack({ oldName: oldName, newName: track.name }); sf.wait({ intervalMs: 300 }); } // Apply color sf.ui.proTools.colorsSelect({ colorBrightness: track.colorParams.colorBrightness, colorNumber: track.colorParams.colorNumber }); sf.wait({ intervalMs: 200 }); } }); // Select all tracks at the end to show the result selectAllVisibleTracks();}