Needing a script for "Open all inserts on Selected Track"
System Information
SoundFlow 4.2.5
OS: darwin 18.7.0
ProductName: Mac OS X
ProductVersion: 10.14.6
BuildVersion: 18G103
Steps to Reproduce
Expected Result
The same result as holding Shift while opening each insert which turns off the plug in's target mode
Actual Result
Workaround
No I have not. For now I have commands to open each insert slot individually.
Other Notes
This seems like something everybody would require as an add on to the existing scripts of opening inserts. I have searched the forum already for a workaround.
Links
User UID: 3bQltHdjljNOhJpGv5cktiTJW8h1
Feedback Key: sffeedback:3bQltHdjljNOhJpGv5cktiTJW8h1:-MYQ7l4PFLVbj32dk6iE
- Kitch Membery @Kitch2021-04-17 23:35:56.334Z
Hi @Jagori_Tanna,
Here is a script that @chrscheuer put together to "Open all plug-in windows on a selected track";
let track = sf.ui.proTools.selectedTrack; function getInsertWin(track, insertIndex) { const insertChars = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']; const insertChar = insertChars[insertIndex]; const trackName = track.normalizedTrackName; return sf.ui.proTools.windows.whoseTitle.startsWith('Plug-in:').filter(w => { if (w.popupButtons.whoseTitle.is('Track Selector').first.value.value !== trackName) return false; if (w.popupButtons.whoseTitle.is('Insert Position selector').first.value.value !== insertChar) return false; return true; })[0]; } for (let i = 0; i < 10; i++) { if (!track.insertButtons[i].invalidate().exists) continue; if (track.insertButtons[i].value.value === "unassigned") continue; let pluginWin = getInsertWin(track, i); if (!pluginWin) { track.insertButtons[i].elementClick(); while (true) { pluginWin = getInsertWin(track, i); if (pluginWin) break; sf.wait({ intervalMs: 100 }); } //Disable target mode on newly opened window pluginWin.buttons.whoseTitle.is('Target button').first.elementClick(); } }
Rock on!
- TTristan Hoogland @Tristan
Hey Kitch!
This is the closest script I've found to what I might be needing. I'm trying to get soundflow to, after selecting a bunch of tracks, open just a single plugin. Ideally the first within the chain so long as it contains the term "UAD".
Don't suppose you have a quick tip for this? I've been scratching my head all day on it!
Kitch Membery @Kitch2022-11-17 00:34:07.745Z
Try this @Tristan_Hoogland
const pluginSearchString = "UAD" const insertButtonInfo = sf.ui.proTools.selectedTrack.insertButtons.map((btn, index) => ({ button: btn, value: btn.value.invalidate().value, insertSlotNumber: index + 1, })); const firstUadPluginSlotIndex = insertButtonInfo.find(btn => btn.value.includes(pluginSearchString)).insertSlotNumber; sf.ui.proTools.appActivateMainWindow(); if (firstUadPluginSlotIndex !== undefined) { sf.ui.proTools.selectedTrack.trackInsertToggleShow({ insertNumber: firstUadPluginSlotIndex, }); }
- TTristan Hoogland @Tristan
hell yea. Thanks K!!!
- In reply toKitch⬆:TTristan Hoogland @Tristan
I'll be sharing the script soon, mate for help on those things we talked about earlier. I definitely am nearing that point of needing your help! Plus it'd be good to share it back (and many others I've got in the pipeline that are a bit of a mess, still).
- In reply toKitch⬆:TTristan Hoogland @Tristan
Hey Kitch. What would be the best way to make
pluginSearchString = "UAD"
into a searchable array? I feel like I should be considering some kind of loop function. Right now this is what I want to do:const pluginSearchString = ['UAD UA 1176LN Rev E", "UAD UA 1176 Rev A", "UAD UA 1176AE"] //etc etc const insertButtonInfo = sf.ui.proTools.selectedTrack.insertButtons.map((btn, index) => ({ button: btn, value: btn.value.invalidate().value, insertSlotNumber: index + 1, })); const firstUadPluginSlotIndex = insertButtonInfo.find(btn => btn.value.includes(pluginSearchString)).insertSlotNumber; sf.ui.proTools.appActivateMainWindow(); if (firstUadPluginSlotIndex !== undefined) { sf.ui.proTools.selectedTrack.trackInsertToggleShow({ insertNumber: firstUadPluginSlotIndex, }); }
Currently when it gets to
btn.value.includes(pluginSearchString)).insertSlotNumber
pluginSearchString becomes invalid. I'm trying to work out the best way of searching that array. Any tips? I'm deep in javascript land in the meantime trying to solve my issue on my own I promise!Kitch Membery @Kitch2022-11-19 21:29:57.862Z
Because you are looking for the possibility of a match to "UAD" with the risk of not finding one, you could do something like this;
const pluginSearchString = "UAD" //Map info from insert slots const insertButtonInfo = sf.ui.proTools.selectedTrack.insertButtons.map((btn, index) => ({ button: btn, value: btn.value.invalidate().value, insertSlotNumber: index + 1, })); //Filter to get all insert slots whose name includes the pluginSearchString const matchingInsertSlots = insertButtonInfo.filter(btn => btn.value.includes(pluginSearchString)); sf.ui.proTools.appActivateMainWindow(); //Loop through the matchingInsertSlots matchingInsertSlots.forEach(insert => { sf.ui.proTools.selectedTrack.trackInsertToggleShow({ insertNumber: insert.insertSlotNumber, }); });
This script filters the plugin names for "UAD" and stores them in an array named
uadInsertSlots
. If the script can't find any matches, thefilter
method will return an empty array.The script will then loop through the
uadInsertSlots
using theforEach
method.Inside the forEach loop is where you can do all the fun stuff. :-)
- TTristan Hoogland @Tristan
Thanks K!
Playing with it now, I'm not entirely sure it's going to work as I was hoping. One bit of knowledge I've left in the realm of assumption is that there are only a handful of UAD and UADx compatible plugins right now. There are like ~100 UAD plugins and only ~15 UADx plugins. So I need to specify what those UADx plugins because otherwise it'll cycle through other UAD plugins that don't have a native companion. Does that make sense?
Kitch Membery @Kitch2022-11-19 22:22:54.567Z
Yes of course.
const uadXpluginLookup = [ { uadPluginName: "UAD UA 1176LN Rev E", uadXPluginName: "UADx UA 1176LN Rev E Compressor", }, { uadPluginName: "UAD UA 1176LN Rev A", uadXPluginName: "UADx UA 1176LN Rev A Compressor", }, ]; //Get an array of usable UAD plugin names const usablePluginNames = uadXpluginLookup.map(item => item.uadPluginName); //Map info from insert slots const insertButtonInfo = sf.ui.proTools.selectedTrack.insertButtons.map((btn, index) => ({ button: btn, value: btn.value.invalidate().value, insertSlotNumber: index + 1, })); //Filter to get all insert slots whose name includes any of the usablePluginNames const matchingInsertSlots = insertButtonInfo.filter(btn => usablePluginNames.some((name) => name === btn.value)); sf.ui.proTools.appActivateMainWindow(); //Loop through the matchingInsertSlots matchingInsertSlots.forEach(insert => { sf.ui.proTools.selectedTrack.trackInsertToggleShow({ insertNumber: insert.insertSlotNumber, }); //For demo purpose only sf.wait({ intervalMs: 1000 }); });
This uses the
some
method to get the matching plugins based on the lookup array. :-)Let me know if that makes sense.
- TTristan Hoogland @Tristan
PERFECT!
Kitch to the rescue once again. I'm not sure I've come across the
.some
function before. I thought something like the array thing would have been the way to go.By the way got it working very well otherwise - updated with use of percentages etc. Just throwing this in, tweaking it so it ignores inactive states and then will find an edge case session for it! ha.
Thanks man.
Kitch Membery @Kitch2022-11-19 22:51:32.073Z
Noice!
A couple of edge cases I can think of:
-
Make sure that insert slots a-e and f-j are open.
-
Make sure the track heights allow for all insert slots to be visible (Otherwise the script will fail.)
-
Ensure that the edit window is focused
-
Make sure that all plugin windows are closed at the start of the script.
Rock on!
- TTristan Hoogland @Tristan
Thanks man!
That's some great stuff to remember, particularly remembering to keep all insert slots visible (I always have them open so it gets me a few times on other systems!). I think the rest of it is accounted for, I'll send it over for your review soon.
While I'm cleaning it up, I'm utilizing
while (true)
for my convert function after this gold you've given here, however, while it's working great - currently it scans through all the plugins going from insert A through to J and then calls the 'convert to uadx' function on the last plugin (I guess because it's no longer found any UADx compatible plugins).Ideally once the script finds a plugin, it'd be good if it breaks and then moves to the 'convert uadx' function and then goes through again, so on and so forth - does that make sense? Currently it's working, just in reverse lol.
In essence it's effectively like running the soundflow
open insert by name
macro in a loop (it always finds and launches the first instance of any given plugin).Anyway, punching away. fun times.
Kitch Membery @Kitch2022-11-19 23:05:02.143Z
Ahh I see... You'll need to move all the actions that are performed to each of the matched plugins into the
forEach
loop otherwise it will only work on the last slot that opens.- TTristan Hoogland @Tristan
You know, I tried that for 15 mins and it turned out my internet dropped out so it kept running an old script!! Now working as expected. Thanks K!
Kitch Membery @Kitch2022-11-20 00:06:04.312Z
Awesome!!!
- TTristan Hoogland @Tristan
Hey @Kitch
I'm assuming this should be a pretty easy one, but I'm just not sure how to interject it into your script snippet here.How would I go about ignoring inserts that are inactive, but have "UAD" in them? In some edge cases I'll have something like a track that has 2 UAD inserts active, but 1 UAD insert inactive, and when repeating the open/copy/paste process it'll still try to do it to the inactive plugins and in turn fail.
Getting the value/inactive state via the insertSelector is easy, just thinking of how to exclude them during the cycling process.
Thanks!
Kitch Membery @Kitch2022-11-29 04:36:25.113Z
Will circle back to this tomorrow, legend.
Rock on!
- TTristan Hoogland @Tristan
make sure you're wearing the cape this time, hero!
Kitch Membery @Kitch2022-11-29 20:45:56.841Z
Well hi there @Tristan_Hoogland,
function getInsertsInfo() { const insertInfo = Array(10).fill(0).map((_, index) => { const track = sf.ui.proTools.selectedTrack; const insertButton = track.invalidate().insertButtons[index]; const insertButtonValue = insertButton.value.invalidate().value; const insertSelectorButton = track.invalidate().insertSelectorButtons[index] const insertSelectorButtonValue = insertSelectorButton.value.invalidate().value; return { insertButton, insertButtonValue, insertSelectorButton, insertSelectorButtonValue, insertIndex: index, pluginName: insertButtonValue, //isBypassed: insertSelectorButtonValue.includes('bypassed'), isActive: !insertSelectorButtonValue.includes('inactive'), }; }); return insertInfo; } const uadXpluginLookup = [ { uadPluginName: "FabFilter Pro-C 2", uadXPluginName: "UADx UA 1176LN Rev E Compressor", }, { uadPluginName: "UAD UA 1176LN Rev A", uadXPluginName: "UADx UA 1176LN Rev A Compressor", }, ]; //Get an array of usable UAD plugin names const usablePluginNames = uadXpluginLookup.map(item => item.uadPluginName); const insertsInfo = getInsertsInfo(); //Filter to get all insert slots whose name includes any of the usablePluginNames const matchingInsertSlots = insertsInfo.filter(btn => { return usablePluginNames.some((name) => name === btn.pluginName) && btn.isActive === true; }); log(matchingInsertSlots);
Something like this will filter out the inactive inserts. :-)
- TTristan Hoogland @Tristan
@Kitch this one is going into the save-for-later folder. Amazing.
The only thing I needed to amend on my end was to increment the insertIndex with a + 1 on the end later in the matchingInserts section ;)
function getInsertsInfo() { const insertInfo = Array(10).fill(0).map((_, index) => { const track = sf.ui.proTools.selectedTrack; const insertButton = track.invalidate().insertButtons[index]; const insertButtonValue = insertButton.value.invalidate().value; const insertSelectorButton = track.invalidate().insertSelectorButtons[index] const insertSelectorButtonValue = insertSelectorButton.value.invalidate().value; return { insertButton, insertButtonValue, insertSelectorButton, insertSelectorButtonValue, insertIndex: index, pluginName: insertButtonValue, //isBypassed: insertSelectorButtonValue.includes('bypassed'), isActive: !insertSelectorButtonValue.includes('inactive'), }; }); return insertInfo; } const uadXpluginLookup = [ { uadPluginName: "FabFilter Pro-C 2", uadXPluginName: "UADx UA 1176LN Rev E Compressor", }, { uadPluginName: "UAD UA 1176LN Rev A", uadXPluginName: "UADx UA 1176LN Rev A Compressor", }, ]; //Get an array of usable UAD plugin names const usablePluginNames = uadXpluginLookup.map(item => item.uadPluginName); const insertsInfo = getInsertsInfo(); //Filter to get all insert slots whose name includes any of the usablePluginNames const matchingInsertSlots = insertsInfo.filter(btn => { return usablePluginNames.some((name) => name === btn.pluginName) && btn.isActive === true; }); sf.ui.proTools.appActivateMainWindow(); //Loop through the matchingInsertSlots matchingInsertSlots.forEach(insert => { sf.ui.proTools.selectedTrack.trackInsertToggleShow({ insertNumber: insert.insertIndex + 1, }) }); }
Just about ready!
Kitch Membery @Kitch2022-11-29 23:55:42.782Z
Awesome! :-)
-