Earlier today, while replying to another fellow user, I recalled that there were many times when I needed to show tracks of the same “type”, for example, just Keys, Base, Drums, etc.
I did this successfully using a bunch of PLE presets.
But after my reply, I though about it again, and came to the conclusion that with recent updates to the MIDI Remote API, I could actually do something less time-consuming than having/adding PLEs for this purpose. Selecting a track and then filtering my project window for tracks that have the very same starting word, would do the trick pretty well, and I would no longer have to do the above tedious operation.
Now, I know that I can always have just one PLE, and then bring it up, type the letters of the word(s) I want to filter by, still, simply clicking and executing a “command” is faster, at least the way I see it.
Anyway, I’ve prepared a MIDI Remote Script which in conjunction with a Process Logical Editor preset does just exactly this. I select a track, trigger a MIDI CC (Channel 0, Num. 20) connected to my MIDI Remote, then the latter filters out the tracks for the very first one (or two) words of the selected track’s name, triggers a PLE and I’m all set!
Here’s the snippet used:
//Finding tracks with a name having the same first word as the selected track's name, and showing just these
//CC 0,20 is for finding tracks with the first word of their name equals the one of the selected track, CC 0,21 for tracks with the two first words equal the ones of the selected track and CC 0,22 for showing all tracks (Visibility option)
var midiremote_api = require('midiremote_api_v1')
var deviceDriver = midiremote_api.makeDeviceDriver("Test","Show Tracks With The Same Prefix","m.c")
var midiInput = deviceDriver.mPorts.makeMidiInput("anInput")
var midiOutput = deviceDriver.mPorts.makeMidiOutput("anOutput")
var detectionUnit=deviceDriver.makeDetectionUnit()
detectionUnit.detectPortPair(midiInput, midiOutput)
.expectInputNameEquals("an input")
.expectOutputNameEquals("an output")
var surface=deviceDriver.mSurface
var mapping=deviceDriver.mMapping
var customVar=surface.makeCustomValueVariable("customVar")
customVar.mMidiBinding
.setInputPort(midiInput)
.bindToControlChange(0,20)
var customVar2=surface.makeCustomValueVariable("customVar2")
customVar2.mMidiBinding
.setInputPort(midiInput)
.bindToControlChange(0,21)
var customPLEVar=surface.makeCustomValueVariable("customPLEVar")
var customPLEDelayVar=surface.makeCustomValueVariable("customPLEDelayVar")
var customShowAllTracksVar=surface.makeCustomValueVariable("customShowAllTracksVar")
customShowAllTracksVar.mMidiBinding
.setInputPort(midiInput)
.bindToControlChange(0,22)
var page=mapping.makePage("page")
var currentMapping
page.mOnActivate=function(activeDevice,activeMapping){
currentMapping=activeMapping
}
var selectedTrack=page.mHostAccess.mTrackSelection.mMixerChannel
var selectedTrackNamePrefix=""
var selectedTrackNamePrefix2=""
var prefixForThePLE="(prefix)"
var selectedTrackID
var mixer=page.mHostAccess.mMixConsole
var daMixer=page.mHostAccess.makeDirectAccess(mixer)
selectedTrack.mOnTitleChange=function(activeDevice,activeMapping,title){
selectedTrackNamePrefix = ((title && title.trim().split(/\s+/)[0]) || "").toLowerCase()
selectedTrackNamePrefix2=(title && title.trim().split(/\s+/).slice(0, 2).join(" ")) || ""
selectedTrackID=selectedTrack.getRuntimeID(currentMapping)
}
customVar.mOnProcessValueChange=function(activeDevice,value,diff){
if(value==1){
findPrefix(activeDevice,selectedTrackNamePrefix)
}
}
customVar2.mOnProcessValueChange=function(activeDevice,value,diff){
if(value==1){
findPrefix(activeDevice,selectedTrackNamePrefix2)
}
}
function findPrefix(activeDevice,prefix){
var mixerID=daMixer.getBaseObjectID(currentMapping)
var numOfChildren=daMixer.getNumberOfChildObjects(currentMapping,mixerID)
if(numOfChildren>0 && selectedTrackNamePrefix.length>0){
var countFound=0
for(var i=0;i<numOfChildren;i++){
var childID=daMixer.getChildObjectID(currentMapping,mixerID,i)
var childTitle=daMixer.getObjectTitle(currentMapping,childID).toLowerCase()
if(childTitle.indexOf(prefix)==0){
daMixer.setParameterDisplayValue(currentMapping,childID,1024,prefixForThePLE+childTitle)
countFound++
}
}
if(countFound>1){
//if just one track found, means its our selected track, no reason to proceed
customPLEVar.setProcessValue(activeDevice,1)
}
}
}
page.makeCommandBinding(customPLEVar,"Process Project Logical Editor","20250629_showTracksPrefixed").mOnValueChange=function(activeDevice,activeMapping,value,diff){
if(value==1){
customPLEDelayVar.setProcessValue(activeDevice,5)
customPLEVar.setProcessValue(activeDevice,0)
}
}
customPLEDelayVar.mOnProcessValueChange=function(activeDevice,value,diff){
value--
if(value>0){
customPLEDelayVar.setProcessValue(activeDevice,value)
} else {
var mixerID=daMixer.getBaseObjectID(currentMapping)
var numOfChildren=daMixer.getNumberOfChildObjects(currentMapping,mixerID)
if(numOfChildren>0){
for(var i=0;i<numOfChildren;i++){
var childID=daMixer.getChildObjectID(currentMapping,mixerID,i)
var childTitle=daMixer.getObjectTitle(currentMapping,childID)
if(childTitle.indexOf(prefixForThePLE)==0){
daMixer.setParameterDisplayValue(currentMapping,childID,1024,childTitle.substring(prefixForThePLE.length))
}
}
}
daMixer.setParameterProcessValue(currentMapping,selectedTrackID,4000,1)
}
}
page.makeCommandBinding(customShowAllTracksVar,"Channel & Track Visibility", "ShowAll")
And a screenshot of the PLE preset needed:
Here’s a small clip demonstrating the use case:
For anyone wanting to get into it, I share the midiRemote file:
Test_Show Tracks With The Same Prefix.midiremote (2.1 KB)
And the PLE preset file:
20250629_showTracksPrefixed.xml (4.6 KB)
Note: As seen in the tags, this script will only work with CB13.0.51 and above.