diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/x_connective.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/x_connective.c | 2904 |
1 files changed, 2904 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/src/x_connective.c b/apps/plugins/pdbox/PDa/src/x_connective.c new file mode 100644 index 0000000000..d68192ea9a --- /dev/null +++ b/apps/plugins/pdbox/PDa/src/x_connective.c | |||
@@ -0,0 +1,2904 @@ | |||
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. */ | ||
4 | |||
5 | /* connective objects */ | ||
6 | |||
7 | #include "m_pd.h" | ||
8 | |||
9 | #include <string.h> | ||
10 | #include <stdio.h> | ||
11 | extern t_pd *newest; | ||
12 | |||
13 | /* -------------------------- int ------------------------------ */ | ||
14 | static t_class *pdint_class; | ||
15 | |||
16 | typedef struct _pdint | ||
17 | { | ||
18 | t_object x_obj; | ||
19 | t_float x_f; | ||
20 | } t_pdint; | ||
21 | |||
22 | static void *pdint_new(t_floatarg f) | ||
23 | { | ||
24 | t_pdint *x = (t_pdint *)pd_new(pdint_class); | ||
25 | x->x_f = f; | ||
26 | outlet_new(&x->x_obj, &s_float); | ||
27 | floatinlet_new(&x->x_obj, &x->x_f); | ||
28 | return (x); | ||
29 | } | ||
30 | |||
31 | static void pdint_bang(t_pdint *x) | ||
32 | { | ||
33 | outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f)); | ||
34 | } | ||
35 | |||
36 | static void pdint_float(t_pdint *x, t_float f) | ||
37 | { | ||
38 | outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f = f)); | ||
39 | } | ||
40 | |||
41 | void pdint_setup(void) | ||
42 | { | ||
43 | pdint_class = class_new(gensym("int"), (t_newmethod)pdint_new, 0, | ||
44 | sizeof(t_pdint), 0, A_DEFFLOAT, 0); | ||
45 | class_addcreator((t_newmethod)pdint_new, gensym("i"), A_DEFFLOAT, 0); | ||
46 | class_addbang(pdint_class, pdint_bang); | ||
47 | class_addfloat(pdint_class, pdint_float); | ||
48 | } | ||
49 | |||
50 | /* -------------------------- float ------------------------------ */ | ||
51 | static t_class *pdfloat_class; | ||
52 | |||
53 | typedef struct _pdfloat | ||
54 | { | ||
55 | t_object x_obj; | ||
56 | t_float x_f; | ||
57 | } t_pdfloat; | ||
58 | |||
59 | /* "float," "symbol," and "bang" are special because | ||
60 | they're created by short-circuited messages to the "new" | ||
61 | object which are handled specially in pd_typedmess(). */ | ||
62 | |||
63 | static void *pdfloat_new(t_pd *dummy, t_float f) | ||
64 | { | ||
65 | t_pdfloat *x = (t_pdfloat *)pd_new(pdfloat_class); | ||
66 | x->x_f = f; | ||
67 | outlet_new(&x->x_obj, &s_float); | ||
68 | floatinlet_new(&x->x_obj, &x->x_f); | ||
69 | newest = &x->x_obj.ob_pd; | ||
70 | return (x); | ||
71 | } | ||
72 | |||
73 | static void *pdfloat_new2(t_floatarg f) | ||
74 | { | ||
75 | return (pdfloat_new(0, f)); | ||
76 | } | ||
77 | |||
78 | static void pdfloat_bang(t_pdfloat *x) | ||
79 | { | ||
80 | outlet_float(x->x_obj.ob_outlet, x->x_f); | ||
81 | } | ||
82 | |||
83 | static void pdfloat_float(t_pdfloat *x, t_float f) | ||
84 | { | ||
85 | outlet_float(x->x_obj.ob_outlet, x->x_f = f); | ||
86 | } | ||
87 | |||
88 | void pdfloat_setup(void) | ||
89 | { | ||
90 | pdfloat_class = class_new(gensym("float"), (t_newmethod)pdfloat_new, 0, | ||
91 | sizeof(t_pdfloat), 0, A_FLOAT, 0); | ||
92 | class_addcreator((t_newmethod)pdfloat_new2, gensym("f"), A_DEFFLOAT, 0); | ||
93 | class_addbang(pdfloat_class, pdfloat_bang); | ||
94 | class_addfloat(pdfloat_class, (t_method)pdfloat_float); | ||
95 | } | ||
96 | |||
97 | /* -------------------------- symbol ------------------------------ */ | ||
98 | static t_class *pdsymbol_class; | ||
99 | |||
100 | typedef struct _pdsymbol | ||
101 | { | ||
102 | t_object x_obj; | ||
103 | t_symbol *x_s; | ||
104 | } t_pdsymbol; | ||
105 | |||
106 | static void *pdsymbol_new(t_pd *dummy, t_symbol *s) | ||
107 | { | ||
108 | t_pdsymbol *x = (t_pdsymbol *)pd_new(pdsymbol_class); | ||
109 | x->x_s = s; | ||
110 | outlet_new(&x->x_obj, &s_symbol); | ||
111 | symbolinlet_new(&x->x_obj, &x->x_s); | ||
112 | newest = &x->x_obj.ob_pd; | ||
113 | return (x); | ||
114 | } | ||
115 | |||
116 | static void pdsymbol_bang(t_pdsymbol *x) | ||
117 | { | ||
118 | outlet_symbol(x->x_obj.ob_outlet, x->x_s); | ||
119 | } | ||
120 | |||
121 | static void pdsymbol_symbol(t_pdsymbol *x, t_symbol *s) | ||
122 | { | ||
123 | outlet_symbol(x->x_obj.ob_outlet, x->x_s = s); | ||
124 | } | ||
125 | |||
126 | static void pdsymbol_anything(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av) | ||
127 | { | ||
128 | outlet_symbol(x->x_obj.ob_outlet, x->x_s = s); | ||
129 | } | ||
130 | |||
131 | void pdsymbol_setup(void) | ||
132 | { | ||
133 | pdsymbol_class = class_new(gensym("symbol"), (t_newmethod)pdsymbol_new, 0, | ||
134 | sizeof(t_pdsymbol), 0, A_SYMBOL, 0); | ||
135 | class_addbang(pdsymbol_class, pdsymbol_bang); | ||
136 | class_addsymbol(pdsymbol_class, pdsymbol_symbol); | ||
137 | class_addanything(pdsymbol_class, pdsymbol_anything); | ||
138 | } | ||
139 | |||
140 | /* -------------------------- bang ------------------------------ */ | ||
141 | static t_class *bang_class; | ||
142 | |||
143 | typedef struct _bang | ||
144 | { | ||
145 | t_object x_obj; | ||
146 | } t_bang; | ||
147 | |||
148 | static void *bang_new(t_pd *dummy) | ||
149 | { | ||
150 | t_bang *x = (t_bang *)pd_new(bang_class); | ||
151 | outlet_new(&x->x_obj, &s_bang); | ||
152 | newest = &x->x_obj.ob_pd; | ||
153 | return (x); | ||
154 | } | ||
155 | |||
156 | static void *bang_new2(t_bang f) | ||
157 | { | ||
158 | return (bang_new(0)); | ||
159 | } | ||
160 | |||
161 | static void bang_bang(t_bang *x) | ||
162 | { | ||
163 | outlet_bang(x->x_obj.ob_outlet); | ||
164 | } | ||
165 | |||
166 | void bang_setup(void) | ||
167 | { | ||
168 | bang_class = class_new(gensym("bang"), (t_newmethod)bang_new, 0, | ||
169 | sizeof(t_bang), 0, 0); | ||
170 | class_addcreator((t_newmethod)bang_new2, gensym("b"), 0); | ||
171 | class_addbang(bang_class, bang_bang); | ||
172 | class_addfloat(bang_class, bang_bang); | ||
173 | class_addsymbol(bang_class, bang_bang); | ||
174 | class_addlist(bang_class, bang_bang); | ||
175 | class_addanything(bang_class, bang_bang); | ||
176 | } | ||
177 | |||
178 | /* -------------------- send ------------------------------ */ | ||
179 | |||
180 | static t_class *send_class; | ||
181 | |||
182 | typedef struct _send | ||
183 | { | ||
184 | t_object x_obj; | ||
185 | t_symbol *x_sym; | ||
186 | } t_send; | ||
187 | |||
188 | static void send_bang(t_send *x) | ||
189 | { | ||
190 | if (x->x_sym->s_thing) pd_bang(x->x_sym->s_thing); | ||
191 | } | ||
192 | |||
193 | static void send_float(t_send *x, t_float f) | ||
194 | { | ||
195 | if (x->x_sym->s_thing) pd_float(x->x_sym->s_thing, f); | ||
196 | } | ||
197 | |||
198 | static void send_symbol(t_send *x, t_symbol *s) | ||
199 | { | ||
200 | if (x->x_sym->s_thing) pd_symbol(x->x_sym->s_thing, s); | ||
201 | } | ||
202 | |||
203 | static void send_pointer(t_send *x, t_gpointer *gp) | ||
204 | { | ||
205 | if (x->x_sym->s_thing) pd_pointer(x->x_sym->s_thing, gp); | ||
206 | } | ||
207 | |||
208 | static void send_list(t_send *x, t_symbol *s, int argc, t_atom *argv) | ||
209 | { | ||
210 | if (x->x_sym->s_thing) pd_list(x->x_sym->s_thing, s, argc, argv); | ||
211 | } | ||
212 | |||
213 | static void send_anything(t_send *x, t_symbol *s, int argc, t_atom *argv) | ||
214 | { | ||
215 | if (x->x_sym->s_thing) typedmess(x->x_sym->s_thing, s, argc, argv); | ||
216 | } | ||
217 | |||
218 | static void *send_new(t_symbol *s) | ||
219 | { | ||
220 | t_send *x = (t_send *)pd_new(send_class); | ||
221 | x->x_sym = s; | ||
222 | return (x); | ||
223 | } | ||
224 | |||
225 | static void send_setup(void) | ||
226 | { | ||
227 | send_class = class_new(gensym("send"), (t_newmethod)send_new, 0, | ||
228 | sizeof(t_send), 0, A_DEFSYM, 0); | ||
229 | class_addcreator((t_newmethod)send_new, gensym("s"), A_DEFSYM, 0); | ||
230 | class_addbang(send_class, send_bang); | ||
231 | class_addfloat(send_class, send_float); | ||
232 | class_addsymbol(send_class, send_symbol); | ||
233 | class_addpointer(send_class, send_pointer); | ||
234 | class_addlist(send_class, send_list); | ||
235 | class_addanything(send_class, send_anything); | ||
236 | } | ||
237 | /* -------------------- receive ------------------------------ */ | ||
238 | |||
239 | static t_class *receive_class; | ||
240 | |||
241 | typedef struct _receive | ||
242 | { | ||
243 | t_object x_obj; | ||
244 | t_symbol *x_sym; | ||
245 | } t_receive; | ||
246 | |||
247 | static void receive_bang(t_receive *x) | ||
248 | { | ||
249 | outlet_bang(x->x_obj.ob_outlet); | ||
250 | } | ||
251 | |||
252 | static void receive_float(t_receive *x, t_float f) | ||
253 | { | ||
254 | outlet_float(x->x_obj.ob_outlet, f); | ||
255 | } | ||
256 | |||
257 | static void receive_symbol(t_receive *x, t_symbol *s) | ||
258 | { | ||
259 | outlet_symbol(x->x_obj.ob_outlet, s); | ||
260 | } | ||
261 | |||
262 | static void receive_pointer(t_receive *x, t_gpointer *gp) | ||
263 | { | ||
264 | outlet_pointer(x->x_obj.ob_outlet, gp); | ||
265 | } | ||
266 | |||
267 | static void receive_list(t_receive *x, t_symbol *s, int argc, t_atom *argv) | ||
268 | { | ||
269 | outlet_list(x->x_obj.ob_outlet, s, argc, argv); | ||
270 | } | ||
271 | |||
272 | static void receive_anything(t_receive *x, t_symbol *s, int argc, t_atom *argv) | ||
273 | { | ||
274 | outlet_anything(x->x_obj.ob_outlet, s, argc, argv); | ||
275 | } | ||
276 | |||
277 | static void *receive_new(t_symbol *s) | ||
278 | { | ||
279 | t_receive *x = (t_receive *)pd_new(receive_class); | ||
280 | x->x_sym = s; | ||
281 | pd_bind(&x->x_obj.ob_pd, s); | ||
282 | outlet_new(&x->x_obj, 0); | ||
283 | return (x); | ||
284 | } | ||
285 | |||
286 | static void receive_free(t_receive *x) | ||
287 | { | ||
288 | pd_unbind(&x->x_obj.ob_pd, x->x_sym); | ||
289 | } | ||
290 | |||
291 | static void receive_setup(void) | ||
292 | { | ||
293 | receive_class = class_new(gensym("receive"), (t_newmethod)receive_new, | ||
294 | (t_method)receive_free, sizeof(t_receive), CLASS_NOINLET, A_DEFSYM, 0); | ||
295 | class_addcreator((t_newmethod)receive_new, gensym("r"), A_DEFSYM, 0); | ||
296 | class_addbang(receive_class, receive_bang); | ||
297 | class_addfloat(receive_class, (t_method)receive_float); | ||
298 | class_addsymbol(receive_class, receive_symbol); | ||
299 | class_addpointer(receive_class, receive_pointer); | ||
300 | class_addlist(receive_class, receive_list); | ||
301 | class_addanything(receive_class, receive_anything); | ||
302 | } | ||
303 | |||
304 | /* -------------------------- select ------------------------------ */ | ||
305 | |||
306 | static t_class *sel1_class; | ||
307 | |||
308 | typedef struct _sel1 | ||
309 | { | ||
310 | t_object x_obj; | ||
311 | t_atom x_atom; | ||
312 | t_outlet *x_outlet1; | ||
313 | t_outlet *x_outlet2; | ||
314 | } t_sel1; | ||
315 | |||
316 | static void sel1_float(t_sel1 *x, t_float f) | ||
317 | { | ||
318 | if (x->x_atom.a_type == A_FLOAT && f == x->x_atom.a_w.w_float) | ||
319 | outlet_bang(x->x_outlet1); | ||
320 | else outlet_float(x->x_outlet2, f); | ||
321 | } | ||
322 | |||
323 | static void sel1_symbol(t_sel1 *x, t_symbol *s) | ||
324 | { | ||
325 | if (x->x_atom.a_type == A_SYMBOL && s == x->x_atom.a_w.w_symbol) | ||
326 | outlet_bang(x->x_outlet1); | ||
327 | else outlet_symbol(x->x_outlet2, s); | ||
328 | } | ||
329 | |||
330 | static t_class *sel2_class; | ||
331 | |||
332 | typedef struct _selectelement | ||
333 | { | ||
334 | t_word e_w; | ||
335 | t_outlet *e_outlet; | ||
336 | } t_selectelement; | ||
337 | |||
338 | typedef struct _sel2 | ||
339 | { | ||
340 | t_object x_obj; | ||
341 | t_atomtype x_type; | ||
342 | t_int x_nelement; | ||
343 | t_selectelement *x_vec; | ||
344 | t_outlet *x_rejectout; | ||
345 | } t_sel2; | ||
346 | |||
347 | static void sel2_float(t_sel2 *x, t_float f) | ||
348 | { | ||
349 | t_selectelement *e; | ||
350 | int nelement; | ||
351 | if (x->x_type == A_FLOAT) | ||
352 | { | ||
353 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
354 | if (e->e_w.w_float == f) | ||
355 | { | ||
356 | outlet_bang(e->e_outlet); | ||
357 | return; | ||
358 | } | ||
359 | } | ||
360 | outlet_float(x->x_rejectout, f); | ||
361 | } | ||
362 | |||
363 | static void sel2_symbol(t_sel2 *x, t_symbol *s) | ||
364 | { | ||
365 | t_selectelement *e; | ||
366 | int nelement; | ||
367 | if (x->x_type == A_SYMBOL) | ||
368 | { | ||
369 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
370 | if (e->e_w.w_symbol == s) | ||
371 | { | ||
372 | outlet_bang(e->e_outlet); | ||
373 | return; | ||
374 | } | ||
375 | } | ||
376 | outlet_symbol(x->x_rejectout, s); | ||
377 | } | ||
378 | |||
379 | static void sel2_free(t_sel2 *x) | ||
380 | { | ||
381 | freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); | ||
382 | } | ||
383 | |||
384 | static void *select_new(t_symbol *s, int argc, t_atom *argv) | ||
385 | { | ||
386 | t_atom a; | ||
387 | if (argc == 0) | ||
388 | { | ||
389 | argc = 1; | ||
390 | SETFLOAT(&a, 0); | ||
391 | argv = &a; | ||
392 | } | ||
393 | if (argc == 1) | ||
394 | { | ||
395 | t_sel1 *x = (t_sel1 *)pd_new(sel1_class); | ||
396 | x->x_atom = *argv; | ||
397 | x->x_outlet1 = outlet_new(&x->x_obj, &s_bang); | ||
398 | if (argv->a_type == A_FLOAT) | ||
399 | { | ||
400 | floatinlet_new(&x->x_obj, &x->x_atom.a_w.w_float); | ||
401 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
402 | } | ||
403 | else | ||
404 | { | ||
405 | symbolinlet_new(&x->x_obj, &x->x_atom.a_w.w_symbol); | ||
406 | x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol); | ||
407 | } | ||
408 | return (x); | ||
409 | } | ||
410 | else | ||
411 | { | ||
412 | int n; | ||
413 | t_selectelement *e; | ||
414 | t_sel2 *x = (t_sel2 *)pd_new(sel2_class); | ||
415 | x->x_nelement = argc; | ||
416 | x->x_vec = (t_selectelement *)getbytes(argc * sizeof(*x->x_vec)); | ||
417 | x->x_type = argv[0].a_type; | ||
418 | for (n = 0, e = x->x_vec; n < argc; n++, e++) | ||
419 | { | ||
420 | e->e_outlet = outlet_new(&x->x_obj, &s_bang); | ||
421 | if ((x->x_type = argv->a_type) == A_FLOAT) | ||
422 | e->e_w.w_float = atom_getfloatarg(n, argc, argv); | ||
423 | else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv); | ||
424 | } | ||
425 | x->x_rejectout = outlet_new(&x->x_obj, &s_float); | ||
426 | return (x); | ||
427 | } | ||
428 | |||
429 | } | ||
430 | |||
431 | void select_setup(void) | ||
432 | { | ||
433 | sel1_class = class_new(gensym("select"), 0, 0, | ||
434 | sizeof(t_sel1), 0, 0); | ||
435 | class_addfloat(sel1_class, sel1_float); | ||
436 | class_addsymbol(sel1_class, sel1_symbol); | ||
437 | |||
438 | sel2_class = class_new(gensym("select"), 0, (t_method)sel2_free, | ||
439 | sizeof(t_sel2), 0, 0); | ||
440 | class_addfloat(sel2_class, sel2_float); | ||
441 | class_addsymbol(sel2_class, sel2_symbol); | ||
442 | |||
443 | class_addcreator((t_newmethod)select_new, gensym("select"), A_GIMME, 0); | ||
444 | class_addcreator((t_newmethod)select_new, gensym("sel"), A_GIMME, 0); | ||
445 | } | ||
446 | |||
447 | /* -------------------------- route ------------------------------ */ | ||
448 | |||
449 | static t_class *route_class; | ||
450 | |||
451 | typedef struct _routeelement | ||
452 | { | ||
453 | t_word e_w; | ||
454 | t_outlet *e_outlet; | ||
455 | } t_routeelement; | ||
456 | |||
457 | typedef struct _route | ||
458 | { | ||
459 | t_object x_obj; | ||
460 | t_atomtype x_type; | ||
461 | t_int x_nelement; | ||
462 | t_routeelement *x_vec; | ||
463 | t_outlet *x_rejectout; | ||
464 | } t_route; | ||
465 | |||
466 | static void route_anything(t_route *x, t_symbol *sel, int argc, t_atom *argv) | ||
467 | { | ||
468 | t_routeelement *e; | ||
469 | int nelement; | ||
470 | if (x->x_type == A_SYMBOL) | ||
471 | { | ||
472 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
473 | if (e->e_w.w_symbol == sel) | ||
474 | { | ||
475 | if (argc > 0 && argv[0].a_type == A_SYMBOL) | ||
476 | outlet_anything(e->e_outlet, argv[0].a_w.w_symbol, | ||
477 | argc-1, argv+1); | ||
478 | else outlet_list(e->e_outlet, 0, argc, argv); | ||
479 | return; | ||
480 | } | ||
481 | } | ||
482 | outlet_anything(x->x_rejectout, sel, argc, argv); | ||
483 | } | ||
484 | |||
485 | static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv) | ||
486 | { | ||
487 | t_routeelement *e; | ||
488 | int nelement; | ||
489 | if (x->x_type == A_FLOAT) | ||
490 | { | ||
491 | float f; | ||
492 | if (!argc) return; | ||
493 | f = atom_getfloat(argv); | ||
494 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
495 | if (e->e_w.w_float == f) | ||
496 | { | ||
497 | if (argc > 1 && argv[1].a_type == A_SYMBOL) | ||
498 | outlet_anything(e->e_outlet, argv[1].a_w.w_symbol, | ||
499 | argc-2, argv+2); | ||
500 | else outlet_list(e->e_outlet, 0, argc-1, argv+1); | ||
501 | return; | ||
502 | } | ||
503 | } | ||
504 | else /* symbol arguments */ | ||
505 | { | ||
506 | if (argc > 1) /* 2 or more args: treat as "list" */ | ||
507 | { | ||
508 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
509 | { | ||
510 | if (e->e_w.w_symbol == &s_list) | ||
511 | { | ||
512 | if (argc > 0 && argv[0].a_type == A_SYMBOL) | ||
513 | outlet_anything(e->e_outlet, argv[0].a_w.w_symbol, | ||
514 | argc-1, argv+1); | ||
515 | else outlet_list(e->e_outlet, 0, argc, argv); | ||
516 | return; | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | else if (argc == 0) /* no args: treat as "bang" */ | ||
521 | { | ||
522 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
523 | { | ||
524 | if (e->e_w.w_symbol == &s_bang) | ||
525 | { | ||
526 | outlet_bang(e->e_outlet); | ||
527 | return; | ||
528 | } | ||
529 | } | ||
530 | } | ||
531 | else if (argv[0].a_type == A_FLOAT) /* one float arg */ | ||
532 | { | ||
533 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
534 | { | ||
535 | if (e->e_w.w_symbol == &s_float) | ||
536 | { | ||
537 | outlet_float(e->e_outlet, argv[0].a_w.w_float); | ||
538 | return; | ||
539 | } | ||
540 | } | ||
541 | } | ||
542 | else | ||
543 | { | ||
544 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
545 | { | ||
546 | if (e->e_w.w_symbol == &s_symbol) | ||
547 | { | ||
548 | outlet_symbol(e->e_outlet, argv[0].a_w.w_symbol); | ||
549 | return; | ||
550 | } | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | outlet_list(x->x_rejectout, 0, argc, argv); | ||
555 | } | ||
556 | |||
557 | |||
558 | static void route_free(t_route *x) | ||
559 | { | ||
560 | freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); | ||
561 | } | ||
562 | |||
563 | static void *route_new(t_symbol *s, int argc, t_atom *argv) | ||
564 | { | ||
565 | int n; | ||
566 | t_routeelement *e; | ||
567 | t_route *x = (t_route *)pd_new(route_class); | ||
568 | t_atom a; | ||
569 | if (argc == 0) | ||
570 | { | ||
571 | argc = 1; | ||
572 | SETFLOAT(&a, 0); | ||
573 | argv = &a; | ||
574 | } | ||
575 | x->x_type = argv[0].a_type; | ||
576 | x->x_nelement = argc; | ||
577 | x->x_vec = (t_routeelement *)getbytes(argc * sizeof(*x->x_vec)); | ||
578 | for (n = 0, e = x->x_vec; n < argc; n++, e++) | ||
579 | { | ||
580 | e->e_outlet = outlet_new(&x->x_obj, &s_list); | ||
581 | if (x->x_type == A_FLOAT) | ||
582 | e->e_w.w_float = atom_getfloatarg(n, argc, argv); | ||
583 | else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv); | ||
584 | } | ||
585 | x->x_rejectout = outlet_new(&x->x_obj, &s_list); | ||
586 | return (x); | ||
587 | } | ||
588 | |||
589 | void route_setup(void) | ||
590 | { | ||
591 | route_class = class_new(gensym("route"), (t_newmethod)route_new, | ||
592 | (t_method)route_free, sizeof(t_route), 0, A_GIMME, 0); | ||
593 | class_addlist(route_class, route_list); | ||
594 | class_addanything(route_class, route_anything); | ||
595 | } | ||
596 | |||
597 | /* -------------------------- pack ------------------------------ */ | ||
598 | |||
599 | static t_class *pack_class; | ||
600 | |||
601 | typedef struct _pack | ||
602 | { | ||
603 | t_object x_obj; | ||
604 | t_int x_n; /* number of args */ | ||
605 | t_atom *x_vec; /* input values */ | ||
606 | t_int x_nptr; /* number of pointers */ | ||
607 | t_gpointer *x_gpointer; /* the pointers */ | ||
608 | t_atom *x_outvec; /* space for output values */ | ||
609 | } t_pack; | ||
610 | |||
611 | static void *pack_new(t_symbol *s, int argc, t_atom *argv) | ||
612 | { | ||
613 | t_pack *x = (t_pack *)pd_new(pack_class); | ||
614 | t_atom defarg[2], *ap, *vec, *vp; | ||
615 | t_gpointer *gp; | ||
616 | int nptr = 0; | ||
617 | int i; | ||
618 | if (!argc) | ||
619 | { | ||
620 | argv = defarg; | ||
621 | argc = 2; | ||
622 | SETFLOAT(&defarg[0], 0); | ||
623 | SETFLOAT(&defarg[1], 0); | ||
624 | } | ||
625 | |||
626 | x->x_n = argc; | ||
627 | vec = x->x_vec = (t_atom *)getbytes(argc * sizeof(*x->x_vec)); | ||
628 | x->x_outvec = (t_atom *)getbytes(argc * sizeof(*x->x_outvec)); | ||
629 | |||
630 | for (i = argc, ap = argv; i--; ap++) | ||
631 | if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p') | ||
632 | nptr++; | ||
633 | |||
634 | gp = x->x_gpointer = (t_gpointer *)t_getbytes(nptr * sizeof (*gp)); | ||
635 | x->x_nptr = nptr; | ||
636 | |||
637 | for (i = 0, vp = x->x_vec, ap = argv; i < argc; i++, ap++, vp++) | ||
638 | { | ||
639 | if (ap->a_type == A_FLOAT) | ||
640 | { | ||
641 | *vp = *ap; | ||
642 | if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float); | ||
643 | } | ||
644 | else if (ap->a_type == A_SYMBOL) | ||
645 | { | ||
646 | char c = *ap->a_w.w_symbol->s_name; | ||
647 | if (c == 's') | ||
648 | { | ||
649 | SETSYMBOL(vp, &s_symbol); | ||
650 | if (i) symbolinlet_new(&x->x_obj, &vp->a_w.w_symbol); | ||
651 | } | ||
652 | else if (c == 'p') | ||
653 | { | ||
654 | vp->a_type = A_POINTER; | ||
655 | vp->a_w.w_gpointer = gp; | ||
656 | gpointer_init(gp); | ||
657 | if (i) pointerinlet_new(&x->x_obj, gp); | ||
658 | gp++; | ||
659 | } | ||
660 | else | ||
661 | { | ||
662 | if (c != 'f') pd_error(x, "pack: %s: bad type", | ||
663 | ap->a_w.w_symbol->s_name); | ||
664 | SETFLOAT(vp, 0); | ||
665 | if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float); | ||
666 | } | ||
667 | } | ||
668 | } | ||
669 | outlet_new(&x->x_obj, &s_list); | ||
670 | return (x); | ||
671 | } | ||
672 | |||
673 | static void pack_bang(t_pack *x) | ||
674 | { | ||
675 | int i, reentered = 0, size = x->x_n * sizeof (t_atom); | ||
676 | t_gpointer *gp; | ||
677 | t_atom *outvec; | ||
678 | for (i = x->x_nptr, gp = x->x_gpointer; i--; gp++) | ||
679 | if (!gpointer_check(gp, 1)) | ||
680 | { | ||
681 | pd_error(x, "pack: stale pointer"); | ||
682 | return; | ||
683 | } | ||
684 | /* reentrancy protection. The first time through use the pre-allocated | ||
685 | x_outvec; if we're reentered we have to allocate new memory. */ | ||
686 | if (!x->x_outvec) | ||
687 | { | ||
688 | /* LATER figure out how to deal with reentrancy and pointers... */ | ||
689 | if (x->x_nptr) | ||
690 | post("pack_bang: warning: reentry with pointers unprotected"); | ||
691 | outvec = t_getbytes(size); | ||
692 | reentered = 1; | ||
693 | } | ||
694 | else | ||
695 | { | ||
696 | outvec = x->x_outvec; | ||
697 | x->x_outvec = 0; | ||
698 | } | ||
699 | memcpy(outvec, x->x_vec, size); | ||
700 | outlet_list(x->x_obj.ob_outlet, &s_list, x->x_n, outvec); | ||
701 | if (reentered) | ||
702 | t_freebytes(outvec, size); | ||
703 | else x->x_outvec = outvec; | ||
704 | } | ||
705 | |||
706 | static void pack_pointer(t_pack *x, t_gpointer *gp) | ||
707 | { | ||
708 | if (x->x_vec->a_type == A_POINTER) | ||
709 | { | ||
710 | gpointer_unset(x->x_gpointer); | ||
711 | *x->x_gpointer = *gp; | ||
712 | if (gp->gp_stub) gp->gp_stub->gs_refcount++; | ||
713 | pack_bang(x); | ||
714 | } | ||
715 | else pd_error(x, "pack_pointer: wrong type"); | ||
716 | } | ||
717 | |||
718 | static void pack_float(t_pack *x, t_float f) | ||
719 | { | ||
720 | if (x->x_vec->a_type == A_FLOAT) | ||
721 | { | ||
722 | x->x_vec->a_w.w_float = f; | ||
723 | pack_bang(x); | ||
724 | } | ||
725 | else pd_error(x, "pack_float: wrong type"); | ||
726 | } | ||
727 | |||
728 | static void pack_symbol(t_pack *x, t_symbol *s) | ||
729 | { | ||
730 | if (x->x_vec->a_type == A_SYMBOL) | ||
731 | { | ||
732 | x->x_vec->a_w.w_symbol = s; | ||
733 | pack_bang(x); | ||
734 | } | ||
735 | else pd_error(x, "pack_symbol: wrong type"); | ||
736 | } | ||
737 | |||
738 | static void pack_list(t_pack *x, t_symbol *s, int ac, t_atom *av) | ||
739 | { | ||
740 | obj_list(&x->x_obj, 0, ac, av); | ||
741 | } | ||
742 | |||
743 | static void pack_anything(t_pack *x, t_symbol *s, int ac, t_atom *av) | ||
744 | { | ||
745 | t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom)); | ||
746 | int i; | ||
747 | for (i = 0; i < ac; i++) | ||
748 | av2[i + 1] = av[i]; | ||
749 | SETSYMBOL(av2, s); | ||
750 | obj_list(&x->x_obj, 0, ac+1, av2); | ||
751 | freebytes(av2, (ac + 1) * sizeof(t_atom)); | ||
752 | } | ||
753 | |||
754 | static void pack_free(t_pack *x) | ||
755 | { | ||
756 | t_gpointer *gp; | ||
757 | int i; | ||
758 | for (gp = x->x_gpointer, i = x->x_nptr; i--; gp++) | ||
759 | gpointer_unset(gp); | ||
760 | freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); | ||
761 | freebytes(x->x_outvec, x->x_n * sizeof(*x->x_outvec)); | ||
762 | freebytes(x->x_gpointer, x->x_nptr * sizeof(*x->x_gpointer)); | ||
763 | } | ||
764 | |||
765 | static void pack_setup(void) | ||
766 | { | ||
767 | pack_class = class_new(gensym("pack"), (t_newmethod)pack_new, | ||
768 | (t_method)pack_free, sizeof(t_pack), 0, A_GIMME, 0); | ||
769 | class_addbang(pack_class, pack_bang); | ||
770 | class_addpointer(pack_class, pack_pointer); | ||
771 | class_addfloat(pack_class, pack_float); | ||
772 | class_addsymbol(pack_class, pack_symbol); | ||
773 | class_addlist(pack_class, pack_list); | ||
774 | class_addanything(pack_class, pack_anything); | ||
775 | } | ||
776 | |||
777 | /* -------------------------- unpack ------------------------------ */ | ||
778 | |||
779 | static t_class *unpack_class; | ||
780 | |||
781 | typedef struct unpackout | ||
782 | { | ||
783 | t_atomtype u_type; | ||
784 | t_outlet *u_outlet; | ||
785 | } t_unpackout; | ||
786 | |||
787 | typedef struct _unpack | ||
788 | { | ||
789 | t_object x_obj; | ||
790 | t_int x_n; | ||
791 | t_unpackout *x_vec; | ||
792 | } t_unpack; | ||
793 | |||
794 | static void *unpack_new(t_symbol *s, int argc, t_atom *argv) | ||
795 | { | ||
796 | t_unpack *x = (t_unpack *)pd_new(unpack_class); | ||
797 | t_atom defarg[2], *ap; | ||
798 | t_unpackout *u; | ||
799 | int i; | ||
800 | if (!argc) | ||
801 | { | ||
802 | argv = defarg; | ||
803 | argc = 2; | ||
804 | SETFLOAT(&defarg[0], 0); | ||
805 | SETFLOAT(&defarg[1], 0); | ||
806 | } | ||
807 | x->x_n = argc; | ||
808 | x->x_vec = (t_unpackout *)getbytes(argc * sizeof(*x->x_vec)); | ||
809 | for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++) | ||
810 | { | ||
811 | t_atomtype type = ap->a_type; | ||
812 | if (type == A_SYMBOL) | ||
813 | { | ||
814 | char c = *ap->a_w.w_symbol->s_name; | ||
815 | if (c == 's') | ||
816 | { | ||
817 | u->u_type = A_SYMBOL; | ||
818 | u->u_outlet = outlet_new(&x->x_obj, &s_symbol); | ||
819 | } | ||
820 | else if (c == 'p') | ||
821 | { | ||
822 | u->u_type = A_POINTER; | ||
823 | u->u_outlet = outlet_new(&x->x_obj, &s_pointer); | ||
824 | } | ||
825 | else | ||
826 | { | ||
827 | if (c != 'f') pd_error(x, "unpack: %s: bad type", | ||
828 | ap->a_w.w_symbol->s_name); | ||
829 | u->u_type = A_FLOAT; | ||
830 | u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
831 | } | ||
832 | } | ||
833 | else | ||
834 | { | ||
835 | u->u_type = A_FLOAT; | ||
836 | u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
837 | } | ||
838 | } | ||
839 | return (x); | ||
840 | } | ||
841 | |||
842 | static void unpack_list(t_unpack *x, t_symbol *s, int argc, t_atom *argv) | ||
843 | { | ||
844 | t_atom *ap; | ||
845 | t_unpackout *u; | ||
846 | int i; | ||
847 | if (argc > x->x_n) argc = x->x_n; | ||
848 | for (i = argc, u = x->x_vec + i, ap = argv + i; u--, ap--, i--;) | ||
849 | { | ||
850 | t_atomtype type = u->u_type; | ||
851 | if (type != ap->a_type) | ||
852 | pd_error(x, "unpack: type mismatch"); | ||
853 | else if (type == A_FLOAT) | ||
854 | outlet_float(u->u_outlet, ap->a_w.w_float); | ||
855 | else if (type == A_SYMBOL) | ||
856 | outlet_symbol(u->u_outlet, ap->a_w.w_symbol); | ||
857 | else outlet_pointer(u->u_outlet, ap->a_w.w_gpointer); | ||
858 | } | ||
859 | } | ||
860 | |||
861 | static void unpack_anything(t_unpack *x, t_symbol *s, int ac, t_atom *av) | ||
862 | { | ||
863 | t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom)); | ||
864 | int i; | ||
865 | for (i = 0; i < ac; i++) | ||
866 | av2[i + 1] = av[i]; | ||
867 | SETSYMBOL(av2, s); | ||
868 | unpack_list(x, 0, ac+1, av2); | ||
869 | freebytes(av2, (ac + 1) * sizeof(t_atom)); | ||
870 | } | ||
871 | |||
872 | static void unpack_free(t_unpack *x) | ||
873 | { | ||
874 | freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); | ||
875 | } | ||
876 | |||
877 | static void unpack_setup(void) | ||
878 | { | ||
879 | unpack_class = class_new(gensym("unpack"), (t_newmethod)unpack_new, | ||
880 | (t_method)unpack_free, sizeof(t_unpack), 0, A_GIMME, 0); | ||
881 | class_addlist(unpack_class, unpack_list); | ||
882 | class_addanything(unpack_class, unpack_anything); | ||
883 | } | ||
884 | |||
885 | /* -------------------------- trigger ------------------------------ */ | ||
886 | |||
887 | static t_class *trigger_class; | ||
888 | #define TR_BANG 0 | ||
889 | #define TR_FLOAT 1 | ||
890 | #define TR_SYMBOL 2 | ||
891 | #define TR_POINTER 3 | ||
892 | #define TR_LIST 4 | ||
893 | #define TR_ANYTHING 5 | ||
894 | |||
895 | typedef struct triggerout | ||
896 | { | ||
897 | int u_type; /* outlet type from above */ | ||
898 | t_outlet *u_outlet; | ||
899 | } t_triggerout; | ||
900 | |||
901 | typedef struct _trigger | ||
902 | { | ||
903 | t_object x_obj; | ||
904 | t_int x_n; | ||
905 | t_triggerout *x_vec; | ||
906 | } t_trigger; | ||
907 | |||
908 | static void *trigger_new(t_symbol *s, int argc, t_atom *argv) | ||
909 | { | ||
910 | t_trigger *x = (t_trigger *)pd_new(trigger_class); | ||
911 | t_atom defarg[2], *ap; | ||
912 | t_triggerout *u; | ||
913 | int i; | ||
914 | if (!argc) | ||
915 | { | ||
916 | argv = defarg; | ||
917 | argc = 2; | ||
918 | SETSYMBOL(&defarg[0], &s_bang); | ||
919 | SETSYMBOL(&defarg[1], &s_bang); | ||
920 | } | ||
921 | x->x_n = argc; | ||
922 | x->x_vec = (t_triggerout *)getbytes(argc * sizeof(*x->x_vec)); | ||
923 | for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++) | ||
924 | { | ||
925 | t_atomtype thistype = ap->a_type; | ||
926 | char c; | ||
927 | if (thistype == TR_SYMBOL) c = ap->a_w.w_symbol->s_name[0]; | ||
928 | else if (thistype == TR_FLOAT) c = 'f'; | ||
929 | else c = 0; | ||
930 | if (c == 'p') | ||
931 | u->u_type = TR_POINTER, | ||
932 | u->u_outlet = outlet_new(&x->x_obj, &s_pointer); | ||
933 | else if (c == 'f') | ||
934 | u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
935 | else if (c == 'b') | ||
936 | u->u_type = TR_BANG, u->u_outlet = outlet_new(&x->x_obj, &s_bang); | ||
937 | else if (c == 'l') | ||
938 | u->u_type = TR_LIST, u->u_outlet = outlet_new(&x->x_obj, &s_list); | ||
939 | else if (c == 's') | ||
940 | u->u_type = TR_SYMBOL, | ||
941 | u->u_outlet = outlet_new(&x->x_obj, &s_symbol); | ||
942 | else if (c == 'a') | ||
943 | u->u_type = TR_ANYTHING, | ||
944 | u->u_outlet = outlet_new(&x->x_obj, &s_symbol); | ||
945 | else | ||
946 | { | ||
947 | pd_error(x, "trigger: %s: bad type", ap->a_w.w_symbol->s_name); | ||
948 | u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
949 | } | ||
950 | } | ||
951 | return (x); | ||
952 | } | ||
953 | |||
954 | static void trigger_list(t_trigger *x, t_symbol *s, int argc, t_atom *argv) | ||
955 | { | ||
956 | t_triggerout *u; | ||
957 | int i; | ||
958 | t_atom at; | ||
959 | if (!argc) | ||
960 | { | ||
961 | argc = 1; | ||
962 | SETFLOAT(&at, 0); | ||
963 | argv = &at; | ||
964 | } | ||
965 | for (i = x->x_n, u = x->x_vec + i; u--, i--;) | ||
966 | { | ||
967 | if (u->u_type == TR_FLOAT) | ||
968 | outlet_float(u->u_outlet, atom_getfloat(argv)); | ||
969 | else if (u->u_type == TR_BANG) | ||
970 | outlet_bang(u->u_outlet); | ||
971 | else if (u->u_type == TR_SYMBOL) | ||
972 | outlet_symbol(u->u_outlet, atom_getsymbol(argv)); | ||
973 | else if (u->u_type == TR_POINTER) | ||
974 | { | ||
975 | if (argv->a_type != TR_POINTER) | ||
976 | pd_error(x, "unpack: bad pointer"); | ||
977 | else outlet_pointer(u->u_outlet, argv->a_w.w_gpointer); | ||
978 | } | ||
979 | else outlet_list(u->u_outlet, &s_list, argc, argv); | ||
980 | } | ||
981 | } | ||
982 | |||
983 | static void trigger_anything(t_trigger *x, t_symbol *s, int argc, t_atom *argv) | ||
984 | { | ||
985 | t_triggerout *u; | ||
986 | int i; | ||
987 | for (i = x->x_n, u = x->x_vec + i; u--, i--;) | ||
988 | { | ||
989 | if (u->u_type == TR_BANG) | ||
990 | outlet_bang(u->u_outlet); | ||
991 | else if (u->u_type == TR_ANYTHING) | ||
992 | outlet_anything(u->u_outlet, s, argc, argv); | ||
993 | else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'", | ||
994 | s->s_name); | ||
995 | } | ||
996 | } | ||
997 | |||
998 | static void trigger_bang(t_trigger *x) | ||
999 | { | ||
1000 | trigger_list(x, 0, 0, 0); | ||
1001 | } | ||
1002 | |||
1003 | static void trigger_pointer(t_trigger *x, t_gpointer *gp) | ||
1004 | { | ||
1005 | t_atom at; | ||
1006 | SETPOINTER(&at, gp); | ||
1007 | trigger_list(x, 0, 1, &at); | ||
1008 | } | ||
1009 | |||
1010 | static void trigger_float(t_trigger *x, t_float f) | ||
1011 | { | ||
1012 | t_atom at; | ||
1013 | SETFLOAT(&at, f); | ||
1014 | trigger_list(x, 0, 1, &at); | ||
1015 | } | ||
1016 | |||
1017 | static void trigger_symbol(t_trigger *x, t_symbol *s) | ||
1018 | { | ||
1019 | t_atom at; | ||
1020 | SETSYMBOL(&at, s); | ||
1021 | trigger_list(x, 0, 1, &at); | ||
1022 | } | ||
1023 | |||
1024 | static void trigger_free(t_trigger *x) | ||
1025 | { | ||
1026 | freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); | ||
1027 | } | ||
1028 | |||
1029 | static void trigger_setup(void) | ||
1030 | { | ||
1031 | trigger_class = class_new(gensym("trigger"), (t_newmethod)trigger_new, | ||
1032 | (t_method)trigger_free, sizeof(t_trigger), 0, A_GIMME, 0); | ||
1033 | class_addcreator((t_newmethod)trigger_new, gensym("t"), A_GIMME, 0); | ||
1034 | class_addlist(trigger_class, trigger_list); | ||
1035 | class_addbang(trigger_class, trigger_bang); | ||
1036 | class_addpointer(trigger_class, trigger_pointer); | ||
1037 | class_addfloat(trigger_class, (t_method)trigger_float); | ||
1038 | class_addsymbol(trigger_class, trigger_symbol); | ||
1039 | class_addanything(trigger_class, trigger_anything); | ||
1040 | } | ||
1041 | |||
1042 | /* -------------------------- spigot ------------------------------ */ | ||
1043 | static t_class *spigot_class; | ||
1044 | |||
1045 | typedef struct _spigot | ||
1046 | { | ||
1047 | t_object x_obj; | ||
1048 | float x_state; | ||
1049 | } t_spigot; | ||
1050 | |||
1051 | static void *spigot_new(void) | ||
1052 | { | ||
1053 | t_spigot *x = (t_spigot *)pd_new(spigot_class); | ||
1054 | floatinlet_new(&x->x_obj, &x->x_state); | ||
1055 | outlet_new(&x->x_obj, 0); | ||
1056 | x->x_state = 0; | ||
1057 | return (x); | ||
1058 | } | ||
1059 | |||
1060 | static void spigot_bang(t_spigot *x) | ||
1061 | { | ||
1062 | if (x->x_state != 0) outlet_bang(x->x_obj.ob_outlet); | ||
1063 | } | ||
1064 | |||
1065 | static void spigot_pointer(t_spigot *x, t_gpointer *gp) | ||
1066 | { | ||
1067 | if (x->x_state != 0) outlet_pointer(x->x_obj.ob_outlet, gp); | ||
1068 | } | ||
1069 | |||
1070 | static void spigot_float(t_spigot *x, t_float f) | ||
1071 | { | ||
1072 | if (x->x_state != 0) outlet_float(x->x_obj.ob_outlet, f); | ||
1073 | } | ||
1074 | |||
1075 | static void spigot_symbol(t_spigot *x, t_symbol *s) | ||
1076 | { | ||
1077 | if (x->x_state != 0) outlet_symbol(x->x_obj.ob_outlet, s); | ||
1078 | } | ||
1079 | |||
1080 | static void spigot_list(t_spigot *x, t_symbol *s, int argc, t_atom *argv) | ||
1081 | { | ||
1082 | if (x->x_state != 0) outlet_list(x->x_obj.ob_outlet, s, argc, argv); | ||
1083 | } | ||
1084 | |||
1085 | static void spigot_anything(t_spigot *x, t_symbol *s, int argc, t_atom *argv) | ||
1086 | { | ||
1087 | if (x->x_state != 0) outlet_anything(x->x_obj.ob_outlet, s, argc, argv); | ||
1088 | } | ||
1089 | |||
1090 | static void spigot_setup(void) | ||
1091 | { | ||
1092 | spigot_class = class_new(gensym("spigot"), (t_newmethod)spigot_new, 0, | ||
1093 | sizeof(t_spigot), 0, A_DEFSYM, 0); | ||
1094 | class_addbang(spigot_class, spigot_bang); | ||
1095 | class_addpointer(spigot_class, spigot_pointer); | ||
1096 | class_addfloat(spigot_class, spigot_float); | ||
1097 | class_addsymbol(spigot_class, spigot_symbol); | ||
1098 | class_addlist(spigot_class, spigot_list); | ||
1099 | class_addanything(spigot_class, spigot_anything); | ||
1100 | } | ||
1101 | |||
1102 | /* --------------------------- moses ----------------------------- */ | ||
1103 | static t_class *moses_class; | ||
1104 | |||
1105 | typedef struct _moses | ||
1106 | { | ||
1107 | t_object x_ob; | ||
1108 | t_outlet *x_out2; | ||
1109 | float x_y; | ||
1110 | } t_moses; | ||
1111 | |||
1112 | static void *moses_new(t_floatarg f) | ||
1113 | { | ||
1114 | t_moses *x = (t_moses *)pd_new(moses_class); | ||
1115 | floatinlet_new(&x->x_ob, &x->x_y); | ||
1116 | outlet_new(&x->x_ob, &s_float); | ||
1117 | x->x_out2 = outlet_new(&x->x_ob, &s_float); | ||
1118 | x->x_y = f; | ||
1119 | return (x); | ||
1120 | } | ||
1121 | |||
1122 | static void moses_float(t_moses *x, t_float f) | ||
1123 | { | ||
1124 | if (f < x->x_y) outlet_float(x->x_ob.ob_outlet, f); | ||
1125 | else outlet_float(x->x_out2, f); | ||
1126 | } | ||
1127 | |||
1128 | static void moses_setup(void) | ||
1129 | { | ||
1130 | moses_class = class_new(gensym("moses"), (t_newmethod)moses_new, 0, | ||
1131 | sizeof(t_moses), 0, A_DEFFLOAT, 0); | ||
1132 | class_addfloat(moses_class, moses_float); | ||
1133 | } | ||
1134 | |||
1135 | /* ----------------------- until --------------------- */ | ||
1136 | |||
1137 | static t_class *until_class; | ||
1138 | |||
1139 | typedef struct _until | ||
1140 | { | ||
1141 | t_object x_obj; | ||
1142 | int x_run; | ||
1143 | int x_count; | ||
1144 | } t_until; | ||
1145 | |||
1146 | static void *until_new(void) | ||
1147 | { | ||
1148 | t_until *x = (t_until *)pd_new(until_class); | ||
1149 | inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2")); | ||
1150 | outlet_new(&x->x_obj, &s_bang); | ||
1151 | x->x_run = 0; | ||
1152 | return (x); | ||
1153 | } | ||
1154 | |||
1155 | static void until_bang(t_until *x) | ||
1156 | { | ||
1157 | x->x_run = 1; | ||
1158 | x->x_count = -1; | ||
1159 | while (x->x_run && x->x_count) | ||
1160 | x->x_count--, outlet_bang(x->x_obj.ob_outlet); | ||
1161 | } | ||
1162 | |||
1163 | static void until_float(t_until *x, t_float f) | ||
1164 | { | ||
1165 | x->x_run = 1; | ||
1166 | x->x_count = f; | ||
1167 | while (x->x_run && x->x_count) | ||
1168 | x->x_count--, outlet_bang(x->x_obj.ob_outlet); | ||
1169 | } | ||
1170 | |||
1171 | static void until_bang2(t_until *x) | ||
1172 | { | ||
1173 | x->x_run = 0; | ||
1174 | } | ||
1175 | |||
1176 | static void until_setup(void) | ||
1177 | { | ||
1178 | until_class = class_new(gensym("until"), (t_newmethod)until_new, 0, | ||
1179 | sizeof(t_until), 0, 0); | ||
1180 | class_addbang(until_class, until_bang); | ||
1181 | class_addfloat(until_class, until_float); | ||
1182 | class_addmethod(until_class, (t_method)until_bang2, gensym("bang2"), 0); | ||
1183 | } | ||
1184 | |||
1185 | /* ----------------------- makefilename --------------------- */ | ||
1186 | |||
1187 | static t_class *makefilename_class; | ||
1188 | |||
1189 | typedef struct _makefilename | ||
1190 | { | ||
1191 | t_object x_obj; | ||
1192 | t_symbol *x_format; | ||
1193 | } t_makefilename; | ||
1194 | |||
1195 | static void *makefilename_new(t_symbol *s) | ||
1196 | { | ||
1197 | t_makefilename *x = (t_makefilename *)pd_new(makefilename_class); | ||
1198 | if (!s->s_name) s = gensym("file.%d"); | ||
1199 | outlet_new(&x->x_obj, &s_symbol); | ||
1200 | x->x_format = s; | ||
1201 | return (x); | ||
1202 | } | ||
1203 | |||
1204 | static void makefilename_float(t_makefilename *x, t_floatarg f) | ||
1205 | { | ||
1206 | char buf[MAXPDSTRING]; | ||
1207 | sprintf(buf, x->x_format->s_name, (int)f); | ||
1208 | outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); | ||
1209 | } | ||
1210 | |||
1211 | static void makefilename_symbol(t_makefilename *x, t_symbol *s) | ||
1212 | { | ||
1213 | char buf[MAXPDSTRING]; | ||
1214 | sprintf(buf, x->x_format->s_name, s->s_name); | ||
1215 | outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); | ||
1216 | } | ||
1217 | |||
1218 | static void makefilename_setup(void) | ||
1219 | { | ||
1220 | makefilename_class = class_new(gensym("makefilename"), | ||
1221 | (t_newmethod)makefilename_new, 0, | ||
1222 | sizeof(t_makefilename), 0, A_DEFSYM, 0); | ||
1223 | class_addfloat(makefilename_class, makefilename_float); | ||
1224 | class_addsymbol(makefilename_class, makefilename_symbol); | ||
1225 | } | ||
1226 | |||
1227 | /* -------------------------- swap ------------------------------ */ | ||
1228 | static t_class *swap_class; | ||
1229 | |||
1230 | typedef struct _swap | ||
1231 | { | ||
1232 | t_object x_obj; | ||
1233 | t_outlet *x_out2; | ||
1234 | t_float x_f1; | ||
1235 | t_float x_f2; | ||
1236 | } t_swap; | ||
1237 | |||
1238 | static void *swap_new(t_floatarg f) | ||
1239 | { | ||
1240 | t_swap *x = (t_swap *)pd_new(swap_class); | ||
1241 | x->x_f2 = f; | ||
1242 | x->x_f1 = 0; | ||
1243 | outlet_new(&x->x_obj, &s_float); | ||
1244 | x->x_out2 = outlet_new(&x->x_obj, &s_float); | ||
1245 | floatinlet_new(&x->x_obj, &x->x_f2); | ||
1246 | return (x); | ||
1247 | } | ||
1248 | |||
1249 | static void swap_bang(t_swap *x) | ||
1250 | { | ||
1251 | outlet_float(x->x_out2, x->x_f1); | ||
1252 | outlet_float(x->x_obj.ob_outlet, x->x_f2); | ||
1253 | } | ||
1254 | |||
1255 | static void swap_float(t_swap *x, t_float f) | ||
1256 | { | ||
1257 | x->x_f1 = f; | ||
1258 | swap_bang(x); | ||
1259 | } | ||
1260 | |||
1261 | void swap_setup(void) | ||
1262 | { | ||
1263 | swap_class = class_new(gensym("swap"), (t_newmethod)swap_new, 0, | ||
1264 | sizeof(t_swap), 0, A_DEFFLOAT, 0); | ||
1265 | class_addcreator((t_newmethod)swap_new, gensym("fswap"), A_DEFFLOAT, 0); | ||
1266 | class_addbang(swap_class, swap_bang); | ||
1267 | class_addfloat(swap_class, swap_float); | ||
1268 | } | ||
1269 | |||
1270 | /* -------------------------- change ------------------------------ */ | ||
1271 | static t_class *change_class; | ||
1272 | |||
1273 | typedef struct _change | ||
1274 | { | ||
1275 | t_object x_obj; | ||
1276 | t_float x_f; | ||
1277 | } t_change; | ||
1278 | |||
1279 | static void *change_new(t_floatarg f) | ||
1280 | { | ||
1281 | t_change *x = (t_change *)pd_new(change_class); | ||
1282 | x->x_f = f; | ||
1283 | outlet_new(&x->x_obj, &s_float); | ||
1284 | return (x); | ||
1285 | } | ||
1286 | |||
1287 | static void change_bang(t_change *x) | ||
1288 | { | ||
1289 | outlet_float(x->x_obj.ob_outlet, x->x_f); | ||
1290 | } | ||
1291 | |||
1292 | static void change_float(t_change *x, t_float f) | ||
1293 | { | ||
1294 | if (f != x->x_f) | ||
1295 | { | ||
1296 | x->x_f = f; | ||
1297 | outlet_float(x->x_obj.ob_outlet, x->x_f); | ||
1298 | } | ||
1299 | } | ||
1300 | |||
1301 | static void change_set(t_change *x, t_float f) | ||
1302 | { | ||
1303 | x->x_f = f; | ||
1304 | } | ||
1305 | |||
1306 | void change_setup(void) | ||
1307 | { | ||
1308 | change_class = class_new(gensym("change"), (t_newmethod)change_new, 0, | ||
1309 | sizeof(t_change), 0, A_DEFFLOAT, 0); | ||
1310 | class_addbang(change_class, change_bang); | ||
1311 | class_addfloat(change_class, change_float); | ||
1312 | class_addmethod(change_class, (t_method)change_set, gensym("set"), | ||
1313 | A_DEFFLOAT, 0); | ||
1314 | } | ||
1315 | |||
1316 | /* -------------------- value ------------------------------ */ | ||
1317 | |||
1318 | static t_class *value_class, *vcommon_class; | ||
1319 | |||
1320 | typedef struct vcommon | ||
1321 | { | ||
1322 | t_pd c_pd; | ||
1323 | int c_refcount; | ||
1324 | t_float c_f; | ||
1325 | } t_vcommon; | ||
1326 | |||
1327 | typedef struct _value | ||
1328 | { | ||
1329 | t_object x_obj; | ||
1330 | t_symbol *x_sym; | ||
1331 | t_float *x_floatstar; | ||
1332 | } t_value; | ||
1333 | |||
1334 | /* get a pointer to a named floating-point variable. The variable | ||
1335 | belongs to a "vcommon" object, which is created if necessary. */ | ||
1336 | t_float *value_get(t_symbol *s) | ||
1337 | { | ||
1338 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
1339 | if (!c) | ||
1340 | { | ||
1341 | c = (t_vcommon *)pd_new(vcommon_class); | ||
1342 | c->c_f = 0; | ||
1343 | c->c_refcount = 0; | ||
1344 | pd_bind(&c->c_pd, s); | ||
1345 | } | ||
1346 | c->c_refcount++; | ||
1347 | return (&c->c_f); | ||
1348 | } | ||
1349 | |||
1350 | /* release a variable. This only frees the "vcommon" resource when the | ||
1351 | last interested party releases it. */ | ||
1352 | void value_release(t_symbol *s) | ||
1353 | { | ||
1354 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
1355 | if (c) | ||
1356 | { | ||
1357 | if (!--c->c_refcount) | ||
1358 | { | ||
1359 | pd_unbind(&c->c_pd, s); | ||
1360 | pd_free(&c->c_pd); | ||
1361 | } | ||
1362 | } | ||
1363 | else bug("value_release"); | ||
1364 | } | ||
1365 | |||
1366 | /* | ||
1367 | * value_getfloat -- obtain the float value of a "value" object | ||
1368 | * return 0 on success, 1 otherwise | ||
1369 | */ | ||
1370 | int | ||
1371 | value_getfloat(t_symbol *s, t_float *f) | ||
1372 | { | ||
1373 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
1374 | if (!c) | ||
1375 | return (1); | ||
1376 | *f = c->c_f; | ||
1377 | return (0); | ||
1378 | } | ||
1379 | |||
1380 | /* | ||
1381 | * value_setfloat -- set the float value of a "value" object | ||
1382 | * return 0 on success, 1 otherwise | ||
1383 | */ | ||
1384 | int | ||
1385 | value_setfloat(t_symbol *s, t_float f) | ||
1386 | { | ||
1387 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
1388 | if (!c) | ||
1389 | return (1); | ||
1390 | c->c_f = f; | ||
1391 | return (0); | ||
1392 | } | ||
1393 | |||
1394 | static void *value_new(t_symbol *s) | ||
1395 | { | ||
1396 | t_value *x = (t_value *)pd_new(value_class); | ||
1397 | x->x_sym = s; | ||
1398 | x->x_floatstar = value_get(s); | ||
1399 | outlet_new(&x->x_obj, &s_float); | ||
1400 | return (x); | ||
1401 | } | ||
1402 | |||
1403 | static void value_bang(t_value *x) | ||
1404 | { | ||
1405 | outlet_float(x->x_obj.ob_outlet, *x->x_floatstar); | ||
1406 | } | ||
1407 | |||
1408 | static void value_float(t_value *x, t_float f) | ||
1409 | { | ||
1410 | *x->x_floatstar = f; | ||
1411 | } | ||
1412 | |||
1413 | static void value_ff(t_value *x) | ||
1414 | { | ||
1415 | value_release(x->x_sym); | ||
1416 | } | ||
1417 | |||
1418 | static void value_setup(void) | ||
1419 | { | ||
1420 | value_class = class_new(gensym("value"), (t_newmethod)value_new, | ||
1421 | (t_method)value_ff, | ||
1422 | sizeof(t_value), 0, A_DEFSYM, 0); | ||
1423 | class_addcreator((t_newmethod)value_new, gensym("v"), A_DEFSYM, 0); | ||
1424 | class_addbang(value_class, value_bang); | ||
1425 | class_addfloat(value_class, value_float); | ||
1426 | vcommon_class = class_new(gensym("value"), 0, 0, | ||
1427 | sizeof(t_vcommon), CLASS_PD, 0); | ||
1428 | } | ||
1429 | |||
1430 | /* -------------- overall setup routine for this file ----------------- */ | ||
1431 | |||
1432 | void x_connective_setup(void) | ||
1433 | { | ||
1434 | pdint_setup(); | ||
1435 | pdfloat_setup(); | ||
1436 | pdsymbol_setup(); | ||
1437 | bang_setup(); | ||
1438 | send_setup(); | ||
1439 | receive_setup(); | ||
1440 | select_setup(); | ||
1441 | route_setup(); | ||
1442 | pack_setup(); | ||
1443 | unpack_setup(); | ||
1444 | trigger_setup(); | ||
1445 | spigot_setup(); | ||
1446 | moses_setup(); | ||
1447 | until_setup(); | ||
1448 | makefilename_setup(); | ||
1449 | swap_setup(); | ||
1450 | change_setup(); | ||
1451 | value_setup(); | ||
1452 | } | ||
1453 | /* Copyright (c) 1997-1999 Miller Puckette. | ||
1454 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL | ||
1455 | * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ | ||
1456 | |||
1457 | /* connective objects */ | ||
1458 | |||
1459 | #include "m_pd.h" | ||
1460 | |||
1461 | #include <string.h> | ||
1462 | #include <stdio.h> | ||
1463 | extern t_pd *newest; | ||
1464 | |||
1465 | /* -------------------------- int ------------------------------ */ | ||
1466 | static t_class *pdint_class; | ||
1467 | |||
1468 | typedef struct _pdint | ||
1469 | { | ||
1470 | t_object x_obj; | ||
1471 | t_float x_f; | ||
1472 | } t_pdint; | ||
1473 | |||
1474 | static void *pdint_new(t_floatarg f) | ||
1475 | { | ||
1476 | t_pdint *x = (t_pdint *)pd_new(pdint_class); | ||
1477 | x->x_f = f; | ||
1478 | outlet_new(&x->x_obj, &s_float); | ||
1479 | floatinlet_new(&x->x_obj, &x->x_f); | ||
1480 | return (x); | ||
1481 | } | ||
1482 | |||
1483 | static void pdint_bang(t_pdint *x) | ||
1484 | { | ||
1485 | outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f)); | ||
1486 | } | ||
1487 | |||
1488 | static void pdint_float(t_pdint *x, t_float f) | ||
1489 | { | ||
1490 | outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f = f)); | ||
1491 | } | ||
1492 | |||
1493 | void pdint_setup(void) | ||
1494 | { | ||
1495 | pdint_class = class_new(gensym("int"), (t_newmethod)pdint_new, 0, | ||
1496 | sizeof(t_pdint), 0, A_DEFFLOAT, 0); | ||
1497 | class_addcreator((t_newmethod)pdint_new, gensym("i"), A_DEFFLOAT, 0); | ||
1498 | class_addbang(pdint_class, pdint_bang); | ||
1499 | class_addfloat(pdint_class, pdint_float); | ||
1500 | } | ||
1501 | |||
1502 | /* -------------------------- float ------------------------------ */ | ||
1503 | static t_class *pdfloat_class; | ||
1504 | |||
1505 | typedef struct _pdfloat | ||
1506 | { | ||
1507 | t_object x_obj; | ||
1508 | t_float x_f; | ||
1509 | } t_pdfloat; | ||
1510 | |||
1511 | /* "float," "symbol," and "bang" are special because | ||
1512 | they're created by short-circuited messages to the "new" | ||
1513 | object which are handled specially in pd_typedmess(). */ | ||
1514 | |||
1515 | static void *pdfloat_new(t_pd *dummy, t_float f) | ||
1516 | { | ||
1517 | t_pdfloat *x = (t_pdfloat *)pd_new(pdfloat_class); | ||
1518 | x->x_f = f; | ||
1519 | outlet_new(&x->x_obj, &s_float); | ||
1520 | floatinlet_new(&x->x_obj, &x->x_f); | ||
1521 | newest = &x->x_obj.ob_pd; | ||
1522 | return (x); | ||
1523 | } | ||
1524 | |||
1525 | static void *pdfloat_new2(t_floatarg f) | ||
1526 | { | ||
1527 | return (pdfloat_new(0, f)); | ||
1528 | } | ||
1529 | |||
1530 | static void pdfloat_bang(t_pdfloat *x) | ||
1531 | { | ||
1532 | outlet_float(x->x_obj.ob_outlet, x->x_f); | ||
1533 | } | ||
1534 | |||
1535 | static void pdfloat_float(t_pdfloat *x, t_float f) | ||
1536 | { | ||
1537 | outlet_float(x->x_obj.ob_outlet, x->x_f = f); | ||
1538 | } | ||
1539 | |||
1540 | void pdfloat_setup(void) | ||
1541 | { | ||
1542 | pdfloat_class = class_new(gensym("float"), (t_newmethod)pdfloat_new, 0, | ||
1543 | sizeof(t_pdfloat), 0, A_FLOAT, 0); | ||
1544 | class_addcreator((t_newmethod)pdfloat_new2, gensym("f"), A_DEFFLOAT, 0); | ||
1545 | class_addbang(pdfloat_class, pdfloat_bang); | ||
1546 | class_addfloat(pdfloat_class, (t_method)pdfloat_float); | ||
1547 | } | ||
1548 | |||
1549 | /* -------------------------- symbol ------------------------------ */ | ||
1550 | static t_class *pdsymbol_class; | ||
1551 | |||
1552 | typedef struct _pdsymbol | ||
1553 | { | ||
1554 | t_object x_obj; | ||
1555 | t_symbol *x_s; | ||
1556 | } t_pdsymbol; | ||
1557 | |||
1558 | static void *pdsymbol_new(t_pd *dummy, t_symbol *s) | ||
1559 | { | ||
1560 | t_pdsymbol *x = (t_pdsymbol *)pd_new(pdsymbol_class); | ||
1561 | x->x_s = s; | ||
1562 | outlet_new(&x->x_obj, &s_symbol); | ||
1563 | symbolinlet_new(&x->x_obj, &x->x_s); | ||
1564 | newest = &x->x_obj.ob_pd; | ||
1565 | return (x); | ||
1566 | } | ||
1567 | |||
1568 | static void pdsymbol_bang(t_pdsymbol *x) | ||
1569 | { | ||
1570 | outlet_symbol(x->x_obj.ob_outlet, x->x_s); | ||
1571 | } | ||
1572 | |||
1573 | static void pdsymbol_symbol(t_pdsymbol *x, t_symbol *s) | ||
1574 | { | ||
1575 | outlet_symbol(x->x_obj.ob_outlet, x->x_s = s); | ||
1576 | } | ||
1577 | |||
1578 | static void pdsymbol_anything(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av) | ||
1579 | { | ||
1580 | outlet_symbol(x->x_obj.ob_outlet, x->x_s = s); | ||
1581 | } | ||
1582 | |||
1583 | void pdsymbol_setup(void) | ||
1584 | { | ||
1585 | pdsymbol_class = class_new(gensym("symbol"), (t_newmethod)pdsymbol_new, 0, | ||
1586 | sizeof(t_pdsymbol), 0, A_SYMBOL, 0); | ||
1587 | class_addbang(pdsymbol_class, pdsymbol_bang); | ||
1588 | class_addsymbol(pdsymbol_class, pdsymbol_symbol); | ||
1589 | class_addanything(pdsymbol_class, pdsymbol_anything); | ||
1590 | } | ||
1591 | |||
1592 | /* -------------------------- bang ------------------------------ */ | ||
1593 | static t_class *bang_class; | ||
1594 | |||
1595 | typedef struct _bang | ||
1596 | { | ||
1597 | t_object x_obj; | ||
1598 | } t_bang; | ||
1599 | |||
1600 | static void *bang_new(t_pd *dummy) | ||
1601 | { | ||
1602 | t_bang *x = (t_bang *)pd_new(bang_class); | ||
1603 | outlet_new(&x->x_obj, &s_bang); | ||
1604 | newest = &x->x_obj.ob_pd; | ||
1605 | return (x); | ||
1606 | } | ||
1607 | |||
1608 | static void *bang_new2(t_bang f) | ||
1609 | { | ||
1610 | return (bang_new(0)); | ||
1611 | } | ||
1612 | |||
1613 | static void bang_bang(t_bang *x) | ||
1614 | { | ||
1615 | outlet_bang(x->x_obj.ob_outlet); | ||
1616 | } | ||
1617 | |||
1618 | void bang_setup(void) | ||
1619 | { | ||
1620 | bang_class = class_new(gensym("bang"), (t_newmethod)bang_new, 0, | ||
1621 | sizeof(t_bang), 0, 0); | ||
1622 | class_addcreator((t_newmethod)bang_new2, gensym("b"), 0); | ||
1623 | class_addbang(bang_class, bang_bang); | ||
1624 | class_addfloat(bang_class, bang_bang); | ||
1625 | class_addsymbol(bang_class, bang_bang); | ||
1626 | class_addlist(bang_class, bang_bang); | ||
1627 | class_addanything(bang_class, bang_bang); | ||
1628 | } | ||
1629 | |||
1630 | /* -------------------- send ------------------------------ */ | ||
1631 | |||
1632 | static t_class *send_class; | ||
1633 | |||
1634 | typedef struct _send | ||
1635 | { | ||
1636 | t_object x_obj; | ||
1637 | t_symbol *x_sym; | ||
1638 | } t_send; | ||
1639 | |||
1640 | static void send_bang(t_send *x) | ||
1641 | { | ||
1642 | if (x->x_sym->s_thing) pd_bang(x->x_sym->s_thing); | ||
1643 | } | ||
1644 | |||
1645 | static void send_float(t_send *x, t_float f) | ||
1646 | { | ||
1647 | if (x->x_sym->s_thing) pd_float(x->x_sym->s_thing, f); | ||
1648 | } | ||
1649 | |||
1650 | static void send_symbol(t_send *x, t_symbol *s) | ||
1651 | { | ||
1652 | if (x->x_sym->s_thing) pd_symbol(x->x_sym->s_thing, s); | ||
1653 | } | ||
1654 | |||
1655 | static void send_pointer(t_send *x, t_gpointer *gp) | ||
1656 | { | ||
1657 | if (x->x_sym->s_thing) pd_pointer(x->x_sym->s_thing, gp); | ||
1658 | } | ||
1659 | |||
1660 | static void send_list(t_send *x, t_symbol *s, int argc, t_atom *argv) | ||
1661 | { | ||
1662 | if (x->x_sym->s_thing) pd_list(x->x_sym->s_thing, s, argc, argv); | ||
1663 | } | ||
1664 | |||
1665 | static void send_anything(t_send *x, t_symbol *s, int argc, t_atom *argv) | ||
1666 | { | ||
1667 | if (x->x_sym->s_thing) typedmess(x->x_sym->s_thing, s, argc, argv); | ||
1668 | } | ||
1669 | |||
1670 | static void *send_new(t_symbol *s) | ||
1671 | { | ||
1672 | t_send *x = (t_send *)pd_new(send_class); | ||
1673 | x->x_sym = s; | ||
1674 | return (x); | ||
1675 | } | ||
1676 | |||
1677 | static void send_setup(void) | ||
1678 | { | ||
1679 | send_class = class_new(gensym("send"), (t_newmethod)send_new, 0, | ||
1680 | sizeof(t_send), 0, A_DEFSYM, 0); | ||
1681 | class_addcreator((t_newmethod)send_new, gensym("s"), A_DEFSYM, 0); | ||
1682 | class_addbang(send_class, send_bang); | ||
1683 | class_addfloat(send_class, send_float); | ||
1684 | class_addsymbol(send_class, send_symbol); | ||
1685 | class_addpointer(send_class, send_pointer); | ||
1686 | class_addlist(send_class, send_list); | ||
1687 | class_addanything(send_class, send_anything); | ||
1688 | } | ||
1689 | /* -------------------- receive ------------------------------ */ | ||
1690 | |||
1691 | static t_class *receive_class; | ||
1692 | |||
1693 | typedef struct _receive | ||
1694 | { | ||
1695 | t_object x_obj; | ||
1696 | t_symbol *x_sym; | ||
1697 | } t_receive; | ||
1698 | |||
1699 | static void receive_bang(t_receive *x) | ||
1700 | { | ||
1701 | outlet_bang(x->x_obj.ob_outlet); | ||
1702 | } | ||
1703 | |||
1704 | static void receive_float(t_receive *x, t_float f) | ||
1705 | { | ||
1706 | outlet_float(x->x_obj.ob_outlet, f); | ||
1707 | } | ||
1708 | |||
1709 | static void receive_symbol(t_receive *x, t_symbol *s) | ||
1710 | { | ||
1711 | outlet_symbol(x->x_obj.ob_outlet, s); | ||
1712 | } | ||
1713 | |||
1714 | static void receive_pointer(t_receive *x, t_gpointer *gp) | ||
1715 | { | ||
1716 | outlet_pointer(x->x_obj.ob_outlet, gp); | ||
1717 | } | ||
1718 | |||
1719 | static void receive_list(t_receive *x, t_symbol *s, int argc, t_atom *argv) | ||
1720 | { | ||
1721 | outlet_list(x->x_obj.ob_outlet, s, argc, argv); | ||
1722 | } | ||
1723 | |||
1724 | static void receive_anything(t_receive *x, t_symbol *s, int argc, t_atom *argv) | ||
1725 | { | ||
1726 | outlet_anything(x->x_obj.ob_outlet, s, argc, argv); | ||
1727 | } | ||
1728 | |||
1729 | static void *receive_new(t_symbol *s) | ||
1730 | { | ||
1731 | t_receive *x = (t_receive *)pd_new(receive_class); | ||
1732 | x->x_sym = s; | ||
1733 | pd_bind(&x->x_obj.ob_pd, s); | ||
1734 | outlet_new(&x->x_obj, 0); | ||
1735 | return (x); | ||
1736 | } | ||
1737 | |||
1738 | static void receive_free(t_receive *x) | ||
1739 | { | ||
1740 | pd_unbind(&x->x_obj.ob_pd, x->x_sym); | ||
1741 | } | ||
1742 | |||
1743 | static void receive_setup(void) | ||
1744 | { | ||
1745 | receive_class = class_new(gensym("receive"), (t_newmethod)receive_new, | ||
1746 | (t_method)receive_free, sizeof(t_receive), CLASS_NOINLET, A_DEFSYM, 0); | ||
1747 | class_addcreator((t_newmethod)receive_new, gensym("r"), A_DEFSYM, 0); | ||
1748 | class_addbang(receive_class, receive_bang); | ||
1749 | class_addfloat(receive_class, (t_method)receive_float); | ||
1750 | class_addsymbol(receive_class, receive_symbol); | ||
1751 | class_addpointer(receive_class, receive_pointer); | ||
1752 | class_addlist(receive_class, receive_list); | ||
1753 | class_addanything(receive_class, receive_anything); | ||
1754 | } | ||
1755 | |||
1756 | /* -------------------------- select ------------------------------ */ | ||
1757 | |||
1758 | static t_class *sel1_class; | ||
1759 | |||
1760 | typedef struct _sel1 | ||
1761 | { | ||
1762 | t_object x_obj; | ||
1763 | t_atom x_atom; | ||
1764 | t_outlet *x_outlet1; | ||
1765 | t_outlet *x_outlet2; | ||
1766 | } t_sel1; | ||
1767 | |||
1768 | static void sel1_float(t_sel1 *x, t_float f) | ||
1769 | { | ||
1770 | if (x->x_atom.a_type == A_FLOAT && f == x->x_atom.a_w.w_float) | ||
1771 | outlet_bang(x->x_outlet1); | ||
1772 | else outlet_float(x->x_outlet2, f); | ||
1773 | } | ||
1774 | |||
1775 | static void sel1_symbol(t_sel1 *x, t_symbol *s) | ||
1776 | { | ||
1777 | if (x->x_atom.a_type == A_SYMBOL && s == x->x_atom.a_w.w_symbol) | ||
1778 | outlet_bang(x->x_outlet1); | ||
1779 | else outlet_symbol(x->x_outlet2, s); | ||
1780 | } | ||
1781 | |||
1782 | static t_class *sel2_class; | ||
1783 | |||
1784 | typedef struct _selectelement | ||
1785 | { | ||
1786 | t_word e_w; | ||
1787 | t_outlet *e_outlet; | ||
1788 | } t_selectelement; | ||
1789 | |||
1790 | typedef struct _sel2 | ||
1791 | { | ||
1792 | t_object x_obj; | ||
1793 | t_atomtype x_type; | ||
1794 | t_int x_nelement; | ||
1795 | t_selectelement *x_vec; | ||
1796 | t_outlet *x_rejectout; | ||
1797 | } t_sel2; | ||
1798 | |||
1799 | static void sel2_float(t_sel2 *x, t_float f) | ||
1800 | { | ||
1801 | t_selectelement *e; | ||
1802 | int nelement; | ||
1803 | if (x->x_type == A_FLOAT) | ||
1804 | { | ||
1805 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1806 | if (e->e_w.w_float == f) | ||
1807 | { | ||
1808 | outlet_bang(e->e_outlet); | ||
1809 | return; | ||
1810 | } | ||
1811 | } | ||
1812 | outlet_float(x->x_rejectout, f); | ||
1813 | } | ||
1814 | |||
1815 | static void sel2_symbol(t_sel2 *x, t_symbol *s) | ||
1816 | { | ||
1817 | t_selectelement *e; | ||
1818 | int nelement; | ||
1819 | if (x->x_type == A_SYMBOL) | ||
1820 | { | ||
1821 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1822 | if (e->e_w.w_symbol == s) | ||
1823 | { | ||
1824 | outlet_bang(e->e_outlet); | ||
1825 | return; | ||
1826 | } | ||
1827 | } | ||
1828 | outlet_symbol(x->x_rejectout, s); | ||
1829 | } | ||
1830 | |||
1831 | static void sel2_free(t_sel2 *x) | ||
1832 | { | ||
1833 | freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); | ||
1834 | } | ||
1835 | |||
1836 | static void *select_new(t_symbol *s, int argc, t_atom *argv) | ||
1837 | { | ||
1838 | t_atom a; | ||
1839 | if (argc == 0) | ||
1840 | { | ||
1841 | argc = 1; | ||
1842 | SETFLOAT(&a, 0); | ||
1843 | argv = &a; | ||
1844 | } | ||
1845 | if (argc == 1) | ||
1846 | { | ||
1847 | t_sel1 *x = (t_sel1 *)pd_new(sel1_class); | ||
1848 | x->x_atom = *argv; | ||
1849 | x->x_outlet1 = outlet_new(&x->x_obj, &s_bang); | ||
1850 | if (argv->a_type == A_FLOAT) | ||
1851 | { | ||
1852 | floatinlet_new(&x->x_obj, &x->x_atom.a_w.w_float); | ||
1853 | x->x_outlet2 = outlet_new(&x->x_obj, &s_float); | ||
1854 | } | ||
1855 | else | ||
1856 | { | ||
1857 | symbolinlet_new(&x->x_obj, &x->x_atom.a_w.w_symbol); | ||
1858 | x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol); | ||
1859 | } | ||
1860 | return (x); | ||
1861 | } | ||
1862 | else | ||
1863 | { | ||
1864 | int n; | ||
1865 | t_selectelement *e; | ||
1866 | t_sel2 *x = (t_sel2 *)pd_new(sel2_class); | ||
1867 | x->x_nelement = argc; | ||
1868 | x->x_vec = (t_selectelement *)getbytes(argc * sizeof(*x->x_vec)); | ||
1869 | x->x_type = argv[0].a_type; | ||
1870 | for (n = 0, e = x->x_vec; n < argc; n++, e++) | ||
1871 | { | ||
1872 | e->e_outlet = outlet_new(&x->x_obj, &s_bang); | ||
1873 | if ((x->x_type = argv->a_type) == A_FLOAT) | ||
1874 | e->e_w.w_float = atom_getfloatarg(n, argc, argv); | ||
1875 | else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv); | ||
1876 | } | ||
1877 | x->x_rejectout = outlet_new(&x->x_obj, &s_float); | ||
1878 | return (x); | ||
1879 | } | ||
1880 | |||
1881 | } | ||
1882 | |||
1883 | void select_setup(void) | ||
1884 | { | ||
1885 | sel1_class = class_new(gensym("select"), 0, 0, | ||
1886 | sizeof(t_sel1), 0, 0); | ||
1887 | class_addfloat(sel1_class, sel1_float); | ||
1888 | class_addsymbol(sel1_class, sel1_symbol); | ||
1889 | |||
1890 | sel2_class = class_new(gensym("select"), 0, (t_method)sel2_free, | ||
1891 | sizeof(t_sel2), 0, 0); | ||
1892 | class_addfloat(sel2_class, sel2_float); | ||
1893 | class_addsymbol(sel2_class, sel2_symbol); | ||
1894 | |||
1895 | class_addcreator((t_newmethod)select_new, gensym("select"), A_GIMME, 0); | ||
1896 | class_addcreator((t_newmethod)select_new, gensym("sel"), A_GIMME, 0); | ||
1897 | } | ||
1898 | |||
1899 | /* -------------------------- route ------------------------------ */ | ||
1900 | |||
1901 | static t_class *route_class; | ||
1902 | |||
1903 | typedef struct _routeelement | ||
1904 | { | ||
1905 | t_word e_w; | ||
1906 | t_outlet *e_outlet; | ||
1907 | } t_routeelement; | ||
1908 | |||
1909 | typedef struct _route | ||
1910 | { | ||
1911 | t_object x_obj; | ||
1912 | t_atomtype x_type; | ||
1913 | t_int x_nelement; | ||
1914 | t_routeelement *x_vec; | ||
1915 | t_outlet *x_rejectout; | ||
1916 | } t_route; | ||
1917 | |||
1918 | static void route_anything(t_route *x, t_symbol *sel, int argc, t_atom *argv) | ||
1919 | { | ||
1920 | t_routeelement *e; | ||
1921 | int nelement; | ||
1922 | if (x->x_type == A_SYMBOL) | ||
1923 | { | ||
1924 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1925 | if (e->e_w.w_symbol == sel) | ||
1926 | { | ||
1927 | if (argc > 0 && argv[0].a_type == A_SYMBOL) | ||
1928 | outlet_anything(e->e_outlet, argv[0].a_w.w_symbol, | ||
1929 | argc-1, argv+1); | ||
1930 | else outlet_list(e->e_outlet, 0, argc, argv); | ||
1931 | return; | ||
1932 | } | ||
1933 | } | ||
1934 | outlet_anything(x->x_rejectout, sel, argc, argv); | ||
1935 | } | ||
1936 | |||
1937 | static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv) | ||
1938 | { | ||
1939 | t_routeelement *e; | ||
1940 | int nelement; | ||
1941 | if (x->x_type == A_FLOAT) | ||
1942 | { | ||
1943 | float f; | ||
1944 | if (!argc) return; | ||
1945 | f = atom_getfloat(argv); | ||
1946 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1947 | if (e->e_w.w_float == f) | ||
1948 | { | ||
1949 | if (argc > 1 && argv[1].a_type == A_SYMBOL) | ||
1950 | outlet_anything(e->e_outlet, argv[1].a_w.w_symbol, | ||
1951 | argc-2, argv+2); | ||
1952 | else outlet_list(e->e_outlet, 0, argc-1, argv+1); | ||
1953 | return; | ||
1954 | } | ||
1955 | } | ||
1956 | else /* symbol arguments */ | ||
1957 | { | ||
1958 | if (argc > 1) /* 2 or more args: treat as "list" */ | ||
1959 | { | ||
1960 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1961 | { | ||
1962 | if (e->e_w.w_symbol == &s_list) | ||
1963 | { | ||
1964 | if (argc > 0 && argv[0].a_type == A_SYMBOL) | ||
1965 | outlet_anything(e->e_outlet, argv[0].a_w.w_symbol, | ||
1966 | argc-1, argv+1); | ||
1967 | else outlet_list(e->e_outlet, 0, argc, argv); | ||
1968 | return; | ||
1969 | } | ||
1970 | } | ||
1971 | } | ||
1972 | else if (argc == 0) /* no args: treat as "bang" */ | ||
1973 | { | ||
1974 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1975 | { | ||
1976 | if (e->e_w.w_symbol == &s_bang) | ||
1977 | { | ||
1978 | outlet_bang(e->e_outlet); | ||
1979 | return; | ||
1980 | } | ||
1981 | } | ||
1982 | } | ||
1983 | else if (argv[0].a_type == A_FLOAT) /* one float arg */ | ||
1984 | { | ||
1985 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1986 | { | ||
1987 | if (e->e_w.w_symbol == &s_float) | ||
1988 | { | ||
1989 | outlet_float(e->e_outlet, argv[0].a_w.w_float); | ||
1990 | return; | ||
1991 | } | ||
1992 | } | ||
1993 | } | ||
1994 | else | ||
1995 | { | ||
1996 | for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++) | ||
1997 | { | ||
1998 | if (e->e_w.w_symbol == &s_symbol) | ||
1999 | { | ||
2000 | outlet_symbol(e->e_outlet, argv[0].a_w.w_symbol); | ||
2001 | return; | ||
2002 | } | ||
2003 | } | ||
2004 | } | ||
2005 | } | ||
2006 | outlet_list(x->x_rejectout, 0, argc, argv); | ||
2007 | } | ||
2008 | |||
2009 | |||
2010 | static void route_free(t_route *x) | ||
2011 | { | ||
2012 | freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec)); | ||
2013 | } | ||
2014 | |||
2015 | static void *route_new(t_symbol *s, int argc, t_atom *argv) | ||
2016 | { | ||
2017 | int n; | ||
2018 | t_routeelement *e; | ||
2019 | t_route *x = (t_route *)pd_new(route_class); | ||
2020 | t_atom a; | ||
2021 | if (argc == 0) | ||
2022 | { | ||
2023 | argc = 1; | ||
2024 | SETFLOAT(&a, 0); | ||
2025 | argv = &a; | ||
2026 | } | ||
2027 | x->x_type = argv[0].a_type; | ||
2028 | x->x_nelement = argc; | ||
2029 | x->x_vec = (t_routeelement *)getbytes(argc * sizeof(*x->x_vec)); | ||
2030 | for (n = 0, e = x->x_vec; n < argc; n++, e++) | ||
2031 | { | ||
2032 | e->e_outlet = outlet_new(&x->x_obj, &s_list); | ||
2033 | if (x->x_type == A_FLOAT) | ||
2034 | e->e_w.w_float = atom_getfloatarg(n, argc, argv); | ||
2035 | else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv); | ||
2036 | } | ||
2037 | x->x_rejectout = outlet_new(&x->x_obj, &s_list); | ||
2038 | return (x); | ||
2039 | } | ||
2040 | |||
2041 | void route_setup(void) | ||
2042 | { | ||
2043 | route_class = class_new(gensym("route"), (t_newmethod)route_new, | ||
2044 | (t_method)route_free, sizeof(t_route), 0, A_GIMME, 0); | ||
2045 | class_addlist(route_class, route_list); | ||
2046 | class_addanything(route_class, route_anything); | ||
2047 | } | ||
2048 | |||
2049 | /* -------------------------- pack ------------------------------ */ | ||
2050 | |||
2051 | static t_class *pack_class; | ||
2052 | |||
2053 | typedef struct _pack | ||
2054 | { | ||
2055 | t_object x_obj; | ||
2056 | t_int x_n; /* number of args */ | ||
2057 | t_atom *x_vec; /* input values */ | ||
2058 | t_int x_nptr; /* number of pointers */ | ||
2059 | t_gpointer *x_gpointer; /* the pointers */ | ||
2060 | t_atom *x_outvec; /* space for output values */ | ||
2061 | } t_pack; | ||
2062 | |||
2063 | static void *pack_new(t_symbol *s, int argc, t_atom *argv) | ||
2064 | { | ||
2065 | t_pack *x = (t_pack *)pd_new(pack_class); | ||
2066 | t_atom defarg[2], *ap, *vec, *vp; | ||
2067 | t_gpointer *gp; | ||
2068 | int nptr = 0; | ||
2069 | int i; | ||
2070 | if (!argc) | ||
2071 | { | ||
2072 | argv = defarg; | ||
2073 | argc = 2; | ||
2074 | SETFLOAT(&defarg[0], 0); | ||
2075 | SETFLOAT(&defarg[1], 0); | ||
2076 | } | ||
2077 | |||
2078 | x->x_n = argc; | ||
2079 | vec = x->x_vec = (t_atom *)getbytes(argc * sizeof(*x->x_vec)); | ||
2080 | x->x_outvec = (t_atom *)getbytes(argc * sizeof(*x->x_outvec)); | ||
2081 | |||
2082 | for (i = argc, ap = argv; i--; ap++) | ||
2083 | if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p') | ||
2084 | nptr++; | ||
2085 | |||
2086 | gp = x->x_gpointer = (t_gpointer *)t_getbytes(nptr * sizeof (*gp)); | ||
2087 | x->x_nptr = nptr; | ||
2088 | |||
2089 | for (i = 0, vp = x->x_vec, ap = argv; i < argc; i++, ap++, vp++) | ||
2090 | { | ||
2091 | if (ap->a_type == A_FLOAT) | ||
2092 | { | ||
2093 | *vp = *ap; | ||
2094 | if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float); | ||
2095 | } | ||
2096 | else if (ap->a_type == A_SYMBOL) | ||
2097 | { | ||
2098 | char c = *ap->a_w.w_symbol->s_name; | ||
2099 | if (c == 's') | ||
2100 | { | ||
2101 | SETSYMBOL(vp, &s_symbol); | ||
2102 | if (i) symbolinlet_new(&x->x_obj, &vp->a_w.w_symbol); | ||
2103 | } | ||
2104 | else if (c == 'p') | ||
2105 | { | ||
2106 | vp->a_type = A_POINTER; | ||
2107 | vp->a_w.w_gpointer = gp; | ||
2108 | gpointer_init(gp); | ||
2109 | if (i) pointerinlet_new(&x->x_obj, gp); | ||
2110 | gp++; | ||
2111 | } | ||
2112 | else | ||
2113 | { | ||
2114 | if (c != 'f') pd_error(x, "pack: %s: bad type", | ||
2115 | ap->a_w.w_symbol->s_name); | ||
2116 | SETFLOAT(vp, 0); | ||
2117 | if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float); | ||
2118 | } | ||
2119 | } | ||
2120 | } | ||
2121 | outlet_new(&x->x_obj, &s_list); | ||
2122 | return (x); | ||
2123 | } | ||
2124 | |||
2125 | static void pack_bang(t_pack *x) | ||
2126 | { | ||
2127 | int i, reentered = 0, size = x->x_n * sizeof (t_atom); | ||
2128 | t_gpointer *gp; | ||
2129 | t_atom *outvec; | ||
2130 | for (i = x->x_nptr, gp = x->x_gpointer; i--; gp++) | ||
2131 | if (!gpointer_check(gp, 1)) | ||
2132 | { | ||
2133 | pd_error(x, "pack: stale pointer"); | ||
2134 | return; | ||
2135 | } | ||
2136 | /* reentrancy protection. The first time through use the pre-allocated | ||
2137 | x_outvec; if we're reentered we have to allocate new memory. */ | ||
2138 | if (!x->x_outvec) | ||
2139 | { | ||
2140 | /* LATER figure out how to deal with reentrancy and pointers... */ | ||
2141 | if (x->x_nptr) | ||
2142 | post("pack_bang: warning: reentry with pointers unprotected"); | ||
2143 | outvec = t_getbytes(size); | ||
2144 | reentered = 1; | ||
2145 | } | ||
2146 | else | ||
2147 | { | ||
2148 | outvec = x->x_outvec; | ||
2149 | x->x_outvec = 0; | ||
2150 | } | ||
2151 | memcpy(outvec, x->x_vec, size); | ||
2152 | outlet_list(x->x_obj.ob_outlet, &s_list, x->x_n, outvec); | ||
2153 | if (reentered) | ||
2154 | t_freebytes(outvec, size); | ||
2155 | else x->x_outvec = outvec; | ||
2156 | } | ||
2157 | |||
2158 | static void pack_pointer(t_pack *x, t_gpointer *gp) | ||
2159 | { | ||
2160 | if (x->x_vec->a_type == A_POINTER) | ||
2161 | { | ||
2162 | gpointer_unset(x->x_gpointer); | ||
2163 | *x->x_gpointer = *gp; | ||
2164 | if (gp->gp_stub) gp->gp_stub->gs_refcount++; | ||
2165 | pack_bang(x); | ||
2166 | } | ||
2167 | else pd_error(x, "pack_pointer: wrong type"); | ||
2168 | } | ||
2169 | |||
2170 | static void pack_float(t_pack *x, t_float f) | ||
2171 | { | ||
2172 | if (x->x_vec->a_type == A_FLOAT) | ||
2173 | { | ||
2174 | x->x_vec->a_w.w_float = f; | ||
2175 | pack_bang(x); | ||
2176 | } | ||
2177 | else pd_error(x, "pack_float: wrong type"); | ||
2178 | } | ||
2179 | |||
2180 | static void pack_symbol(t_pack *x, t_symbol *s) | ||
2181 | { | ||
2182 | if (x->x_vec->a_type == A_SYMBOL) | ||
2183 | { | ||
2184 | x->x_vec->a_w.w_symbol = s; | ||
2185 | pack_bang(x); | ||
2186 | } | ||
2187 | else pd_error(x, "pack_symbol: wrong type"); | ||
2188 | } | ||
2189 | |||
2190 | static void pack_list(t_pack *x, t_symbol *s, int ac, t_atom *av) | ||
2191 | { | ||
2192 | obj_list(&x->x_obj, 0, ac, av); | ||
2193 | } | ||
2194 | |||
2195 | static void pack_anything(t_pack *x, t_symbol *s, int ac, t_atom *av) | ||
2196 | { | ||
2197 | t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom)); | ||
2198 | int i; | ||
2199 | for (i = 0; i < ac; i++) | ||
2200 | av2[i + 1] = av[i]; | ||
2201 | SETSYMBOL(av2, s); | ||
2202 | obj_list(&x->x_obj, 0, ac+1, av2); | ||
2203 | freebytes(av2, (ac + 1) * sizeof(t_atom)); | ||
2204 | } | ||
2205 | |||
2206 | static void pack_free(t_pack *x) | ||
2207 | { | ||
2208 | t_gpointer *gp; | ||
2209 | int i; | ||
2210 | for (gp = x->x_gpointer, i = x->x_nptr; i--; gp++) | ||
2211 | gpointer_unset(gp); | ||
2212 | freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); | ||
2213 | freebytes(x->x_outvec, x->x_n * sizeof(*x->x_outvec)); | ||
2214 | freebytes(x->x_gpointer, x->x_nptr * sizeof(*x->x_gpointer)); | ||
2215 | } | ||
2216 | |||
2217 | static void pack_setup(void) | ||
2218 | { | ||
2219 | pack_class = class_new(gensym("pack"), (t_newmethod)pack_new, | ||
2220 | (t_method)pack_free, sizeof(t_pack), 0, A_GIMME, 0); | ||
2221 | class_addbang(pack_class, pack_bang); | ||
2222 | class_addpointer(pack_class, pack_pointer); | ||
2223 | class_addfloat(pack_class, pack_float); | ||
2224 | class_addsymbol(pack_class, pack_symbol); | ||
2225 | class_addlist(pack_class, pack_list); | ||
2226 | class_addanything(pack_class, pack_anything); | ||
2227 | } | ||
2228 | |||
2229 | /* -------------------------- unpack ------------------------------ */ | ||
2230 | |||
2231 | static t_class *unpack_class; | ||
2232 | |||
2233 | typedef struct unpackout | ||
2234 | { | ||
2235 | t_atomtype u_type; | ||
2236 | t_outlet *u_outlet; | ||
2237 | } t_unpackout; | ||
2238 | |||
2239 | typedef struct _unpack | ||
2240 | { | ||
2241 | t_object x_obj; | ||
2242 | t_int x_n; | ||
2243 | t_unpackout *x_vec; | ||
2244 | } t_unpack; | ||
2245 | |||
2246 | static void *unpack_new(t_symbol *s, int argc, t_atom *argv) | ||
2247 | { | ||
2248 | t_unpack *x = (t_unpack *)pd_new(unpack_class); | ||
2249 | t_atom defarg[2], *ap; | ||
2250 | t_unpackout *u; | ||
2251 | int i; | ||
2252 | if (!argc) | ||
2253 | { | ||
2254 | argv = defarg; | ||
2255 | argc = 2; | ||
2256 | SETFLOAT(&defarg[0], 0); | ||
2257 | SETFLOAT(&defarg[1], 0); | ||
2258 | } | ||
2259 | x->x_n = argc; | ||
2260 | x->x_vec = (t_unpackout *)getbytes(argc * sizeof(*x->x_vec)); | ||
2261 | for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++) | ||
2262 | { | ||
2263 | t_atomtype type = ap->a_type; | ||
2264 | if (type == A_SYMBOL) | ||
2265 | { | ||
2266 | char c = *ap->a_w.w_symbol->s_name; | ||
2267 | if (c == 's') | ||
2268 | { | ||
2269 | u->u_type = A_SYMBOL; | ||
2270 | u->u_outlet = outlet_new(&x->x_obj, &s_symbol); | ||
2271 | } | ||
2272 | else if (c == 'p') | ||
2273 | { | ||
2274 | u->u_type = A_POINTER; | ||
2275 | u->u_outlet = outlet_new(&x->x_obj, &s_pointer); | ||
2276 | } | ||
2277 | else | ||
2278 | { | ||
2279 | if (c != 'f') pd_error(x, "unpack: %s: bad type", | ||
2280 | ap->a_w.w_symbol->s_name); | ||
2281 | u->u_type = A_FLOAT; | ||
2282 | u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
2283 | } | ||
2284 | } | ||
2285 | else | ||
2286 | { | ||
2287 | u->u_type = A_FLOAT; | ||
2288 | u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
2289 | } | ||
2290 | } | ||
2291 | return (x); | ||
2292 | } | ||
2293 | |||
2294 | static void unpack_list(t_unpack *x, t_symbol *s, int argc, t_atom *argv) | ||
2295 | { | ||
2296 | t_atom *ap; | ||
2297 | t_unpackout *u; | ||
2298 | int i; | ||
2299 | if (argc > x->x_n) argc = x->x_n; | ||
2300 | for (i = argc, u = x->x_vec + i, ap = argv + i; u--, ap--, i--;) | ||
2301 | { | ||
2302 | t_atomtype type = u->u_type; | ||
2303 | if (type != ap->a_type) | ||
2304 | pd_error(x, "unpack: type mismatch"); | ||
2305 | else if (type == A_FLOAT) | ||
2306 | outlet_float(u->u_outlet, ap->a_w.w_float); | ||
2307 | else if (type == A_SYMBOL) | ||
2308 | outlet_symbol(u->u_outlet, ap->a_w.w_symbol); | ||
2309 | else outlet_pointer(u->u_outlet, ap->a_w.w_gpointer); | ||
2310 | } | ||
2311 | } | ||
2312 | |||
2313 | static void unpack_anything(t_unpack *x, t_symbol *s, int ac, t_atom *av) | ||
2314 | { | ||
2315 | t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom)); | ||
2316 | int i; | ||
2317 | for (i = 0; i < ac; i++) | ||
2318 | av2[i + 1] = av[i]; | ||
2319 | SETSYMBOL(av2, s); | ||
2320 | unpack_list(x, 0, ac+1, av2); | ||
2321 | freebytes(av2, (ac + 1) * sizeof(t_atom)); | ||
2322 | } | ||
2323 | |||
2324 | static void unpack_free(t_unpack *x) | ||
2325 | { | ||
2326 | freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); | ||
2327 | } | ||
2328 | |||
2329 | static void unpack_setup(void) | ||
2330 | { | ||
2331 | unpack_class = class_new(gensym("unpack"), (t_newmethod)unpack_new, | ||
2332 | (t_method)unpack_free, sizeof(t_unpack), 0, A_GIMME, 0); | ||
2333 | class_addlist(unpack_class, unpack_list); | ||
2334 | class_addanything(unpack_class, unpack_anything); | ||
2335 | } | ||
2336 | |||
2337 | /* -------------------------- trigger ------------------------------ */ | ||
2338 | |||
2339 | static t_class *trigger_class; | ||
2340 | #define TR_BANG 0 | ||
2341 | #define TR_FLOAT 1 | ||
2342 | #define TR_SYMBOL 2 | ||
2343 | #define TR_POINTER 3 | ||
2344 | #define TR_LIST 4 | ||
2345 | #define TR_ANYTHING 5 | ||
2346 | |||
2347 | typedef struct triggerout | ||
2348 | { | ||
2349 | int u_type; /* outlet type from above */ | ||
2350 | t_outlet *u_outlet; | ||
2351 | } t_triggerout; | ||
2352 | |||
2353 | typedef struct _trigger | ||
2354 | { | ||
2355 | t_object x_obj; | ||
2356 | t_int x_n; | ||
2357 | t_triggerout *x_vec; | ||
2358 | } t_trigger; | ||
2359 | |||
2360 | static void *trigger_new(t_symbol *s, int argc, t_atom *argv) | ||
2361 | { | ||
2362 | t_trigger *x = (t_trigger *)pd_new(trigger_class); | ||
2363 | t_atom defarg[2], *ap; | ||
2364 | t_triggerout *u; | ||
2365 | int i; | ||
2366 | if (!argc) | ||
2367 | { | ||
2368 | argv = defarg; | ||
2369 | argc = 2; | ||
2370 | SETSYMBOL(&defarg[0], &s_bang); | ||
2371 | SETSYMBOL(&defarg[1], &s_bang); | ||
2372 | } | ||
2373 | x->x_n = argc; | ||
2374 | x->x_vec = (t_triggerout *)getbytes(argc * sizeof(*x->x_vec)); | ||
2375 | for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++) | ||
2376 | { | ||
2377 | t_atomtype thistype = ap->a_type; | ||
2378 | char c; | ||
2379 | if (thistype == TR_SYMBOL) c = ap->a_w.w_symbol->s_name[0]; | ||
2380 | else if (thistype == TR_FLOAT) c = 'f'; | ||
2381 | else c = 0; | ||
2382 | if (c == 'p') | ||
2383 | u->u_type = TR_POINTER, | ||
2384 | u->u_outlet = outlet_new(&x->x_obj, &s_pointer); | ||
2385 | else if (c == 'f') | ||
2386 | u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
2387 | else if (c == 'b') | ||
2388 | u->u_type = TR_BANG, u->u_outlet = outlet_new(&x->x_obj, &s_bang); | ||
2389 | else if (c == 'l') | ||
2390 | u->u_type = TR_LIST, u->u_outlet = outlet_new(&x->x_obj, &s_list); | ||
2391 | else if (c == 's') | ||
2392 | u->u_type = TR_SYMBOL, | ||
2393 | u->u_outlet = outlet_new(&x->x_obj, &s_symbol); | ||
2394 | else if (c == 'a') | ||
2395 | u->u_type = TR_ANYTHING, | ||
2396 | u->u_outlet = outlet_new(&x->x_obj, &s_symbol); | ||
2397 | else | ||
2398 | { | ||
2399 | pd_error(x, "trigger: %s: bad type", ap->a_w.w_symbol->s_name); | ||
2400 | u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float); | ||
2401 | } | ||
2402 | } | ||
2403 | return (x); | ||
2404 | } | ||
2405 | |||
2406 | static void trigger_list(t_trigger *x, t_symbol *s, int argc, t_atom *argv) | ||
2407 | { | ||
2408 | t_triggerout *u; | ||
2409 | int i; | ||
2410 | t_atom at; | ||
2411 | if (!argc) | ||
2412 | { | ||
2413 | argc = 1; | ||
2414 | SETFLOAT(&at, 0); | ||
2415 | argv = &at; | ||
2416 | } | ||
2417 | for (i = x->x_n, u = x->x_vec + i; u--, i--;) | ||
2418 | { | ||
2419 | if (u->u_type == TR_FLOAT) | ||
2420 | outlet_float(u->u_outlet, atom_getfloat(argv)); | ||
2421 | else if (u->u_type == TR_BANG) | ||
2422 | outlet_bang(u->u_outlet); | ||
2423 | else if (u->u_type == TR_SYMBOL) | ||
2424 | outlet_symbol(u->u_outlet, atom_getsymbol(argv)); | ||
2425 | else if (u->u_type == TR_POINTER) | ||
2426 | { | ||
2427 | if (argv->a_type != TR_POINTER) | ||
2428 | pd_error(x, "unpack: bad pointer"); | ||
2429 | else outlet_pointer(u->u_outlet, argv->a_w.w_gpointer); | ||
2430 | } | ||
2431 | else outlet_list(u->u_outlet, &s_list, argc, argv); | ||
2432 | } | ||
2433 | } | ||
2434 | |||
2435 | static void trigger_anything(t_trigger *x, t_symbol *s, int argc, t_atom *argv) | ||
2436 | { | ||
2437 | t_triggerout *u; | ||
2438 | int i; | ||
2439 | for (i = x->x_n, u = x->x_vec + i; u--, i--;) | ||
2440 | { | ||
2441 | if (u->u_type == TR_BANG) | ||
2442 | outlet_bang(u->u_outlet); | ||
2443 | else if (u->u_type == TR_ANYTHING) | ||
2444 | outlet_anything(u->u_outlet, s, argc, argv); | ||
2445 | else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'", | ||
2446 | s->s_name); | ||
2447 | } | ||
2448 | } | ||
2449 | |||
2450 | static void trigger_bang(t_trigger *x) | ||
2451 | { | ||
2452 | trigger_list(x, 0, 0, 0); | ||
2453 | } | ||
2454 | |||
2455 | static void trigger_pointer(t_trigger *x, t_gpointer *gp) | ||
2456 | { | ||
2457 | t_atom at; | ||
2458 | SETPOINTER(&at, gp); | ||
2459 | trigger_list(x, 0, 1, &at); | ||
2460 | } | ||
2461 | |||
2462 | static void trigger_float(t_trigger *x, t_float f) | ||
2463 | { | ||
2464 | t_atom at; | ||
2465 | SETFLOAT(&at, f); | ||
2466 | trigger_list(x, 0, 1, &at); | ||
2467 | } | ||
2468 | |||
2469 | static void trigger_symbol(t_trigger *x, t_symbol *s) | ||
2470 | { | ||
2471 | t_atom at; | ||
2472 | SETSYMBOL(&at, s); | ||
2473 | trigger_list(x, 0, 1, &at); | ||
2474 | } | ||
2475 | |||
2476 | static void trigger_free(t_trigger *x) | ||
2477 | { | ||
2478 | freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); | ||
2479 | } | ||
2480 | |||
2481 | static void trigger_setup(void) | ||
2482 | { | ||
2483 | trigger_class = class_new(gensym("trigger"), (t_newmethod)trigger_new, | ||
2484 | (t_method)trigger_free, sizeof(t_trigger), 0, A_GIMME, 0); | ||
2485 | class_addcreator((t_newmethod)trigger_new, gensym("t"), A_GIMME, 0); | ||
2486 | class_addlist(trigger_class, trigger_list); | ||
2487 | class_addbang(trigger_class, trigger_bang); | ||
2488 | class_addpointer(trigger_class, trigger_pointer); | ||
2489 | class_addfloat(trigger_class, (t_method)trigger_float); | ||
2490 | class_addsymbol(trigger_class, trigger_symbol); | ||
2491 | class_addanything(trigger_class, trigger_anything); | ||
2492 | } | ||
2493 | |||
2494 | /* -------------------------- spigot ------------------------------ */ | ||
2495 | static t_class *spigot_class; | ||
2496 | |||
2497 | typedef struct _spigot | ||
2498 | { | ||
2499 | t_object x_obj; | ||
2500 | float x_state; | ||
2501 | } t_spigot; | ||
2502 | |||
2503 | static void *spigot_new(void) | ||
2504 | { | ||
2505 | t_spigot *x = (t_spigot *)pd_new(spigot_class); | ||
2506 | floatinlet_new(&x->x_obj, &x->x_state); | ||
2507 | outlet_new(&x->x_obj, 0); | ||
2508 | x->x_state = 0; | ||
2509 | return (x); | ||
2510 | } | ||
2511 | |||
2512 | static void spigot_bang(t_spigot *x) | ||
2513 | { | ||
2514 | if (x->x_state != 0) outlet_bang(x->x_obj.ob_outlet); | ||
2515 | } | ||
2516 | |||
2517 | static void spigot_pointer(t_spigot *x, t_gpointer *gp) | ||
2518 | { | ||
2519 | if (x->x_state != 0) outlet_pointer(x->x_obj.ob_outlet, gp); | ||
2520 | } | ||
2521 | |||
2522 | static void spigot_float(t_spigot *x, t_float f) | ||
2523 | { | ||
2524 | if (x->x_state != 0) outlet_float(x->x_obj.ob_outlet, f); | ||
2525 | } | ||
2526 | |||
2527 | static void spigot_symbol(t_spigot *x, t_symbol *s) | ||
2528 | { | ||
2529 | if (x->x_state != 0) outlet_symbol(x->x_obj.ob_outlet, s); | ||
2530 | } | ||
2531 | |||
2532 | static void spigot_list(t_spigot *x, t_symbol *s, int argc, t_atom *argv) | ||
2533 | { | ||
2534 | if (x->x_state != 0) outlet_list(x->x_obj.ob_outlet, s, argc, argv); | ||
2535 | } | ||
2536 | |||
2537 | static void spigot_anything(t_spigot *x, t_symbol *s, int argc, t_atom *argv) | ||
2538 | { | ||
2539 | if (x->x_state != 0) outlet_anything(x->x_obj.ob_outlet, s, argc, argv); | ||
2540 | } | ||
2541 | |||
2542 | static void spigot_setup(void) | ||
2543 | { | ||
2544 | spigot_class = class_new(gensym("spigot"), (t_newmethod)spigot_new, 0, | ||
2545 | sizeof(t_spigot), 0, A_DEFSYM, 0); | ||
2546 | class_addbang(spigot_class, spigot_bang); | ||
2547 | class_addpointer(spigot_class, spigot_pointer); | ||
2548 | class_addfloat(spigot_class, spigot_float); | ||
2549 | class_addsymbol(spigot_class, spigot_symbol); | ||
2550 | class_addlist(spigot_class, spigot_list); | ||
2551 | class_addanything(spigot_class, spigot_anything); | ||
2552 | } | ||
2553 | |||
2554 | /* --------------------------- moses ----------------------------- */ | ||
2555 | static t_class *moses_class; | ||
2556 | |||
2557 | typedef struct _moses | ||
2558 | { | ||
2559 | t_object x_ob; | ||
2560 | t_outlet *x_out2; | ||
2561 | float x_y; | ||
2562 | } t_moses; | ||
2563 | |||
2564 | static void *moses_new(t_floatarg f) | ||
2565 | { | ||
2566 | t_moses *x = (t_moses *)pd_new(moses_class); | ||
2567 | floatinlet_new(&x->x_ob, &x->x_y); | ||
2568 | outlet_new(&x->x_ob, &s_float); | ||
2569 | x->x_out2 = outlet_new(&x->x_ob, &s_float); | ||
2570 | x->x_y = f; | ||
2571 | return (x); | ||
2572 | } | ||
2573 | |||
2574 | static void moses_float(t_moses *x, t_float f) | ||
2575 | { | ||
2576 | if (f < x->x_y) outlet_float(x->x_ob.ob_outlet, f); | ||
2577 | else outlet_float(x->x_out2, f); | ||
2578 | } | ||
2579 | |||
2580 | static void moses_setup(void) | ||
2581 | { | ||
2582 | moses_class = class_new(gensym("moses"), (t_newmethod)moses_new, 0, | ||
2583 | sizeof(t_moses), 0, A_DEFFLOAT, 0); | ||
2584 | class_addfloat(moses_class, moses_float); | ||
2585 | } | ||
2586 | |||
2587 | /* ----------------------- until --------------------- */ | ||
2588 | |||
2589 | static t_class *until_class; | ||
2590 | |||
2591 | typedef struct _until | ||
2592 | { | ||
2593 | t_object x_obj; | ||
2594 | int x_run; | ||
2595 | int x_count; | ||
2596 | } t_until; | ||
2597 | |||
2598 | static void *until_new(void) | ||
2599 | { | ||
2600 | t_until *x = (t_until *)pd_new(until_class); | ||
2601 | inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2")); | ||
2602 | outlet_new(&x->x_obj, &s_bang); | ||
2603 | x->x_run = 0; | ||
2604 | return (x); | ||
2605 | } | ||
2606 | |||
2607 | static void until_bang(t_until *x) | ||
2608 | { | ||
2609 | x->x_run = 1; | ||
2610 | x->x_count = -1; | ||
2611 | while (x->x_run && x->x_count) | ||
2612 | x->x_count--, outlet_bang(x->x_obj.ob_outlet); | ||
2613 | } | ||
2614 | |||
2615 | static void until_float(t_until *x, t_float f) | ||
2616 | { | ||
2617 | x->x_run = 1; | ||
2618 | x->x_count = f; | ||
2619 | while (x->x_run && x->x_count) | ||
2620 | x->x_count--, outlet_bang(x->x_obj.ob_outlet); | ||
2621 | } | ||
2622 | |||
2623 | static void until_bang2(t_until *x) | ||
2624 | { | ||
2625 | x->x_run = 0; | ||
2626 | } | ||
2627 | |||
2628 | static void until_setup(void) | ||
2629 | { | ||
2630 | until_class = class_new(gensym("until"), (t_newmethod)until_new, 0, | ||
2631 | sizeof(t_until), 0, 0); | ||
2632 | class_addbang(until_class, until_bang); | ||
2633 | class_addfloat(until_class, until_float); | ||
2634 | class_addmethod(until_class, (t_method)until_bang2, gensym("bang2"), 0); | ||
2635 | } | ||
2636 | |||
2637 | /* ----------------------- makefilename --------------------- */ | ||
2638 | |||
2639 | static t_class *makefilename_class; | ||
2640 | |||
2641 | typedef struct _makefilename | ||
2642 | { | ||
2643 | t_object x_obj; | ||
2644 | t_symbol *x_format; | ||
2645 | } t_makefilename; | ||
2646 | |||
2647 | static void *makefilename_new(t_symbol *s) | ||
2648 | { | ||
2649 | t_makefilename *x = (t_makefilename *)pd_new(makefilename_class); | ||
2650 | if (!s->s_name) s = gensym("file.%d"); | ||
2651 | outlet_new(&x->x_obj, &s_symbol); | ||
2652 | x->x_format = s; | ||
2653 | return (x); | ||
2654 | } | ||
2655 | |||
2656 | static void makefilename_float(t_makefilename *x, t_floatarg f) | ||
2657 | { | ||
2658 | char buf[MAXPDSTRING]; | ||
2659 | sprintf(buf, x->x_format->s_name, (int)f); | ||
2660 | outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); | ||
2661 | } | ||
2662 | |||
2663 | static void makefilename_symbol(t_makefilename *x, t_symbol *s) | ||
2664 | { | ||
2665 | char buf[MAXPDSTRING]; | ||
2666 | sprintf(buf, x->x_format->s_name, s->s_name); | ||
2667 | outlet_symbol(x->x_obj.ob_outlet, gensym(buf)); | ||
2668 | } | ||
2669 | |||
2670 | static void makefilename_setup(void) | ||
2671 | { | ||
2672 | makefilename_class = class_new(gensym("makefilename"), | ||
2673 | (t_newmethod)makefilename_new, 0, | ||
2674 | sizeof(t_makefilename), 0, A_DEFSYM, 0); | ||
2675 | class_addfloat(makefilename_class, makefilename_float); | ||
2676 | class_addsymbol(makefilename_class, makefilename_symbol); | ||
2677 | } | ||
2678 | |||
2679 | /* -------------------------- swap ------------------------------ */ | ||
2680 | static t_class *swap_class; | ||
2681 | |||
2682 | typedef struct _swap | ||
2683 | { | ||
2684 | t_object x_obj; | ||
2685 | t_outlet *x_out2; | ||
2686 | t_float x_f1; | ||
2687 | t_float x_f2; | ||
2688 | } t_swap; | ||
2689 | |||
2690 | static void *swap_new(t_floatarg f) | ||
2691 | { | ||
2692 | t_swap *x = (t_swap *)pd_new(swap_class); | ||
2693 | x->x_f2 = f; | ||
2694 | x->x_f1 = 0; | ||
2695 | outlet_new(&x->x_obj, &s_float); | ||
2696 | x->x_out2 = outlet_new(&x->x_obj, &s_float); | ||
2697 | floatinlet_new(&x->x_obj, &x->x_f2); | ||
2698 | return (x); | ||
2699 | } | ||
2700 | |||
2701 | static void swap_bang(t_swap *x) | ||
2702 | { | ||
2703 | outlet_float(x->x_out2, x->x_f1); | ||
2704 | outlet_float(x->x_obj.ob_outlet, x->x_f2); | ||
2705 | } | ||
2706 | |||
2707 | static void swap_float(t_swap *x, t_float f) | ||
2708 | { | ||
2709 | x->x_f1 = f; | ||
2710 | swap_bang(x); | ||
2711 | } | ||
2712 | |||
2713 | void swap_setup(void) | ||
2714 | { | ||
2715 | swap_class = class_new(gensym("swap"), (t_newmethod)swap_new, 0, | ||
2716 | sizeof(t_swap), 0, A_DEFFLOAT, 0); | ||
2717 | class_addcreator((t_newmethod)swap_new, gensym("fswap"), A_DEFFLOAT, 0); | ||
2718 | class_addbang(swap_class, swap_bang); | ||
2719 | class_addfloat(swap_class, swap_float); | ||
2720 | } | ||
2721 | |||
2722 | /* -------------------------- change ------------------------------ */ | ||
2723 | static t_class *change_class; | ||
2724 | |||
2725 | typedef struct _change | ||
2726 | { | ||
2727 | t_object x_obj; | ||
2728 | t_float x_f; | ||
2729 | } t_change; | ||
2730 | |||
2731 | static void *change_new(t_floatarg f) | ||
2732 | { | ||
2733 | t_change *x = (t_change *)pd_new(change_class); | ||
2734 | x->x_f = f; | ||
2735 | outlet_new(&x->x_obj, &s_float); | ||
2736 | return (x); | ||
2737 | } | ||
2738 | |||
2739 | static void change_bang(t_change *x) | ||
2740 | { | ||
2741 | outlet_float(x->x_obj.ob_outlet, x->x_f); | ||
2742 | } | ||
2743 | |||
2744 | static void change_float(t_change *x, t_float f) | ||
2745 | { | ||
2746 | if (f != x->x_f) | ||
2747 | { | ||
2748 | x->x_f = f; | ||
2749 | outlet_float(x->x_obj.ob_outlet, x->x_f); | ||
2750 | } | ||
2751 | } | ||
2752 | |||
2753 | static void change_set(t_change *x, t_float f) | ||
2754 | { | ||
2755 | x->x_f = f; | ||
2756 | } | ||
2757 | |||
2758 | void change_setup(void) | ||
2759 | { | ||
2760 | change_class = class_new(gensym("change"), (t_newmethod)change_new, 0, | ||
2761 | sizeof(t_change), 0, A_DEFFLOAT, 0); | ||
2762 | class_addbang(change_class, change_bang); | ||
2763 | class_addfloat(change_class, change_float); | ||
2764 | class_addmethod(change_class, (t_method)change_set, gensym("set"), | ||
2765 | A_DEFFLOAT, 0); | ||
2766 | } | ||
2767 | |||
2768 | /* -------------------- value ------------------------------ */ | ||
2769 | |||
2770 | static t_class *value_class, *vcommon_class; | ||
2771 | |||
2772 | typedef struct vcommon | ||
2773 | { | ||
2774 | t_pd c_pd; | ||
2775 | int c_refcount; | ||
2776 | t_float c_f; | ||
2777 | } t_vcommon; | ||
2778 | |||
2779 | typedef struct _value | ||
2780 | { | ||
2781 | t_object x_obj; | ||
2782 | t_symbol *x_sym; | ||
2783 | t_float *x_floatstar; | ||
2784 | } t_value; | ||
2785 | |||
2786 | /* get a pointer to a named floating-point variable. The variable | ||
2787 | belongs to a "vcommon" object, which is created if necessary. */ | ||
2788 | t_float *value_get(t_symbol *s) | ||
2789 | { | ||
2790 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
2791 | if (!c) | ||
2792 | { | ||
2793 | c = (t_vcommon *)pd_new(vcommon_class); | ||
2794 | c->c_f = 0; | ||
2795 | c->c_refcount = 0; | ||
2796 | pd_bind(&c->c_pd, s); | ||
2797 | } | ||
2798 | c->c_refcount++; | ||
2799 | return (&c->c_f); | ||
2800 | } | ||
2801 | |||
2802 | /* release a variable. This only frees the "vcommon" resource when the | ||
2803 | last interested party releases it. */ | ||
2804 | void value_release(t_symbol *s) | ||
2805 | { | ||
2806 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
2807 | if (c) | ||
2808 | { | ||
2809 | if (!--c->c_refcount) | ||
2810 | { | ||
2811 | pd_unbind(&c->c_pd, s); | ||
2812 | pd_free(&c->c_pd); | ||
2813 | } | ||
2814 | } | ||
2815 | else bug("value_release"); | ||
2816 | } | ||
2817 | |||
2818 | /* | ||
2819 | * value_getfloat -- obtain the float value of a "value" object | ||
2820 | * return 0 on success, 1 otherwise | ||
2821 | */ | ||
2822 | int | ||
2823 | value_getfloat(t_symbol *s, t_float *f) | ||
2824 | { | ||
2825 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
2826 | if (!c) | ||
2827 | return (1); | ||
2828 | *f = c->c_f; | ||
2829 | return (0); | ||
2830 | } | ||
2831 | |||
2832 | /* | ||
2833 | * value_setfloat -- set the float value of a "value" object | ||
2834 | * return 0 on success, 1 otherwise | ||
2835 | */ | ||
2836 | int | ||
2837 | value_setfloat(t_symbol *s, t_float f) | ||
2838 | { | ||
2839 | t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class); | ||
2840 | if (!c) | ||
2841 | return (1); | ||
2842 | c->c_f = f; | ||
2843 | return (0); | ||
2844 | } | ||
2845 | |||
2846 | static void *value_new(t_symbol *s) | ||
2847 | { | ||
2848 | t_value *x = (t_value *)pd_new(value_class); | ||
2849 | x->x_sym = s; | ||
2850 | x->x_floatstar = value_get(s); | ||
2851 | outlet_new(&x->x_obj, &s_float); | ||
2852 | return (x); | ||
2853 | } | ||
2854 | |||
2855 | static void value_bang(t_value *x) | ||
2856 | { | ||
2857 | outlet_float(x->x_obj.ob_outlet, *x->x_floatstar); | ||
2858 | } | ||
2859 | |||
2860 | static void value_float(t_value *x, t_float f) | ||
2861 | { | ||
2862 | *x->x_floatstar = f; | ||
2863 | } | ||
2864 | |||
2865 | static void value_ff(t_value *x) | ||
2866 | { | ||
2867 | value_release(x->x_sym); | ||
2868 | } | ||
2869 | |||
2870 | static void value_setup(void) | ||
2871 | { | ||
2872 | value_class = class_new(gensym("value"), (t_newmethod)value_new, | ||
2873 | (t_method)value_ff, | ||
2874 | sizeof(t_value), 0, A_DEFSYM, 0); | ||
2875 | class_addcreator((t_newmethod)value_new, gensym("v"), A_DEFSYM, 0); | ||
2876 | class_addbang(value_class, value_bang); | ||
2877 | class_addfloat(value_class, value_float); | ||
2878 | vcommon_class = class_new(gensym("value"), 0, 0, | ||
2879 | sizeof(t_vcommon), CLASS_PD, 0); | ||
2880 | } | ||
2881 | |||
2882 | /* -------------- overall setup routine for this file ----------------- */ | ||
2883 | |||
2884 | void x_connective_setup(void) | ||
2885 | { | ||
2886 | pdint_setup(); | ||
2887 | pdfloat_setup(); | ||
2888 | pdsymbol_setup(); | ||
2889 | bang_setup(); | ||
2890 | send_setup(); | ||
2891 | receive_setup(); | ||
2892 | select_setup(); | ||
2893 | route_setup(); | ||
2894 | pack_setup(); | ||
2895 | unpack_setup(); | ||
2896 | trigger_setup(); | ||
2897 | spigot_setup(); | ||
2898 | moses_setup(); | ||
2899 | until_setup(); | ||
2900 | makefilename_setup(); | ||
2901 | swap_setup(); | ||
2902 | change_setup(); | ||
2903 | value_setup(); | ||
2904 | } | ||