[PD] Clocks and [pipe] in Lua

Frank Barknecht fbar at footils.org
Thu Mar 13 15:46:04 CET 2008


Hallo,
matteo sisti sette hat gesagt: // matteo sisti sette wrote:

> > > Something like this probably works (untested...):
> > >
> > > function M:in_1(sel, atoms)
> > > [...]
> > > end
> >
> > Ah, a very elegant solution. It's tested now (attached) and seems to
> > work really well.
> 
> I'll need some time to understand this (have to read some pdlua
> documentaion, understand clicks, ntm get familiar with lua), so in the
> meanwhile please forgive a stupid question:
> 
> Does this solve/eliminate the problem mentioned by Frank? that is:
> 
> > My problem is the hypothetical "makeclock". It should be a clock that
> > somehow is tied to the event. But as I see it, clocks in pdlua are
> > supposed to be tied to a pdclass object itself, and their callback
> > methods don't accept any additional arguments to specify which of the
> > event they should handle.

Yes, it does. The clock is still registered to the pd-object ("self")
and the callback function that the clock calls after the delay time
has passed, is also tied to the pd-object, but now the message payload
is known to the callback function, because it is kept in the
callback's environment as a so called upvalue (and the callback is a
closure now). See http://www.lua.org/pil/6.1.html for details on
closures and upvalues. 

Basically closures are functions that you define inside of other
functions. Local variables that are defined in the outer function are
accessible in the inner function, the closure, as well, even after the
outer function returns. So what Claude's solution does is this: 

First the inlet method for the first inlet is defined:

 function M:in_1(sel, atoms)
   ... 
 end

This gets called whenever anything comes in to the 1st inlet. Then a
local variable "clock" is created to hold the clock, the payload is
available as local variables "sel" and "atoms" as well (coming in as
arguments to M:in_1). 

 function M:in_1(sel, atoms)
   ...
   local clock = pd.Clock:new():register(self, id)
   ...
 end

Registering a clock this way will try to call back a method in self's
function table with the name of the value of the variable id, i.e.:
self[id] later like: self[id](self)

So Claude just creates such a method locally in the next step:

 function M:in_1(sel, atoms)
   ...
   local clock = pd.Clock:new():register(self, id)
   ...
   self[id] = function (self)
      ...
   end
   ...
 end

Now inside of this dynamically created function, "clock", "sel" and
"atoms", the upvalues, are accessible. Voila! 

After the closure is defined, all that is left to do is start the
clock with clock:delay(time) and then return from the inlet function.
The upvalues are still available to the closure, which later commits
suicide after killing the clock as well.

You can call the inlet method many times to create many clocks and
delay many different messages just like [pipe]. In Lua this is a
30 line file, in C/Pd it takes 230 lines.

Ciao
-- 
 Frank Barknecht                                     _ ______footils.org__




More information about the Pd-list mailing list