Forums > MaxMSP

[sharing is fun] OO Objects for Max

June 12, 2008 | 11:58 am

Hello all,

As some of you may remember, there was a long discussion where we tried to apply object oriented (OO) principles to Max: http://www.cycling74.com/forums/index.php?t=msg&th=25272. In the end, John Pitcairn and I teamed up to address this issue.

You can now find the first official release of the OO Objects for Max on my user page:

http://www.cycling74.com/twiki/bin/view/Share/MattijsKneppers

We developed two simple but powerful externals, oo.method and oo.call, that enable you to apply OO techniques within Max. This vastly improves the manageability of complex Max patches.

The objects are Mac-only for now. So far they have been tested by a select group of experienced Max users but we are interested in more user experiences before we start the development for Windows. Max 5 versions will come as soon as Cycling ’74 releases the Max 5 API.

All feedback is appreciated!

Cheers,
Mattijs


June 12, 2008 | 12:55 pm

OMFG! This is great. Thanks Mattijs and John for this wonderful addition! Now, just have to wait for the Max5 version. I must admit, this will keep me attached to Max4 a little longer than anticipated ;)

Zachary


June 12, 2008 | 1:08 pm

Absolutely fantastic, thank you very much.

Do you have any experience on performance, e.g. how does it compare to CPU utilisation of a ftm based system calling functions or methods stored in matrices and dictionaries?


June 12, 2008 | 1:20 pm

On 12 Jun 2008, at 14:08, Sebastian Lexer wrote:

> Absolutely fantastic, thank you very much.

Agreed – it’s quite sweet.

Just curious: is it thread-safe?

– N.

Nick Rothwell / Cassiel.com Limited
http://www.cassiel.com
http://www.myspace.com/cassieldotcom
http://www.last.fm/music/cassiel
http://www.reverbnation.com/cassiel
http://www.linkedin.com/in/cassiel
http://www.loadbang.net


June 12, 2008 | 4:15 pm

Thanks, guys.

Sebastian, we didn’t compare directly to ftm based systems, but we did compare with send/receive/forward, pvar and the pattr family, as you can see in section 17 of the help patch. The oo objects are very fast, i.e. faster than pattr and pvar and only slightly slower than send/receive (which of course don’t support all the extra functionality).

Nick, yes, they are thread-safe. We’re not fooling with threads at all, we use the native event handling system. Although on load, some interesting things are going on, see section 15 of the help file: "loadbang limitations for oo objects".

Mattijs


June 12, 2008 | 4:35 pm

I would love to try this. Is there a Windows version?


June 12, 2008 | 7:11 pm

Quote: Mattijs wrote on Thu, 12 June 2008 04:58
—————————————————-
> Max 5 versions will come as soon as Cycling ’74 releases the Max 5 API.
>

I’m using Max 5 almost exclusively now so I’m really looking forward to the Max 5 version. I hope you and John get to beta test the Max 5 SDK. That would be a win-win situation for everyone.

It will be very interesting to see how people use these objects: which OO patterns are effective in Max and what do they look like in patch form? So please share (because it’s fun!) and I will do the same :)


June 12, 2008 | 9:23 pm

Quote: nick rothwell / cassiel wrote on Fri, 13 June 2008 01:20
—————————————————-
> Just curious: is it thread-safe?

It should be thread-safe, if C74′s internal hashtab and linklist handling is threadsafe. As Mattijs says, we don’t use any internal threading of our own. We’ve tested on single and multiprocessor PPC and Intel Mac systems, overdrive on/off, and this release seems very stable. I’d certainly be interested in any crash results that indicate it isn’t thread-safe.


June 12, 2008 | 9:27 pm

these look very interesting. now that i’m beginning to work on a large complex patch i’m interested in learning more about these objects…

although i don’t have a programming background, i have a general idea about what oop is. enough to see how it can simplify some patch building routines.

the problem i have now is that i’ve looked at the objects and the helps files, but i can’t quite make the next step to use these objects. can someone post an example patch, using these in context? i know that would help me a great deal.

thanks
david


June 12, 2008 | 9:33 pm

YOU BASTARD! :-)

totally have a copy of something like this running on my computer!

Thought I was a genius! I had nearly all of Javascript in max form.

Also, it operated like jitter where you could pass "max_object id" messages to other methods so you could operate on objects


June 12, 2008 | 9:46 pm

Hi David,

as Adam Murray said, there are a lot of different ways in which you can use these objects, depending on the situation. In text-based languages people have defined a series of recurring programming patterns and I am certainly curious how those will relate to max.

On my user page you will also find the MPC Studio patch. This is a complex patch that would have been impossible to create as modular and clean as it is now without the oo objects. Feel free to use it as an example, but as it is with big patches, I can imagine it takes some time to plough through all the subpatchers and recognize the structure I used.

Adam, we definitely have to document the patterns you came up with during the beta tests. We could exchange some of them in this thread, I guess? That way others will have the opportunity to chime in. Maybe after a while we’ll be able to bundle the examples and provide them on the user page together with the OO Objects.

Mattijs

Quote: david@5of4.com wrote on Thu, 12 June 2008 23:27
—————————————————-
> these look very interesting. now that i’m beginning to work on a large complex patch i’m interested in learning more about these objects…
>
> although i don’t have a programming background, i have a general idea about what oop is. enough to see how it can simplify some patch building routines.
>
> the problem i have now is that i’ve looked at the objects and the helps files, but i can’t quite make the next step to use these objects. can someone post an example patch, using these in context? i know that would help me a great deal.
>
> thanks
> david
>
>
—————————————————-


June 12, 2008 | 9:55 pm

Quote: Anthony Palomba wrote on Thu, 12 June 2008 18:35
—————————————————-
> I would love to try this. Is there a Windows version?
—————————————————-

As I said in the initial post:

The objects are Mac-only for now. So far they have been tested by a select group of experienced Max users but we are interested in more user experiences before we start the development for Windows. Max 5 versions will come as soon as Cycling ’74 releases the Max 5 API.

Mattijs


June 12, 2008 | 10:02 pm

Haha! No way! I’m curious to see your system though. Do you have a preview of any kind that you could send me..?

Mattijs

Quote: Matthew Aidekman wrote on Thu, 12 June 2008 23:33
—————————————————-
> YOU BASTARD! :-)
>
> totally have a copy of something like this running on my computer!
>
> Thought I was a genius! I had nearly all of Javascript in max form.
>
>
> Also, it operated like jitter where you could pass "max_object id" messages to other methods so you could operate on objects
>
>
—————————————————-


June 12, 2008 | 10:47 pm

The license makes this useless for me.

bt


June 13, 2008 | 12:03 am

Quote: barry threw wrote on Fri, 13 June 2008 10:47
—————————————————-
> The license makes this useless for me.

What’s the problem?


June 13, 2008 | 12:23 am

Quote: Matthew Aidekman wrote on Fri, 13 June 2008 09:33
—————————————————-
> totally have a copy of something like this running on my
> computer! Thought I was a genius! I had nearly all of
> Javascript in max form.

Wow. As compiled max objects, java objects, js objects, or as abstractions?

We wound up ruling out js and abstractions for doing the heavy lifting due to abysmal performance and/or excessive load-time overhead for large patches. Switching to C speeded things up by at least an order of magnitude, but also slowed development time by a corresponding amount :-


June 13, 2008 | 12:37 am

> Adam, we definitely have to document the patterns you came up with during the beta tests. We could exchange some of them in this thread, I guess? That way others will have the opportunity to chime in. Maybe after a while we’ll be able to bundle the examples and provide them on the user page together with the OO Objects.

Sure, that sounds good. I will probably host any of my patches on my website too. I need a bit of time to clean them up, maybe add some comments. I will post here in the not too distant future.


June 13, 2008 | 3:01 am

Quote: barry threw wrote on Fri, 13 June 2008 10:47
—————————————————-
> The license makes this useless for me.

seems like a pretty flexible license to me…


June 13, 2008 | 4:40 am

I checked, its broken right now. It was like 2 years ago. I tried programming it from scratch three times. I had it kind of half working. Then called max "art that kills you" I was so touched by those words I decided to drop ir (at least this project) from my to do list

I included the very very first max based version

I’m going to rant here because this will be the last place this project lives.

this is how the last version went:

oom.instnace
//loaded a max patch with the code for the object inside.

oom.method
//where you defined a method inside your instance code. you could also instantiate it outside your oom_object patcher and it would forward the arguments to the corrisponding oom.method inside the oom_object patcher, then return the value from oom.return

oom.instancevalue
//like the v object in max but oom kept track of it. you could also instantiate it outside your oom_object patcher and it would refer to the correct value

oom.return
//where you sent the results of your method.


June 13, 2008 | 5:15 am

that should read: Then a friend called max…


June 13, 2008 | 7:10 am

Non-commercial.

bt

On Jun 12, 2008, at 5:03 PM, John Pitcairn wrote:

>
> Quote: barry threw wrote on Fri, 13 June 2008 10:47
> —————————————————-
>> The license makes this useless for me.
>
> What’s the problem?
>


June 13, 2008 | 7:29 am

Quote: barry threw wrote on Fri, 13 June 2008 09:10
—————————————————-
> Non-commercial.
>
> bt
>

No, not non-commercial. "Don’t include the objects in commercial distributions without permission of the authors".

The thing is, we’d like to know about every commercial project that these objects get involved in up to a level where they need to be re-distributed.

I previously had a situation where the DAW Fruityloops (now called FL Studio) made a Jeskola Buzz wrapper, and included Buzz machines, some of which I made, in their main distribution without asking or even notifying the authors, selling copy after copy. And they must have made quite a bit of money out of that.

Mattijs


June 13, 2008 | 7:46 am

Re: OO patterns in Max
First up: the strategy pattern

Check out the attached zip. If the forum swallowed it, you can also get it here:

http://compusition.com/code/max/oo/strategy.pattern.zip

This pattern is about swappable behaviors. It can be used to construct generic subpatchers that do some sort of processing not defined ahead of time. A UI can be built to change the behavior on the fly.

The important thing to understand here is I’m passing around addresses to the oo.methods and deferring execution until the oo.call gets triggered by MIDI input.

It’s worth noting that multiple transformer abstractions can be hooked up to the same transformation strategy. You can set two to "octave_up" in this patch. And you can open this patch multiple times without the kind of interference problems you’d have with send/receive.

In a structured OO language like Java, we’d be using an interface to make a well-defined the strategy. There’s no way to enforce an interface here so it’s up to the patch maker to ensure they all work the same way. My "interface" is to send the message [pitch velocity duration callback_address] and expect to receive [pitch velocity duration]. The callback stuff is needed when delays are involved (more info in the oo help file).


June 13, 2008 | 10:48 am

Barry Threw schrieb:
> Non-commercial.

So just ask for a commercial license, it doesn’t mean you can’t use it,
it only means you don’t know the commercial license (yet)…
And it’s exactly what is written there, they want you to ask first…
It is probably to prevent Microsoft to abuse it, make billions of
dollars with it but don’t participate in the cost of the development.
I think its fair. But I’d recommend to Mattjis and John to look into
cc-licenses, there is a non-commercial variant, which is pretty robust
and checked by real lawyers…

Stefan


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


June 13, 2008 | 3:39 pm

Quote: Stefan Tiedje wrote on Fri, 13 June 2008 12:48
—————————————————-
> But I’d recommend to Mattjis

That would be MattIJs. I remember you corrected me once because I wrote ‘Stephan’, now we’re even ;)

> and John to look into
> cc-licenses, there is a non-commercial variant, which is pretty robust
> and checked by real lawyers…

I looked a bit into CC, but the first things I stumbled upon were all very much like GNU, which is all about open source, which these objects aren’t. If you or someone else can find a CC license that has the same content as the current home-made one, I’d be happy to replace it.

Mattijs


June 13, 2008 | 4:12 pm

Quote: Adam Murray wrote on Fri, 13 June 2008 09:46
—————————————————-
> Re: OO patterns in Max
> First up: the strategy pattern
>

Wow, impressive! Clean and comprehensible, and a nice case too!

A thought: if I adopted this patch as a pattern I think I’d rather put the transformations in subpatchers instead of abstractions. 1) because it would be easier to debug, the idea of this pattern being of course that the transformations can become pretty complex, 2) because abstractions are typically used for functionality you need multiple copies of. One of the big strengths of your example is that there only has to be one copy of every transformation, while they are called in multiple locations (saving a lot of load time if the same transformations are used everywhere throughout a huge patch).

Also, but you have probably noticed this, the callback system is only necessary if a transformation is switched before the delay of the previous one ends. oo.method remembers its return address until it is called by a new oo.call. But in this case, with the midi notes, I can imagine a lot of fun with wild transformation switches at non-obvious moments in the note stream.

Mattijs


June 13, 2008 | 4:50 pm

Quote: Mattijs wrote on Fri, 13 June 2008 09:12
—————————————————-
> A thought: if I adopted this patch as a pattern I think I’d rather put the transformations in subpatchers instead of abstractions. 1) because it would be easier to debug, the idea of this pattern being of course that the transformations can become pretty complex,

Sure, that makes sense. And you can patch up some new transformations on the fly and hook them up to the rest of the patch without changing anything else, since there’s no cable connections.

> 2) because abstractions are typically used for functionality you need multiple copies of.

I did it this way because I parameterized those abstractions – for example, the transpose abstraction needs to know how many semitones to transpose.

But I realized a much better way: When setting the transformation, also pass any parameters needed by the transformation. So instead of calling "transformer.set &octave_up" you call "transformer.set &transpose 12". That makes this technique even more flexible and completely removes redundancy in the patch. And seems like a good way to simulate a closure, one of the features that makes high level languages so powerful IMO.

Here’s a simplified example:

#P window setfont "Sans Serif" 9.;
#P number 283 172 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P newex 26 148 62 196617 prepend set;
#P message 26 170 72 196617 60 45 250;
#N vpatcher 496 48 928 341;
#P window setfont "Sans Serif" 9.;
#P newex 37 144 40 196617 append;
#P newex 75 79 51 196617 zl slice 1;
#P newex 116 106 62 196617 prepend set;
#P comment 180 53 160 196617 set a transformer "strategy";
#P comment 138 173 160 196617 passthrough by default;
#P newex 59 204 112 196617 oo.method passthrough;
#P newex 37 169 96 196617 oo.call passthrough;
#P newex 75 51 101 196617 oo.method public set;
#P outlet 37 244 15 0;
#P inlet 37 45 15 0;
#P comment 183 108 216 196617 any parameters needed for the transformation;
#P connect 1 0 10 0;
#P connect 8 0 10 0;
#P connect 10 0 4 0;
#P connect 5 0 2 0;
#P connect 4 0 2 0;
#P connect 3 0 9 0;
#P connect 9 1 8 0;
#P connect 9 0 4 1;
#P pop 1;
#P newobj 131 146 124 196617 p @oo public transformer;
#P message 283 202 77 196617 &transpose $1;
#N vpatcher 497 364 664 565;
#P window setfont "Sans Serif" 9.;
#P newex 48 134 57 196617 pack 0 0 0;
#P newex 48 106 20 196617 +;
#P newex 48 71 80 196617 unpack 0 0 0 0;
#P newex 48 46 75 196617 oo.method this;
#P fasten 3 0 0 0 53 160 35 160 35 37 53 37;
#P connect 0 0 1 0;
#P connect 1 0 2 0;
#P connect 2 0 3 0;
#P connect 1 3 2 1;
#P connect 1 1 3 1;
#P connect 1 2 3 2;
#P pop 1;
#P newobj 277 59 112 196617 p @oo public transpose;
#P message 58 67 37 196617 60 90;
#P newex 283 229 146 196617 oo.call transformer.set eval 1;
#P newex 143 178 62 196617 prepend set;
#P message 143 200 72 196617 72 45 250;
#P newex 109 264 42 196617 noteout;
#P newex 109 235 85 196617 makenote 80 100;
#P newex 109 93 93 196617 pack 0 0 250;
#P newex 109 70 51 196617 stripnote;
#P newex 109 45 93 196617 notein;
#P window linecount 2;
#P comment 284 136 100 196617 Set a parameterized transformation:;
#P connect 3 0 14 0;
#P connect 14 0 13 0;
#P connect 1 0 2 0;
#P connect 2 0 3 0;
#P connect 9 0 3 0;
#P connect 12 0 4 0;
#P connect 3 0 4 0;
#P connect 4 0 5 0;
#P connect 4 1 5 1;
#P connect 3 0 12 0;
#P connect 12 0 7 0;
#P connect 7 0 6 0;
#P connect 1 1 2 1;
#P connect 2 1 3 1;
#P connect 15 0 11 0;
#P connect 11 0 8 0;
#P window clipboard copycount 16;


June 13, 2008 | 6:52 pm

Nice example. This made me "get it" a little more than the examples
that came with.

This is a nice way to work.

bt


June 13, 2008 | 10:29 pm

Quote: barry threw wrote on Fri, 13 June 2008 20:52
—————————————————-
> Nice example. This made me "get it" a little more than the examples
> that came with.
>
> This is a nice way to work.
>
> bt
>
>
>
—————————————————-

And now an MVC example, Adam! ;)

Yes, I agree that examples like this are essential to understanding the oo objects, especially for maxers that are not familiar with oo programming.

Mattijs


June 14, 2008 | 4:04 am

Quote: Mattijs wrote on Fri, 13 June 2008 15:29
—————————————————-
>
> And now an MVC example, Adam! ;)
>

I know what patch you want to see :) But you may not recognize it, it got seriously revamped.

This is the observer pattern. Use it to register "event listeners" that will be notified every time some state changes.

In bigger patches it’s probably useful to put a pattr inside the "subject" object to store the state and get all the benefits of using pattrstorage (presets, saving/loading to a file, etc). Then you’d probably want a GUI to manage the pattr. But that would require two way communication between the GUI object and pattr, and this pattern only goes one way (from subject to observer). I played around with using oo.objects to go both ways, but I still feel that using [pattr @bindto] is the most straightforward (although slightly less efficient) way to do this. But that’s a conversation for another day.

I have a question. The oo help file shows examples of calling methods relative to the current patch. I can go down (child.method) or up (parent.method or .method). Can I also reference objects absolutely from the top scope?

Observer pattern patch:

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 123 301 157 196617 oo.call subject.notify_observers;
#B color 9;
#P window linecount 2;
#P message 67 66 337 196617 ; max launchbrowser http://en.wikipedia.org/wiki/Observer_pattern;
#P window setfont "Sans Serif" 14.;
#P comment 68 22 321 196622 Demonstrates using the observer pattern from OO programming in Max/MSP;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 322 442 85 196617 noteout;
#P newex 322 413 85 196617 makenote 80 100;
#P window setfont "Sans Serif" 24.;
#P number 17 413 67 24 0 0 8356 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P user multiSlider 164 410 120 52 0. 127. 1 3177 15 0 0 2 0 0 0;
#M frgb 0 0 0;
#M brgb 255 255 255;
#M rgb2 127 127 127;
#M rgb3 0 0 0;
#M rgb4 37 52 91;
#M rgb5 74 105 182;
#M rgb6 112 158 18;
#M rgb7 149 211 110;
#M rgb8 187 9 201;
#M rgb9 224 62 37;
#M rgb10 7 114 128;
#P window setfont "Sans Serif" 12.;
#P comment 182 274 165 196620 2. Trigger notifications;
#P toggle 195 181 15 0;
#P window setfont "Sans Serif" 9.;
#P message 195 181 66 196617 $1 &history;
#B color 5;
#P toggle 102 181 15 0;
#P message 102 181 65 196617 $1 &display;
#B color 5;
#N vpatcher 485 58 836 227;
#P origin -2 0;
#P window setfont "Sans Serif" 9.;
#P window linecount 3;
#P comment 173 60 137 196617 This helper patch needs to be in the same scope as the methods we are referencing;
#P inlet 26 59 15 0;
#P window setfont "Sans Serif" 36.;
#P window linecount 1;
#P comment 131 7 26 196644 );
#P comment 4 7 26 196644 (;
#P toggle 25 14 15 0;
#P window setfont "Sans Serif" 9.;
#P message 25 34 107 196617 $1 &callback_method;
#P newex 26 86 52 196617 route 1 0;
#P newex 179 125 138 196617 oo.call subject.detach eval 1;
#P newex 26 125 137 196617 oo.call subject.attach eval 1;
#P window linecount 2;
#P comment 174 21 137 196617 attach or detach to the subject based on toggle state;
#P connect 5 0 4 0;
#P connect 8 0 3 0;
#P connect 3 0 1 0;
#P fasten 3 1 2 0 52 114 184 114;
#P pop 1;
#P newobj 195 216 93 196617 p observe_subject;
#B color 9;
#P toggle 287 181 15 0;
#P window setfont "Sans Serif" 14.;
#P number 123 272 50 14 0 127 3 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window setfont "Sans Serif" 9.;
#P newex 17 384 119 196617 oo.method public display;
#B color 5;
#P newex 164 384 120 196617 oo.method public history;
#B color 5;
#P newex 322 385 121 196617 oo.method public to_midi;
#B color 5;
#P message 287 181 67 196617 $1 &to_midi;
#B color 5;
#P window setfont "Sans Serif" 12.;
#N vpatcher 485 250 836 574;
#P window setfont "Sans Serif" 9.;
#P comment 61 282 100 196617 each callback;
#P newex 174 158 149 196617 print "subject.detach callback";
#P newex 120 93 148 196617 print "subject.attach callback";
#P newex 119 158 49 196617 append 0;
#P newex 66 93 49 196617 append 1;
#P newex 16 279 44 196617 oo.call;
#P newex 66 221 27 196617 t b i;
#P newex 16 255 36 196617 zl reg;
#P newex 25 49 27 196617 t b l;
#P newex 66 198 27 196617 bag;
#P newex 25 26 166 196617 oo.method public notify_observers;
#P newex 119 134 116 196617 oo.method public detach;
#P newex 66 69 115 196617 oo.method public attach;
#P comment 95 201 155 196617 stores the notify callbacks;
#P connect 7 0 6 0;
#P connect 6 0 8 0;
#P connect 3 0 5 0;
#P connect 5 1 6 1;
#P connect 7 1 8 1;
#P connect 1 0 9 0;
#P connect 5 0 4 0;
#P connect 9 0 4 0;
#P fasten 10 0 4 0 124 179 71 179;
#P connect 4 0 7 0;
#P connect 2 0 10 0;
#P fasten 1 0 11 0 71 89 125 89;
#P fasten 2 0 12 0 124 154 179 154;
#P pop 1;
#P newobj 169 114 130 196620 p @oo public subject;
#B color 9;
#P objectname observable;
#P comment 159 157 147 196620 1. Select observers;
#P window setfont "Sans Serif" 9.;
#P comment 354 484 100 196617 Adam Murray 2008;
#P user panel 94 154 272 90;
#X brgb 220 243 221;
#X frgb 0 0 0;
#X border 1;
#X rounded 12;
#X shadow 2;
#X done;
#P user panel 94 261 271 69;
#X brgb 231 248 245;
#X frgb 0 0 0;
#X border 1;
#X rounded 12;
#X shadow 2;
#X done;
#P window setfont "Sans Serif" 12.;
#P comment 181 358 83 196620 Observers;
#P user panel 8 348 444 122;
#X brgb 187 187 242;
#X frgb 0 0 0;
#X border 1;
#X rounded 12;
#X shadow 2;
#X done;
#P connect 10 0 20 0;
#P hidden connect 15 0 14 0;
#P connect 11 0 25 0;
#P connect 9 0 19 0;
#P hidden connect 17 0 16 0;
#P fasten 7 0 13 0 292 206 200 206;
#P connect 16 0 13 0;
#P fasten 14 0 13 0 107 206 200 206;
#P hidden connect 12 0 7 0;
#P connect 8 0 21 0;
#P connect 21 0 22 0;
#P connect 21 1 22 1;
#P window clipboard copycount 26;


June 15, 2008 | 10:40 am

Quote: Adam Murray wrote on Sat, 14 June 2008 06:04
—————————————————-
>
> This is the observer pattern. Use it to register "event listeners" that will be notified every time some state changes.
>

Again a great example! It has definitely evolved since the last time I saw it, and became even easier to understand.

> In bigger patches it’s probably useful to put a pattr inside the "subject" object to store the state and get all the benefits of using pattrstorage (presets, saving/loading to a file, etc). Then you’d probably want a GUI to manage the pattr. But that would require two way communication between the GUI object and pattr, and this pattern only goes one way (from subject to observer). I played around with using oo.objects to go both ways, but I still feel that using [pattr @bindto] is the most straightforward (although slightly less efficient) way to do this. But that’s a conversation for another day.

I have been working with a system that avoids pattrstorage but uses a simple coll to store presets. It also illustrates the max equivalent of how I do this two-way communication in my object oriented Java applications. I’ll see if I can post an example soon.

>
> I have a question. The oo help file shows examples of calling methods relative to the current patch. I can go down (child.method) or up (parent.method or .method). Can I also reference objects absolutely from the top scope?

No, you can’t. If that would be possible, the whole thing would lose its local aspect. But I’m curious where you would need that. The supposed way to do this is to pass a reference from the top scope to the scopes where you need them.

Although, there is one thing I have been thinking about. There is no way to store that location in a variable (for example ‘main’) and calling it directly, like [oo.call main.updateGui]. Maybe that is a feature we could add in the future.

Mattijs


June 15, 2008 | 10:44 am

Quote: Matthew Aidekman wrote on Fri, 13 June 2008 06:40
—————————————————-
> I checked, its broken right now. It was like 2 years ago. I tried programming it from scratch three times. I had it kind of half working. Then called max "art that kills you" I was so touched by those words I decided to drop ir (at least this project) from my to do list
>
>
> I included the very very first max based version
>
>
> I’m going to rant here because this will be the last place this project lives.
>

Matthew, it looks like you have been going through very much the same process as we did. I assume you also found out that using abstractions is not the way to go due to excessive load times. We then turned to javascript, but it wasn’t fast and stable enough, so we ended up writing our own externals.

I can imagine that you have some interesting and useful feedback for us, based on your own experiences. I would be happy to hear it.

Mattijs


June 15, 2008 | 4:09 pm

Mattijs Kneppers schrieb:
> That would be MattIJs. I remember you corrected me once because I
> wrote ‘Stephan’, now we’re even ;)

I see, I have to get to Ooraanje visit you and learn some dutch…

> I looked a bit into CC, but the first things I stumbled upon were all
> very much like GNU, which is all about open source, which these
> objects aren’t. If you or someone else can find a CC license that has
> the same content as the current home-made one, I’d be happy to
> replace it.

It has nothing to do with open source, as the license is going with the
actual copy you distribute, if you don’t give away a source, there is no
license for the source. You can also choose a license which prevents
changes if you want to…

Stefan


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


June 15, 2008 | 4:46 pm

Quote: Stefan Tiedje wrote on Sun, 15 June 2008 18:09
—————————————————-
> Mattijs Kneppers schrieb:
> > That would be MattIJs. I remember you corrected me once because I
> > wrote ‘Stephan’, now we’re even ;)
>
> I see, I have to get to Ooraanje visit you and learn some dutch…

You’re always welcome, the beer is on me. Although, now with Oranje beating Italy and France in the European Soccer Championship you might want to wait a bit with coming this way. All the bars are orange.

>
> > I looked a bit into CC, but the first things I stumbled upon were all
> > very much like GNU, which is all about open source, which these
> > objects aren’t. If you or someone else can find a CC license that has
> > the same content as the current home-made one, I’d be happy to
> > replace it.
>
> It has nothing to do with open source, as the license is going with the
> actual copy you distribute, if you don’t give away a source, there is no
> license for the source. You can also choose a license which prevents
> changes if you want to…

Hm, I tried that, but didn’t really get somewhere. On creativecommons.org, where you can choose a license, it starts with the absence of ‘software’ as a ‘format of your work’. When I choose Interactive instead, and No for ‘Allow modifications of your work?’, in the final license I get "No Derivative Works. You may not alter, transform, or build upon this work.", which is not applicable. There is also a different link to Software, to the right, but when I click that I get only open source stuff, pointing me to GNU GPL.

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


June 15, 2008 | 6:39 pm

Quote: Mattijs wrote on Sun, 15 June 2008 03:40
—————————————————-
>
> I have been working with a system that avoids pattrstorage but uses a simple coll to store presets. It also illustrates the max equivalent of how I do this two-way communication in my object oriented Java applications. I’ll see if I can post an example soon.

I’d like to see it. And I have to spend more time looking at your MPC Studio patch.

I thought of pattr when you brought up the topic of model-view-controller, because pattr was the way to go before the oo objects. It has some very nice features that might be a pain to recreate (like interpolation). But it also has some downsides the oo objects address. In a given patch I might use pattr, or oo, or a combination of the two. I haven’t figured out my preferences yet.

> > Can I also reference objects absolutely from the top scope?
>
> No, you can’t. If that would be possible, the whole thing would lose its local aspect. But I’m curious where you would need that. The supposed way to do this is to pass a reference from the top scope to the scopes where you need them.
>
> Although, there is one thing I have been thinking about. There is no way to store that location in a variable (for example ‘main’) and calling it directly, like [oo.call main.updateGui]. Maybe that is a feature we could add in the future.

I’m not sure I follow your ‘main’ example but that might be what I am looking for.

This is an issue with implementing the singleton pattern. Say I want some global object called "service" available everywhere so I put it in the topmost scope. And I’m writing abstractions that are used in various scopes throughout my patch. I need to call methods in "service" without knowing how far up it is.

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#N vpatcher 600 55 895 183;
#P window setfont "Sans Serif" 9.;
#N vpatcher 599 212 1004 451;
#P button 157 53 15 0;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 157 81 109 196617 oo.call oo_top.service;
#P window linecount 2;
#P comment 177 50 100 196617 can I do something like this instead?;
#P button 45 51 15 0;
#P window linecount 1;
#P newex 45 77 82 196617 oo.call ..service;
#P connect 1 0 0 0;
#P connect 4 0 3 0;
#P pop 1;
#P newobj 50 51 114 196617 p @oo public grandchild;
#P pop 1;
#P newobj 146 186 89 196617 p @oo public child;
#P newex 145 131 69 196617 print service;
#P newex 145 105 121 196617 oo.method public service;
#P connect 0 0 1 0;
#P window clipboard copycount 3;


June 15, 2008 | 10:42 pm

Quote: Adam Murray wrote on Fri, 13 June 2008 19:46
—————————————————-
> In a structured OO language like Java, we’d be using an
> interface to make a well-defined the strategy. There’s no way
> to enforce an interface here so it’s up to the patch maker to
> ensure they all work the same way.

Yeah. We haven’t really considered things right down to the level of specifying interfaces, abstract/virtual methods or even argument/return typing yet, but we have had some preliminary discussions on formalizing the way inheritance should be handled, and interfaces would follow from that.

Nice example.

> This is the observer pattern. Use it to register "event
> listeners" that will be notified every time some state
> changes.

This has certainly been worked on since it was first prototyped in the original discussion thread!

We will likely be adding notifier/listener functionality to the core objects, possibly quite soon as the code already exists, it’s just the specific manifestation as objects that needs to be worked out.

The end result will be that you get one-to-many messaging functionality (like send/receive) which is currently missing from the core OO objects unless you build it as you have done.


June 15, 2008 | 11:15 pm

Quote: Adam Murray wrote on Sat, 14 June 2008 16:04
—————————————————-
> I have a question. The oo help file shows examples of calling
> methods relative to the current patch. I can go down
> (child.method) or up (parent.method or .method). Can I also
> reference objects absolutely from the top scope?

Mattijs has explained why we decided against providing an explicit "top" specifier, but you can get a path to (or reference for) the top scope at any time, something like:

#P window setfont "Sans Serif" 9.;
#P number 70 158 59 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P message 70 104 25 196617 this;
#P newex 41 128 39 196617 oo.call;
#N vpatcher 405 235 581 372;
#P window setfont "Sans Serif" 9.;
#N vpatcher 405 395 582 525;
#P window setfont "Sans Serif" 9.;
#N vpatcher 584 234 1004 526;
#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 287 164 32 196617 print;
#P newex 287 139 70 196617 oo.call topref;
#P newex 33 219 78 196617 oo.i @oo topref;
#P newex 143 143 70 196617 oo.call topref;
#P newex 311 116 32 196617 print;
#P button 287 52 15 0;
#P newex 311 91 75 196617 oo.call toppath;
#P newex 139 173 75 196617 oo.call toppath;
#P newex 33 241 86 196617 oo.v @oo toppath;
#P newex 106 109 32 196617 sel 0;
#P newex 128 194 61 196617 sprintf .%s;
#P newex 99 143 39 196617 oo.call;
#P message 106 51 39 196617 parent;
#P newex 35 87 81 196617 oo.call errors 0;
#P fasten 3 0 0 1 133 222 234 222 234 77 111 77;
#P connect 1 0 0 1;
#P connect 0 1 4 0;
#P connect 4 1 2 1;
#P connect 2 1 3 0;
#P connect 2 1 6 0;
#P connect 4 1 10 0;
#P connect 8 0 12 0;
#P connect 12 0 13 0;
#P connect 8 0 7 0;
#P connect 7 0 9 0;
#P pop 1;
#P newobj 51 78 67 196617 p @oo level3;
#P pop 1;
#P newobj 44 71 67 196617 p @oo level2;
#P pop 1;
#P newobj 38 54 67 196617 p @oo level1;
#P connect 2 0 1 1;
#P connect 1 1 3 0;
#P window clipboard copycount 4;

But it might be worthwhile in future if we add this as a native patcher method similar to "getmembers"?

Just bear in mind that in a highly dynamic application, you might get loaded in as a component of something else, so "top" may change. Storing it in a variable as above is therefore setting up for potential trouble.

Note this example exposes a bug in the oo.call errors setting – it shouldn’t throw an error here, but does. Will fix for next release.


June 15, 2008 | 11:24 pm

Quote: Mattijs wrote on Sun, 15 June 2008 22:40
—————————————————-
> There is no way to store that location in a variable (for example
> ‘main’) and calling it directly, like [oo.call main.updateGui].
> Maybe that is a feature we could add in the future.

Do you recall the discussion we had about the hypothetical "oo.alias" or "oo.ref" (formerly oo.var) which would effectively be a pointer to another member? That’s exactly how you’d use it.

Find reference to top (or any) member "parent.parent.(etc)".
Pass reference to local oo.alias "main".
Call "main.updateGUI".

Though the caveats against storing a reference to the presumed top scope in a dynamic system would still apply.

oo.alias would be very useful when passing references in patcher args via constructor methods, or in evaluated oo.call input.


June 16, 2008 | 8:24 pm

Quote: johnpitcairn wrote on Sun, 15 June 2008 15:42
—————————————————-
> Quote: Adam Murray wrote on Fri, 13 June 2008 19:46
> —————————————————-
> > In a structured OO language like Java, we’d be using an
> > interface to make a well-defined the strategy. There’s no way
> > to enforce an interface here so it’s up to the patch maker to
> > ensure they all work the same way.
>
> Yeah. We haven’t really considered things right down to the level of specifying interfaces, abstract/virtual methods or even argument/return typing yet, but we have had some preliminary discussions on formalizing the way inheritance should be handled, and interfaces would follow from that.
>

I wasn’t criticizing the lack of interface. These days I prefer using highly dynamic scripting languages for most of my programming, because it’s easier to extend functionality and sometimes there are pleasant surprises in terms of emergent functionality (unplanned features) when you aren’t locked into well-defined interfaces.

So I don’t think I’d want interfaces to be well-defined in Max. For me, it’s all about the open-ended message passing and fast prototyping…

But interested to see whatever you come up with.


June 16, 2008 | 9:31 pm

To make this discussion a little more concrete, I’m trying to generalize that observer pattern to a larger patch. I want a single "event manager" object. Instead of attaching event listeners to specific "subject" objects, I’ll subscribe to notifications for specific event types. So instead of using a [bag] like in my observer patch, there would be a [coll] that stores entries like: "event_type callback_1 … callback_n". All events pass through the the global event manager, which triggers the appropriate callbacks.

For example, if I’m playing a MIDI keyboard, there might be a chord detector that sends "chord" events (like "chord major", "chord minor"). Other parts of my patch would subscribe to "chord" events, and then whenever anything generates a chord event, the listeners would receive messages like "major" or "minor". This is a many-to-many notification system (instead of one-to-many like my observer patch) and it could be a great way to build very flexible generative music patches.

If I was doing something like this in another programming language, I would have a singleton class with static methods for registering event listeners and generating events. I don’t see a good way to translate that into the oo objects yet. The complication is I want to drop in abstractions that have initialization logic like:
1. find the event manager
2a. register as a listener for some event type
or
2b. generate events

I want to drop the abstraction in and have it initialize itself, because I might be dropping in abstractions on the fly. That’s why I was asking how to find the top scope, because I can put the event manager there and anything can find it. I understand your warnings – I’ll just make sure the event manager is always at the top. If you have any other ideas on how to do this, I’m all ears.

BTW thanks for sharing that patch to find the top scope.

Quote: johnpitcairn wrote on Sun, 15 June 2008 16:24
—————————————————-
> Quote: Mattijs wrote on Sun, 15 June 2008 22:40
> —————————————————-
> > There is no way to store that location in a variable (for example
> > ‘main’) and calling it directly, like [oo.call main.updateGui].
> > Maybe that is a feature we could add in the future.
>
> Do you recall the discussion we had about the hypothetical "oo.alias" or "oo.ref" (formerly oo.var) which would effectively be a pointer to another member? That’s exactly how you’d use it.
>
> Find reference to top (or any) member "parent.parent.(etc)".
> Pass reference to local oo.alias "main".
> Call "main.updateGUI".
>
> Though the caveats against storing a reference to the presumed top scope in a dynamic system would still apply.
>
> oo.alias would be very useful when passing references in patcher args via constructor methods, or in evaluated oo.call input.
—————————————————-


June 16, 2008 | 10:42 pm

Quote: Adam Murray wrote on Tue, 17 June 2008 09:31
—————————————————-
> If I was doing something like this in another programming
> language, I would have a singleton class with static methods
> for registering event listeners and generating events. I don’t
> see a good way to translate that into the oo objects yet.

I don’t know if static members will be especially do-able in this environment, but we’ll continue to think about that, they’d be pretty handy.

> The complication is I want to drop in abstractions that have
> initialization logic like:
> 1. find the event manager
> 2a. register as a listener for some event type
> or
> 2b. generate events

Thinking …

First, rather than just blindly finding "top", it might be safer to try to call an event manager "discovery" method that returns a known magic value (maybe use the entry method?) in each parent, recursing up until you find it, ie:

.EventManager
..EventManager
…etc

Then:

2a: EventManager.attachListener as you’ve prototyped, or

2b: Pass the generated events to a handler method, EventManager.handleEvent.

You’d get a reference to this method returned from something like EventManager.getHandler, and use it to set a call in the generator.

You could pass the event type with each event generated for a generic handler, or use a separate handler method for each event type (perhaps passing the type in to getHandler).

Workable?


June 16, 2008 | 11:21 pm

Quote: johnpitcairn wrote on Mon, 16 June 2008 15:42
—————————————————-
>
> rather than just blindly finding "top", it might be safer to try to call an event manager "discovery" method that returns a known magic value (maybe use the entry method?) in each parent, recursing up until you find it, ie:
>
> .EventManager
> ..EventManager
> …etc
>
[snip]
>
> Workable?
>
—————————————————-

Yeah, I think so. Seems pretty reasonable.

I’ll let you know how it goes. Might not have time to try this right away though.


June 17, 2008 | 6:51 am

Mattijs Kneppers schrieb:
> Hm, I tried that, but didn’t really get somewhere. On
> creativecommons.org, where you can choose a license, it starts with
> the absence of ‘software’ as a ‘format of your work’. When I choose
> Interactive instead, and No for ‘Allow modifications of your work?’,
> in the final license I get "No Derivative Works. You may not alter,
> transform, or build upon this work.", which is not applicable. There
> is also a different link to Software, to the right, but when I click
> that I get only open source stuff, pointing me to GNU GPL.

I just tried, and it’ll give me BY-NC-ND…

Stefan


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


June 19, 2008 | 5:20 pm

Quote: Adam Murray wrote on Sun, 15 June 2008 20:39
—————————————————-
> Quote: Mattijs wrote on Sun, 15 June 2008 03:40
> —————————————————-
> >
> > I have been working with a system that avoids pattrstorage but uses a simple coll to store presets. It also illustrates the max equivalent of how I do this two-way communication in my object oriented Java applications. I’ll see if I can post an example soon.
>
> I’d like to see it.

I attached a simple patch that shows my current idea of a model-view-controller setup, including an easy way to store presets in a coll. It also has multiple views of the same data, and addresses the two-way interface (the same data can be adjusted in multiple locations). Not as polished as your examples, Adam, but hopefully still understandable.

I didn’t use an observer system for the interface, although that would be a useful add-on when the patch gets more complex.

Mattijs


June 20, 2008 | 8:34 am

Quote: Stefan Tiedje wrote on Tue, 17 June 2008 08:51
—————————————————-
> Mattijs Kneppers schrieb:
> > Hm, I tried that, but didn’t really get somewhere. On
> > creativecommons.org, where you can choose a license, it starts with
> > the absence of ‘software’ as a ‘format of your work’. When I choose
> > Interactive instead, and No for ‘Allow modifications of your work?’,
> > in the final license I get "No Derivative Works. You may not alter,
> > transform, or build upon this work.", which is not applicable. There
> > is also a different link to Software, to the right, but when I click
> > that I get only open source stuff, pointing me to GNU GPL.
>
> I just tried, and it’ll give me BY-NC-ND…
>
> Stefan
>

What exactly did you just try? Clicking the separate software link or filling out the form with Interaction as a ‘format of your work’?

Mattijs


June 20, 2008 | 5:10 pm


January 10, 2009 | 5:33 pm

So any news in Max 5 now SDK is out?


January 10, 2009 | 10:41 pm

Mattijs and I have both been really busy for a few months, but I’m working on it now. No great problems, just a couple of things remain to update for Max 5 (as per my posts in the dev forum if you’re interested). I’m hoping for a release later this month, stay tuned.


January 11, 2009 | 12:21 am

Quote: johnpitcairn wrote on Sat, 10 January 2009 23:41
—————————————————-
> Mattijs and I have both been really busy for a few months, but I’m working on it now. No great problems, just a couple of things remain to update for Max 5 (as per my posts in the dev forum if you’re interested). I’m hoping for a release later this month, stay tuned.
—————————————————-

Seconded.

Mattijs


February 6, 2009 | 8:14 pm

I’m looking forward to the updated oo objects. Thanks for your work on this, great initiative.



kjg
February 7, 2009 | 12:18 pm

thank you for the continued work on the OO objects.
they are a very valuable addition to max.

regards,
klaas-jan


March 23, 2009 | 2:43 pm

Any more news on this?

Would be really good for a project I’m working on now.

James.


March 23, 2009 | 3:06 pm
James Drake wrote on Mon, 23 March 2009 15:43
Any more news on this?

Would be really good for a project I’m working on now.

James.

Hi James,

Everything works except for edge cases that are not especially limiting. Although we do prefer to get rid of all the issues we know about before starting a beta test, I could send you a personal copy of the current distribution.

So if you feel like testing the current version please mail me off-list and I’ll send you a zip.

Best,
Mattijs


March 30, 2009 | 1:49 pm

@Adam Murray or Mattijs (or anyone else in fact)

Looking through the examples posted so far has been very helpful, thanks for everyone’s work so far on this. There are still some things i’m not fully grasping that you might be able to shed some light on

Firstly: In (eg) Java, we might have a Class and instantiate objects from it. Using OO objects, how should i be imagining the equivalent? do we have one scoped patcher which we somehow create instances from at runtime? or is there no direct equivalent of a Class, and instances are represented by separate patchers that exist in the saved patch?

Secondly: an instance (i’ll call it channel_group) might need to keep a list of references to other objects of a certain kind (channels), which it can use to call (currently unknown) methods on in the future. The group might have a public interface that allows channels to be added and removed from its internal list. The observer example seems to give some clues in this direction but the penny hasn’t dropped yet for me. Is there already an example around of this kind of arrangement?


March 31, 2009 | 12:20 am
Quote:
In (eg) Java, we might have a Class and instantiate objects from it. Using OO objects, how should i be imagining the equivalent?

Class definition = abstraction (patcher saved to disk).

Class instance = abstraction instantiated in patcher with @oo attribute

A (non-abstraction) subpatcher with an @oo attribute can be thought of as a singleton class instance with an implied class definition.

Quote:
Secondly: an instance (i’ll call it channel_group) might need to keep a list of references to other objects … The observer example seems to give some clues in this direction but the penny hasn’t dropped yet for me.

Essentially you’d define a class based on some object that can maintain a list of integers, giving it some public access oo.methods – add, remove, clear, dump, etc. Instantiate that inside your channel_group instance.

Bag, funbuff, table, coll, zl etc are all good candidate objects, depending on exactly what you need to store and how you need to access it.

Note that it needn’t be a separate class, you can just use the object itself cabled inside your instance – wrapping the access to it with oo.methods if you want a consistent interface (ie you might change the object used in future).


March 31, 2009 | 7:21 am
bitbutter wrote on Mon, 30 March 2009 15:49
do we have one scoped patcher which we somehow create instances from at runtime?

In addition to what John said: the oo objects do not provide a way to create instances of objects dynamically during ‘runtime’. That is still done with Max, by hand, with scripting or using a poly~ object.

The oo objects do support auto-naming these dynamically created instances, see the help patch for more information about that.

Mattijs


March 31, 2009 | 8:40 am

Thanks for the clarifications, that makes sense.

Quote:
Essentially you’d define a class based on some object that can maintain a list of integers, giving it some public access oo.methods – add, remove, clear, dump, etc. Instantiate that inside your channel_group instance.

Inside whichever storage object got used, would it be the numerical id’s of the ‘this’ method of the channel instances that would get stored?

If i understood that correctly, then i understand how channel_group can call the ‘this’ method of its channel objects, but is there then a way for the channel_group object to (for instance) call the ‘print_something’ method on each of the objects represented in its store object instead?

Thanks again for your answers and apologies if these questions are very basic.


March 31, 2009 | 10:51 am
bitbutter wrote on Tue, 31 March 2009 10:40
but is there then a way for the channel_group object to (for instance) call the ‘print_something’ method on each of the objects represented in its store object instead?

There is. Input the stored integer reference to ‘this’ of the destination object in the right inlet of oo.call, oo.call will translate it to the destination name. Then use [sprintf %s.print_something] to append the actual destination method, input the result in the right inlet of another oo.call, then use its left inlet to send data to your destined method.

Hope that helps, but if this is not clear send me a (preferably simplified) patch with your current state of affairs and I’ll see if I can implement the solution for you.

Mattijs


March 31, 2009 | 2:24 pm

Ahh i see, Thanks. I made this intermediate patch to help get an understanding of the conversion/deconversion process that would be involved in storing references to objects (which you could then call arbitrary methods on at a later time). Great stuff!

[patch removed]


March 31, 2009 | 2:42 pm
bitbutter wrote on Tue, 31 March 2009 16:24
I made this intermediate patch to help get an understanding of the conversion/deconversion process that would be involved in storing references to objects (which you could then call arbitrary methods on at a later time). Great stuff!

Thanks, and yes, that example is correct. But please let’s take exchanging Max 5 patches off-list as long as we haven’t released the oo objects for Max 5 yet.


March 31, 2009 | 3:00 pm

No problem. Patch removed.


March 31, 2009 | 8:57 pm
Mattijs wrote on Tue, 31 March 2009 23:51
Input the stored integer reference to ‘this’ of the destination object in the right inlet of oo.call, oo.call will translate it to the destination name. Then use [sprintf %s.print_something] to append the actual destination method

Another way to handle it would be to do your own message despatch from the channel object’s "this" method, based on an appended method name. zl ecils to get the method name and cable it to oo.call’s right inlet, cabling the rest of the message to oo.call’s left inlet.

As Max 4 (heh):

#P window setfont "Sans Serif" 9.;
#P window linecount 1;
#P newex 98 120 51 196617 oo.call;
#P newex 98 97 51 196617 zl ecils 1;
#P newex 98 75 75 196617 oo.method this;
#P connect 1 1 2 1;
#P connect 1 0 2 0;
#P connect 0 0 1 0;
#P window clipboard copycount 3;

[oo.alias] is something we’ve discussed for a future version, it would store a reference and allow you to call that as if it was the original object referred to:

channel a = new channel;
alias b = a;
b.print_something() // calls a.print_something()


April 23, 2009 | 5:46 pm

Is there currently (or are their any plans to implement) a way of intercepting calls to unimplemented methods in a scoped subpatcher? I was looking for a way to have a subpatcher relay all calls to methods that it doesn’t implement, to another object (to have it act as a kind of proxy).


April 26, 2009 | 10:22 pm

When faced with this sort of request, my usual response would be "why do you need to do that"?

Can you frame your question in terms of what you want to achieve, rather than how you expect to achieve it? The scoped patcher can already tell you what methods it implements, if that’s of any use.

Alternately, what would be the equivalent in some other oo language?


April 27, 2009 | 8:06 am
Quote:
Alternately, what would be the equivalent in some other oo language?

Ruby’s method_missing

http://www.sitepoint.com/blogs/2008/07/11/lets-get-meta-missing-method/


April 27, 2009 | 5:23 pm
bitbutter wrote on Mon, 27 April 2009 01:06
Ruby’s method_missing

Although I have found Ruby’s method_missing hook incredibly useful in some situations, I’m having trouble seeing how to get the same benefit in Max. Wouldn’t it be simpler to create an ‘anything’ method and [route] as needed based on the parameters?

Maybe you can describe a particular problem you are trying to solve.


April 27, 2009 | 11:31 pm

We could posit some [oo.method missing] construct I suppose, but how would you expect oo.call to respond when an attempt is made to set a call to a non-existent method? Should it output the reference of [oo.method missing] instead of 0? Seems a bit ambiguous, and I hate ambiguity.

If you really want to go this way, you could use the "this" method and roll your own method despatch internally based on appended message arguments, as I outlined a few posts back in response to another question.

Or test at oo.call set if the method exists, and if not, set the call to some known default method instead? All the tools you need to do that exist, you’d just make an abstraction extending oo.call.

Or include your own method-discovery method inside your patchers, returning a reference to the method (if found) or to the default method (if not)?

As Adam suggests, I think a description of the problem you need to solve would be useful, rather than a request for a specific solution.


April 28, 2009 | 10:09 am

For the patch i was working on i scrapped the idea of using a missing_method type approach and used a simpler solution.

Thanks for the suggestions for emulating something like method_missing, I’ll revist them next time I think it would be useful.


June 5, 2009 | 5:08 pm

Hi,

For all you fans, we have done a silent release of the Max 5 and Windows versions of the oo objects:

http://www.cycling74.com/twiki/bin/view/Share/MattijsKneppers

This version, 0.41, is focused only on the transition to Max 5 and Windows. We’ve also been working on some other upgrades which we believe will make the oo objects easier to understand for new users. But these need more work before we will be ready to release them in 0.5 and 0.6.

With this version we included a folder called ‘oo examples’. In the future we want to keep adding examples of how scope and object oriented principles can improve working with complex max patches.

If you have any questions or suggestions, let us know!

Cheers,
Mattijs and John


September 18, 2009 | 4:45 pm

Hi,

I ran into some scoping trouble getting the oo objects (v0.41) to work in a poly~ under Max 5.0.7. Sorry if somebody’s already asked you about this one, or if you already know!

In my patch I have a poly~ scoped as "test". Inside the poly~ are three subpatchers, scoped as "p1", "p2" and "p3". Each one contains a method named "rand". In p1 and p2 the rand methods are public, and in p3 it is private. There are four calls in the top level of the poly~ patcher – to p1.rand, p2.rand, p3.rand and test.rand.

What seems to happen is that _none_ of the subpatchers in the poly~ get registered using their @oo attributes, and the subpatcher "p3" get registered with the @oo attribute of the poly~ object itself (as "test"). The Max window shows the first two subpatchers also attempting to register as "test" and failing, I think:

"patcher: oo patcher: cannot register patcher as "test" in parent scope "test[1]", name is already in use"

So calls to p1.rand, p2.rand and p3.rand throw errors saying they can’t find any such members, and a call to test.rand throws an error that the method is private.

Any thoughts? Here are the patches:

myPatch.maxpat

– Pasted Max Patch, click to expand. –

oopoly.maxpat

– Pasted Max Patch, click to expand. –

September 19, 2009 | 6:08 pm

Hi Josiah,

Thanks for the elaborate description and example patches. I will look into this in the next few days.

Best,
Mattijs


December 7, 2009 | 2:31 am

The link for OO Objects no longer works. It looks like the share pages were taken down temporarily for the recent website redesign. Is there somewhere else we can get them until the share pages are restored?


December 8, 2009 | 11:46 pm

Uh. Seems I don’t have a complete Mac/Win distribution zip for 0.42 here either. Mattijs, I think we need you…


December 9, 2009 | 7:54 am

Estas parecen muy interesantes. ahora que estoy empezando a trabajar en un parche grande y compleja que estoy interesado en aprender más acerca de estos objetos …

aunque no tengo conocimientos de programación, tengo una idea general sobre lo que es OOP. lo suficiente para ver cómo se puede simplificar algunas rutinas de revisión de la construcción.

el problema que tenemos ahora es que me he mirado los objetos y la ayuda a los archivos, pero yo no puedo dar el siguiente paso para utilizar estos objetos. ¿Puede alguien publique un parche ejemplo, el uso de estos en su contexto? Yo sé que me ayudaría mucho.

Allied International Credit


December 9, 2009 | 8:51 pm

Can anyone translate that for those of us who have only English?


December 9, 2009 | 9:00 pm

Don’t think we released 0.42 yet, duh. I’ve put 0.41 up on the Opus Locus webserver:

oo objects 0.41 (mac)
oo objects 0.41 (windows)


July 6, 2013 | 5:08 am

Any news on these objects?
(Using Max 6.1.3 on Mac OS X 10.8.4 they don’t work)
Thank you
Bernhard


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