MIDI Remote - Defects & Lesson Learned

Just to clearify import midiremote_api from 'midiremote_api_v1'; is a newer import variation indicating that you use the default export (otherwise it’s import {something} ... and I believe this is why you get the Object.defineProperty(...) and the midiremote_api_v1_1.default.makeDeviceDriver lines. At least they are an effect of it. So I hope that using require in the typescript file could avoid the transpiler to write these lines.

In my lib I always avoided using the import. I don’t use Typescript ofc so there’s a difference but I remember that never worked. Visual Studio Code always highlight that I can convert to ES module but that fails when trying to make Cubase run the script.

I just wrote and deleted a book that was mostly grousing about ES5 and how difficult it makes things, and how it doesn’t make sense when it could have at least been ES6, if not just TypeScript. I mean, why make it more difficult than it needs to be? I know I’m a rather proficient software engineer, so how is ES5 for non coders?

ES5 is like trying to put a fire out with buckets of water when there is a fire hydrant in the front garden. But maybe it has something to do with a fear of concurrence. But you can forget about that, because one could make that happen anyway, It’s a mystery.

Anyway, that one line is a forward reference to allow imports and exports, and if you flag it out, then it also takes away the inheritance boilerplate.

I found a lot of people writing scripts to be installed in other platforms that had the same issue, and they all seemed to resort to what I am doing. Writing the whole thing in one file, and deleting that one line. I thought that would be a temporary workaround.

The added “_1” is intentional. That doesn’t look right, but it is.

This fixes the second “default” rewrite. And also brings the types in nicely, but it complains a LOT about the midiremote_api_v1.d.ts file. Which it says is not complient.

/// <reference path="../../../.api/v1/midiremote_api_v1.d.ts" />
import midiremote_api = require('midiremote_api_v1');

if you put the following in that file it will stop complaining:

// @ts-nocheck

It will still stick the offending export forward definition in, but not add the default.

But this will produce perfectly functioning JS.

/// <reference path="../../../.api/v1/midiremote_api_v1.d.ts" />
var midiremote_api = require('midiremote_api_v1');

If you leave it as “import” and then just before transpiling, change it to a “var”, alles ist gut.

I really wish I knew a more strait forward work around. It would be nice if Jochen et. al. would add the nocheck to the .d.ts file or clean it up so it works in TS.

Personally, I would rather do something I really didn’t want to do, and just wrap the whole API so the issue only shows in one location, than to write anything else in ES5.

For now, I simply copied the ,api directory and added the flag at the top of the file.

Baby steps, but it’s closer.

Thank you for your help!!!

That was an error! Not one the effected anything, but that config was incorrect.

See above for the solution and the repo for the fixed tsconfig.json.
Also, again, I just copied the .api to another directory because it gets re-written every time.

Really wish that file was TS compliant, or the whole thing was just in TS. I will push more fixes when I get the files separated, and tested.

As I am digging into this, I must agree with this assessment and @oqion suggestion on mOnDisplayValueChange (that it be split in to two functors, mOnHostValueChange, and mOnEncoderValueChange)

@Jochen_Trappe. Please take this into consideration.

  • Ron

Hi @oqion and @Ron.Garrison, the functor mOnDisplayValueChange is meant to be used to drive hardware displays only. That’s where the “Display” part of the name comes from.

Regarding the request having a mOnHostValueChange and a mOnEncoderValueChange separately, there is at least a way to get the mOnHostValueChange done. By using “makeValueBinding(…).mOnValueChange = function …”

3 Likes

@Jochen_Trappe - Can you please point me to “mOnValueChange”. I’m not finding it in the MIDI Remote API.

Thanks!

I know tried that, and it didn’t work right. It was a while ago and I don’t remember what went wrong. I will go back and review my code with the expectation that I had a defect in my code.

1 Like

it’s not documented, but it’s in the code. I see now what I was doing wrong.
Look in the midiremote_api_v1.d.ts file

1 Like

Thanks. I thought I searched, but found it this time. Will try it out. This is a steep learning curve for me. I’m sure my code has a lot to be desired.

Ron

Don’t feel bad, it’s a steep learning curve for me to, and I have credentials that would suggest that it wouldn’t be. Sometimes my experience and expectations are working against me though.

That said, it is quite impressive. But you should not feel bad if you find it hard. Even if you are a coder.

1 Like

I know VHDL. So in that sense I am a “coder” bit it is a completely different beast. And this is my first go with javascript. However, it is nice that I can get this (slowly) to work. Everybody’s examples help greatly.

1 Like

@Jochen_Trappe , Thank-you!! mOnValueChange did the trick. Now things seem to be working as expected. Now to work on the host mapping.

Edit: When using mOnValueChange, subPages no longer work so it does not solve my problem after all.

-Ron

1 Like

PLEASE, this is not true. It is in the API Reference and documented on:
PluginOnValue
PluginBypassValue
PluginEditValue

Dont point people to something like midiremote_api_v1.d.ts file, if you can find this in the README_v1.html of the API Reference.
The only sad thing is, that we are missing proper examples how to use this. Maybe there are examples for these in the Example Scripts.

I am no coder or a experienced JavaScript developer and for me it is already SUPERHARD to follow the code, just to understand what is happening. Pointing into even deeper $hit, is not a help.

Just to be clear: I like this thread as you (oqion) and some other users, are the only users that show us “normal” users examples, that are not documented elsewhere.

I would like to know, how much of this API stuff is based on the MCU protocol? Or is it really completely new and has nothing to do with MCU protocol.

Yes. Otherwise we would only see (abstract) values on the hardware display, like i.e. 0-127 instead of L(1-100)-C-R(1-100) for Pan.
If we do a search for mOnDisplayValueChange in the midiremote_api_v1.d.ts file, we will find 53 hits where it is used (55 in total).
To me it means that Cubase has 53 cases, where Cubase can show a “better” value on hardware displays, instead of only i.e. 0-127.

It was not at the time. I haven’t looked at the most recent update yet.

It’s a mater of digging in. “circuit bending” or “hacking”. Though “hacking” is an ever changing and overloaded word. (It use to mean writing bad code, then the more popular, movie definition, of writing illegal code, but now means, writing code with little to no documentation.)

Am I wrong that you are frustrated? Know that this happens as new code is presented sometimes, and many professional software engineers and computer scientists take issue with it as well. But as systems have begun to change more quickly we have all become more accustomed to it. Some even enjoy it.

I have not yet looked into the most recent release but I suspect that the documentation will become more beneficial as time goes on. Understand, that the old view of code as something that is fully complete and fully documented when released has given way to ideas of evolutionary design. It is a struggle in the whole of the software industry to find a balance. I don’t know if that helps with the frustration, but I can tell you that you are not alone.

I am anxious to try the latest release and see what changes have been made. There were issues with the solution that Jochen had suggested, but I suspect that those are now, or will be resolved. For the time being, I have been focused elsewhere, and have not had a chance to look at the new release.

To answer your question about the MCU protocol, I can not say whether there is some relationship at a deeper level, but it does not appear to be the case. It is best to approach the script writing for MRs as a completely new thing.

Hi oqion :slight_smile: ,

I am at 12.0 , so again this is not true. You simply overlooked it… sorry.

I am not only frustrated. I am VERY frustrated. I will try to explain my issues with JavaScript:
I have no problems with the API index of functions available.
My problems start with using that functions. Using them involves using abstract naming conventions and EVERY developer/user do exactly this differently. This is in reality means pure CHAOS or a mindfuck where you simply give up as a novice.

I really hope it. The documentation needs to be complete, because of the problems i mentioned previously. We have good examples in the Example and Company Scripts, but as i said EVERYONE uses different naming conventions. So two scripts describe the same function, but the code will definetily look different and this is $HIT.
For me it becomes nearly impossible to copy code from someone that has a solution (to a problem of my script) and to copy code from a different thread/solution and to finally merge both codes into my own script.

Sorry, but i want a 100% proofed answer, because for me it is quite the opposite of “does not appear to be the case”. It just misses some stuff, that is available in MCU.

Totally agree, but i still want to know, how much of it is based on MCU protocol.

In regards to the API and what you’ll touch JS wise, none of it is based on the MCU protocol. It’s purely based around the ‘hooks’ within Cubase that we can attach (bind) to, and handle the feedback of those.

The MCU protocol is purely a standard nomenclature the communication is just standard MIDI protocols. i.e. It defines more ‘which’ MIDI data should be communicated to write to the screen, set faders etc.

As the core functions of the API transports MIDI Data you can conform that to the MCU standard via code if you wanted to. But the default scope is global across the MIDI protocol and not at all tied to MCU.

Some of the examples include a function to parse text into a sysex format that work directly with MCU displays. That may lead you to think there’s elements based on it. But those are not part of the API, simply an example of what you can do via user functions.

1 Like

Hi,

There is no relation between MCU protocol and MIDI Remote Api in Cubase. MCU protocol is just a standard/definition, how should the software react to some (specific) incoming MIDI messages. Nothing more.

For example (in the default setup): PitchBend at channel 1 controls the Volume (fader) of the 1st channel of the given bank.

MIDI Remote Api on the other hand, doesn’t define any usage of the MIDI messages. You can use any MIDI message to control any (or let’s be precise… pre-defined) parameter in Cubase.

Hi skijumptoes, hi Martin.Jirsak,

I did not wrote tied (which i would translate to “is dependent” on), i wrote based. I hope you see a difference here. This brings me to the next quote:

You are right, this is a perfect example where i clearly think there´s elements based on it.
And it makes sense, why would Steinberg reinvent the wheel, if they did this before ???
Then there is the circumstance that in over 15 years, nearly no developer did not follow the MCU concept, be it Behringer and all the other clones that follow MCU protocol.

This is only a assumption, that i will not believe until proofed. In no way i believe that the (display) sysex handling is done via simple user functions.
To be honest, i was really suprised that the (display) sysex handling worked nearly out of the box. There must and there is a reason why the API do support these displays.

Normally you would need to write a own ASCII parser to manage the text properly and you will not find a single example (not in scripts and not in API) that has code that do this.
For me it means, the ASCII parser is already implemented in Cubase and you can use it with the API. I believe that this is only possible, because MCU exists.

You will nowhere find a description for (display) sysex handling in the API for this case.
Even the Example Scripts have no description for it. You will only find code in the /helper file of the Real World Example script or in some Company scripts, that make use of this ASCII parser, but the parser itself is undocumented.

So back to topic (a little at least):
The same that applies to the ASCII parser, can be found with mOnDisplayValueChange.
This is also a leftover from MCU. You will not found any code or example script, that define how the value is displayed on hardware displays.

What i mean is for example Pan:
there is no code that tells the hardware display “hey, use L-C-R instead of 0-127”. There is only mOnDisplayValueChange that “activates” the use of that code that is undocumented elsewhere.

This example is a (maybe unique) feature of the MCU and of the C4. This feature can only work, if you prior define it in your DAW code, what values should be replaced with text.

How do i know this?
Well, the Commander Software for C4 has a manual, where exactly this is described, if you want to write your own script and want to represent values in a different way.
Steinberg did use this feature, with the invention of MCU and i simply do not believe they did this again for the API and hardware displays. mOnDisplayValueChange just uses those predefined “values” somewhere deep in Cubase code and this code is only there, because MCU could used it.

OMG, yeah those weren’t supposed to be exposed :joy:. I’ll remove them from the type-helper-file as they aren’t accessible/usable/implemented anyway.