MIDI Remote API. How can I tell which control was changed?

So I started making my remote script now finally, and I am running into a few things I can’t figure out.

Say in the case that I have 2 controls that are controlling the same thing.
For ease of explaining:
knob 1 controls Selected Track Volume
knob 2 also controls Selected Track Volume

If I turn knob 1 I only want to send midi to knob 2 to update its position on my controls, similarly if I turn knob 2 I want to send midi to knob 1.

I have events set up to handle changes:
"knob2.mSurfaceValue.mOnProcessValueChange = function (context, newValue) " etc…
However, a change in knob 2 will then fire both the event for knob 1 and knob 2, but they happen simultaneously, and they seem to be fired in the order the knobs were created. So I can’t tell which of knob1 or knob2 actually was physically turned.

Is there any means to figure this out? Can I somehow read which midi cc was sent from my controller?

In short, I want to create a behaviour where I only send midi to controls mapped to the same function, but not to the control that is physically moved.
Can I do this in a somewhat easy way?

The way I did it was to use virtual midi cable and a midi monitor outside of cubase. Run the controller through the virtual cables and midi monitor then into cubase.

Judging from your previous posts that is probably enough information but if you need more then just ask.

1 Like

Ah yeah, in this particular case, I actually moved on to making the whole thing in javascript, and trying to make it work with a single controller (but the potential for multiple controls changing the same parameters exist, so I wanted to see how I can work around that).

I.e. I want to ensure that a changed parameter in Cubase sends to the physical control that is bound to the parameter, but at the same time, if the parameter is changed by a certain physical control, I want to avoid it feeding back midi to itself, which is part of what causes the jitter when controlling.

I did actually solve it in a way that I’m continuing to experiment on today.

How I did it was setting up a custom value variable that is the physical control, and that in turn controls a knob in the Cubase Midi Remote API.
That let’s me control if the parameter changed is my specific physical controller. Kinda tricky, but seems to work so far.
My plan is to simplify it a bit now, but so far I removed all my issues I experienced with the Midi Remote Editor GUI. Everything is rounded correctly, no midi feedback, and no delayed messages causing wonky jitter.

I made a generic function for creating a “smart” knob controller in Cubase now, and it will be extremely easy to adapt to faders etc… I tried it out a bit now, and there’s no jitter that I’m noticing, no extra delayed messages, no feedback to the sending controller, no rounding errors.

This is the rough one I got so far, and it should be easily adapted into anyones script if they want to have a go:

function makeSmartKnob (name, midi_channel, midi_cc, x,y, w, h, hostValue)
{
	var knob_physical = deviceDriver.mSurface.makeCustomValueVariable(name)
	var knob_cubase = deviceDriver.mSurface.makeKnob(x, y, w, h)

	var knob_prev_value = -1
	var knob_prev_value_physical = -1
	var knob_prev_value_cubase = -1

	knob_physical.mMidiBinding
		.setInputPort(midiInput)
		.setIsConsuming(true)
		.bindToControlChange (0, midi_cc)

	page.makeValueBinding(knob_cubase.mSurfaceValue, hostValue)


	knob_physical.mOnProcessValueChange = function (context, newValue)
	{
		knob_prev_value_physical = knob_prev_value
		if(knob_prev_value!=newValue)
		{
			knob_cubase.mSurfaceValue.setProcessValue(context,newValue)
			knob_prev_value = newValue
		}
	}
	knob_cubase.mSurfaceValue.mOnProcessValueChange = function (context, newValue, oldValue) 
	{
		if(knob_prev_value_cubase != newValue)
		{
			knob_prev_value_cubase = newValue
			var knob_midi_value = Math.round(newValue*127.0)
			var knob_prev_midi_value = Math.round(knob_prev_value*127.0)

			if(knob_midi_value!=knob_prev_midi_value)
			{
					midiOutput.sendMidi(context,  [176+midi_channel, midi_cc, knob_midi_value])
					knob_prev_value_physical = newValue
			}
		}
	}
}

This can then just be called like this, and it’ll create a knob at a given position, width/height, mapped to a midi channel+cc of your choice, as well as mapped to the corresponding control in Cubase.
You call it like this, and that should be all that you need to do for it to appear in Cubase.

makeSmartKnob("External encoder", 0, 81, 1, 0, 1, 1, page.mHostAccess.mMouseCursor.mValueUnderMouse)
makeSmartKnob("Macropad encoder", 0, 13, 0, 0, 1, 1, hostSelectedTrackChannel.mValue.mVolume)
1 Like