From 5c23ba319e78d959c4361ce1d08e8264f5215980 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 23 Sep 2002 18:46:26 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r149, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/olafmatt/; revision=150 --- clone/abstraction.pd | 40 +++ clone/clone.c | 803 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 843 insertions(+) create mode 100644 clone/abstraction.pd create mode 100644 clone/clone.c (limited to 'clone') diff --git a/clone/abstraction.pd b/clone/abstraction.pd new file mode 100644 index 0000000..ac28a1e --- /dev/null +++ b/clone/abstraction.pd @@ -0,0 +1,40 @@ +#N canvas 280 62 707 469 12; +#X obj 219 108 inlet; +#X obj 177 399 outlet; +#X floatatom 410 269 5 0 0; +#X obj 410 227 float \$0; +#X text 118 38 but \$1 is always the number of the current instance +!; +#X text 118 56 \$0 works as usual; +#X text 117 20 you can get the creation arguments with \$2 \, \$3 ... +as usual; +#X floatatom 495 268 5 0 0; +#X floatatom 580 266 5 0 0; +#X obj 580 224 float \$2; +#X obj 495 225 float \$1; +#X obj 177 257 float \$1; +#X obj 177 348 pack f f; +#X obj 284 225 float \$1; +#X obj 249 258 * 1; +#X obj 219 178 t b f b; +#X obj 40 398 outlet~; +#X obj 40 309 osc~ 440; +#X obj 40 359 *~ 0.125; +#X obj 422 140 loadbang; +#X connect 0 0 15 0; +#X connect 3 0 2 0; +#X connect 9 0 8 0; +#X connect 10 0 7 0; +#X connect 11 0 12 0; +#X connect 12 0 1 0; +#X connect 13 0 14 1; +#X connect 14 0 12 1; +#X connect 14 0 17 0; +#X connect 15 0 11 0; +#X connect 15 1 14 0; +#X connect 15 2 13 0; +#X connect 17 0 18 0; +#X connect 18 0 16 0; +#X connect 19 0 3 0; +#X connect 19 0 10 0; +#X connect 19 0 9 0; diff --git a/clone/clone.c b/clone/clone.c new file mode 100644 index 0000000..e477ced --- /dev/null +++ b/clone/clone.c @@ -0,0 +1,803 @@ +/* ------------------------- clone ------------------------------------------ */ +/* */ +/* clone :: abstraction cloner object */ +/* Written by Olaf Matthes */ +/* Based on rabin~ by Krzysztof Czaja. */ +/* Get source at http://www.akustische-kunst.org/puredata/maxlib/ */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program 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 General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +/* */ +/* Based on PureData by Miller Puckette and others. */ +/* */ +/* ---------------------------------------------------------------------------- */ + +#include "m_imp.h" +#include "g_canvas.h" +#include "clone.h" + +#ifdef NT +#include +#else +#include +#endif +#include +#include + +#define MAXINOUT 256 /* maximum number of control inlets / outlets */ +#define MAXSIGINOUT 8 /* maximum number of signal inlets / outlets */ + +static char *version = "clone v0.0.6, written by Olaf Matthes \n" + " based on rabin~ by Krzysztof Czaja"; + +static t_class *clone_class; +static t_class *clone_rcv_class; +static t_class *clone_snd_class; +extern t_class *clone_in_class; +extern t_class *clone_sigin_class; +extern t_class *clone_out_class; +extern t_class *clone_sigout_class; + +int ncloneinstance = 0; /* number of instances of 'clone' */ + +typedef struct _cloneelement +{ + struct _clone *e_owner; + t_canvas *e_ab; + t_pd *e_target[MAXINOUT]; +} t_cloneelement; + +typedef struct _clone +{ + t_object x_obj; + t_outlet *x_outlet[MAXINOUT]; + t_outlet *x_rejectout; + + t_glist *x_glist; /* parent glist */ + int x_vectorsize; /* signal vector size */ + t_float *x_catchvec[MAXSIGINOUT]; /* signal vector */ + t_float *x_throwvec[MAXSIGINOUT]; /* signal vector */ + t_symbol *x_name; /* .pd file name */ + t_symbol *x_dir; /* file directory */ + t_symbol *x_rcvname[MAXINOUT]; /* our internal receive names */ + int x_argc; /* number of creation arguments (incl. inst. no.) */ + t_atom *x_argv; /* the creation arguments + prepended instance number */ + t_binbuf *x_binbuf; /* file contents */ + int x_nelems; /* number of instances we've created */ + t_int x_nin; /* number of control inlets */ + t_int x_nsigin; /* number of signal inlets */ + t_int x_nout; /* number of control outlets */ + t_int x_nsigout; /* number of signal outlets */ + int x_tablesize; /* as allocated */ + t_cloneelement *x_table; + t_float x_float; +} t_clone; + +typedef struct _clone_rcv +{ + t_object r_obj; + t_clone *r_owner; + t_int r_index; /* number of outlet */ +} t_clone_rcv; + +typedef struct _clone_snd +{ + t_object s_obj; + t_clone *s_owner; + t_int s_index; /* number of inlet */ +} t_clone_snd; + + +/* ------------------- stuff to handle the abstractions ---------------------- */ + +static t_symbol *clone_s_inlet, *clone_s_siginlet, + *clone_s_outlet, *clone_s_sigoutlet, + *clone_s_in, *clone_s_sigin, + *clone_s_out, *clone_s_sigout; + +static void clone_setup_symbols(void) +{ + clone_s_inlet = gensym("inlet"); + clone_s_siginlet = gensym("inlet~"); + clone_s_outlet = gensym("outlet"); + clone_s_sigoutlet = gensym("outlet~"); + clone_s_in = gensym("clonein"); + clone_s_sigin = gensym("clonein~"); + clone_s_out = gensym("cloneout"); + clone_s_sigout = gensym("cloneout~"); +} + +static void clone_inout_premapping(t_atom *ap) +{ + if (ap->a_type == A_SYMBOL) + { + if (ap->a_w.w_symbol == clone_s_inlet) + SETSYMBOL(ap, clone_s_in); + else if (ap->a_w.w_symbol == clone_s_siginlet) + SETSYMBOL(ap, clone_s_sigin); + else if (ap->a_w.w_symbol == clone_s_outlet) + SETSYMBOL(ap, clone_s_out); + else if (ap->a_w.w_symbol == clone_s_sigoutlet) + SETSYMBOL(ap, clone_s_sigout); + } +} + +static void clone_inout_postmapping(t_atom *ap) +{ + if (ap->a_type == A_SYMBOL) + { + if (ap->a_w.w_symbol == clone_s_in) + SETSYMBOL(ap, clone_s_inlet); + else if (ap->a_w.w_symbol == clone_s_sigin) + SETSYMBOL(ap, clone_s_siginlet); + else if (ap->a_w.w_symbol == clone_s_out) + SETSYMBOL(ap, clone_s_outlet); + else if (ap->a_w.w_symbol == clone_s_sigout) + SETSYMBOL(ap, clone_s_sigoutlet); + } +} + + /* canvas_popabstraction() */ +static t_canvas *clone_popabstraction(t_pd *x) +{ + t_canvas *cv = (t_canvas *)x; + pd_popsym(x); /* same as canvas_unsetcurrent() */ + cv->gl_loading = 0; + canvas_resortinlets(cv); + canvas_resortoutlets(cv); + return (cv); /* or 0, when we add a check */ +} + +static void clone_instance_init(t_clone *x, t_cloneelement *ep, t_pd *y, int instance) +{ + if (ep->e_ab = clone_popabstraction(y)) + { + t_gobj *g; + ep->e_owner = x; + x->x_nin = x->x_nsigin = x->x_nout = x->x_nsigout = 0; + for (g = ep->e_ab->gl_list; g; g = g->g_next) + { + if (g->g_pd == clone_in_class) + ep->e_target[x->x_nin++] = (t_pd *)g; + else if (g->g_pd == clone_sigin_class) + clone_sigin_set((t_clone_sigin *)g, x->x_vectorsize, x->x_throwvec[x->x_nsigin++]); + else if (g->g_pd == clone_out_class) + clone_out_set((t_clone_out *)g, instance, x->x_rcvname[x->x_nout++]); + else if (g->g_pd == clone_sigout_class) + clone_sigout_set((t_clone_sigout *)g, x->x_vectorsize, x->x_catchvec[x->x_nsigout++]); + } + } +} + + /* send loadbang to all instances */ +static void clone_loadbang(t_clone *x) +{ + t_canvas *cv; + int i; + + for (i = 0; i < x->x_nelems; i++) + { + if (cv = x->x_table[i].e_ab) + pd_vmess(&cv->gl_pd, gensym("loadbang"), ""); + } +} + + /* the two below borrow from binbuf_evalfile() -- which may change... */ +static void clone_instantiate_all(t_clone *x) +{ + if (x->x_name && x->x_dir && x->x_binbuf) + { + int dspstate = canvas_suspend_dsp(); + t_pd *current = s__X.s_thing; + t_cloneelement *ep; + int i; + + for (i = 0, ep = x->x_table; i < x->x_nelems; i++, ep++) + { + glob_setfilename(0, x->x_name, x->x_dir); + SETFLOAT(x->x_argv, i + 1); /* first arg is number of instance */ + canvas_setargs(x->x_argc, x->x_argv); /* pass args to canvas */ + binbuf_eval(x->x_binbuf, 0, 0, 0); + if (s__X.s_thing != current) + clone_instance_init(x, ep, current = s__X.s_thing, i); + glob_setfilename(0, &s_, &s_); + canvas_setargs(0, 0); + } + canvas_resume_dsp(dspstate); + clone_loadbang(x); + } +} + +static void clone_loadfile(t_clone *x) +{ + if (x->x_name && x->x_dir) + { + glob_setfilename(0, x->x_name, x->x_dir); + if (!x->x_binbuf) x->x_binbuf = binbuf_new(); + if (binbuf_read(x->x_binbuf, x->x_name->s_name, x->x_dir->s_name, 0)) + { + binbuf_free(x->x_binbuf); + x->x_binbuf = 0; + perror(x->x_name->s_name); + } + else + { + /* rename inlets and outlets */ + t_atom *ap = binbuf_getvec(x->x_binbuf); + int natoms = binbuf_getnatom(x->x_binbuf); + int i; + for (i = 0; i < natoms; i++, ap++) clone_inout_premapping(ap); + } + } +} + +static int clone_new_table(t_clone *x, int nelems) +{ + int i; + t_cloneelement *ep, **epp; + if (!x->x_table || nelems > x->x_tablesize) + { + /* LATER check if vc supports null pointer passing */ + if (!(x->x_table = resizebytes(x->x_table, + x->x_tablesize * sizeof(t_cloneelement), + nelems * sizeof(t_cloneelement)))) + { + x->x_tablesize = x->x_nelems = 0; + return (0); + } + x->x_tablesize = nelems; + } + x->x_nelems = nelems; + return (1); +} + +static void clone_free_elems(t_clone *x) +{ + if (x->x_table && x->x_tablesize > 0) + { + int i; + for (i = 0; i < x->x_nelems; i++) + if (x->x_table[i].e_ab) canvas_free(x->x_table[i].e_ab); + } + x->x_nelems = 0; +} + +static void clone_free_table(t_clone *x) +{ + if (x->x_table && x->x_tablesize > 0) + freebytes(x->x_table, x->x_tablesize * sizeof(t_cloneelement)); + x->x_tablesize = 0; + x->x_table = 0; +} + + /* returns: number of elements, or 0 in case of error */ +static int clone_checkargs(int ac, t_atom *av) +{ + int nelems = 0; + if (ac < 2 || av->a_type != A_SYMBOL + || av->a_w.w_symbol == &s_ + || av[1].a_type != A_FLOAT + || (nelems = (int)av[1].a_w.w_float) < 1) + error("clone: bad arguments"); + return (nelems > 0 ? nelems : 0); +} + +/* ---------------------- methods --------------------------------- */ +/* + (This whole issue below is probably obsolete (we do not use ordinary + inlets/outlets), but lets keep it that way -- just in case.) + + We must make sure there is always at most one instance visible. + + If user creates or deletes an inlet or outlet, Pd wants to kill + clone box in order to recreate it with this change reflected. This + poses a problem, because clone box interface should not change until + all instances are updated. Unfortunately, we have to allow for the + change, because it is hard-coded into canvas_class's widgetbehaviour. + We cannot use our replacement class derived from the canvas_class, + because there are various ``== canvas_class'' tests all over around + Pd core, and failing those tests means cheating, and eventually + crashing Pd. +*/ + + /* show instance 'f' of our abstraction */ +static void clone_show(t_clone *x, float f) +{ + if (x->x_table) + { + int i = (int)f; + if (i > 0) i--; + if (i >= 0 && i < x->x_nelems && x->x_table[i].e_ab) + { + int j; + for (j = 0; j < x->x_nelems; j++) + { + if (j == i) + { + canvas_vis(x->x_table[i].e_ab, 1); + } + else if (x->x_table[j].e_ab) + canvas_vis(x->x_table[j].e_ab, 0); + } + } + } +} + + /* show abstraction in case we click on object */ +static void clone_click(t_clone *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + clone_show(x, 0); +} + + /* we don't accept anything else than lists ! */ +static void clone_anything(t_clone *x, t_symbol *sel, int argc, t_atom *argv) +{ + outlet_anything(x->x_rejectout, sel, argc, argv); +} + + /* route input to the specified instance of the abstraction */ +static void clone_list(t_clone *x, t_symbol *sel, int argc, t_atom *argv) +{ + if (x->x_table) + { + if (x->x_nin && !x->x_nsigin) + { + t_cloneelement *ep; + int i, j; + if (argc > 1) /* 2 or more args: treat as "list" */ + { + i = (int)atom_getfloat(argv); + if(i <= 0) + j = x->x_nelems, i = 0; + else + j = i--; + if(j > x->x_nelems) goto reject; /* out of range */ + + for (ep = &x->x_table[i]; i < j; i++, ep++) + { + if (ep->e_target[0]) + { + if (argv[1].a_type == A_SYMBOL) + typedmess(ep->e_target[0], argv[1].a_w.w_symbol, argc-2, argv+2); + else + pd_list(ep->e_target[0], 0, argc-1, argv+1); + } + } + return; + } + } + else post("clone: no method for list..."); + } +reject: + outlet_list(x->x_rejectout, 0, argc, argv); +} + + /* send symbol to all instances */ +static void clone_symbol(t_clone *x, t_symbol *s) +{ + if(x->x_nin && !x->x_nsigin) + { + t_atom list[2]; + SETFLOAT(list, 0); + SETSYMBOL(list+1, s); + clone_list(x, NULL, 2, list); + } + else post("clone: no method for symbol..."); +} + + /* send float to all instances */ +static void clone_float(t_clone *x, t_floatarg f) +{ + if(x->x_nin && !x->x_nsigin) + { + t_atom list[2]; + SETFLOAT(list, 0); + SETFLOAT(list+1, f); + clone_list(x, NULL, 2, list); + } + else post("clone: no method for float..."); +} + + /* we don't accept anything else than lists ! */ +static void clone_snd_anything(t_clone_snd *snd, t_symbol *sel, int argc, t_atom *argv) +{ + t_clone *x = (t_clone *)(snd->s_owner); + outlet_anything(x->x_rejectout, sel, argc, argv); +} + + /* route input to the specified instance of the abstraction */ +static void clone_snd_list(t_clone_snd *snd, t_symbol *sel, int argc, t_atom *argv) +{ + t_clone *x = (t_clone *)(snd->s_owner); + if (x->x_table) + { + t_cloneelement *ep; + int i, j; + if (argc > 1) /* 2 or more args: treat as "list" */ + { + i = (int)atom_getfloat(argv); + if(i <= 0) + j = x->x_nelems, i = 0; + else + j = i--; + if(j > x->x_nelems) goto reject; /* out of range */ + + for (ep = &x->x_table[i]; i < j; i++, ep++) + { + if (ep->e_target[0]) + { + if (argv[1].a_type == A_SYMBOL) + typedmess(ep->e_target[snd->s_index], argv[1].a_w.w_symbol, argc-2, argv+2); + else + pd_list(ep->e_target[0], 0, argc-1, argv+1); + } + } + return; + } + } +reject: + outlet_list(x->x_rejectout, 0, argc, argv); +} + + /* send symbol to all instances */ +static void clone_snd_symbol(t_clone_snd *snd, t_symbol *s) +{ + t_clone *x = (t_clone *)(snd->s_owner); + t_atom list[2]; + SETFLOAT(list, 0); + SETSYMBOL(list+1, s); + clone_snd_list(snd, NULL, 2, list); +} + + /* send float to all instances */ +static void clone_snd_float(t_clone_snd *snd, t_floatarg f) +{ + t_clone *x = (t_clone *)(snd->s_owner); + t_atom list[2]; + SETFLOAT(list, 0); + SETFLOAT(list+1, f); + clone_snd_list(snd, NULL, 2, list); +} + + /* send received anything to outlet */ +static void clone_rcv_anything(t_clone_rcv *r, t_symbol *s, int argc, t_atom *argv) +{ + t_clone *x = (t_clone *)(r->r_owner); + outlet_anything(x->x_outlet[r->r_index], s, argc, argv); +} + + /* send received list to outlet */ +static void clone_rcv_list(t_clone_rcv *r, t_symbol *s, int argc, t_atom *argv) +{ + t_clone *x = (t_clone *)(r->r_owner); + outlet_list(x->x_outlet[r->r_index], s, argc, argv); +} + + /* send received symbol to outlet */ +static void clone_rcv_symbol(t_clone_rcv *r, t_symbol *s) +{ + t_clone *x = (t_clone *)(r->r_owner); + outlet_symbol(x->x_outlet[r->r_index], s); +} + + /* send received float to outlet */ +static void clone_rcv_float(t_clone_rcv *r, t_floatarg f) +{ + t_clone *x = (t_clone *)(r->r_owner); + outlet_float(x->x_outlet[r->r_index], f); +} + +static t_int *clone_perform(t_int *w) +{ + t_clone *x = (t_clone *)(w[1]); + t_float* throwout[MAXSIGINOUT]; + t_float* in[MAXSIGINOUT]; + t_float* catchin[MAXSIGINOUT]; + t_float* out[MAXSIGINOUT]; + int n = (int)(w[2 + x->x_nsigin + x->x_nsigout]); + int i; + + for(i = 0; i < x->x_nsigin; i++) + { + in[i] = (t_float *)(w[2+i]); + throwout[i] = (t_float *)(x->x_throwvec[i]); + } + + for(i = 0; i < x->x_nsigout; i++) + { + catchin[i] = (t_float *)(x->x_catchvec[i]); + out[i] = (t_float *)(w[2 + x->x_nsigin + i]); + } + + while (n--) + { + /* throw audio to abstractions */ + for(i = 0; i < x->x_nsigin; i++) + *throwout[i]++ = *in[i]++; + /* catch audio from abstractions */ + for(i = 0; i < x->x_nsigout; i++) + *out[i]++ = *catchin[i], *catchin[i]++ = 0; + } + return (w + 3 + x->x_nsigin + x->x_nsigout); +} + +static void clone_dsp(t_clone *x, t_signal **sp) +{ + if (x->x_table) + { + t_canvas *cv; + int i, nsig = x->x_nsigout + x->x_nsigin; + for (i = 0; i < x->x_nelems; i++) + if (cv = x->x_table[i].e_ab) + mess1(&cv->gl_pd, gensym("dsp"), sp); + + if (x->x_nsigout || x->x_nsigin) + { + if (x->x_vectorsize != sp[0]->s_n) + { + error("clone: unexpected vector size"); + return; + } + switch (nsig) + { + case 1: + dsp_add(clone_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); + break; + case 2: + dsp_add(clone_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, + sp[0]->s_n); + break; + case 3: + dsp_add(clone_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[0]->s_n); + break; + case 4: + dsp_add(clone_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); + break; + case 5: + dsp_add(clone_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); + break; + case 6: + dsp_add(clone_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, + sp[0]->s_n); + break; + case 7: + dsp_add(clone_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, + sp[6]->s_vec, sp[0]->s_n); + break; + case 8: + dsp_add(clone_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, + sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, + sp[6]->s_vec, sp[7]->s_vec, sp[0]->s_n); + break; + default: + break; + } + } + } +} + +static void clone_reload(t_clone *x, t_symbol *s, int ac, t_atom *av) +{ + int nelems; + + if (nelems = clone_checkargs(ac, av)) + { + t_symbol *dir; + int fd; + int i; + char dirbuf[MAXPDSTRING], *nameptr; + ac--; s = av++->a_w.w_symbol; /* name of abstraction */ + av++; ac--; + canvas_setcurrent(x->x_glist); + dir = canvas_getcurrentdir(); + if ((fd = open_via_path(dir->s_name, s->s_name, ".pd", + dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0) + { + close(fd); + clone_free_elems(x); + if (!clone_new_table(x, nelems)) + { + canvas_unsetcurrent(x->x_glist); + return; + } + x->x_name = gensym(nameptr); + x->x_dir = gensym(dirbuf); + if (x->x_argv) freebytes(x->x_argv, x->x_argc * sizeof(t_atom)); + x->x_argc = ac + 1; /* we'll add the instance's number later */ + x->x_argv = getbytes(x->x_argc * sizeof(t_atom)); /* allocate memory */ + for(i = 0; i < ac; i++) /* copy args, leave space for instance number */ + { + x->x_argv[i + 1] = av[i]; + } + /* Here goes: if (!pd_setloadingabstraction(s)) + needed for nested loads. It is local to pd.c. */ + clone_loadfile(x); + clone_instantiate_all(x); + } + else post("no such abstraction: %s", s->s_name); + canvas_unsetcurrent(x->x_glist); + } +} + +static void clone_free(t_clone *x) +{ + int i; + clone_free_elems(x); + clone_free_table(x); + if (x->x_argv) freebytes(x->x_argv, x->x_argc * sizeof(t_atom)); + for(i = 0; i < MAXSIGINOUT; i++) + { + freebytes(x->x_catchvec[i], x->x_vectorsize * sizeof(t_float)); + freebytes(x->x_throwvec[i], x->x_vectorsize * sizeof(t_float)); + } +} + +static void *clone_new(t_symbol *s, int ac, t_atom *av) +{ + t_clone *x = 0; + t_clone_rcv *rcv[MAXINOUT]; + t_clone_snd *snd[MAXINOUT]; + int i; + char rcvname[20]; + + post(version); + + if (clone_checkargs(ac, av) && (x = (t_clone *)pd_new(clone_class))) + { + x->x_glist = canvas_getcurrent(); + /* create unique receive names */ + for(i = 0; i < MAXINOUT; i++) + { + sprintf(rcvname, "clone_rcv_%03d_%03d", ncloneinstance, i); + x->x_rcvname[i] = gensym(rcvname); + } + ncloneinstance++; /* count this new instance of clone */ + + x->x_name = 0; + x->x_dir = 0; + x->x_argc = 0; + x->x_argv = 0; + x->x_binbuf = 0; + x->x_nelems = 0; + x->x_tablesize = 0; + x->x_table = 0; + /* catch & throw vector must be ready for clone_reload() */ + x->x_vectorsize = sys_getblksize(); + for (i = 0; i < MAXSIGINOUT; i++) + { + x->x_catchvec[i] = (t_float *)getbytes(x->x_vectorsize * sizeof(float)); + memset((char *)x->x_catchvec[i], 0, x->x_vectorsize * sizeof(float)); + x->x_throwvec[i] = (t_float *)getbytes(x->x_vectorsize * sizeof(float)); + } + + clone_reload(x, s, ac, av); + + if (x->x_table) + { + /* create inlets as needed */ + for (i = 1; i < x->x_nsigin; i++) /* signal inlets come first... */ + { + inlet_new (&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + } + for (i = 0; i < x->x_nin; i++) /* ..followed by control inlets */ + { + if(i == 0 && x->x_nsigin == 0) + continue; /* no need to create extra proxy inlet */ + snd[i] = (t_clone_snd *)pd_new(clone_snd_class); + snd[i]->s_owner = x; /* make x visible to the proxy inlets */ + snd[i]->s_index = i; /* remember our number */ + /* the inlet we're going to create belongs to the object + 't_clone' but the destination is the instance 'i' + of the proxy inlet class 't_clone_snd' */ + inlet_new(&x->x_obj, &snd[i]->s_obj.ob_pd, 0,0); + } + /* create outlets as needed */ + for (i = 0; i < x->x_nsigout; i++) /* signal outlets come first... */ + outlet_new(&x->x_obj, &s_signal); + for (i = 0; i < x->x_nout; i++) /* ..followed by control outlets */ + { + /* create a 'receive-like' class that feeds the outlet */ + rcv[i] = (t_clone_rcv *)pd_new(clone_rcv_class); + pd_bind(&rcv[i]->r_obj.ob_pd, x->x_rcvname[i]); /* bind to receive name */ + rcv[i]->r_owner = x; /* make x visible to the new class */ + rcv[i]->r_index = i; + x->x_outlet[i] = outlet_new(&x->x_obj, &s_list); + } + x->x_rejectout = outlet_new(&x->x_obj, &s_list); + } + else + { + pd_free((t_pd *)x); + x = 0; + } + } + return (x); +} + +static t_widgetbehavior *clone_text_widgetbehaviorp; +static t_widgetbehavior clone_widgetbehavior; + +static void clone_inout_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_binbuf *bb = ((t_text *)z)->te_binbuf; + if (bb && binbuf_getnatom(bb)) + clone_inout_postmapping(binbuf_getvec(bb)); + (*clone_text_widgetbehaviorp->w_visfn)(z, glist, vis); +} + +static void clone_inout_save(t_gobj *z, t_binbuf *b) +{ + t_binbuf *bb = ((t_text *)z)->te_binbuf; + if (bb && binbuf_getnatom(bb)) + clone_inout_postmapping(binbuf_getvec(bb)); + (*clone_text_widgetbehaviorp->w_savefn)(z, b); +} + +void clone_setup(void) +{ + clone_class = class_new(gensym("clone"), (t_newmethod)clone_new, + (t_method)clone_free, sizeof(t_clone), 0, A_GIMME, 0); + class_addcreator((t_newmethod)clone_new, gensym("clone~"), A_GIMME, 0); + CLASS_MAINSIGNALIN(clone_class, t_clone, x_float); + + /* a class for the proxy inlet: */ + clone_snd_class = class_new(gensym("clone_snd"), NULL, NULL, sizeof(t_clone_snd), + CLASS_PD|CLASS_NOINLET, A_NULL); + /* a class for the control outlet */ + clone_rcv_class = class_new(gensym("clone_rcv"), NULL, NULL, sizeof(t_clone_rcv), + CLASS_PD|CLASS_NOINLET, A_NULL); + + class_addmethod(clone_class, (t_method)clone_reload, gensym("reload"), A_GIMME, 0); + class_addmethod(clone_class, (t_method)clone_show, gensym("show"), A_DEFFLOAT, 0); + class_addmethod(clone_class, (t_method)clone_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + + class_addmethod(clone_class, (t_method)clone_dsp, gensym("dsp"), 0); + class_addfloat(clone_class, (t_method)clone_float); + class_addsymbol(clone_class, (t_method)clone_symbol); + class_addlist(clone_class, (t_method)clone_list); + class_addanything(clone_class, (t_method)clone_anything); + /* methods for outlets */ + class_addfloat(clone_rcv_class, (t_method)clone_rcv_float); + class_addsymbol(clone_rcv_class, (t_method)clone_rcv_float); + class_addlist(clone_rcv_class, (t_method)clone_rcv_list); + class_addanything(clone_rcv_class, (t_method)clone_rcv_anything); + /* methods for proxy inlets */ + class_addfloat(clone_snd_class, (t_method)clone_snd_float); + class_addsymbol(clone_snd_class, (t_method)clone_snd_symbol); + class_addlist(clone_snd_class, (t_method)clone_snd_list); + class_addanything(clone_snd_class, (t_method)clone_snd_anything); + + clone_setup_symbols(); + clone_text_widgetbehaviorp = clone_class->c_wb; + clone_widgetbehavior = *clone_text_widgetbehaviorp; + clone_widgetbehavior.w_visfn = clone_inout_vis; + clone_widgetbehavior.w_savefn = clone_inout_save; + clone_in_setup(); + class_setwidget(clone_in_class, &clone_widgetbehavior); + clone_sigin_setup(); + class_setwidget(clone_sigin_class, &clone_widgetbehavior); + clone_out_setup(); + class_setwidget(clone_out_class, &clone_widgetbehavior); + clone_sigout_setup(); + class_setwidget(clone_sigout_class, &clone_widgetbehavior); + + class_sethelpsymbol(clone_class, gensym("help-clone.pd")); +} \ No newline at end of file -- cgit v1.2.1