I’m trying to create a Stream Deck button (or keyboard shortcut) for adding a certain plug in into the next free insert slot on selected track. I’m trying this script:
function getFirstFreeInsertIndex() {
var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons;
for (var i = 0; i < 10; i++)
if (btns[i].value.invalidate().value === "unassigned") return i;
return -1;
}
sf.ui.proTools.selectedTrack.trackInsertOrSendSearch({
insertOrSend: 'Insert',
pluginNumber: getFirstFreeInsertIndex() + 1,
});
sf.keyboard.type({
text: "D-Verb",
});
sf.keyboard.press({
keys: "return",
});
… but the text is not written in the search field. Any ideas?
Still new to this. Trying to learn… :)
thnx
Linked from:
- Christian Scheuer @chrscheuer2020-03-17 10:29:18.177Z
Hi @Muzzle1996.
Please see this thread:
https://forum.soundflow.org/-744/insert-plugin-in-first-available-empty-slot- RRobert Sörling @robertsorling
Ok. that works! Thanks.
How ever, still trying to figure out how to paste a text via a script or macro in a search field pop up like this:
Would be great in many situations.
Thanks
- RRobert Sörling @robertsorling
Ok, I solved this by simply making Multi Actions within the Stream Deck App.
Christian Scheuer @chrscheuer2020-03-24 23:46:16.147Z
Hi @Muzzle1996.
You don't have to use the popup at all if you use the actions that I linked to.
The popup is only needed if you want the user to input text.
If you want to select an insert completely without the popup, no need to first show it and then simulate the keyboard.You were using the "search" version of the script which opens the popup - but instead use the "select" version.
This directly gives you the D-Verb insert - no popup needed:
function getFirstFreeInsertIndex() { var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons; for (var i = 0; i < 10; i++) if (btns[i].value.invalidate().value === "unassigned") return i; return -1; } sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({ insertOrSend: "Insert", pluginNumber: getFirstFreeInsertIndex() + 1, pluginSelector: items => items.filter(item => item.path[0] === "plug-in" && item.path.slice(-1)[0].indexOf("D-Verb") === 0)[0], });
- RRobert Sörling @robertsorling
Ok, thanks. Mh, what I'm trying to do is to make shortcuts in Stream Deck for my favorite plug ins to open in the next free insert slot. I tried the linked script but the problem is that, and correct me if I'm wrong, if I use the script you posted I will have to make two D-verb shortcuts, one for stereo tracks and one for mono tracks? If I could paste the text "D-verb" in the popup instead I can do it on the fly without thinking about wether the track is mono or stereo. At this point I am doing this from within the Stream Deck by using a Multi Action. This works just fine but of course it would be better to do it all from within the soundflow app, I guess. A sidenote is also that it's very fast to set up a series of plug-in shortcuts by just copying the Multi Action within the Stream Deck app, pasting it and just changing the "search for plug-in text" in the Multi Action to whatever the new shortcut might be. Hope I'm making sense.
Thank you for the fantastic support and a great product!
Christian Scheuer @chrscheuer2020-03-25 00:34:42.013Z2020-03-25 00:47:57.123Z
Please check the script I quoted above - it doesn't require you to specify D-Verb more than once. This script above uses new features to do exactly this that came with 3.5 which was released a few days ago. Download 3.5 from here: https://soundflow.org/download
You could even change it like this, so it's easy to swap out the name of the plugin (first line):
const pluginName = 'D-Verb'; function getFirstFreeInsertIndex() { var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons; for (var i = 0; i < 10; i++) if (btns[i].value.invalidate().value === "unassigned") return i; return -1; } sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({ insertOrSend: "Insert", pluginNumber: getFirstFreeInsertIndex() + 1, pluginSelector: items => items.filter(item => item.path[0] === "plug-in" && item.path.slice(-1)[0].indexOf(pluginName) === 0)[0], });
We don't recommend using the Stream Deck designer for your decks at all - we highly recommend that you design your Decks inside SoundFlow via the "+ New" -> "Deck" feature.
Please read more here:
https://soundflow.org/docs/how-to/stream-deck/setting-upAndrew Scheps @Andrew_Scheps
Hi Christian. I still can't get the new type of code to work in this script. My script is almost identical to the one above, I just use an array to prioritise my insert slots (I prefer slot C if they're all open).
sf.ui.proTools.appActivateMainWindow(); function getFirstFreeInsertIndex() { var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons; let insertArray = [2, 3, 4, 5, 6, 7, 8, 9, 1, 0]; for (let i = 0; i < insertArray.length; i++) if (btns[insertArray[i]].value.invalidate().value === "unassigned") return (insertArray[i]); throw 0; } sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({ insertOrSend: "Insert", pluginNumber: getFirstFreeInsertIndex() + 1, pluginSelector: items => items.filter(item => item.path[0] === "plug-in" && item.path.slice(-1)[0].indexOf("Scheps Omni Channel") === 0)[0], });
When I run it I get:
25.03.2020 18:37:52.38 <info> [Backend]: Error in line 11: Could not select plugin menu item: '<selector>' (TrackSelectInsertOrSendAction) No menu item was returned by menuSelector callback (PopupMenuSelectAction)
This version still runs fine:
function clickPopupMenu(popupMenu, paths) { for (var i = 0; i < paths.length; i++) { var path = paths[i]; if (popupMenu.menuClickPopupMenu({ menuPath: path, onError: 'Continue' }).success) { return; } } throw "None of the provided paths were present in this popup menu"; } function addSchepsOC() { var popupMenu = sf.ui.proTools.selectedTrack.trackInsertOrSendOpenMenu({ insertOrSend: "Insert", pluginNumber: getFirstFreeInsertIndex() + 1, }).popupMenu; clickPopupMenu(popupMenu, [ ['plug-in', 'EQ', 'Scheps Omni Channel (mono)'], ['multichannel plug-in', 'EQ', 'Scheps Omni Channel (stereo)'] ]); }
Any thoughts?
Christian Scheuer @chrscheuer2020-03-26 01:51:19.021Z
Try this:
The script above would fail for stereo tracks since I had an error in the selector.sf.ui.proTools.appActivateMainWindow(); function getFirstFreeInsertIndex() { var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons; let insertArray = [2, 3, 4, 5, 6, 7, 8, 9, 1, 0]; for (let i = 0; i < insertArray.length; i++) if (btns[insertArray[i]].value.invalidate().value === "unassigned") return (insertArray[i]); throw 0; } sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({ insertOrSend: "Insert", pluginNumber: getFirstFreeInsertIndex() + 1, pluginSelector: items => items.filter(item => item.path[0].indexOf("plug-in") >= 0 && item.path.slice(-1)[0].indexOf("Scheps Omni Channel") === 0)[0], });
- RRobert Sörling @robertsorling
Great, now this works! Thnks
- In reply tochrscheuer⬆:
Andrew Scheps @Andrew_Scheps
Hi Christian. This works but is very slow. There is about a 5 second stall while it searches the menu. I wonder if this needs caching like the other script we were working on.
Christian Scheuer @chrscheuer2020-03-26 11:07:53.252Z
Hi Andrew
Since you have the large menu, you should use the other version that I wrote for you:
https://forum.soundflow.org/-1693#post-8There should be no need for you to move to the selector based approach, since it works by fetching the entire contents which in your case is slow due to the huge number of plugins.
Andrew Scheps @Andrew_Scheps
Great, that's what I thought, thanks.
- JJordon Popp @Jordon_Popp
Sorry to hijack this, but is there a way to get this to function across all selected tracks?
Cheers,
JordonAndrew Scheps @Andrew_Scheps
You could easily use
sf.ui.protools.selectedTracks
and put the rest inside a loop, but you would need some pretty robust error checking which is why I kept it to one track.
- JJordon Popp @Jordon_Popp
Thanks, Andrew! I'm going to tinker with this over the weekend. Rather new to coding, and it's all a bit overwhelming, haha.
Cheers!
- In reply toAndrew_Scheps⬆:Nnick krill @nick_krill
Hi Andrew,
I might have found a tip to minimize the wait time while this script looks for plug-ins. I've found that it helps if I mark the plug-ins that I want to use in the script as "Favorites" in Pro Tools by Command+Clicking the name of the plugin in the plug in list. This way the script seems to grab the plug in from that little "Favorites" section at the top of the plug in menu, and seems to insert it prettty quickly. This might help avoid having to hunt through a large plugin menus.
-nick
- RIn reply torobertsorling⬆:Robert Sörling @robertsorling
"We don't recommend using the Stream Deck designer for your decks at all - we highly recommend that you design your Decks inside SoundFlow via the "+ New" -> "Deck" feature."
Ok! "I realise that. Now" (Frank Drebin)
- AIn reply torobertsorling⬆:Alan Saucedo @Alan_Saucedo
Hello!
This is my first "coding" shortcut, i'm using the FabFilter Pro-Q 3 plugin like this:
preformatted text
sf.ui.proTools.appActivateMainWindow();function getFirstFreeInsertIndex() {
var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons;
for (let i = 0; i < 10; i++)
if (btns[i].value.invalidate().value === "unassigned") return i;
throw 0;
}sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({
insertOrSend: "Insert",
pluginNumber: getFirstFreeInsertIndex() + 1,
pluginSelector: items => items.filter(item => item.path[0].indexOf("plug-in") >= 0 && item.path.slice(-1)[0].indexOf("FabFilter Pro-Q 3 ") === 0)[0],
});But i'm having troubles when running in the "Mix Window". Any advices?
Chris Shaw @Chris_Shaw2020-06-19 22:05:52.512Z2020-06-20 04:18:17.347Z
Alan,
SF is designed to primarily work in the Edit window. The simple workaround would be to create an if/else decision around the code you want to execute: if the mix window is active switch to edit window, execute your script and switch back to the Mix window - Else just execute the script.Like this:
sf.ui.proTools.appActivateMainWindow(); // First, let's get the selected track name var originallySelectedTrackNames = sf.ui.proTools.selectedTrackNames; // This next function makes sure the selected track is visible in the Edit Window function ensureFirstSelectedTrackIsVisible() { sf.ui.proTools.trackGetByName({ name: originallySelectedTrackNames[0], makeVisible: true }).track.trackScrollToView(); } // Next we wrap your whole script into a single function function insertEqInFirstFreeSlot() { function getFirstFreeInsertIndex() { var btns = sf.ui.proTools.selectedTrack.invalidate().insertButtons; for (let i = 0; i < 10; i++) if (btns[i].value.invalidate().value === "unassigned") return i; throw 0; } sf.ui.proTools.selectedTrack.trackInsertOrSendSelect({ insertOrSend: "Insert", pluginNumber: getFirstFreeInsertIndex() + 1, pluginSelector: items => items.filter(item => item.path[0].indexOf("plug-in") >= 0 && item.path.slice(-1)[0].indexOf("FabFilter Pro-Q 3 ") === 0)[0], }); } // Here we create a new function that executes everything function main() { //Check if Mix window is visible. If not switch to Edit Window and execute your script, then switch back if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"], targetValue: "Enable", }); ensureFirstSelectedTrackIsVisible(); insertEqInFirstFreeSlot() // your script sf.ui.proTools.menuClick({ menuPath: ["Window", "Mix"], targetValue: "Enable", }); } /// Else if the Edit window is the main window, just execute the script else { ensureFirstSelectedTrackIsVisible(); insertEqInFirstFreeSlot(); sf.ui.proTools.trackSelectByName({ names: originallySelectedTrackNames, deselectOthers: true }); } } // Now execute main main();
Now your script will work in both windows.
Todd Burke @Todd_Burke8
Woo hoo! So happy to have found this. Thanks fellas.
Chris Shaw @Chris_Shaw2020-07-04 18:45:35.241Z
Yep
You just have to check which window is the main one, switch to the edit window and then back again. It’s clumsy but it works.Todd Burke @Todd_Burke8
Now if I can just find an “add track to existing group” script I might get back to this mix :)
Chris Shaw @Chris_Shaw2020-07-04 21:29:52.322Z
If you’re looking to add a new track to an existing group there’s a thread here:
https://forum.soundflow.org/-217/duplicate-tracks-without-any-mediaBut if you’re trying to add an already existing track to an already existing group you may have to write one yourself. Shouldn’t be that hard.
BTW - I’m going to make a slightly more elegant script for switching back and forth from the Mix window. I’ll post here when I do.
//CS//
Todd Burke @Todd_Burke8
Thanks so much!
Chris Shaw @Chris_Shaw2020-07-05 18:54:53.131Z
Here's a better implementation. This approach doesn't require you to put your entire script into a function. Just place the appropriate lines at the beginning and end of your script:
sf.ui.proTools.appActivate(); sf.ui.proTools.invalidate(); /// Add this to the beginning of your Script //// // This function ensures that the track you've selected // in the Mix window will be visible in the Edit Window function ensureFirstSelectedTrackIsVisible() { var originallySelectedTrackNames = sf.ui.proTools.selectedTrackNames; sf.ui.proTools.selectedTrack.trackScrollToView(); sf.ui.proTools.trackSelectByName({ names: originallySelectedTrackNames, deselectOthers: true }); } /// this determines which window is your main window - Mix or Edit /// and switches to the Edit window if necessary if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) { var mainWindow = "Mix"; sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"], }); ensureFirstSelectedTrackIsVisible(); } else { mainWindow = "Edit"; ensureFirstSelectedTrackIsVisible(); } ////////////// ///////////////////////////// ///////YOUR SCRIPT HERE////// ///////////////////////////// ////////////// /// Insert at end of script //Switch back to Mix window if necessary switch (mainWindow) { case "Mix": sf.ui.proTools.menuClick({ menuPath: ["Window", "Mix"], }); break; case "Edit": break; }
As a rule of thumb, create your scripts to work in the Edit window and use the above code to make them compatible with the Mix window.
- In reply torobertsorling⬆:Chris Shaw @Chris_Shaw2020-07-11 19:39:57.896Z
Here's a more refined way to check for and switch to the Edit window and back:
// define functions at start of script function mainWindowStatus() { if (sf.ui.proTools.getMenuItem('Window', 'Mix').isMenuChecked) { sf.ui.proTools.menuClick({ menuPath: ["Window", "Edit"], }); return "Mix"; } else { return "Edit"; } } function returnToStartingMainWIndow(mainWindow) { switch (mainWindow) { case "Mix": sf.ui.proTools.menuClick({ menuPath: ["Window", "Mix"], }); break; case "Edit": break; } } /// start with this code var startingWindow= mainWindowStatus(); alert("Pause") // sample code / your code // end with this returnToStartingMainWIndow(startingWindow);