Add the identifying header
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / m_pd.c
blob25f5f2d212a2faa60148af78e5a2d555b37e81dc
1 /* Copyright (c) 1997-1999 Miller Puckette.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 #include "m_pd.h"
6 #include "m_imp.h"
8 #ifdef ROCKBOX
9 void pd_checkgui(t_pd *x, t_symbol *s);
10 #else /* ROCKBOX */
11 #include <stdlib.h>
12 #endif /* ROCKBOX */
14 /* FIXME no out-of-memory testing yet! */
16 t_pd *pd_new(t_class *c)
18 t_pd *x;
19 if (!c)
20 bug ("pd_new: apparently called before setup routine");
21 x = (t_pd *)t_getbytes(c->c_size);
22 *x = c;
23 if (c->c_patchable)
25 ((t_object *)x)->ob_inlet = 0;
26 ((t_object *)x)->ob_outlet = 0;
28 return (x);
31 void pd_free(t_pd *x)
33 t_class *c = *x;
34 if (c->c_freemethod) (*(t_gotfn)(c->c_freemethod))(x);
35 if (c->c_patchable)
37 while (((t_object *)x)->ob_outlet)
38 outlet_free(((t_object *)x)->ob_outlet);
39 while (((t_object *)x)->ob_inlet)
40 inlet_free(((t_object *)x)->ob_inlet);
41 if (((t_object *)x)->ob_binbuf)
42 binbuf_free(((t_object *)x)->ob_binbuf);
44 if (c->c_size) t_freebytes(x, c->c_size);
47 void gobj_save(t_gobj *x, t_binbuf *b)
49 t_class *c = x->g_pd;
50 if (c->c_savefn)
51 (c->c_savefn)(x, b);
54 /* deal with several objects bound to the same symbol. If more than one, we
55 actually bind a collection object to the symbol, which forwards messages sent
56 to the symbol. */
58 static t_class *bindlist_class;
60 typedef struct _bindelem
62 t_pd *e_who;
63 struct _bindelem *e_next;
64 } t_bindelem;
66 typedef struct _bindlist
68 t_pd b_pd;
69 t_bindelem *b_list;
70 } t_bindlist;
72 static void bindlist_bang(t_bindlist *x)
74 t_bindelem *e;
75 for (e = x->b_list; e; e = e->e_next)
76 pd_bang(e->e_who);
79 static void bindlist_float(t_bindlist *x, t_float f)
81 t_bindelem *e;
82 for (e = x->b_list; e; e = e->e_next) {
83 pd_float(e->e_who, f);
87 static void bindlist_symbol(t_bindlist *x, t_symbol *s)
89 t_bindelem *e;
90 for (e = x->b_list; e; e = e->e_next)
91 pd_symbol(e->e_who, s);
94 static void bindlist_pointer(t_bindlist *x, t_gpointer *gp)
96 t_bindelem *e;
97 for (e = x->b_list; e; e = e->e_next)
98 pd_pointer(e->e_who, gp);
101 static void bindlist_list(t_bindlist *x, t_symbol *s,
102 int argc, t_atom *argv)
104 t_bindelem *e;
105 for (e = x->b_list; e; e = e->e_next)
106 pd_list(e->e_who, s, argc, argv);
109 static void bindlist_anything(t_bindlist *x, t_symbol *s,
110 int argc, t_atom *argv)
112 t_bindelem *e;
113 for (e = x->b_list; e; e = e->e_next)
114 pd_typedmess(e->e_who, s, argc, argv);
117 void m_pd_setup(void)
119 bindlist_class = class_new(gensym("bindlist"), 0, 0,
120 sizeof(t_bindlist), CLASS_PD, 0);
121 class_addbang(bindlist_class, bindlist_bang);
122 class_addfloat(bindlist_class, (t_method)bindlist_float);
123 class_addsymbol(bindlist_class, bindlist_symbol);
124 class_addpointer(bindlist_class, bindlist_pointer);
125 class_addlist(bindlist_class, bindlist_list);
126 class_addanything(bindlist_class, bindlist_anything);
129 void pd_bind(t_pd *x, t_symbol *s)
131 pd_checkgui(x,s);
132 if (s->s_thing)
134 if (*s->s_thing == bindlist_class)
136 t_bindlist *b = (t_bindlist *)s->s_thing;
137 t_bindelem *e = (t_bindelem *)getbytes(sizeof(t_bindelem));
138 e->e_next = b->b_list;
139 e->e_who = x;
140 b->b_list = e;
142 else
144 t_bindlist *b = (t_bindlist *)pd_new(bindlist_class);
145 t_bindelem *e1 = (t_bindelem *)getbytes(sizeof(t_bindelem));
146 t_bindelem *e2 = (t_bindelem *)getbytes(sizeof(t_bindelem));
147 b->b_list = e1;
148 e1->e_who = x;
149 e1->e_next = e2;
150 e2->e_who = s->s_thing;
151 e2->e_next = 0;
152 s->s_thing = &b->b_pd;
155 else s->s_thing = x;
158 void pd_unbind(t_pd *x, t_symbol *s)
160 if (s->s_thing == x) s->s_thing = 0;
161 else if (s->s_thing && *s->s_thing == bindlist_class)
163 /* bindlists always have at least two elements... if the number
164 goes down to one, get rid of the bindlist and bind the symbol
165 straight to the remaining element. */
167 t_bindlist *b = (t_bindlist *)s->s_thing;
168 t_bindelem *e, *e2;
169 if ((e = b->b_list)->e_who == x)
171 b->b_list = e->e_next;
172 freebytes(e, sizeof(t_bindelem));
174 else for (e = b->b_list; (e2 = e->e_next); e = e2)
175 if (e2->e_who == x)
177 e->e_next = e2->e_next;
178 freebytes(e2, sizeof(t_bindelem));
179 break;
181 if (!b->b_list->e_next)
183 s->s_thing = b->b_list->e_who;
184 freebytes(b->b_list, sizeof(t_bindelem));
185 pd_free(&b->b_pd);
188 else pd_error(x, "%s: couldn't unbind", s->s_name);
191 void zz(void) {}
193 t_pd *pd_findbyclass(t_symbol *s, t_class *c)
195 t_pd *x = 0;
197 if (!s->s_thing) return (0);
198 if (*s->s_thing == c) return (s->s_thing);
199 if (*s->s_thing == bindlist_class)
201 t_bindlist *b = (t_bindlist *)s->s_thing;
202 #ifdef ROCKBOX
203 t_bindelem *e;
204 #else /* ROCKBOX */
205 t_bindelem *e, *e2;
206 #endif /* ROCKBOX */
207 int warned = 0;
209 for (e = b->b_list; e; e = e->e_next)
210 if (*e->e_who == c)
212 if (x && !warned)
214 zz();
215 post("warning: %s: multiply defined", s->s_name);
216 warned = 1;
218 x = e->e_who;
221 return x;
224 /* stack for maintaining bindings for the #X symbol during nestable loads.
227 typedef struct _gstack
229 t_pd *g_what;
230 t_symbol *g_loadingabstraction;
231 struct _gstack *g_next;
232 } t_gstack;
234 static t_gstack *gstack_head = 0;
235 static t_pd *lastpopped;
236 static t_symbol *pd_loadingabstraction;
238 int pd_setloadingabstraction(t_symbol *sym)
240 t_gstack *foo = gstack_head;
241 for (foo = gstack_head; foo; foo = foo->g_next)
242 if (foo->g_loadingabstraction == sym)
243 return (1);
244 pd_loadingabstraction = sym;
245 return (0);
248 void pd_pushsym(t_pd *x)
250 t_gstack *y = (t_gstack *)t_getbytes(sizeof(*y));
251 y->g_what = s__X.s_thing;
252 y->g_next = gstack_head;
253 y->g_loadingabstraction = pd_loadingabstraction;
254 pd_loadingabstraction = 0;
255 gstack_head = y;
256 s__X.s_thing = x;
259 void pd_popsym(t_pd *x)
261 if (!gstack_head || s__X.s_thing != x) bug("gstack_pop");
262 else
264 t_gstack *headwas = gstack_head;
265 s__X.s_thing = headwas->g_what;
266 gstack_head = headwas->g_next;
267 t_freebytes(headwas, sizeof(*headwas));
268 lastpopped = x;
272 void pd_doloadbang(void)
274 if (lastpopped)
275 pd_vmess(lastpopped, gensym("loadbang"), "");
276 lastpopped = 0;
279 void pd_bang(t_pd *x)
281 (*(*x)->c_bangmethod)(x);
284 void pd_float(t_pd *x, t_float f)
286 (*(*x)->c_floatmethod)(x, f);
289 void pd_pointer(t_pd *x, t_gpointer *gp)
291 (*(*x)->c_pointermethod)(x, gp);
294 void pd_symbol(t_pd *x, t_symbol *s)
296 (*(*x)->c_symbolmethod)(x, s);
299 void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv)
301 #ifdef ROCKBOX
302 (void) s;
303 #endif
304 (*(*x)->c_listmethod)(x, &s_list, argc, argv);
307 void mess_init(void);
308 void obj_init(void);
309 void conf_init(void);
310 void glob_init(void);
312 void pd_init(void)
314 mess_init();
315 obj_init();
316 conf_init();
317 glob_init();