JavaScript utilities to address all objects without patchcords

Glennzone's icon

I'm trying to use a JS object and a thispatcher object to control all the objects in a patch. All objects in the patch have a scripting name.

1. I'm looking for a JS utility script which can report back all the objects in a patcher and subpatchers. This is for the purpose of learning exactly how to address all objects from a JS object, without the use of any patchcords.

I found something called printobj, but I believe it's incomplete.

2. I'm also looking for another utility JS example script which can show me how to output the data type that a selection of objects needs :

Matrixctrl, message, number, textedit, pattr, pattrstorage, preset, js, etc.

It is my belief that with these utilities, it is much easier to understand how to successfully use JS with Max.

Does no one use such things ? I have been making quite an exhaustive search, but come up with little info.

I've used things like :

var p = this.patcher;
//It is expected that the message object called flower would be changed
// from its current message of Fred to Wilma
p.getnamed(["flower"]).message("Wilma"); //"flower" being a message object

I've had trouble with various objects and data types, but I know there are experts among us. Could someone please share this invaluable information ?

Mike S's icon

I'm also interested in this!

Julien Bayle's icon

Hi there,
by requesting the patcher object, you can address all your objects and get properties like count, maxclass.
Check : https://cycling74.com/docs/max6/dynamic/c74_docs.html#jspatcherobject

message methods use string only, afaik.

I don't know if I answered...

Nat's icon

Of main interest are the apply and applydeep functions that you can use to iterate all objects in a current patcher for the former and in the current patcher and all subpatchers for the latter.

Glennzone's icon

@Julien : Yes, I'm already using the thispatcher object within my patch. I think that brings us to the same end, if I understand correctly. The question is, how do you ask of it to send you a list of all it's children, grandchildren, etc., and their properties ?

@Nat : That would certainly be part of the JS solution. The question there is, what exactly is the syntax for such a utility script ?

@MikeS : You seem to be the only one (other than me, of course) not in denial !

:-D

More answers, please . . . .

Nat's icon

the maxtoolbox source has a lot of examples of the apply and applydeep functions:
https://github.com/natcl/maxtoolbox/blob/master/javascript/maxtoolbox.js

Julien Bayle's icon
Max Patch
Copy patch and select New From Clipboard in Max.

I didn't talk about thispatcher object but this.patcher representation inside JS code.
Basically, you can use this patch, after to have downloaded and place in the path the JS I attached.

objectsFun.js
js
Julien Bayle's icon

As shown by @nat-liststudioimaginairecom, indeed, you can do much more than my short piece of code (just an example, btw)

Glennzone's icon

@Nat : I am looking at the maxtoolbox.js and the toolbox_config.js and there is no mention of applydeep that I've found.

@Julien : I'm playing around with your patch, but it's not doing much for me yet.

@MikeS : Did you get anywhere with what Nat and Julien gave us to work with ?

So, I'm still not there, but when I finally have a working technology demonstrator, I will definitely post it here. This really seems to me like one of the absolute necessities to have with the Max package.

Glennzone's icon

Still nothing breaking loose here. No other input ?

Luke Hall's icon

For your first task you mention reporting all the objects in your patch and any subpatches - do you mean their maxclass (the type of max object it is) or the varname (scripting name) that the object has been given?

I'm not sure how having a list of either of these will help if the varnames aren't obvious or you have lots of the same object in your patch - how will you tell which is which?

Either way I've included some javascript below which shows you how to use applydeep, it will report the scripting names of all the objects in the patch and any subpatchers (patcher objects or abstractions) when you send it a bang. If you want it to report the object type just swap out the last "obj.varname" for "obj.maxclass".

function bang() {
    this.patcher.applydeep(search);
}

function search(obj) {
    if (obj.varname != "") {
        post(obj.varname,"\n")
    }
}

I'm a bit confused with your second point too. Do you mean you want your javascript code to be aware of what type of input (message, list, integer, float, etc) each object can receive? The only way I can think of doing this is to create a big lookup table/array inside your code to refer to based on the maxclass.

Or did you mean you want a list of the messages the object can receive (programmatically - rather than just clicking on the inlet for the contextual help). This actually is possible by loading in the maxref file for the object class and parsing the xml to get a list of accepted messages and I can post an example if you'd like.

If neither of those things are helpful you might need to clarify your goals a little so I can wrap my head around it!

Glennzone's icon

Answers inline . . .

For your first task you mention reporting all the objects in your patch and any subpatches – do you mean their maxclass (the type of max object it is) or the varname (scripting name) that the object has been given?

I’m not sure how having a list of either of these will help if the varnames aren’t obvious or you have lots of the same object in your patch – how will you tell which is which?

>>The utility script I'm referring to is something you would run against your patch, not something to be used within the patch itself. Certainly, I know my script names (varnames).It's about using this "report" to build the JavaScript syntax in order to manipulate the objects within the patch (and subpatches, and parent patches). Here's my modified version of what you wrote :

// This script gives the information on the objects in a patch
// necessary to direct messages to (and receive from) the objects directly
// without patchcords.
// no inlets, no outlets

autowatch = 1;

function bang() {
//    loadbang();
this.patcher.applydeep(search);
}

function search(obj) {

if (obj.varname != "") {
post("This object's script name is : " + obj.varname,"(" + obj.maxclass,")\n");
     post(" This object's patcher name is : " + obj.patcher,"\n");
        post(" Selectable for text entry : (" + obj.canhilite,") and ignores clicks : ( " + obj.ignoreclick,")\n");
        post(" . . . . . . . . . . . . . . . . .\n");
}
}

The object of this is to have information to assist in directing messages to and from the patch. Sometimes when writing code, the results aren't as expected, and this can be caused for a number of reasons. One of the symptoms is when an object returns "undefined." Another is when the object has a property or method I don't know how to address properly.

Either way I’ve included some javascript below which shows you how to use applydeep, it will report the scripting names of all the objects in the patch and any subpatchers (patcher objects or abstractions) when you send it a bang. If you want it to report the object type just swap out the last “obj.varname” for “obj.maxclass”.

function bang() {
this.patcher.applydeep(search);
}

function search(obj) {
if (obj.varname != "") {
post(obj.varname,"\n")
}
}

>>That's exactly what I'm looking for, but in part. How would I write the code which would return the names of each of these objects' properties and methods ? That would be quite useful.

I’m a bit confused with your second point too. Do you mean you want your javascript code to be aware of what type of input (message, list, integer, float, etc) each object can receive? The only way I can think of doing this is to create a big lookup table/array inside your code to refer to based on the maxclass.

>> No.

Or did you mean you want a list of the messages the object can receive (programmatically – rather than just clicking on the inlet for the contextual help). This actually is possible by loading in the maxref file for the object class and parsing the xml to get a list of accepted messages and I can post an example if you’d like.

>>No again.

If neither of those things are helpful you might need to clarify your goals a little so I can wrap my head around it!

>> The script you included was useful, but incomplete as compared to what I'm hoping to be able to get back from this script. I want whatever's necessary to form the code lines properly to get the messages to and from the objects within the patch. The help files only give so much, and to be honest, I find them very confusing; the arguments seem ambiguous and you don't really know whether you need them or not, etc,. etc.

Thanks again,
Glennzone

Luke Hall's icon

Have a look at the reference XML doc for something like the [number] object (in my Max5 install it can be found in Max5 > patches > docs > refpages > max-ref). Open it in a text editor and then let me know what sort of information you'd like to be able to pull out of it as this is probably the best source of object information aside from the help files which can be easily parsed in Max. I'm imagining it will be the attributes and the methods/messages but you'll know what you need!

Glennzone's icon

Oooh, more resources ! Good stuff. I haven't yet done much diving under the hood, so this is good.

Note : within the xml files in this folder is the following comment line :

Of course, they don't tell you where you can find the edits folder, but . . . doing a search on "_ref.xml" produces nothing.

I'll take a peek at those and see what I find. The attributes are easily found in the inspector of any object by simply clicking on the "@" icon at the bottom of the inspector, so that's a non-issue. Even the messages I believe are likely self-explanatory. It's the methods which will likely be of most interest. However, I get the feeling not all methods will be found in the respective xml files, due the "common" ones being excluded.

Luke Hall's icon

The "methods" section in the XML should include all the messages the object can receive (I'm assuming that by "method" you mean receiving different types of input - float/list/matrix/int/bang/etc. rather than set/max/size/etc messages) which I think is include; within the tag "" for example.

For generic messages such as setting fonts/colours/positions you should look at jbox.maxref.xml in the same location - it includes everything that applies to all standard objects.

Glennzone's icon

Methods : no, actually, I AM referring to the set, get, max, etc., but isn't there also "value" or other such thing as regards referencing the contents of a particular object ?

jbox.maxref.xml : cool. Thanks.

So, to get the attributes, we generally do a this.patcher.getnamed, . . . correct ?

Now what do we do to get the current contents of a particular object ?

Luke Hall's icon

To find the current value of, for example, a number box named "steve" and assign it to a variable you would do something like:

var sploo = this.patcher.getnamed("steve").getvalueof();

To find what type of argument follows any message you'd probably need to parse the description, using regular expressions in your js, for number/float/etc although it doesn't look like it would be completely reliable.

Glennzone's icon

You'll be happy to know that I figured a way very similar to your suggestion on my own (research included, of course).

Max Patch
Copy patch and select New From Clipboard in Max.

You'll notice the JS object has no outlets whatsoever, and the only inlet is to receive a bang to trigger the function. I don't need any outlets because the JS can send commands using the getnamed(script name).message.

There's a little bit of extra stuff in the code (a bit of the utility stuff I've asking for. Still insufficient . . .), but my solution makes use of pattrstorage, as the patches I'm working with in this way are already using pattrstorage. This is nice. Once I pull everything needed into the JS, I won't have to use any outlets to send out instructions to the various objects; I can code for and manipulate the data within the JS world.

At this point, the only thing I'll really need to do is to setup event listeners, which will basically trigger when there's a change to an object, and then the function can run to update the cache data within the JS.

Any caveats I should know about ?

Having said that, I notice it doesn't work with message boxes. I wonder if there's a workaround for that ?

Mike S's icon

Found a few threads like this but not sure which was the most relevant.

In any case, my question is how do I get the values of named objects in subpatchers from a parent patcher in JS?