Attached preset demonstrates the "power" of AZ Controller when processing buttons.
Note that
buttons tutorial is recommended before trying to understand/adopt this example.
Most controllers have way less physical elements then we wish to have. And sometimes explicit switching "modes" for all or subset of elements (see
this tutorial) is not desired. Fortunately, long time ago smart people have noticed that one button can perform several operations alone (while obvious by now, the idea was patented originally). In this example, I show how to distinguish "short", "long" and "double" button presses.
To test this preset with your own controller you will need "momentary" buttons or pads. So, they should send some MIDI message (usually "Note" or "CC") when they are pressed (with value not zero) AND when they are released (with value zero). Pads normally send pressure dependent value while buttons send fixed value (usually 127).
After loading preset, in the Options Tab from "Tweak current preset..." select "Forget all assignments". Then assign your controller buttons in the Hardware tab to Btn1...Btn4.
Optionally open AZ Display (from Options Tab).
Expected functionality.4 buttons control 4 WAI Tracks. Short press toggle Mute, long press toggle Solo, double press focus the track. Display monitors Mute.
Note:
- short press has some "delay" after the button is released. Unlike on mouse, controller buttons are usually hard to double-click fast. So this delay is intentional.
- long press operation is executed once "long" is detected, it is not waiting till you release the button
- double press operation is executed on the second press, so it is also not waiting till release
ExplanationSince the implementation requires many Actions, to simplify replicating buttons I use "functions", "state dependent software set" and "state dependent actions". Related definitions can be found in the user manual.
Btn1 - Btn2 differ in 2 Actions only:
- Set State _Ch -> N (with N = 1..4)
- Reset Monitor Timer, it should reset the timer for the same control.
So if you want extend the number of controlled strips, "Dup" "Btn4" control required amount of times, add missing states to the _Ch Set and modify mentioned actions in new controls. Optionally configure Display to show required number of columns. No other modifications required, everything else just use _Ch.
General processing concept is relatively simple. We use some Software Set (BtnState) to keep track of the button state. Initially the button is "Inactive". When pressed the first time, we remember that setting "Pressed" state. And we trigger Timer with desired delay. If you release the button, the state is changed to "Released", but in case it is "Pressed" ONLY (that is important). When pressed again and the state is "Released", we know it was double click. When timer triggers (and it always triggers), we are interested just in two cases: the button is "Pressed" - means it is pressed all the time till the timer, so "Long" pressed; the button is "Released" - means it was released before timer and was not pressed again, so "Short" pressed. And we imitate yet another artificial press using loop MIDI, in these cases only (ignoring all other). Real operations are performed when the button is pressed, really or artificially, and is in "Short", "Long" or "Double" state, ignoring all other states and button released.
As usual, the evil is in details...
Timer and value monitor should be as on top on the list as possible. So they are just after "Ch -> N" which they use. Software Set manipulations are applied also in Monitoring Dry Runs, so shifted downwards the Timer will misbehave.
We need separate State for each button. It is too easy to start operate more then one button in parallel (since reaction has delay). State Dependent Set is used for that, BtnState(_Btn) is in fact _Btn number different Sets. Once _Btn is set (at the beginning), correct one is used in all other Actions.
Some Actions should work when the button is released, that will be indicated by "Note:Off" (even in case other MIDI messages as used, as long as control type is "Pad"). By default, all Actions have "Note:On" condition. So for some, including _Ch->N, "Note:Any" is explicitly set.
fBtnAction(_Btn) must "reset" the state to "Inactive" after processing, as long as the state is not transient (>= "Short"). So "final" Actions can't be used during processing (if processing is complicated, it is better Call separate function for it).
I use set by fBtnPar(_Btn) parameter (corresponding track Mute) in fBtnAction, instead of explicitly selecting it again. In case monitoring/reaction are more complicated than in this example, it is better select required parameter in fBtnAction explicitly.
And one more time... Since the same Control Action List is called under many different conditions (real interaction with controller with press and releases, looped MIDI, monitoring, any of mentioned with different button states) it is essential to explicitly process well defined conditions only and "ignore" other. Mistakes there will invisibly break the logic.