data returned from banged patcherargs newinstance()

May 11, 2007 at 4:10am

data returned from banged patcherargs newinstance()

So:

t_object *patcherargs = newinstance(gensym(“patcherargs”),0,0L);
void(?) *args = typedmess(patcherargs,gensym(“bang”),0,0L);

What am I getting returned from the banged patcherargs instance there? Can this technique actually be used to get the parent patcher’s arguments, or should I be looking elsewhere?

The documentation in “writing externals” (Revision 12 / 3 August 2005) suggest looking at the source for coll to see this in action, but coll.c does not appear to contain any use of newinstance()…

#31856
May 11, 2007 at 9:58am

The “bang” method of an object is typically a function with no return
value (e.g. void myobject_bang()), so you’re not going to get
anything there.

The t_box containing the patcher has a field called b_binbuf. This
should contain the contents of the box as typed in. You can use the
binbuf functions to get at it. So, you need to get the parentpatcher,
and then figure out which of the boxes in the parent patcher contain
the child patcher. Fun fun fun.

This is extremely hacky stuff, and will be breaking with Max 5.

jb

Am 11.05.2007 um 06:10 schrieb John Pitcairn:

>
> So:
>
> t_object *patcherargs = newinstance(gensym(“patcherargs”),0,0L);
> void(?) *args = typedmess(patcherargs,gensym(“bang”),0,0L);
>
> What am I getting returned from the banged patcherargs instance
> there? Can this technique actually be used to get the parent
> patcher’s arguments, or should I be looking elsewhere?
>
> The documentation in “writing externals” (Revision 12 / 3 August
> 2005) suggest looking at the source for coll to see this in action,
> but coll.c does not appear to contain any use of newinstance()…
>

#103982
May 12, 2007 at 12:52am

Quote: Jeremy Bernstein wrote on Fri, 11 May 2007 21:58
—————————————————-
> So, you need to get the parentpatcher,
> and then figure out which of the boxes in the parent patcher
> contain the child patcher. Fun fun fun.
> This is extremely hacky stuff, and will be breaking with Max
> 5.

Thanks, I’ll take a look at that. As long as it can be implemented in such a way that a rewrite of a single function will return the same result in Max 5, I don’t see that as a huge impediment, and I’m learning a fair amount in the process.

Unless, of course, Max 5 is closer than, say, sometime next year. Do feel free to stop me, privately…

#103983
May 13, 2007 at 11:55pm

Quote: Jeremy Bernstein wrote on Fri, 11 May 2007 21:58
—————————————————-
> So, you need to get the parentpatcher,
> and then figure out which of the boxes in the parent patcher
> contain the child patcher. Fun fun fun.

Oh, right, NOW I see what you mean. Fun, uh.

Seems you can’t directly read t_box->b_binbuf anyway, as it may contain garbage and crash binbuf_getatom/binbuf_totext, or produce nothing. Yes?

This, found in another thread, works:

mess1((Object *)parentpatcher,gensym(“save”),mybinbuf);

But the result of the save contains everything in the parent patcher AND any child subpatchers, as per a save to disk, which does indeed make identifying “my” patcher problematic.

Seems to me the only way to tell is by parsing and comparing the location of each #P to my patcher’s location, and that will not be reliable if patchers are instantiated on top of each other, or a patcher has the same position in any sibling subpatch. Meh.

It’s looking a lot more reliable to have the user connect a patcherargs object to my object.

Will Max 5 make it more feasible to retrieve an object’s patcher arguments?

#103984
Jun 3, 2007 at 8:38pm

Quote: johnpitcairn wrote on Mon, 14 May 2007 01:55
—————————————————-
> Quote: Jeremy Bernstein wrote on Fri, 11 May 2007 21:58
> —————————————————-
> > So, you need to get the parentpatcher,
> > and then figure out which of the boxes in the parent patcher
> > contain the child patcher. Fun fun fun.
>
> Oh, right, NOW I see what you mean. Fun, uh.
>
> Seems you can’t directly read t_box->b_binbuf anyway, as it may contain garbage and crash binbuf_getatom/binbuf_totext, or produce nothing. Yes?

I’m looking into this as well. If I do this:

long textSize;
char *text;

binbuf_totext(b->b_binbuf, &text, &textSize);
if (text)
{
post(“patcher code: %s”, text);
}
else
{
post(“text still null..”);
}

I get

patcher code:

in the max window.

Seems like binbuf_totext converts the binbuf to an empty string. Does this make sense to you, Jeremy?

(I love hacky stuff ;)

Mattijs

>
> This, found in another thread, works:
>
> mess1((Object *)parentpatcher,gensym(“save”),mybinbuf);
>
> But the result of the save contains everything in the parent patcher AND any child subpatchers, as per a save to disk, which does indeed make identifying “my” patcher problematic.
>
> Seems to me the only way to tell is by parsing and comparing the location of each #P to my patcher’s location, and that will not be reliable if patchers are instantiated on top of each other, or a patcher has the same position in any sibling subpatch. Meh.
>
> It’s looking a lot more reliable to have the user connect a patcherargs object to my object.
>
> Will Max 5 make it more feasible to retrieve an object’s patcher arguments?
—————————————————-

#103985
Jun 3, 2007 at 8:44pm

Quote: Mattijs wrote on Sun, 03 June 2007 22:38
—————————————————-

> I’m looking into this as well. If I do this:
>
> long textSize;
> char *text;
>
> binbuf_totext(b->b_binbuf, &text, &textSize);
> if (text)
> {
> post(“patcher code: %s”, text);
> }
> else
> {
> post(“text still null..”);
> }
>
> I get
>
> patcher code:
>
> in the max window.
>
>
> Seems like binbuf_totext converts the binbuf to an empty string. Does this make sense to you, Jeremy?
>
> (I love hacky stuff ;)
>
>
> Mattijs
>

The other option I tried to determine the patcher arguments is:

t_atom holder;
long to, so;
to = 0;
so = 0;

while (!binbuf_getatom(b->b_binbuf, &to, &so, &holder))
{
printAtom(&holder);
}

with printAtom:

void printAtom (t_atom *atom)
{
post(“printAtom, type = %d”, atom->a_type);
switch (atom->a_type)
{
case A_LONG:
post(“atom is a long: %ld”, atom->a_w.w_long);
break;
case A_SYM:
post(“atom is a symbol: name %s”, atom->a_w.w_sym->s_name);
break;
case A_FLOAT:
post(“atom is a float: %lf”, atom->a_w.w_float);
break;
}
}

The atom’s types are somewhere between 100 and 115. Could this be an undocumented type? Or are the atoms simply invalid?

Please feel free not to answer if it is too much of a hassle for you ;)

Mattijs

#103986
Jun 3, 2007 at 8:49pm

On Jun 3, 2007, at 3:44 PM, Mattijs Kneppers wrote:

> The atom’s types are somewhere between 100 and 115. Could this be
> an undocumented type? Or are the atoms simply invalid?

The atoms are invalid.
Tim

#103987
Jun 3, 2007 at 9:43pm

Quote: Timothy Place wrote on Sun, 03 June 2007 22:49
—————————————————-
> On Jun 3, 2007, at 3:44 PM, Mattijs Kneppers wrote:
>
> > The atom’s types are somewhere between 100 and 115. Could this be
> > an undocumented type? Or are the atoms simply invalid?
>
> The atoms are invalid.
> Tim
>
>
—————————————————-

Okay, thanks Tim. So does that mean the box’s binbuf is simply invalid? Perhaps it is set only when saving/copying etc? Looks like we’re definitly approaching some caveats here. In that case I will have to proceed with the option john mentioned, get the binbuf from a save of the parent patcher and parse through the data looking for the appropriate patcher.

Or think of a different solution.. eh.. hack. ;)

Best,
Mattijs

#103988
Jun 3, 2007 at 9:46pm

On Jun 3, 2007, at 4:43 PM, Mattijs Kneppers wrote:

> Quote: Timothy Place wrote on Sun, 03 June 2007 22:49
> —————————————————-
>> On Jun 3, 2007, at 3:44 PM, Mattijs Kneppers wrote:
>>
>>> The atom’s types are somewhere between 100 and 115. Could this be
>>> an undocumented type? Or are the atoms simply invalid?
>>
>> The atoms are invalid.
>> Tim
>
> Okay, thanks Tim. So does that mean the box’s binbuf is simply
> invalid? Perhaps it is set only when saving/copying etc? Looks like
> we’re definitly approaching some caveats here. In that case I will
> have to proceed with the option john mentioned, get the binbuf from
> a save of the parent patcher and parse through the data looking for
> the appropriate patcher.
>
> Or think of a different solution.. eh.. hack. ;)

If you haven’t checked it out yet, I highly recommend checking out
the js object for this type of thing. It will save you a lot of time
and hassle…
best,
Tim

#103989
Jun 4, 2007 at 7:27am

Quote: Timothy Place wrote on Sun, 03 June 2007 23:46
—————————————————-
> On Jun 3, 2007, at 4:43 PM, Mattijs Kneppers wrote:
>
> > Quote: Timothy Place wrote on Sun, 03 June 2007 22:49
> > —————————————————-
> >> On Jun 3, 2007, at 3:44 PM, Mattijs Kneppers wrote:
> >>
> >>> The atom’s types are somewhere between 100 and 115. Could this be
> >>> an undocumented type? Or are the atoms simply invalid?
> >>
> >> The atoms are invalid.
> >> Tim
> >
> > Okay, thanks Tim. So does that mean the box’s binbuf is simply
> > invalid? Perhaps it is set only when saving/copying etc? Looks like
> > we’re definitly approaching some caveats here. In that case I will
> > have to proceed with the option john mentioned, get the binbuf from
> > a save of the parent patcher and parse through the data looking for
> > the appropriate patcher.
> >
> > Or think of a different solution.. eh.. hack. ;)
>
> If you haven’t checked it out yet, I highly recommend checking out
> the js object for this type of thing. It will save you a lot of time
> and hassle…
> best,
> Tim
>

Thanks for the suggestion but the reason I’m trying this with C is exactly because I checked out the js object before. It is way too slow for what I want to do (see the thread ‘How to apply oo in max’ in the Max/MSP forum).

But it is interesting that you mention this. In js there is the Patcher.name property. Surely it must be translated to the C api somehow? So I guess I overlooked something. I can only find the ob_name macro which always returns “patcher” for a patcher object. This would be similar to the maxclass property in js.

Do you happen to know how the js function Patcher.name is implemented in C?

Thanks in advance,
Mattijs

#103990
Jun 4, 2007 at 8:42am

Both patcher and bpatcher understand the message “pname”. patcher
returns a t_symbol*, bpatcher returns a char*. You may need to strip
the suffix from the returned name, since it might be the file name.

Although I appreciate your curiosity and willingness to hack this
stuff, I feel like it needs to be stressed that you’re spending a lot
of time trying to solve problems which depend on private APIs which
are going to change drastically, from the developer standpoint, in
the coming months. One could say that you are wasting your time.
Another might say that you’re doing preliminary research, knowing
that you’ll have to redo the work down the road. But please
understand if we seem or are reluctant to give you information about
our private APIs.

You may also find that existing objects can be used to do what you
want to do in a more future-proof fashion. For instance, you could
use pattrstorage or pattrhub objects to get a list of clients in a
patch. Anything which isn’t a leaf node is some kind of container,
no? Why not parse these name symbols and get the information which
you need?

jb

Am 04.06.2007 um 09:27 schrieb Mattijs Kneppers:

> Do you happen to know how the js function Patcher.name is
> implemented in C?

#103991
Jun 5, 2007 at 9:26am

Quote: Jeremy Bernstein wrote on Mon, 04 June 2007 10:42
—————————————————-
> Both patcher and bpatcher understand the message “pname”. patcher
> returns a t_symbol*, bpatcher returns a char*. You may need to strip
> the suffix from the returned name, since it might be the file name.

Ah, great!

>
> Although I appreciate your curiosity and willingness to hack this
> stuff, I feel like it needs to be stressed that you’re spending a lot
> of time trying to solve problems which depend on private APIs which
> are going to change drastically, from the developer standpoint, in
> the coming months. One could say that you are wasting your time.
> Another might say that you’re doing preliminary research, knowing
> that you’ll have to redo the work down the road.

I’ll go for the latter ;) In fact I have no other option than to do this now. The lack of the functionality I’m after (some small tools to structure patches in an OO manner) is a very real constraint in the practice of a sideproject I am currently working on. At this point I can either do some preliminary research or do nothing at all in the time I reserved for that project.

Besides, of course, I am always interested in figuring out how stuff works. I must say I already gained a lot of insight by studying the binbuf/atomized construction of max patches. Nice work :)

> But please
> understand if we seem or are reluctant to give you information about
> our private APIs.

Absolutely, I greatly value your willingness as a company to help users getting involved. I think Cycling ’74 is unique in that aspect. Naturally I understand if there is a limit to your spare time spent on this.

>
> You may also find that existing objects can be used to do what you
> want to do in a more future-proof fashion. For instance, you could
> use pattrstorage or pattrhub objects to get a list of clients in a
> patch. Anything which isn’t a leaf node is some kind of container,
> no? Why not parse these name symbols and get the information which
> you need?

Thanks for the suggestion. We stumbled onto a few objections against this idea:
- since the existing objects are not tuned for this specific task, it will take quite a few of them in every abstraction (to parse strings etc.) This would increase loading times drastically.
- traversing patchers with javascript as an alternative to more elaborate string parsing seemed satisfactory at first but in performance tests appeared to be far too slow.
- with the existing objects it is not possible to communicate and bind across patchers that are unnamed (pv is the only object that comes close but has this one problem that makes it not suitable, see the topic ‘feature request (with prototype): overridable pv’)

In short, as it looks now there is not other option than to dive into the C api.

Thanks for your reply,
Mattijs

>
> jb
>
> Am 04.06.2007 um 09:27 schrieb Mattijs Kneppers:
>
> > Do you happen to know how the js function Patcher.name is
> > implemented in C?
>
>
—————————————————-

#103992
Jun 21, 2007 at 5:32am

OK, so back to getting the patcher’s typed-in arguments:

Is there any chance of getting some example code showing how the patcherargs object goes about this?

Privately if you’d rather, and with the absolute understanding that it’s hacky, unsupported, will break in Max 5, might drink all my booze, kill my cat, sleep with my wife, etc…

#103993
Jun 21, 2007 at 8:54am

Someone will correct me if I’m wrong, but I believe that patcherargs
works using private API and structure definitions which we’re not
going to publish at this time. Sorry!

Waiting is good for the character, at least that’s what my dad used
to tell me.

jb

Am 21.06.2007 um 07:32 schrieb John Pitcairn:

>
> OK, so back to getting the patcher’s typed-in arguments:
>
> Is there any chance of getting some example code showing how the
> patcherargs object goes about this?
>
> Privately if you’d rather, and with the absolute understanding that
> it’s hacky, unsupported, will break in Max 5, might drink all my
> booze, kill my cat, sleep with my wife, etc…

#103994
Jun 21, 2007 at 8:43pm

Quote: Jeremy Bernstein wrote on Thu, 21 June 2007 20:54
—————————————————-
> Waiting is good for the character, at least that’s what my dad
> used to tell me.

Aww. As I used to ask my dad, “are we nearly there yet”? (duck)

Guess I’ll probably take another crack at saving and parsing the patcher binbuf. I’d really really like to get rid of my last patcherargs dependence for this project, so that when Max 5 makes this all magically easier from within an external (right?), there won’t be different patching requirements for 4.6 vs 5.x.

If anyone has any ready-made code for saving and parsing a patcher’s binbuf they’d care to make available, that could save me a fair bit of hacking around, for which I’d be grateful.

#103995

You must be logged in to reply to this topic.