Forums > MaxMSP

Local send/receives? (using the #0 trick)

June 12, 2007 | 5:44 am

Hi there,

According to several threads in the forums, the most common solution for making send/receives work locally instead of globally is to use the special #0 argument before a name. My understanding of the way this is supposed to work is that the #0 gets replaced by a random four digit string of numbers when your patch is loaded. This dynamically creates a unique name to use in your send and receives (i.e. "#0foobar" becomes "1001foobar" when your patch is loaded. Then, if you load the same patch again, the "#0foobar" in the second instance will become "1002foobar", therefore allowing send and receives to be used without the two patches affecting each other.)

(Doing a forum search for "send receive local" will find numerous references to this technique).

I could only find one reference to this technique in the Max/MSP documentation (in Max Topics):

"#0 has a special meaning. It can be put at the beginning of a symbol argument, transforming that argument into an identifier unique to each patcher (and its subpatchers) when the patcher is loaded. This allows you to open several copies of a patcher containing objects such as send and receive without having the copies interfere with each other."

Sounds great, and it is exactly what I am looking for to prevent multiple versions of the same patch from interfering with each other.

The only problem is I can’t seem to get it to work, so I think I must be missing something. Here is a simple test to demonstrate this functionality not working correct (based on my understanding of how it is supposed to work). Create two versions of the patch that follows patch and save them under separate names. Open both patches in Max and change the number box in one of them. The number will get outputted twice, once by each version of the patch showing that the send and receives still working globally.

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 232 109 32 196617 print;
#P number 108 66 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 231 71 89 196617 receive $0foobar;
#P newex 108 102 75 196617 send $0foobar;
#P connect 1 0 3 0;
#P connect 2 0 0 0;
#P window clipboard copycount 4;

(This is my first time including a patch in a post so please let me know if I didn’t do it correctly.)

Any help or ideas would be greatly appreciated. Thanks!!


June 12, 2007 | 6:43 am

if you save your patch as an abstraction and call many instances of
it, it works as it is supposed to.
by abstraction i mean a sub-patch, that you name (i called it zero,
could be anything), save, and use as an object

best

kasper

>Hi there,
>
>According to several threads in the forums, the most common solution
>for making send/receives work locally instead of globally is to use
>the special #0 argument before a name. My understanding of the way
>this is supposed to work is that the #0 gets replaced by a random
>four digit string of numbers when your patch is loaded. This
>dynamically creates a unique name to use in your send and receives
>(i.e. "#0foobar" becomes "1001foobar" when your patch is loaded.
>Then, if you load the same patch again, the "#0foobar" in the second
>instance will become "1002foobar", therefore allowing send and
>receives to be used without the two patches affecting each other.)
>
>(Doing a forum search for "send receive local" will find numerous
>references to this technique).
>
>I could only find one reference to this technique in the Max/MSP
>documentation (in Max Topics):
>
>"#0 has a special meaning. It can be put at the beginning of a
>symbol argument, transforming that argument into an identifier
>unique to each patcher (and its subpatchers) when the patcher is
>loaded. This allows you to open several copies of a patcher
>containing objects such as send and receive without having the
>copies interfere with each other."
>
>Sounds great, and it is exactly what I am looking for to prevent
>multiple versions of the same patch from interfering with each other.
>
>The only problem is I can’t seem to get it to work, so I think I
>must be missing something. Here is a simple test to demonstrate this
>functionality not working correct (based on my understanding of how
>it is supposed to work). Create two versions of the patch that
>follows patch and save them under separate names. Open both patches
>in Max and change the number box in one of them. The number will get
>outputted twice, once by each version of the patch showing that the
>send and receives still working globally.
>
>#P window setfont "Sans Serif" 9.;
>#P window linecount 1;
>#P newex 232 109 32 196617 print;
>#P number 108 66 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
>#P newex 231 71 89 196617 receive $0foobar;
>#P newex 108 102 75 196617 send $0foobar;
>#P connect 1 0 3 0;
>#P connect 2 0 0 0;
>#P window clipboard copycount 4;
>
>(This is my first time including a patch in a post so please let me
>know if I didn’t do it correctly.)
>
>Any help or ideas would be greatly appreciated. Thanks!!


June 12, 2007 | 6:45 am

A #0 #1 or #2 argument only works when the patch is a subpatch of another parent patch. When you open the patch directly the #0 shows up just as #0. However, if you save the patch and then load it as an object in another patch, the #0 will turn into the random number you are expecting.


June 12, 2007 | 6:54 am

Hi there,

Thanks for the replies. Yup I tested it this way and the #0 works as expected when used this way.

Unfortunately I don’t think that will solve the problem I am having. Basically I just want to send a value using a "send" in a patch into a "receive" in an abstraction loaded by that patch (and then be able to load multiple instances of the top level patch without them interfering with each other).

The reason this implementation of the #0 trick won’t work is that the top level patch would have to know the value used for the #0 in the abstraction.

Thanks again for the replies though, great to know how the #0 actually works.

If you have any other ideas for accomplishing my goal above I’d love to hear them. It seems so trivial that I am surprised at how difficult it is. Basically I think all I want is a "pv" that automatically outputs it’s value when it changes…

-Roben


June 12, 2007 | 7:28 am

ok here is a solution. The trick is…. you have to save the patch named "subpatch" as a separate patch. Load that patch as an object into the parent patch in the example (in place of the [p subpatch]). THEN save the parent patch, and load it as a subpatch in another grandparent patch-

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#N vpatcher 10 59 225 212;
#P window setfont "Sans Serif" 9.;
#P number 30 69 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 30 40 159 196617 receive $1bar;
#P connect 0 0 1 0;
#P pop;
#P newobj 46 111 188 196617 p subpatch $0foo;
#P number 46 42 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 46 80 185 196617 send $0foobar;
#P connect 1 0 0 0;
#P window clipboard copycount 3;

The reason formated the arguments for the subpatch they way i did was because #0 needs a symbol at the end of it to work properly. So, I just put in foo at the end of #0 and then added bar at the end of the #1 in the subpatch.

I know this is confusing and I hope it makes sense!


June 12, 2007 | 7:40 am


June 12, 2007 | 8:41 am

hi,

maybe your solution would be to use a poly, and then targeting the instance you want to communicate with… this doesn’t involve #0, and send/receive neither. just use the [in] object in your patch and the "target" message with the [poly] object.

have a nice day, all.

G

here’s an example

polydemo.mxt :
#P window setfont "Sans Serif" 12.;
#P window linecount 1;
#P comment 319 104 211 196620 2-load the second one i give you;
#P message 179 120 50 196620 BANG !;
#P button 180 92 15 0;
#P newex 122 155 150 196620 sprintf i am $0_ …..%s;
#N in 2;
#P newobj 181 52 32 196620 in 2;
#N in 1;
#P newobj 97 50 32 196620 in 1;
#P number 97 91 35 12 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window setfont "Sans Serif" 9.;
#P newex 159 212 32 196617 print;
#P window setfont "Sans Serif" 12.;
#P comment 171 187 323 196620 print the $0 just to prove it’s not the same instance;
#P window linecount 2;
#P comment 320 59 211 196620 1-save this patch as polydemo.mxt;
#P connect 4 0 3 0;
#P connect 8 0 6 0;
#P connect 3 0 6 0;
#P connect 6 0 2 0;
#P connect 7 0 8 0;
#P connect 5 0 7 0;
#P window clipboard copycount 10;

and the parent patcher:

#P window setfont "Sans Serif" 12.;
#P number 5 34 35 12 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P message 5 73 68 196620 target $1;
#P number 81 36 35 12 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 81 71 150 196620 poly~ polydemo.mxt 10;
#P connect 1 0 0 0;
#P connect 2 0 0 0;
#P connect 3 0 2 0;
#P window clipboard copycount 4;


June 12, 2007 | 9:05 am

Yup, as far as I am concerned this is a basic shortcoming of Max.

Quote: robenkleene wrote on Tue, 12 June 2007 08:54
—————————————————-
> Basically I think all I want is a "pv" that automatically outputs it’s value when it changes…

And in the long run you also want it to only work downward, not upward, if you get what I mean.

Here is an abstraction I made that might be what you need:

http://www.arttech.nl/overridable-pv-with-direct-output.zip

Mattijs


June 12, 2007 | 11:02 am

#0 doesn’t work in a main patch – only in patches stored as abstractions.
Save your patch with some name in your search path and then make several
instances in another main patch.

On 6/12/07 1:44 AM, "Roben Kleene" wrote:

> #P window setfont "Sans Serif" 9.;
> #P window linecount 1;
> #P newex 232 109 32 196617 print;
> #P number 108 66 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
> #P newex 231 71 89 196617 receive $0foobar;
> #P newex 108 102 75 196617 send $0foobar;
> #P connect 1 0 3 0;
> #P connect 2 0 0 0;
> #P window clipboard copycount 4;

Cheers
Gary Lee Nelson
Oberlin College
http://www.timara.oberlin.edu/GaryLeeNelson


June 12, 2007 | 4:04 pm

Thanks for all the suggestions everyone!

I am going to try some of them later on tonight.


September 30, 2007 | 10:53 am

the #0 trick has been pretty handy for me. though i have a few abstractions within abstractions, and this method doesn’t work for me when this happens. is there another way to send a message locally or to all child patches, but not others higher in the tree?

what does #2 do? i couldn’t find it in the manual.

thanks guys!


September 30, 2007 | 11:53 am

On 30 sept. 07, at 12:53, blairell wrote:

>
> the #0 trick has been pretty handy for me. though i have a few
> abstractions within abstractions, and this method doesn’t work for
> me when this happens. is there another way to send a message
> locally or to all child patches, but not others higher in the tree?
>
> what does #2 do? i couldn’t find it in the manual.

You’ll have to pass the #0 to the abstractions within your
abstraction, by using the "normal arguments" #n (with n > = 1 && n < =
9).

HTH,
ej


September 30, 2007 | 12:39 pm

thanks for the reply. where could i find a good explanation of #n? i haven’t used it before either and it doesn’t seem to be in the help file.


September 30, 2007 | 2:40 pm

On 30 sept. 07, at 14:39, blairell wrote:

> thanks for the reply. where could i find a good explanation of #n?
> i haven’t used it before either and it doesn’t seem to be in the
> help file.

"Arguments: $ and #", p. 8 in "Max46Topics.pdf".

ej


October 2, 2007 | 3:07 am

i tried to use the #1 argument to reference a coll onject name, but this didn’t work. the coll object interprets #1 as "#1", not as the value placed after the patch name


October 2, 2007 | 6:25 am

On 2 oct. 07, at 05:07, blairell wrote:

> i tried to use the #1 argument to reference a coll onject name, but
> this didn’t work. the coll object interprets #1 as "#1", not as
> the value placed after the patch name

This would be great if you could provide a patch, otherwise we can
only speculate.

ej


October 6, 2007 | 8:20 am

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 301 157 70 9109513 deletetestb 2 5;
#N vpatcher 356 459 956 859;
#P window setfont "Sans Serif" 9.;
#N coll $1#2;
#P newobj 50 50 53 9109513 coll $1#2;
#P pop 1;
#P newobj 157 149 62 9109513 p deletetestb;
#P window clipboard copycount 2;

in this example (youl have to save the patcher out so it works) you can see coll successfully takes the #1 argument, but not #2.

this is preventing me from having multiple independent banks of coll objects. does anyone know a way of working around this? perhaps a way of setting #1 with a sprintf command?


October 6, 2007 | 9:06 am

On 6 oct. 07, at 10:21, blairell wrote:

> this is preventing me from having multiple independent banks of
> coll objects. does anyone know a way of working around this?
> perhaps a way of setting #1 with a sprintf command?

When you use "#1#2" as a symbol, the only one which will be replaced
is the first one. You could use [loadmess] to get the arguments at
initialisation (or [patcherargs]), [sprint] to concatenate the
strings and then the refer message to [coll]. There might be another
issue which is that the coll need to exist, in that case refer won’t
do anything, so I added a way to create a [coll] on instantiation.

save at deletetestb:

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 85 127 72 196617 prepend refer;
#P newex 85 85 108 196617 sprintf symout %s%s;
#P newex 85 58 83 196617 loadmess $1 $2;
#N coll $1#2;
#P newobj 30 167 53 196617 coll;
#P newex 329 151 49 196617 append 1;
#N thispatcher;
#Q end;
#P newobj 329 180 61 196617 thispatcher;
#P newex 329 123 192 196617 prepend newex 329 213 61 196617 coll;
#P comment 328 44 136 196617 This migth not be necessary;
#P connect 6 0 7 0;
#P connect 6 0 1 0;
#P fasten 3 0 2 0 334 176;
#P connect 1 0 3 0;
#P connect 5 0 6 0;
#P connect 7 0 4 0;
#P window clipboard copycount 8;

Save as whatever:

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 361 217 90 196617 deletetestb toto 5;
#P window clipboard copytext "deletetestb toto 5" #E;
#P window clipboard copycount 1;

HTH,
ej


October 7, 2007 | 7:10 am

your second example is the path i think ill have to go down, as these coll’s are being dynamicly created so that other coll objects can actually refer to them.

im very new to creating these sorts of scripts though, and i dont really understand how what you did actually works. i need to learn how connect the output of another two objects which already exist into that new coll object.

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 49 176 38 9109513 r $1coll;
#P newex 105 174 90 9109513 sprintf %s %s%s.kt;
#P window clipboard copycount 2;

what do you think is the best part in the manual/tuts to learn about this stuff? thanks for your help again ej, its been great.


October 7, 2007 | 10:42 am

On 7 oct. 07, at 09:10, blairell wrote:

> your second example is the path i think ill have to go down, as
> these coll’s are being dynamicly created so that other coll objects
> can actually refer to them.
>
> im very new to creating these sorts of scripts though, and i dont
> really understand how what you did actually works. i need to learn
> how connect the output of another two objects which already exist
> into that new coll object.
>
> #P window setfont "Sans Serif" 9.;
> #P window linecount 1;
> #P newex 49 176 38 9109513 r $1coll;
> #P newex 105 174 90 9109513 sprintf %s %s%s.kt;
> #P window clipboard copycount 2;
>
> what do you think is the best part in the manual/tuts to learn
> about this stuff? thanks for your help again ej, its been great.

Sure. For other scripting examples, have a look to [thispatcher] help
file there’s a few subpatchers in it about the scripting. In that
case "newex" is the keyword to create a non-UI object, after that you
have the x and y position of the object, the width, 196617 is a magic
number which contains the font informations and the name of the
object [coll]. One thing you can do is just to copy a coll object,
and paste in a texteditor which will display something really near to
the script.

Cheers,
ej


Viewing 20 posts - 1 through 20 (of 20 total)