From faada59567f8cb252f4a909116595ce309ff5828 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Fri, 23 May 2003 12:29:55 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r647, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/miXed/; revision=648 --- cyclone/hammer/bondo.c | 394 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 cyclone/hammer/bondo.c (limited to 'cyclone/hammer/bondo.c') diff --git a/cyclone/hammer/bondo.c b/cyclone/hammer/bondo.c new file mode 100644 index 0000000..2fcdce3 --- /dev/null +++ b/cyclone/hammer/bondo.c @@ -0,0 +1,394 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER revisit buffer handling (maxsize, reentrancy) */ +/* LATER rethink handling of symbols */ + +/* CHECKED: if 'n' argument is given, then store whole messages, instead of + distributing atoms across successive slots. This is a new, buddy-like + behaviour. */ +/* CHECKED: without 'n' argument, 'symbol test' is parsed as two symbol atoms, + but 'float 1' (or 'list 1') as a single float. */ + +#include +#include "m_pd.h" +#include "common/grow.h" + +#define BONDO_MINSLOTS 2 +#define BONDO_INISIZE 4 /* LATER rethink (useful only in multiatom mode) */ + +typedef struct _bondo +{ + t_object x_ob; + t_float x_delay; + int x_multiatom; + int x_nslots; + int x_nproxies; /* as requested (and allocated) */ + t_pd **x_proxies; + t_outlet **x_outs; + t_clock *x_clock; +} t_bondo; + +typedef struct _bondo_proxy +{ + t_object p_ob; + t_bondo *p_master; + int p_id; + t_symbol *p_selector; + t_float p_float; + t_symbol *p_symbol; + t_gpointer *p_pointer; + int p_size; /* as allocated */ + int p_natoms; /* as used */ + t_atom *p_message; + t_atom p_messini[BONDO_INISIZE]; +} t_bondo_proxy; + +static t_class *bondo_class; +static t_class *bondo_proxy_class; + +static void bondo_doit(t_bondo *x) +{ + t_bondo_proxy **p = (t_bondo_proxy **)x->x_proxies; + int i = x->x_nslots; + p = (t_bondo_proxy **)x->x_proxies; + i = x->x_nslots; + while (i--) + { + t_symbol *s = p[i]->p_selector; + /* LATER consider complaining about extra arguments (CHECKED) */ + if (s == &s_bang) + outlet_bang(x->x_outs[i]); + else if (s == &s_float) + outlet_float(x->x_outs[i], p[i]->p_float); + else if (s == &s_symbol && p[i]->p_symbol) + { + /* LATER rethink */ + if (x->x_multiatom) + outlet_symbol(x->x_outs[i], p[i]->p_symbol); + else + outlet_anything(x->x_outs[i], p[i]->p_symbol, 0, 0); + } + else if (s == &s_pointer) + { + /* LATER */ + } + else if (s == &s_list) + outlet_list(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); + else if (s) /* CHECKED: a slot may be inactive (in multiatom mode) */ + outlet_anything(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); + } +} + +static void bondo_arm(t_bondo *x) +{ + if (x->x_delay <= 0) bondo_doit(x); + else clock_delay(x->x_clock, x->x_delay); +} + +static void bondo_proxy_bang(t_bondo_proxy *x) +{ + bondo_arm(x->p_master); /* CHECKED: bang in any inlet works in this way */ +} + +static void bondo_proxy_dofloat(t_bondo_proxy *x, t_float f, int doit) +{ + x->p_selector = &s_float; + x->p_float = f; + x->p_natoms = 0; /* defensive */ + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_float(t_bondo_proxy *x, t_float f) +{ + bondo_proxy_dofloat(x, f, 1); +} + +static void bondo_proxy_dosymbol(t_bondo_proxy *x, t_symbol *s, int doit) +{ + x->p_selector = &s_symbol; + x->p_symbol = s; + x->p_natoms = 0; /* defensive */ + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_symbol(t_bondo_proxy *x, t_symbol *s) +{ + bondo_proxy_dosymbol(x, s, 1); +} + +static void bondo_proxy_dopointer(t_bondo_proxy *x, t_gpointer *gp, int doit) +{ + x->p_selector = &s_pointer; + x->p_pointer = gp; + x->p_natoms = 0; /* defensive */ + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_pointer(t_bondo_proxy *x, t_gpointer *gp) +{ + bondo_proxy_dopointer(x, gp, 1); +} + +/* CHECKED: the slots fire in right-to-left order, + but they trigger only once (refman error) */ +static void bondo_distribute(t_bondo *x, int startid, + t_symbol *s, int ac, t_atom *av, int doit) +{ + t_atom *ap = av; + t_bondo_proxy **pp; + int id = startid + ac; + if (s) id++; + if (id > x->x_nslots) + id = x->x_nslots; + ap += id - startid; + pp = (t_bondo_proxy **)(x->x_proxies + id); + if (s) ap--; + while (ap-- > av) + { + pp--; + if (ap->a_type == A_FLOAT) + bondo_proxy_dofloat(*pp, ap->a_w.w_float, 0); + else if (ap->a_type == A_SYMBOL) + bondo_proxy_dosymbol(*pp, ap->a_w.w_symbol, 0); + else if (ap->a_type == A_POINTER) + bondo_proxy_dopointer(*pp, ap->a_w.w_gpointer, 0); + } + if (s) + bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[startid], s, 0); + if (doit) bondo_arm(x); +} + +static void bondo_proxy_domultiatom(t_bondo_proxy *x, + int ac, t_atom *av, int doit) +{ + if (ac > x->p_size) + { + /* LATER consider using BONDO_MAXSIZE (and warning if exceeded) */ + x->p_message = grow_nodata(&ac, &x->p_size, x->p_message, + BONDO_INISIZE, x->p_messini, + sizeof(*x->p_message)); + } + x->p_natoms = ac; + memcpy(x->p_message, av, ac * sizeof(*x->p_message)); + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_dolist(t_bondo_proxy *x, int ac, t_atom *av, int doit) +{ + if (x->p_master->x_multiatom) + { + x->p_selector = &s_list; + bondo_proxy_domultiatom(x, ac, av, doit); + } + else bondo_distribute(x->p_master, x->p_id, 0, ac, av, doit); +} + +static void bondo_proxy_list(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_dolist(x, ac, av, 1); +} + +static void bondo_proxy_doanything(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av, int doit) +{ + if (x->p_master->x_multiatom) + { + /* LATER rethink and CHECKME */ + if (s == &s_symbol) + { + if (ac && av->a_type == A_SYMBOL) + bondo_proxy_dosymbol(x, av->a_w.w_symbol, doit); + else + bondo_proxy_dosymbol(x, &s_symbol, doit); + } + else + { + x->p_selector = s; + bondo_proxy_domultiatom(x, ac, av, doit); + } + } + else bondo_distribute(x->p_master, x->p_id, s, ac, av, doit); +} + +static void bondo_proxy_anything(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_doanything(x, s, ac, av, 1); +} + +static void bondo_proxy_set(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + if (av->a_type == A_FLOAT) + { + if (ac > 1) + bondo_proxy_dolist(x, ac, av, 0); + else + bondo_proxy_dofloat(x, av->a_w.w_float, 0); + } + else if (av->a_type == A_SYMBOL) + /* CHECKED: no tests for 'set float ...' and 'set list...' -- + the parsing is made in an output routine */ + bondo_proxy_doanything(x, av->a_w.w_symbol, ac-1, av+1, 0); + else if (av->a_type == A_POINTER) + bondo_proxy_dopointer(x, av->a_w.w_gpointer, 0); + } + /* CHECKED: 'set' without arguments makes a slot inactive, + if multiatom, but is ignored, if !multiatom */ + else if (x->p_master->x_multiatom) x->p_selector = 0; +} + +static void bondo_bang(t_bondo *x) +{ + bondo_proxy_bang((t_bondo_proxy *)x->x_proxies[0]); +} + +static void bondo_float(t_bondo *x, t_float f) +{ + bondo_proxy_dofloat((t_bondo_proxy *)x->x_proxies[0], f, 1); +} + +static void bondo_symbol(t_bondo *x, t_symbol *s) +{ + bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[0], s, 1); +} + +static void bondo_pointer(t_bondo *x, t_gpointer *gp) +{ + bondo_proxy_dopointer((t_bondo_proxy *)x->x_proxies[0], gp, 1); +} + +static void bondo_list(t_bondo *x, t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_dolist((t_bondo_proxy *)x->x_proxies[0], ac, av, 1); +} + +static void bondo_anything(t_bondo *x, t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_doanything((t_bondo_proxy *)x->x_proxies[0], s, ac, av, 1); +} + +static void bondo_set(t_bondo *x, t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_set((t_bondo_proxy *)x->x_proxies[0], s, ac, av); +} + +static void bondo_free(t_bondo *x) +{ + if (x->x_clock) clock_free(x->x_clock); + if (x->x_proxies) + { + int i = x->x_nslots; + while (i--) + { + t_bondo_proxy *y = (t_bondo_proxy *)x->x_proxies[i]; + if (y->p_message != y->p_messini) + freebytes(y->p_message, y->p_size * sizeof(*y->p_message)); + pd_free((t_pd *)y); + } + freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); + } + if (x->x_outs) + freebytes(x->x_outs, x->x_nslots * sizeof(*x->x_outs)); +} + +static void *bondo_new(t_symbol *s, int ac, t_atom *av) +{ + t_bondo *x; + int i, nslots, nproxies = BONDO_MINSLOTS; + int multiatom = 0; + t_float delay = 0; + t_pd **proxies; + t_outlet **outs; + i = 0; + while (ac--) + { + /* CHECKED: no warnings */ + if (av->a_type == A_FLOAT) + { + if (i == 0) + nproxies = (int)av->a_w.w_float; + else if (i == 1) + delay = av->a_w.w_float; + i++; + } + else if (av->a_type == A_SYMBOL) + { + if (av->a_w.w_symbol == gensym("n")) multiatom = 1; + /* CHECKED: 'n' has to be the last argument given; + the arguments after any symbol are silently ignored -- + LATER decide if we should comply and break here */ + } + av++; + } + if (nproxies < BONDO_MINSLOTS) + nproxies = BONDO_MINSLOTS; + if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) + return (0); + for (nslots = 0; nslots < nproxies; nslots++) + if (!(proxies[nslots] = pd_new(bondo_proxy_class))) break; + if (nslots < BONDO_MINSLOTS + || !(outs = (t_outlet **)getbytes(nslots * sizeof(*outs)))) + { + i = nslots; + while (i--) pd_free(proxies[i]); + freebytes(proxies, nproxies * sizeof(*proxies)); + return (0); + } + x = (t_bondo *)pd_new(bondo_class); + x->x_delay = delay; + x->x_multiatom = multiatom; + x->x_nslots = nslots; + x->x_nproxies = nproxies; + x->x_proxies = proxies; + x->x_outs = outs; + for (i = 0; i < nslots; i++) + { + t_bondo_proxy *y = (t_bondo_proxy *)proxies[i]; + y->p_master = x; + y->p_id = i; + y->p_selector = &s_float; /* CHECKED: it is so in multiatom mode too */ + y->p_float = 0; + y->p_symbol = 0; + y->p_pointer = 0; + y->p_size = BONDO_INISIZE; + y->p_natoms = 0; + y->p_message = y->p_messini; + if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); + x->x_outs[i] = outlet_new((t_object *)x, &s_anything); + } + x->x_clock = clock_new(x, (t_method)bondo_doit); + return (x); +} + +void bondo_setup(void) +{ + bondo_class = class_new(gensym("bondo"), + (t_newmethod)bondo_new, + (t_method)bondo_free, + sizeof(t_bondo), 0, A_GIMME, 0); + class_addbang(bondo_class, bondo_bang); + class_addfloat(bondo_class, bondo_float); + class_addsymbol(bondo_class, bondo_symbol); + class_addpointer(bondo_class, bondo_pointer); + class_addlist(bondo_class, bondo_list); + class_addanything(bondo_class, bondo_anything); + class_addmethod(bondo_class, (t_method)bondo_set, + gensym("set"), A_GIMME, 0); + bondo_proxy_class = class_new(gensym("_bondo_proxy"), 0, 0, + sizeof(t_bondo_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(bondo_proxy_class, bondo_proxy_bang); + class_addfloat(bondo_proxy_class, bondo_proxy_float); + class_addsymbol(bondo_proxy_class, bondo_proxy_symbol); + class_addpointer(bondo_proxy_class, bondo_proxy_pointer); + class_addlist(bondo_proxy_class, bondo_proxy_list); + class_addanything(bondo_proxy_class, bondo_proxy_anything); + class_addmethod(bondo_proxy_class, (t_method)bondo_proxy_set, + gensym("set"), A_GIMME, 0); +} -- cgit v1.2.1