/* Copyright (c) 2003-2005 krzYszcz and others. * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ #include #include "m_pd.h" #include "unstable/fragile.h" #include "common/loud.h" #include "toxy/plusbob.h" #include "plustot.h" #ifdef KRZYSZCZ #define PLUSTOT_QLIST_DEBUG #endif /* Need only an access to x_binbuf field. */ typedef struct _qlist { t_object x_ob; t_outlet *x_bangout; void *x_binbuf; } t_qlist; typedef struct _plusproxy_qlist { t_pd pp_pd; struct _plustot_qlist *pp_master; } t_plusproxy_qlist; typedef struct _plustot_qlist { t_plusobject x_plusobject; t_glist *x_glist; t_plustob *x_tob; t_outlet *x_rightout; t_plusproxy_qlist *x_proxy; } t_plustot_qlist; static t_class *plusproxy_qlist_class; static t_class *plustot_qlist_class; static t_binbuf *plustot_qlist_usurp(t_plustot_qlist *x) { static t_symbol *types[2]; static int ntypes = 0; t_object *booty; if (ntypes == 0) { types[0] = gensym("qlist"); types[1] = gensym("textfile"); ntypes = 2; } if (booty = fragile_outlet_destination( ((t_object *)x)->ob_outlet, ntypes, types, (t_pd *)x, "(connect left outlet to a qlist or textfile)")) { t_binbuf *bb = ((t_qlist *)booty)->x_binbuf; #ifdef PLUSTOT_QLIST_DEBUG loudbug_post("booty '%s' at %x:", class_getname(*(t_pd *)booty), (int)booty); loudbug_postbinbuf(bb); #endif return (bb); } else return (0); } static t_plusproxy_qlist *plusproxy_qlist_new(t_plustot_qlist *master) { t_plusproxy_qlist *pp = (t_plusproxy_qlist *)pd_new(plusproxy_qlist_class); pp->pp_master = master; return (pp); } static void plusproxy_qlist_symbol(t_plusproxy_qlist *pp, t_symbol *s) { t_plustot_qlist *x = pp->pp_master; Tcl_Interp *interp = 0; if (plustag_isvalid(s, 0)) { t_plustin *tin; Tcl_Obj *ob; if ((tin = plustag_tobtin(s, PLUSBOB_OWNER)) && (ob = plustob_getvalue((t_plustob *)s))) { t_binbuf *bb; if (bb = plustot_qlist_usurp(x)) { int nlists; Tcl_Obj **lists; interp = plustin_getinterp(tin); if (Tcl_ListObjGetElements(interp, ob, &nlists, &lists) == TCL_OK) { int lc; Tcl_Obj **lp; binbuf_clear(bb); for (lc = 0, lp = lists; lc < nlists; lc++, lp++) { int natoms; Tcl_Obj **atoms; if (Tcl_ListObjGetElements(interp, *lp, &natoms, &atoms) == TCL_OK) { int ac; Tcl_Obj **ap; for (ac = 0, ap = atoms; ac < natoms; ac++, ap++) { double d; int len; char *ptr; Tcl_IncrRefCount(*ap); if (Tcl_GetDoubleFromObj(interp, *ap, &d) == TCL_OK) { t_atom at; SETFLOAT(&at, (float)d); binbuf_add(bb, 1, &at); } else if ((ptr = Tcl_GetStringFromObj(*ap, &len)) && len) { t_atom at; if (ptr[len - 1]) { char buf[MAXPDSTRING]; if (len > MAXPDSTRING - 1) len = MAXPDSTRING - 1; strncpy(buf, ptr, len); buf[len] = 0; ptr = buf; } SETSYMBOL(&at, gensym(ptr)); binbuf_add(bb, 1, &at); } /* FIXME else */ Tcl_DecrRefCount(*ap); } binbuf_addsemi(bb); } else { binbuf_clear(bb); goto notalist; } } } else goto notalist; } } } return; notalist: if (interp) plusloud_tclerror((t_pd *)x, interp, "not a list"); } static void plustot_qlist_bang(t_plustot_qlist *x) { t_binbuf *bb; if (bb = plustot_qlist_usurp(x)) { if (plustob_setbinbuf(x->x_tob, bb)) outlet_plusbob(x->x_rightout, (t_plusbob *)x->x_tob); } } static void plustot_qlist_free(t_plustot_qlist *x) { plusbob_release((t_plusbob *)x->x_tob); if (x->x_proxy) pd_free((t_pd *)x->x_proxy); plusobject_free(&x->x_plusobject); } void *plustot_qlist_new(t_symbol *s, int ac, t_atom *av) { t_plustot_qlist *x = 0; t_glist *glist = canvas_getcurrent(); t_plustin *tin = 0; t_plustob *tob = 0; if ((tin = plustin_glistprovide(glist, PLUSTIN_GLIST_ANY, 0)) && (tob = plustob_new(tin, 0))) { x = (t_plustot_qlist *) plusobject_new(plustot_qlist_class, s, ac, av, 0); plusbob_preserve((t_plusbob *)tob); plusbob_setowner((t_plusbob *)tob, (t_pd *)x); plustob_setlist(tob, ac, av); x->x_glist = glist; x->x_tob = tob; x->x_proxy = plusproxy_qlist_new(x); plusinlet_new(&x->x_plusobject, (t_pd *)x->x_proxy, 0, 0); plusoutlet_new(&x->x_plusobject, &s_anything); x->x_rightout = outlet_new((t_object *)x, &s_symbol); } else { loud_error(0, "+qlist: cannot initialize"); if (tin) { plusbob_preserve((t_plusbob *)tin); plusbob_release((t_plusbob *)tin); } } return (x); } void plustot_qlist_setup(void) { plustot_qlist_class = class_new(gensym("+qlist"), 0, (t_method)plustot_qlist_free, sizeof(t_plustot_qlist), 0, 0); plusclass_inherit(plustot_qlist_class, gensym("+qlist")); class_addbang(plustot_qlist_class, plustot_qlist_bang); plusproxy_qlist_class = class_new(gensym("+qlist proxy"), 0, 0, sizeof(t_plusproxy_qlist), CLASS_PD, 0); class_addsymbol(plusproxy_qlist_class, plusproxy_qlist_symbol); }