pdlua: attempt to fix the require situation (but it's still confusing..)
[pdlua:pdlua.git] / src / lua.c
1 /** @file lua.c 
2  *  @brief pdlua -- a Lua embedding for Pd.
3  *  @author Claude Heiland-Allen <claudiusmaximus@goto10.org>
4  *  @date 2008
5  *  @version 0.6~svn
6  *
7  * Copyright (C) 2007,2008 Claude Heiland-Allen <claudiusmaximus@goto10.org>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22  *
23  */ 
24
25 /* various C stuff, mainly for reading files */
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30
31 /* we use Lua */
32 #include <lua.h>
33 #include <lauxlib.h>
34 #include <lualib.h>
35
36 /* we use Pd */
37 #include <m_pd.h>
38
39 /* support windows */
40 #ifdef MSW
41 #define EXPORT __declspec(dllexport) extern
42 #else
43 #define EXPORT                       extern
44 #endif
45
46
47 /* BAD: support for Pd < 0.41 */
48
49 #if PD_MAJOR_VERSION == 0
50 # if PD_MINOR_VERSION >= 41
51 #  define PDLUA_PD41
52 /* use new garray support that is 64-bit safe */
53 #  define PDLUA_ARRAYGRAB garray_getfloatwords
54 #  define PDLUA_ARRAYTYPE t_word
55 #  define PDLUA_ARRAYELEM(arr,idx) ((arr)[(idx)].w_float)
56 # elif PD_MINOR_VERSION >= 40
57 #  define PDLUA_PD40
58 /* use old garray support, not 64-bit safe */
59 #  warning "Pd version is not new enough for 64-bit safe arrays"
60 #  define PDLUA_ARRAYGRAB garray_getfloatarray
61 #  define PDLUA_ARRAYTYPE t_float
62 #  define PDLUA_ARRAYELEM(arr,idx) ((arr)[(idx)])
63 # elif PD_MINOR_VERSION >= 39
64 #  define PDLUA_PD39
65 /* use old garray support, not 64-bit safe */
66 #  warning "Pd version is not new enough for 64-bit safe arrays"
67 #  define PDLUA_ARRAYGRAB garray_getfloatarray
68 #  define PDLUA_ARRAYTYPE t_float
69 #  define PDLUA_ARRAYELEM(arr,idx) ((arr)[(idx)])
70 # else
71 #  error "Pd version is too old, please upgrade"
72 # endif
73 #else
74 # error "Pd version is too new, please file a bug report"
75 #endif
76
77 /* BAD: end of bad section */
78
79 /* EVIL: TODO: File requests/patches to Pd so that this becomes unnecessary. */
80
81 /** Pd loader type, defined in pd/src/s_loader.c but not exported. */
82 typedef int (*loader_t)(t_canvas *, char *);
83
84 /** Pd loader registration, defined in pd/src/s_loader.c but not exported. */
85 void sys_register_loader(loader_t loader);
86
87 /** Pd extern dir declaration (for help finding), defined in pd/src/m_class.c but not exported. */
88 void class_set_extern_dir(t_symbol *s);
89
90 /** Pd [value] getter, defined in pd/src/x_connective.c but not exported. */
91 int value_getfloat(t_symbol *s, t_float *f);
92
93 /** Pd [value] setter, defined in pd/src/x_connective.c but not exported. */
94 int value_setfloat(t_symbol *s, t_float f);
95
96 /* EVIL: end of evil section. */
97
98 /** Global Lua interpreter state, needed in the constructor. */
99 static lua_State *L;
100
101 /** State for the Lua file reader. */
102 typedef struct pdlua_readerdata {
103   int fd; /**< File descriptor to read from. */
104   char buffer[MAXPDSTRING]; /**< Buffer to read into. */
105 } t_pdlua_readerdata;
106
107 /** Lua file reader callback. */
108 static const char *pdlua_reader(
109   lua_State *L, /**< Lua interpreter state. */
110   void *rr, /**< Lua file reader state. */
111   size_t *size /**< How much data we have read. */
112 ) {
113   t_pdlua_readerdata *r = rr;
114   ssize_t s;
115   s = read(r->fd, r->buffer, MAXPDSTRING-2);
116   if (s <= 0) {
117     *size = 0;
118     return NULL;
119   } else {
120     *size = s;
121     return r->buffer;
122   }
123 }
124
125 /* declare some stuff in advance */
126 struct pdlua_proxyinlet;
127 struct pdlua_proxyreceive;
128 struct pdlua_proxyclock;
129
130 /** Pd object data. */
131 typedef struct pdlua {
132   t_object pd; /**< We are a Pd object. */
133   unsigned int inlets; /**< Number of inlets. */
134   struct pdlua_proxyinlet *in; /**< The inlets themselves. */
135   unsigned int outlets; /**< Number of outlets. */
136   t_outlet **out; /**< The outlets themselves. */
137   t_canvas *canvas; /**< The canvas that the object was created on. */
138 } t_pdlua;
139
140 /* more forward declarations */
141 static void pdlua_dispatch(
142   t_pdlua *o, unsigned int inlet, t_symbol *s, int argc, t_atom *argv
143 );
144 static void pdlua_receivedispatch(
145   struct pdlua_proxyreceive *r, t_symbol *s, int argc, t_atom *argv
146 );
147 static void pdlua_clockdispatch(
148   struct pdlua_proxyclock *clock
149 );
150
151
152 /** Proxy inlet class pointer. */
153 static t_class *pdlua_proxyinlet_class;
154
155 /** Proxy inlet object data. */
156 typedef struct pdlua_proxyinlet {
157   t_pd pd; /**< Minimal Pd object. */
158   struct pdlua *owner; /**< The owning object to forward inlet messages to. */
159   unsigned int id; /**< The number of this inlet. */
160 } t_pdlua_proxyinlet;
161
162 /** Proxy inlet 'anything' method. */
163 static void pdlua_proxyinlet_anything(
164   t_pdlua_proxyinlet *p, /**< The proxy inlet that received the message. */
165   t_symbol *s, /**< The message selector. */
166   int argc, /**< The message length. */
167   t_atom *argv /**< The atoms in the message. */
168 ) {
169   pdlua_dispatch(p->owner, p->id, s, argc, argv);
170 }
171
172 /** Proxy inlet initialization. */
173 static void pdlua_proxyinlet_init(
174   t_pdlua_proxyinlet *p, /**< The proxy inlet to initialize. */
175   struct pdlua *owner, /**< The owning object. */
176   unsigned int id /**< The inlet number. */
177 ) {
178   p->pd = pdlua_proxyinlet_class;
179   p->owner = owner;
180   p->id = id;
181 }
182
183 /** Register the proxy inlet class with Pd. */
184 static void pdlua_proxyinlet_setup() {
185   pdlua_proxyinlet_class = class_new(
186     gensym("pdlua proxy inlet"),
187     0,
188     0,
189     sizeof(t_pdlua_proxyinlet),
190     0,
191     0
192   );
193   class_addanything(
194     pdlua_proxyinlet_class, pdlua_proxyinlet_anything
195   );
196 }
197
198
199 /** Proxy receive class pointer. */
200 static t_class *pdlua_proxyreceive_class;
201
202 /** Proxy receive object data. */
203 typedef struct pdlua_proxyreceive {
204   t_pd pd; /**< Minimal Pd object. */
205   struct pdlua *owner; /**< The owning object to forward received messages to. */
206   t_symbol *name; /**< The receive-symbol to bind to. */
207 } t_pdlua_proxyreceive;
208
209 /** Proxy receive 'anything' method. */
210 static void pdlua_proxyreceive_anything(
211   t_pdlua_proxyreceive *r, /**< The proxy receive that received the message. */
212   t_symbol *s, /**< The message selector. */
213   int argc, /**< The message length. */
214   t_atom *argv /**< The atoms in the message. */
215 ) {
216   pdlua_receivedispatch(r, s, argc, argv);
217 }
218
219 /** Proxy receive allocation and initialization. */
220 static t_pdlua_proxyreceive *pdlua_proxyreceive_new(
221   struct pdlua *owner, /**< The owning object. */
222   t_symbol *name /**< The symbol to bind to. */
223 ) {
224   t_pdlua_proxyreceive *r = malloc(sizeof(t_pdlua_proxyreceive));
225   r->pd = pdlua_proxyreceive_class;
226   r->owner = owner;
227   r->name = name;
228   pd_bind(&r->pd, r->name);
229   return r;
230 }
231
232 /** Proxy receive cleanup and deallocation. */
233 static void pdlua_proxyreceive_free(
234   t_pdlua_proxyreceive *r /**< The proxy receive to free. */
235 ) {
236   pd_unbind(&r->pd, r->name);
237   r->pd = NULL;
238   r->owner = NULL;
239   r->name = NULL;
240   free(r);
241 }
242
243 /** Register the proxy receive class with Pd. */
244 static void pdlua_proxyreceive_setup() {
245   pdlua_proxyreceive_class = class_new(
246     gensym("pdlua proxy receive"),
247     0,
248     0,
249     sizeof(t_pdlua_proxyreceive),
250     0,
251     0
252   );
253   class_addanything(
254     pdlua_proxyreceive_class, pdlua_proxyreceive_anything
255   );
256 }
257
258
259 /** Proxy clock class pointer. */
260 static t_class *pdlua_proxyclock_class;
261
262 /** Proxy clock object data. */
263 typedef struct pdlua_proxyclock {
264   t_pd pd; /**< Minimal Pd object. */
265   struct pdlua *owner; /**< Object to forward messages to. */
266   t_clock *clock; /** Pd clock to use. */
267 } t_pdlua_proxyclock;
268
269 /** Proxy clock 'bang' method. */
270 static void pdlua_proxyclock_bang(
271   t_pdlua_proxyclock *c /**< The proxy clock that received the message. */
272 ) {
273   pdlua_clockdispatch(c);
274 }
275
276 /** Proxy clock allocation and initialization. */
277 static t_pdlua_proxyclock *pdlua_proxyclock_new(
278   struct pdlua *owner /**< The object to forward messages to. */
279 ) {
280   t_pdlua_proxyclock *c = malloc(sizeof(t_pdlua_proxyclock));
281   c->pd = pdlua_proxyclock_class;
282   c->owner = owner;
283   c->clock = clock_new(c, (t_method) pdlua_proxyclock_bang);
284   return c;
285 }
286
287 /** Register the proxy clock class with Pd. */
288 static void pdlua_proxyclock_setup() {
289   pdlua_proxyclock_class = class_new(
290     gensym("pdlua proxy clock"),
291     0,
292     0,
293     sizeof(t_pdlua_proxyclock),
294     0,
295     0
296   );
297 }
298
299 /** Dump an array of atoms into a Lua table. */
300 static void pdlua_pushatomtable(
301   int argc, /**< The number of atoms in the array. */
302   t_atom *argv /**< The array of atoms. */
303 ) {
304   int i;
305   lua_newtable(L);
306   for (i = 0; i < argc; ++i) {
307     lua_pushnumber(L, i+1);
308     switch (argv[i].a_type) {
309     case A_FLOAT:
310       lua_pushnumber(L, argv[i].a_w.w_float);
311       break;
312     case A_SYMBOL:
313       lua_pushstring(L, argv[i].a_w.w_symbol->s_name);
314       break;
315     case A_POINTER: /* FIXME: check experimentality */
316       lua_pushlightuserdata(L, argv[i].a_w.w_gpointer);
317       break;
318     default:
319       error("lua: zomg weasels!");
320       lua_pushnil(L);
321       break;
322     }
323     lua_settable(L, -3);
324   }
325 }
326
327 /** Pd object constructor. */
328 static t_pdlua *pdlua_new(
329   t_symbol *s, /**< The construction message selector. */
330   int argc, /**< The construction message atom count. */
331   t_atom *argv /**< The construction message atoms. */
332 ) {
333   lua_getglobal(L, "pd");
334   lua_getfield(L, -1, "_constructor");
335   lua_pushstring(L, s->s_name);
336   pdlua_pushatomtable(argc, argv);
337   if (lua_pcall(L, 2, 1, 0)) {
338     error(
339       "lua: error in constructor for `%s':\n%s",
340       s->s_name, lua_tostring(L, -1)
341     );
342     lua_pop(L, 1);
343     return NULL;
344   } else {
345     t_pdlua *object = NULL;
346     if (lua_islightuserdata(L, -1)) {
347       object = lua_touserdata(L, -1);
348       lua_pop(L, 1);
349       return object;
350     } else {
351       lua_pop(L, 1);
352       return NULL;
353     }
354   }
355 }
356
357 /** Pd object destructor. */
358 static void pdlua_free(
359   t_pdlua *o /**< The object to destruct. */
360 ) {
361   lua_getglobal(L, "pd");
362   lua_getfield (L, -1, "_destructor");
363   lua_pushlightuserdata(L, o);
364   if (lua_pcall(L, 1, 0, 0)) {
365     error(
366       "lua: error in destructor:\n%s",
367       lua_tostring(L, -1)
368     );
369     lua_pop(L, 1);
370   }
371   return;
372 }
373
374 /** Lua class registration. */
375 static int pdlua_class_new(
376   lua_State *L /**< Lua interpreter state.
377   * \par Inputs:
378   * \li \c 1 Class name string.
379   * \par Outputs:
380   * \li \c 1 Pd class pointer.
381   * */
382 ) {
383   const char *name = luaL_checkstring(L, 1);
384   t_class *c = class_new(
385     gensym((char *) name),
386     (t_newmethod) pdlua_new,
387     (t_method) pdlua_free,
388     sizeof(t_pdlua),
389     CLASS_NOINLET,
390     A_GIMME,
391     0
392   );
393   lua_pushlightuserdata(L, c);
394   return 1;
395 }
396
397 /** Lua object creation. */
398 static int pdlua_object_new(
399   lua_State *L /**< Lua interpreter state.
400   * \par Inputs:
401   * \li \c 1 Pd class pointer.
402   * \par Outputs:
403   * \li \c 2 Pd object pointer.
404   * */
405 ) {
406   if (lua_islightuserdata(L, 1)) {
407     t_class *c = lua_touserdata(L, 1);
408     if (c) {
409       t_pdlua *o = (t_pdlua *) pd_new(c);
410       if (o) {
411         o->inlets = 0;
412         o->in = NULL;
413         o->outlets = 0;
414         o->out = NULL;
415         o->canvas = canvas_getcurrent();
416         lua_pushlightuserdata(L, o);
417         return 1;
418       }
419     }
420   }
421   return 0;
422 }
423
424 /** Lua object inlet creation. */
425 static int pdlua_object_createinlets(
426   lua_State *L /**< Lua interpreter state.
427   * \par Inputs:
428   * \li \c 1 Pd object pointer.
429   * \li \c 2 Number of inlets.
430   * */
431 ) {
432   unsigned int i;
433   if (lua_islightuserdata(L, 1)) {
434     t_pdlua *o = lua_touserdata(L, 1);
435     if (o) {
436       o->inlets = luaL_checknumber(L, 2);
437       o->in = malloc(o->inlets * sizeof(t_pdlua_proxyinlet));
438       for (i = 0; i < o->inlets; ++i) {
439         pdlua_proxyinlet_init(&o->in[i], o, i);
440         inlet_new(&o->pd, &o->in[i].pd, 0, 0);
441       }
442     }
443   }
444   return 0;
445 }
446
447 /** Lua object outlet creation. */
448 static int pdlua_object_createoutlets(
449   lua_State *L /**< Lua interpreter state.
450   * \par Inputs:
451   * \li \c 1 Pd object pointer.
452   * \li \c 2 Number of outlets.
453   * */
454 ) {
455   unsigned int i;
456   if (lua_islightuserdata(L, 1)) {
457     t_pdlua *o = lua_touserdata(L, 1);
458     if (o) {
459       o->outlets = luaL_checknumber(L, 2);
460       if (o->outlets > 0) {
461         o->out = malloc(o->outlets * sizeof(t_outlet *));
462         for (i = 0; i < o->outlets; ++i) {
463           o->out[i] = outlet_new(&o->pd, 0);
464         }
465       } else {
466         o->out = NULL;
467       }
468     }
469   }
470   return 0;
471 }
472
473 /** Lua object receive creation. */
474 static int pdlua_receive_new(
475   lua_State *L /**< Lua interpreter state.
476   * \par Inputs:
477   * \li \c 1 Pd object pointer.
478   * \li \c 2 Receive name string.
479   * \par Outputs:
480   * \li \c 1 Pd receive pointer.
481   * */
482 ) {
483   if (lua_islightuserdata(L, 1)) {
484     t_pdlua *o = lua_touserdata(L, 1);
485     if (o) {
486       const char *name = luaL_checkstring(L, 2);
487       if (name) {
488         t_pdlua_proxyreceive *r =  pdlua_proxyreceive_new(o, gensym((char *) name)); /* const cast */
489         lua_pushlightuserdata(L, r);
490         return 1;
491       }
492     }
493   }
494   return 0;
495 }
496
497 /** Lua object receive destruction. */
498 static int pdlua_receive_free(
499   lua_State *L /**< Lua interpreter state.
500   * \par Inputs:
501   * \li \c 1 Pd recieve pointer.
502   * */
503 ) {
504   if (lua_islightuserdata(L, 1)) {
505     t_pdlua_proxyreceive *r = lua_touserdata(L, 1);
506     if (r) {
507       pdlua_proxyreceive_free(r);
508     }
509   }
510   return 0;
511 }
512
513 /** Lua object clock creation. */
514 static int pdlua_clock_new(
515   lua_State *L /**< Lua interpreter state.
516   * \par Inputs:
517   * \li \c 1 Pd object pointer.
518   * \par Outputs:
519   * \li \c 1 Pd clock pointer.
520   * */
521 ) {
522   if (lua_islightuserdata(L, 1)) {
523     t_pdlua *o = lua_touserdata(L, 1);
524     if (o) {
525       t_pdlua_proxyclock *c =  pdlua_proxyclock_new(o);
526       lua_pushlightuserdata(L, c);
527       return 1;
528     }
529   }
530   return 0;
531 }
532
533 /** Lua proxy clock delay. */
534 static int pdlua_clock_delay(
535   lua_State *L /**< Lua interpreter state.
536   * \par Inputs:
537   * \li \c 1 Pd clock pointer.
538   * \li \c 2 Number of milliseconds to delay.
539   * */
540 ) {
541   if (lua_islightuserdata(L, 1)) {
542     t_pdlua_proxyclock *c = lua_touserdata(L, 1);
543     if (c) {
544       double delaytime = luaL_checknumber(L, 2);
545       clock_delay(c->clock, delaytime);
546     }
547   }
548   return 0;
549 }
550
551 /** Lua proxy clock set. */
552 static int pdlua_clock_set(
553   lua_State *L /**< Lua interpreter state.
554   * \par Inputs:
555   * \li \c 1 Pd clock pointer.
556   * \li \c 2 Number to set the clock.
557   * */
558 ) {
559   if (lua_islightuserdata(L, 1)) {
560     t_pdlua_proxyclock *c = lua_touserdata(L, 1);
561     if (c) {
562       double systime = luaL_checknumber(L, 2);
563       clock_set(c->clock, systime);
564     }
565   }
566   return 0;
567 }
568
569 /** Lua proxy clock unset. */
570 static int pdlua_clock_unset(
571   lua_State *L /**< Lua interpreter state.
572   * \par Inputs:
573   * \li \c 1 Pd clock pointer.
574   * */
575 ) {
576   if (lua_islightuserdata(L, 1)) {
577     t_pdlua_proxyclock *c = lua_touserdata(L, 1);
578     if (c) {
579       clock_unset(c->clock);
580     }
581   }
582   return 0;
583 }
584
585 /** Lua proxy clock destruction. */
586 static int pdlua_clock_free(
587   lua_State *L /**< Lua interpreter state.
588   * \par Inputs:
589   * \li \c 1 Pd clock pointer.
590   * */
591 ) {
592   if (lua_islightuserdata(L, 1)) {
593     t_pdlua_proxyclock *c = lua_touserdata(L, 1);
594     if (c) {
595       clock_free(c->clock);
596       free(c);
597     }
598   }
599   return 0;
600 }
601
602 /** Lua object destruction. */
603 static int pdlua_object_free(
604   lua_State *L /**< Lua interpreter state.
605   * \par Inputs:
606   * \li \c 1 Pd object pointer.
607   * */
608 ) {
609   unsigned int i;
610   if (lua_islightuserdata(L, 1)) {
611     t_pdlua *o = lua_touserdata(L, 1);
612     if (o) {
613       if (o->in) {
614         free(o->in);
615       }
616       if(o->out) {
617         for (i = 0; i < o->outlets; ++i) {
618           outlet_free(o->out[i]);
619         }
620         free(o->out);
621         o->out = NULL;
622       }
623     }
624   }
625   return 0;
626 }
627
628 /** Dispatch Pd inlet messages to Lua objects. */
629 static void pdlua_dispatch(
630   t_pdlua *o, /**< The object that received the message. */
631   unsigned int inlet, /**< The inlet that the message arrived at. */
632   t_symbol *s, /**< The message selector. */
633   int argc, /**< The message length. */
634   t_atom *argv /**< The atoms in the message. */
635 ) {
636   lua_getglobal(L, "pd");
637   lua_getfield (L, -1, "_dispatcher");
638   lua_pushlightuserdata(L, o);
639   lua_pushnumber(L, inlet + 1); /* C has 0.., Lua has 1.. */
640   lua_pushstring(L, s->s_name);
641   pdlua_pushatomtable(argc, argv);
642   if (lua_pcall(L, 4, 0, 0)) {
643     pd_error(
644       o,
645       "lua: error in dispatcher:\n%s",
646       lua_tostring(L, -1)
647     );
648     lua_pop(L, 1);
649   }
650   return;  
651 }
652
653 /** Dispatch Pd receive messages to Lua objects. */
654 static void pdlua_receivedispatch(
655   t_pdlua_proxyreceive *r, /**< The proxy receive that received the message. */
656   t_symbol *s, /**< The message selector. */
657   int argc, /**< The message length. */
658   t_atom *argv /**< The atoms in the message. */
659 ) {
660   lua_getglobal(L, "pd");
661   lua_getfield (L, -1, "_receivedispatch");
662   lua_pushlightuserdata(L, r);
663   lua_pushstring(L, s->s_name);
664   pdlua_pushatomtable(argc, argv);
665   if (lua_pcall(L, 3, 0, 0)) {
666     pd_error(
667       r->owner,
668       "lua: error in receive dispatcher:\n%s",
669       lua_tostring(L, -1)
670     );
671     lua_pop(L, 1);
672   }
673   return;  
674 }
675
676 /** Dispatch Pd clock messages to Lua objects. */
677 static void pdlua_clockdispatch(
678   t_pdlua_proxyclock *clock /**< The proxy clock that received the message. */
679 ) {
680   lua_getglobal(L, "pd");
681   lua_getfield (L, -1, "_clockdispatch");
682   lua_pushlightuserdata(L, clock);
683   if (lua_pcall(L, 1, 0, 0)) {
684     pd_error(
685       clock->owner,
686       "lua: error in clock dispatcher:\n%s",
687       lua_tostring(L, -1)
688     );
689     lua_pop(L, 1);
690   }
691   return;  
692 }
693
694 /** Convert a Lua table into a Pd atom array. */
695 static t_atom *pdlua_popatomtable(
696   lua_State *L, /**< Lua interpreter state.
697   * \par Inputs:
698   * \li \c -1 Table to convert.
699   * */
700   int *count, /**< Where to store the array length. */
701   t_pdlua *o /**< Object reference for error messages. */
702 ) {
703   int i;
704   int ok;
705   t_float f;
706   const char *s;
707   void *p;
708   size_t sl;
709   t_atom *atoms;
710   atoms = NULL;
711   ok = 1;
712   if (lua_istable(L, -1)) {
713     *count = lua_objlen(L, -1);
714     if (*count > 0) {
715       atoms = malloc(*count * sizeof(t_atom));
716     }
717     i = 0;
718     lua_pushnil(L);
719     while (lua_next(L, -2) != 0) {
720       if (i == *count) {
721         pd_error(o, "lua: error: too many table elements");
722         ok = 0;
723         break;
724       }
725       switch (lua_type(L, -1)) {
726       case (LUA_TNUMBER):
727         f = lua_tonumber(L, -1);
728         SETFLOAT(&atoms[i], f);
729         break;
730       case (LUA_TSTRING):
731         s = lua_tolstring(L, -1, &sl);
732         if (s) {
733           if (strlen(s) != sl) {
734             pd_error(o, "lua: warning: symbol munged (contains \\0 in body)");
735           }
736           SETSYMBOL(&atoms[i], gensym((char *) s));
737         } else {
738           pd_error(o, "lua: error: null string in table");
739           ok = 0;
740         }
741         break;
742       case (LUA_TLIGHTUSERDATA): /* FIXME: check experimentality */
743         p = lua_touserdata(L, -1);
744         SETPOINTER(&atoms[i], p);
745         break;
746       default:
747         pd_error(o, "lua: error: table element must be number or string or pointer");
748         ok = 0;
749         break;
750       }
751       lua_pop(L, 1);
752       ++i;
753     }
754     if (i != *count) {
755       pd_error(o, "lua: error: too few table elements");
756       ok = 0;
757     }
758   } else {
759     pd_error(o, "lua: error: not a table");
760     ok = 0;
761   }
762   lua_pop(L, 1);
763   if (ok) {
764     return atoms;
765   } else {
766     if (atoms) {
767       free(atoms);
768     }
769     return NULL;
770   }
771 }
772
773 /** Send a message from a Lua object outlet. */
774 static int pdlua_outlet(
775   lua_State *L /**< Lua interpreter state.
776   * \par Inputs:
777   * \li \c 1 Pd object pointer.
778   * \li \c 2 Outlet number.
779   * \li \c 3 Message selector string.
780   * \li \c 4 Message atom table.
781   * */
782 ) {
783   t_pdlua *o;
784   int out;
785   size_t sl;
786   const char *s;
787   t_symbol *sym;
788   int count;
789   t_atom *atoms;
790   if (lua_islightuserdata(L, 1)) {
791     o = lua_touserdata(L, 1);
792     if (o) {
793       if (lua_isnumber(L, 2)) {
794         out = lua_tonumber(L, 2) - 1; /* C has 0.., Lua has 1.. */
795       } else {
796         pd_error(o, "lua: error: outlet must be a number");
797         return 0;
798       }
799       if (0 <= out && out < o->outlets) {
800         if (lua_isstring(L, 3)) {
801           s = lua_tolstring(L, 3, &sl);
802           sym = gensym((char *) s); /* const cast */
803           if (s) {
804             if (strlen(s) != sl) {
805               pd_error(o, "lua: warning: symbol munged (contains \\0 in body)");
806             }
807             lua_pushvalue(L, 4);
808             atoms = pdlua_popatomtable(L, &count, o);
809             if (count == 0 || atoms) {
810               outlet_anything(o->out[out], sym, count, atoms);
811             } else {
812               pd_error(o, "lua: error: no atoms??");
813             }
814             if (atoms) {
815               free(atoms);
816               return 0;
817             }
818           } else {
819             pd_error(o, "lua: error: null selector");
820           }
821         } else {
822           pd_error(o, "lua: error: selector must be a string");
823         }
824       } else {
825         pd_error(o, "lua: error: outlet out of range");
826       }
827     } else {
828       error("lua: error: no object to outlet from");
829     }
830   } else {
831     error("lua: error: bad arguments to outlet");
832   }
833   return 0;
834 }
835
836 /** Send a message from a Lua object to a Pd receiver. */
837 static int pdlua_send(
838   lua_State *L /**< Lua interpreter state.
839   * \par Inputs:
840   * \li \c 1 Receiver string.
841   * \li \c 2 Message selector string.
842   * \li \c 3 Message atom table.
843   * */
844 ) {
845   size_t receivenamel;
846   const char *receivename;
847   t_symbol *receivesym;
848   size_t selnamel;
849   const char *selname;
850   t_symbol *selsym;
851   int count;
852   t_atom *atoms;
853   if (lua_isstring(L, 1)) {
854     receivename = lua_tolstring(L, 1, &receivenamel);
855     receivesym = gensym((char *) receivename); /* const cast */
856     if (receivesym) {
857       if (strlen(receivename) != receivenamel) {
858         error("lua: warning: symbol munged (contains \\0 in body)");
859       }
860       if (lua_isstring(L, 2)) {
861         selname = lua_tolstring(L, 2, &selnamel);
862         selsym = gensym((char *) selname); /* const cast */
863         if (selsym) {
864           if (strlen(selname) != selnamel) {
865             error("lua: warning: symbol munged (contains \\0 in body)");
866           }
867           lua_pushvalue(L, 3);
868           atoms = pdlua_popatomtable(L, &count, NULL);
869           if (count == 0 || atoms) {
870             if (receivesym->s_thing) {
871               typedmess(receivesym->s_thing, selsym, count, atoms);
872             }
873           } else {
874             error("lua: error: no atoms??");
875           }
876           if (atoms) {
877             free(atoms);
878             return 0;
879           }
880         } else {
881           error("lua: error: null selector");
882         }
883       } else {
884         error("lua: error: selector must be a string");
885       }
886     } else {
887       error("lua: error: null receive name");
888     }
889   } else {
890     error("lua: error: receive name must be string");
891   }
892   return 0;
893 }
894
895 /** Set a [value] object's value. */
896 static int pdlua_setvalue(
897   lua_State *L /**< Lua interpreter state.
898   * \par Inputs:
899   * \li \c 1 Value name string.
900   * \li \c 2 Value number.
901   * \par Outputs:
902   * \li \c 1 success (usually depends on a [value] existing or not).
903   */
904 ) {
905   const char *str = luaL_checkstring(L, 1);
906   t_float val = luaL_checknumber(L, 2);
907   int err = value_setfloat(gensym(str), val);
908   lua_pushboolean(L, !err);
909   return 1;
910 }
911
912 /** Get a [value] object's value. */
913 static int pdlua_getvalue(
914   lua_State *L /**< Lua interpreter state.
915   * \par Inputs:
916   * \li \c 1 Value name string.
917   * \par Outputs:
918   * \li \c 1 Value number, or nil for failure.
919   * */
920 ) {
921   const char *str = luaL_checkstring(L, 1);
922   t_float val;
923   int err = value_getfloat(gensym(str), &val);
924   if (!err) {
925     lua_pushnumber(L, val);
926   } else {
927     lua_pushnil(L);
928   }
929   return 1;
930 }
931
932 /** Get a [table] object's array. */
933 static int pdlua_getarray(
934   lua_State *L /**< Lua interpreter state.
935   * \par Inputs:
936   * \li \c 1 Table name string.
937   * \par Outputs:
938   * \li \c 1 Table length, or < 0 for failure.
939   * \li \c 2 Table pointer, or nil for failure.
940   * */
941 ) {
942   t_garray *a;
943   int n;
944   PDLUA_ARRAYTYPE *v;
945   const char *str = luaL_checkstring(L, 1);
946   if (!(a = (t_garray *) pd_findbyclass(gensym(str), garray_class))) {
947     lua_pushnumber(L, -1);
948     return 1;
949   } else if (!PDLUA_ARRAYGRAB(a, &n, &v)) {
950     lua_pushnumber(L, -2);
951     return 1;
952   } else {
953     lua_pushnumber(L, n);
954     lua_pushlightuserdata(L, v);
955     return 2;
956   }
957 }
958
959 /** Read from a [table] object's array. */
960 static int pdlua_readarray(
961   lua_State *L /**< Lua interpreter state.
962   * \par Inputs:
963   * \li \c 1 Table length number.
964   * \li \c 2 Table array pointer.
965   * \li \c 3 Table index number.
966   * \par Outputs:
967   * \li \c 1 Table element value, or nil for index out of range.
968   * */
969 ) {
970   int n = luaL_checknumber(L, 1);
971   PDLUA_ARRAYTYPE *v = lua_islightuserdata(L, 2) ? lua_touserdata(L, 2) : NULL;
972   int i = luaL_checknumber(L, 3);
973   if (0 <= i && i < n && v) {
974     lua_pushnumber(L, PDLUA_ARRAYELEM(v, i));
975     return 1;
976   }
977   return 0;
978 }
979
980 /** Write to a [table] object's array. */
981 static int pdlua_writearray(
982   lua_State *L /**< Lua interpreter state.
983   * \par Inputs:
984   * \li \c 1 Table length number.
985   * \li \c 2 Table array pointer.
986   * \li \c 3 Table index number.
987   * \li \c 4 Table element value number.
988   * */
989 ) {
990   int n = luaL_checknumber(L, 1);
991   PDLUA_ARRAYTYPE *v = lua_islightuserdata(L, 2) ? lua_touserdata(L, 2) : NULL;
992   int i = luaL_checknumber(L, 3);
993   t_float x = luaL_checknumber(L, 4);
994   if (0 <= i && i < n && v) {
995     PDLUA_ARRAYELEM(v, i) = x;
996   }
997   return 0;
998 }
999
1000 /** Redraw a [table] object's graph. */
1001 static int pdlua_redrawarray(
1002   lua_State *L /**< Lua interpreter state.
1003   * \par Inputs:
1004   * \li \c 1 Table name string.
1005   * */
1006 ) {
1007   t_garray *a;
1008   const char *str = luaL_checkstring(L, 1);
1009   if ((a = (t_garray *) pd_findbyclass(gensym(str), garray_class))) {
1010     garray_redraw(a);
1011   }
1012   return 0;
1013 }
1014
1015 /** Post to Pd's console. */
1016 static int pdlua_post(
1017   lua_State *L /**< Lua interpreter state.
1018   * \par Inputs:
1019   * \li \c 1 Message string.
1020   * */
1021 ) {
1022   const char *str = luaL_checkstring(L, 1);
1023   post("%s", str);
1024   return 0;
1025 }
1026
1027 /** Report an error from a Lua object to Pd's console. */
1028 static int pdlua_error(
1029   lua_State *L /**< Lua interpreter state.
1030   * \par Inputs:
1031   * \li \c 1 Pd object pointer.
1032   * \li \c 2 Message string.
1033   * */
1034 ) {
1035   t_pdlua *o;
1036   const char *s;
1037   if (lua_islightuserdata(L, 1)) {
1038     o = lua_touserdata(L, 1);
1039     if (o) {
1040       s = luaL_checkstring(L, 2);
1041       if (s) {
1042         pd_error(o, "%s", s);
1043       } else {
1044         pd_error(o, "lua: error: null string in error function");
1045       }
1046     } else {
1047       error("lua: error: null object in error function");
1048     }
1049   } else {
1050     error("lua: error: bad arguments to error function");
1051   }
1052   return 0;
1053 }
1054
1055 void pdlua_setrequirepath( /* FIXME: documentation */
1056   lua_State *L,
1057   const char *path
1058 ) {
1059   lua_getglobal(L, "pd");
1060   lua_pushstring(L, "_setrequirepath");
1061   lua_gettable(L, -2);
1062   lua_pushstring(L, path);
1063   if (lua_pcall(L, 1, 0, 0) != 0) {
1064     post("lua: internal error in `pd._setrequirepath': %s", lua_tostring(L, -1));
1065     lua_pop(L, 1);
1066   }
1067   lua_pop(L, 1);
1068 }
1069
1070 void pdlua_clearrequirepath( /* FIXME: documentation */
1071   lua_State *L
1072 ) {
1073   lua_getglobal(L, "pd");
1074   lua_pushstring(L, "_clearrequirepath");
1075   lua_gettable(L, -2);
1076   if (lua_pcall(L, 0, 0, 0) != 0) {
1077     post("lua: internal error in `pd._clearrequirepath': %s", lua_tostring(L, -1));
1078     lua_pop(L, 1);
1079   }
1080   lua_pop(L, 1);
1081 }
1082
1083 /** Run a Lua script using Pd's path. */
1084 static int pdlua_dofile(
1085   lua_State *L /**< Lua interpreter state.
1086   * \par Inputs:
1087   * \li \c 1 Pd object pointer.
1088   * \li \c 2 Filename string.
1089   * \par Outputs:
1090   * \li \c * Determined by the script.
1091   * */
1092 ) {
1093   char buf[MAXPDSTRING];
1094   char *ptr;
1095   t_pdlua_readerdata reader;
1096   int fd;
1097   int n;
1098   const char *filename;
1099   t_pdlua * o;
1100   n = lua_gettop(L);
1101   if (lua_islightuserdata(L, 1)) {
1102     o = lua_touserdata(L, 1);
1103     if (o) {
1104       filename = luaL_optstring(L, 2, NULL);
1105       fd = canvas_open(o->canvas, filename, "", buf, &ptr, MAXPDSTRING, 1);
1106       if (fd >= 0) {
1107         pdlua_setrequirepath(L, buf);
1108         reader.fd = fd;
1109         if (lua_load(L, pdlua_reader, &reader, filename)) {
1110           close(fd);
1111           pdlua_clearrequirepath(L);
1112           lua_error(L);
1113         } else {
1114           if (lua_pcall(L, 0, LUA_MULTRET, 0)) {
1115             pd_error(
1116               o,
1117               "lua: error running `%s':\n%s",
1118               filename,
1119               lua_tostring(L, -1)
1120             );
1121             lua_pop(L, 1);
1122             close(fd);
1123             pdlua_clearrequirepath(L);
1124           } else {
1125             /* succeeded */
1126             close(fd);
1127             pdlua_clearrequirepath(L);
1128           }
1129         }
1130       } else {
1131         pd_error(o, "lua: error loading `%s': canvas_open() failed", filename);
1132       }
1133     } else {
1134       error("lua: error in object:dofile() - object is null");
1135     }
1136   } else {
1137     error("lua: error in object:dofile() - object is wrong type");
1138   }
1139   return lua_gettop(L) - n;
1140 }
1141
1142 /** Initialize the pd API for Lua. */
1143 static void pdlua_init(
1144   lua_State *L /**< Lua interpreter state. */
1145 ) {
1146   lua_newtable(L);
1147   lua_setglobal(L, "pd");
1148   lua_getglobal(L, "pd");
1149   lua_pushstring(L, "_iswindows");
1150 #ifdef MSW
1151   lua_pushboolean(L, 1);
1152 #else
1153   lua_pushboolean(L, 0);
1154 #endif
1155   lua_settable(L, -3);
1156   lua_pushstring(L, "_register");
1157   lua_pushcfunction(L, pdlua_class_new);
1158   lua_settable(L, -3);
1159   lua_pushstring(L, "_create");
1160   lua_pushcfunction(L, pdlua_object_new);
1161   lua_settable(L, -3);
1162   lua_pushstring(L, "_createinlets");
1163   lua_pushcfunction(L, pdlua_object_createinlets);
1164   lua_settable(L, -3);
1165   lua_pushstring(L, "_createoutlets");
1166   lua_pushcfunction(L, pdlua_object_createoutlets);
1167   lua_settable(L, -3);
1168   lua_pushstring(L, "_destroy");
1169   lua_pushcfunction(L, pdlua_object_free);
1170   lua_settable(L, -3);
1171   lua_pushstring(L, "_outlet");
1172   lua_pushcfunction(L, pdlua_outlet);
1173   lua_settable(L, -3);
1174   lua_pushstring(L, "_createreceive");
1175   lua_pushcfunction(L, pdlua_receive_new);
1176   lua_settable(L, -3);
1177   lua_pushstring(L, "_receivefree");
1178   lua_pushcfunction(L, pdlua_receive_free);
1179   lua_settable(L, -3);
1180   lua_pushstring(L, "_createclock");
1181   lua_pushcfunction(L, pdlua_clock_new);
1182   lua_settable(L, -3);
1183   lua_pushstring(L, "_clockfree");
1184   lua_pushcfunction(L, pdlua_clock_free);
1185   lua_settable(L, -3);
1186   lua_pushstring(L, "_clockset");
1187   lua_pushcfunction(L, pdlua_clock_set);
1188   lua_settable(L, -3);
1189   lua_pushstring(L, "_clockunset");
1190   lua_pushcfunction(L, pdlua_clock_unset);
1191   lua_settable(L, -3);
1192   lua_pushstring(L, "_clockdelay");
1193   lua_pushcfunction(L, pdlua_clock_delay);
1194   lua_settable(L, -3);
1195   lua_pushstring(L, "_dofile");
1196   lua_pushcfunction(L, pdlua_dofile);
1197   lua_settable(L, -3);
1198   lua_pushstring(L, "send");
1199   lua_pushcfunction(L, pdlua_send);
1200   lua_settable(L, -3);
1201   lua_pushstring(L, "getvalue");
1202   lua_pushcfunction(L, pdlua_getvalue);
1203   lua_settable(L, -3);
1204   lua_pushstring(L, "setvalue");
1205   lua_pushcfunction(L, pdlua_setvalue);
1206   lua_settable(L, -3);
1207   lua_pushstring(L, "_getarray");
1208   lua_pushcfunction(L, pdlua_getarray);
1209   lua_settable(L, -3);
1210   lua_pushstring(L, "_readarray");
1211   lua_pushcfunction(L, pdlua_readarray);
1212   lua_settable(L, -3);
1213   lua_pushstring(L, "_writearray");
1214   lua_pushcfunction(L, pdlua_writearray);
1215   lua_settable(L, -3);
1216   lua_pushstring(L, "_redrawarray");
1217   lua_pushcfunction(L, pdlua_redrawarray);
1218   lua_settable(L, -3);
1219   lua_pushstring(L, "post");
1220   lua_pushcfunction(L, pdlua_post);
1221   lua_settable(L, -3);
1222   lua_pushstring(L, "_error");
1223   lua_pushcfunction(L, pdlua_error);
1224   lua_settable(L, -3);
1225   lua_pop(L, 1);
1226 }
1227
1228 /** Pd loader hook for loading and executing Lua scripts. */
1229 static int pdlua_loader(
1230   t_canvas *canvas, /**< Pd canvas to use to find the script. */
1231   char *name /**< The name of the script (without .pd_lua extension). */
1232 ) {
1233   char dirbuf[MAXPDSTRING];
1234   char *ptr;
1235   int fd;
1236   t_pdlua_readerdata reader;
1237   fd = canvas_open(canvas, name, ".pd_lua", dirbuf, &ptr, MAXPDSTRING, 1);
1238   if (fd >= 0) {
1239     class_set_extern_dir(gensym(dirbuf));
1240     pdlua_setrequirepath(L, dirbuf);
1241     reader.fd = fd;
1242     if (lua_load(L, pdlua_reader, &reader, name) ||
1243         lua_pcall(L, 0, 0, 0)) {
1244       error(
1245         "lua: error loading `%s':\n%s",
1246         name,
1247         lua_tostring(L, -1)
1248       );
1249       lua_pop(L, 1);
1250       close(fd);
1251       pdlua_clearrequirepath(L);
1252       class_set_extern_dir(&s_);
1253       return 0;
1254     }
1255     close(fd);
1256     pdlua_clearrequirepath(L);
1257     class_set_extern_dir(&s_);
1258     return 1;
1259   } else {
1260     return 0;
1261   }
1262 }
1263
1264 /** Start the Lua runtime and register our loader hook. */
1265 EXPORT void lua_setup(void) {
1266   char buf[MAXPDSTRING];
1267   char *ptr;
1268   t_pdlua_readerdata reader;
1269   int fd;
1270   post("lua 0.6~svn (GPL) 2008 Claude Heiland-Allen <claudiusmaximus@goto10.org>");
1271   post("lua: compiled for pd-%d.%d on %s %s", PD_MAJOR_VERSION, PD_MINOR_VERSION, __DATE__, __TIME__);
1272   pdlua_proxyinlet_setup();
1273   pdlua_proxyreceive_setup();
1274   pdlua_proxyclock_setup();
1275   L = lua_open();
1276   luaL_openlibs(L);
1277   pdlua_init(L);
1278   /* "pd.lua" is the Lua part of pdlua, want to keep the C part minimal */
1279   fd = canvas_open(0, "pd", ".lua", buf, &ptr, MAXPDSTRING, 1);
1280   if (fd >= 0) {
1281     reader.fd = fd;
1282     if (lua_load(L, pdlua_reader, &reader, "pd.lua") ||
1283         lua_pcall(L, 0, 0, 0)) {
1284       error(
1285         "lua: error loading `pd.lua':\n%s",
1286         lua_tostring(L, -1)
1287       );
1288       error("lua: loader will not be registered!");
1289       error("lua: (is `pd.lua' in Pd's path list?)");
1290       lua_pop(L, 1);
1291       close(fd);
1292     } else {
1293       close(fd);
1294       sys_register_loader(pdlua_loader);
1295     }
1296   } else {
1297     error("lua: error loading `pd.lua': canvas_open() failed");
1298     error("lua: loader will not be registered!");
1299   }
1300 }
1301
1302 /* EOF */