/* Copyright (C) 2003 Antoine Rousseau This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* a shared symbol array, ala "value" .*/ #include "m_pd.h" #include #include #include static t_class *dispatch_class, *dispsnd_class; static t_symbol *s__; typedef struct _dispatch t_dispatch; typedef struct dispsnd { t_pd d_pd; t_symbol *d_eachsnd; t_symbol *d_allsnd; t_int d_num; } t_dispsnd; struct _dispatch { t_object x_obj; t_symbol *x_sym; int x_from; int x_to; t_dispsnd **x_snds; t_symbol *x_allrcv; t_symbol **x_eachrcvs; }; /*--------------------- dispsnd ------------------------------------*/ static void dispsnd_ff(t_dispsnd *x) { pd_unbind((t_pd *)x, x->d_eachsnd); } static void *dispsnd_new(t_symbol *eachsnd,t_symbol *allsnd,int num) { t_dispsnd *x = (t_dispsnd *)pd_new(dispsnd_class); //post("new dispsnd: num=%d rcv=%s snd=%s",num,eachsnd->s_name,allsnd->s_name); x->d_eachsnd=eachsnd; x->d_allsnd=allsnd; x->d_num=num; pd_bind((t_pd *)x, x->d_eachsnd); return (x); } static void dispsnd_float(t_dispsnd *x, t_float f) { t_atom out[2]; if (x->d_allsnd->s_thing) { SETFLOAT(&out[0],x->d_num); SETFLOAT(&out[1],f); typedmess(x->d_allsnd->s_thing, &s_list, 2, out); } } static void dispsnd_anything(t_dispsnd *x, t_symbol *s, int argc, t_atom *argv) { t_atom *out; if (x->d_allsnd->s_thing) { out = (t_atom *)getbytes(sizeof(t_atom)*(argc+2)); memcpy(&out[2], argv, argc*sizeof(t_atom)); SETFLOAT(&out[0],x->d_num); SETSYMBOL(&out[1],s); typedmess(x->d_allsnd->s_thing, &s_list, argc+2, out); freebytes(out, sizeof(t_atom)*(argc+2)); } } /*--------------------- dispatch ------------------------------------*/ static void *dispatch_new(t_symbol *s,t_float from,t_float to) { int i,len; t_dispatch *x = (t_dispatch *)pd_new(dispatch_class); char str[512]; t_symbol *allsnd,*eachsnd; x->x_snds=0; x->x_sym = s; x->x_from = from; x->x_to = to; len=x->x_to-x->x_from+1; if(len>0) { sprintf(str,"%s-snd",x->x_sym->s_name); allsnd=gensym(str); sprintf(str,"%s-rcv",x->x_sym->s_name); x->x_allrcv=gensym(str); pd_bind((t_pd *)x, x->x_allrcv); x->x_snds=getbytes(len*sizeof(t_dispsnd *)); x->x_eachrcvs=getbytes(len*sizeof(t_symbol *)); for(i=0; ix_sym->s_name,i+x->x_from); eachsnd=gensym(str); x->x_snds[i]=dispsnd_new(eachsnd,allsnd,i+x->x_from); sprintf(str,"%s%d-rcv",x->x_sym->s_name,i+x->x_from); x->x_eachrcvs[i]=gensym(str); } } return (x); } static void dispatch_ff(t_dispatch *x) { int i,len=x->x_to-x->x_from+1; if(len<=0) return; pd_unbind((t_pd *)x, x->x_allrcv); for(i=0; ix_snds[i]); freebytes(x->x_snds,len*sizeof(t_dispsnd *)); freebytes(x->x_eachrcvs,len*sizeof(t_symbol *)); } static void dispatch_list(t_dispatch *x, t_symbol *s, int argc, t_atom *argv) { int num; if((!argc)|(argv[0].a_type!=A_FLOAT)) { error("dispatch: bad list format"); return; } num=atom_getint(&argv[0]); if((numx_from)|(num>x->x_to)) { //error("dispatch: bad num"); return; } if (x->x_eachrcvs[num-x->x_from]->s_thing) pd_forwardmess(x->x_eachrcvs[num-x->x_from]->s_thing, argc-1, argv+1); } /*--------------------------------------------------------------*/ void dispatch_setup(void) { dispatch_class = class_new(gensym("dispatch"), (t_newmethod)dispatch_new, (t_method)dispatch_ff, sizeof(t_dispatch), 0, A_SYMBOL, A_FLOAT, A_FLOAT,0); class_addlist(dispatch_class, dispatch_list); dispsnd_class = class_new(gensym("dispatch"), 0, (t_method)dispsnd_ff, sizeof(t_dispsnd), CLASS_PD, 0); class_addanything(dispsnd_class, dispsnd_anything); class_addfloat(dispsnd_class, dispsnd_float); }