How to apply oo within Max

May 10, 2007 at 9:42am

Here’s a super link, where Amazon got the descriptions of two books
mixed up:

http://www.amazon.de/Judaism-Web-Irving-Green/dp/1558285156/
ref=sr_1_1/302-6214979-8968827?ie=UTF8&s=books-intl-
de&qid=1178789753&sr=1-1

Here’s someone else who shares Tim’s outlook:

http://mail.python.org/pipermail/python-list/2002-December/176508.html

But what they’re really talking about is the dogmatic application and
unbridled evangelism of structural principles, not about communing
with the Great Badger. What we cannot speak about we must pass over
in silence.

jb

Am 10.05.2007 um 09:25 schrieb Mattijs Kneppers:

>
> Hi Tim,
>
> So funny that everyone keeps referring to a religous aspect of oo
> programming and I really don’t have a clue what that is about. Can
> someone send me a link or something that illustrates that idea?
>
> Thanks,
> Mattijs
>
>> Of course, given that what OO means can spark ‘religious’
>> reactions in people, I’m sure that people will disagree — but the
>> point is that OO considerations have weighed heaviliy throughout
>> the entire development of Jamoma, and that continues.
>>
>> Hopefully this is helpful somehow!
>> Tim
>>
> —————————————————-
>
>
> –
> SmadSteck – http://www.smadsteck.nl
> Hard- and software for interactive audiovisual sampling

#100106
May 10, 2007 at 9:52am

Hi Mattijs,

Hanging out on comp.object for any length of time would probably do the
trick. In the meantime the page of holy wars at the portland pattern
wiki (http://c2.com/cgi-bin/wiki?HolyWar) has some good examples, such
as debates about what OO may or may not be
(http://c2.com/cgi-bin/wiki?NobodyAgreesOnWhatOoIs), from whence the
stage is set for just about anybody to disagree with just about anything
(e.g. Java and CPP people on multiple inheritance – a conversation that
never gets interesting).


O

Mattijs Kneppers wrote:
> Hi Tim,
>
> So funny that everyone keeps referring to a religous aspect of oo
> programming and I really don’t have a clue what that is about. Can
> someone send me a link or something that illustrates that idea?
>
> Thanks, Mattijs
>

#100107
May 11, 2007 at 9:50am

Owen Green schrieb:
> Hanging out on comp.object for any length of time would probably do the
> trick. In the meantime the page of holy wars at the portland pattern
> wiki (http://c2.com/cgi-bin/wiki?HolyWar) has some good examples, such
> as debates about what OO may or may not be
> (http://c2.com/cgi-bin/wiki?NobodyAgreesOnWhatOoIs),

Thanks for these links, according to that Object Oriented Programming is:
Program execution is regarded as a physical model, simulating the
behaviour of either a real or imaginary part of the world…

And that’s it. (No hint to inheritance, but practical oo is inherited
from that… ;-)

But OO might also be Orientation Oriented Programming.

I think its just a way of thinking, and I tend not to restrict myself to
a single one. And I spend more likely more time with the easy ones, the
ones I don’t need to think about too much…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#100108
May 11, 2007 at 10:22am

Quote: Stefan Tiedje wrote on Thu, 10 May 2007 11:12
—————————————————-
> Timothy Place schrieb:
> > I’m a bit late to this thread, as I haven’t been actively reading the
> > list/forums for a while now… This thread did catach my attention
> > though.
>
> I followed this thread on/off, and just out of my intuition, I’d advise
> Mattjis and John to really look at Jamoma deeper, because I believe what
> you have been talking and testing about recently is all there, but in an
> advanced state.

I do think you’re right about looking into Jamoma, but rather because they have to deal with the same limitations of max in their implementation.

As long as we stay in Max world (to stay clear of the discussion whether OO is also an architectural pattern like an MVC) I agree that Jamoma and an OO system are similar in that they provide a way to structure complex patches to make them more manageable.

The two systems are fundamentally different though, I’m sure Tim wil agree with me on that. Probably with pro’s and con’s on both sides. Still I want to mention again that OO has been around for quite a while and is not only being used by Max users. I have been taught OO in college, as I am sure a lot of other people have.

Btw, Jamoma is much more than a way to structure patches, it’s also a toolkit for interface building, an object library, a communication protocol, and probably much more. I don’t think the goal of this oo discussion is to address those kind of issues as well..

Mattijs

> It would be great if these discussions would be
> incorporated into Jamoma instead of creating something very similar
> aside of it…
>
> just my 2 cents…
>
> Stefan
>
> —
> Stefan Tiedje————x——-
> –_____———–|————–
> –(_|_ —-|—–|—–()——-
> — _|_)—-|—–()————–
> ———-()——–www.ccmix.com
>
>
—————————————————-

#100109
May 11, 2007 at 10:40am

That’s really interesting, it seems oo has been upsetting a lot of people, something I wasn’t really aware of. Could it be that in big companies oo is being enforced on projects where another system would work much better (or no system, because it’s small and easily manageable)?

I have started using oo only after my projects got big and I felt the need for something, anything, to get more control over data floating around. First I started inventing my own systems, naming conventions etc, but when I learned about oo I kindof compared my own techniques with oo and then decided that oo was beneficial. Which means there was some really convincing evidence, I tend to believe in my own systems and am quite persistent (stubborn ;) by nature.

I now feel exactly the same need for something to get more control over my max projects. I have already been inventing all kinds of systems in the past two years but I guess now would be a great time to make the same fundamental step towards oo.

Mattijs

Quote: Jeremy Bernstein wrote on Thu, 10 May 2007 11:42
—————————————————-
> Here’s a super link, where Amazon got the descriptions of two books
> mixed up:
>
> http://www.amazon.de/Judaism-Web-Irving-Green/dp/1558285156/
> ref=sr_1_1/302-6214979-8968827?ie=UTF8&s=books-intl-
> de&qid=1178789753&sr=1-1
>
> Here’s someone else who shares Tim’s outlook:
>
> http://mail.python.org/pipermail/python-list/2002-December/176508.html
>
> But what they’re really talking about is the dogmatic application and
> unbridled evangelism of structural principles, not about communing
> with the Great Badger. What we cannot speak about we must pass over
> in silence.
>
> jb
>
> Am 10.05.2007 um 09:25 schrieb Mattijs Kneppers:
>
> >
> > Hi Tim,
> >
> > So funny that everyone keeps referring to a religous aspect of oo
> > programming and I really don’t have a clue what that is about. Can
> > someone send me a link or something that illustrates that idea?
> >
> > Thanks,
> > Mattijs
> >
> >> Of course, given that what OO means can spark ‘religious’
> >> reactions in people, I’m sure that people will disagree — but the
> >> point is that OO considerations have weighed heaviliy throughout
> >> the entire development of Jamoma, and that continues.
> >>
> >> Hopefully this is helpful somehow!
> >> Tim
> >>
> > —————————————————-
> >
> >
> > –
> > SmadSteck – http://www.smadsteck.nl
> > Hard- and software for interactive audiovisual sampling
>
>
—————————————————-

#100110
May 11, 2007 at 10:58am

Hi Mattijs,

Jamoma grew out of a need to solve certain issues experienced from
practical work with Max on big projects. Along the way development has
tried to find general approaches, drawing on any philosophy of
programming that we have seen that Jamoma could benefit from. But Jamoma
was not initiated to solve issues concerning how to do oo programming in
Max per se, so you are quite right that the initial objectives have been
different.

I would to like to add that we have also seen the use of oo ways of
thinking on more abstract levels as well, in particular in terms of the
osc namespace used for modules. This is to increasing degree itself
designed according to oo ways of thinking so that any module using e.g.
a limiter will share the same namespace for addressing the parameters of
the limiter, although there might not be any abstractions ready to go to
attach to the modules as a kind of limiter wizards.

I haven’t had the time to follow this discussion in detail, but if you
have the interest, time and energy to look into Jamoma, we would
appreciate any review, criticism and proposals that could help improve
the design of both the Jamoma specification and the Max implementation.

One of the strengths of Jamoma being an open-source project has been
that each new developer joining in has been revealing blind spots in the
construction of the system and suggestions for improvements that we all
feel that the project has benefited largely from. That kind of input is
still very much welcome, and one of the reasons for holding version
numbers at 0.x.x is that we can remain entitled to do changes that break
backwards compatibility if we see that it will have major benefits in
the long run.

Best,
Trond

Mattijs Kneppers wrote:
> Quote: Stefan Tiedje wrote on Thu, 10 May 2007 11:12
> —————————————————-
>> Timothy Place schrieb:
>>> I’m a bit late to this thread, as I haven’t been actively reading the
>>> list/forums for a while now… This thread did catach my attention
>>> though.
>> I followed this thread on/off, and just out of my intuition, I’d advise
>> Mattjis and John to really look at Jamoma deeper, because I believe what
>> you have been talking and testing about recently is all there, but in an
>> advanced state.
>
> I do think you’re right about looking into Jamoma, but rather because they have to deal with the same limitations of max in their implementation.
>
> As long as we stay in Max world (to stay clear of the discussion whether OO is also an architectural pattern like an MVC) I agree that Jamoma and an OO system are similar in that they provide a way to structure complex patches to make them more manageable.
>
> The two systems are fundamentally different though, I’m sure Tim wil agree with me on that. Probably with pro’s and con’s on both sides. Still I want to mention again that OO has been around for quite a while and is not only being used by Max users. I have been taught OO in college, as I am sure a lot of other people have.
>
> Btw, Jamoma is much more than a way to structure patches, it’s also a toolkit for interface building, an object library, a communication protocol, and probably much more. I don’t think the goal of this oo discussion is to address those kind of issues as well..
>
> Mattijs
>
>
>> It would be great if these discussions would be
>> incorporated into Jamoma instead of creating something very similar
>> aside of it…
>>
>> just my 2 cents…
>>
>> Stefan
>>
>> —
>> Stefan Tiedje————x——-
>> –_____———–|————–
>> –(_|_ —-|—–|—–()——-
>> — _|_)—-|—–()————–
>> ———-()——–www.ccmix.com
>>
>>
> —————————————————-
>
>
> –
> SmadSteck – http://www.smadsteck.nl
> Hard- and software for interactive audiovisual sampling
>

#100111
May 11, 2007 at 3:19pm

Hehe, cool stuff, thanks for the links.

Let’s say that we’re inspired to make a system a bit like what Java calls OO, also a bit like what C++ calls OO, but more important like what everyone on this list thinks should be OO in max.

Mattijs

Quote: owen wrote on Thu, 10 May 2007 11:52
—————————————————-
> Hi Mattijs,
>
> Hanging out on comp.object for any length of time would probably do the
> trick. In the meantime the page of holy wars at the portland pattern
> wiki (http://c2.com/cgi-bin/wiki?HolyWar) has some good examples, such
> as debates about what OO may or may not be
> (http://c2.com/cgi-bin/wiki?NobodyAgreesOnWhatOoIs), from whence the
> stage is set for just about anybody to disagree with just about anything
> (e.g. Java and CPP people on multiple inheritance – a conversation that
> never gets interesting).
>
> —
> O
>
> Mattijs Kneppers wrote:
> > Hi Tim,
> >
> > So funny that everyone keeps referring to a religous aspect of oo
> > programming and I really don’t have a clue what that is about. Can
> > someone send me a link or something that illustrates that idea?
> >
> > Thanks, Mattijs
> >
>
—————————————————-

#100112
May 11, 2007 at 4:22pm

Hi Trond,

Thanks for your contextual explanation of Jamoma. I am definitly interested, I’ll look into it more later, perhaps enough to provide some useful feedback. But until it reaches a conclusive state I’ll be focussed on the oo idea, although I can imagine that Jamoma also offers a great deal of practical solutions when it comes to implementation of the oo ideas.

Mattijs

Quote: Trond Lossius wrote on Fri, 11 May 2007 12:58
—————————————————-
> Hi Mattijs,
>
> Jamoma grew out of a need to solve certain issues experienced from
> practical work with Max on big projects. Along the way development has
> tried to find general approaches, drawing on any philosophy of
> programming that we have seen that Jamoma could benefit from. But Jamoma
> was not initiated to solve issues concerning how to do oo programming in
> Max per se, so you are quite right that the initial objectives have been
> different.
>
> I would to like to add that we have also seen the use of oo ways of
> thinking on more abstract levels as well, in particular in terms of the
> osc namespace used for modules. This is to increasing degree itself
> designed according to oo ways of thinking so that any module using e.g.
> a limiter will share the same namespace for addressing the parameters of
> the limiter, although there might not be any abstractions ready to go to
> attach to the modules as a kind of limiter wizards.
>
> I haven’t had the time to follow this discussion in detail, but if you
> have the interest, time and energy to look into Jamoma, we would
> appreciate any review, criticism and proposals that could help improve
> the design of both the Jamoma specification and the Max implementation.
>
> One of the strengths of Jamoma being an open-source project has been
> that each new developer joining in has been revealing blind spots in the
> construction of the system and suggestions for improvements that we all
> feel that the project has benefited largely from. That kind of input is
> still very much welcome, and one of the reasons for holding version
> numbers at 0.x.x is that we can remain entitled to do changes that break
> backwards compatibility if we see that it will have major benefits in
> the long run.
>
> Best,
> Trond
>
>
>
>
>
> Mattijs Kneppers wrote:
> > Quote: Stefan Tiedje wrote on Thu, 10 May 2007 11:12
> > —————————————————-
> >> Timothy Place schrieb:
> >>> I’m a bit late to this thread, as I haven’t been actively reading the
> >>> list/forums for a while now… This thread did catach my attention
> >>> though.
> >> I followed this thread on/off, and just out of my intuition, I’d advise
> >> Mattjis and John to really look at Jamoma deeper, because I believe what
> >> you have been talking and testing about recently is all there, but in an
> >> advanced state.
> >
> > I do think you’re right about looking into Jamoma, but rather because they have to deal with the same limitations of max in their implementation.
> >
> > As long as we stay in Max world (to stay clear of the discussion whether OO is also an architectural pattern like an MVC) I agree that Jamoma and an OO system are similar in that they provide a way to structure complex patches to make them more manageable.
> >
> > The two systems are fundamentally different though, I’m sure Tim wil agree with me on that. Probably with pro’s and con’s on both sides. Still I want to mention again that OO has been around for quite a while and is not only being used by Max users. I have been taught OO in college, as I am sure a lot of other people have.
> >
> > Btw, Jamoma is much more than a way to structure patches, it’s also a toolkit for interface building, an object library, a communication protocol, and probably much more. I don’t think the goal of this oo discussion is to address those kind of issues as well..
> >
> > Mattijs
> >
> >
> >> It would be great if these discussions would be
> >> incorporated into Jamoma instead of creating something very similar
> >> aside of it…
> >>
> >> just my 2 cents…
> >>
> >> Stefan
> >>
> >> —
> >> Stefan Tiedje————x——-
> >> –_____———–|————–
> >> –(_|_ —-|—–|—–()——-
> >> — _|_)—-|—–()————–
> >> ———-()——–www.ccmix.com
> >>
> >>
> > —————————————————-
> >
> >
> > –
> > SmadSteck – http://www.smadsteck.nl
> > Hard- and software for interactive audiovisual sampling
> >
>
>
—————————————————-

#100113
May 12, 2007 at 1:51am

From my point of view, what I’m looking for at least initially is a *very* small set of low-overhead objects that function as a drop-in way of defining public/private scope in Max, with reasonable enforcement of that scope via scope-checked method calls and private variables. This should be relatively easy to retrofit to existing well-structured applications.

Issues of inheritance etc can to some degree be handled with existing Max constructs, and this thread has provided some useful mechanisms for doing so.

#100114
May 12, 2007 at 6:50am

Quote: Stefan Tiedje wrote on Fri, 11 May 2007 03:50

> But OO might also be Orientation Oriented Programming.

Obsolete Overstyled Patching.

Oldfashioned Oversugared Peacake.

Obscure Oriental Pandora

Overtaking Omnicausual Paranoia.

Organized Oligarchic Professors.

#100115
May 13, 2007 at 10:11pm

Mattijs Kneppers schrieb:
> Btw, Jamoma is much more than a way to structure patches, it’s also a
> toolkit for interface building, an object library, a communication
> protocol, and probably much more. I don’t think the goal of this oo
> discussion is to address those kind of issues as well..

You are right, Jamoma is much more, but to achieve it there was the need
to develop oo techniques, and the same can be used for other projects
where these techniques have nothing to do with interface building. But
as soon you start doing things like that, you also start to define
conventions, like defining name spaces. For me who might be interested
in that, I’d simply prefer to follow one single convention than learning
several…
Jamoma is using the naming convention of OSC messages, which is already
different than the pattr naming convention, but both have been
established in the past already…
If the oo techniques of Jamoma would fit your needs, which I do believe
could be the case, then there is neither a need to invent the wheel
again, nor a need to define yet another naming convention.
You could rather put yourself into the Jamoma development discussions,
to get finally all you ever dreamed of, probably faster than doing it
with a team of two…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#100116
May 14, 2007 at 12:34am

Quote: Stefan Tiedje wrote on Mon, 14 May 2007 10:11
—————————————————-
> You could rather put yourself into the Jamoma development
> discussions, to get finally all you ever dreamed of, probably
> faster than doing it with a team of two…

Well, I dunno. What we want is fairly lightweight, we have it mostly prototyped in js and/or max objects, and Jamoma seems well on the way to becoming a big, complex beast. Just the time it would take to learn enough of it to figure out how much of what we want can be done by Jamoma might be non-trivial. And I don’t see Jamoma as something that can be readily retrofitted to existing apps, though I could well be wrong on that. I’m looking for something that operates at a lower level of abstraction.

In any case, I, for one, am not sure I’m willing to inflict my Max-C-for-dummies level programming on an existing development team, or attempt to divert their programming resources from existing goals.

So now that I’ve pretty much given up on extracting the object’s parent patcher arguments directly (see dev forum) – it’s back to [patcherargs], and progress towards a working object might be reasonably rapid.

#100117
Jun 12, 2007 at 9:16pm

Hi all,

Back from Dev to MaxMSP. Thanks to Jeremy Bernstein and Timothy Place for some important in-depth info!

Here is a new example. It is the same as my previous one except that the javascripts are replaced by C externals (mac only for now) which results in a vast improvement of speed and stability. Make sure to copy the externals to the Cycling ’74/externals folder before starting the main patch.

http://www.arttech.nl/OO%20example%20Mattijs%20070611.zip

Please feel free to post comments and ideas about both concept and implementation. I included the source code of the externals.

I believe this version is ready for testing in bigger patches, which I will start doing from now. I’m really curious whether this system could create practical support for OO programming in Max.

Cheers,
Mattijs

Quote: Mattijs wrote on Thu, 10 May 2007 09:18
—————————————————-
> Also looking into the SDK for ways to traverse patcher hierarchy and such. So far I only wrote externals for data management and some dsp, didn’t spend much time interfacing with max. If someone happens to have an example that does stuff similar to the javascripts in these oo examples and you’re willing to share.. that would be great.
>
> Mattijs

#100118
Jun 13, 2007 at 1:14am

Nice. Lots faster than the js version on my lowly 1GHz TiBook, the speed test runs stably at close to 80ms, compared to a very jittery 380ms for your earlier js-version.

For that “shady” 1024-character path string declaration you’ve commented in the source, it’s best to malloc some memory I think, ie:

str = malloc(strlen(path->s_name));
if(str != NULL) strcpy(str, path->s_name);

…do stuff…

free(str);

It will be interesting to see how my version will stack up against this for speed. I’m avoiding send/receive/forward altogether, which helps prevent circumvention of the scoping, and the call path is validated against the caller’s scope when oo.call receives its first input (or when its call changes).

The eventual plan is to allow oo.call to address a method in all like-named objects in a scope by using a name[-1].method call, so you don’t need to track how many there are.

I suspect the validation will prove very expensive in situations like your example, necessitating some caching of the validated paths to speed things up.

Back soon…

#100119
Jun 13, 2007 at 3:54am

Quote: johnpitcairn wrote on Wed, 13 June 2007 13:14
—————————————————-
> I suspect the validation will prove very expensive in
> situations like your example.

Huh. Or perhaps not. I’ve put together the same test using my objects, and even with the calls being scope-validated for each call change, it still runs at 24ms on my lowly TiBook. I guess the message-passing among objects still incurs considerable overhead in your abstractions.

It will be interesting to see if a call scope-validation caching scheme (hashtab-based I guess) would be a significant improvement on that, though I’m not sure that’s something I’ll bother with unless the performance is still unsatisfactory in the real world.

I’ll hold off on posting the objects until I have call and method accepting all input (currently just int), and I’d like to add private variables. But contact me privately if you want to take a look at it now (it’s reasonably commented).

#100120
Jun 13, 2007 at 8:35am

Quote: johnpitcairn wrote on Wed, 13 June 2007 03:14
—————————————————-
> Nice. Lots faster than the js version on my lowly 1GHz TiBook, the speed test runs stably at close to 80ms, compared to a very jittery 380ms for your earlier js-version.
>
> For that “shady” 1024-character path string declaration you’ve commented in the source, it’s best to malloc some memory I think, ie:
>
> str = malloc(strlen(path->s_name));
> if(str != NULL) strcpy(str, path->s_name);
>
> …do stuff…
>
> free(str);

Ah, thanks :)

>
>
> It will be interesting to see how my version will stack up against this for speed.

I am quite sure there is a lot to gain by programming the functionality of the surrounding native objects inside the custom ones. As far as I can see the only native object necessary should be the patcherargs object.

But before I start optimizing I’d like to test this in a real life situation, to check the concept. The javascript versions were so abysmally slow that testing in a big patch was impossible but the step to C solves that problem.

> I’m avoiding send/receive/forward altogether, which helps prevent circumvention of the scoping, and the call path is validated against the caller’s scope when oo.call receives its first input (or when its call changes).

Path validation is one of the first things I would add too, as is storing the references in a proper doubly linked list inside the external instead of id’s in a coll. I’m very curious how you’re doing.

>
> The eventual plan is to allow oo.call to address a method in all like-named objects in a scope by using a name[-1].method call, so you don’t need to track how many there are.

That sounds like a good idea.

>
> I suspect the validation will prove very expensive in situations like your example, necessitating some caching of the validated paths to speed things up.
>
> Back soon…
>

Quote: johnpitcairn wrote on Wed, 13 June 2007 05:54
—————————————————-
> I’ve put together the same test using my objects, and even with the calls being scope-validated for each call change, it still runs at 24ms on my lowly TiBook.

Cool :)

> I guess the message-passing among objects still incurs considerable overhead in your abstractions.

I am sure about that.

>
> It will be interesting to see if a call scope-validation caching scheme (hashtab-based I guess) would be a significant improvement on that, though I’m not sure that’s something I’ll bother with unless the performance is still unsatisfactory in the real world.
>
> I’ll hold off on posting the objects until I have call and method accepting all input (currently just int), and I’d like to add private variables. But contact me privately if you want to take a look at it now (it’s reasonably commented).

Allthough this will probably tempt me to dive into the code again (which I want to avoid because I want to test the concept first), I would like to have a peek. I’ll send you a message off-list.

Best,
Mattijs

#100121
Jun 13, 2007 at 9:35pm

Quote: Mattijs wrote on Wed, 13 June 2007 20:35
—————————————————-
> Path validation is one of the first things I would add too, as
> is storing the references in a proper doubly linked list
> inside the external instead of id’s in a coll. I’m very
> curious how you’re doing.

Each object (scoped or not) registers a pointer to itself in a t_linklist in its parent object.

Each object that defines a public or private scope also stores registered child scope names in a “namespace” t_hashtab. Namespace entries are t_linklists containing pointers to the object-instances of that name. If an object is deleted, the appropriate linked list entry is set to NULL (not removed), and is re-used by the next-created instance of the same name – so if you delete name[55], higher instances are not re-numbered, and you can re-create name[55].

The trick with call path validation is that it can’t happen until the entire object heirarchy for the path is built and registered, and the caller may not be in that heirarchy. This means you can’t validate the path at oo.call instantiation, nor on patcherargs “done” – you’d need to deferlow which makes it difficult to know when the patch is ready to go. So oo.call is validating at first data input, or whenever the call path changes. It’s rather less expensive than I thought it would be.

#100122
Jul 19, 2007 at 12:22am

This is just to say that if you guys make any more progress on applying oo principles in max, I for one would love to hear about it here on the forum …

#100123
Jul 19, 2007 at 2:58am

From another thread, but worth reposting here:

An update from my perspective: as Mattijs said, it’s being worked on, though what we have is not part of the pattr system, and doesn’t use pattr syntax (my version can be recompiled to use object:method rather than object.method if desired).

I’m a little busy to work on my version much at present, but in its current state it implements public/private objects (patcher, abstraction, bpatcher or poly~) containing public/private methods that can return a message to the caller.

Calls to methods are scope-checked at first call, using top-down global syntax (:object.object.method), scope-relative local syntax (object.object.method), or scope-relative parent syntax (..object.object.method).

Mattijs has suggested not implementing a public/private variable object as such, instead simply defining a method that sets/gets any suitable int, float, list or symbol storage object, and calling to that from wherever it’s needed. I’m warming to this idea.

I’ve recently implemented the system entirely as externals rather than using abstractions, and method call/return are now very efficient, similar to using just send/receive.

Some work needs to be done between Mattijs and myself to merge our somewhat divergent ideas, with better agreement on scoping and naming conventions. I’d be reluctant to make anything available until we have that locked down.

But we’re getting there…

#100124
Jul 19, 2007 at 3:19am

I would highly recommend open sourcing this project. I think its a
very interesting, and would love to see where it goes.

Thanks for the update.

On Jul 18, 2007, at 10:58 PM, John Pitcairn wrote:

>
>> From another thread, but worth reposting here:
>
> An update from my perspective: as Mattijs said, it’s being worked
> on, though what we have is not part of the pattr system, and
> doesn’t use pattr syntax (my version can be recompiled to use
> object:method rather than object.method if desired).
>
> I’m a little busy to work on my version much at present, but in its
> current state it implements public/private objects (patcher,
> abstraction, bpatcher or poly~) containing public/private methods
> that can return a message to the caller.
>
> Calls to methods are scope-checked at first call, using top-down
> global syntax (:object.object.method), scope-relative local syntax
> (object.object.method), or scope-relative parent syntax
> (..object.object.method).
>
> Mattijs has suggested not implementing a public/private variable
> object as such, instead simply defining a method that sets/gets any
> suitable int, float, list or symbol storage object, and calling to
> that from wherever it’s needed. I’m warming to this idea.
>
> I’ve recently implemented the system entirely as externals rather
> than using abstractions, and method call/return are now very
> efficient, similar to using just send/receive.
>
> Some work needs to be done between Mattijs and myself to merge our
> somewhat divergent ideas, with better agreement on scoping and
> naming conventions. I’d be reluctant to make anything available
> until we have that locked down.
>
> But we’re getting there…

v a d e //

http://www.vade.info
abstrakt.vade.info

#100125
Jul 19, 2007 at 9:43am

A little update from my side; I’m almost done with a first version of a more or less complex patch that is programmed with my current version of the oo objects, according to what I believe is an oo way of thinking within Max. The purpose is to clearly lay out the idea behind the oo system, as well as reality-checking the oo objects in the process of programming this patch. I’m very curious what your reactions will be.

If someone likes to comment on work in progress I’ll post the current state of what I’m working on, otherwise I’ll wait until there is something really new and report back. Once the first version of my demonstration patch is finished I will first send it to John and wait for his comments, then post it on the forum.

John’s objects are better optimized than mine at the moment, since my priorities lie with the demo patch. In my opinion the very best thing would be to come to a point where my demo patch uses John’s externals. But as John said, we’ll have to do some more thinking about the most suitable scoping and naming conventions.

John, I didn’t have the chance to reply to your most recent mails yet (I prefer to answer your mails carefully, which, including some research and testing, could easily take me a long evening seeing that english is not my native language. ;) I’m running up to a major deadline for other work, but please know that I will reply as soon as I have some time.

Cheers,
Mattijs

#100126
Oct 12, 2007 at 4:02am

This is a follow-up on this conversation: http://www.cycling74.com/forums/index.php?t=rview&goto=117854#msg_117854

A bit about my perspective:
I am a full-time OO programmer so I know there are many good ideas to draw from OO, but Max is not OO and so it doesn’t make sense (to me) to try to artificially force it to be OO. Use what works!

As far as send/receive: I think of them like the “goto” command in other languages. That is not to say you should never use it. Certainly for inter-patch communication they work well. For OO-related issues though, I don’t want to jump through hoops creating the namespaces needed for send/receive to work without unwanted collisions. Also, having messages jump from one place to another breaks Max’s dataflow paradigm and can make it harder to debug. With the approach I am about to show it is trivial to attach a print to the inlet of each abstraction and see exactly what’s going on.

So how do I avoid using send & receive in complicated patcher hierarchies? By consistently applying a very simple routing pattern as demonstrated in the patch below. Follow the subpatchers all the way down to see what is going on. This is a laughably simple idea, but really, this pattern has been working quite well for me so far.

A critical part of this pattern is the use of a single inlet connected to a route object. Route exactly defines the public interface that an abstraction/object can handle. This makes patches more readable and self-documenting, in my opinion.

Note that all the like-named subpatchers are identical, yet a clear namespace with many unique objects and params is constructed. I like the symmetry here, it allows for easy reusability/multiple instantiation of objects. This pattern also carries over well to poly~ patches (arrays of objects), with the help of an abstraction to convert to “voice X, message” format.

Finally, I need to give some credit to Ali Momeni. In Max/MSP school he pointed out this pattern a few times and says over the years he’s seen a lot of successful Maxers using it. I had intuitively used it a couple times, but after hearing that I started using it very methodically to my benefit.

-Adam

#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N vpatcher 153 554 534 846;
#P window setfont “Sans Serif” 9.;
#N vpatcher 245 517 537 808;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N vpatcher 141 165 492 473;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 375 203 645 460;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 3 0 2 0;
#P connect 4 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P window linecount 0;
#P newex 55 149 82 196617 prepend param1;
#P window linecount 1;
#N vpatcher 394 201 664 458;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 3 0 2 0;
#P connect 4 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P window linecount 0;
#P newex 55 74 108 196617 route param1 param2;
#P outlet 55 218 15 0;
#P inlet 55 44 15 0;
#P connect 0 0 2 0;
#P connect 2 0 3 0;
#P connect 3 0 4 0;
#P connect 4 0 1 0;
#P connect 6 0 1 0;
#P connect 2 1 5 0;
#P connect 5 0 6 0;
#P pop;
#P newobj 118 125 32 196617 p obj;
#P outlet 60 217 15 0;
#P newex 142 166 68 196617 prepend obj2;
#P window linecount 0;
#P newex 60 166 68 196617 prepend obj1;
#N vpatcher 141 165 492 473;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 375 203 645 460;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 4 0 2 0;
#P connect 3 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P window linecount 0;
#P newex 55 149 82 196617 prepend param1;
#P window linecount 1;
#N vpatcher 394 201 664 458;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 4 0 2 0;
#P connect 3 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P window linecount 0;
#P newex 55 74 108 196617 route param1 param2;
#P outlet 55 218 15 0;
#P inlet 55 44 15 0;
#P connect 0 0 2 0;
#P connect 2 0 3 0;
#P connect 3 0 4 0;
#P connect 6 0 1 0;
#P connect 4 0 1 0;
#P connect 2 1 5 0;
#P connect 5 0 6 0;
#P pop;
#P newobj 60 127 32 196617 p obj;
#P newex 60 83 80 196617 route obj1 obj2;
#P inlet 60 40 15 0;
#P connect 0 0 1 0;
#P connect 1 0 2 0;
#P connect 2 0 3 0;
#P connect 4 0 5 0;
#P connect 3 0 5 0;
#P connect 1 1 6 0;
#P connect 6 0 4 0;
#P pop;
#P newobj 145 103 43 196617 p group;
#P newex 145 143 79 196617 prepend group2;
#P newex 50 143 79 196617 prepend group1;
#P newex 50 50 102 196617 route group1 group2;
#N vpatcher 704 567 1030 864;
#P window setfont “Sans Serif” 9.;
#N vpatcher 141 165 492 473;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 375 203 645 460;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 4 0 2 0;
#P connect 3 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P window linecount 0;
#P newex 55 149 82 196617 prepend param1;
#P window linecount 1;
#N vpatcher 394 201 664 458;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 4 0 2 0;
#P connect 3 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P window linecount 0;
#P newex 55 74 108 196617 route param1 param2;
#P outlet 55 218 15 0;
#P inlet 55 44 15 0;
#P connect 0 0 2 0;
#P connect 2 0 3 0;
#P connect 3 0 4 0;
#P connect 6 0 1 0;
#P connect 4 0 1 0;
#P connect 2 1 5 0;
#P connect 5 0 6 0;
#P pop;
#P newobj 118 125 32 196617 p obj;
#P outlet 60 217 15 0;
#P newex 142 166 68 196617 prepend obj2;
#P window linecount 0;
#P newex 60 166 68 196617 prepend obj1;
#N vpatcher 973 82 1324 390;
#P window setfont “Sans Serif” 9.;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 375 203 645 460;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 3 0 2 0;
#P connect 4 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P window linecount 0;
#P newex 55 149 82 196617 prepend param1;
#P window linecount 1;
#N vpatcher 1103 533 1373 790;
#P outlet 59 168 15 0;
#P window setfont “Sans Serif” 9.;
#P window linecount 0;
#P newex 82 107 62 196617 prepend set;
#P button 53 110 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 53 82 68 196617 route get set;
#P inlet 53 50 15 0;
#P connect 0 0 1 0;
#P connect 1 0 3 0;
#P connect 3 0 2 0;
#P connect 4 0 2 0;
#P connect 2 0 5 0;
#P connect 1 1 4 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P window linecount 0;
#P newex 55 74 108 196617 route param1 param2;
#P outlet 55 218 15 0;
#P inlet 55 44 15 0;
#P connect 0 0 2 0;
#P connect 2 0 3 0;
#P connect 3 0 4 0;
#P connect 4 0 1 0;
#P connect 6 0 1 0;
#P connect 2 1 5 0;
#P connect 5 0 6 0;
#P pop;
#P newobj 60 127 32 196617 p obj;
#P newex 60 83 80 196617 route obj1 obj2;
#P inlet 60 40 15 0;
#P connect 0 0 1 0;
#P connect 1 0 2 0;
#P connect 2 0 3 0;
#P connect 3 0 5 0;
#P connect 4 0 5 0;
#P connect 1 1 6 0;
#P connect 6 0 4 0;
#P pop;
#P newobj 50 103 43 196617 p group;
#P inlet 50 25 15 0;
#P outlet 50 223 15 0;
#P connect 1 0 3 0;
#P connect 3 0 2 0;
#P connect 2 0 4 0;
#P connect 4 0 0 0;
#P connect 5 0 0 0;
#P connect 3 1 6 0;
#P connect 6 0 5 0;
#P pop;
#P newobj 200 229 80 196617 p datastructure;
#P newex 279 94 156 196617 prepend group1 obj2 param2 set;
#P number 279 59 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 317 118 118 196617 group1 obj2 param2 get;
#P newex 479 130 156 196617 prepend group2 obj1 param2 set;
#P newex 86 85 156 196617 prepend group1 obj1 param1 set;
#P number 479 94 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 86 50 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 516 153 118 196617 group2 obj1 param2 get;
#P message 126 110 118 196617 group1 obj1 param1 get;
#P message 200 299 192 196617 result of get message will appear here…;
#P newex 200 261 62 196617 prepend set;
#P connect 4 0 6 0;
#P connect 3 0 11 0;
#P connect 2 0 11 0;
#P connect 8 0 11 0;
#P connect 6 0 11 0;
#P connect 10 0 11 0;
#P connect 7 0 11 0;
#P connect 11 0 0 0;
#P connect 0 0 1 0;
#P connect 9 0 10 0;
#P connect 5 0 7 0;
#P window clipboard copycount 12;

#100127
Oct 12, 2007 at 6:12am

Hm. Thats not bad, but seems like a lot of work for very little pay
off in my opinion. Automatically loading patchers, creating named
sends and recieves is not that hard with javascript. Im half way
through porting some of my v001 loading stuff from (ugly) patcher
based scripts to javascript, and its nice because all I have to do is
just duplicate a module on disk, and it is automatically loaded again
at runtime, has a unique name, a unique send/receive pair, can be
loaded in a bank of effects if I want, etc etc.

Here is a simple module loading javascript that I used for a client
to load single instances of a module folder. I personally find using
sends/recives as with namespaces much more dynamic and flexible, and
actually fits in my head more closely with the patching paradigm (the
patchcoords are just invisible, thats ok!) than with hyper nested
routes, prepends, getting and setting.

But I really think that this al comes down to style. I never worked
that way, so it doesnt really ‘work’ for me, and id imagine its vice
versa.

However, now that ive said all that, there is nothing to stop you
from automating the creation of these routing groups either. Hm. I
guess ive got nothing to say, but you might find this interesting:

note this does not implement the sends and receive creation, because
i havent gotten to it, but you can see how using a few of these could
be useful maybe?

Iterating through each module and creating a send and receive for
each inlet/outlet should be fairly straightforward.

On Oct 12, 2007, at 12:02 AM, Adam Murray wrote:

v a d e //

http://www.vade.info
abstrakt.vade.info

#100128
Oct 12, 2007 at 8:05am

Quote: vade wrote on Thu, 11 October 2007 23:12
—————————————————-
>
> Hm. Thats not bad, but seems like a lot of work for very little pay
> off in my opinion.

My example was contrived for educational purposes ;) I don’t normally go that many levels deep and I don’t normally use getters.

The important idea is the single inlet + route to establish an interface. There’s no reason you couldn’t make this a receive + route. Then you have a choice to message an object or to message its parameters directly (is that a choice worth having?)

A better example is a synth patch with “route amp freq env detune noteon noteoff”. I’ve made a few synths and consistently used this route at the top. The big benefit became clear later once I implemented a decoupled GUI control patch. I can easily swap in any of my synths thanks to a consistent interface. I imagine you get the same benefits from a consistent send/receive system.

Lots of routes will impose overhead that could be avoided with send/receive. But maybe some non-technical Maxers who don’t do scripts will find the route approach easier?

> But I really think that this al comes down to style. I never worked
> that way, so it doesnt really ‘work’ for me, and id imagine its vice
> versa.

Yes, it is all about style. The point is to find a pattern that makes sense to you and apply it consistently. That’s how you keep a handle on complex patches and can come back later to modify or extend it without breaking it.

Perhaps this idea of appying OO to Max is so interesting because OO has a fairly intuitive formal structure that it imposes on programs. That makes it easier to build large systems because of the structural consistency. In many ways, Max is kind of structureless and I think that’s why people tend to have trouble making more complex patches.

> you might find this interesting:
>

I don’t see anything… did the forum swallow it?

I realized I shouldn’t criticize the send/receive approach until I’ve played with few well designed patch that use it, so I am eager to see some. I’m sure I could learn a thing or two.

-Adam

#100129
Oct 12, 2007 at 10:43am

Quote: adamj wrote on Fri, 12 October 2007 06:02
—————————————————-
> This is a follow-up on this conversation:

Hi Adam, thanks for sharing.

Below is the way your patch would look with the oo system (but note that our ideas are still evolving!). This is a working example (on my computer) but I replaced the externals with dummy abstractions because the externals I used are really temporary, before posting them I’d like to make sure they are properly coded otherwise you’re all going to laugh at me. ;)

Comparing the two patches, I think they are pretty similar where functionality and structure are concerned. From what I see the oo system would fit very well in your patching style, mostly adding some practical benefits.

A real difference is that your system takes significantly more mouse clicks to set up due to the patch cords-only approach. My experience is that this prevents me from restructuring and encapsulating frequently, something I found essential when working with complex patches. I also think the message overhead in your patch is significantly larger. An oo.call object resolves the path to its oo.method only once and then saves a pointer to it. In fact your patch resolves the path again on every call.

However I really like looking at your patch, it is a very clean example of introducing scope and a call path in max within the current limitations.

I hope we (John and me) are able to post a beta version of the objects in this thread soon, together with a relatively large example patch that is built using the oo objects.

Mattijs

– save as oo.class –

#N comlet (symbol) unique reference;
#P outlet 21 135 15 0;
#N comlet info: print members;
#P inlet 21 30 15 0;
#P objectname (info);
#P comment 32 85 41 196617 dummy;

– save as oo.call –

#N comlet (symbol) call path;
#P inlet 60 30 15 0;
#P objectname (info)[1];
#N comlet (anything) return value;
#P outlet 21 135 15 0;
#N comlet (anything) arguments;
#P inlet 21 30 15 0;
#P objectname (info);
#P comment 32 85 41 196617 dummy;

– save as oo.method –

#N comlet (anything) input to method body;
#P outlet 21 135 15 0;
#N comlet (anything) return value;
#P inlet 21 30 15 0;
#P objectname (info);
#P comment 32 85 41 196617 dummy;

– main patch –

#P window setfont “Sans Serif” 9.;
#P message 456 120 62 196617;
#P window linecount 1;
#P newex 456 99 62 196617 prepend set;
#P window linecount 0;
#P message 248 120 62 196617;
#P window linecount 1;
#P newex 248 99 62 196617 prepend set;
#P button 439 58 15 0;
#P number 456 58 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 456 78 165 196617 oo.call group2.obj1.param2.getSet;
#P window linecount 0;
#P message 40 120 62 196617;
#P button 231 58 15 0;
#P number 248 58 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 248 78 165 196617 oo.call group1.obj2.param2.getSet;
#P button 23 58 15 0;
#P newex 20 21 46 196617 oo.class;
#P number 40 58 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#N vpatcher 68 358 230 486;
#P window setfont “Sans Serif” 9.;
#N vpatcher 150 415 346 567;
#P window setfont “Sans Serif” 9.;
#N vpatcher 210 480 483 648;
#P window setfont “Sans Serif” 9.;
#N vpatcher 282 550 632 786;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 3 0 1 0;
#P connect 4 0 1 0;
#P connect 3 1 4 0;
#P pop;
#P newobj 26 87 120 196617 p param @public param2;
#P objectname param2;
#P newex 9 27 46 196617 oo.class;
#N vpatcher 282 550 632 786;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 4 0 1 0;
#P connect 3 0 1 0;
#P connect 3 1 4 0;
#P pop;
#P newobj 26 67 120 196617 p param @public param1;
#P objectname param1;
#P pop;
#P newobj 21 80 92 196617 p obj @public obj2;
#P objectname obj2;
#P newex 12 24 46 196617 oo.class;
#N vpatcher 210 480 483 648;
#P window setfont “Sans Serif” 9.;
#N vpatcher 282 550 632 786;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 4 0 1 0;
#P connect 3 0 1 0;
#P connect 3 1 4 0;
#P pop;
#P newobj 26 87 120 196617 p param @public param2;
#P objectname param2;
#P newex 9 27 46 196617 oo.class;
#N vpatcher 282 550 632 786;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 3 0 1 0;
#P connect 4 0 1 0;
#P connect 3 1 4 0;
#P pop;
#P newobj 26 67 120 196617 p param @public param1;
#P objectname param1;
#P pop;
#P newobj 21 60 92 196617 p obj @public obj1;
#P objectname obj1;
#P pop;
#P newobj 17 60 114 196617 p group @public group2;
#P objectname group2;
#N vpatcher 233 383 389 522;
#P window setfont “Sans Serif” 9.;
#N vpatcher 210 480 483 648;
#P window setfont “Sans Serif” 9.;
#N vpatcher 282 550 632 786;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 4 0 1 0;
#P connect 3 0 1 0;
#P connect 3 1 4 0;
#P pop;
#P newobj 26 87 120 196617 p param @public param2;
#P objectname param2;
#P newex 9 27 46 196617 oo.class;
#N vpatcher 282 550 632 786;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 3 0 1 0;
#P connect 4 0 1 0;
#P connect 3 1 4 0;
#P pop;
#P newobj 26 67 120 196617 p param @public param1;
#P objectname param1;
#P pop;
#P newobj 21 80 92 196617 p obj @public obj2;
#P objectname obj2;
#P newex 12 24 46 196617 oo.class;
#N vpatcher 393 406 580 558;
#P window setfont “Sans Serif” 9.;
#N vpatcher 282 550 632 786;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 3 0 1 0;
#P connect 4 0 1 0;
#P connect 3 1 4 0;
#P pop;
#P newobj 26 87 120 196617 p param @public param2;
#P objectname param2;
#P newex 9 27 46 196617 oo.class;
#N vpatcher 585 429 797 631;
#P window setfont “Sans Serif” 9.;
#P newex 94 117 62 196617 prepend set;
#P newex 47 95 57 196617 route bang;
#P newex 12 26 46 196617 oo.class;
#P number 47 139 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 47 74 87 196617 oo.method getSet;
#P fasten 1 0 0 0 52 160 31 160 31 66 52 66;
#P connect 0 0 3 0;
#P connect 4 0 1 0;
#P connect 3 0 1 0;
#P connect 3 1 4 0;
#P pop 1;
#P newobj 26 67 120 196617 p param @public param1;
#P objectname param1;
#P pop 1;
#P newobj 21 60 92 196617 p obj @public obj1;
#P objectname obj1;
#P pop 1;
#P newobj 17 40 114 196617 p group @public group1;
#P objectname group1;
#P pop 1;
#P newobj 40 163 80 196617 p datastructure;
#P objectname datastructure;
#P newex 40 99 62 196617 prepend set;
#P newex 40 78 165 196617 oo.call group1.obj1.param1.getSet;
#P comment 103 22 152 196617 Illustration only , not functional;
#P connect 16 0 17 0;
#P connect 11 0 16 0;
#P connect 13 0 11 0;
#P connect 12 0 11 0;
#P connect 14 0 15 0;
#P connect 7 0 14 0;
#P connect 9 0 7 0;
#P connect 8 0 7 0;
#P connect 2 0 10 0;
#P connect 1 0 2 0;
#P connect 6 0 1 0;
#P connect 4 0 1 0;
#P window clipboard copycount 18;

#100130
Oct 12, 2007 at 2:36pm

Well – apparently *this is not possible at all* with javascript in
Max 4.x Who’d have thought? That puts a halt to my plans.

On Oct 12, 2007, at 2:12 AM, vade wrote:

>
> Iterating through each module and creating a send and receive for
> each inlet/outlet should be fairly straightforward.
>
>

v a d e //

http://www.vade.info
abstrakt.vade.info

#100131
Oct 13, 2007 at 9:28am

if you name your outlets “outlet0″ “oulet1″ … and have a js that
counts them interal to the patch, and then outputs that count, then
maybe. Or another internal variable that updates and stores the
result in a messagebox or numberbox other object when the module is
saved.

I think the trick here is having some data fields that are internal
to the module for the external patch to query from the module when it
is loaded, instead of dynamically counting the inlets/outlets at each
load.

cheers
evan

On Oct 12, 2007, at 3:36 PM, vade wrote:

> Well – apparently *this is not possible at all* with javascript in
> Max 4.x Who’d have thought? That puts a halt to my plans.
>
> On Oct 12, 2007, at 2:12 AM, vade wrote:
>
>>
>> Iterating through each module and creating a send and receive for
>> each inlet/outlet should be fairly straightforward.
>>
>>
>
> v a d e //
>
> http://www.vade.info
> abstrakt.vade.info
>
>
>

#100132
Oct 13, 2007 at 7:32pm

i have no idea what you’re doing, or how to do this in js, but…
is there a way you can access the outlets in a while loop, increment a counter, catch your errors, and break from the while loop when you receive an error that indicates the outlet doesn’t exist?

(pseudo-code)
no_error = true;
count = 0;
while(no_error){
no_error = check_outlet(outlets[count++]);
}

that’s how you query for the number of audio channels available on a device when using openal. no idea if that’s doable in js.

-rob

#100133
Oct 15, 2007 at 11:10pm

Quote: Mattijs wrote on Fri, 12 October 2007 03:43
—————————————————-
> Comparing the two patches, I think they are pretty similar where functionality and structure are concerned. From what I see the oo system would fit very well in your patching style, mostly adding some practical benefits.

> the message overhead in your patch is significantly larger. An oo.call object resolves the path to its oo.method only once and then saves a pointer to it. In fact your patch resolves the path again on every call.

Yes, this is a very good point and probably the biggest deficiency in my approach. I am concerned how much I can scale up, but when patches get too complicated I often start implementing externals so it hasn’t been a major limitation for me yet. When you & John provide a nice set of objects for oo style method calling, if I can drop it into my patches with a little rework to get a performance boost then I am on board.

I mostly have a problem with send/receive because of it’s global nature and potential for collisions when running multiple copies of a patch side by side. A well designed object messaging system that hides those sorts of issues would be very nice indeed.

-Adam

#100134
Oct 25, 2007 at 10:06am

Adam Murray schrieb:
> As far as send/receive: I think of them like the “goto” command in
> other languages. That is not to say you should never use it.

Yes, absolutely…

> Note that all the like-named subpatchers are identical, yet a clear
> namespace with many unique objects and params is constructed.

I use the pattr system for this kind of message passing, much less
connections, no routes necessary and creating the namespace works
automatically.
The pattr namespace allows also for easily finding the targets of the
messages…

A somehow modified version of your example below…
Its not complete, but you get the idea, as a pattr object can be
reassigned to another pattr object somwhere within the whole patch…

Stefan

#P window setfont “Sans Serif” 9.;
#P window linecount 3;
#P newex 228 90 124 196617 pattrforward
datastructure::group[1]::obj[2]::param[2]::param;
#P number 228 55 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 367 90 124 196617 pattrforward
datastructure::group[2]::obj[1]::param[2]::param;
#P newex 92 90 124 196617 pattrforward
datastructure::group[1]::obj[1]::param[1]::param;
#P number 367 54 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 92 65 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P message 96 271 192 196617 group2 obj1 param2 17;
#P newex 96 233 62 196617 prepend set;
#N vpatcher 268 308 649 600;
#P window setfont “Sans Serif” 9.;
#N vpatcher 624 338 950 635;
#P outlet 60 217 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 142 166 68 196617 prepend obj2;
#P newex 60 166 68 196617 prepend obj1;
#N vpatcher 573 131 924 439;
#P window setfont “Sans Serif” 9.;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 17;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P objectname param[2];
#P newex 55 149 82 196617 prepend param1;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 0;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P objectname param[1];
#P outlet 55 218 15 0;
#P connect 1 0 2 0;
#P connect 4 0 0 0;
#P connect 2 0 0 0;
#P connect 3 0 4 0;
#P pop;
#P newobj 60 127 32 196617 p obj;
#P objectname obj[1];
#N vpatcher 573 131 924 439;
#P window setfont “Sans Serif” 9.;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 0;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P objectname param[2];
#P newex 55 149 82 196617 prepend param1;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 0;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P objectname param[1];
#P outlet 55 218 15 0;
#P connect 1 0 2 0;
#P connect 2 0 0 0;
#P connect 4 0 0 0;
#P connect 3 0 4 0;
#P pop;
#P newobj 142 127 32 196617 p obj;
#P objectname obj[2];
#P connect 1 0 2 0;
#P connect 3 0 4 0;
#P connect 2 0 4 0;
#P connect 0 0 3 0;
#P pop;
#P newobj 145 103 43 196617 p group;
#P objectname group[2];
#P newex 145 143 79 196617 prepend group2;
#P newex 50 143 79 196617 prepend group1;
#N vpatcher 624 338 950 635;
#P outlet 60 217 15 0;
#P window setfont “Sans Serif” 9.;
#P newex 142 166 68 196617 prepend obj2;
#P newex 60 166 68 196617 prepend obj1;
#N vpatcher 573 131 924 439;
#P window setfont “Sans Serif” 9.;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 0;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P objectname param[2];
#P newex 55 149 82 196617 prepend param1;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 9;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P objectname param[1];
#P outlet 55 218 15 0;
#P connect 1 0 2 0;
#P connect 2 0 0 0;
#P connect 4 0 0 0;
#P connect 3 0 4 0;
#P pop;
#P newobj 60 127 32 196617 p obj;
#P objectname obj[1];
#N vpatcher 573 131 924 439;
#P window setfont “Sans Serif” 9.;
#P newex 154 150 82 196617 prepend param2;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 16;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 154 119 46 196617 p param;
#P objectname param[2];
#P newex 55 149 82 196617 prepend param1;
#N vpatcher 121 345 391 602;
#P window setfont “Sans Serif” 9.;
#P newex 31 105 66 196617 pattr param;
#X prestore 1 0 0;
#P objectname param;
#P outlet 59 168 15 0;
#P number 59 136 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P objectname number;
#P connect 2 1 0 0;
#P connect 0 0 1 0;
#P pop;
#P newobj 55 118 46 196617 p param;
#P objectname param[1];
#P outlet 55 218 15 0;
#P connect 1 0 2 0;
#P connect 4 0 0 0;
#P connect 2 0 0 0;
#P connect 3 0 4 0;
#P pop;
#P newobj 142 127 32 196617 p obj;
#P objectname obj[2];
#P connect 1 0 2 0;
#P connect 2 0 4 0;
#P connect 3 0 4 0;
#P connect 0 0 3 0;
#P pop;
#P newobj 50 103 43 196617 p group;
#P objectname group[1];
#P outlet 50 223 15 0;
#P connect 1 0 2 0;
#P connect 2 0 0 0;
#P connect 3 0 0 0;
#P connect 4 0 3 0;
#P pop;
#P newobj 96 205 80 196617 p datastructure;
#P objectname datastructure;
#P connect 4 0 6 0;
#P connect 7 0 8 0;
#P connect 3 0 5 0;
#P connect 0 0 1 0;
#P connect 1 0 2 0;
#P window clipboard copycount 9;


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#100135
Oct 26, 2007 at 6:34am

Quote: Stefan Tiedje wrote on Thu, 25 October 2007 03:06
—————————————————-
>
> I use the pattr system for this kind of message passing, much less
> connections, no routes necessary and creating the namespace works
> automatically.
> The pattr namespace allows also for easily finding the targets of the
> messages…
>

Nice. I like this approach, except how it is still using prepends and connections for the “getter”. I think the best option for that right now is a pattrhub.

Another useful pattern from OO programming is the EventListener. For that, a reverse pattrforward would be perfect, but until C74 gives us that we can use a pattr object bound to another pattr. There is a major annoyance with using redundant pattrs like that though: it can really clutter up your pattrstorage. However, with a little planning, I think it’s possible to put event listeners one level above the pattrstorage.

Here’s another version that demonstrates all this. You can follow the subpatches all the way down and try changing the values at the lowest level to see the event listener in action. Or use pattrhub to grab the value only when you want it. Seems like this covers all the object value setting and querying one would typically need…

#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P comment 417 205 82 196617 alternate setter;
#P number 506 253 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 506 202 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 506 225 253 196617 pattr @bindto datastructure::group[1]::obj[1]::int[1];
#X prestore 1 0 33;
#P objectname u229000027;
#P comment 422 255 76 196617 event listener;
#N vpatcher 1028 270 1294 478;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N vpatcher 782 524 1026 728;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N vpatcher 573 131 980 354;
#P window setfont “Sans Serif” 9.;
#P number 205 130 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 131 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 205 62 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 61 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 205 95 114 196617 pattr int[2] @type long;
#X prestore 1 0 110;
#P objectname int[2];
#P newex 57 95 114 196617 pattr int[1] @type long;
#X prestore 1 0 11;
#P objectname int[1];
#P comment 66 39 277 196617 try changing the value down here , and watch the “getter”;
#P connect 3 0 1 0;
#P connect 1 0 5 0;
#P connect 4 0 2 0;
#P connect 2 0 6 0;
#P pop;
#P newobj 134 102 32 196617 p obj;
#P objectname obj[2];
#P comment 134 84 35 196617 obj[2];
#P window linecount 0;
#N vpatcher 573 131 980 354;
#P window setfont “Sans Serif” 9.;
#P number 205 130 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 131 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 205 62 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 61 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 205 95 114 196617 pattr int[2] @type long;
#X prestore 1 0 110;
#P objectname int[2];
#P newex 57 95 114 196617 pattr int[1] @type long;
#X prestore 1 0 11;
#P objectname int[1];
#P comment 66 39 277 196617 try changing the value down here , and watch the “getter”;
#P connect 3 0 1 0;
#P connect 1 0 5 0;
#P connect 4 0 2 0;
#P connect 2 0 6 0;
#P pop;
#P newobj 49 102 32 196617 p obj;
#P objectname obj[1];
#P comment 49 83 35 196617 obj[1];
#P pop;
#P newobj 158 61 43 196617 p group;
#P objectname group[2];
#P newex 90 123 67 196617 pattrstorage;
#X client_rect 10 59 570 300;
#X storage_rect 0 0 640 240;
#P objectname u928000013;
#P comment 159 42 49 196617 group[2];
#P window linecount 0;
#N vpatcher 839 525 1083 729;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#N vpatcher 573 131 980 354;
#P window setfont “Sans Serif” 9.;
#P number 205 130 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 131 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 205 62 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 61 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 205 95 114 196617 pattr int[2] @type long;
#X prestore 1 0 110;
#P objectname int[2];
#P newex 57 95 114 196617 pattr int[1] @type long;
#X prestore 1 0 11;
#P objectname int[1];
#P comment 66 39 277 196617 try changing the value down here , and watch the “getter”;
#P connect 3 0 1 0;
#P connect 1 0 5 0;
#P connect 4 0 2 0;
#P connect 2 0 6 0;
#P pop;
#P newobj 134 102 32 196617 p obj;
#P objectname obj[2];
#P comment 134 84 35 196617 obj[2];
#P window linecount 0;
#N vpatcher 836 138 1243 361;
#P window setfont “Sans Serif” 9.;
#P number 205 130 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 131 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 205 62 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P number 57 61 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 205 95 114 196617 pattr int[2] @type long;
#X prestore 1 0 110;
#P objectname int[2];
#P window linecount 0;
#P newex 57 95 114 196617 pattr int[1] @type long;
#X prestore 1 0 33;
#P objectname int[1];
#P comment 66 39 277 196617 try changing the value down here , and watch the “getter”;
#P connect 3 0 1 0;
#P connect 1 0 5 0;
#P connect 4 0 2 0;
#P connect 2 0 6 0;
#P pop;
#P newobj 49 102 32 196617 p obj;
#P objectname obj[1];
#P comment 49 83 35 196617 obj[1];
#P pop;
#P newobj 59 62 43 196617 p group;
#P objectname group[1];
#P comment 60 42 49 196617 group[1];
#P pop;
#P newobj 43 42 80 196617 p datastructure;
#P objectname datastructure;
#P window linecount 3;
#P comment 137 34 197 196617 open this subpatch , double click pattrstorage , and watch the clientwindow while changing values below;
#P number 362 100 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 362 130 252 196617 pattrforward datastructure::group[1]::obj[1]::int[2];
#P objectname datastructure::group[3];
#P message 168 250 50 196617 getint[2];
#P number 379 328 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P comment 45 280 38 196617 getter;
#P number 338 327 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 107 250 50 196617 getint[1];
#P newex 338 303 92 196617 route int[1] int[2];
#P newex 107 276 241 196617 pattrhub @patcher datastructure::group[1]::obj[1];
#P number 82 94 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 82 124 252 196617 pattrforward datastructure::group[1]::obj[1]::int[1];
#P objectname datastructure::group[1];
#P comment 36 124 38 196617 setter;
#P connect 16 0 15 0;
#P connect 15 0 17 0;
#P connect 5 0 3 0;
#P connect 4 0 6 0;
#P connect 3 1 4 0;
#P connect 4 1 8 0;
#P connect 9 0 3 0;
#P connect 11 0 10 0;
#P connect 2 0 1 0;
#P window clipboard copycount 19;

#100136
Oct 30, 2007 at 10:59pm

Adam Murray schrieb:
> Another useful pattern from OO programming is the EventListener. For
> that, a reverse pattrforward would be perfect,

;-)

(this smile is for Jeremy, as its been a long wish of mine, the
pattrbackward…)

I know why I will love Max 5…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#100137
Oct 31, 2007 at 4:41pm

Quote: adamj wrote on Fri, 26 October 2007 08:34
—————————————————-
> Quote: Stefan Tiedje wrote on Thu, 25 October 2007 03:06
> —————————————————-
> >
> > I use the pattr system for this kind of message passing, much less
> > connections, no routes necessary and creating the namespace works
> > automatically.
> > The pattr namespace allows also for easily finding the targets of the
> > messages…
> >
>

pattr is how I currently manage my patches. But apart from that the pattr system is not conceptually tuned for object oriented programming, I keep running into three practical problems:

- the pattr system is slow (compared to send/receive)
- the pattr system is not yet initialized on loadbang (the only system that initializes strictly inside-out), thus always requires a global initialization system.
- when encapsulating something you have to change all the pattr paths that connect to and from the newly created subpatch. pattr doesn’t allow for unnamed intermediate subpatchers. The pattr namespace is still global so not usable in a situation where scope is important.

But I still think it is the best method that is currently available to manage complex patches.

Cheers,
Mattijs

#100138
Oct 31, 2007 at 4:46pm

Quote: Stefan Tiedje wrote on Tue, 30 October 2007 23:59
—————————————————-
> ;-)

Yep, pattrbackward is quite essential. If it has the same speed benefits that pattrforward has over pattr, pattrbackward would certainly give my current patches a big speed boost.

Mattijs

#100139
Nov 1, 2007 at 4:56am

Quote: Mattijs wrote on Wed, 31 October 2007 09:41
—————————————————-
> – when encapsulating something you have to change all the pattr paths that connect to and from the newly created subpatch. pattr doesn’t allow for unnamed intermediate subpatchers. The pattr namespace is still global so not usable in a situation where scope is important.

The namespace issue is definitely a headache. It makes it tough to rework the structure of a large patcher hierarchy once the pattr system has been introduced. I don’t think it’s an issue with the global namespace or scope, though. In the attached patch you can message pattrs using a relative path from any point in the patch. Abstractions can be reused no problem. Or use the fully qualified path from the top level. How is it not usable where scope is important?

I think the real problem is the namespace depends on the patch structure. These need to be decoupled, or as you said, we need “unnamed intermediate subpatchers”. One idea that might work well with the current pattr system is to introduce a pattrlink object that allows for setting up symlinks for use with pattrforward and pattrbackward.

So if we had:
pattrlink pathName @bindto subpatchWeDontCareAbout::nestedSubpatch

then we could do:
pattrforward pathName::param

to bypass that extra subpatch we don’t care about. It’s a little extra work, but at least if you want to encapsulate you could drop in a pattrlink and everything would continue working the same as before. And what if one day Max auto-updates these paths when you encapsulate/de-encapsulate.

Are you handling the “unnamed intermediate subpatchers” problem in your OO javascript work or the C externals you’re doing with John?

-Adam

#P window setfont “Sans Serif” 9.;
#P number 38 40 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 38 67 214 196617 pattrforward package[1]::object[1]::param1;
#N vpatcher 621 355 947 534;
#P window setfont “Sans Serif” 9.;
#P number 37 24 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 37 47 157 196617 pattrforward object[1]::param1;
#P objectname u995000002;
#N vpatcher 828 586 1060 723;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 124 61 70 196617 pattr param2;
#X prestore 1 0 0;
#P objectname param2;
#P newex 34 61 70 196617 pattr param1;
#X prestore 1 0 0;
#P objectname param1;
#P pop 1;
#P newobj 163 90 46 196617 p object;
#P objectname object[2];
#N vpatcher 585 586 817 723;
#P window setfont “Sans Serif” 9.;
#P window linecount 1;
#P newex 124 61 70 196617 pattr param2;
#X prestore 1 0 0;
#P objectname param2;
#P newex 34 61 70 196617 pattr param1;
#X prestore 1 0 83;
#P objectname param1;
#P pop 1;
#P newobj 55 89 46 196617 p object;
#P objectname object[1];
#P connect 3 0 2 0;
#P pop 1;
#P newobj 138 156 53 196617 p package;
#P objectname package[2];
#P newex 66 116 67 196617 pattrstorage;
#X client_rect 456 72 1096 312;
#X storage_rect 0 0 640 240;
#P objectname u581000001;
#N vpatcher 81 369 407 548;
#P window setfont “Sans Serif” 9.;
#P number 37 24 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P newex 37 47 157 196617 pattrforward object[1]::param1;
#P objectname u995000002;
#N vpatcher 319 588 551 725;
#P window setfont “Sans Serif” 9.;
#P newex 124 61 70 196617 pattr param2;
#X prestore 1 0 0;
#P objectname param2;
#P newex 34 61 70 196617 pattr param1;
#X prestore 1 0 0;
#P objectname param1;
#P pop 1;
#P newobj 163 90 46 196617 p object;
#P objectname object[2];
#N vpatcher 67 579 299 716;
#P window setfont “Sans Serif” 9.;
#P newex 124 61 70 196617 pattr param2;
#X prestore 1 0 0;
#P objectname param2;
#P newex 34 61 70 196617 pattr param1;
#X prestore 1 0 27;
#P objectname param1;
#P pop 1;
#P newobj 55 89 46 196617 p object;
#P objectname object[1];
#P connect 3 0 2 0;
#P pop 1;
#P newobj 66 156 53 196617 p package;
#P objectname package[1];
#P window linecount 3;
#P comment 138 107 162 196617 watch the client window and send message to the pattrforward here and in the package objects;
#P connect 5 0 4 0;
#P window clipboard copycount 6;

#100140
Nov 1, 2007 at 11:32am

Mattijs Kneppers schrieb:
> – when encapsulating something you have to change all the pattr paths
> that connect to and from the newly created subpatch. pattr doesn’t
> allow for unnamed intermediate subpatchers. The pattr namespace is
> still global so not usable in a situation where scope is important.

How do you deal with this in strict oo manner? You have to adress
somehow your patches.
And you could still use a pattrmarker object inside an encapsulation.
But you’re right, that name will be global…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#100141
Nov 1, 2007 at 11:54am

Adam Murray schrieb:
> I think the real problem is the namespace depends on the patch
> structure. These need to be decoupled, or as you said, we need
> “unnamed intermediate subpatchers”. One idea that might work well
> with the current pattr system is to introduce a pattrlink object that
> allows for setting up symlinks for use with pattrforward and
> pattrbackward.

I guess the pattrmarker object would allow for unnamed intermediate
subpatchers, and even if they get named automatically, it wouldn’t hurt.
You could adress your object either by the full path or the pattrmarker
name path…

You might need some extra patching/scripting to create independent
pattrmarker names though. But that seems to be a solvable problem…
I can imagine to use a sort of #0_patrmarker_names and a coll which
would keep track of all the instances…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#100142
Nov 1, 2007 at 9:19pm

Quote: adamj wrote on Thu, 01 November 2007 17:56
—————————————————-
> Are you handling the “unnamed intermediate subpatchers”
> problem in your OO javascript work or the C externals you’re
> doing with John?

Yes, in C externals. The javascript has been abandoned as too slow.

Patchers and abstractions can generate a scope/namespace by the addition of @public, @private, @protected attributes, and this is optional – so you can choose whether to use any given patcher or abstraction scoped or unscoped without modifying it internally.

Unscoped patchers do not exist in the namespace:

[oo.call myobject.mymethod]

[p @public myobject]

…[p something]

……[oo.method @public mymethod]

#100143
Nov 1, 2007 at 9:30pm

Quote: Stefan Tiedje wrote on Fri, 02 November 2007 00:54
—————————————————-
> You might need some extra patching/scripting to create
> independent pattrmarker names though. But that seems to be a
> solvable problem… I can imagine to use a sort of
> #0_patrmarker_names and a coll which would keep track of all
> the instances…

I prototyped most of a non-pattr namespace system using coll etc to keep track of names/instances, and found that as things scaled up, the number of supporting objects and coll sizes required became a problem. Load times were getting seriously long, and coll lookup overhead for calls wasn’t ideal.

A pattr-based system as you describe would certainly fare better, but the supporting object cruft is less than desirable.

And you still have the problem that everything is public.

#100144
Nov 1, 2007 at 10:28pm

Quote: adamj wrote on Thu, 01 November 2007 05:56
—————————————————-
> Quote: Mattijs wrote on Wed, 31 October 2007 09:41
> —————————————————-
> > – when encapsulating something you have to change all the pattr paths that connect to and from the newly created subpatch. pattr doesn’t allow for unnamed intermediate subpatchers. The pattr namespace is still global so not usable in a situation where scope is important.
>
> The namespace issue is definitely a headache. It makes it tough to rework the structure of a large patcher hierarchy once the pattr system has been introduced. I don’t think it’s an issue with the global namespace or scope, though. In the attached patch you can message pattrs using a relative path from any point in the patch. Abstractions can be reused no problem. Or use the fully qualified path from the top level. How is it not usable where scope is important?
>

Ah no, I was talking about the pattrmarker object, the equivalent of a namespace in C++. pattrmarker could be used to connect to pattrs without having to specify every intermediate patcher in the path, but pattrmarker defines a global name, so is not usable when you need an independent scope.

Mattijs

#100145
Nov 2, 2007 at 10:11am

John Pitcairn schrieb:
> And you still have the problem that everything is public.

Yes it is, but those objects which don’t have the information can’t
access it anyway… ;-) The #0_arguments will create unique names…
Under the hood of a “real” oo language also all is public in a way…

You can hide the #0 part for the user, and that way it isn’t really
public…

Stefan


Stefan Tiedje————x——-
–_____———–|————–
–(_|_ —-|—–|—–()——-
– _|_)—-|—–()————–
———-()——–www.ccmix.com

#100146
Nov 4, 2007 at 11:40pm

Quote: Stefan Tiedje wrote on Fri, 02 November 2007 23:11
—————————————————-
> The #0_arguments will create unique names…

Sure. But won’t work if used in an ordinary patcher’s args.

The general incompleteness of this approach to max scoping and namespaces seems, to us, to be problematic to implement and keep track of. Should you use pattr? #0_arguments? pvar? v? pv? send/forward/receive? Roll your own solution? It’s something of a minefield, with no map.

That’s what we’re hoping to avoid.

#100147
Dec 17, 2007 at 2:26am

Hi.

Id like some feedback on my module loading system – so I offer up a
pre-release of what ive been working on.

it now can:

automagically deduce proper path information from the js/-main patch
location – no odd global variables anymore
automagically deduce the number of inlets and outlets, and connect
sends/recieves to them with a specified namespace – which makes it
more useful for just about everyone

You can set banks of modules, included in the name space to load
multiple versions of the same module while maintaining a unique ID in
the namespace -basically if I wanted multiple versions of my ‘blur’
effect to be independent, etc.

How it works

: the js v001.lib.module.loader.js takes two arguments

1 : bank number
2: sub folder of modules.

should you only specify one input, it assumes you mean the folder, and
the bank number defaults to 1. Should you enter no arguments it
assumes the parent module folder is the only folder to load modules
from.

Check the attached patch as an example – its super easy to grok.. Its
pretty simple, but it just works, out of the box. You can add inlets/
outlets in various counts to your modules and things should still just
work.

It needs a bit of work wrt the positioning of the sub modules for
cleanliness/readability, but for now, its good enough for a preview.

This does not directly address the concerns of everyone in this
thread, but is on topic enough to be of interest I think, and solves
lots of problems for me.

Let me know what you folk think.

More to come soon:)

Credit to Jeremy Bernstein for a work around in the JS code :)

-vade

#100148
Dec 17, 2007 at 8:37am

Hi vade,

I’d like to check out your work but there’s the classic problem again that the forum doesn’t display mailing list attachments. Could you post your attachment to the forum?

Thanks,
Mattijs

#100149
Dec 17, 2007 at 3:01pm

I hate this unholy forum+email monster! :)

http://abstrakt.vade.info/ILOVETHEMAXLIST/v001ModuleLoadingOO.zip

Ive found a few small issues that I fixed last night, and am now using
it in my main performance patch for module loading. Needs some tweaks,
but the above should suffice to get the idea.

Let me know.

On Dec 17, 2007, at 3:37 AM, Mattijs Kneppers wrote:

>
> Hi vade,
>
> I’d like to check out your work but there’s the classic problem
> again that the forum doesn’t display mailing list attachments. Could
> you post your attachment to the forum?
>
> Thanks,
> Mattijs
> –
> SmadSteck – http://www.smadsteck.nl
> Hard- and software for interactive audiovisual sampling

#100150
Dec 17, 2007 at 3:41pm

This is the thread that doesn’t end
yes it goes on and on my friend
some people started writing it not knowing what it was
and they’ll continue writing it forever just because
This is the thread that doesn’t end
yes it goes on and on my friend
some people started writing it not knowing what it was
and they’ll continue writing it forever just because
This is the thread that doesn’t end
yes it goes on and on my friend
some people started writing it not knowing what it was
and they’ll continue writing it forever just because
This is the thread that doesn’t end
yes it goes on and on my friend
some people started writing it not knowing what it was
and they’ll continue writing it forever just because

#100151
Dec 17, 2007 at 3:50pm

Quote: Axiom-Crux wrote on Mon, 17 December 2007 16:41
—————————————————-

> some people started writing it not knowing what it was

Hehe.. I’ll prove you wrong lad ;)

Mattijs

#100152
Dec 17, 2007 at 3:55pm

Quote: vade wrote on Mon, 17 December 2007 16:01
—————————————————-
> I hate this unholy forum+email monster! :)
>
> http://abstrakt.vade.info/ILOVETHEMAXLIST/v001ModuleLoadingOO.zip
>
> Ive found a few small issues that I fixed last night, and am now using
> it in my main performance patch for module loading. Needs some tweaks,
> but the above should suffice to get the idea.
>
> Let me know.

Thanks, vade. But I seem to miss your shaders:

When I press laod:

• error: jit.gl.shader: can’t find file v001.blackandwhite.jxs
• error: jit.gl.shader: can’t find file v001.film-colorgrade.jxs
• error: jit.gl.shader: can’t find file v001.exposure.jxs
• error: jit.gl.shader: can’t find file v001.film-lightleak.jxs
• error: jit.gl.shader: can’t find file v001.invert.jxs

Mattijs

#100153
Dec 17, 2007 at 5:06pm

well, er, its just an example on loading modules dynamically, you can
make your own subpatchers etc. I just took some random modules that I
had and threw them in there. The modules arent the point, the loading
mechanism is.

Duplicate modules, make your own, put them in a sub folder and it just
works.

On Dec 17, 2007, at 10:55 AM, Mattijs Kneppers wrote:

>
> Quote: vade wrote on Mon, 17 December 2007 16:01
> —————————————————-
>> I hate this unholy forum+email monster! :)
>>
>> http://abstrakt.vade.info/ILOVETHEMAXLIST/v001ModuleLoadingOO.zip
>>
>> Ive found a few small issues that I fixed last night, and am now
>> using
>> it in my main performance patch for module loading. Needs some
>> tweaks,
>> but the above should suffice to get the idea.
>>
>> Let me know.
>
>
> Thanks, vade. But I seem to miss your shaders:
>
> When I press laod:
>
> • error: jit.gl.shader: can’t find file v001.blackandwhite.jxs
> • error: jit.gl.shader: can’t find file v001.film-colorgrade.jxs
> • error: jit.gl.shader: can’t find file v001.exposure.jxs
> • error: jit.gl.shader: can’t find file v001.film-lightleak.jxs
> • error: jit.gl.shader: can’t find file v001.invert.jxs
>
> Mattijs
>
> –
> SmadSteck – http://www.smadsteck.nl
> Hard- and software for interactive audiovisual sampling

#100154
Dec 17, 2007 at 5:15pm

Quote: vade wrote on Mon, 17 December 2007 18:06
—————————————————-
> well, er, its just an example on loading modules dynamically, you can
> make your own subpatchers etc. I just took some random modules that I
> had and threw them in there. The modules arent the point, the loading
> mechanism is.

Ah, ok. I saw errors and immediately assumed something unintended was happening. I’ll have a closer look.

Mattijs

#100155
Dec 17, 2007 at 5:37pm

hehehe, yeah I sent it and then had that very thought, oh well. Ill
try and come up with a nicer/cleaner example later on, showing
multiple banks of standard jitter objects, multiple module folders,
with serialized loading etc all working. :)

On Dec 17, 2007, at 12:15 PM, Mattijs Kneppers wrote:

> Ah, ok. I saw errors and immediately assumed something unintended
> was happening. I’ll have a closer look.

#100156
Jun 12, 2008 at 11:59am

Hi all,

Back again, this time with finished, tested and working externals that are a direct answer to “How to apply oo within Max”!

John Pitcairn and I joined our forces and the result is better than I could have expected. This has proven to be a very inspiring and involved topic, we spent far more time on it than we anticipated. As far as I am concerned, the result is a big leap forward in the feasibility of complex Max patches.

I started a new thread:

http://www.cycling74.com/forums/index.php?t=msg&goto=144760

I am really curious what your thoughts are, please let us know in the new thread. Thanks for all your input in this thread!

Mattijs

#100157

You must be logged in to reply to this topic.