JS objects output each others messages

lovecouch's icon

I created more than one instance of the same JS object that rotates through an array of ids. one set of ids is only compressors, one set of ids is only eqs. even though i can see 2 arrays going into two js objects, the same output appears on both of them. I tried giving the object a jsargument at the end but this didnt help.

autowatch = 1;
inlets = 1;
var i = 0;

function list(){
    arr = arrayfromargs(messagename,arguments);
    }
function anything(){
    if (messagename == 'next'){handleNext();}
    else if (messagename == 'first'){handleFirst();}
    }
function handleNext(){
    i++;
    if (i>=arr.length){i = 0;}
    outMess();
    }
function handleFirst(){
    i=0;
    outMess();
    }
function outMess(){
    outlet(0,arr[i]);
    }

Lume's icon

I got around it by naming the array in the 2nd js object ""arr2".
But this is strange behaviour, contact support maybe?

I don't think it should happen unless you use a Global variable.

Upload your patch next time too. It's faster.

Jan M's icon

as there is no."var" keyword before your declaration you are in fact using a global variable.
change to:
var arr = ....

lovecouch's icon

Thank you. are you saying that if i want to have more than one instance of a JS object, I shouldn't use global variables?

lovecouch's icon

when i tried this, it didnt know what arr was when i refered to it later in line 14

Jan M's icon

In general Global variables should be handled with great care in JavaSript (especially when using general names for them). Concerning Max: Better avoid them for several reasons (performance, unpredictable interactions....)
if you need to exchange values across [js] instance in Max use the Global Object (as described in the docs)

lovecouch's icon
Jan M's icon

... but that's about a different topic. The Max global namespace is not related to global JS variables...

lovecouch's icon

I still don't understand the Max global namespace, but i do know that when i gave each js object an argument with a # then a number, the problem went away. Just incase anyone else stumbles on a similar problem, this helped me.

lovecouch's icon

* i still got to keep the global arrays by using ^ that

Jan M's icon

The global name space in Max refers to objects that require a name, such as send/receive/buffer~ ...
these objects can be adresses from anywhere in an any patcher inside Max. #0 is a way to make them only valid within an abstraction. I.e. [send #0foo] inside an abstraction will replace the #0 with a unique number automatically. hence you can have multiple abstaction instances, but send will only send messages inside every instance.

Varables in JavaScript are completely independend from that system. They also have a scope where they are valid, but thus refers only to the JavaScript code.

The place holders #1 -#9 are a way to use argunents inside an abstraction. I am sure that giving your js instance an argument is not the reason why your code started working. It must have another cause.
;)

lovecouch's icon

Oh no, I definitely changed it much before I added that tip. But thanks for the clarity... much needed.

lovecouch's icon

what does it mean when someone puts a .local at the end of a method?

autowatch = 1;

function bang()
{
    var api = getTrackPath();
    if (!api) return;

    iterateDevices(api);
}

function iterateDevices(api)
{
    var count = api.getcount("devices");
    var apiPath = dequotePath(api);
    for (var i = 0; i < count; i++) {
        var deviceApi = new LiveAPI(apiPath + " devices " + i);
        if (deviceApi) {
            var deviceName = deviceApi.get("name");
            var deviceApiPath = dequotePath(deviceApi);
            var chainsCount;
            var chainApi;
            var j;

            post("found device " + deviceName + " at path \'" + deviceApiPath + "\'\n");
            if (deviceApi.get("can_have_chains") == 1) {
                chainsCount = deviceApi.getcount("chains"); // only racks have chains
                for (j = 0; j < chainsCount; j++) {
                    chainApi = new LiveAPI(deviceApiPath + " chains " + j);
                    iterateDevices(chainApi);
                }
                chainsCount = deviceApi.getcount("return_chains"); // only racks have chains
                for (j = 0; j < chainsCount; j++) {
                    chainApi = new LiveAPI(deviceApiPath + " return_chains " + j);
                    iterateDevices(chainApi);
                }
            }
        }
    }
}
iterateDevices.local = 1;

function getTrackPath()
{
    var api = new LiveAPI("this_device");
    if (api) {
        trackPath = dequotePath(api);
        trackPath = trackPath.replace(/\s+devices.*?$/g, ""); // remove 'devices N' at the end
        return new LiveAPI(trackPath);
    }
    return null;
}
getTrackPath.local = 1;

function dequotePath(api)
{
    return api.path.replace(/\"/g, ""); // remove quotes
}
dequotePath.local = 1;

Lume's icon

"var", of course. lol.

Lume's icon

Did a search, .local means the function is private to the js object.
The function cannot be accessed from the patch.

lovecouch's icon

Thanks lume