1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
pdlua
===
The Lua loader included in -lib pdlua allows externals for Pd to be
written in the Lua programming language.
If you try to create an object [foo] in Pd, Pd checks if the class
"foo" exists. If it doesn't, it tries to load an external file that
"probably" will contain code for "foo". The Lua loader adds support
for loading "foo.pd_lua" when you try to create [foo].
Class Creation
--------------
The first expression/statement in the file should be of the form:
local foo = pd.Class:new():register("foo")
This creates a new Pd class called "foo". The 'local' declaration
is optional, but recommended -- without it, 'foo' is global, which
means any Lua code can modify it (possibly by accident).
Object Initialization
---------------------
Then you can add methods to the Pd class. The most important one
is 'initialize', which is executed when a new object is created.
function foo:initialize(sel, atoms)
-- code
end
or equivalently:
foo.initialize = function (self, sel, atoms)
-- code
end
'sel' is usually (always?) the class name, 'atoms' are the creation
arguments in a Lua table. An example:
Pd :: [foo a b 1 2 3 c]
sel == "foo"
atoms == { "a", "b", 1, 2, 3, "c" }
Being a method, 'initialize' has a 'self' variable (which is the
object to be created), and if you want your objects to have inlets
or outlets you need need to set those fields in this method (Pd
doesn't support changing the number of inlets or outlets after an
object is created):
self.inlets = 1
self.outlets = atoms[1]
The default inlet/outlet counts are 0.
The return value of 'initialize' is used to allow objects to fail
to create (for example, if the creation arguments are bad). Most
of the time you will 'return true', but if you really can't create
then you can 'return false'.
If you need to do things after the Pd object is created, but before
control is returned to Pd, you can use the 'postinitialize' method:
function foo:postinitialize()
-- code
end
Object Finalization
-------------------
The 'finalize' method is called when the object is deleted by Pd.
You can clean up stuff here if needed. The default implementation
does nothing.
Inlet Methods
-------------
FIXME: write about inlet methods/dispatching
FIXME: for now, see examples/*.pd_lua and src/pd.lua
Sending To Outlets
------------------
FIXME: write about self:outlet(outletNumber, selector, atoms)
FIXME: for now, see examples/*.pd_lua and src/pd.lua
Sending To Receivers
--------------------
You can send messages to receivers like this:
pd.send("receiver", "selector", { "a", "message", 1, 2, 3 }
See examples/lsend.pd_lua for details.
Receivers
---------
You can bind methods to receivers, to get messages from
[send receiver] and "; receiver message".
See examples/lreceive.pd_lua for details.
Remember to clean up your receivers in object:finalize(), or weird
things will happen.
Clocks
------
You can bind methods to clocks, for timing based on Pd's logical clock.
See examples/ldelay.pd_lua for details.
Remember to clean up your clocks in object:finalize(), or weird things
will happen.
Miscellaneous Object Methods
----------------------------
Execute a Lua file using Pd's path to find it:
self:dofile("filename")
Report an error to Pd's console:
self:error("message")
Miscellaneous Functions
-----------------------
Print a string to Pd's console:
pd.post("a string")
Note that pd.post() should not really be used for errors.
FIXME: add pd.error() for error messages
|