Hello,
does anyone know a way to bind sysex values to a surface element and then transfer it to the host?
I have a Roland VM C7x00 and would like to transfer the “time values” (MMC) of the console to Cubase via the MIDI Remote API. Basically, the MMC device control of the Roland VM C7x00 works with Cubase!
Reading the sysex data is not my problem, I have the values in Console.log() and in variables but how do I bind them to a surface element?
Here is my code, including the 16 faders:
// 0. Custom Functions
// global time var's
var tHour = 0;
var tMin = 0;
var tSec = 0;
var tFrame = 0;
// check time sysex
function isSysexTimeMsg(sysexMsg)
{
// 12 bytes
var needLenght = 12;
// 240 127 127 6 68 6 1
var sFirst = [0xF0, 0x7F, 0x7F, 0x06, 0x44, 0x06, 0x01] ; // 7 bytes
if( Array.isArray(sysexMsg) && sysexMsg.length === needLenght+1 )
{
// check last byte, 247DEZ
if( sysexMsg[needLenght] !== 0xF7 ){
return false;
}
// check first bytes
for( var i = 0; i< sFirst.length; i++ )
{
if( sysexMsg[i] !== sFirst[i] ){
return false;
}
}
// if allright then: get Time now
tHour = sysexMsg[sFirst.length+0] - 0x20; // default 0 is 32Dez (0x20HEX) then sub 32 = result ist hour
tMin = sysexMsg[sFirst.length+1];
tSec = sysexMsg[sFirst.length+2];
tFrame = sysexMsg[sFirst.length+3];
console.log("Time: " + tHour + ":"+ tMin +":"+ tSec +":"+ tFrame );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// 1. DRIVER SETUP - create driver object, midi ports and detection information
//-----------------------------------------------------------------------------
// get the api's entry point
var midiremote_api = require('midiremote_api_v1');
// create the device driver main object
var deviceDriver = midiremote_api.makeDeviceDriver('Roland', 'VM-C7x00', 'Pierre Babeck');
// create objects representing the hardware's MIDI ports
var midiInput = deviceDriver.mPorts.makeMidiInput();
// Egal welches Device
deviceDriver.makeDetectionUnit();
//-----------------------------------------------------------------------------
// 2. SURFACE LAYOUT - create control elements and midi bindings
//-----------------------------------------------------------------------------
var knobs = []
var faders = []
//var labels = []
var numChannels = 16
for(var ci = 0; ci < numChannels; ci++) {
var knob = deviceDriver.mSurface.makeKnob(ci * 2, 0, 2, 2) // position x : number, y : number, w : number, h : numbe
knob.mSurfaceValue.mMidiBinding
.setInputPort(midiInput)
//.setOutputPort(midiOutput)
.bindToControlChange (ci, 10) // Chanel 0-16, CC 10 PAN
knobs.push(knob)
var fader = deviceDriver.mSurface.makeFader(ci * 2 + 0.5, 2, 1, 6) // position
// Label direkt an den Fader, muss dann nicht extra aufgerufen werden
var label = deviceDriver.mSurface.makeLabelField(ci * 2, 8, 2, 1) // position
label.relateTo(fader);
fader.mSurfaceValue.mMidiBinding
.setInputPort(midiInput)
//.setOutputPort(midiOutput)
.bindToControlChange (ci, 7) // Chanel 0-16, CC 7 VOL
faders.push(fader)
//var label = deviceDriver.mSurface.makeLabelField(ci * 2 + 0.5, 8, 2, 1) // position
//labels.push(label);
//console.log("Layout x: " + (ci * 2) + " y: " + 8); // 16 *2 => x ist 30
}
// Time knop
var timeKnob = deviceDriver.mSurface.makeKnob(32, 6, 4, 4) ;
//timeKnob.mSurfaceValue.
//-----------------------------------------------------------------------------
// 3. HOST MAPPING - create mapping pages and host bindings
//-----------------------------------------------------------------------------
// create at least one mapping page
var pageMixer1_16 = deviceDriver.mMapping.makePage('Mixer Page 1-16')
var locator = pageMixer1_16.mHostAccess.mTransport.mTimeDisplay.mPrimary.mTransportLocator;
//locator.setTime(timeKnob.activeMapping, "0:02:05.000");
console.log("Locator: ");
var output = '';
for (var property in locator) {
output += property + ': ' + locator[property]+'; ';
}
console.log(output);
// create host accessing objects
// https://steinbergmedia.github.io/midiremote_api_doc/codedoc_api_reference/#mixerbankzone
var hostMixerBankZone = pageMixer1_16.mHostAccess.mMixConsole.makeMixerBankZone()
.includeAudioChannels()
.includeInputChannels()
.includeOutputChannels()
for(var ci = 0; ci < numChannels; ci++) {
// wird automatisch iteriert
var channelBankItem = hostMixerBankZone.makeMixerBankChannel();
var knobSurfaceValue = knobs[ci].mSurfaceValue;
var faderSurfaceValue = faders[ci].mSurfaceValue;
pageMixer1_16.makeValueBinding(knobSurfaceValue, channelBankItem.mValue.mPan).setValueTakeOverModePickup();
pageMixer1_16.makeValueBinding(faderSurfaceValue, channelBankItem.mValue.mVolume).setValueTakeOverModePickup();
// labels wenn nicht "relateTo to fader"
// pageMixer1_16.setLabelFieldHostObject(labels[ci], channelBankItem);
console.log("Mapping " + (ci) );
}
// Time Knob
//pageMixer1_16
// ex: page.makeCommandBinding(surfaceElements.transport.prevBnk.mSurfaceValue, 'Transport', 'Locate Previous Marker')
// Sysex Midi In Event, Callback Funktion !?
midiInput.mOnSysex = function (activeDevice, sysexMsg)
{
// set
activeDevice.setState('getSysex', 'true');
if(isSysexTimeMsg(sysexMsg) === true){
console.log("Sysex TIME OK " );
//pageMixer1_16
}
// get
activeDevice.getState("getSysex");
}
The “isSysexTimeMsg(sysexMsg)” function checks a sysex Msg for “time” information and writes the values to global variables like “tHour”, “tMin” etc. The function is called by “midiInput.mOnSysex = function (activeDevice, sysexMsg)”. How can the values now be transferred to the “timeKnob”, for example?