MIDI Remote - Defects & Lesson Learned


This is one of the differences of MCU and the MIDI Remote Api. This is not part of the MIDI Remote Api at all, because every hardware can handle it by own way. You have to write in to the script to handle it. It’s not part of the mOnDisplayValueChange method.

Not really. The mOnDisplayValueChange method is just the callback from Cubase. If the DisplayValue changes in Cubase, it sends the new value out. In the script, you have to take care to print the value to the display the correct way. It might differ based on the device specification.

These “values” are named UTF-8 or UTF-16 standards, which have not been defined neither by Mackie nor by Steinberg.

1 Like

Nope, i dont agree with this. Because you did not write anything in your script (nor Ron.Garrison in his script), that would make that possible. I only agree with, that this is not a part of API and you will not find any evidence in the API, how this is done.
BUT L-C-R, 400.00 Hz, On / Off etc. exists only, because it was already defined for MCU in the past.
You might/can change this with a script, but this would be some “nice” extra work and no one has this done so far.

I did not wrote that. I wrote that mOnDisplayValueChange activates a code/part of Cubase (not API) where all that predefined stuff can be found ( L-C-R, 400.00 Hz, On / Off ).
We can not influence how this is displayed, we can only activate it by the use of mOnDisplayValueChange .
You can not change L-C-R to Left-Center-Right without writing extra code for it and you did not write any code for L-C-R either. I hope that it is clear now, what i really meant. This has nothing to do with UTF-8 or UTF-16 standards. It has to do with something that translate values of 0-127 into something more meaningful like On / Off or L-C-R or etc. and this will you not find in UTF.

But I have done this. For instance, this section of my code:

button.pushEncoder.mEncoderValue.mOnDisplayValueChange = function (context, displayText, str2) {
      var r = button.row.toString();
      var c = button.column.toString();
      //console.log("DisplayValueChange(".concat(r, ",", c, ") - ", displayText))

      var text = "      |"
      switch (button.row) {
        case 0:
          // Frequency
          // Strip Hz off the end
          text = text.replace(text.substring(0, displayText.length-2), displayText.substring(0, displayText.length-2));
        case 1:

          text = text.replace(text.substring(0, displayText.length-2), displayText.substring(0, displayText.length-2));
        case 2:
          text = text.replace(text.substring(0, displayText.length), displayText.substring(0, displayText.length));
        case 3:
          switch (displayText) {
            case 'Parametric I':   text = "P I   |"; break;
            case 'Parametric II':  text = "P II  |"; break;
            case 'Low Shelf I':    text = "LS I  |"; break;
            case 'Low Shelf II':   text = "LS II |"; break;
            case 'Low Shelf III':  text = "LS III|"; break;
            case 'Low Shelf IV':   text = "LS IV |"; break;
            case 'High Pass I':    text = "HP I  |"; break;
            case 'High Pass II':   text = "HP II |"; break;
            case 'High Shelf I':   text = "HS I  |"; break;
            case 'High Shelf II':  text = "HS II |"; break;
            case 'High Shelf III': text = "HS III|"; break;
            case 'High Shelf IV':  text = "HS IV |"; break;
            case 'Low Pass I':     text = "LP I  |"; break;
            case 'Low Pass II':    text = "LP II |"; break;
      button.setLabelText(context, 1, text);

It has to do with something that translate values of 0-127 into something more meaningful like On / Off or L-C-R

I have experimented with this. For instance I could take the raw encoder value (which is 0-1 as opposed to 0-127), and interpreted it to “something more meaningful”, but you run into edge conditions in which the physical display will be slightly different from the cubase display. Usually this is not much of a concern, but for “discrete type”, like the filter types .above, the filter type might change on the controller but not yet in cubase putting them out of sync.

1 Like

Hi Ron.Garrison :slight_smile: ,

Ok, i admit you really did put in some extra work for this.
BUT, you initially started with mOnDisplayValueChange too.
Otherwise you simply would not have the “right” numbers to show up on display. I can not tell what kind of value would be displayed, if you have not used mOnDisplayValueChange.

This is not the raw encoder value, this is the response from Midi Remote. The encoder deals with ±65 steps and nothing with a range from 0-1 and the (defined) steps inbetween 0-1.
I meant with 0-127, the value that is shown on display, if you dont use mOnDisplayValueChange. Or otherwise said, your “raw encoder values” are printed like 0-127 to display (and not like 0-1 with predefined steps inbetween).

I see these problems too. I accuse rounding problems with the math formula that is used in 0-1 that is send out by Midi Remote. It simply said is not accurate enough and even worse are not constant values. They can be different for the exact same situation. This will lead to for example, that a LED segment of the feedback ring will be On for lets say a value of 70 and will be Off if you turn the encoder to move to value 50 and return to the exact value of 70 again. This should not happen, but it happens.


Not really. Mackie was using already existing standard UTF-8. So the only thing we have to do in the script is: text.charCodeAt(i). The reason, Mackie (for whom we are writing our scripts) is using this UTF-8 table. If any other hardware vendor would use different way of printing to the display, we would need to translate it other way.

Not really. We get a string from Cubase. Then we have to print it to the display. What I do in the script is, I go character by character and translate it to the UTF-16. Please see more details of this JavaScript method here. Mackie decides to do it via SysEx message and use the UTF-16 table. That was smart and other HW vendors are following this very often. But it doesn’t mean, this is the only one way. There could be other ways and MIDI Remote Api can handle these other ways too. Because it’s not linked to the MCU standard at all and it’s open and flexible. And tis is the reason, why it’s not documented in the Api, because other hardware can handle it different way.

Cubase gives us a string. We have to translate every single character of the string to the integer between 0 and 65535 representing the UTF-16 code unit at the given index. This is what does the text.charCodeAt(i) method do. We have to do this, because Mackie requires this way. Then Mackie receives the number and print it to the display as a character.

1 Like

Exactly. And the content of this string must be defined somewhere in Cubase code. How Mackie translate that to print it on display, is what you describe. You dont describe where the content of that string is defined.

Again, i never wrote that. Off course there could be other ways, but then you would start from scratch and you would need to define the contents of that string. Or you simply follow, by what is already there and use that string from Cubase and following the “Mackie” method to print that on display. Mackie does not require anything, Mackie could simply just print 0-127 to display. Mackie “offers” to solve this in a better way, by using that method. Nothing else.

This whole thing here, turns into hair splitting and it seems that noone understand, what i try to say here.


Exactly. It’s defined in Cubase. It has nothing to do with MCU.

And i say, it is defined in Cubase, because MCU was invented and Mackie where the first who offered this possibility. This string would not exist otherwise. That is what i believe.

These strings were in Cubase prior MCU had been defined. :wink: You can see these in other devices, using older protocols than MCU is.

The MIDI Remote API has nothing to do with MCU.
They are completely different things.

MIDI Remote API works with MIDI CCs, just like any other Plugin and its corresponding “MIDI learn” feature.

MCU is a protocol that uses various MIDI messages under the hood (like note on/off events, PitchBend), usually thru a different MIDI port than the one used for the main (musical instrument) MIDI communication.

Just put a device in MCU mode (some call it “DAW control”), try to “learn” it via the MIDI Remote API and see where you get.

Ok, this might be true, then Mackie used/supported the same method and some other vendor was the first. Then i revise my statement and say the string is only there, because some other vendor offered this method of showing values. This string makes only sense, if you have a display to print it on.

And guess what, the V-pots of a MCU/C4 work with CC too. Coincedence?
Midi Remote API does not only work with CC. It is much more than this.

Usually you would do that with every controller that use midi-communication, except you want to controll the musical instrument. If you use the same Midi port, like you use for the musical instrument, it could easily happen that you accidently use controls of the controller too. Not practicable, who would do that?

What do you want to tell me here?

Ok, let’s say it is based on MCU then. Not sure what difference it really makes. :slight_smile:

The elephant in the room being that it doesn’t support MCU, or can offer deep integration of such, of course - but we’ll let that fly.

It makes a difference, as it might help me to find out, if mOnDisplayValueChange is a bug that needs a report or if it is just not correctly used in scripts for the C4 from different people like Ron.Garrison or Martin.Jirsak.

Since even Jochen_Trappe wrote that mOnDisplayValueChange should not be listened in the API index, we are talking about a unsupported feature or in his words should not be “accessible/usable/implemented anyway”. (see post 39).

Question is now, is this reportable as a bug? Should those people even use mOnDisplayValueChange any further?

I dont understand this, but it sounds NOT good toward my person.

Actually what he wrote was

Whch is exactly what we are using it for. It is simply a callback that should be called when the hardware display needs updating, but it isn’t always called. I firmly believe it is a bug, but would really like @Jochen_Trappe to chime in on the other thread.


Yes, he wrote this, but he also wrote this:

And since,
are the only functions that make use of mOnDisplayValueChange in the API index, it means as a result, that mOnDisplayValueChange is a unsupported feature (currently).
Can you agree with me on that point? Or i am totally dumb here?

Hello :joy:, a bit too fast man!
mOnDisplayValueChange is available on all SurfaceValue-objects:


That might be true, but if you do a search for mOnDisplayValueChange on API index, you will only have results for what i wrote previously.
It is true, that i will find mOnDisplayValueChange in the Example scripts, but it is not documented anywhere in the API index, except those i mentioned.

Please do a search for mSurfaceValue too in the API index :grin: :joy:
Tell us the result. :grin:

Not funny :face_with_monocle:

1 Like

No it is not, i am afraid.


The bug is very nice described here.