aboutsummaryrefslogtreecommitdiff
path: root/cyclone/hammer/bondo.c
diff options
context:
space:
mode:
Diffstat (limited to 'cyclone/hammer/bondo.c')
-rw-r--r--cyclone/hammer/bondo.c394
1 files changed, 394 insertions, 0 deletions
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 <string.h>
+#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);
+}