Issuing a single command to multiple js scripts using a global

Griotspeak's icon

i declare a global variable in my router function:

mcGlobal = new Global("maxConfigGlobal");

and in clients, i declare a function as a property of that global to act as a listener

mcGlobal.allClients = processClientAcknowledgement;

i but only one listener ever recieves messages...

what am i doing incorrectly? i am trying to make an open channel for all of the client scripts to recieve message on.

artm's icon

you have one global object and one global property to which you assign a callable in each client? then each assignment overwrites the previous one and only the last one gets called.

attached is an example of one way to handle this. I maintain a list of clients ("slaves") and route every message to those slaves who can handle it. The solution could be elaborated to support multiple master>slaves bundles, but I never ran into a complex enough problem to want that :-)

898.spread-test.maxpat
Max Patch
amounra's icon

Ok, that beats the heck out of what I've been trying to do.

Question, though: I'm having the same issue with the method that I'm currently using, which is forcing me to predefine the length of the array I'm using for clients, thus limiting the number of clients I can have open at once.

I'm using closebang to delete the clients when I close a patch and remove them from the array that contains the clients.

Is there at better way, utilizing your method, to delete a specific client when its closed?

Thanks.

Griotspeak's icon

Thank you!

i actually figured out that aspect of the issue my solution was to create a second global for one way communication from the router to the client. but since i have your attention and you seem to be doing something similar: my current issue with this script is that the global containing a list of all the clients clears if i start a new patch with a client in it. i have a different thread about it, but i probably should have posted it here, since ei did figure out the initial thing. but thank you, it is good not to be talking into a void.

artm's icon

amounra: I didn't think about that yet. The safest way I think is to check if a client is valid() before routing to it and remove it if so (thus (1) filter out all nonvalid clients, (2) route). I'll try now if that works.

artm's icon

Griotspeak: if I understand the problem correctly, you could do something like this:

(1) create the global (if it exists already it's content will remain intact)
(2) check if it is initialized already (e.g. it has a list of clients property)
(3) if it isn't - initialize it

I'll add that to my solution as well, as a demonstration.

artm's icon

ok, avoiding unnecessary reinitialization is simpler then client deletion.

my idea is to check if "lib.slaves" property exists when the [js spread] script is instantiated. the best way to test this that I found is: if (!lib.slaves instanceof Array) lib.slaves = [];

I haven't found a nice way to check client validity yet: I wanted to check client.box.valid but after closing the patch with a [js] object, this object's .box property starts to point to some stil valid box all of a sudden!

but there is a workaround possible that I'll try now.

Griotspeak's icon

My code is there....it doesn't seem like I am actually I itializing...since I only initialize in the router software. The router is being re initialized when a new client appears in a new patch.

artm's icon

new version of the "spread" script. this one filters out all closed slaves and allows multiple master scripts (e.g. one per patch) to cooperate (not overwrite the global slave list).

the check for invalid slave is not very correct - it relies on a bug in Max's javascript that changes ".box" property when the patch containing [js] is closed. When registering a slave I store its current .box into a new property ._box and assume that as long as the two properties remain equal the slave is still valid. This doesn't sound very robust or convincing, but I can't seem to invent a better way. Especially since even stored "._box" reports as ".valid" after its patch is closed.

915.spread-002.zip
zip
amounra's icon

I've been messing around with different methods for the last couple of days. Thanks for the comments, although I haven't had a chance to check out the ammended spread script yet.

My main issue is not solved, though, I think.

My whole purpose is to use the js to keep track of unique channels for non-js clients/hosts, so each client/host has to have a unique id. My big problem is that the id's have to be persistent across saves in m4l. I've come up with several schemes that work (setting host.id's as a property of the obj that's passed to the global, etc), but nothing that works all that well. I am going to start from scratch after taking a look at your stuff, and I'll post my results when I'm done...I'm anxious to get this puppy working, as it will simplify the rest of my endeavors a great deal.

Thanks again for the help :)

edit:: sounds like a nice little exploit to figure out validity of slaves. I've just been using [closebang] to delete the obj from the array when I delete a patch, and this works (as long as the js is able to find the right obj via its id to delete). I should mention I'm also calling the spread function from inside the js, so my patches look a little different.

It seems like my main problem is understanding exactly how namespace works in js. If I declare a global in my js "var foo=n", but then redefine it in a function as "foo=n", it should be global to the js but local to that js only, right?

One other thing...passing "this" to the set_slave function: what is this actually refering to, the js itself?

Sorry, I'm a relative newbie to js (and therefore a little knowledge is very dangerous hehe).

Griotspeak's icon

I will post an earlier version of this where I was making patched objects

Griotspeak's icon

here you go. i still used two scripts, but i made patcher objects that i kept track of with the js.

scripting names are important, as that is the only way i know of for a js to get the object outside of the script

918.gs.maxConfig.zip
zip
amounra's icon

So, I just noticed that when copying a plugin from one to another in m4l, closebang sends a bang. This is very irritating. This is what has been foiling all my plans for the last two days, and I've just now noticed it. I guess I'll be finding another method (read: using yours or something similar) to delete clients. What a bummer.

amounra's icon

And now its not doing it....very strange.

amounra's icon

So, apparently, closebang happens anytime that a plugin moves out of the visible screen area of a m4l patch. WTF?

amounra's icon

nm. apparently what I was looking for was freebang. So all is working...except its not working on recalling a saved project. Back to the old "instantiation order" conundrum.

amounra's icon

K...my two cents. This seems to work, although I doubt it will be any use to you. Basically this just populates a [umenu] with a list of all clients/hosts, and will provide a channel that they can communicate by when I'm done (all this will be done via send/receive in m4l).

Save/restore seems to work now. I used some dirty tricks lol.

921.Host_frz_080410.amxd
amxd