How to control the Stream Deck device with the showModal action
This requires SoundFlow 3.0 which is in beta at the time of writing this.
Sample script:
var sd = sf.devices.streamDeck.firstDevice;
var selectedValue = sd.showModal({
items: [{
title: 'Test 1',
color: { r: 255, g: 100, b: 0 },
value: 1,
}, {
title: 'Test 2',
color: { r: 100, g: 255, b: 0 },
value: 2,
}]
}).selectedItem.value;
log(selectedValue + '');
- Christian Scheuer @chrscheuer2019-04-13 09:58:02.020Z
Answer is in the question
Dario Ramaglia @dario.ramaglia
Ok, I just received my StreamDeck and I wanted to try this script. I'm on Stream_Deck_4.2.0.10031.
At the moment when I run this script SF just stays on the blue icon.
I'm sure I'm doing something wrong or something really stupid. Any suggestion?
Thanks in advance,Dario
Christian Scheuer @chrscheuer2019-04-14 16:57:31.060Z
@dario.ramaglia let's get you on board with all the regular commands for the Stream Deck first.
It can be a little tricky to get this script working right now - @Fokke knows all about that, he might also be able to help.
Once you wanna get started, you'll need to download the SF-SD plugin anew from here:
https://forum.soundflow.org/-492/220-preview-19You should uninstall your current SF-SD plugin first.
- In reply tochrscheuer⬆:
Christian Scheuer @chrscheuer2019-04-14 16:59:48.076Z
We need to add some error handling so that SF doesn't stay blue (remember Ctrl+Shift+Escape fixes that). But there are definitely SF bugs related to this feature. The Stream Deck device's API is very complex to interact with (sigh).
Dario Ramaglia @dario.ramaglia
It seems that when I restart the Stream Deck Software it works. Kinda :)
Christian Scheuer @chrscheuer2019-04-14 17:17:20.079Z
Yea it's definitely still buggy
Christian Scheuer @chrscheuer2019-04-15 18:22:49.565Z
Pushed 2.2 preview 24 with some bugfixes for the Stream Deck action.
- In reply tochrscheuer⬆:Christian Scheuer @chrscheuer2019-04-14 16:58:30.215Z
Actually, I just moved this to Alpha/Beta ideas since this is still an alpha/beta feature, so wanna make sure we can share private info in here.
- In reply tochrscheuer⬆:Christian Scheuer @chrscheuer2019-05-16 05:21:14.511Z
Here's how to control the Stream Deck with paging:
function streamDeckSelectWithPaging(device, items) { var result; var startIndex = 0; while (true) { var pageSize = 15; var hasPrevious = false, hasNext = false; if (startIndex > 0) { pageSize--; //Make room for "Previous" hasPrevious = true; } if (items.length > startIndex + pageSize) { pageSize--; //Make room for "Next" hasNext = true; } var pageItems = items.slice(startIndex, startIndex + pageSize); if (hasPrevious) { pageItems.splice(0, 0, { title: '<<', value: '<<' }); } if (hasNext) { pageItems.push({ title: '>>', value: '>>' }); } result = device.showModal({ items: pageItems, }).selectedItem; if (result.value === '<<') { startIndex = startIndex - 13; if (startIndex === 1) startIndex = 0; } else if (result.value === '>>') { startIndex += pageSize; } else { return result; } } } var device = sf.devices.streamDeck.firstDevice; var items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35].map(function (i) { return { title: '# ' + i, value: 'V' + i, color: { r: i * 255 / 35, g: 100, b: 100, } }; }); var selectedItem = streamDeckSelectWithPaging(device, items); log(selectedItem.value);
- In reply tochrscheuer⬆:Jesper Ankarfeldt @JesperA2019-05-16 07:49:22.418Z
The paging function could almost be a build in thing at a point.
I'm thinking it could be a bit like applescripts display dialog, where you have a couple of "build in" functions to choose/add from.
Some ideas for extra Modal functions could be:
- paging (as the above enable it)
- escape/cancel key (adding a key in the corner that cancels the action)
- Static (so the modal surface stays after a key press. Obviously this would require that it runs in the background, and also an "escape" key maybe)
- adding keys with custom name (such as OK). Could be handy if it is used to input more data.
Christian Scheuer @chrscheuer2019-05-16 07:53:51.273Z
Great ideas!
You can already make stuff with custom names - just give your button a "title" property. Color is optional by the way. If you don't specify color, it will just have the dimmed SoundFlow icon as the background, like you see in the paging.
You may also specify imagePath pointing to a png file, and then that will be used :)
- SIn reply tochrscheuer⬆:Steve @stevef
OK, I thought I would look in to Soundflow controlling Stream deck, and I am afriad I am not really understadning any of it. I know there's the example script at the top, but I ahve no idea how to even implement that! Any chance of a step-by-step tutorial at some point with a simple example as to what sort of things can be done? I mean, can you actually change what an individual button does and what it looks like based on what window you have open in Cubase? Can you get it to switch profiles or more importantly, can you get it to open a sub page of a profile?
One idea I have is to have key switches set up for different Kontakt instruments, and wondered if possible for Soundflow to activate the correct page / profile on the stream deck when a certain instrument is loaded? Although that is probably not a nice simple one to start!
So can it do something like changing what a button does when you select some audio, and then do something different when nothing is selected. And maybe something else if a MIDI part is selcted?
Any pointers would be appreciated!
Thanks.
Christian Scheuer @chrscheuer2019-05-25 19:57:25.446Z
cc: @JesperA.
Think of the showModal function as a popup window on your Mac with a list of things you can press, and once you've selected one of the things (clicked on a button), the function will return and tell you what was selected. Only it does it on the Stream Deck.
This is the first building block to creating more advanced workflows such as the ones you're describing.
@JesperA has made some great small apps that can show you how this works. Maybe he can link to some of the videos he created here?I mean, can you actually change what an individual button does and what it looks like based on what window you have open in Cubase?
This is a more advanced scenario, but it should be possible, although a little tricky.
First you need to have a script trigger when a different window is open in Cubase. You do that by creating a script that loops in the background and constantly checks which Cubase window is active.
Then you'd need to sort of "take over" the Stream Deck.. Actually now I'm thinking about it, I'm not sure we're completely ready for this to work still.Can you get it to switch profiles or more importantly, can you get it to open a sub page of a profile?
Elgato decided that profile switching is not possible unless we switch to profiles created by SoundFlow. In other words, no you can't tell it to switch to existing profiles that you designed on the Stream Deck.
Later we hope to allow you to design profiles directly in SoundFlow which will make this possible.If you do the profiles via the showModal command however, you will be able to do this - you just can't switch to profiles designed in Stream Deck.
Again, JesperA has some great examples of this in Cubase with for example color switching.
Jesper Ankarfeldt @JesperA2019-05-26 08:15:43.391Z
Hey Steve.
I mean, can you actually change what an individual button does and what it looks like based on what window you have open in Cubase?
As Christian says, it's more advanced, and right now it doesn't make sense, because Stream Deck only works properly with the showModal function, which blocks SF for other inputs.
I've attached a script for you to check. It basically sets my stream deck with a couple of buttens. As it came from an earlier thing I did with stream deck, it's made with icons, so if you wanna try it I've attached the icons.
Basically what you do is put the key command for your export mix down as a trigger for the script. The idea is to have some pre-configured settings. I'm selection specific outputs and if it should be marker export or not with the different keys, so I don't have to think when exporting.
If I would write the script today I would probably just have made it with colors coded for the stream deck, rather then icons.if (sf.ui.nuendo.exists || sf.ui.cubase.exists) { var app = sf.ui.nuendo.exists ? sf.ui.nuendo : sf.ui.cubase; var version = app.shortVersionString; var cubendo = app.title.value; } else { cubendo = 'Cubase' version = '10' } if (sf.devices.streamDeck.deviceCount == 1) var device = sf.devices.streamDeck.firstDevice; else var device = sf.devices.streamDeck.secondDevice; function checkThatExportAudioMixdownWindowIsOpen() { if (!app.getWindowWithTitleStartingWith('Export Audio Mixdown').exists) app.menuClick({ menuPath: ['File', 'Export', 'Audio Mixdown...'] }) else app.getWindowWithTitleStartingWith('Export Audio Mixdown').elementRaise(); } function exportFuntion(channelName, cycleMarker, homeEnd) { var EAMWin = app.getWindowWithTitleStartingWith('Export Audio Mixdown') EAMWin.elementRaise(); EAMWin.mouseClickElement({ relativePosition: { x: 40, y: 164 } }) if (cycleMarker) EAMWin.mouseClickElement({ relativePosition: { x: 40, y: 300 } }) else EAMWin.mouseClickElement({ relativePosition: { x: 40, y: 270 } }) EAMWin.mouseClickElement({ relativePosition: { x: 280, y: 164 } }) sf.clipboard.setText({ text: channelName }); sf.keyboard.press({ keys: 'cmd+v,enter' }) EAMWin.elementRaise(); } function exportCueStems() { var EAMWin = app.getWindowWithTitleStartingWith('Export Audio Mixdown') EAMWin.elementRaise(); EAMWin.mouseClickElement({ relativePosition: { x: 40, y: 195 } }) EAMWin.mouseClickElement({ relativePosition: { x: 40, y: 300 } }) } function clickEAMWinPos(x, y, cornerX, cornerY) { var EAMWinFrame = app.getWindowWithTitleStartingWith('Export Audio Mixdown').frame; var EAMWinX = EAMWinFrame.x + (EAMWinFrame.w * cornerX); var EAMWinY = EAMWinFrame.y + (EAMWinFrame.h * cornerY); sf.mouse.click({ position: { x: EAMWinX + x, y: EAMWinY + y } }); } function pathLocation(folderName) { clickEAMWinPos(-100, 90, true, false) var path = app.getFirstWithTitleContaining(cubendo).getString('AXDocument'); var sessionDirectory = decodeURIComponent(path.substring(7).split('/').slice(0, -1).join('/')).replace(/ /g, ' '); // directory of the file open in Cubase var directory = sessionDirectory.split('/')[5] // directory of the parent folder //set your standardized folder structure sf.clipboard.setText({ text: '/Volumes/HDD/Music/Cubase/' + directory + '/' + folderName }); sf.keyboard.press({ keys: 'shift+cmd+g, cmd+v, enter,enter' }); sf.wait({ intervalMs: 100 }) sf.keyboard.press({ keys: 'enter' }) app.getWindowWithTitleStartingWith('Export Audio Mixdown').elementRaise(); } function pathProjectAudio() { clickEAMWinPos(-27, 120, true, false) sf.keyboard.press({ keys: 'down,down,enter' }); } function openAudioExportWindow() { app.menuClick({ menuPath: ['File', 'Export', 'Audio Mixdown'], looseMatch: true }); } function render() { var tempIconNames = ['black', 'black', 'black', 'black', 'mixdown_projectBouncePath', 'black', 'mixdown_selection', 'mixdown_cues', 'mixdown_video', 'black', 'black', 'black', 'mixdown_cuesStems', 'black', 'export']; var names = ['', '', '', '', 'Project Bounce Path', '', 'Export Selection', 'Export Cue', 'Export Video', '', '', '', 'Export Cue & Stems', '', 'Export']; // set the folder of where the icons are: var newFile = '/Volumes/HDD/Google Drev/5ComputerRelateret/StreamDeck/Flexible Icons/MIDI Selector/' var items = []; var color; for (var i = 0; i < names.length; i++) { color = { r: 0, g: 0, b: 0, a: 0 } items.push({ // title: names[i].replace(/ /g, '\n'), value: names[i], //color: color imagePath: newFile + tempIconNames[i] + '.png' }) } return items; } function handleAction(actionValue) { var actionArgs = actionValue.split(/:/g); switch (actionArgs[0]) { case '': app.getWindowWithTitleStartingWith('Export Audio Mixdown').windowClose(); return false case 'Name': clickEAMWinPos(-400, 80, true, false); return true case 'Export Selection': exportFuntion('MusicMixDown', false, 'home'); return true case 'Export Cue': exportFuntion('MusicMixDown', true, 'home'); return true case 'Export Cue & Stems': exportCueStems(); return true case 'Export Video': exportFuntion('StereoMixDown', false, 'home'); return true case 'Cancel': clickEAMWinPos(-150, -20, true, true); return true case 'Path Audio': pathProjectAudio(); return true case 'Project Bounce Path': pathLocation('1Bounce'); return true case 'Export': { clickEAMWinPos(300, 520, false, false); if (app.focusedWindow.title.value.match('Export Audio Mixdown')) clickEAMWinPos(300, 690, false, false); return false } } } function main() { openAudioExportWindow() device.doWithSeizedDevice({ action: function () { while (true) { var items = render(); var actionValue = device.showModal({ items: render(), }).selectedItem.value; if (!handleAction(actionValue)) break; } } }); } main();
export icons.zip (194.39 kB)
Jesper Ankarfeldt @JesperA2019-05-26 08:19:28.115Z
On the store there's a new color app/package. it works really well for stream deck. Still needs a little documentations. But that would more be like a button you press when you wanna color stuff, and in that way works like a sub folder as we already do with stream deck's own app. the difference is thought that what you see on the stream deck is made from the default.xml file in Cubase/Nuendo, so it'll always be up to date with your colors, and there's settings so you can change the behaviour.
But I do look forward to seizeDevice for the Stream Deck becomes fully functional, since if you forget to close the Stream Deck after showModal SF will be paralyzed :P
Christian Scheuer @chrscheuer2019-05-26 10:12:58.809Z
@stevef as you can see Jesper's doing some pretty advanced things with this, but it still is kinda new ground so it takes a while to get your head wrapped around everything.
I think you should try out Jesper's script for selecting colors for tracks and events via the Stream Deck. It's pretty epic. I think it still might need a bit of beta testing (it's hardcoded to use multiple Stream Decks so right now it doesn't work here). Jesper which of your packages is this contained in?Jesper Ankarfeldt @JesperA2019-05-26 10:15:45.407Z
It's contained in it's own new package called Cubendo Color Tool, which has some beta version of surfaces as well.
Christian Scheuer @chrscheuer2019-05-26 10:17:23.172Z
Great! I thought so :) This one wants me to have 3 Stream Decks though haha... Don't work on it now, go to sleep! But we can talk about next week if we can find a way to let the user configure which device to use. Maybe first time the command is run, it pops up and asks the user which device to use.
- SSteve @stevef
Thank you both for your input. I'll take a look at these and see if it makes any sense ;)
- In reply toJesperA⬆:SSteve @stevef
@JesperA - This is brilliant and potentially extremely useful! Whilst I don't quite understand the way it is scripted, I do understand what it is doing and actually understand quite a bit of the script. It actually has similarities to Kontakt KSP which I am OK with. For example, I understand the setting up of functions and calling them. Also, the way it deals with the buttons is just like how Kontakt deals with menu's, so I totally get that. You name a button and then you use Case to see which button is pressed and call the function (Kontakt uses Case as well when selecting menu items). So, changing your paths (and adding a black.png icon which was missing), I got this to work. I even managed to add my own buttong which changed from Wav export to mp3! How the script then interacts with the Stream Deck is still beyond me at the moment, but then, having a script like this to work from solves that for now :)
I have a question about the EAMwinpos item, but I'll start a new post for that. But thanks very much for this. As you say, it would be nice to swap out the icons for colours. But, I can really see how useful the interaction with stream deck will be.
Jesper Ankarfeldt @JesperA2019-05-27 20:50:03.599Z
arg damn, forgot to include the black icon. Sorry. It's just because I like it a bit cleaner, so adding black ones to the spaces.
Sounds to me like you undestand the script pretty well. I think it could probably be scripted a little smoother now, as I did this more then half a year ago for surface and just adapted that to Stream Deck.