Scripting basics!

Hi folks,

I’m a total beginner with scripting and coding in general, so i’m probably going to ask some very dumb questions, apologies in advance!

  1. When i create a controller and script, it’s a json file (in /local)

But when i look in the public folder, i see only js files for all the included controllers.

Why the difference and is it important in this case?

  1. When i create a controller with only one button, and map transport > start to it, it works, but in the code in VS Studio (of the json file) i can’t find the word “Start” when i search for it , even though that seems to be the code for that action, according to the Steinberg API docs (see pic below).

I also notice that the size of the json file remains 5117 bytes, whether or not i map the button, which suggests to me that this piece of code is being written to another file somewhere else (perhaps related to the json / js question above?)

Thanks!

When you’re using the mapping assistant approach, a json file is generated containing the control surface elements.
When scripting, you’re actually creating a js file, and this is the type you mostly see in the Public folder.

As said earlier, just the surface is in the json file. The assignments are stored in a different location [your Documents Folder]\Steinberg\Cubase\MIDI Remote\User Settings again in a json file with a name similar to the one of your original (surface) json file.
In the case of your screenshot, you will then find the assignment inside this file.
For example:

εικόνα

Thanks very much, that clears things up a lot!

My idea was that i would create the most simple controller with the mapping assistant, then start to hack at it to learn how to script the functions i need. But i guess that won’t work as it creates a json, whereas i need a js file.

Obviously i could just use one of the ready made controllers in the public folder, copy it over to local, then start hacking away, but the problem is they all contain way more stuff than i need, which will make learning much more difficult.

So my next question is, how do i create the simplest possible js file that has the barebones stuff i need?

And is it possible to copy parts of the code created (as you just explained) in Steinberg\Cubase\MIDI Remote\User Settings and paste it into my barebones js file?

So as an example, perhaps i want to add a fader that controls metronome volume. Then my hope is that i could first add the feature using the mapping assistant approach, then look at the code created in the json in Steinberg\Cubase\MIDI Remote\User Settings, and copy that into my js.

Or is that a dumb idea or is there a better way?

You copy an existing script, but there’s a trick: you have to follow a specific naming scheme for the file and modify the script so that manufacturer, device and creator are consistent.

Why not start following the steinberg’s guide? They provide 3 scripts to start learning the API.

And while you can Copy/Paste snippets of code, some variable names might need to be changed.

Oh and you’ll need some basic JavaScript understanding too, there are many good (and free) tutorials online.

It’s a bit of a learning curve, but in my opinion, it’s worth it.

Thanks, after tearing my hair out for half an hour, i worked out the naming convention to copy from public to local.

A couple more questions: in terms of pure layout, is it possible to just using the mapping assistant to get everything in the right place, then copy that code from the json to the js? Because that would be a lot easier than doing layout only looking at reams of numbers in the VS Code editor!

And it’s still not clear to me what the purpose is of the json file in Steinberg\Cubase\MIDI Remote\User Settings

What gets set up there as opposed to the local folder file?

Are these two separate files always required to completely describe a controller, and if so, how do you know which info to put in which file?

The json file in the local folder defines the controller surface, i.e. the design of knobs, buttons etc.
The json file in the user settings folder defines the assignments to the controller surface’s elements, i.e. Commands and Host Values.
So yes, it’s the combination of them that really defines the controller and the actions assigned to it.

Not out of the box. I did create something about it but till I find some time to give it a hard test,I will not publish it.
Nevertheless, watching the stuff you want to assign (seen in another thread) I’m not quite sure you should go into the scripting approach. Mind asking what are your expectations by this transition?

Thanks!

I wrote another reply, but maybe i can just condense my main question to this:

What is the correct workflow when creating a script?

When one makes an edit in the code, you need to see / try the result inside Cubase, right?

I copied the ExampleCompany_SimpleDevice.js to local, changed the name and then “Add MIDI Controller Surface”.

I create the controller, assign the MIDI ports and then press “Create MIDI Controller Surface”.

So far so good.

But now, if i press “refresh” anywhere in the “MIDI Remote” tab, it (SimpleDevice) disappears, whether or not i changed anything in VS Code Studio or not!

So each time i want to change anything in the code i need to refresh, then go through the “Create MIDI Controller Surface” routine each time.

That can’t be the correct workflow?!

You asked the general question about why i even want to bother with this whole scripting hassle. Here’s a simple example:

I want to have a button on my controller that sets snap to “on”. I don’t want to have to look at the toolbar to see if snap is already on or off. I just want to be able to decide “i definitely want snap on now”, press a button, and know it’s on. It seems me that sort of thing isn’t possible without scripting!

It is. It’s the command Snap On:

εικόνα

Generally though, there are indeed things we can’t do without toggling. So, yes, scripting is helpful in such cases, but even then, sometimes advanced knowledge of Cubase internal properties is needed unfortunately.

This is because inside the script you haven’t set the midi ports’ names of your actual device. This is an issue first appeared in CB13.
I’m talking about these lines of code:

deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
    .expectInputNameEquals('SimpleDevice IN')
    .expectOutputNameEquals('SimpleDevice OUT')

Instead of the SimpleDevice IN/OUT you should write the port names of your controller.

Sorry, you’re right, i think they changed that because in my memory in the past that was not possible (snap).

But here’s another example: move the playline with forward / rewind and select the object under the cursor (playline) on the selected track.

Thanks for the tip on the MIDI i/o in the js, that fixes it!

Advanced warning: more questions to come! :joy:

Sure. I’ve given my thoughts on this one, here:

Anyway, I’m not trying to discourage you from getting into scripting, trust me I’d be the last person in this forum to do this :slight_smile: It’s just that I wouldn’t want you to spend precious time, only to find out later that it was not needed.

Ah-ha, i missed that reply, because for some reason i never get notifications when there’s a reply.

As there is virtually no learning material for Cubase scripting, i’m going to think about what you said!