MSL #continuous Directive
This is one I threw in for @gustebeast
When you put the #continuous directive in an MSL script, it means that the script will behave like a parameter rather than a function. Most scripts behave like functions. You bind them to a control that has a press and a release and you can have the script do different things when the control is held down, or it is "clicked" multiple times rapidly.
For some things though, you would like to bind the script to a rotary controller rather than a pushbutton, and have the script run every time the controller changes its value. This can be used for a number of things, you might want to invert or constrain the range of values the controller is sending. Or if the controller is "stepped" you can use each step to behave like a function and have one script that does multiple things depending on which step the controller is on.
#continuous scripts will be called every time the CC value of the bound MIDI event changes. Normally they are only called on CC 127 (down) and CC 0 up. To do something interesting you need to know what the MIDI event was that caused this script to run. This is done through a few new variables that are passed into the script:
triggerSource - the name of the source that caused this event: midi, key, button, some others
triggerType - note, control, program
triggerChannel - raw MIDI channel starting from zero
triggerNumber - note, program, or controller number
triggerValue - note velocity, or CC value
Here is an example that just prints the value of a CC.
#name CCMe
#continuous
print (triggerValue)
Add this as a script, bind it to any controller that produces CCs, open the Script->Console window and twist the knob. you should see lots of numbers in the console.
A problem I've had with this is that CCs have a value from 0 to 127, but I'm only interested in a few different outcomes, such as setting the value of an enumerated parameter like QuantizeMode that has 4 possible values. To set those 4 values with a CC you would have to divide the full range of 128 CC values into 4 regions where values 0-31 means first, and 32-63 means second, etc. Then as you twist the knob from 0 to 127 you can select each of the 4 possible values without cramming them all at the beginning which would be very difficult to control accurately. This BTW is how CC or host bindings to parameters work. It accepts the full range of 128 values then scales that down to fit the possible value range of the parameter.
To make this easier in a script I added a built-in script function ScaleMidi that takes three arguments:
the value to scale (usually the value of triggerValue)
the lowest number you want to use
the highest number you want to use
For example:
#CCMe Slowly
#continuous
print(ScaleMidi(triggerValue 1 5))
ScaleMidi takes the triggerValue from 0 to 127 and returns a value from 1 to 5 spread evenly through the range.
For @gustebeast this could be used to select Snapshots to load using a CC. Use the triggerValue, either scaled or unscaled and convert that into a snapshot name:
var snapshotName = "snapshot-" + ScaleMidi(triggerValue 1 4)
print("I'm about to load snapshot" snapshotName)
LoadSnapshot snapshotName
With that you need to go to your snapshot list and give 4 of them the names: snapshot-1, snapshot-2 etc
You can also call LoadSnapshot with just a number, which will be used as an index into the snapshot list starting from 0