OK, back.
Here’s a snippet for changing BPM using a knob set to CC 24 - Channel 0 - TwosComplement, while at the same time inserting the new BPM at cursor. This will work as long as we are on the Tempo Track.
I’ve followed the instructions given by @Phil_Pendlebury, however instead of creating a PLE (not possible in midi remote) I’ve created a sequence of commands to execute.
I’ve done some pretty basic testing, seems to work well here, but who knows? However, it can give some ideas to anyone interested into this approach.
var midiremote_api = require('midiremote_api_v1')
var deviceDriver = midiremote_api.makeDeviceDriver('Intro', 'Script BPM', 'Someone')
var midiInput = deviceDriver.mPorts.makeMidiInput("midiInput")
var midiOutput = deviceDriver.mPorts.makeMidiOutput("midiOutput")
var detect = deviceDriver.makeDetectionUnit()
detect
.detectPortPair(midiInput, midiOutput)
.expectInputNameContains('your midi input name or part of it')
.expectOutputNameContains('your midi output name or part of it')
var surface=deviceDriver.mSurface
var knobBPM=surface.makeKnob(0,0,1,1)
knobBPM.mSurfaceValue.mMidiBinding
.setInputPort(midiInput)
.bindToControlChange(0,24)
.setTypeRelativeTwosComplement()
var page=deviceDriver.mMapping.makePage("page")
var delayMS=10
var timeStampForKnob=0
var bpmStep=1
page.mHostAccess.mTransport.mTimeDisplay.mOnChangeTempoBPM=function(activeDevice,activeMapping,BPM){
activeDevice.setState("BPM",""+BPM)
}
var customVarBPMUp=surface.makeCustomValueVariable("customVarBPMUp")
var customVarBPMDown=surface.makeCustomValueVariable("customVarBPMDown")
var dummyBPMUp=page.mCustom.makeHostValueVariable("dummyBPMUp")
var dummyBPMDown=page.mCustom.makeHostValueVariable("dummyBPMDown")
var ourSequence=[['Navigate','Right'],['Edit','Copy'],['Edit','Paste'],['Transport','Enter Tempo']]
var ourSequenceLength=ourSequence.length
var ourSequenceCustomVars=[]
for(var i=0;i<ourSequenceLength;i++){
var customSequenceStepVar=surface.makeCustomValueVariable("customSequenceStepVar"+i)
ourSequenceCustomVars.push(customSequenceStepVar)
}
for(var i=0;i<ourSequenceLength;i++){
page.makeCommandBinding(ourSequenceCustomVars[i],ourSequence[i][0],ourSequence[i][1]).mOnValueChange=function(activeDevice,activeMapping,value,diff){
var i=this.i
if(i<this.ourSequenceLength-1){
i++
ourSequenceCustomVars[i].setProcessValue(activeDevice,1-ourSequenceCustomVars[i].getProcessValue(activeDevice))
} else {
ourSequenceCustomVar.setProcessValue(activeDevice,1-ourSequenceCustomVar.getProcessValue(activeDevice))
}
}.bind({i,ourSequenceLength})
}
var ourSequenceCustomVar=surface.makeCustomValueVariable("ourSequenceCustomVar")
var finalBPMDummyHostValue=page.mCustom.makeHostValueVariable("finalBPMDummyHostValue")
page.makeValueBinding(ourSequenceCustomVar,finalBPMDummyHostValue).mOnValueChange=function(activeDevice,activeMapping,value,diff){
var newBPMInt=parseInt(activeDevice.getState("newBPM"))
page.mHostAccess.mTransport.mTimeDisplay.setTempoBPM(activeMapping,newBPMInt)
}
knobBPM.mSurfaceValue.mOnProcessValueChange=function(activeDevice,value,diff){
var currentStamp=new Date().getTime()
if (currentStamp<timeStampForKnob+delayMS){
return
}
timeStampForKnob=currentStamp
if(diff<0 || value==0){
customVarBPMDown.setProcessValue(activeDevice,1-customVarBPMDown.getProcessValue(activeDevice))
} else {
customVarBPMUp.setProcessValue(activeDevice,1-customVarBPMUp.getProcessValue(activeDevice))
}
}
page.makeValueBinding(customVarBPMUp,dummyBPMUp).mOnValueChange=function(activeDevice,activeMapping,value,diff){
updateBPM(activeDevice,1)
}
page.makeValueBinding(customVarBPMDown,dummyBPMDown).mOnValueChange=function(activeDevice,activeMapping,value,diff){
updateBPM(activeDevice,-1)
}
function updateBPM(activeDevice,direction){
var BPMInt=parseInt(activeDevice.getState("BPM"))
var newBPM=BPMInt+direction*bpmStep
if(!(newBPM>360 || newBPM<1)){
activeDevice.setState("newBPM",""+newBPM)
ourSequenceCustomVars[0].setProcessValue(activeDevice,1-ourSequenceCustomVars[0].getProcessValue(activeDevice))
}
}