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

I had suspected this might be the case. I wonder if there is a way to soft reset the cubase side of MCU by sending some sysex back to trick cubase into resending all the bytes?

The difficulty I see with buffering is that it will be hard to know what has not been sent previously to therefore compare.
For example Cubase may send woodwinds track 1
Then the new track that comes in might be called
winds Track 2
or
woodwinds track 2
but sysex would say
winds Track 2

if it's called woodwinds track 2 you even only get back 2...

great idea. let's investigate :crazy_face:

We won't be the first - from a quick google there are a lot of people who have looked at MCU over the years!

Maybe, maybe I’ve just had a brainwave.

I think we now know that MCU sends only what it needs to send in terms of a track name to save bytes. Which means if you connected to a real unit it only ‘corrects’ on the LCD the characters it needs to on the units display when a new name is received.

Which means it will start the character string at a different point on the LCD unit and send in sysex where the correction starts...

Which means if we can buffer the names from previous track name sends and identify the MCU sysex string is to starts at a different point in the track name we just then to extract the bit from the old name that we need, and it add the new bit of the name creating the full track name again…

Does that make sense?!

this makes sense. i know what you mean. but how do we know if and where the next track name gets truncated?

I read it somewhere is some of the MCU documents somewhere but where is the next question!

From the cubase forum thread I’m reading Cubase forum posts on the topic

1 Like

if i send note 81 the console goes crazy...

tried with two buttons one for note 44 and the other note 81. doesn't work, unfortunately.

I haven’t tried yet but how are you sending the data?
be careful you’re not creating some sort of loop that keeps sending and receiving.

first i did it in the custom module, i guess there i had a loop going on. then i did it with a push button sending note 81.

That is the way it works

Any idea where it’s documented as to what part of the sysex shows where it’s to go?!

this script from earlier does exactly what we need but i have no idea how to integrate it into the custom module:

locals.text = locals.text || Array(112).fill(" ") // persistent variable to store full text

if (value.includes("f0 00 00 66 14 12")) { // sysex header for mackie lcd text

var d = value.split(" ").slice(6).map(x=>parseInt(x, 16)), // hex to int
    pos = d[0], // first byte -> position
    text = d.slice(1).map(x=>String.fromCharCode(x)) // rest -> updated characters

text.pop() // drop sysex closing byte

// update characters
for (var i = 0; i < text.length; i++) {
  locals.text[i + pos] = text[i] // update 
}


// update text widget
set("lcd_MODIFIED", locals.text.slice(72,101).join(""))
  
}

Here in custom module

1 Like

Also, I’ve solved the track name limitation (well nearly) just need to resolve something in the js around how I buffer the previous name…

Watch this space…

1 Like

:ghost: :ghost: :ghost:

this sounds promising.

AMAZING!!!

Just need to sort the logic and various IF conditions. It’s all to do with what’s left from the previous track name and what needs replacing…

And for my Friday gift to you all - working code that extracts full cubase track name with 29 characters...

//Sysex Track Variables

var trackName = "unpopulated"
var pos = 72
var rootPosLCD = 72
var keepStringVal = 0
var trackNameJoined = "unpopulated"
var bufferTrackName = "undefined"
var posBuffer = 72
var nameLengthCheck = 0
send('midi', 'MCU_From_OSC', '/note', 1, 44, 127);  //Send MCU command to swith to track name sending

module.exports = {

    oscInFilter:function(data){

        
        var { address, args, host, port } = data

       // if (host === 'midi' && port == 'MCU_To_OSC') {console.log('2MCU PING OCCOURED' + address)}

        // MCU TEST AREA HERE


        if (host === 'midi' && port === 'MCU_To_OSC' && address === '/sysex') {

           
            if (args[0].value.includes("f0 00 00 66 14 12")) { // sysex header for mackie lcd text

                var nameDone = false

                var sysExVal = args[0].value
                var d = sysExVal.split(" ").slice(6).map(x => parseInt(x, 16))
               // console.log('d = ' + d)
                pos = d[0] // first byte -> position // hex to int
                    //console.log('pos = ' + pos)
                text = d.slice(1).map(x => String.fromCharCode(x)) // rest -> updated characters
                text.pop() // drop sysex closing byte                    
                trackName = text.join('')
            
                nameLengthCheck = bufferTrackName.length - trackName.length
                charFromStart = pos - rootPosLCD 

                var lengthCheck = charFromStart + trackName.lenth

                if (lengthCheck < 29) {

                    let newEndLength = 29 - charFromStart - trackName.length

                    newEnd = bufferTrackName.substring(bufferTrackName.length - newEndLength)
                } else {newEnd = ""}
                



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


                    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

                    console.log('TrackName Joined = ' + trackNameJoined);

                } 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

                    console.log('TrackName Joined = ' + trackNameJoined);

                        }
            }

           

            

           
        }
//END MCU TEST AREA


        return {address, args, host, port}
        
    },

	oscOutFilter: function (data) { 		// Filter incomming osc messages

		var { address, args, host, port } = data




    return data  //End of OSC out Filter here
	}
}

Edit: Any bugs or problems let me know. It's probably not the most efficient code and could do with tidying up but it works on my machine...

Edit: there is a way better solution further down the thread with the bugs ironed out here Better solution here

2 Likes

this is brilliant! thanks so much for this. all working. YESSS!

now the thread deserves its title.