On Load scripting issues
Posted: 02 Feb 2015 11:57
The summary of this post/rant is - Having to guess at how Lemur works internally causes template development to be an order of magnitude more difficult than it should be for someone.
The goal - have the template initialize one or more MIDI clocks to use for generating LFOs. The clock numbers used are user-defined.
Initial attempt: (FAIL)
create a top level variable called clockBase = 5;
create an On Load script called onload() that initializes some background variables, uses setattribute() to apply labels to some objects, then finally calls initClock(1);
(the base = 5, and calling initClock() with a 1 parameter - for LFO 1, is all for user readability.)
initClock(val) is a manual script inside a container that has a local variable called myClock = 0;
initClock(val) does the following:
myClock = val+clockBase-1;
setattribute(lfo_on, 'labels', {'LFO ' + val});
clock_setbpm(myClock, lfoBPM);
clock_stop(myClock);
If I print out to a Monitor object the value of myClock is says myClock = 0, not 5 most of the time I load the template.
Second attempt: (SUCCESS)
onload() does not call initClock(1). Instead, it sets a variable called initDone = 0;
create another script called frame_processing() that executes On Frame.
frame_processing() does the following:
if (initDone == 0)
initDone = 1;
else if (initDone == 1) { // basically delays execution of this init call by 2 Lemur frames
initDone == 2;
initClock(1);
}
initClock(val) stays the same. Now a print to a Monitor object inside initClock(val) shows myClock to be set to 5 and everything works as designed.
So OK, what's the big deal? I figured out a workaround and life is good again. The big deal is now I have frame_processing() script running for every frame and wasting CPU cycles making some 'if' checks that only are needed once in the lifetime of the program. In addition, even though Lemur clearly knows I have a variable called clockBase (no scripts errors showing up), it apparently doesn't have the value set correctly even though it is pre-set in the template. This calls into question all initialization, not just the initialization done inside On Load scripts (which the manual warns about, but it does say they should work correctly when using external numerical constants or arrays of constant numerical data).
It would be great if there was a more technical discussion somewhere of how Lemur evaluates templates and processes scripts, variables, and calls. What happens if your script runs for longer than a single frame? Does execution pick up where it left off or does it get restarted? There's a lot of questions that end up causing template developers to spend extra time debugging or coding workarounds because there's no documented behavior to reference. Sure, if you're just coding up the Lemur equivalent of 'Hello World', life is fine. But if you actually try to use more advanced objects and concepts, you tend to run into these weird corners of the environment with no obvious answer.
The goal - have the template initialize one or more MIDI clocks to use for generating LFOs. The clock numbers used are user-defined.
Initial attempt: (FAIL)
create a top level variable called clockBase = 5;
create an On Load script called onload() that initializes some background variables, uses setattribute() to apply labels to some objects, then finally calls initClock(1);
(the base = 5, and calling initClock() with a 1 parameter - for LFO 1, is all for user readability.)
initClock(val) is a manual script inside a container that has a local variable called myClock = 0;
initClock(val) does the following:
myClock = val+clockBase-1;
setattribute(lfo_on, 'labels', {'LFO ' + val});
clock_setbpm(myClock, lfoBPM);
clock_stop(myClock);
If I print out to a Monitor object the value of myClock is says myClock = 0, not 5 most of the time I load the template.
Second attempt: (SUCCESS)
onload() does not call initClock(1). Instead, it sets a variable called initDone = 0;
create another script called frame_processing() that executes On Frame.
frame_processing() does the following:
if (initDone == 0)
initDone = 1;
else if (initDone == 1) { // basically delays execution of this init call by 2 Lemur frames
initDone == 2;
initClock(1);
}
initClock(val) stays the same. Now a print to a Monitor object inside initClock(val) shows myClock to be set to 5 and everything works as designed.
So OK, what's the big deal? I figured out a workaround and life is good again. The big deal is now I have frame_processing() script running for every frame and wasting CPU cycles making some 'if' checks that only are needed once in the lifetime of the program. In addition, even though Lemur clearly knows I have a variable called clockBase (no scripts errors showing up), it apparently doesn't have the value set correctly even though it is pre-set in the template. This calls into question all initialization, not just the initialization done inside On Load scripts (which the manual warns about, but it does say they should work correctly when using external numerical constants or arrays of constant numerical data).
It would be great if there was a more technical discussion somewhere of how Lemur evaluates templates and processes scripts, variables, and calls. What happens if your script runs for longer than a single frame? Does execution pick up where it left off or does it get restarted? There's a lot of questions that end up causing template developers to spend extra time debugging or coding workarounds because there's no documented behavior to reference. Sure, if you're just coding up the Lemur equivalent of 'Hello World', life is fine. But if you actually try to use more advanced objects and concepts, you tend to run into these weird corners of the environment with no obvious answer.