pdlua luatrace.lua debugging library
[pdlua:pdlua.git] / src / pd.lua
1 --[[
2 pdlua -- a Lua embedding for Pd
3 Copyright (C) 2007 Claude Heiland-Allen
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18 --]]
19
20 pd = { }
21
22 --[[============================]]--
23 --[[ sanitise pdraw definitions ]]--
24 --[[============================]]--
25
26 pd.init = function (x)
27   pd[x] = pdraw[x]
28 end
29 pd.init_wrap = function (x)
30   pd["_wrap__" .. x] = pdraw[x]
31 end
32
33 pd.init("PD_MAJOR_VERSION")
34 pd.init("PD_MINOR_VERSION")
35 pd.init("PD_BUGFIX_VERSION")
36 pd.init("PD_TEST_VERSION")
37 pd.init("MAXPDSTRING")
38 pd.init("MAXPDARG")
39 pd.init("GP_NONE")
40 pd.init("GP_GLIST")
41 pd.init("GP_ARRAY")
42 pd.init("A_NULL")
43 pd.init("A_FLOAT")
44 pd.init("A_SYMBOL")
45 pd.init("A_POINTER")
46 pd.init("A_SEMI")
47 pd.init("A_COMMA")
48 pd.init("A_DEFFLOAT")
49 pd.init("A_DEFSYM")
50 pd.init("A_DOLLAR")
51 pd.init("A_DOLLSYM")
52 pd.init("A_GIMME")
53 pd.init("A_CANT")
54 pd.init("A_DEFSYMBOL")
55 pd.init("T_TEXT")
56 pd.init("T_OBJECT")
57 pd.init("T_MESSAGE")
58 pd.init("T_ATOM")
59 pd.init("pd_objectmaker")
60 pd.init("pd_canvasmaker")
61 pd.init("s_pointer")
62 pd.init("s_float")
63 pd.init("s_symbol")
64 pd.init("s_bang")
65 pd.init("s_list")
66 pd.init("s_anything")
67 pd.init("s_signal")
68 pd.init("s__N")
69 pd.init("s__X")
70 pd.init("s_x")
71 pd.init("s_y")
72 pd.init("s_")
73 pd.init("pd_typedmess")
74 pd.init("pd_forwardmess")
75 pd.init("gensym")
76 pd.init("getfn")
77 pd.init("zgetfn")
78 pd.init("nullfn")
79 pd.init("pd_vmess")
80 pd.init("obj_list")
81 pd.init("pd_newest")
82 pd.init("getbytes")
83 pd.init("getzbytes")
84 pd.init("copybytes")
85 pd.init("freebytes")
86 pd.init("resizebytes")
87 pd.init("atom_getfloat")
88 pd.init("atom_getint")
89 pd.init("atom_getsymbol")
90 pd.init("atom_gensym")
91 pd.init("atom_getfloatarg")
92 pd.init("atom_getintarg")
93 pd.init("atom_getsymbolarg")
94
95 --[[ seems to require a writeable buffer, probably unsafe
96 pd.init("atom_string")
97 --]]
98
99 --[[ don't know yet if these are safe to use
100 pd.init("binbuf_new")
101 pd.init("binbuf_free")
102 pd.init("binbuf_duplicate")
103 pd.init("binbuf_text")
104 pd.init("binbuf_gettext")
105 pd.init("binbuf_clear")
106 pd.init("binbuf_add")
107 pd.init("binbuf_addv")
108 pd.init("binbuf_addbinbuf")
109 pd.init("binbuf_addsemi")
110 pd.init("binbuf_restore")
111 pd.init("binbuf_print")
112 pd.init("binbuf_getnatom")
113 pd.init("binbuf_getvec")
114 pd.init("binbuf_eval")
115 pd.init("binbuf_read")
116 pd.init("binbuf_read_via_canvas")
117 pd.init("binbuf_read_via_path")
118 pd.init("binbuf_write")
119 pd.init("binbuf_evalfile")
120 pd.init("binbuf_realizedollsym")
121 --]]
122
123 pd.init_wrap("clock_new")      -- TODO write wrapper
124 pd.init("clock_set")
125 pd.init("clock_delay")
126 pd.init("clock_unset")
127 pd.init("clock_getlogicaltime")
128 pd.init("clock_getsystime")
129 pd.init("clock_gettimesince")
130 pd.init("clock_getsystimeafter")
131 pd.init("clock_free")
132
133 pd.init_wrap("pd_new")
134 pd.init("pd_free")
135 pd.init("pd_bind")
136 pd.init("pd_unbind")
137 pd.init("pd_findbyclass")
138 pd.init("pd_pushsym")
139 pd.init("pd_popsym")
140 --[[ undefined symbol in pd
141 pd.init("pd_getfilename")
142 pd.init("pd_getdirname")
143 --]]
144 pd.init("pd_bang")
145 pd.init("pd_pointer")
146 pd.init("pd_float")
147 pd.init("pd_symbol")
148 pd.init("pd_list")
149 --[[ undefined symbol in pd
150 pd.init("pd_anything")
151 --]]
152
153 --[[ don't know if these are safe yet 
154 EXTERN void gpointer_init(t_gpointer *gp);
155 EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto);
156 EXTERN void gpointer_unset(t_gpointer *gp);
157 EXTERN int gpointer_check(const t_gpointer *gp, int headok);
158 --]]
159
160 --[[ don't know if these are safe yet 
161 EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1,
162     t_symbol *s2);
163 EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp);
164 EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp);
165 EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp);
166 EXTERN t_inlet *signalinlet_new(t_object *owner, t_float f);
167 EXTERN void inlet_free(t_inlet *x);
168 --]]
169 pd.init("outlet_new")
170 pd.init("outlet_bang")
171 pd.init("outlet_pointer")
172 pd.init("outlet_float")
173 pd.init("outlet_symbol")
174 pd.init("outlet_list")       -- TODO make useable
175 pd.init("outlet_anything")   -- TODO make useable
176 pd.init("outlet_getsymbol")
177 pd.init("outlet_free")
178 pd.init("pd_checkobject")
179
180 --[[ don't know what this is
181 EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir);
182 --]]
183 pd.init("canvas_setargs")
184 --[[ don't know how to handle writable arguments yet
185 EXTERN void canvas_getargs(int *argcp, t_atom **argvp);
186 --]]
187 pd.init("canvas_getcurrentdir")
188 pd.init("canvas_getcurrent")
189 --[[ don't know how to handle writable arguments yet
190 EXTERN void canvas_makefilename(t_glist *c, char *file,
191     char *result,int resultsize);
192 --]]
193 pd.init("canvas_getdir")
194 pd.init("sys_fontwidth")
195 pd.init("sys_fontheight")
196 --[[ don't know how to handle binbufs or writable arguments yet
197 EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b);
198 EXTERN int canvas_open(t_canvas *x, const char *name, const char *ext,
199     char *dirresult, char **nameresult, unsigned int size, int bin);
200 --]]
201
202 pd.init("pd_getparentwidget")
203
204 pd.init("CLASS_DEFAULT")
205 pd.init("CLASS_PD")
206 pd.init("CLASS_GOBJ")
207 pd.init("CLASS_PATCHABLE")
208 pd.init("CLASS_NOINLET")
209 pd.init("CLASS_TYPEMASK")
210
211 pd.init_wrap("class_new")
212 pd.init_wrap("class_addcreator")
213 pd.init_wrap("class_addmethod")
214 pd.init_wrap("class_addbang")
215 pd.init_wrap("class_addpointer")
216 pd.init_wrap("class_doaddfloat")
217 pd.init_wrap("class_addsymbol")
218 pd.init_wrap("class_addlist")
219 pd.init_wrap("class_addanything")
220 pd.init("class_sethelpsymbol")
221 pd.init("class_setwidget")
222 pd.init("class_setparentwidget")
223 --[[ undefined symbol in pd
224 EXTERN t_parentwidgetbehavior *class_parentwidget(t_class *c);
225 --]]
226 pd.init("class_getname")
227 pd.init("class_gethelpname")
228 pd.init("class_setdrawcommand")
229 pd.init("class_isdrawcommand")
230 pd.init("class_domainsignalin")
231
232 pd.init_wrap("class_setsavefn")        -- TODO write wrapper
233 pd.init_wrap("class_getsavefn")        -- TODO write wrapper
234 pd.init_wrap("class_setpropertiesfn")  -- TODO write wrapper
235 pd.init_wrap("class_getpropertiesfn")  -- TODO write wrapper
236
237 pd.init("post")
238 pd.init("startpost")
239 pd.init("poststring")
240 pd.init("postfloat")
241 pd.init("postatom")
242 pd.init("endpost")
243 pd.init("error")
244 pd.init("verbose")
245 pd.init("bug")
246 pd.init("pd_error")
247 pd.init("sys_logerror")
248 pd.init("sys_unixerror")
249 pd.init("sys_ouch")
250
251 --[[ undefined symbol in pd
252 EXTERN int sys_isreadablefile(const char *name);
253 --]]
254 --[[ don't know how to handle writeable arguments
255 EXTERN void sys_bashfilename(const char *from, char *to);
256 EXTERN void sys_unbashfilename(const char *from, char *to);
257 EXTERN int open_via_path(const char *name, const char *ext, const char *dir,
258     char *dirresult, char **nameresult, unsigned int size, int bin);
259 --]]
260 pd.init("sched_geteventno")
261 pd.init("sys_getrealtime")
262 --[[ don't know how to deal with this
263 EXTERN int (*sys_idlehook)(void);
264 --]]
265
266 pd.init("sys_lock")
267 pd.init("sys_unlock")
268 pd.init("sys_trylock")
269
270 pd.init("MAXLOGSIG")
271 pd.init("MAXSIGSIZE")
272
273 --[[ we don't handle dsp yet
274
275 EXTERN t_int *plus_perform(t_int *args);
276 EXTERN t_int *zero_perform(t_int *args);
277 EXTERN t_int *copy_perform(t_int *args);
278
279 EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n);
280 EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n);
281 EXTERN void dsp_add_scalarcopy(t_sample *in, t_sample *out, int n);
282 EXTERN void dsp_add_zero(t_sample *out, int n);
283
284 EXTERN int sys_getblksize(void);
285 EXTERN float sys_getsr(void);
286 EXTERN int sys_get_inchannels(void);
287 EXTERN int sys_get_outchannels(void);
288
289 EXTERN void dsp_add(t_perfroutine f, int n, ...);
290 EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec);
291 EXTERN void pd_fft(float *buf, int npoints, int inverse);
292 EXTERN int ilog2(int n);
293
294 EXTERN void mayer_fht(float *fz, int n);
295 EXTERN void mayer_fft(int n, float *real, float *imag);
296 EXTERN void mayer_ifft(int n, float *real, float *imag);
297 EXTERN void mayer_realfft(int n, float *real);
298 EXTERN void mayer_realifft(int n, float *real);
299
300 EXTERN float *cos_table;
301 #define LOGCOSTABSIZE 9
302 #define COSTABSIZE (1<<LOGCOSTABSIZE)
303
304 EXTERN int canvas_suspend_dsp(void);
305 EXTERN void canvas_resume_dsp(int oldstate);
306 EXTERN void canvas_update_dsp(void);
307 EXTERN int canvas_dspstate;
308
309 EXTERN void resample_init(t_resample *x);
310 EXTERN void resample_free(t_resample *x);
311
312 EXTERN void resample_dsp(t_resample *x, t_sample *in, int insize, t_sample *out, int outsize, int method);
313 EXTERN void resamplefrom_dsp(t_resample *x, t_sample *in, int insize, int outsize, int method);
314 EXTERN void resampleto_dsp(t_resample *x, t_sample *out, int insize, int outsize, int method);
315
316 --]]
317
318 pd.init("mtof")
319 pd.init("ftom")
320 pd.init("rmstodb")
321 pd.init("powtodb")
322 pd.init("dbtorms")
323 pd.init("dbtopow")
324 pd.init("q8_sqrt")
325 pd.init("q8_rsqrt")
326 pd.init("qsqrt")
327 pd.init("qrsqrt")
328
329 --[[ we don't handle arrays yet
330
331 EXTERN_STRUCT _garray;
332 #define t_garray struct _garray
333
334 EXTERN t_class *garray_class;
335 EXTERN int garray_getfloatarray(t_garray *x, int *size, t_float **vec);
336 #if 0
337 EXTERN float garray_get(t_garray *x, t_symbol *s, t_int indx);
338 #endif
339 EXTERN void garray_redraw(t_garray *x);
340 EXTERN int garray_npoints(t_garray *x);
341 EXTERN char *garray_vec(t_garray *x);
342 EXTERN void garray_resize(t_garray *x, t_floatarg f);
343 EXTERN void garray_usedindsp(t_garray *x);
344 EXTERN void garray_setsaveit(t_garray *x, int saveit);
345 EXTERN t_class *scalar_class;
346
347 EXTERN t_float *value_get(t_symbol *s);
348 EXTERN void value_release(t_symbol *s);
349 EXTERN int value_getfloat(t_symbol *s, t_float *f);
350 EXTERN int value_setfloat(t_symbol *s, t_float f);
351
352 --]]
353
354 --[[ we don't handle GUI yet
355 typedef void (*t_guicallbackfn)(t_gobj *client, t_glist *glist);
356
357 EXTERN void sys_vgui(char *fmt, ...);
358 EXTERN void sys_gui(char *s);
359 EXTERN void sys_pretendguibytes(int n);
360 EXTERN void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f);
361 EXTERN void sys_unqueuegui(void *client);
362     /* dialog window creation and destruction */
363 EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd);
364 EXTERN void gfxstub_deleteforkey(void *key);
365 --]]
366
367 pd.init("glob_pdobject")
368
369 --[[ undefined symbol in pd
370 EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine,
371     t_method freeroutine, t_symbol *name, size_t size, int tiny, \
372     t_atomtype arg1, ...);
373 EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...);
374 --]]
375
376 --[[ we don't handle loaders yet
377 void sys_register_loader(loader_t loader);
378 --]]
379
380 pd.internal_class_new         = pdraw.pdlua_internal_class_new
381 pd.internal_class_addcreator  = pdraw.pdlua_internal_class_addcreator
382 pd.internal_class_addanything = pdraw.pdlua_internal_class_addanything
383 pd.internal_pd_new            = pdraw.pdlua_internal_pd_new
384
385 -- clean up
386 pd.init = nil
387 pd.init_wrap = nil
388 pdraw = nil
389
390 --[[==============================]]--
391 --[[ interesting code starts here ]]--
392 --[[==============================]]--
393
394 -- various storage for Pd C<->Lua interaction
395 pd.constructor  = { }
396 pd.destructor   = { }
397 pd.object       = { }
398 pd.classmethod  = { }
399 pd.objectmethod = { }
400
401 -- a non-string key for the method tables' "anything" methods
402 pd.ANYTHING = -1
403
404 -- id for objects, because SWIG for Lua makes pointers incomparable
405 pd.internal_nextid = 999
406 pd.nextid = function ()
407   pd.internal_nextid = pd.internal_nextid + 1
408   return pd.internal_nextid
409 end
410
411 -- object constructor
412 pd.pd_new = function (class, data)
413   local object = pd.internal_pd_new(class)
414   object.id = pd.nextid()
415   pd.object[object.id] = data
416   return object
417 end
418
419 -- get the stuff we stored in the constructor
420 pd.getdata = function (object)
421   return pd.object[object.id]
422 end
423
424 -- constructor dispatcher
425 pd.internal_new = function (classsym, argc, argv, id)
426   return pd.constructor[classsym.s_name](classsym, argc, argv)
427 end
428
429 -- destructor dispatcher
430 pd.internal_free = function (class, object)
431   if pd.destructor[pd.class_getname(class)] then
432     pd.destructor[pd.class_getname(class)](object)
433   end
434   pd.object[object.id] = nil
435 end
436
437 -- method dispatcher
438 pd.internal_dispatch = function (class, object, inlet, sel, argc, argv)
439   classname = pd.class_getname(class)
440   if pd.classmethod[classname][inlet][sel.s_name] then
441     pd.classmethod[classname][inlet][sel.s_name](object, sel, argc, argv)
442   elseif pd.classmethod[classname][inlet][pd.ANYTHING] then
443     pd.classmethod[classname][inlet][pd.ANYTHING](object, sel, argc, argv)
444   elseif pd.objectmethod[object.id][inlet][sel.s_name] then
445     pd.objectmethod[object.id][inlet][sel.s_name](object, sel, argc, argv)
446   elseif pd.objectmethod[object.id][inlet][pd.ANYTHING] then
447     pd.objectmethod[object.id][inlet][pd.ANYTHING](object, sel, argc, argv)
448   end
449 end
450
451 -- class constructor, store stuff for later
452 pd.class_new = function (classname, new, free, flags)
453   local class = pd.internal_class_new(classname, flags)
454   pd.constructor[classname.s_name] = new
455   pd.destructor[pd.class_getname(class)] = free
456   return class
457 end
458
459 -- add a synonym for a class
460 pd.class_addcreator = function (classname, new)
461   pd.internal_class_addcreator(classname)
462   pd.constructor[classname.s_name] = new
463 end
464
465 -- add a method
466 pd.class_addmethod = function (class, method, sel)
467   name = pd.class_getname(class)
468   if not pd.classmethod[name]    then pd.classmethod[name]    = { } end
469   if not pd.classmethod[name][0] then pd.classmethod[name][0] = { } end
470   if sel then
471     pd.classmethod[name][0][sel.s_name] = method
472   else
473     pd.classmethod[name][0][pd.ANYTHING] = method
474   end
475   if #pd.classmethod[name][0] == 0 then
476     -- internally, we have only one method per inlet and dispatch ourself
477     pd.internal_class_addanything(class)
478   end
479 end
480 pd.class_addanything = function (class, method)
481   pd.class_addmethod(class, method, nil)
482 end
483
484 -- some simple options to make life easier
485 pd.class_addbang = function (class, method)
486   local wrapped = function (obj, sel, argc, argv)
487     method(obj)
488   end
489   pd.class_addmethod(class, wrapped, pd.s_bang)
490 end
491 pd.class_addpointer = function (class, method)
492   local wrapped = function (obj, sel, argc, argv)
493     x = pd.atom_getpointerarg(0, argc, argv)
494     method(obj, x)
495   end
496   pd.class_addmethod(class, wrapped, pd.s_pointer)
497 end
498 pd.class_addfloat = function (class, method)
499   local wrapped = function (obj, sel, argc, argv)
500     x = pd.atom_getfloatarg(0, argc, argv)
501     method(obj, x)
502   end
503   pd.class_addmethod(class, wrapped, pd.s_float)
504 end
505 pd.class_addsymbol = function (class, method)
506   local wrapped = function (obj, sel, argc, argv)
507     x = pd.atom_getsymbolarg(0, argc, argv)
508     method(obj, x)
509   end
510   pd.class_addmethod(class, wrapped, pd.s_symbol)
511 end
512 pd.class_addlist = function (class, method)
513   pd.class_addmethod(class, method, pd.s_list)
514 end
515
516 -- EOF --