Subroutines allow you to hive off oft-used code into a separate block that you then call from your script later to re-use. Subroutines can have their own arguments that get set when the code runs.
You define a subroutine as follows:
if load subroutine <subroutine name> [<subroutine args> ...] # multi line subroutine code end end
Then when you want to use the subroutine in your code, you just use the subroutine name as the first word of the rule and (optionally) pass some arguments:
if load # send a CC given a channel, number and value subroutine sendCC channel number value math i0 = B0 + channel send I0 number value end end
# send all notes off on MIDI stop to all channels if M0 == FC ass L0 = 0 while L0 < $16 sendCC L0 $123 00 mat L0 = L0 + 1 end end
Arguments to subroutines are optional and inside a subroutine, the passed arguments (if any) are also contained in the internal 'Z' variable array and the number of passed arguments is available in the special variable ZN. So, it is possible to create a subroutine that takes an unknown number of arguments and does something with them. Here is an example:
if load # sets all passed arguments to zero subroutine zap ass I0 = 0 while I0 < ZN ZI0 = 0 mat I0 = I0 + 1 end
# zero some things zap 12 L0 LI0 end
Programmers reading this will want to know that array arguments are passed by reference but literal arguments are passed by value. In that last example the subroutine will try and assign 0 to the literal value 12. This assignment is simply ignored (as opposed to causing a run-time error)
We now have setup some aliases and defines and written some subroutines, but would like to use these in multiple scripts. Instead of copying/pasting our work (and having to change it in multiple places if we wish to maintain our work), StreamByter lets you 'pull in' code from another (StreamByter) preset by 'including' it when you install rules.
You save all your common defines, aliases and subroutines into a preset (local or iCloud) and then when you want to make use of those in a script you just include them. Here is a step by step example:
Let's say we define some aliases and a simple subroutine as follows:
alias MT messageType define isControllerMessage messageByte0 == F0
subroutine copyControllerMsg dest_array assign dest_array = M0 M1 M2 end
You'll note that I did not include the if load block around the code in this instance. That is because it is up to the includer to decide whether the code should be inside if load or not.
Save the above code using the StreamByter presets (not the host) into Local (or iCloud) with the name 'myIncludes'
Important - any include preset must be a single word name (no spaces)
Now, start a new script and include the myIncludes and make use of the code therein in the caller script:
if load # include myIncludes (replace local with icloud if the include is there) set include local myIncludes end
if isControllerMessage copyControllerMessage L0 end
If there is an error in an included preset or the included preset could not be found then StreamByter will flag that as normal.
StreamByter ships with a 'standard_includes' preset in it's Factory presets. You can load in the standard_includes and take a look - there are aliases and defines for common MIDI things, control movement detection and subroutines for incrementing/decrementing variables. To make use of the Factory standard includes: