aboutsummaryrefslogtreecommitdiff
path: root/pd/src/x_connective.c
diff options
context:
space:
mode:
Diffstat (limited to 'pd/src/x_connective.c')
-rw-r--r--pd/src/x_connective.c1452
1 files changed, 1452 insertions, 0 deletions
diff --git a/pd/src/x_connective.c b/pd/src/x_connective.c
new file mode 100644
index 00000000..2b28f052
--- /dev/null
+++ b/pd/src/x_connective.c
@@ -0,0 +1,1452 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* connective objects */
+
+#include "m_pd.h"
+
+#include <string.h>
+#include <stdio.h>
+extern t_pd *newest;
+
+/* -------------------------- int ------------------------------ */
+static t_class *pdint_class;
+
+typedef struct _pdint
+{
+ t_object x_obj;
+ t_float x_f;
+} t_pdint;
+
+static void *pdint_new(t_floatarg f)
+{
+ t_pdint *x = (t_pdint *)pd_new(pdint_class);
+ x->x_f = f;
+ outlet_new(&x->x_obj, &s_float);
+ floatinlet_new(&x->x_obj, &x->x_f);
+ return (x);
+}
+
+static void pdint_bang(t_pdint *x)
+{
+ outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f));
+}
+
+static void pdint_float(t_pdint *x, t_float f)
+{
+ outlet_float(x->x_obj.ob_outlet, (t_float)(int)(x->x_f = f));
+}
+
+void pdint_setup(void)
+{
+ pdint_class = class_new(gensym("int"), (t_newmethod)pdint_new, 0,
+ sizeof(t_pdint), 0, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)pdint_new, gensym("i"), A_DEFFLOAT, 0);
+ class_addbang(pdint_class, pdint_bang);
+ class_addfloat(pdint_class, pdint_float);
+}
+
+/* -------------------------- float ------------------------------ */
+static t_class *pdfloat_class;
+
+typedef struct _pdfloat
+{
+ t_object x_obj;
+ t_float x_f;
+} t_pdfloat;
+
+ /* "float," "symbol," and "bang" are special because
+ they're created by short-circuited messages to the "new"
+ object which are handled specially in pd_typedmess(). */
+
+static void *pdfloat_new(t_pd *dummy, t_float f)
+{
+ t_pdfloat *x = (t_pdfloat *)pd_new(pdfloat_class);
+ x->x_f = f;
+ outlet_new(&x->x_obj, &s_float);
+ floatinlet_new(&x->x_obj, &x->x_f);
+ newest = &x->x_obj.ob_pd;
+ return (x);
+}
+
+static void *pdfloat_new2(t_floatarg f)
+{
+ return (pdfloat_new(0, f));
+}
+
+static void pdfloat_bang(t_pdfloat *x)
+{
+ outlet_float(x->x_obj.ob_outlet, x->x_f);
+}
+
+static void pdfloat_float(t_pdfloat *x, t_float f)
+{
+ outlet_float(x->x_obj.ob_outlet, x->x_f = f);
+}
+
+void pdfloat_setup(void)
+{
+ pdfloat_class = class_new(gensym("float"), (t_newmethod)pdfloat_new, 0,
+ sizeof(t_pdfloat), 0, A_FLOAT, 0);
+ class_addcreator((t_newmethod)pdfloat_new2, gensym("f"), A_DEFFLOAT, 0);
+ class_addbang(pdfloat_class, pdfloat_bang);
+ class_addfloat(pdfloat_class, (t_method)pdfloat_float);
+}
+
+/* -------------------------- symbol ------------------------------ */
+static t_class *pdsymbol_class;
+
+typedef struct _pdsymbol
+{
+ t_object x_obj;
+ t_symbol *x_s;
+} t_pdsymbol;
+
+static void *pdsymbol_new(t_pd *dummy, t_symbol *s)
+{
+ t_pdsymbol *x = (t_pdsymbol *)pd_new(pdsymbol_class);
+ x->x_s = s;
+ outlet_new(&x->x_obj, &s_symbol);
+ symbolinlet_new(&x->x_obj, &x->x_s);
+ newest = &x->x_obj.ob_pd;
+ return (x);
+}
+
+static void pdsymbol_bang(t_pdsymbol *x)
+{
+ outlet_symbol(x->x_obj.ob_outlet, x->x_s);
+}
+
+static void pdsymbol_symbol(t_pdsymbol *x, t_symbol *s)
+{
+ outlet_symbol(x->x_obj.ob_outlet, x->x_s = s);
+}
+
+static void pdsymbol_anything(t_pdsymbol *x, t_symbol *s, int ac, t_atom *av)
+{
+ outlet_symbol(x->x_obj.ob_outlet, x->x_s = s);
+}
+
+void pdsymbol_setup(void)
+{
+ pdsymbol_class = class_new(gensym("symbol"), (t_newmethod)pdsymbol_new, 0,
+ sizeof(t_pdsymbol), 0, A_SYMBOL, 0);
+ class_addbang(pdsymbol_class, pdsymbol_bang);
+ class_addsymbol(pdsymbol_class, pdsymbol_symbol);
+ class_addanything(pdsymbol_class, pdsymbol_anything);
+}
+
+/* -------------------------- bang ------------------------------ */
+static t_class *bang_class;
+
+typedef struct _bang
+{
+ t_object x_obj;
+} t_bang;
+
+static void *bang_new(t_pd *dummy)
+{
+ t_bang *x = (t_bang *)pd_new(bang_class);
+ outlet_new(&x->x_obj, &s_bang);
+ newest = &x->x_obj.ob_pd;
+ return (x);
+}
+
+static void *bang_new2(t_bang f)
+{
+ return (bang_new(0));
+}
+
+static void bang_bang(t_bang *x)
+{
+ outlet_bang(x->x_obj.ob_outlet);
+}
+
+void bang_setup(void)
+{
+ bang_class = class_new(gensym("bang"), (t_newmethod)bang_new, 0,
+ sizeof(t_bang), 0, 0);
+ class_addcreator((t_newmethod)bang_new2, gensym("b"), 0);
+ class_addbang(bang_class, bang_bang);
+ class_addfloat(bang_class, bang_bang);
+ class_addsymbol(bang_class, bang_bang);
+ class_addlist(bang_class, bang_bang);
+ class_addanything(bang_class, bang_bang);
+}
+
+/* -------------------- send ------------------------------ */
+
+static t_class *send_class;
+
+typedef struct _send
+{
+ t_object x_obj;
+ t_symbol *x_sym;
+} t_send;
+
+static void send_bang(t_send *x)
+{
+ if (x->x_sym->s_thing) pd_bang(x->x_sym->s_thing);
+}
+
+static void send_float(t_send *x, t_float f)
+{
+ if (x->x_sym->s_thing) pd_float(x->x_sym->s_thing, f);
+}
+
+static void send_symbol(t_send *x, t_symbol *s)
+{
+ if (x->x_sym->s_thing) pd_symbol(x->x_sym->s_thing, s);
+}
+
+static void send_pointer(t_send *x, t_gpointer *gp)
+{
+ if (x->x_sym->s_thing) pd_pointer(x->x_sym->s_thing, gp);
+}
+
+static void send_list(t_send *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (x->x_sym->s_thing) pd_list(x->x_sym->s_thing, s, argc, argv);
+}
+
+static void send_anything(t_send *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (x->x_sym->s_thing) typedmess(x->x_sym->s_thing, s, argc, argv);
+}
+
+static void *send_new(t_symbol *s)
+{
+ t_send *x = (t_send *)pd_new(send_class);
+ x->x_sym = s;
+ return (x);
+}
+
+static void send_setup(void)
+{
+ send_class = class_new(gensym("send"), (t_newmethod)send_new, 0,
+ sizeof(t_send), 0, A_DEFSYM, 0);
+ class_addcreator((t_newmethod)send_new, gensym("s"), A_DEFSYM, 0);
+ class_addbang(send_class, send_bang);
+ class_addfloat(send_class, send_float);
+ class_addsymbol(send_class, send_symbol);
+ class_addpointer(send_class, send_pointer);
+ class_addlist(send_class, send_list);
+ class_addanything(send_class, send_anything);
+}
+/* -------------------- receive ------------------------------ */
+
+static t_class *receive_class;
+
+typedef struct _receive
+{
+ t_object x_obj;
+ t_symbol *x_sym;
+} t_receive;
+
+static void receive_bang(t_receive *x)
+{
+ outlet_bang(x->x_obj.ob_outlet);
+}
+
+static void receive_float(t_receive *x, t_float f)
+{
+ outlet_float(x->x_obj.ob_outlet, f);
+}
+
+static void receive_symbol(t_receive *x, t_symbol *s)
+{
+ outlet_symbol(x->x_obj.ob_outlet, s);
+}
+
+static void receive_pointer(t_receive *x, t_gpointer *gp)
+{
+ outlet_pointer(x->x_obj.ob_outlet, gp);
+}
+
+static void receive_list(t_receive *x, t_symbol *s, int argc, t_atom *argv)
+{
+ outlet_list(x->x_obj.ob_outlet, s, argc, argv);
+}
+
+static void receive_anything(t_receive *x, t_symbol *s, int argc, t_atom *argv)
+{
+ outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
+}
+
+static void *receive_new(t_symbol *s)
+{
+ t_receive *x = (t_receive *)pd_new(receive_class);
+ x->x_sym = s;
+ pd_bind(&x->x_obj.ob_pd, s);
+ outlet_new(&x->x_obj, 0);
+ return (x);
+}
+
+static void receive_free(t_receive *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, x->x_sym);
+}
+
+static void receive_setup(void)
+{
+ receive_class = class_new(gensym("receive"), (t_newmethod)receive_new,
+ (t_method)receive_free, sizeof(t_receive), CLASS_NOINLET, A_DEFSYM, 0);
+ class_addcreator((t_newmethod)receive_new, gensym("r"), A_DEFSYM, 0);
+ class_addbang(receive_class, receive_bang);
+ class_addfloat(receive_class, (t_method)receive_float);
+ class_addsymbol(receive_class, receive_symbol);
+ class_addpointer(receive_class, receive_pointer);
+ class_addlist(receive_class, receive_list);
+ class_addanything(receive_class, receive_anything);
+}
+
+/* -------------------------- select ------------------------------ */
+
+static t_class *sel1_class;
+
+typedef struct _sel1
+{
+ t_object x_obj;
+ t_atom x_atom;
+ t_outlet *x_outlet1;
+ t_outlet *x_outlet2;
+} t_sel1;
+
+static void sel1_float(t_sel1 *x, t_float f)
+{
+ if (x->x_atom.a_type == A_FLOAT && f == x->x_atom.a_w.w_float)
+ outlet_bang(x->x_outlet1);
+ else outlet_float(x->x_outlet2, f);
+}
+
+static void sel1_symbol(t_sel1 *x, t_symbol *s)
+{
+ if (x->x_atom.a_type == A_SYMBOL && s == x->x_atom.a_w.w_symbol)
+ outlet_bang(x->x_outlet1);
+ else outlet_symbol(x->x_outlet2, s);
+}
+
+static t_class *sel2_class;
+
+typedef struct _selectelement
+{
+ t_word e_w;
+ t_outlet *e_outlet;
+} t_selectelement;
+
+typedef struct _sel2
+{
+ t_object x_obj;
+ t_atomtype x_type;
+ t_int x_nelement;
+ t_selectelement *x_vec;
+ t_outlet *x_rejectout;
+} t_sel2;
+
+static void sel2_float(t_sel2 *x, t_float f)
+{
+ t_selectelement *e;
+ int nelement;
+ if (x->x_type == A_FLOAT)
+ {
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ if (e->e_w.w_float == f)
+ {
+ outlet_bang(e->e_outlet);
+ return;
+ }
+ }
+ outlet_float(x->x_rejectout, f);
+}
+
+static void sel2_symbol(t_sel2 *x, t_symbol *s)
+{
+ t_selectelement *e;
+ int nelement;
+ if (x->x_type == A_SYMBOL)
+ {
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ if (e->e_w.w_symbol == s)
+ {
+ outlet_bang(e->e_outlet);
+ return;
+ }
+ }
+ outlet_symbol(x->x_rejectout, s);
+}
+
+static void sel2_free(t_sel2 *x)
+{
+ freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
+}
+
+static void *select_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_atom a;
+ if (argc == 0)
+ {
+ argc = 1;
+ SETFLOAT(&a, 0);
+ argv = &a;
+ }
+ if (argc == 1)
+ {
+ t_sel1 *x = (t_sel1 *)pd_new(sel1_class);
+ x->x_atom = *argv;
+ x->x_outlet1 = outlet_new(&x->x_obj, &s_bang);
+ if (argv->a_type == A_FLOAT)
+ {
+ floatinlet_new(&x->x_obj, &x->x_atom.a_w.w_float);
+ x->x_outlet2 = outlet_new(&x->x_obj, &s_float);
+ }
+ else
+ {
+ symbolinlet_new(&x->x_obj, &x->x_atom.a_w.w_symbol);
+ x->x_outlet2 = outlet_new(&x->x_obj, &s_symbol);
+ }
+ return (x);
+ }
+ else
+ {
+ int n;
+ t_selectelement *e;
+ t_sel2 *x = (t_sel2 *)pd_new(sel2_class);
+ x->x_nelement = argc;
+ x->x_vec = (t_selectelement *)getbytes(argc * sizeof(*x->x_vec));
+ x->x_type = argv[0].a_type;
+ for (n = 0, e = x->x_vec; n < argc; n++, e++)
+ {
+ e->e_outlet = outlet_new(&x->x_obj, &s_bang);
+ if ((x->x_type = argv->a_type) == A_FLOAT)
+ e->e_w.w_float = atom_getfloatarg(n, argc, argv);
+ else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv);
+ }
+ x->x_rejectout = outlet_new(&x->x_obj, &s_float);
+ return (x);
+ }
+
+}
+
+void select_setup(void)
+{
+ sel1_class = class_new(gensym("select"), 0, 0,
+ sizeof(t_sel1), 0, 0);
+ class_addfloat(sel1_class, sel1_float);
+ class_addsymbol(sel1_class, sel1_symbol);
+
+ sel2_class = class_new(gensym("select"), 0, (t_method)sel2_free,
+ sizeof(t_sel2), 0, 0);
+ class_addfloat(sel2_class, sel2_float);
+ class_addsymbol(sel2_class, sel2_symbol);
+
+ class_addcreator((t_newmethod)select_new, gensym("select"), A_GIMME, 0);
+ class_addcreator((t_newmethod)select_new, gensym("sel"), A_GIMME, 0);
+}
+
+/* -------------------------- route ------------------------------ */
+
+static t_class *route_class;
+
+typedef struct _routeelement
+{
+ t_word e_w;
+ t_outlet *e_outlet;
+} t_routeelement;
+
+typedef struct _route
+{
+ t_object x_obj;
+ t_atomtype x_type;
+ t_int x_nelement;
+ t_routeelement *x_vec;
+ t_outlet *x_rejectout;
+} t_route;
+
+static void route_anything(t_route *x, t_symbol *sel, int argc, t_atom *argv)
+{
+ t_routeelement *e;
+ int nelement;
+ if (x->x_type == A_SYMBOL)
+ {
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ if (e->e_w.w_symbol == sel)
+ {
+ if (argc > 0 && argv[0].a_type == A_SYMBOL)
+ outlet_anything(e->e_outlet, argv[0].a_w.w_symbol,
+ argc-1, argv+1);
+ else outlet_list(e->e_outlet, 0, argc, argv);
+ return;
+ }
+ }
+ outlet_anything(x->x_rejectout, sel, argc, argv);
+}
+
+static void route_list(t_route *x, t_symbol *sel, int argc, t_atom *argv)
+{
+ t_routeelement *e;
+ int nelement;
+ if (x->x_type == A_FLOAT)
+ {
+ float f;
+ if (!argc) return;
+ f = atom_getfloat(argv);
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ if (e->e_w.w_float == f)
+ {
+ if (argc > 1 && argv[1].a_type == A_SYMBOL)
+ outlet_anything(e->e_outlet, argv[1].a_w.w_symbol,
+ argc-2, argv+2);
+ else outlet_list(e->e_outlet, 0, argc-1, argv+1);
+ return;
+ }
+ }
+ else /* symbol arguments */
+ {
+ if (argc > 1) /* 2 or more args: treat as "list" */
+ {
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ {
+ if (e->e_w.w_symbol == &s_list)
+ {
+ if (argc > 0 && argv[0].a_type == A_SYMBOL)
+ outlet_anything(e->e_outlet, argv[0].a_w.w_symbol,
+ argc-1, argv+1);
+ else outlet_list(e->e_outlet, 0, argc, argv);
+ return;
+ }
+ }
+ }
+ else if (argc == 0) /* no args: treat as "bang" */
+ {
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ {
+ if (e->e_w.w_symbol == &s_bang)
+ {
+ outlet_bang(e->e_outlet);
+ return;
+ }
+ }
+ }
+ else if (argv[0].a_type == A_FLOAT) /* one float arg */
+ {
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ {
+ if (e->e_w.w_symbol == &s_float)
+ {
+ outlet_float(e->e_outlet, argv[0].a_w.w_float);
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (nelement = x->x_nelement, e = x->x_vec; nelement--; e++)
+ {
+ if (e->e_w.w_symbol == &s_symbol)
+ {
+ outlet_symbol(e->e_outlet, argv[0].a_w.w_symbol);
+ return;
+ }
+ }
+ }
+ }
+ outlet_list(x->x_rejectout, 0, argc, argv);
+}
+
+
+static void route_free(t_route *x)
+{
+ freebytes(x->x_vec, x->x_nelement * sizeof(*x->x_vec));
+}
+
+static void *route_new(t_symbol *s, int argc, t_atom *argv)
+{
+ int n;
+ t_routeelement *e;
+ t_route *x = (t_route *)pd_new(route_class);
+ t_atom a;
+ if (argc == 0)
+ {
+ argc = 1;
+ SETFLOAT(&a, 0);
+ argv = &a;
+ }
+ x->x_type = argv[0].a_type;
+ x->x_nelement = argc;
+ x->x_vec = (t_routeelement *)getbytes(argc * sizeof(*x->x_vec));
+ for (n = 0, e = x->x_vec; n < argc; n++, e++)
+ {
+ e->e_outlet = outlet_new(&x->x_obj, &s_list);
+ if (x->x_type == A_FLOAT)
+ e->e_w.w_float = atom_getfloatarg(n, argc, argv);
+ else e->e_w.w_symbol = atom_getsymbolarg(n, argc, argv);
+ }
+ x->x_rejectout = outlet_new(&x->x_obj, &s_list);
+ return (x);
+}
+
+void route_setup(void)
+{
+ route_class = class_new(gensym("route"), (t_newmethod)route_new,
+ (t_method)route_free, sizeof(t_route), 0, A_GIMME, 0);
+ class_addlist(route_class, route_list);
+ class_addanything(route_class, route_anything);
+}
+
+/* -------------------------- pack ------------------------------ */
+
+static t_class *pack_class;
+
+typedef struct _pack
+{
+ t_object x_obj;
+ t_int x_n; /* number of args */
+ t_atom *x_vec; /* input values */
+ t_int x_nptr; /* number of pointers */
+ t_gpointer *x_gpointer; /* the pointers */
+ t_atom *x_outvec; /* space for output values */
+} t_pack;
+
+static void *pack_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_pack *x = (t_pack *)pd_new(pack_class);
+ t_atom defarg[2], *ap, *vec, *vp;
+ t_gpointer *gp;
+ int nptr = 0;
+ int i;
+ if (!argc)
+ {
+ argv = defarg;
+ argc = 2;
+ SETFLOAT(&defarg[0], 0);
+ SETFLOAT(&defarg[1], 0);
+ }
+
+ x->x_n = argc;
+ vec = x->x_vec = (t_atom *)getbytes(argc * sizeof(*x->x_vec));
+ x->x_outvec = (t_atom *)getbytes(argc * sizeof(*x->x_outvec));
+
+ for (i = argc, ap = argv; i--; ap++)
+ if (ap->a_type == A_SYMBOL && *ap->a_w.w_symbol->s_name == 'p')
+ nptr++;
+
+ gp = x->x_gpointer = (t_gpointer *)t_getbytes(nptr * sizeof (*gp));
+ x->x_nptr = nptr;
+
+ for (i = 0, vp = x->x_vec, ap = argv; i < argc; i++, ap++, vp++)
+ {
+ if (ap->a_type == A_FLOAT)
+ {
+ *vp = *ap;
+ if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float);
+ }
+ else if (ap->a_type == A_SYMBOL)
+ {
+ char c = *ap->a_w.w_symbol->s_name;
+ if (c == 's')
+ {
+ SETSYMBOL(vp, &s_symbol);
+ if (i) symbolinlet_new(&x->x_obj, &vp->a_w.w_symbol);
+ }
+ else if (c == 'p')
+ {
+ vp->a_type = A_POINTER;
+ vp->a_w.w_gpointer = gp;
+ gpointer_init(gp);
+ if (i) pointerinlet_new(&x->x_obj, gp);
+ gp++;
+ }
+ else
+ {
+ if (c != 'f') pd_error(x, "pack: %s: bad type",
+ ap->a_w.w_symbol->s_name);
+ SETFLOAT(vp, 0);
+ if (i) floatinlet_new(&x->x_obj, &vp->a_w.w_float);
+ }
+ }
+ }
+ outlet_new(&x->x_obj, &s_list);
+ return (x);
+}
+
+static void pack_bang(t_pack *x)
+{
+ int i, reentered = 0, size = x->x_n * sizeof (t_atom);
+ t_gpointer *gp;
+ t_atom *outvec;
+ for (i = x->x_nptr, gp = x->x_gpointer; i--; gp++)
+ if (!gpointer_check(gp, 1))
+ {
+ pd_error(x, "pack: stale pointer");
+ return;
+ }
+ /* reentrancy protection. The first time through use the pre-allocated
+ x_outvec; if we're reentered we have to allocate new memory. */
+ if (!x->x_outvec)
+ {
+ /* LATER figure out how to deal with reentrancy and pointers... */
+ if (x->x_nptr)
+ post("pack_bang: warning: reentry with pointers unprotected");
+ outvec = t_getbytes(size);
+ reentered = 1;
+ }
+ else
+ {
+ outvec = x->x_outvec;
+ x->x_outvec = 0;
+ }
+ memcpy(outvec, x->x_vec, size);
+ outlet_list(x->x_obj.ob_outlet, &s_list, x->x_n, outvec);
+ if (reentered)
+ t_freebytes(outvec, size);
+ else x->x_outvec = outvec;
+}
+
+static void pack_pointer(t_pack *x, t_gpointer *gp)
+{
+ if (x->x_vec->a_type == A_POINTER)
+ {
+ gpointer_unset(x->x_gpointer);
+ *x->x_gpointer = *gp;
+ if (gp->gp_stub) gp->gp_stub->gs_refcount++;
+ pack_bang(x);
+ }
+ else pd_error(x, "pack_pointer: wrong type");
+}
+
+static void pack_float(t_pack *x, t_float f)
+{
+ if (x->x_vec->a_type == A_FLOAT)
+ {
+ x->x_vec->a_w.w_float = f;
+ pack_bang(x);
+ }
+ else pd_error(x, "pack_float: wrong type");
+}
+
+static void pack_symbol(t_pack *x, t_symbol *s)
+{
+ if (x->x_vec->a_type == A_SYMBOL)
+ {
+ x->x_vec->a_w.w_symbol = s;
+ pack_bang(x);
+ }
+ else pd_error(x, "pack_symbol: wrong type");
+}
+
+static void pack_list(t_pack *x, t_symbol *s, int ac, t_atom *av)
+{
+ obj_list(&x->x_obj, 0, ac, av);
+}
+
+static void pack_anything(t_pack *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom));
+ int i;
+ for (i = 0; i < ac; i++)
+ av2[i + 1] = av[i];
+ SETSYMBOL(av2, s);
+ obj_list(&x->x_obj, 0, ac+1, av2);
+ freebytes(av2, (ac + 1) * sizeof(t_atom));
+}
+
+static void pack_free(t_pack *x)
+{
+ t_gpointer *gp;
+ int i;
+ for (gp = x->x_gpointer, i = x->x_nptr; i--; gp++)
+ gpointer_unset(gp);
+ freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
+ freebytes(x->x_outvec, x->x_n * sizeof(*x->x_outvec));
+ freebytes(x->x_gpointer, x->x_nptr * sizeof(*x->x_gpointer));
+}
+
+static void pack_setup(void)
+{
+ pack_class = class_new(gensym("pack"), (t_newmethod)pack_new,
+ (t_method)pack_free, sizeof(t_pack), 0, A_GIMME, 0);
+ class_addbang(pack_class, pack_bang);
+ class_addpointer(pack_class, pack_pointer);
+ class_addfloat(pack_class, pack_float);
+ class_addsymbol(pack_class, pack_symbol);
+ class_addlist(pack_class, pack_list);
+ class_addanything(pack_class, pack_anything);
+}
+
+/* -------------------------- unpack ------------------------------ */
+
+static t_class *unpack_class;
+
+typedef struct unpackout
+{
+ t_atomtype u_type;
+ t_outlet *u_outlet;
+} t_unpackout;
+
+typedef struct _unpack
+{
+ t_object x_obj;
+ t_int x_n;
+ t_unpackout *x_vec;
+} t_unpack;
+
+static void *unpack_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_unpack *x = (t_unpack *)pd_new(unpack_class);
+ t_atom defarg[2], *ap;
+ t_unpackout *u;
+ int i;
+ if (!argc)
+ {
+ argv = defarg;
+ argc = 2;
+ SETFLOAT(&defarg[0], 0);
+ SETFLOAT(&defarg[1], 0);
+ }
+ x->x_n = argc;
+ x->x_vec = (t_unpackout *)getbytes(argc * sizeof(*x->x_vec));
+ for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++)
+ {
+ t_atomtype type = ap->a_type;
+ if (type == A_SYMBOL)
+ {
+ char c = *ap->a_w.w_symbol->s_name;
+ if (c == 's')
+ {
+ u->u_type = A_SYMBOL;
+ u->u_outlet = outlet_new(&x->x_obj, &s_symbol);
+ }
+ else if (c == 'p')
+ {
+ u->u_type = A_POINTER;
+ u->u_outlet = outlet_new(&x->x_obj, &s_pointer);
+ }
+ else
+ {
+ if (c != 'f') pd_error(x, "unpack: %s: bad type",
+ ap->a_w.w_symbol->s_name);
+ u->u_type = A_FLOAT;
+ u->u_outlet = outlet_new(&x->x_obj, &s_float);
+ }
+ }
+ else
+ {
+ u->u_type = A_FLOAT;
+ u->u_outlet = outlet_new(&x->x_obj, &s_float);
+ }
+ }
+ return (x);
+}
+
+static void unpack_list(t_unpack *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_atom *ap;
+ t_unpackout *u;
+ int i;
+ if (argc > x->x_n) argc = x->x_n;
+ for (i = argc, u = x->x_vec + i, ap = argv + i; u--, ap--, i--;)
+ {
+ t_atomtype type = u->u_type;
+ if (type != ap->a_type)
+ pd_error(x, "unpack: type mismatch");
+ else if (type == A_FLOAT)
+ outlet_float(u->u_outlet, ap->a_w.w_float);
+ else if (type == A_SYMBOL)
+ outlet_symbol(u->u_outlet, ap->a_w.w_symbol);
+ else outlet_pointer(u->u_outlet, ap->a_w.w_gpointer);
+ }
+}
+
+static void unpack_anything(t_unpack *x, t_symbol *s, int ac, t_atom *av)
+{
+ t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom));
+ int i;
+ for (i = 0; i < ac; i++)
+ av2[i + 1] = av[i];
+ SETSYMBOL(av2, s);
+ unpack_list(x, 0, ac+1, av2);
+ freebytes(av2, (ac + 1) * sizeof(t_atom));
+}
+
+static void unpack_free(t_unpack *x)
+{
+ freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
+}
+
+static void unpack_setup(void)
+{
+ unpack_class = class_new(gensym("unpack"), (t_newmethod)unpack_new,
+ (t_method)unpack_free, sizeof(t_unpack), 0, A_GIMME, 0);
+ class_addlist(unpack_class, unpack_list);
+ class_addanything(unpack_class, unpack_anything);
+}
+
+/* -------------------------- trigger ------------------------------ */
+
+static t_class *trigger_class;
+#define TR_BANG 0
+#define TR_FLOAT 1
+#define TR_SYMBOL 2
+#define TR_POINTER 3
+#define TR_LIST 4
+#define TR_ANYTHING 5
+
+typedef struct triggerout
+{
+ int u_type; /* outlet type from above */
+ t_outlet *u_outlet;
+} t_triggerout;
+
+typedef struct _trigger
+{
+ t_object x_obj;
+ t_int x_n;
+ t_triggerout *x_vec;
+} t_trigger;
+
+static void *trigger_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_trigger *x = (t_trigger *)pd_new(trigger_class);
+ t_atom defarg[2], *ap;
+ t_triggerout *u;
+ int i;
+ if (!argc)
+ {
+ argv = defarg;
+ argc = 2;
+ SETSYMBOL(&defarg[0], &s_bang);
+ SETSYMBOL(&defarg[1], &s_bang);
+ }
+ x->x_n = argc;
+ x->x_vec = (t_triggerout *)getbytes(argc * sizeof(*x->x_vec));
+ for (i = 0, ap = argv, u = x->x_vec; i < argc; u++, ap++, i++)
+ {
+ t_atomtype thistype = ap->a_type;
+ char c;
+ if (thistype == TR_SYMBOL) c = ap->a_w.w_symbol->s_name[0];
+ else if (thistype == TR_FLOAT) c = 'f';
+ else c = 0;
+ if (c == 'p')
+ u->u_type = TR_POINTER,
+ u->u_outlet = outlet_new(&x->x_obj, &s_pointer);
+ else if (c == 'f')
+ u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float);
+ else if (c == 'b')
+ u->u_type = TR_BANG, u->u_outlet = outlet_new(&x->x_obj, &s_bang);
+ else if (c == 'l')
+ u->u_type = TR_LIST, u->u_outlet = outlet_new(&x->x_obj, &s_list);
+ else if (c == 's')
+ u->u_type = TR_SYMBOL,
+ u->u_outlet = outlet_new(&x->x_obj, &s_symbol);
+ else if (c == 'a')
+ u->u_type = TR_ANYTHING,
+ u->u_outlet = outlet_new(&x->x_obj, &s_symbol);
+ else
+ {
+ pd_error(x, "trigger: %s: bad type", ap->a_w.w_symbol->s_name);
+ u->u_type = TR_FLOAT, u->u_outlet = outlet_new(&x->x_obj, &s_float);
+ }
+ }
+ return (x);
+}
+
+static void trigger_list(t_trigger *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_triggerout *u;
+ int i;
+ t_atom at;
+ if (!argc)
+ {
+ argc = 1;
+ SETFLOAT(&at, 0);
+ argv = &at;
+ }
+ for (i = x->x_n, u = x->x_vec + i; u--, i--;)
+ {
+ if (u->u_type == TR_FLOAT)
+ outlet_float(u->u_outlet, atom_getfloat(argv));
+ else if (u->u_type == TR_BANG)
+ outlet_bang(u->u_outlet);
+ else if (u->u_type == TR_SYMBOL)
+ outlet_symbol(u->u_outlet, atom_getsymbol(argv));
+ else if (u->u_type == TR_POINTER)
+ {
+ if (argv->a_type != TR_POINTER)
+ pd_error(x, "unpack: bad pointer");
+ else outlet_pointer(u->u_outlet, argv->a_w.w_gpointer);
+ }
+ else outlet_list(u->u_outlet, &s_list, argc, argv);
+ }
+}
+
+static void trigger_anything(t_trigger *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_triggerout *u;
+ int i;
+ for (i = x->x_n, u = x->x_vec + i; u--, i--;)
+ {
+ if (u->u_type == TR_BANG)
+ outlet_bang(u->u_outlet);
+ else if (u->u_type == TR_ANYTHING)
+ outlet_anything(u->u_outlet, s, argc, argv);
+ else pd_error(x, "trigger: can only convert 's' to 'b' or 'a'",
+ s->s_name);
+ }
+}
+
+static void trigger_bang(t_trigger *x)
+{
+ trigger_list(x, 0, 0, 0);
+}
+
+static void trigger_pointer(t_trigger *x, t_gpointer *gp)
+{
+ t_atom at;
+ SETPOINTER(&at, gp);
+ trigger_list(x, 0, 1, &at);
+}
+
+static void trigger_float(t_trigger *x, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ trigger_list(x, 0, 1, &at);
+}
+
+static void trigger_symbol(t_trigger *x, t_symbol *s)
+{
+ t_atom at;
+ SETSYMBOL(&at, s);
+ trigger_list(x, 0, 1, &at);
+}
+
+static void trigger_free(t_trigger *x)
+{
+ freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec));
+}
+
+static void trigger_setup(void)
+{
+ trigger_class = class_new(gensym("trigger"), (t_newmethod)trigger_new,
+ (t_method)trigger_free, sizeof(t_trigger), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)trigger_new, gensym("t"), A_GIMME, 0);
+ class_addlist(trigger_class, trigger_list);
+ class_addbang(trigger_class, trigger_bang);
+ class_addpointer(trigger_class, trigger_pointer);
+ class_addfloat(trigger_class, (t_method)trigger_float);
+ class_addsymbol(trigger_class, trigger_symbol);
+ class_addanything(trigger_class, trigger_anything);
+}
+
+/* -------------------------- spigot ------------------------------ */
+static t_class *spigot_class;
+
+typedef struct _spigot
+{
+ t_object x_obj;
+ float x_state;
+} t_spigot;
+
+static void *spigot_new(void)
+{
+ t_spigot *x = (t_spigot *)pd_new(spigot_class);
+ floatinlet_new(&x->x_obj, &x->x_state);
+ outlet_new(&x->x_obj, 0);
+ x->x_state = 0;
+ return (x);
+}
+
+static void spigot_bang(t_spigot *x)
+{
+ if (x->x_state != 0) outlet_bang(x->x_obj.ob_outlet);
+}
+
+static void spigot_pointer(t_spigot *x, t_gpointer *gp)
+{
+ if (x->x_state != 0) outlet_pointer(x->x_obj.ob_outlet, gp);
+}
+
+static void spigot_float(t_spigot *x, t_float f)
+{
+ if (x->x_state != 0) outlet_float(x->x_obj.ob_outlet, f);
+}
+
+static void spigot_symbol(t_spigot *x, t_symbol *s)
+{
+ if (x->x_state != 0) outlet_symbol(x->x_obj.ob_outlet, s);
+}
+
+static void spigot_list(t_spigot *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (x->x_state != 0) outlet_list(x->x_obj.ob_outlet, s, argc, argv);
+}
+
+static void spigot_anything(t_spigot *x, t_symbol *s, int argc, t_atom *argv)
+{
+ if (x->x_state != 0) outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
+}
+
+static void spigot_setup(void)
+{
+ spigot_class = class_new(gensym("spigot"), (t_newmethod)spigot_new, 0,
+ sizeof(t_spigot), 0, A_DEFSYM, 0);
+ class_addbang(spigot_class, spigot_bang);
+ class_addpointer(spigot_class, spigot_pointer);
+ class_addfloat(spigot_class, spigot_float);
+ class_addsymbol(spigot_class, spigot_symbol);
+ class_addlist(spigot_class, spigot_list);
+ class_addanything(spigot_class, spigot_anything);
+}
+
+/* --------------------------- moses ----------------------------- */
+static t_class *moses_class;
+
+typedef struct _moses
+{
+ t_object x_ob;
+ t_outlet *x_out2;
+ float x_y;
+} t_moses;
+
+static void *moses_new(t_floatarg f)
+{
+ t_moses *x = (t_moses *)pd_new(moses_class);
+ floatinlet_new(&x->x_ob, &x->x_y);
+ outlet_new(&x->x_ob, &s_float);
+ x->x_out2 = outlet_new(&x->x_ob, &s_float);
+ x->x_y = f;
+ return (x);
+}
+
+static void moses_float(t_moses *x, t_float f)
+{
+ if (f < x->x_y) outlet_float(x->x_ob.ob_outlet, f);
+ else outlet_float(x->x_out2, f);
+}
+
+static void moses_setup(void)
+{
+ moses_class = class_new(gensym("moses"), (t_newmethod)moses_new, 0,
+ sizeof(t_moses), 0, A_DEFFLOAT, 0);
+ class_addfloat(moses_class, moses_float);
+}
+
+/* ----------------------- until --------------------- */
+
+static t_class *until_class;
+
+typedef struct _until
+{
+ t_object x_obj;
+ int x_run;
+ int x_count;
+} t_until;
+
+static void *until_new(void)
+{
+ t_until *x = (t_until *)pd_new(until_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("bang"), gensym("bang2"));
+ outlet_new(&x->x_obj, &s_bang);
+ x->x_run = 0;
+ return (x);
+}
+
+static void until_bang(t_until *x)
+{
+ x->x_run = 1;
+ x->x_count = -1;
+ while (x->x_run && x->x_count)
+ x->x_count--, outlet_bang(x->x_obj.ob_outlet);
+}
+
+static void until_float(t_until *x, t_float f)
+{
+ x->x_run = 1;
+ x->x_count = f;
+ while (x->x_run && x->x_count)
+ x->x_count--, outlet_bang(x->x_obj.ob_outlet);
+}
+
+static void until_bang2(t_until *x)
+{
+ x->x_run = 0;
+}
+
+static void until_setup(void)
+{
+ until_class = class_new(gensym("until"), (t_newmethod)until_new, 0,
+ sizeof(t_until), 0, 0);
+ class_addbang(until_class, until_bang);
+ class_addfloat(until_class, until_float);
+ class_addmethod(until_class, (t_method)until_bang2, gensym("bang2"), 0);
+}
+
+/* ----------------------- makefilename --------------------- */
+
+static t_class *makefilename_class;
+
+typedef struct _makefilename
+{
+ t_object x_obj;
+ t_symbol *x_format;
+} t_makefilename;
+
+static void *makefilename_new(t_symbol *s)
+{
+ t_makefilename *x = (t_makefilename *)pd_new(makefilename_class);
+ if (!s->s_name) s = gensym("file.%d");
+ outlet_new(&x->x_obj, &s_symbol);
+ x->x_format = s;
+ return (x);
+}
+
+static void makefilename_float(t_makefilename *x, t_floatarg f)
+{
+ char buf[MAXPDSTRING];
+ sprintf(buf, x->x_format->s_name, (int)f);
+ outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
+}
+
+static void makefilename_symbol(t_makefilename *x, t_symbol *s)
+{
+ char buf[MAXPDSTRING];
+ sprintf(buf, x->x_format->s_name, s->s_name);
+ outlet_symbol(x->x_obj.ob_outlet, gensym(buf));
+}
+
+static void makefilename_setup(void)
+{
+ makefilename_class = class_new(gensym("makefilename"),
+ (t_newmethod)makefilename_new, 0,
+ sizeof(t_makefilename), 0, A_DEFSYM, 0);
+ class_addfloat(makefilename_class, makefilename_float);
+ class_addsymbol(makefilename_class, makefilename_symbol);
+}
+
+/* -------------------------- swap ------------------------------ */
+static t_class *swap_class;
+
+typedef struct _swap
+{
+ t_object x_obj;
+ t_outlet *x_out2;
+ t_float x_f1;
+ t_float x_f2;
+} t_swap;
+
+static void *swap_new(t_floatarg f)
+{
+ t_swap *x = (t_swap *)pd_new(swap_class);
+ x->x_f2 = f;
+ x->x_f1 = 0;
+ outlet_new(&x->x_obj, &s_float);
+ x->x_out2 = outlet_new(&x->x_obj, &s_float);
+ floatinlet_new(&x->x_obj, &x->x_f2);
+ return (x);
+}
+
+static void swap_bang(t_swap *x)
+{
+ outlet_float(x->x_out2, x->x_f1);
+ outlet_float(x->x_obj.ob_outlet, x->x_f2);
+}
+
+static void swap_float(t_swap *x, t_float f)
+{
+ x->x_f1 = f;
+ swap_bang(x);
+}
+
+void swap_setup(void)
+{
+ swap_class = class_new(gensym("swap"), (t_newmethod)swap_new, 0,
+ sizeof(t_swap), 0, A_DEFFLOAT, 0);
+ class_addcreator((t_newmethod)swap_new, gensym("fswap"), A_DEFFLOAT, 0);
+ class_addbang(swap_class, swap_bang);
+ class_addfloat(swap_class, swap_float);
+}
+
+/* -------------------------- change ------------------------------ */
+static t_class *change_class;
+
+typedef struct _change
+{
+ t_object x_obj;
+ t_float x_f;
+} t_change;
+
+static void *change_new(t_floatarg f)
+{
+ t_change *x = (t_change *)pd_new(change_class);
+ x->x_f = f;
+ outlet_new(&x->x_obj, &s_float);
+ return (x);
+}
+
+static void change_bang(t_change *x)
+{
+ outlet_float(x->x_obj.ob_outlet, x->x_f);
+}
+
+static void change_float(t_change *x, t_float f)
+{
+ if (f != x->x_f)
+ {
+ x->x_f = f;
+ outlet_float(x->x_obj.ob_outlet, x->x_f);
+ }
+}
+
+static void change_set(t_change *x, t_float f)
+{
+ x->x_f = f;
+}
+
+void change_setup(void)
+{
+ change_class = class_new(gensym("change"), (t_newmethod)change_new, 0,
+ sizeof(t_change), 0, A_DEFFLOAT, 0);
+ class_addbang(change_class, change_bang);
+ class_addfloat(change_class, change_float);
+ class_addmethod(change_class, (t_method)change_set, gensym("set"),
+ A_DEFFLOAT, 0);
+}
+
+/* -------------------- value ------------------------------ */
+
+static t_class *value_class, *vcommon_class;
+
+typedef struct vcommon
+{
+ t_pd c_pd;
+ int c_refcount;
+ t_float c_f;
+} t_vcommon;
+
+typedef struct _value
+{
+ t_object x_obj;
+ t_symbol *x_sym;
+ t_float *x_floatstar;
+} t_value;
+
+ /* get a pointer to a named floating-point variable. The variable
+ belongs to a "vcommon" object, which is created if necessary. */
+t_float *value_get(t_symbol *s)
+{
+ t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
+ if (!c)
+ {
+ c = (t_vcommon *)pd_new(vcommon_class);
+ c->c_f = 0;
+ c->c_refcount = 0;
+ pd_bind(&c->c_pd, s);
+ }
+ c->c_refcount++;
+ return (&c->c_f);
+}
+
+ /* release a variable. This only frees the "vcommon" resource when the
+ last interested party releases it. */
+void value_release(t_symbol *s)
+{
+ t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
+ if (c)
+ {
+ if (!--c->c_refcount)
+ {
+ pd_unbind(&c->c_pd, s);
+ pd_free(&c->c_pd);
+ }
+ }
+ else bug("value_release");
+}
+
+/*
+ * value_getfloat -- obtain the float value of a "value" object
+ * return 0 on success, 1 otherwise
+ */
+int
+value_getfloat(t_symbol *s, t_float *f)
+{
+ t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
+ if (!c)
+ return (1);
+ *f = c->c_f;
+ return (0);
+}
+
+/*
+ * value_setfloat -- set the float value of a "value" object
+ * return 0 on success, 1 otherwise
+ */
+int
+value_setfloat(t_symbol *s, t_float f)
+{
+ t_vcommon *c = (t_vcommon *)pd_findbyclass(s, vcommon_class);
+ if (!c)
+ return (1);
+ c->c_f = f;
+ return (0);
+}
+
+static void *value_new(t_symbol *s)
+{
+ t_value *x = (t_value *)pd_new(value_class);
+ x->x_sym = s;
+ x->x_floatstar = value_get(s);
+ outlet_new(&x->x_obj, &s_float);
+ return (x);
+}
+
+static void value_bang(t_value *x)
+{
+ outlet_float(x->x_obj.ob_outlet, *x->x_floatstar);
+}
+
+static void value_float(t_value *x, t_float f)
+{
+ *x->x_floatstar = f;
+}
+
+static void value_ff(t_value *x)
+{
+ value_release(x->x_sym);
+}
+
+static void value_setup(void)
+{
+ value_class = class_new(gensym("value"), (t_newmethod)value_new,
+ (t_method)value_ff,
+ sizeof(t_value), 0, A_DEFSYM, 0);
+ class_addcreator((t_newmethod)value_new, gensym("v"), A_DEFSYM, 0);
+ class_addbang(value_class, value_bang);
+ class_addfloat(value_class, value_float);
+ vcommon_class = class_new(gensym("value"), 0, 0,
+ sizeof(t_vcommon), CLASS_PD, 0);
+}
+
+/* -------------- overall setup routine for this file ----------------- */
+
+void x_connective_setup(void)
+{
+ pdint_setup();
+ pdfloat_setup();
+ pdsymbol_setup();
+ bang_setup();
+ send_setup();
+ receive_setup();
+ select_setup();
+ route_setup();
+ pack_setup();
+ unpack_setup();
+ trigger_setup();
+ spigot_setup();
+ moses_setup();
+ until_setup();
+ makefilename_setup();
+ swap_setup();
+ change_setup();
+ value_setup();
+}