/* 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 #include 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(); }