THERE IT IS: the ultimate custom module for cubase users (at least for me)

Evening All,

I've tidied the whole thing up a lot and pulled a lot of the sections if it out into functions in the JS to make it all more manageable. Consequently there are many more lines of code now so too many probably to just paste here - I've added a file however with all the code in.

Some of this relates to my specific OSC session so it might not work directly but you should be able to work it all out from this and snip out what you need...
Good luck!

sysexAndNaming.js (23.0 KB)

1 Like

This is fixed I think...

Now not needed if you ensure you have
send('midi', 'MCU_From_OSC', '/note', 1, 44, 127);
Before anything else in the custom module - this is the cubase MCU handshake

Not really - it was a full team effort!

Wow... i just had a look at your js... and wow... just thinking "So many infos ! So much to learn from this !... but when ?.... and when will i get back to real life, now ? :smiley: "

Thank you very much for sharing this :+1:

1 Like

Just wondering - did you ever get through this little bug?…

If you didn’t I have finally got round to looking at it and have solved it in my CM now - track name extreatted cleanly every time, with no offset or random characters, even when going from midi to instrument or audio tracks… let me know and I’ll post if you need it.


Sure you can post your solution, it will help anybody :ok_hand:

Here you go - it's all down to how the MCU reads and erases characters on the LCD screen - if it knows that there are characters from the previous track it will send spaces, so you have to trim these off.

Here is the full function which you need to call:
  function getTrackName(sysExVal) {

    var nameDone = false

        var d = sysExVal.split(" ").slice(6).map(x => parseInt(x, 16)) //this devides up using  .split, then slices off the front 6 elements,  and x => parseInt(x, 16) converts the rest from Hex to Int then .map creates the array d[]
         pos = d[0] // first byte -> position // hex to int

        console.log("position = " + pos)
        //console.log("sysExVal = " + sysExVal)
        text = d.slice(1).map(x => String.fromCharCode(x))// these are the new characters which are updated on the console, the rest -> updated characters
        if (pos < 29) {

            return trackNameJoined
    text.pop() // drop sysex closing byte                    
    trackName = text.join('')

        //MCU only sends what it needs so you need to buffer the previous name and use parts of that
        //Check the length of the new name vs the buffer
        nameLengthCheck = bufferTrackName.length - trackName.length

        //MCU sends some sysex data to tell the screen where to start showing the new characters
        //This is related to the root position on the screen which is 72

        //Check if root position matches the position where the characters are to be placed
        charFromStart = pos - rootPosLCD

        var lengthCheck = charFromStart + trackName.length

    if (lengthCheck < 29) {

        let newEndLength = 29 - charFromStart - trackName.length

        newEnd = bufferTrackName.substring(bufferTrackName.length - newEndLength)

    } else { newEnd = "" }

    if (pos == 72) {       //Full length name received

        trackNameJoined = trackName + newEnd
        bufferTrackName = trackNameJoined
        posBuffer = pos
        // console.log('TrackName Joined = ' + trackNameJoined)

        nameDone = true

    } else if (pos > posBuffer && posBuffer == 72 && nameDone == false) {

        keepStringVal = pos - posBuffer  //new name follows a full string text

        var prevTrackKeep = bufferTrackName.substring(0, keepStringVal)

        trackNameJoined = prevTrackKeep + trackName + newEnd
        bufferTrackName = trackNameJoined
        posBuffer = pos
        nameDone = true

    } else {

        keepStringVal = pos - rootPosLCD  //new name follows a full string text

        var prevTrackKeep = bufferTrackName.substring(0, keepStringVal)

        trackNameJoined = prevTrackKeep + trackName + newEnd
        bufferTrackName = trackNameJoined
        posBuffer = pos
        nameDone = true


        //MCU will sometimes send the characters (MIDI) as part of the track name
        //so you need to strip these out
    const findMidiTag = '(';

    var posMidiTag ="\\(M");
    var posBrackTag ="\\(");

        if (posBrackTag == trackNameJoined.length - 1) {

            trackNameJoined = trackNameJoined.substring(0, (posBrackTag - 1))


        if (posMidiTag > -1) {

            trackNameJoined = trackNameJoined.substring(0, (posMidiTag - 1))


        //trim off all the spaces at the end

        trackNameJoined = trackNameJoined.trimEnd();

        return trackNameJoined


Thanks for sharing the solution. I'm new to OSC and my template only consists of some basic buttons so far triggering commands using Generic Remote. This is way over my head but I'm determined to implement this eventually! Curious @Sub3OneDay what your OSC template looks like.

Welcome to the fun Echo_7...

Since you ask, have a look here:

Something that I made With OSC

Some Extracts from My OSC Panel

Wow that's incredible! The Albion look is awesome haha. I'm sure you spent a while on those visualizations, but it looks really great. I may have to bother you at some point if I struggle with the expression maps! :slight_smile:

1 Like

Feel free to ask away - but be warned - OSC is a black hole... I used to be a composer - I'm now an OSC hobbyist...


Thank you for your great work!!
I'll have to ask a dumb question..
How excatly do I use this in OSC? :joy: :face_holding_back_tears:

After getting to know OSC
I'm always trying to get a better and even better solution for something...
There're just way too much knowledge to learn

I know I'll have to load this in the "custom module".
But after that, what's next?
In the server page, do I need to create a new session?

There is quite a lot on the forum already about Using custom modules generally but I'm (very slowly as busy) trying to pull together a step by step on how to implement this specific solution which I will post when done.


Hey Sylvain! :sob:

Could you plz tell me how do excatly do you use the custom module to read from cubase?

I'm totally new to the custom module.... I've read all the reply in this post, but still don't know how to get it to work. :sob:

And can you plz tell me how do you use osc to remote control the expression map of cubase?

People in this post seems always be talking about reading from cubase. But no one seems to be talking about how to control the expression maps :face_holding_back_tears:

I'd be very glad if you can help me, even just give me some clues

Thanks in advance!


first: very nice work !!!!! At all out there.

I have some questions:

how does the text widget get the data from the custom module?

And if i implement the node module xml2json i get a big err in my osc console?

It would be nice to get some help.


Alright. Now i have setting everything up with node and the custom module.

With the script widget i can read out the Track names from cubase but i can not read out stuff from the custom modul.

Can someone please help me with this? Thx a lot for the help

Hi Sylvain,

very nice work with the MatrixButtons.

Can you please help me where my problem is?

I have set up your project with your custom modul. I have installed the node modules xml2js and glob in my custom modul folder and set the right path for glob and the Expression Map

I get the the first text_1 from Cubase with little glitches but ok.
Text_2 makes nothing (recieved from xml)
And no Buttons on the grid.. I have the one expression map in cubase loaded.

Can you please help me were my mistake is?
Thank you very much


As for the text-2 widget, how did you name your expression maps ?
For me, using this : AmpleSound - ASBU - Bass Upright.expressionmap shows ASBU in text_2.


I'm really sorry Barry, but right now i'm "out from o-s-c"... i've spent too much time on it (actually... months... learning everything from 0...)... Custom module is a huge piece i do not master, and to help you with what i know, i would have to dig again into it... but now, i... just can't... I just need to turn off my pc, and have a big big break...

I'll be back for sure, and will be pleased to help you... as soon as possible...

In the meanwhile, have fun exploring this amazing piece of software ! (and don't forget to go for a walk...)

1 Like