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. */
9 void pd_checkgui(t_pd
*x
, t_symbol
*s
);
14 /* FIXME no out-of-memory testing yet! */
16 t_pd
*pd_new(t_class
*c
)
20 bug ("pd_new: apparently called before setup routine");
21 x
= (t_pd
*)t_getbytes(c
->c_size
);
25 ((t_object
*)x
)->ob_inlet
= 0;
26 ((t_object
*)x
)->ob_outlet
= 0;
34 if (c
->c_freemethod
) (*(t_gotfn
)(c
->c_freemethod
))(x
);
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
)
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
58 static t_class
*bindlist_class
;
60 typedef struct _bindelem
63 struct _bindelem
*e_next
;
66 typedef struct _bindlist
72 static void bindlist_bang(t_bindlist
*x
)
75 for (e
= x
->b_list
; e
; e
= e
->e_next
)
79 static void bindlist_float(t_bindlist
*x
, t_float f
)
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
)
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
)
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
)
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
)
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
)
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
;
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
));
150 e2
->e_who
= s
->s_thing
;
152 s
->s_thing
= &b
->b_pd
;
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
;
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
)
177 e
->e_next
= e2
->e_next
;
178 freebytes(e2
, sizeof(t_bindelem
));
181 if (!b
->b_list
->e_next
)
183 s
->s_thing
= b
->b_list
->e_who
;
184 freebytes(b
->b_list
, sizeof(t_bindelem
));
188 else pd_error(x
, "%s: couldn't unbind", s
->s_name
);
193 t_pd
*pd_findbyclass(t_symbol
*s
, t_class
*c
)
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
;
209 for (e
= b
->b_list
; e
; e
= e
->e_next
)
215 post("warning: %s: multiply defined", s
->s_name
);
224 /* stack for maintaining bindings for the #X symbol during nestable loads.
227 typedef struct _gstack
230 t_symbol
*g_loadingabstraction
;
231 struct _gstack
*g_next
;
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
)
244 pd_loadingabstraction
= sym
;
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;
259 void pd_popsym(t_pd
*x
)
261 if (!gstack_head
|| s__X
.s_thing
!= x
) bug("gstack_pop");
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
));
272 void pd_doloadbang(void)
275 pd_vmess(lastpopped
, gensym("loadbang"), "");
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
)
304 (*(*x
)->c_listmethod
)(x
, &s_list
, argc
, argv
);
307 void mess_init(void);
309 void conf_init(void);
310 void glob_init(void);