Fix pdbox makefile to actually take part in dependency generation
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / x_connective.c
blobbd504b54a41f9a89ea4b77b38210d79f6f6ff362
1 /* Copyright (c) 1997-1999 Miller Puckette.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 /* connective objects */
7 #ifdef ROCKBOX
8 #include "plugin.h"
9 #include "../../pdbox.h"
10 #endif
12 #include "m_pd.h"
14 #ifndef ROCKBOX
15 #include <string.h>
16 #include <stdio.h>
17 #endif
19 extern t_pd *newest;
21 /* -------------------------- int ------------------------------ */
22 static t_class *pdint_class;
24 typedef struct _pdint
26 t_object x_obj;
27 t_float x_f;
28 } t_pdint;
30 static void *pdint_new(t_floatarg f)
32 t_pdint *x = (t_pdint *)pd_new(pdint_class);
33 x->x_f = f;
34 outlet_new(&x->x_obj, &s_float);
35 floatinlet_new(&x->x_obj, &x->x_f);
36 return (x);
39 static void pdint_bang(t_pdint *x)
41 outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f));
44 static void pdint_float(t_pdint *x, t_float f)
46 outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f = f));
49 void pdint_setup(void)
51 pdint_class = class_new(gensym("int"), (t_newmethod)pdint_new, 0,
52 sizeof(t_pdint), 0, A_DEFFLOAT, 0);
53 class_addcreator((t_newmethod)pdint_new, gensym("i"), A_DEFFLOAT, 0);
54 class_addbang(pdint_class, pdint_bang);
55 class_addfloat(pdint_class, pdint_float);
58 /* -------------------------- float ------------------------------ */
59 static t_class *pdfloat_class;
61 typedef struct _pdfloat
63 t_object x_obj;
64 t_float x_f;
65 } t_pdfloat;
67 /* "float," "symbol," and "bang" are special because
68 they're created by short-circuited messages to the "new"
69 object which are handled specially in pd_typedmess(). */
71 static void *pdfloat_new(t_pd *dummy, t_float f)
73 #ifdef ROCKBOX
74 (void) dummy;
75 #endif
76 t_pdfloat *x = (t_pdfloat *)pd_new(pdfloat_class);
77 x->x_f = f;
78 outlet_new(&x->x_obj, &s_float);
79 floatinlet_new(&x->x_obj, &x->x_f);
80 newest = &x->x_obj.ob_pd;
81 return (x);
84 static void *pdfloat_new2(t_floatarg f)
86 return (pdfloat_new(0, f));
89 static void pdfloat_bang(t_pdfloat *x)
91 outlet_float(x->x_obj.ob_outlet, x->x_f);
94 static void pdfloat_float(t_pdfloat *x, t_float f)
96 outlet_float(x->x_obj.ob_outlet, x->x_f = f);
99 void pdfloat_setup(void)
101 pdfloat_class = class_new(gensym("float"), (t_newmethod)pdfloat_new, 0,
102 sizeof(t_pdfloat), 0, A_FLOAT, 0);
103 class_addcreator((t_newmethod)pdfloat_new2, gensym("f"), A_DEFFLOAT, 0);
104 class_addbang(pdfloat_class, pdfloat_bang);
105 class_addfloat(pdfloat_class, (t_method)pdfloat_float);
108 /* -------------------------- symbol ------------------------------ */
109 static t_class *pdsymbol_class;
111 typedef struct _pdsymbol
113 t_object x_obj;
114 t_symbol *x_s;
115 } t_pdsymbol;
117 static void *pdsymbol_new(t_pd *dummy, t_symbol *s)
119 #ifdef ROCKBOX
120 (void) dummy;
121 #endif
122 t_pdsymbol *x = (t_pdsymbol *)pd_new(pdsymbol_class);
123 x->x_s = s;
124 outlet_new(&x->x_obj, &s_symbol);
125 symbolinlet_new(&x->x_obj, &x->x_s);
126 newest = &x->x_obj.ob_pd;
127 return (x);
130 static void pdsymbol_bang(t_pdsymbol *x)
132 outlet_symbol(x->x_obj.ob_outlet, x->x_s);
135 static void pdsymbol_symbol(t_pdsymbol *x, t_symbol *s)
137 outlet_symbol(x->x_obj.ob_outlet, x->x_s = s);
140 static void pdsymbol_anything(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av)
142 #ifdef ROCKBOX
143 (void) ac;
144 (void) av;
145 #endif
146 outlet_symbol(x->x_obj.ob_outlet, x->x_s = s);
149 void pdsymbol_setup(void)
151 pdsymbol_class = class_new(gensym("symbol"), (t_newmethod)pdsymbol_new, 0,
152 sizeof(t_pdsymbol), 0, A_SYMBOL, 0);
153 class_addbang(pdsymbol_class, pdsymbol_bang);
154 class_addsymbol(pdsymbol_class, pdsymbol_symbol);
155 class_addanything(pdsymbol_class, pdsymbol_anything);
158 /* -------------------------- bang ------------------------------ */
159 static t_class *bang_class;
161 typedef struct _bang
163 t_object x_obj;
164 } t_bang;
166 static void *bang_new(t_pd *dummy)
168 #ifdef ROCKBOX
169 (void) dummy;
170 #endif
171 t_bang *x = (t_bang *)pd_new(bang_class);
172 outlet_new(&x->x_obj, &s_bang);
173 newest = &x->x_obj.ob_pd;
174 return (x);
177 static void *bang_new2(t_bang f)
179 #ifdef ROCKBOX
180 (void) f;
181 #endif
182 return (bang_new(0));
185 static void bang_bang(t_bang *x)
187 outlet_bang(x->x_obj.ob_outlet);
190 void bang_setup(void)
192 bang_class = class_new(gensym("bang"), (t_newmethod)bang_new, 0,
193 sizeof(t_bang), 0, 0);
194 class_addcreator((t_newmethod)bang_new2, gensym("b"), 0);
195 class_addbang(bang_class, bang_bang);
196 class_addfloat(bang_class, bang_bang);
197 class_addsymbol(bang_class, bang_bang);
198 class_addlist(bang_class, bang_bang);
199 class_addanything(bang_class, bang_bang);
202 /* -------------------- send ------------------------------ */
204 static t_class *send_class;
206 typedef struct _send
208 t_object x_obj;
209 t_symbol *x_sym;
210 } t_send;
212 static void send_bang(t_send *x)
214 if (x->x_sym->s_thing) pd_bang(x->x_sym->s_thing);
217 static void send_float(t_send *x, t_float f)
219 if (x->x_sym->s_thing) pd_float(x->x_sym->s_thing, f);
222 static void send_symbol(t_send *x, t_symbol *s)
224 if (x->x_sym->s_thing) pd_symbol(x->x_sym->s_thing, s);
227 static void send_pointer(t_send *x, t_gpointer *gp)
229 if (x->x_sym->s_thing) pd_pointer(x->x_sym->s_thing, gp);
232 static void send_list(t_send *x, t_symbol *s, int argc, t_atom *argv)
234 if (x->x_sym->s_thing) pd_list(x->x_sym->s_thing, s, argc, argv);
237 static void send_anything(t_send *x, t_symbol *s, int argc, t_atom *argv)
239 if (x->x_sym->s_thing) typedmess(x->x_sym->s_thing, s, argc, argv);
242 static void *send_new(t_symbol *s)
244 t_send *x = (t_send *)pd_new(send_class);
245 x->x_sym = s;
246 return (x);
249 static void send_setup(void)
251 send_class = class_new(gensym("send"), (t_newmethod)send_new, 0,
252 sizeof(t_send), 0, A_DEFSYM, 0);
253 class_addcreator((t_newmethod)send_new, gensym("s"), A_DEFSYM, 0);
254 class_addbang(send_class, send_bang);
255 class_addfloat(send_class, send_float);
256 class_addsymbol(send_class, send_symbol);
257 class_addpointer(send_class, send_pointer);
258 class_addlist(send_class, send_list);
259 class_addanything(send_class, send_anything);
261 /* -------------------- receive ------------------------------ */
263 static t_class *receive_class;
265 typedef struct _receive
267 t_object x_obj;
268 t_symbol *x_sym;
269 } t_receive;
271 static void receive_bang(t_receive *x)
273 outlet_bang(x->x_obj.ob_outlet);
276 static void receive_float(t_receive *x, t_float f)
278 outlet_float(x->x_obj.ob_outlet, f);
281 static void receive_symbol(t_receive *x, t_symbol *s)
283 outlet_symbol(x->x_obj.ob_outlet, s);
286 static void receive_pointer(t_receive *x, t_gpointer *gp)
288 outlet_pointer(x->x_obj.ob_outlet, gp);
291 static void receive_list(t_receive *x, t_symbol *s, int argc, t_atom *argv)
293 outlet_list(x->x_obj.ob_outlet, s, argc, argv);
296 static void receive_anything(t_receive *x, t_symbol *s, int argc, t_atom *argv)
298 outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
301 static void *receive_new(t_symbol *s)
303 t_receive *x = (t_receive *)pd_new(receive_class);
304 x->x_sym = s;
305 pd_bind(&x->x_obj.ob_pd, s);
306 outlet_new(&x->x_obj, 0);
307 return (x);
310 static void receive_free(t_receive *x)
312 pd_unbind(&x->x_obj.ob_pd, x->x_sym);
315 static void receive_setup(void)
317 receive_class = class_new(gensym("receive"), (t_newmethod)receive_new,
318 (t_method)receive_free, sizeof(t_receive), CLASS_NOINLET, A_DEFSYM, 0);
319 class_addcreator((t_newmethod)receive_new, gensym("r"), A_DEFSYM, 0);
320 class_addbang(receive_class, receive_bang);
321 class_addfloat(receive_class, (t_method)receive_float);
322 class_addsymbol(receive_class, receive_symbol);
323 class_addpointer(receive_class, receive_pointer);
324 class_addlist(receive_class, receive_list);
325 class_addanything(receive_class, receive_anything);
328 /* -------------------------- select ------------------------------ */
330 static t_class *sel1_class;
332 typedef struct _sel1
334 t_object x_obj;
335 t_atom x_atom;
336 t_outlet *x_outlet1;
337 t_outlet *x_outlet2;
338 } t_sel1;
340 static void sel1_float(t_sel1 *x, t_float f)
342 if (x->x_atom.a_type == A_FLOAT && f == x->x_atom.a_w.w_float)
343 outlet_bang(x->x_outlet1);
344 else outlet_float(x->x_outlet2, f);
347 static void sel1_symbol(t_sel1 *x, t_symbol *s)
349 if (x->x_atom.a_type == A_SYMBOL && s == x->x_atom.a_w.w_symbol)
350 outlet_bang(x->x_outlet1);
351 else outlet_symbol(x->x_outlet2, s);
354 static t_class *sel2_class;
356 typedef struct _selectelement
358 t_word e_w;
359 t_outlet *e_outlet;
360 } t_selectelement;
362 typedef struct _sel2
364 t_object x_obj;
365 t_atomtype x_type;
366 t_int x_nelement;
367 t_selectelement *x_vec;
368 t_outlet *x_rejectout;
369 } t_sel2;
371 static void sel2_float(t_sel2 *x, t_float f)
373 t_selectelement *e;
374 int nelement;
375 if (x->x_type == A_FLOAT)
377 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
378 if (e->e_w.w_float == f)
380 outlet_bang(e->e_outlet);
381 return;
384 outlet_float(x->x_rejectout, f);
387 static void sel2_symbol(t_sel2 *x, t_symbol *s)
389 t_selectelement *e;
390 int nelement;
391 if (x->x_type == A_SYMBOL)
393 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
394 if (e->e_w.w_symbol == s)
396 outlet_bang(e->e_outlet);
397 return;
400 outlet_symbol(x->x_rejectout, s);
403 static void sel2_free(t_sel2 *x)
405 freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
408 static void *select_new(t_symbol *s, int argc, t_atom *argv)
410 #ifdef ROCKBOX
411 (void) s;
412 #endif
413 t_atom a;
414 if (argc == 0)
416 argc = 1;
417 SETFLOAT(&a, 0);
418 argv = &a;
420 if (argc == 1)
422 t_sel1 *x = (t_sel1 *)pd_new(sel1_class);
423 x->x_atom = *argv;
424 x->x_outlet1 = outlet_new(&x->x_obj, &s_bang);
425 if (argv->a_type == A_FLOAT)
427 floatinlet_new(&x->x_obj, &x->x_atom.a_w.w_float);
428 x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
430 else
432 symbolinlet_new(&x->x_obj, &x->x_atom.a_w.w_symbol);
433 x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol);
435 return (x);
437 else
439 int n;
440 t_selectelement *e;
441 t_sel2 *x = (t_sel2 *)pd_new(sel2_class);
442 x->x_nelement = argc;
443 x->x_vec = (t_selectelement *)getbytes(argc * sizeof(*x->x_vec));
444 x->x_type = argv[0].a_type;
445 for (n = 0, e = x->x_vec; n < argc; n++, e++)
447 e->e_outlet = outlet_new(&x->x_obj, &s_bang);
448 if ((x->x_type = argv->a_type) == A_FLOAT)
449 e->e_w.w_float = atom_getfloatarg(n, argc, argv);
450 else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv);
452 x->x_rejectout = outlet_new(&x->x_obj, &s_float);
453 return (x);
458 void select_setup(void)
460 sel1_class = class_new(gensym("select"), 0, 0,
461 sizeof(t_sel1), 0, 0);
462 class_addfloat(sel1_class, sel1_float);
463 class_addsymbol(sel1_class, sel1_symbol);
465 sel2_class = class_new(gensym("select"), 0, (t_method)sel2_free,
466 sizeof(t_sel2), 0, 0);
467 class_addfloat(sel2_class, sel2_float);
468 class_addsymbol(sel2_class, sel2_symbol);
470 class_addcreator((t_newmethod)select_new, gensym("select"), A_GIMME, 0);
471 class_addcreator((t_newmethod)select_new, gensym("sel"), A_GIMME, 0);
474 /* -------------------------- route ------------------------------ */
476 static t_class *route_class;
478 typedef struct _routeelement
480 t_word e_w;
481 t_outlet *e_outlet;
482 } t_routeelement;
484 typedef struct _route
486 t_object x_obj;
487 t_atomtype x_type;
488 t_int x_nelement;
489 t_routeelement *x_vec;
490 t_outlet *x_rejectout;
491 } t_route;
493 static void route_anything(t_route *x, t_symbol *sel, int argc, t_atom *argv)
495 t_routeelement *e;
496 int nelement;
497 if (x->x_type == A_SYMBOL)
499 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
500 if (e->e_w.w_symbol == sel)
502 if (argc > 0 && argv[0].a_type == A_SYMBOL)
503 outlet_anything(e->e_outlet, argv[0].a_w.w_symbol,
504 argc-1, argv+1);
505 else outlet_list(e->e_outlet, 0, argc, argv);
506 return;
509 outlet_anything(x->x_rejectout, sel, argc, argv);
512 static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv)
514 #ifdef ROCKBOX
515 (void) sel;
516 #endif
517 t_routeelement *e;
518 int nelement;
519 if (x->x_type == A_FLOAT)
521 float f;
522 if (!argc) return;
523 f = atom_getfloat(argv);
524 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
525 if (e->e_w.w_float == f)
527 if (argc > 1 && argv[1].a_type == A_SYMBOL)
528 outlet_anything(e->e_outlet, argv[1].a_w.w_symbol,
529 argc-2, argv+2);
530 else outlet_list(e->e_outlet, 0, argc-1, argv+1);
531 return;
534 else /* symbol arguments */
536 if (argc > 1) /* 2 or more args: treat as "list" */
538 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
540 if (e->e_w.w_symbol == &s_list)
542 if (argc > 0 && argv[0].a_type == A_SYMBOL)
543 outlet_anything(e->e_outlet, argv[0].a_w.w_symbol,
544 argc-1, argv+1);
545 else outlet_list(e->e_outlet, 0, argc, argv);
546 return;
550 else if (argc == 0) /* no args: treat as "bang" */
552 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
554 if (e->e_w.w_symbol == &s_bang)
556 outlet_bang(e->e_outlet);
557 return;
561 else if (argv[0].a_type == A_FLOAT) /* one float arg */
563 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
565 if (e->e_w.w_symbol == &s_float)
567 outlet_float(e->e_outlet, argv[0].a_w.w_float);
568 return;
572 else
574 for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
576 if (e->e_w.w_symbol == &s_symbol)
578 outlet_symbol(e->e_outlet, argv[0].a_w.w_symbol);
579 return;
584 outlet_list(x->x_rejectout, 0, argc, argv);
588 static void route_free(t_route *x)
590 freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
593 static void *route_new(t_symbol *s, int argc, t_atom *argv)
595 #ifdef ROCKBOX
596 (void) s;
597 #endif
598 int n;
599 t_routeelement *e;
600 t_route *x = (t_route *)pd_new(route_class);
601 t_atom a;
602 if (argc == 0)
604 argc = 1;
605 SETFLOAT(&a, 0);
606 argv = &a;
608 x->x_type = argv[0].a_type;
609 x->x_nelement = argc;
610 x->x_vec = (t_routeelement *)getbytes(argc * sizeof(*x->x_vec));
611 for (n = 0, e = x->x_vec; n < argc; n++, e++)
613 e->e_outlet = outlet_new(&x->x_obj, &s_list);
614 if (x->x_type == A_FLOAT)
615 e->e_w.w_float = atom_getfloatarg(n, argc, argv);
616 else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv);
618 x->x_rejectout = outlet_new(&x->x_obj, &s_list);
619 return (x);
622 void route_setup(void)
624 route_class = class_new(gensym("route"), (t_newmethod)route_new,
625 (t_method)route_free, sizeof(t_route), 0, A_GIMME, 0);
626 class_addlist(route_class, route_list);
627 class_addanything(route_class, route_anything);
630 /* -------------------------- pack ------------------------------ */
632 static t_class *pack_class;
634 typedef struct _pack
636 t_object x_obj;
637 t_int x_n; /* number of args */
638 t_atom *x_vec; /* input values */
639 t_int x_nptr; /* number of pointers */
640 t_gpointer *x_gpointer; /* the pointers */
641 t_atom *x_outvec; /* space for output values */
642 } t_pack;
644 static void *pack_new(t_symbol *s, int argc, t_atom *argv)
646 #ifdef ROCKBOX
647 (void) s;
648 #endif
649 t_pack *x = (t_pack *)pd_new(pack_class);
650 t_atom defarg[2], *ap, *vec, *vp;
651 t_gpointer *gp;
652 int nptr = 0;
653 int i;
654 if (!argc)
656 argv = defarg;
657 argc = 2;
658 SETFLOAT(&defarg[0], 0);
659 SETFLOAT(&defarg[1], 0);
662 x->x_n = argc;
663 vec = x->x_vec = (t_atom *)getbytes(argc * sizeof(*x->x_vec));
664 x->x_outvec = (t_atom *)getbytes(argc * sizeof(*x->x_outvec));
666 for (i = argc, ap = argv; i--; ap++)
667 if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p')
668 nptr++;
670 gp = x->x_gpointer = (t_gpointer *)t_getbytes(nptr * sizeof (*gp));
671 x->x_nptr = nptr;
673 for (i = 0, vp = x->x_vec, ap = argv; i < argc; i++, ap++, vp++)
675 if (ap->a_type == A_FLOAT)
677 *vp = *ap;
678 if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float);
680 else if (ap->a_type == A_SYMBOL)
682 char c = *ap->a_w.w_symbol->s_name;
683 if (c == 's')
685 SETSYMBOL(vp, &s_symbol);
686 if (i) symbolinlet_new(&x->x_obj, &vp->a_w.w_symbol);
688 else if (c == 'p')
690 vp->a_type = A_POINTER;
691 vp->a_w.w_gpointer = gp;
692 gpointer_init(gp);
693 if (i) pointerinlet_new(&x->x_obj, gp);
694 gp++;
696 else
698 if (c != 'f') pd_error(x, "pack: %s: bad type",
699 ap->a_w.w_symbol->s_name);
700 SETFLOAT(vp, 0);
701 if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float);
705 outlet_new(&x->x_obj, &s_list);
706 return (x);
709 static void pack_bang(t_pack *x)
711 int i, reentered = 0, size = x->x_n * sizeof (t_atom);
712 t_gpointer *gp;
713 t_atom *outvec;
714 for (i = x->x_nptr, gp = x->x_gpointer; i--; gp++)
715 if (!gpointer_check(gp, 1))
717 pd_error(x, "pack: stale pointer");
718 return;
720 /* reentrancy protection. The first time through use the pre-allocated
721 x_outvec; if we're reentered we have to allocate new memory. */
722 if (!x->x_outvec)
724 /* LATER figure out how to deal with reentrancy and pointers... */
725 if (x->x_nptr)
726 post("pack_bang: warning: reentry with pointers unprotected");
727 outvec = t_getbytes(size);
728 reentered = 1;
730 else
732 outvec = x->x_outvec;
733 x->x_outvec = 0;
735 memcpy(outvec, x->x_vec, size);
736 outlet_list(x->x_obj.ob_outlet, &s_list, x->x_n, outvec);
737 if (reentered)
738 t_freebytes(outvec, size);
739 else x->x_outvec = outvec;
742 static void pack_pointer(t_pack *x, t_gpointer *gp)
744 if (x->x_vec->a_type == A_POINTER)
746 gpointer_unset(x->x_gpointer);
747 *x->x_gpointer = *gp;
748 if (gp->gp_stub) gp->gp_stub->gs_refcount++;
749 pack_bang(x);
751 else pd_error(x, "pack_pointer: wrong type");
754 static void pack_float(t_pack *x, t_float f)
756 if (x->x_vec->a_type == A_FLOAT)
758 x->x_vec->a_w.w_float = f;
759 pack_bang(x);
761 else pd_error(x, "pack_float: wrong type");
764 static void pack_symbol(t_pack *x, t_symbol *s)
766 if (x->x_vec->a_type == A_SYMBOL)
768 x->x_vec->a_w.w_symbol = s;
769 pack_bang(x);
771 else pd_error(x, "pack_symbol: wrong type");
774 static void pack_list(t_pack *x, t_symbol *s, int ac, t_atom *av)
776 #ifdef ROCKBOX
777 (void) s;
778 #endif
779 obj_list(&x->x_obj, 0, ac, av);
782 static void pack_anything(t_pack *x, t_symbol *s, int ac, t_atom *av)
784 t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom));
785 int i;
786 for (i = 0; i < ac; i++)
787 av2[i + 1] = av[i];
788 SETSYMBOL(av2, s);
789 obj_list(&x->x_obj, 0, ac+1, av2);
790 freebytes(av2, (ac + 1) * sizeof(t_atom));
793 static void pack_free(t_pack *x)
795 t_gpointer *gp;
796 int i;
797 for (gp = x->x_gpointer, i = x->x_nptr; i--; gp++)
798 gpointer_unset(gp);
799 freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
800 freebytes(x->x_outvec, x->x_n * sizeof(*x->x_outvec));
801 freebytes(x->x_gpointer, x->x_nptr * sizeof(*x->x_gpointer));
804 static void pack_setup(void)
806 pack_class = class_new(gensym("pack"), (t_newmethod)pack_new,
807 (t_method)pack_free, sizeof(t_pack), 0, A_GIMME, 0);
808 class_addbang(pack_class, pack_bang);
809 class_addpointer(pack_class, pack_pointer);
810 class_addfloat(pack_class, pack_float);
811 class_addsymbol(pack_class, pack_symbol);
812 class_addlist(pack_class, pack_list);
813 class_addanything(pack_class, pack_anything);
816 /* -------------------------- unpack ------------------------------ */
818 static t_class *unpack_class;
820 typedef struct unpackout
822 t_atomtype u_type;
823 t_outlet *u_outlet;
824 } t_unpackout;
826 typedef struct _unpack
828 t_object x_obj;
829 t_int x_n;
830 t_unpackout *x_vec;
831 } t_unpack;
833 static void *unpack_new(t_symbol *s, int argc, t_atom *argv)
835 #ifdef ROCKBOX
836 (void) s;
837 #endif
838 t_unpack *x = (t_unpack *)pd_new(unpack_class);
839 t_atom defarg[2], *ap;
840 t_unpackout *u;
841 int i;
842 if (!argc)
844 argv = defarg;
845 argc = 2;
846 SETFLOAT(&defarg[0], 0);
847 SETFLOAT(&defarg[1], 0);
849 x->x_n = argc;
850 x->x_vec = (t_unpackout *)getbytes(argc * sizeof(*x->x_vec));
851 for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++)
853 t_atomtype type = ap->a_type;
854 if (type == A_SYMBOL)
856 char c = *ap->a_w.w_symbol->s_name;
857 if (c == 's')
859 u->u_type = A_SYMBOL;
860 u->u_outlet = outlet_new(&x->x_obj, &s_symbol);
862 else if (c == 'p')
864 u->u_type = A_POINTER;
865 u->u_outlet = outlet_new(&x->x_obj, &s_pointer);
867 else
869 if (c != 'f') pd_error(x, "unpack: %s: bad type",
870 ap->a_w.w_symbol->s_name);
871 u->u_type = A_FLOAT;
872 u->u_outlet = outlet_new(&x->x_obj, &s_float);
875 else
877 u->u_type = A_FLOAT;
878 u->u_outlet = outlet_new(&x->x_obj, &s_float);
881 return (x);
884 static void unpack_list(t_unpack *x, t_symbol *s, int argc, t_atom *argv)
886 #ifdef ROCKBOX
887 (void) s;
888 #endif
889 t_atom *ap;
890 t_unpackout *u;
891 int i;
892 if (argc > x->x_n) argc = x->x_n;
893 for (i = argc, u = x->x_vec + i, ap = argv + i; u--, ap--, i--;)
895 t_atomtype type = u->u_type;
896 if (type != ap->a_type)
897 pd_error(x, "unpack: type mismatch");
898 else if (type == A_FLOAT)
899 outlet_float(u->u_outlet, ap->a_w.w_float);
900 else if (type == A_SYMBOL)
901 outlet_symbol(u->u_outlet, ap->a_w.w_symbol);
902 else outlet_pointer(u->u_outlet, ap->a_w.w_gpointer);
906 static void unpack_anything(t_unpack *x, t_symbol *s, int ac, t_atom *av)
908 t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom));
909 int i;
910 for (i = 0; i < ac; i++)
911 av2[i + 1] = av[i];
912 SETSYMBOL(av2, s);
913 unpack_list(x, 0, ac+1, av2);
914 freebytes(av2, (ac + 1) * sizeof(t_atom));
917 static void unpack_free(t_unpack *x)
919 freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
922 static void unpack_setup(void)
924 unpack_class = class_new(gensym("unpack"), (t_newmethod)unpack_new,
925 (t_method)unpack_free, sizeof(t_unpack), 0, A_GIMME, 0);
926 class_addlist(unpack_class, unpack_list);
927 class_addanything(unpack_class, unpack_anything);
930 /* -------------------------- trigger ------------------------------ */
932 static t_class *trigger_class;
933 #define TR_BANG 0
934 #define TR_FLOAT 1
935 #define TR_SYMBOL 2
936 #define TR_POINTER 3
937 #define TR_LIST 4
938 #define TR_ANYTHING 5
940 typedef struct triggerout
942 int u_type; /* outlet type from above */
943 t_outlet *u_outlet;
944 } t_triggerout;
946 typedef struct _trigger
948 t_object x_obj;
949 t_int x_n;
950 t_triggerout *x_vec;
951 } t_trigger;
953 static void *trigger_new(t_symbol *s, int argc, t_atom *argv)
955 #ifdef ROCKBOX
956 (void) s;
957 #endif
958 t_trigger *x = (t_trigger *)pd_new(trigger_class);
959 t_atom defarg[2], *ap;
960 t_triggerout *u;
961 int i;
962 if (!argc)
964 argv = defarg;
965 argc = 2;
966 SETSYMBOL(&defarg[0], &s_bang);
967 SETSYMBOL(&defarg[1], &s_bang);
969 x->x_n = argc;
970 x->x_vec = (t_triggerout *)getbytes(argc * sizeof(*x->x_vec));
971 for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++)
973 t_atomtype thistype = ap->a_type;
974 char c;
975 if (thistype == TR_SYMBOL) c = ap->a_w.w_symbol->s_name[0];
976 else if (thistype == TR_FLOAT) c = 'f';
977 else c = 0;
978 if (c == 'p')
979 u->u_type = TR_POINTER,
980 u->u_outlet = outlet_new(&x->x_obj, &s_pointer);
981 else if (c == 'f')
982 u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float);
983 else if (c == 'b')
984 u->u_type = TR_BANG, u->u_outlet = outlet_new(&x->x_obj, &s_bang);
985 else if (c == 'l')
986 u->u_type = TR_LIST, u->u_outlet = outlet_new(&x->x_obj, &s_list);
987 else if (c == 's')
988 u->u_type = TR_SYMBOL,
989 u->u_outlet = outlet_new(&x->x_obj, &s_symbol);
990 else if (c == 'a')
991 u->u_type = TR_ANYTHING,
992 u->u_outlet = outlet_new(&x->x_obj, &s_symbol);
993 else
995 pd_error(x, "trigger: %s: bad type", ap->a_w.w_symbol->s_name);
996 u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float);
999 return (x);
1002 static void trigger_list(t_trigger *x, t_symbol *s, int argc, t_atom *argv)
1004 #ifdef ROCKBOX
1005 (void) s;
1006 #endif
1007 t_triggerout *u;
1008 int i;
1009 t_atom at;
1010 if (!argc)
1012 argc = 1;
1013 SETFLOAT(&at, 0);
1014 argv = &at;
1016 for (i = x->x_n, u = x->x_vec + i; u--, i--;)
1018 if (u->u_type == TR_FLOAT)
1019 outlet_float(u->u_outlet, atom_getfloat(argv));
1020 else if (u->u_type == TR_BANG)
1021 outlet_bang(u->u_outlet);
1022 else if (u->u_type == TR_SYMBOL)
1023 outlet_symbol(u->u_outlet, atom_getsymbol(argv));
1024 else if (u->u_type == TR_POINTER)
1026 if (argv->a_type != TR_POINTER)
1027 pd_error(x, "unpack: bad pointer");
1028 else outlet_pointer(u->u_outlet, argv->a_w.w_gpointer);
1030 else outlet_list(u->u_outlet, &s_list, argc, argv);
1034 static void trigger_anything(t_trigger *x, t_symbol *s, int argc, t_atom *argv)
1036 t_triggerout *u;
1037 int i;
1038 for (i = x->x_n, u = x->x_vec + i; u--, i--;)
1040 if (u->u_type == TR_BANG)
1041 outlet_bang(u->u_outlet);
1042 else if (u->u_type == TR_ANYTHING)
1043 outlet_anything(u->u_outlet, s, argc, argv);
1044 else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'",
1045 s->s_name);
1049 static void trigger_bang(t_trigger *x)
1051 trigger_list(x, 0, 0, 0);
1054 static void trigger_pointer(t_trigger *x, t_gpointer *gp)
1056 t_atom at;
1057 SETPOINTER(&at, gp);
1058 trigger_list(x, 0, 1, &at);
1061 static void trigger_float(t_trigger *x, t_float f)
1063 t_atom at;
1064 SETFLOAT(&at, f);
1065 trigger_list(x, 0, 1, &at);
1068 static void trigger_symbol(t_trigger *x, t_symbol *s)
1070 t_atom at;
1071 SETSYMBOL(&at, s);
1072 trigger_list(x, 0, 1, &at);
1075 static void trigger_free(t_trigger *x)
1077 freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
1080 static void trigger_setup(void)
1082 trigger_class = class_new(gensym("trigger"), (t_newmethod)trigger_new,
1083 (t_method)trigger_free, sizeof(t_trigger), 0, A_GIMME, 0);
1084 class_addcreator((t_newmethod)trigger_new, gensym("t"), A_GIMME, 0);
1085 class_addlist(trigger_class, trigger_list);
1086 class_addbang(trigger_class, trigger_bang);
1087 class_addpointer(trigger_class, trigger_pointer);
1088 class_addfloat(trigger_class, (t_method)trigger_float);
1089 class_addsymbol(trigger_class, trigger_symbol);
1090 class_addanything(trigger_class, trigger_anything);
1093 /* -------------------------- spigot ------------------------------ */
1094 static t_class *spigot_class;
1096 typedef struct _spigot
1098 t_object x_obj;
1099 float x_state;
1100 } t_spigot;
1102 static void *spigot_new(void)
1104 t_spigot *x = (t_spigot *)pd_new(spigot_class);
1105 floatinlet_new(&x->x_obj, &x->x_state);
1106 outlet_new(&x->x_obj, 0);
1107 x->x_state = 0;
1108 return (x);
1111 static void spigot_bang(t_spigot *x)
1113 if (x->x_state != 0) outlet_bang(x->x_obj.ob_outlet);
1116 static void spigot_pointer(t_spigot *x, t_gpointer *gp)
1118 if (x->x_state != 0) outlet_pointer(x->x_obj.ob_outlet, gp);
1121 static void spigot_float(t_spigot *x, t_float f)
1123 if (x->x_state != 0) outlet_float(x->x_obj.ob_outlet, f);
1126 static void spigot_symbol(t_spigot *x, t_symbol *s)
1128 if (x->x_state != 0) outlet_symbol(x->x_obj.ob_outlet, s);
1131 static void spigot_list(t_spigot *x, t_symbol *s, int argc, t_atom *argv)
1133 if (x->x_state != 0) outlet_list(x->x_obj.ob_outlet, s, argc, argv);
1136 static void spigot_anything(t_spigot *x, t_symbol *s, int argc, t_atom *argv)
1138 if (x->x_state != 0) outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
1141 static void spigot_setup(void)
1143 spigot_class = class_new(gensym("spigot"), (t_newmethod)spigot_new, 0,
1144 sizeof(t_spigot), 0, A_DEFSYM, 0);
1145 class_addbang(spigot_class, spigot_bang);
1146 class_addpointer(spigot_class, spigot_pointer);
1147 class_addfloat(spigot_class, spigot_float);
1148 class_addsymbol(spigot_class, spigot_symbol);
1149 class_addlist(spigot_class, spigot_list);
1150 class_addanything(spigot_class, spigot_anything);
1153 /* --------------------------- moses ----------------------------- */
1154 static t_class *moses_class;
1156 typedef struct _moses
1158 t_object x_ob;
1159 t_outlet *x_out2;
1160 float x_y;
1161 } t_moses;
1163 static void *moses_new(t_floatarg f)
1165 t_moses *x = (t_moses *)pd_new(moses_class);
1166 floatinlet_new(&x->x_ob, &x->x_y);
1167 outlet_new(&x->x_ob, &s_float);
1168 x->x_out2 = outlet_new(&x->x_ob, &s_float);
1169 x->x_y = f;
1170 return (x);
1173 static void moses_float(t_moses *x, t_float f)
1175 if (f < x->x_y) outlet_float(x->x_ob.ob_outlet, f);
1176 else outlet_float(x->x_out2, f);
1179 static void moses_setup(void)
1181 moses_class = class_new(gensym("moses"), (t_newmethod)moses_new, 0,
1182 sizeof(t_moses), 0, A_DEFFLOAT, 0);
1183 class_addfloat(moses_class, moses_float);
1186 /* ----------------------- until --------------------- */
1188 static t_class *until_class;
1190 typedef struct _until
1192 t_object x_obj;
1193 int x_run;
1194 int x_count;
1195 } t_until;
1197 static void *until_new(void)
1199 t_until *x = (t_until *)pd_new(until_class);
1200 inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2"));
1201 outlet_new(&x->x_obj, &s_bang);
1202 x->x_run = 0;
1203 return (x);
1206 static void until_bang(t_until *x)
1208 x->x_run = 1;
1209 x->x_count = -1;
1210 while (x->x_run && x->x_count)
1211 x->x_count--, outlet_bang(x->x_obj.ob_outlet);
1214 static void until_float(t_until *x, t_float f)
1216 x->x_run = 1;
1217 x->x_count = f;
1218 while (x->x_run && x->x_count)
1219 x->x_count--, outlet_bang(x->x_obj.ob_outlet);
1222 static void until_bang2(t_until *x)
1224 x->x_run = 0;
1227 static void until_setup(void)
1229 until_class = class_new(gensym("until"), (t_newmethod)until_new, 0,
1230 sizeof(t_until), 0, 0);
1231 class_addbang(until_class, until_bang);
1232 class_addfloat(until_class, until_float);
1233 class_addmethod(until_class, (t_method)until_bang2, gensym("bang2"), 0);
1236 /* ----------------------- makefilename --------------------- */
1238 static t_class *makefilename_class;
1240 typedef struct _makefilename
1242 t_object x_obj;
1243 t_symbol *x_format;
1244 } t_makefilename;
1246 static void *makefilename_new(t_symbol *s)
1248 t_makefilename *x = (t_makefilename *)pd_new(makefilename_class);
1249 if (!s->s_name) s = gensym("file.%d");
1250 outlet_new(&x->x_obj, &s_symbol);
1251 x->x_format = s;
1252 return (x);
1255 static void makefilename_float(t_makefilename *x, t_floatarg f)
1257 char buf[MAXPDSTRING];
1258 #ifdef ROCKBOX
1259 snprintf(buf, sizeof(buf), x->x_format->s_name, (int)f);
1260 #else
1261 sprintf(buf, x->x_format->s_name, (int)f);
1262 #endif
1263 outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
1266 static void makefilename_symbol(t_makefilename *x, t_symbol *s)
1268 char buf[MAXPDSTRING];
1269 #ifdef ROCKBOX
1270 snprintf(buf, sizeof(buf), x->x_format->s_name, s->s_name);
1271 #else
1272 sprintf(buf, x->x_format->s_name, s->s_name);
1273 #endif
1274 outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
1277 static void makefilename_setup(void)
1279 makefilename_class = class_new(gensym("makefilename"),
1280 (t_newmethod)makefilename_new, 0,
1281 sizeof(t_makefilename), 0, A_DEFSYM, 0);
1282 class_addfloat(makefilename_class, makefilename_float);
1283 class_addsymbol(makefilename_class, makefilename_symbol);
1286 /* -------------------------- swap ------------------------------ */
1287 static t_class *swap_class;
1289 typedef struct _swap
1291 t_object x_obj;
1292 t_outlet *x_out2;
1293 t_float x_f1;
1294 t_float x_f2;
1295 } t_swap;
1297 static void *swap_new(t_floatarg f)
1299 t_swap *x = (t_swap *)pd_new(swap_class);
1300 x->x_f2 = f;
1301 x->x_f1 = 0;
1302 outlet_new(&x->x_obj, &s_float);
1303 x->x_out2 = outlet_new(&x->x_obj, &s_float);
1304 floatinlet_new(&x->x_obj, &x->x_f2);
1305 return (x);
1308 static void swap_bang(t_swap *x)
1310 outlet_float(x->x_out2, x->x_f1);
1311 outlet_float(x->x_obj.ob_outlet, x->x_f2);
1314 static void swap_float(t_swap *x, t_float f)
1316 x->x_f1 = f;
1317 swap_bang(x);
1320 void swap_setup(void)
1322 swap_class = class_new(gensym("swap"), (t_newmethod)swap_new, 0,
1323 sizeof(t_swap), 0, A_DEFFLOAT, 0);
1324 class_addcreator((t_newmethod)swap_new, gensym("fswap"), A_DEFFLOAT, 0);
1325 class_addbang(swap_class, swap_bang);
1326 class_addfloat(swap_class, swap_float);
1329 /* -------------------------- change ------------------------------ */
1330 static t_class *change_class;
1332 typedef struct _change
1334 t_object x_obj;
1335 t_float x_f;
1336 } t_change;
1338 static void *change_new(t_floatarg f)
1340 t_change *x = (t_change *)pd_new(change_class);
1341 x->x_f = f;
1342 outlet_new(&x->x_obj, &s_float);
1343 return (x);
1346 static void change_bang(t_change *x)
1348 outlet_float(x->x_obj.ob_outlet, x->x_f);
1351 static void change_float(t_change *x, t_float f)
1353 if (f != x->x_f)
1355 x->x_f = f;
1356 outlet_float(x->x_obj.ob_outlet, x->x_f);
1360 static void change_set(t_change *x, t_float f)
1362 x->x_f = f;
1365 void change_setup(void)
1367 change_class = class_new(gensym("change"), (t_newmethod)change_new, 0,
1368 sizeof(t_change), 0, A_DEFFLOAT, 0);
1369 class_addbang(change_class, change_bang);
1370 class_addfloat(change_class, change_float);
1371 class_addmethod(change_class, (t_method)change_set, gensym("set"),
1372 A_DEFFLOAT, 0);
1375 /* -------------------- value ------------------------------ */
1377 static t_class *value_class, *vcommon_class;
1379 typedef struct vcommon
1381 t_pd c_pd;
1382 int c_refcount;
1383 t_float c_f;
1384 } t_vcommon;
1386 typedef struct _value
1388 t_object x_obj;
1389 t_symbol *x_sym;
1390 t_float *x_floatstar;
1391 } t_value;
1393 /* get a pointer to a named floating-point variable. The variable
1394 belongs to a "vcommon" object, which is created if necessary. */
1395 t_float *value_get(t_symbol *s)
1397 t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
1398 if (!c)
1400 c = (t_vcommon *)pd_new(vcommon_class);
1401 c->c_f = 0;
1402 c->c_refcount = 0;
1403 pd_bind(&c->c_pd, s);
1405 c->c_refcount++;
1406 return (&c->c_f);
1409 /* release a variable. This only frees the "vcommon" resource when the
1410 last interested party releases it. */
1411 void value_release(t_symbol *s)
1413 t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
1414 if (c)
1416 if (!--c->c_refcount)
1418 pd_unbind(&c->c_pd, s);
1419 pd_free(&c->c_pd);
1422 else bug("value_release");
1426 * value_getfloat -- obtain the float value of a "value" object
1427 * return 0 on success, 1 otherwise
1430 value_getfloat(t_symbol *s, t_float *f)
1432 t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
1433 if (!c)
1434 return (1);
1435 *f = c->c_f;
1436 return (0);
1440 * value_setfloat -- set the float value of a "value" object
1441 * return 0 on success, 1 otherwise
1444 value_setfloat(t_symbol *s, t_float f)
1446 t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
1447 if (!c)
1448 return (1);
1449 c->c_f = f;
1450 return (0);
1453 static void *value_new(t_symbol *s)
1455 t_value *x = (t_value *)pd_new(value_class);
1456 x->x_sym = s;
1457 x->x_floatstar = value_get(s);
1458 outlet_new(&x->x_obj, &s_float);
1459 return (x);
1462 static void value_bang(t_value *x)
1464 outlet_float(x->x_obj.ob_outlet, *x->x_floatstar);
1467 static void value_float(t_value *x, t_float f)
1469 *x->x_floatstar = f;
1472 static void value_ff(t_value *x)
1474 value_release(x->x_sym);
1477 static void value_setup(void)
1479 value_class = class_new(gensym("value"), (t_newmethod)value_new,
1480 (t_method)value_ff,
1481 sizeof(t_value), 0, A_DEFSYM, 0);
1482 class_addcreator((t_newmethod)value_new, gensym("v"), A_DEFSYM, 0);
1483 class_addbang(value_class, value_bang);
1484 class_addfloat(value_class, value_float);
1485 vcommon_class = class_new(gensym("value"), 0, 0,
1486 sizeof(t_vcommon), CLASS_PD, 0);
1489 /* -------------- overall setup routine for this file ----------------- */
1491 void x_connective_setup(void)
1493 pdint_setup();
1494 pdfloat_setup();
1495 pdsymbol_setup();
1496 bang_setup();
1497 send_setup();
1498 receive_setup();
1499 select_setup();
1500 route_setup();
1501 pack_setup();
1502 unpack_setup();
1503 trigger_setup();
1504 spigot_setup();
1505 moses_setup();
1506 until_setup();
1507 makefilename_setup();
1508 swap_setup();
1509 change_setup();
1510 value_setup();