aboutsummaryrefslogtreecommitdiff
path: root/cyclone/hammer/funnel.c
diff options
context:
space:
mode:
Diffstat (limited to 'cyclone/hammer/funnel.c')
-rw-r--r--cyclone/hammer/funnel.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/cyclone/hammer/funnel.c b/cyclone/hammer/funnel.c
new file mode 100644
index 0000000..d289d8d
--- /dev/null
+++ b/cyclone/hammer/funnel.c
@@ -0,0 +1,179 @@
+/* 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. */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+#define FUNNEL_MINSLOTS 2
+#define FUNNEL_INISIZE 32 /* LATER rethink */
+#define FUNNEL_MAXSIZE 256
+
+typedef struct _funnel
+{
+ t_object x_ob;
+ int x_nslots;
+ int x_nproxies; /* as requested (and allocated) */
+ t_pd **x_proxies;
+} t_funnel;
+
+typedef struct _funnel_proxy
+{
+ t_object p_ob;
+ t_outlet *p_out; /* master outlet (the same value for each slot) */
+ int p_id; /* adjusted according to an offset argument */
+ t_float p_value;
+ int p_size; /* as allocated */
+ t_atom *p_message;
+ t_atom p_messini[FUNNEL_INISIZE];
+ int p_entered;
+} t_funnel_proxy;
+
+static t_class *funnel_class;
+static t_class *funnel_proxy_class;
+
+static void funnel_proxy_bang(t_funnel_proxy *x)
+{
+ t_atom at[2];
+ SETFLOAT(&at[0], x->p_id);
+ SETFLOAT(&at[1], x->p_value);
+ outlet_list(x->p_out, &s_list, 2, at);
+}
+
+static void funnel_proxy_float(t_funnel_proxy *x, t_float f)
+{
+ x->p_value = f;
+ funnel_proxy_bang(x);
+}
+
+static void funnel_proxy_list(t_funnel_proxy *x,
+ t_symbol *s, int ac, t_atom *av)
+{
+ int reentered = x->p_entered;
+ int prealloc = !reentered;
+ int ntotal = ac + 1;
+ x->p_entered = 1;
+ if (prealloc && ntotal > x->p_size)
+ {
+ if (ntotal > FUNNEL_MAXSIZE)
+ prealloc = 0;
+ else
+ {
+ x->p_message = grow_nodata(&ntotal, &x->p_size, x->p_message,
+ FUNNEL_INISIZE, x->p_messini,
+ sizeof(*x->p_message));
+ ac = ntotal - 1;
+ }
+ }
+ /* LATER consider a compatibility warning if av->a_type != A_FLOAT */
+ x->p_value = ((ac && av->a_type == A_FLOAT) ? av->a_w.w_float : 0);
+ if (prealloc)
+ {
+ SETFLOAT(x->p_message, x->p_id);
+ if (ac)
+ memcpy(x->p_message + 1, av, ac * sizeof(*x->p_message));
+ outlet_list(x->p_out, &s_list, ntotal, x->p_message);
+ }
+ else
+ {
+ /* LATER consider using the stack if ntotal <= MAXSTACK */
+ t_atom *buf = getbytes(ntotal * sizeof(*buf));
+ if (buf)
+ {
+ SETFLOAT(buf, x->p_id);
+ if (ac)
+ memcpy(buf + 1, av, ac * sizeof(*buf));
+ outlet_list(x->p_out, &s_list, ntotal, buf);
+ freebytes(buf, ntotal * sizeof(*buf));
+ }
+ }
+ if (!reentered) x->p_entered = 0;
+}
+
+static void funnel_bang(t_funnel *x)
+{
+ funnel_proxy_bang((t_funnel_proxy *)x->x_proxies[0]);
+}
+
+static void funnel_float(t_funnel *x, t_float f)
+{
+ funnel_proxy_float((t_funnel_proxy *)x->x_proxies[0], f);
+}
+
+static void funnel_list(t_funnel *x, t_symbol *s, int ac, t_atom *av)
+{
+ funnel_proxy_list((t_funnel_proxy *)x->x_proxies[0], s, ac, av);
+}
+
+static void funnel_free(t_funnel *x)
+{
+ if (x->x_proxies)
+ {
+ int i = x->x_nslots;
+ while (i--)
+ {
+ t_funnel_proxy *y = (t_funnel_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));
+ }
+}
+
+static void *funnel_new(t_floatarg f1, t_floatarg f2)
+{
+ t_funnel *x;
+ int i, nslots, nproxies = (int)f1;
+ int offset = (int)f2;
+ t_outlet *out;
+ t_pd **proxies;
+ if (nproxies < 1) /* CHECKED: one-slot funnel may be created */
+ nproxies = FUNNEL_MINSLOTS;
+ if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies))))
+ return (0);
+ for (nslots = 0; nslots < nproxies; nslots++)
+ if (!(proxies[nslots] = pd_new(funnel_proxy_class))) break;
+ if (!nslots)
+ {
+ freebytes(proxies, nproxies * sizeof(*proxies));
+ return (0);
+ }
+ x = (t_funnel *)pd_new(funnel_class);
+ x->x_nslots = nslots;
+ x->x_nproxies = nproxies;
+ x->x_proxies = proxies;
+ out = outlet_new((t_object *)x, &s_list);
+ for (i = 0; i < nslots; i++)
+ {
+ t_funnel_proxy *y = (t_funnel_proxy *)proxies[i];
+ y->p_out = out;
+ y->p_id = offset++;
+ y->p_value = 0;
+ y->p_size = FUNNEL_INISIZE;
+ y->p_message = y->p_messini;
+ y->p_entered = 0;
+ if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0);
+ }
+ return (x);
+}
+
+void funnel_setup(void)
+{
+ funnel_class = class_new(gensym("funnel"),
+ (t_newmethod)funnel_new,
+ (t_method)funnel_free,
+ sizeof(t_funnel), 0, A_DEFFLOAT, A_DEFFLOAT, 0);
+ class_addbang(funnel_class, funnel_bang);
+ class_addfloat(funnel_class, funnel_float);
+ class_addlist(funnel_class, funnel_list);
+ /* CHECKED: funnel doesn't understand symbol, anything */
+ funnel_proxy_class = class_new(gensym("_funnel_proxy"), 0, 0,
+ sizeof(t_funnel_proxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(funnel_proxy_class, funnel_proxy_bang);
+ class_addfloat(funnel_proxy_class, funnel_proxy_float);
+ class_addlist(funnel_proxy_class, funnel_proxy_list);
+ /* CHECKED: funnel doesn't understand symbol, anything */
+}