working example of saving js state in M4L

parkingsun's icon

I've been trying to work out how to get a JS script to remember some internal state in an M4L device so that innter patch working involving javascript can be, e.g. save in presets etc.

I've had no luck yet. I tried to do an M4L version of the notorious "cowbell" example in the tutorial, using "getvalueof()/setvalueof()" JS functions in a @parameter_enable 1 JS object, but my JS object never seems to recall data with the patcher (i.e. when you call the "howmanycowbells" function, it does not recall a different version for each device.

In the interim I've been working around it by having the javascript object write out the value of getvalueof() to a pattr in parameter mode, and then an initialisation i get the pattr to send that data back again with "setvalueof" prepended.

For your convenience my javascript is included below so that you can inform me how I've been a dunderhead.

comments, critique gratefully accepted.

autowatch = 1;
var numcowbells = 1;

function cowbells(a)
{
    numcowbells = a;
    notifyclients();
}

//AFAICT this is only used for saving JS state with the patcher itself, not in the M4L version
function save()
{
    embedmessage("cowbells", numcowbells);
}

function howmanycowbells()
{
    post("numcowbells", numcowbells);
    outlet(0, numcowbells);
}

function getvalueof() {
    return numcowbells;
}

function setvalueof(a) {
    cowbells(a);
}
5358.testjsstate.maxpat
Max Patch
Lee's icon

Hi, the getvalueof() and setvalueof() functions interact with the pattr system... if you attach the middle outlet of an 'pattr @parameter_enable 1' to the first inlet of your js then everything should be good.....

The save() function you have is for storing state in a patcher and isn't needed here....

Hope this helps...

parkingsun's icon

Ahhh. Thank you Lee.

Got it. So @parameter_enable 1 doesn't really do anything with JS - I should defer all that stuff to a pattr, for which @parameter_enable 1 does what one expects. OK.

Bonus points if anyone can tell me what @parameter_enable 1 DOES do for a javascript object.

Lee's icon

pattr objects normally need a pattrstorage object in order to determine where the information is stored.... the pattr object with @parameter_enable 1 indicates that the information should be stored within the patch and you don't need to provide an independent pattrstorage object...

Lee's icon

for above post, should add that the @parameter_enable 1 is part of the pattr storage for m4l...

parkingsun's icon

Thanks, Lee for diving back in to it again!

I think I perhaps could have phrase my flippant final question better.

To do that now, yes I understand that @parameter enable tells the pattr to store information with the preset rather than in the patch. However, my question is, rather, why it seems to behave differently between a JS object and other objects. So if I put a [pattr] or, say, a [flonum] in @parameter_enable 1 mode, then they instantly and magically behave like standard live interface objects such as [live.dial], in that they store their state in the preset. If, however, I create a [js @parameter_enable 1] object, it seems, if I am understanding you correctly, to additionally require to be attached to a [pattr @parameter_enable 1] object to save its state, and does not save that state itself. Therefore, as far as I understand, @parameter_mode 1 doesn't do anything for JS objects, and may as well be ignored.

The patch works fine, by the way, using your [pattr @parameter_enable 1] hack! At this point I'm more trying to understand rather than fix anything.

Lee's icon

Ah, I see what you mean... I misunderstood your post... I was not aware that you could supply @parameter_enable 1 as an attribute to a js object - I guess this should behave as you expect... I'll give this a try when I have a few mins...

Peter Kyme's icon

Just in case anyone else runs into this problem, I was struggling to get pattr to bind successfully to a js object, but only when the device was running within Live. If you had the pattr object visible in the device, it was being highlighted red, and not functioning.

The solution was to freeze the device after editing it. This seems to fix the issue for the duration of the Live session, and oddly enough it's only required once and seems to affect all non-frozen devices using pattr/js binding, not just the one you're editing.

This is with Live 10.1.2b5 and the embedded Max 10.1 beta.