Ok, it took some time to understand the Midi flow in Lemur. I think it's poor that the Lemur editor MIDI mapping interface can't be changed via script.
And for shure you must implement a function that converts text to numbers or getting the index of the active container tab.
Can't be that hard after all you created within Lemur.
My goal was to build a bidirectional control between Lemur and my DAW Studio One with the possibility to plug-in a hardware controller with endless encoders in this circuit.
Lemur sends on Lemurs Deamon port Midi 0 to Studio One and receives on port Deamon port Midi 1 from Studio One. Lemur receives the hardware control on Deamon port Midi 0.
Lemur -> Deamon port Midi 0 Ch1 -> Studio One;
Studio One -> Deamon port Midi 1 Ch1 -> Lemur;
Hardware controller -> Deamon port Midi 0 Ch1-> Lemur;
The Midi mappings are completely done inside the global MIDI_MAPPINGS script.
Code: Select all
Example:
setexpression(ContainerTab.TabContainer_1.K_1,'CC',1);
setexpression(ContainerTab.TabContainer_1.CBu_1,'CC',17);
setexpression(ContainerTab.TabContainer_2.K_1,'CC',33);
setexpression(ContainerTab.TabContainer_2.CBu_1,'CC',49);
The controls inside Lemur (knob, button) have 3 scripts ( MIDI_IN, MIDI_OUT, DAW_MIDI) and one variable/ expression (CC) set inside the global MIDI_MAPPINGS script.
Code: Select all
MIDI_IN - SCRIPT - Knob
if ((MState == floor(CC / Divider)) && ( CC == MIDI_ARGS[0] + offset) && (MIDI_ARGS[2]==0))
{
if ( MIDI_ARGS[1]== 1) x= x + (1/127);
if ( MIDI_ARGS[1]== 127) x= x - (1/127);
}
Comment: After some filtering the MIDI_IN script is increasing and decreasing the values in Lemur. I use BeatStep in relative#2 mode. Clockwise it gives me 1 and counterclockwise 127.
It's confusing cause it should be the opposite. That's why the received value of (1) increases and (127) decreases. Adjust those 2 values to the endless encoder behaviour of your hardware.
MIDI_IN - SCRIPT - Button
if ((MState == floor(CC / Divider)) && ( CC == MIDI_ARGS[0] + offset) && (MIDI_ARGS[2]==0))
{
if ( MIDI_ARGS[1]== 127)
{
if (x==0) x=1; else x=0;
}
}
Code: Select all
MIDI_OUT - SCRIPT - Knob
ctlout(PORT,CC,x*127,CH);
MIDI_OUT - SCRIPT - Button
ctlout(PORT,CC,x*127,CH);
Comment: Both work "On Expression". As soon as the MIDI_IN script is triggered and the control inside Lemur moves,
Lemur interprets it as "On Expression" and triggers the MIDI_OUT script automatically.
Code: Select all
DAW_MIDI - SCRIPT - Knob
if ((CC == MIDI_ARGS[0]) && (MIDI_ARGS[2]==0)) x= MIDI_ARGS[1]/127;
DAW_MIDI - SCRIPT - Button
if ((CC == MIDI_ARGS[0]) && (MIDI_ARGS[2]==0)) x= MIDI_ARGS[1];
Basically you only have to adjust the MIDI_IN script to work with your hardware.
After this is done you can copy/ paste the controls and do the CC mapping inside
the global MIDI_MAPPINGS script.
You might noticed that the MIDI_IN script deals with global variables called "Divider" and "offset".
The purpose of those two is to remap your hardware controller inside Lemur by using Tabs.
I recommend the following:
Hardware
Set your hardware encoders and buttons to send CCs starting from CC1.
My Arturia Beatstep for example has 16 small encoders and 16 pads i want to use with Lemur.
So i have 32 controls at once without recalling a different preset or changing the midi channel on my Beatstep.
I set them to send CC1-32 values.
Lemur
Now I copy the knobs and buttons inside Lemur (TabContainer_1) so that they mirror my hardware. Working like a display.
Map them inside the global MIDI_MAPPINGS script to receive/send on CC1-32.
Code: Select all
setexpression(ContainerTab.TabContainer_1.K_1,'CC',1);
(...)
setexpression(ContainerTab.TabContainer_1.CBu_1,'CC',17);
(...)
After everything is working in (TabContainer_1) copy and paste (TabContainer_1) into (2 Tab) and Lemur will name it properly (TabContainer_2).
Now do the mapping inside the global MIDI_MAPPINGS script.
Code: Select all
setexpression(ContainerTab.TabContainer_2.K_1,'CC',33);
(...)
setexpression(ContainerTab.TabContainer_2.CBu_1,'CC',49);
(...)
Since I already used CC1-32, I set them to receive/ send on CC33-64. In this scenario 32 is obviously my "offset/ Divider".
Changable inside the global MIDI_MAPPINGS script.
So now when i'm on Tab 2 moving my CC1 BeatStep encoder the MIDI_IN script receives the midi with the + offset of 32 = CC33 and I'm able to control the CC33 Knob on Tab 2.
uso. If you copy/ paste in order everything should be named properly and logically. If you made mistakes delete the last till the root, correct the mistake and start copy/pasting again.
Studi One
Create a "New Keyboard" in Preferences/ Midi Devices set it to receive from Deamon Midiport 0 and send to Deamon Midiport 1.
Watch this video for more details
https://www.youtube.com/watch?v=MG76UEQqcuI
Everything should work like in this video only with a Lemur display/ control between your hardware controller and the DAW.
If you find this helpful, and believe me informations on this topic are very hard to find, it took days to set it up, ... drop a "thanks".