Your code is 99% correct. The issue comes from the setOutputPort of the mute/solo/arm buttons. We need to handle the messages sent to our controller without respecting this mirroring.
I’ve altered your script, removed the setOutputPort from these buttons, and added functions for sending the MIDI messages expected by the controller. No other changes were made. Give it a try and let me know if it now works correctly.
//-----------------------------------------------------------------------------
// 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('icon', 'Platform X Plus', 'Greyboxaudio')
// create objects representing the hardware's MIDI ports
var midiInput = deviceDriver.mPorts.makeMidiInput()
var midiOutput = deviceDriver.mPorts.makeMidiOutput()
// define all possible names the device's MIDI ports could have
// NOTE: Windows and macOS handle port naming differently
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
.expectInputNameEquals('Platform X+1 V2.13')
.expectOutputNameEquals('Platform X+1 V2.13')
deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput)
.expectInputNameEquals('Platform X+1 V2.13 (MIDI IN)')
.expectOutputNameEquals('Platform X+1 V2.13 (MIDI OUT)')
//-----------------------------------------------------------------------------
// 2. SURFACE LAYOUT - create control elements and midi bindings
//-----------------------------------------------------------------------------
var knobs = []
var faders = []
var buttonsSelect = []
var buttonsMute = []
var buttonsSolo = []
var buttonsRec = []
var numChannels = 8
for (var channelIndex = 0; channelIndex < numChannels; ++channelIndex) {
var defaultMult = 3
var offset = 2
var knob = deviceDriver.mSurface.makePushEncoder(channelIndex * defaultMult, 0, 2, 2)
knob.mEncoderValue.mMidiBinding
.setInputPort(midiInput).setOutputPort(midiOutput)
.bindToControlChange(0, 16 + channelIndex)
.setTypeRelativeSignedBit()
knob.mPushValue.mMidiBinding
.setInputPort(midiInput).setOutputPort(midiOutput)
.bindToNote(0, 32 + channelIndex)
knobs.push(knob)
var fader = deviceDriver.mSurface.makeFader(channelIndex * defaultMult + 0.5, 2, 1, 6)
fader.mSurfaceValue.mMidiBinding
.setInputPort(midiInput).setOutputPort(midiOutput)
.bindToPitchBend(0 + channelIndex)
faders.push(fader)
var buttonSelect = deviceDriver.mSurface.makeButton(channelIndex * defaultMult + offset, 4, 1, 1)
buttonSelect.mSurfaceValue.mMidiBinding
.setInputPort(midiInput).setOutputPort(midiOutput)
.bindToNote(0, 24 + channelIndex)
buttonsSelect.push(buttonSelect)
var buttonMute = deviceDriver.mSurface.makeButton(channelIndex * defaultMult + offset, 5, 1, 1)
buttonMute.mSurfaceValue.mMidiBinding
.setInputPort(midiInput)
.bindToNote(0, 16 + channelIndex)
buttonsMute.push(buttonMute)
var buttonSolo = deviceDriver.mSurface.makeButton(channelIndex * defaultMult + offset, 6, 1, 1)
buttonSolo.mSurfaceValue.mMidiBinding
.setInputPort(midiInput)
.bindToNote(0, 8 + channelIndex)
buttonsSolo.push(buttonSolo)
var buttonRec = deviceDriver.mSurface.makeButton(channelIndex * defaultMult + offset, 7, 1, 1)
buttonRec.setShapeCircle()
buttonRec.mSurfaceValue.mMidiBinding
.setInputPort(midiInput)
.bindToNote(0, 0 + channelIndex)
buttonsRec.push(buttonRec)
}
//-----------------------------------------------------------------------------
// 3. HOST MAPPING - create mapping pages and host bindings
//-----------------------------------------------------------------------------
var page = deviceDriver.mMapping.makePage('Example Mixer Page')
var hostMixerBankZone = page.mHostAccess.mMixConsole.makeMixerBankZone()
.excludeInputChannels()
.excludeOutputChannels()
var previousMuteSoloArmValues=[
[-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1]
]
for (var channelIndex = 0; channelIndex < numChannels; ++channelIndex) {
var hostMixerBankChannel = hostMixerBankZone.makeMixerBankChannel()
var knobEncoderValue = knobs[channelIndex].mEncoderValue;
//var knobPushValue = knobs[channelIndex].mPushValue;
var faderSurfaceValue = faders[channelIndex].mSurfaceValue;
var buttonSurfaceValue = buttonsSelect[channelIndex].mSurfaceValue;
var buttonMuteSurfaceValue = buttonsMute[channelIndex].mSurfaceValue;
var buttonSoloSurfaceValue = buttonsSolo[channelIndex].mSurfaceValue;
var buttonRecSurfaceValue = buttonsRec[channelIndex].mSurfaceValue;
page.makeValueBinding(knobEncoderValue, hostMixerBankChannel.mValue.mPan)
page.makeValueBinding(faderSurfaceValue, hostMixerBankChannel.mValue.mVolume)
page.makeValueBinding(buttonSurfaceValue, hostMixerBankChannel.mValue.mSelected)
page.makeValueBinding(buttonMuteSurfaceValue, hostMixerBankChannel.mValue.mMute).setTypeToggle()
page.makeValueBinding(buttonSoloSurfaceValue, hostMixerBankChannel.mValue.mSolo).setTypeToggle()
page.makeValueBinding(buttonRecSurfaceValue, hostMixerBankChannel.mValue.mRecordEnable).setTypeToggle()
buttonRecSurfaceValue.mOnProcessValueChange=function(activeDevice,value,diff){
setNewState(activeDevice,0,this.channelIndex,value)
}.bind({channelIndex})
buttonSoloSurfaceValue.mOnProcessValueChange=function(activeDevice,value,diff){
setNewState(activeDevice,1,this.channelIndex,value)
}.bind({channelIndex})
buttonMuteSurfaceValue.mOnProcessValueChange=function(activeDevice,value,diff){
setNewState(activeDevice,2,this.channelIndex,value)
}.bind({channelIndex})
}
function setNewState(activeDevice,recSoloMute,index,value){
//recSoloMute: 0=Rec, 1=Solo, 2=Mute
var prevVal=previousMuteSoloArmValues[recSoloMute][index]
if(value!=prevVal){
previousMuteSoloArmValues[recSoloMute][index]=value
midiOutput.sendMidi(activeDevice,[0x90,8*recSoloMute+index,127*value])
}
}