Starting out JAVA in MAX - send message directly to object

kmll's icon

I have just installed eclipse and got it running with MAX:) I have used Javascript in the past but need something that performs better so this is why I am starting to use JAVA. I used to access objects directly from javascript using the following syntax:

objline1 = this.patcher.getnamed("sn_line1");
objline1.message(0,10);

Is it possible to send a message directly to an object using JAVA?

Lee's icon

Hi. No, this isn't possible from Java, you need to send out of an outlet and route appropriately...

kmll's icon

Ok. Thanks for the advise. Do you happen to know of any good tutorials apart from the "Writing Max Externals in Java" pdf?

Also when sending to an outlet can I please ask you to advise how to format the message. I am sending the string below to a play object but it did not understand it.

import com.cycling74.max.MaxObject;

public class PlayFragment extends MaxObject {
    public void bang() {
        String str ="start 100 2000 1900";
        post(str);
        outlet(0,str);
    }
}

Chris Vik's icon

Yo KMLL,

You need to parse the values you want to output as "Atoms" ( the generic datatype that Max uses ), build an Atom[] array from those values, then output the array.

This is how I go about it:

String someString = "allTheThings";
float someFloat = 0.4f;
Atom[] outputAtom = new Atom[] { Atom.newAtom ( someString ), Atom.newAtom ( someFloat ) };
outlet ( 0, outputAtom );

Chris.

Lee's icon

yup, that.

As for additional tutorials, don't know of any of hand, but didn't look that much. found the pdf to be informative enough. i'm guessing if you hunt around for emamples of other people's code that may help you.

kmll's icon

Thank you both for the input:)

I studied the API in more detail yesterday and it seems that it is actually possible to send a message direcly to an object. Here is an example:

MaxPatcher p = this.getParentPatcher();
MaxBox mb = p.getNamedBox("sn_play1");//The script name needs to be set in the inspector
Atom[] outputAtom = new Atom[] { Atom.newAtom (200), Atom.newAtom (500),Atom.newAtom (300)};
mb.send("start", outputAtom);

Lee's icon

well, thanks. i've learnt something new today also :)

Lee's icon

btw, if you look in the java/classes directory under your MAX install, there are a number of java files in there that do basic things

kmll's icon

Thanks for the pointer to the files:)

Chris Vik's icon

KMLL, you wonderful person, you.

I've seen this question a few times and the response was always "it can't be done". This will save me from having to route all over the place. Well done and many thanks!

Chris.

Peter Castine's icon

Yes, it's possible to send messages between Java objects without using patch cords.

Doing so will make it well-nigh impossible to debug your patches unless you document the holy shit out of what you're doing. Which you won't.

Sending messages through patch cords means you have to draw the patch cords, but then you can see the connections in your patch. With invisible connections: you make one change, nothing works, and you can spend many long and tedious hours trying to figure out what's gone wrong.

If you want your code to be reusable, if you're working on a project that's supposed to last and develop over more than a week, then stay away from this trick. But if your time is worth nothing at all, go ahead and be it on your head.-)

kmll's icon

Thanks for the input on this thread you all. Glad I could help Chris:) Guess Peter has a good point but it is a matter of coding style I guess. Also I have to warn any readers that I found the API to be inadequate when interacting with certain objects e.g the line object but I have created a seperate thread about this issue. - Thanks

volker böhm's icon

Also I have to warn any readers that I found the API to be inadequate when interacting with certain objects e.g the line object

there's nothing wrong with the API in this regard.
you just have to know that a list, e.g. 20 200, is a message starting with the (mostly hidden) message header list. i.e. 20 200 and list 20 200 is basically the same.
so in java you can use the send(java.lang.String message, Atom[] args) method to send a list to a max object, like this:

int args[] = {20, 2000};
MaxPatcher p = this.getParentPatcher();
MaxBox mb = p.getNamedBox("sn_line1");
mb.send("list", Atom.newAtom(args));

hope that clears it up.

Roth's icon

As Volker said, you can use send(java.lang.String message, Atom[] args). There is also MaxSystem.sendMessageToBoundObject(java.lang.String sym_name, java.lang.String msg, Atom[] args)

As mentioned in your other thread about sending messages to line, it may be easier to use the overloaded methods for java primitive types than using the atom versions--performance is better too.

Yes, it’s possible to send messages between Java objects without using patch cords.

Doing so will make it well-nigh impossible to debug your patches unless you document the holy shit out of what you’re doing. Which you won’t.

I totally agree with Peter, but if you do document everything well, you can do many quite powerful things messaging between Java objects. Using the two methods mentioned above maybe have some performance and threading issues vs some of the methods available for using your MXJ's outlets. You can even build stuff that doesn't use the Max API but passes around references to Java objects if you really want to get into crazy town.

Mike S's icon
int args[] = {20, 2000};
MaxPatcher p = this.getParentPatcher();
MaxBox mb = p.getNamedBox("sn_line1");
mb.send("list", Atom.newAtom(args));

I get the following error from the code above....

"cannot find symbol
symbol : method send(java.lang.String,com.cycling74.max.Atom)
location: class com.cycling74.max.MaxBox
mb.send("list", Atom.newAtom("test"));"

This error is a bit weird as it seemed to come and go, now it is always there.
I was also wondering if it's possible to name the MaxPatcher something other than p?
Like so...

MaxPatcher mypatch = this.getParentPatcher();
MaxBox pattr = mypatch.getNamedBox("pattr_object");
pattr.send("dump");