aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--riddle/rdremote.c814
-rw-r--r--riddle/riddle.c1317
-rw-r--r--riddle/riddle.h131
-rw-r--r--riddle/riddleguts.h35
4 files changed, 1449 insertions, 848 deletions
diff --git a/riddle/rdremote.c b/riddle/rdremote.c
new file mode 100644
index 0000000..689e079
--- /dev/null
+++ b/riddle/rdremote.c
@@ -0,0 +1,814 @@
+/* Copyright (c) 2007 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 <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include "m_pd.h"
+#include "common/loud.h"
+#include "common/grow.h"
+#include "sickle/sic.h"
+#include "riddle.h"
+#include "riddleguts.h"
+
+/* obj_starttraverseoutlet, obj_nexttraverseoutlet, obj_noutlets,
+ obj_nsiginlets, obj_nsigoutlets, obj_siginletindex, obj_sigoutletindex,
+ obj_issignalinlet, obj_issignaloutlet */
+#include "m_imp.h"
+
+/* struct _glist, canvas_class, vinlet_class */
+#include "g_canvas.h"
+
+EXTERN_STRUCT _rdpool;
+#define t_rdpool struct _rdpool
+
+typedef struct _rdenvironment
+{
+ t_pd en_pd;
+ t_rdpool *en_graphpools;
+ t_rdremote *en_writers;
+ t_rdremote *en_readers; /* list of orphaned readers */
+ t_clock *en_updatedspclock;
+} t_rdenvironment;
+
+static t_class *rdenvironment_class = 0;
+
+#define RDREMOTE_INISIZE 1024
+
+struct _rdremote
+{
+ int re_id; /* positive for readers, otherwise zero */
+ t_symbol *re_name;
+ t_riddle *re_owner;
+ int re_phase;
+ t_rdremote *re_portlink; /* slist of object i/o */
+ t_rdremote *re_prev; /* double-linked list of readers or writers */
+ t_rdremote *re_next;
+
+ /* common part, copied from writer to all its readers
+ immediately after any change */
+ int re_nframes;
+ int re_framesize;
+ int re_npoints;
+ int re_maxphase;
+ t_float *re_data;
+
+ /* writer-specific part */
+ t_rdremote *re_readers;
+ int re_datasize;
+ t_float *re_inidata;
+};
+
+#define RDPICKER_INISIZE 64
+
+struct _rdpool
+{
+ t_canvas *po_graph;
+ int po_refcount;
+ t_rdpicker *po_pickstore;
+ t_rdpool *po_prev;
+ t_rdpool *po_next;
+};
+
+struct _rdpicker
+{
+ t_symbol *pi_key;
+ int pi_refcount;
+ t_rdpool *pi_graphpool;
+ int pi_size;
+ int pi_maxsize;
+ t_float *pi_data;
+ t_float pi_inidata[RDPICKER_INISIZE];
+ t_rdpicker *pi_prev;
+ t_rdpicker *pi_next;
+};
+
+typedef struct _rdfeeder
+{
+ t_rdpicker *fe_picker;
+ struct _rdfeeder *fe_next;
+} t_rdfeeder;
+
+struct _rdfeedchain
+{
+ t_rdfeeder *ch_head;
+ int ch_outno;
+};
+
+static t_symbol *rdps__idle = 0;
+
+static void rdenvironment_updatedsptick(t_rdenvironment *en)
+{
+ canvas_update_dsp();
+}
+
+static void rdenvironment_anything(t_rdenvironment *en,
+ t_symbol *s, int ac, t_atom *av)
+{
+ /* FIXME */
+}
+
+static t_rdenvironment *rdenvironment_provide(void)
+{
+ t_rdenvironment *en;
+ t_symbol *ps__riddle = gensym("_riddle"); /* class name */
+ t_symbol *ps_hashriddle = gensym("#riddle"); /* instance binding */
+ if (ps_hashriddle->s_thing)
+ {
+ char *cname = class_getname(*ps_hashriddle->s_thing);
+ if (strcmp(cname, ps__riddle->s_name))
+ {
+ /* FIXME protect against the danger of someone else
+ (e.g. receive) binding to #riddle */
+ loudbug_bug("rdenvironment_provide");
+ }
+ else
+ {
+ /* FIXME compatibility test */
+ rdenvironment_class = *ps_hashriddle->s_thing;
+ return ((t_rdenvironment *)ps_hashriddle->s_thing);
+ }
+ }
+ rdps__idle = gensym("_idle");
+ rdenvironment_class = class_new(ps__riddle, 0, 0,
+ sizeof(t_rdenvironment),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addanything(rdenvironment_class, rdenvironment_anything);
+ en = (t_rdenvironment *)pd_new(rdenvironment_class); /* never freed */
+ en->en_graphpools = 0;
+ en->en_writers = 0;
+ en->en_readers = 0;
+ en->en_updatedspclock =
+ clock_new(en, (t_method)rdenvironment_updatedsptick);
+ pd_bind((t_pd *)en, ps_hashriddle); /* never unbound */
+ return (en);
+}
+
+t_pd *riddle_getenvironment(void)
+{
+ return ((t_pd *)rdenvironment_provide());
+}
+
+
+/* subgraph-localized remote connections: feeders and pickers
+ LATER should become a kind of rdremote writers and readers */
+
+t_rdpicker *rdpicker_attach(t_riddle *rd, t_symbol *key)
+{
+ t_rdenvironment *en = rdenvironment_provide();
+ /* FIXME protect against calling outside of the constructor */
+ t_canvas *graph = canvas_getcurrent();
+ t_rdpool *po;
+ t_rdpicker *pi;
+ for (po = en->en_graphpools; po; po = po->po_next)
+ {
+ if (po->po_graph == graph)
+ {
+ for (pi = po->po_pickstore; pi; pi = pi->pi_next)
+ {
+ if (pi->pi_key == key)
+ {
+ pi->pi_refcount++;
+ return (pi);
+ }
+ }
+ }
+ }
+
+ if (po)
+ po->po_refcount++;
+ else
+ {
+ po = getbytes(sizeof(*po));
+ po->po_graph = graph;
+ po->po_refcount = 1;
+ po->po_pickstore = 0;
+ po->po_prev = 0;
+ if (en->en_graphpools)
+ en->en_graphpools->po_prev = po;
+ po->po_next = en->en_graphpools;
+ en->en_graphpools = po;
+ }
+
+ pi = getbytes(sizeof(*pi));
+ pi->pi_key = key;
+ pi->pi_refcount = 1;
+ pi->pi_graphpool = po;
+ pi->pi_size = 0;
+ pi->pi_maxsize = RDPICKER_INISIZE;
+ pi->pi_data = pi->pi_inidata;
+ pi->pi_prev = 0;
+ if (po->po_pickstore)
+ po->po_pickstore->pi_prev = pi;
+ pi->pi_next = po->po_pickstore;
+ po->po_pickstore = pi;
+ return (pi);
+}
+
+void rdpicker_detach(t_rdpicker *pi, t_riddle *rd)
+{
+ if (pi->pi_refcount > 1)
+ pi->pi_refcount--;
+ else
+ {
+ if (pi->pi_data && pi->pi_data != pi->pi_inidata)
+ freebytes(pi->pi_data, pi->pi_maxsize * sizeof(*pi->pi_data));
+ if (pi->pi_prev)
+ pi->pi_prev->pi_next = pi->pi_next;
+ else if (pi->pi_graphpool)
+ pi->pi_graphpool->po_pickstore = pi->pi_next;
+ else
+ loudbug_bug("rdpicker_detach 1");
+ if (pi->pi_next)
+ pi->pi_next->pi_prev = pi->pi_prev;
+ if (pi->pi_graphpool)
+ {
+ t_rdpool *po = pi->pi_graphpool;
+ t_rdenvironment *en = rdenvironment_provide();
+ if (po->po_refcount > 1)
+ po->po_refcount--;
+ else
+ {
+ if (po->po_pickstore)
+ loudbug_bug("rdpicker_detach 2");
+ if (po->po_prev)
+ po->po_prev->po_next = po->po_next;
+ else
+ en->en_graphpools = po->po_next;
+ if (po->po_next)
+ po->po_next->po_prev = po->po_prev;
+ freebytes(po, sizeof(*po));
+ }
+ }
+ freebytes(pi, sizeof(*pi));
+ }
+}
+
+t_float *rdpicker_pick(t_rdpicker *pi, int *sizep)
+{
+ *sizep = pi->pi_size;
+ return (pi->pi_data);
+}
+
+t_float rdpicker_pick1(t_rdpicker *pi)
+{
+ return (*pi->pi_data);
+}
+
+static t_rdpicker *rdpool_linkpicker(t_rdpool *po, t_symbol *key, int size)
+{
+ t_rdpicker *pi;
+ for (pi = po->po_pickstore; pi; pi = pi->pi_next)
+ {
+ if (pi->pi_key == key)
+ {
+ if (size > pi->pi_maxsize)
+ pi->pi_data = grow_nodata(&size, &pi->pi_maxsize, pi->pi_data,
+ RDPICKER_INISIZE, pi->pi_inidata,
+ sizeof(*pi->pi_data));
+ pi->pi_size = size;
+ return (pi);
+ }
+ }
+ return (0);
+}
+
+/* LATER think about rdpool_unlinkpicker() */
+
+static void rdfeedchain_proliferate(t_rdfeedchain *ch, t_rdpool *pohead,
+ t_gobj *g, t_symbol *key, int size)
+{
+ int result = 0;
+ for (; g; g = g->g_next)
+ {
+ if (pd_class((t_pd *)g) == canvas_class)
+ {
+ t_canvas *graph = (t_canvas *)g;
+ t_rdpool *po;
+ t_rdpicker *pi;
+ for (po = pohead; po; po = po->po_next)
+ if (po->po_graph == graph)
+ break;
+ if (po && (pi = rdpool_linkpicker(po, key, size)))
+ {
+ t_rdfeeder *fe = getbytes(sizeof(*fe)); /* FIXME reuse */
+ fe->fe_picker = pi;
+ fe->fe_next = ch->ch_head;
+ ch->ch_head = fe;
+ }
+ rdfeedchain_proliferate(ch, pohead, graph->gl_list, key, size);
+ }
+ }
+}
+
+void rdfeedchain_free(t_rdfeedchain *ch)
+{
+ t_rdfeeder *fe, *fenext;
+ for (fe = ch->ch_head; fe; fe = fenext)
+ {
+ fenext = fe->fe_next;
+ freebytes(fe, sizeof(*fe));
+ }
+}
+
+t_rdfeedchain *rdfeedchain_new(int outno)
+{
+ t_rdfeedchain *ch = getbytes(sizeof(*ch));
+ ch->ch_head = 0;
+ ch->ch_outno = outno;
+}
+
+t_rdfeedchain *riddle_usefeedchain(t_riddle *rd,
+ int sigoutno, t_symbol *key, int size)
+{
+ t_rdfeedchain *ch;
+ if (ch = riddle_getfeedchain(rd, sigoutno))
+ {
+ t_canvas *graph;
+ t_rdfeeder *fe, *fenext;
+ /* LATER reuse */
+ for (fe = ch->ch_head; fe; fe = fenext)
+ {
+ fenext = fe->fe_next;
+ freebytes(fe, sizeof(*fe));
+ }
+ for (graph = riddle_firstgraph(rd, ch->ch_outno);
+ graph; graph = riddle_nextgraph(rd))
+ {
+ t_rdenvironment *en = rdenvironment_provide();
+ t_rdpool *po;
+ t_rdpicker *pi;
+ for (po = en->en_graphpools; po; po = po->po_next)
+ if (po->po_graph == graph)
+ break;
+ if (po && (pi = rdpool_linkpicker(po, key, size)))
+ {
+ t_rdfeeder *fe = getbytes(sizeof(*fe));
+ fe->fe_picker = pi;
+ fe->fe_next = 0;
+ ch->ch_head = fe;
+ }
+ else ch->ch_head = 0;
+ rdfeedchain_proliferate(ch, en->en_graphpools,
+ (t_gobj *)graph, key, size);
+ }
+ }
+ return (ch);
+}
+
+t_rdfeedchain *riddle_useidlechain(t_riddle *rd, int sigoutno)
+{
+ return (riddle_usefeedchain(rd, sigoutno, rdps__idle, 1));
+}
+
+void rdfeedchain_feed(t_rdfeedchain *ch, int size, t_float *data)
+{
+ t_rdfeeder *fe;
+ for (fe = ch->ch_head; fe; fe = fe->fe_next)
+ {
+ t_rdpicker *pi = fe->fe_picker;
+ if (size > pi->pi_size)
+ size = pi->pi_size;
+ memcpy(pi->pi_data, data, size * sizeof(*pi->pi_data));
+ }
+}
+
+void rdfeedchain_feed1(t_rdfeedchain *ch, t_float v)
+{
+ t_rdfeeder *fe;
+ for (fe = ch->ch_head; fe; fe = fe->fe_next)
+ *fe->fe_picker->pi_data = v;
+}
+
+int riddle_isidle(t_riddle *rd)
+{
+ return (rd->rd_idlepicker && *rd->rd_idlepicker->pi_data > .5);
+}
+
+void riddle_updatedsp(void)
+{
+ t_rdenvironment *en = rdenvironment_provide();
+ loud_warning((t_pd *)en, 0, "...trying to reconstruct the dsp chain");
+ clock_delay(en->en_updatedspclock, 0);
+}
+
+
+/* rdremote: global named writers, global named readers,
+ and private anonymous bidirectional buffers */
+
+
+static t_rdremote *rdenvironment_getbuffer(t_rdenvironment *en, t_symbol *name)
+{
+ t_rdremote *re = en->en_writers;
+ while (re)
+ {
+ if (re->re_name == name)
+ return (re);
+ re = re->re_next;
+ }
+ return (0);
+}
+
+t_rdremote *rdremote_getwriter(t_rdremote *re)
+{
+ t_rdenvironment *en = rdenvironment_provide();
+ return (rdenvironment_getbuffer(en, re->re_name));
+}
+
+t_rdremote *rdremote_nextreader(t_rdremote *re)
+{
+ while (re && !re->re_id)
+ re = re->re_portlink;
+ return (re);
+}
+
+int rdremote_getsourceblock(t_rdremote *re)
+{
+ if (re->re_owner && re->re_id > 0)
+ return (riddle_getsourceblock(re->re_owner, -re->re_id));
+ else
+ {
+ loudbug_bug("rdremote_getsourceblock");
+ return (0);
+ }
+}
+
+t_symbol *rdremote_getsourcelayout(t_rdremote *re, int *maxblockp)
+{
+ if (re->re_owner && re->re_id > 0)
+ return (riddle_getsourcelayout(re->re_owner, -re->re_id, maxblockp));
+ else
+ {
+ loudbug_bug("rdremote_getsourcelayout");
+ return (0);
+ }
+}
+
+int rdremote_getsourceflags(t_rdremote *re)
+{
+ if (re->re_owner && re->re_id > 0)
+ return (riddle_getsourceflags(re->re_owner, -re->re_id));
+ else
+ {
+ loudbug_bug("rdremote_getsourceflags");
+ return (0);
+ }
+}
+
+/* this call reallocates memory if necessary, so the caller should check
+ for failures: the number of frames and/ot framesize may decrease
+ (the actually available framesize is returned by the call) */
+/* LATER optionally use old contents by zero-padding, interpolating, etc. */
+static int rdremote_setframesize(t_rdremote *re, int framesize)
+{
+ t_rdremote *reader;
+ if (re->re_inidata == 0)
+ {
+ /* not a writer */
+ loudbug_bug("rdremote_setframesize 1");
+ return (0);
+ }
+ if (framesize <= 0)
+ {
+ if (re->re_owner)
+ framesize = re->re_owner->rd_graphblock;
+ else
+ {
+ loudbug_bug("rdremote_setframesize 2");
+ return (0);
+ }
+ }
+ re->re_npoints = framesize * re->re_nframes;
+ if (re->re_npoints > re->re_datasize)
+ {
+ int reqsize = re->re_npoints;
+ /* LATER use grow_withdata() */
+ re->re_data = grow_nodata(&re->re_npoints, &re->re_datasize,
+ re->re_data, RDREMOTE_INISIZE,
+ re->re_inidata, sizeof(*re->re_data));
+ if (re->re_npoints != reqsize)
+ {
+ re->re_nframes = re->re_npoints / framesize;
+ if (re->re_nframes < 1)
+ {
+ loudbug_bug("rdremote_setframesize 3");
+ re->re_nframes = 1;
+ framesize = re->re_npoints;
+ }
+ }
+ }
+ /* LATER convert old buffer's contents of re->re_framesize * re->re_nframes
+ points into the new buffer of framesize * re->re_nframes points */
+ memset(re->re_data, 0, re->re_npoints * sizeof(*re->re_data));
+ re->re_phase = 0; /* LATER adjust */
+ re->re_maxphase = re->re_npoints - framesize;
+ re->re_framesize = framesize;
+
+ for (reader = re->re_readers; reader; reader = reader->re_next)
+ {
+ reader->re_nframes = re->re_nframes;
+ reader->re_framesize = re->re_framesize;
+ reader->re_npoints = re->re_npoints;
+ reader->re_maxphase = re->re_maxphase;
+ reader->re_data = re->re_data;
+ reader->re_phase = 0; /* LATER adjust */
+ }
+ return (framesize);
+}
+
+void rdremote_setoutblock(t_rdremote *re, int nblock)
+{
+ if (nblock = rdremote_setframesize(re, nblock))
+ {
+ t_rdremote *reader;
+ for (reader = re->re_readers; reader; reader = reader->re_next)
+ if (reader->re_owner && reader->re_id > 0)
+ riddle_setsourceblock(reader->re_owner, -reader->re_id,
+ re->re_framesize);
+ }
+}
+
+void rdremote_setoutlayout(t_rdremote *re, t_symbol *pattern, int maxblock)
+{
+ if (maxblock = rdremote_setframesize(re, maxblock))
+ {
+ t_rdremote *reader;
+ for (reader = re->re_readers; reader; reader = reader->re_next)
+ if (reader->re_owner && reader->re_id > 0)
+ riddle_setsourcelayout(reader->re_owner, -reader->re_id,
+ pattern, re->re_framesize);
+ }
+}
+
+void rdremote_setoutflags(t_rdremote *re, int flags)
+{
+ t_rdremote *reader;
+ for (reader = re->re_readers; reader; reader = reader->re_next)
+ if (reader->re_owner && reader->re_id > 0)
+ riddle_setsourceflags(reader->re_owner, -reader->re_id, flags);
+}
+
+void rdremote_reset(t_rdremote *re)
+{
+ if (re->re_inidata)
+ {
+ memset(re->re_data, 0, re->re_npoints * sizeof(*re->re_data));
+ re->re_phase = 0;
+ }
+ else
+ {
+ t_rdremote *writer = rdremote_getwriter(re);
+ if (writer)
+ re->re_phase = writer->re_phase;
+ else
+ re->re_phase = 0;
+ }
+}
+
+t_float *rdremote_gethead(t_rdremote *re)
+{
+ return (re->re_data + re->re_phase);
+}
+
+void rdremote_stephead(t_rdremote *re)
+{
+ re->re_phase += re->re_framesize;
+ if (re->re_phase > re->re_maxphase)
+ re->re_phase = 0;
+}
+
+void rdremote_movehead(t_rdremote *re, int nframes)
+{
+ if (re->re_nframes <= 0)
+ {
+ loudbug_bug("rdremote_movehead");
+ }
+ else if (nframes > 0)
+ {
+ if (nframes >= re->re_nframes)
+ nframes = re->re_nframes - 1;
+ re->re_phase += nframes * re->re_framesize;
+ while (re->re_phase > re->re_maxphase)
+ re->re_phase -= re->re_npoints;
+ }
+ else if (nframes < 0)
+ {
+ nframes = -nframes;
+ if (nframes >= re->re_nframes)
+ nframes = re->re_nframes - 1;
+ re->re_phase -= nframes * re->re_framesize;
+ while (re->re_phase < 0)
+ re->re_phase += re->re_npoints;
+ }
+}
+
+void rdremote_delayhead(t_rdremote *re, int nframes)
+{
+ if (re->re_inidata)
+ loudbug_bug("rdremote_delayhead"); /* not a reader */
+ else
+ {
+ t_rdremote *writer = rdremote_getwriter(re);
+ if (writer)
+ {
+ re->re_phase = writer->re_phase;
+ rdremote_movehead(re, -nframes);
+ }
+ }
+}
+
+static void rdremote_free(t_rdremote *re)
+{
+ if (re->re_inidata)
+ {
+ if (re->re_data != re->re_inidata)
+ freebytes(re->re_data, re->re_datasize * sizeof(*re->re_data));
+ if (re->re_name)
+ {
+ t_rdremote *reader;
+ t_rdenvironment *en = rdenvironment_provide();
+ /* remove from the environment */
+ if (re->re_next)
+ re->re_next->re_prev = re->re_prev;
+ if (re->re_prev)
+ re->re_prev->re_next = re->re_next;
+ else
+ en->en_writers = re->re_next;
+ /* move all readers to the orphanage */
+ if (reader = re->re_readers)
+ {
+ while (reader->re_next)
+ reader = reader->re_next;
+ if (en->en_readers)
+ en->en_readers->re_prev = reader;
+ reader->re_next = en->en_readers;
+ en->en_readers = re->re_readers;
+ }
+ }
+ }
+ else
+ {
+ if (re->re_name)
+ {
+ /* remove from writer's list or orphanage */
+ if (re->re_next)
+ re->re_next->re_prev = re->re_prev;
+ if (re->re_prev)
+ re->re_prev->re_next = re->re_next;
+ else
+ {
+ t_rdenvironment *en = rdenvironment_provide();
+ t_rdremote *writer = rdenvironment_getbuffer(en, re->re_name);
+ if (writer)
+ writer->re_readers = re->re_next;
+ else
+ en->en_readers = re->re_next;
+ }
+ }
+ }
+ freebytes(re, sizeof(*re));
+}
+
+void rdremote_freeports(t_rdremote *re)
+{
+ while (re)
+ {
+ t_rdremote *nxt = re->re_portlink;
+ rdremote_free(re);
+ re = nxt;
+ }
+}
+
+/* FIXME do not rely on pd_new() callocing owner->rd_nremoteslots
+ and owner->rd_remoteports to zero... one option is to traverse
+ environment in riddle_new() after newfn call */
+static t_rdremote *rdremote_newany(t_riddle *owner, t_symbol *name, int nframes)
+{
+ t_rdremote *re = (t_rdremote *)getbytes(sizeof(*re));
+ if (name && !nframes)
+ {
+ owner->rd_nremoteslots++;
+ re->re_id = owner->rd_nremoteslots; /* starting from 1 */
+ }
+ else re->re_id = 0;
+ re->re_name = 0;
+ re->re_owner = owner;
+ re->re_phase = 0;
+ re->re_nframes = nframes;
+ re->re_framesize = 0;
+ re->re_npoints = 0;
+ re->re_maxphase = 0;
+ if (nframes)
+ {
+ re->re_datasize = RDREMOTE_INISIZE;
+ re->re_inidata = getbytes(re->re_datasize * sizeof(*re->re_inidata));
+ re->re_data = re->re_inidata;
+ }
+ else
+ {
+ re->re_datasize = 0;
+ re->re_inidata = 0;
+ re->re_data = 0;
+ }
+ re->re_readers = 0;
+ re->re_prev = 0;
+ re->re_next = 0;
+ if (owner->rd_remoteports)
+ {
+ t_rdremote *prv = owner->rd_remoteports;
+ while (prv->re_portlink)
+ prv = prv->re_portlink;
+ prv->re_portlink = re;
+ }
+ else owner->rd_remoteports = re;
+ re->re_portlink = 0;
+ return (re);
+}
+
+t_rdremote *rdremote_newwriter(t_riddle *owner, t_symbol *name, int nframes)
+{
+ if (name && *name->s_name)
+ {
+ t_rdremote *re =
+ rdremote_newany(owner, name, (nframes > 1 ? nframes : 1));
+ t_rdenvironment *en = rdenvironment_provide();
+ if (rdenvironment_getbuffer(en, re->re_name))
+ {
+ /* LATER accumulating writers case */
+ loud_error((t_pd *)owner, "duplicate buffer name \"%s\"",
+ re->re_name->s_name);
+ /* FIXME put on the namesakes queue */
+ }
+ else
+ {
+ t_rdremote *reader;
+ /* store in the environment */
+ if (en->en_writers)
+ en->en_writers->re_prev = re;
+ re->re_next = en->en_writers;
+ en->en_writers = re;
+ /* recover readers from the orphanage */
+ for (reader = en->en_readers; reader; reader = reader->re_next)
+ {
+ if (reader->re_name == re->re_name)
+ {
+ if (reader->re_next)
+ reader->re_next->re_prev = reader->re_prev;
+ if (reader->re_prev)
+ reader->re_prev->re_next = reader->re_next;
+ else
+ en->en_readers = reader->re_next;
+ if (re->re_readers)
+ re->re_readers->re_prev = reader;
+ reader->re_next = re->re_readers;
+ re->re_readers = reader;
+ }
+ }
+ }
+ return (re);
+ }
+ else
+ {
+ loudbug_bug("rdremote_newwriter");
+ return (0);
+ }
+}
+
+t_rdremote *rdremote_newreader(t_riddle *owner, t_symbol *name)
+{
+ if (name && *name->s_name)
+ {
+ t_rdremote *re = rdremote_newany(owner, name, 0);
+ t_rdenvironment *en = rdenvironment_provide();
+ t_rdremote *writer = rdenvironment_getbuffer(en, name);
+ if (writer)
+ {
+ /* register to the writer */
+ if (writer->re_readers)
+ writer->re_readers->re_prev = re;
+ re->re_next = writer->re_readers;
+ writer->re_readers = re;
+ }
+ else
+ {
+ /* store in the orphanage */
+ if (en->en_readers)
+ en->en_readers->re_prev = re;
+ re->re_next = en->en_readers;
+ en->en_readers = re;
+ }
+ return (re);
+ }
+ else
+ {
+ loudbug_bug("rdremote_newreader");
+ return (0);
+ }
+}
+
+t_rdremote *rdremote_newbuffer(t_riddle *owner, int nframes)
+{
+ return (rdremote_newany(owner, 0, (nframes > 1 ? nframes : 1)));
+}
diff --git a/riddle/riddle.c b/riddle/riddle.c
index 26e17e7..1348413 100644
--- a/riddle/riddle.c
+++ b/riddle/riddle.c
@@ -11,97 +11,70 @@
#include "common/grow.h"
#include "sickle/sic.h"
#include "riddle.h"
+#include "riddleguts.h"
/* obj_starttraverseoutlet, obj_nexttraverseoutlet, obj_noutlets,
obj_nsiginlets, obj_nsigoutlets, obj_siginletindex, obj_sigoutletindex,
obj_issignalinlet, obj_issignaloutlet */
#include "m_imp.h"
-/* struct _glist, canvas_class */
+/* struct _glist, canvas_class, vinlet_class */
#include "g_canvas.h"
-#define RIDDLE_DEBUG
+/* it is horrible, but we need x_canvas and x_parentoutlet and o_next for
+ pushing through an outlet~, which is here for the completeness of the tests;
+ LATER remove from library version, unless there is an API way to do it... */
-typedef struct _rdenvironment
+/* from g_io.c */
+typedef struct _rdvoutlet
{
- t_pd re_pd;
- t_rdpool *re_graphpools;
- t_rdbuffer *re_writers;
- t_rdbuffer *re_readers; /* list of orphaned readers */
- t_clock *re_updatedspclock;
-} t_rdenvironment;
-
-static t_class *rdenvironment_class = 0;
-
-struct _rdsource
+ t_object x_obj;
+ t_canvas *x_canvas;
+ t_outlet *x_parentoutlet;
+ /* ... */
+} t_rdvoutlet;
+
+/* from m_obj.c */
+typedef struct _rdoutlet
{
- t_riddle *ri_riddle;
- int ri_sourcecount;
- t_symbol *ri_pattern;
- t_symbol *ri_newpattern;
- int ri_block; /* if non-zero pattern: largest expected block */
- int ri_newblock;
-};
+ t_object *o_owner;
+ struct _rdoutlet *o_next;
+ /* ... */
+} t_rdoutlet;
-struct _rdsink
+#define RIDDLE_DEBUG
+
+struct _rdprivate
{
- t_riddle *ro_riddle;
- int ro_outno;
- t_symbol *ro_pattern;
- int ro_block; /* if non-zero pattern: largest expected block */
- t_atom ro_outbuf[3]; /* siginno, pattern, block */
- int ro_isready;
- int ro_isstrict; /* if set: non-riddle sinks are rejected */
+ t_outconnect *pr_oc;
};
-#define RDPOOL_INISIZE 64
-
-typedef struct _rdlink
-{
- t_symbol *rl_key;
- int rl_size;
- int rl_maxsize;
- t_float *rl_data;
- t_float rl_inidata[RDPOOL_INISIZE];
- struct _rdlink *rl_next;
-} t_rdlink;
-
-struct _rdpool
+struct _rdsource
{
- t_canvas *rp_graph;
- int rp_refcount;
- t_rdlink *rp_links;
- t_rdpool *rp_prev;
- t_rdpool *rp_next;
+ t_riddle *so_riddle;
+ t_rdremote *so_remote;
+ int so_sourcecount;
+ t_symbol *so_pattern;
+ t_symbol *so_newpattern;
+ int so_block; /* if non-zero pattern: largest expected block */
+ int so_newblock;
+ int so_flags;
};
-#define RDBUFFER_INISIZE 1024
-
-struct _rdbuffer
+struct _rdsink
{
- t_symbol *rb_name;
- t_riddle *rb_owner;
- int rb_phase;
- t_rdbuffer *rb_prev;
- t_rdbuffer *rb_next;
-
- /* common part, copied from writer to all its readers
- immediately after any change */
- int rb_nframes;
- int rb_framesize;
- int rb_npoints;
- int rb_maxphase;
- t_float *rb_buf;
-
- /* writer-specific part */
- t_rdbuffer *rb_readers;
- int rb_bufsize;
- t_float *rb_bufini;
+ t_riddle *si_riddle;
+ int si_outno;
+ t_symbol *si_pattern;
+ int si_block; /* if non-zero pattern: largest expected block */
+ int si_flags;
+ t_atom si_outbuf[4]; /* siginno, pattern, block, flags */
+ t_rdfeedchain *si_feedchain;
+ int si_isready;
};
/* these are filled in riddle_setup() */
static t_symbol *rdps__reblock = 0;
-static t_symbol *rdps__idle = 0;
static t_symbol *rdps__ = 0;
void riddlebug_post(t_riddle *rd, char *pfx, char *fmt, ...)
@@ -123,221 +96,6 @@ void riddlebug_post(t_riddle *rd, char *pfx, char *fmt, ...)
#endif
}
-static void riddle_updatedsptick(t_rdenvironment *re)
-{
- canvas_update_dsp();
-}
-
-static void rdenvironment_anything(t_rdenvironment *re,
- t_symbol *s, int ac, t_atom *av)
-{
- /* FIXME */
-}
-
-static t_rdenvironment *rdenvironment_provide(void)
-{
- t_rdenvironment *re;
- t_symbol *ps__riddle = gensym("_riddle");
- t_symbol *ps_hashriddle = gensym("#riddle");
- if (ps_hashriddle->s_thing)
- {
- char *cname = class_getname(*ps_hashriddle->s_thing);
- if (strcmp(cname, ps__riddle->s_name))
- {
- /* FIXME protect against the danger of someone else
- (e.g. receive) binding to #riddle */
- loudbug_bug("rdenvironment_provide");
- }
- else
- {
- /* FIXME compatibility test */
- rdenvironment_class = *ps_hashriddle->s_thing;
- return ((t_rdenvironment *)ps_hashriddle->s_thing);
- }
- }
- rdenvironment_class = class_new(ps__riddle, 0, 0,
- sizeof(t_rdenvironment),
- CLASS_PD | CLASS_NOINLET, 0);
- class_addanything(rdenvironment_class, rdenvironment_anything);
- re = (t_rdenvironment *)pd_new(rdenvironment_class); /* never freed */
- re->re_graphpools = 0;
- re->re_writers = 0;
- re->re_readers = 0;
- re->re_updatedspclock = clock_new(re, (t_method)riddle_updatedsptick);
- pd_bind((t_pd *)re, ps_hashriddle); /* never unbound */
- return (re);
-}
-
-static t_rdpool *rdpool_attach(t_rdenvironment *re, t_canvas *graph)
-{
- t_rdpool *rp;
- for (rp = re->re_graphpools; rp; rp = rp->rp_next)
- if (rp->rp_graph == graph)
- break;
- if (rp)
- rp->rp_refcount++;
- else
- {
- rp = getbytes(sizeof(*rp));
- rp->rp_graph = graph;
- rp->rp_refcount = 1;
- rp->rp_links = 0;
- rp->rp_prev = 0;
- if (re->re_graphpools)
- re->re_graphpools->rp_prev = rp;
- rp->rp_next = re->re_graphpools;
- re->re_graphpools = rp;
- }
- return (rp);
-}
-
-static void rdpool_detach(t_rdpool *rp, t_rdenvironment *re)
-{
- if (rp->rp_refcount > 1)
- rp->rp_refcount--;
- else
- {
- while (rp->rp_links)
- {
- t_rdlink *rl = rp->rp_links;
- rp->rp_links = rl->rl_next;
- if (rl->rl_data)
- freebytes(rl->rl_data, rl->rl_size * sizeof(*rl->rl_data));
- freebytes(rl, sizeof(*rl));
- }
- if (rp->rp_prev)
- rp->rp_prev->rp_next = rp->rp_next;
- else
- re->re_graphpools = rp->rp_next;
- if (rp->rp_next)
- rp->rp_next->rp_prev = rp->rp_prev;
- freebytes(rp, sizeof(*rp));
- }
-}
-
-static void rdpool_setthis(t_rdpool *rp,
- t_symbol *key, int size, t_float *data)
-{
- t_rdlink *rl;
- for (rl = rp->rp_links; rl; rl = rl->rl_next)
- if (rl->rl_key == key)
- break;
- if (!rl)
- {
- rl = getbytes(sizeof(*rl));
- rl->rl_key = key;
- rl->rl_maxsize = RDPOOL_INISIZE;
- rl->rl_data = rl->rl_inidata;
- rl->rl_next = rp->rp_links;
- rp->rp_links = rl;
- }
- if (size > rl->rl_maxsize)
- rl->rl_data = grow_nodata(&size, &rl->rl_maxsize, rl->rl_data,
- RDPOOL_INISIZE, rl->rl_inidata,
- sizeof(*rl->rl_data));
- rl->rl_size = size;
- memcpy(rl->rl_data, data, size * sizeof(*rl->rl_data));
-}
-
-static void rdpool_proliferate(t_rdpool *rphead, t_gobj *g,
- t_symbol *key, int size, t_float *data)
-{
- for (; g; g = g->g_next)
- {
- if (pd_class((t_pd *)g) == canvas_class)
- {
- t_canvas *graph = (t_canvas *)g;
- t_rdpool *rp;
- for (rp = rphead; rp; rp = rp->rp_next)
- if (rp->rp_graph == graph)
- break;
- if (rp)
- rdpool_setthis(rp, key, size, data);
- rdpool_proliferate(rphead, graph->gl_list, key, size, data);
- }
- }
-}
-
-/* LATER setcache */
-void rdpool_set(t_rdpool *rp, t_symbol *key, int size, t_float *data)
-{
- t_rdenvironment *re = rdenvironment_provide();
- rdpool_setthis(rp, key, size, data);
- rdpool_proliferate(re->re_graphpools, (t_gobj *)rp->rp_graph,
- key, size, data);
-}
-
-/* LATER setcache */
-void rdpool_setbygraph(t_canvas *graph, t_symbol *key, int size, t_float *data)
-{
- t_rdenvironment *re = rdenvironment_provide();
- t_rdpool *rp;
- for (rp = re->re_graphpools; rp; rp = rp->rp_next)
- if (rp->rp_graph == graph)
- break;
- if (rp)
- rdpool_setthis(rp, key, size, data);
- rdpool_proliferate(re->re_graphpools, (t_gobj *)graph, key, size, data);
-}
-
-t_float *rdpool_get(t_rdpool *rp, t_symbol *key, int *sizep)
-{
- t_rdlink *rl;
- for (rl = rp->rp_links; rl; rl = rl->rl_next)
- {
- if (rl->rl_key == key)
- {
- *sizep = rl->rl_size;
- return (rl->rl_data);
- }
- }
- return (0);
-}
-
-t_float *riddle_getlink(t_riddle *rd, t_symbol *key, int *sizep)
-{
- return (rdpool_get(rd->rd_graphpool, key, sizep));
-}
-
-/* LATER traversal api */
-t_canvas *riddle_getgraph(t_riddle *rd, int sigoutno)
-{
- t_outlet *op;
- int outno = rd->rd_outslots[sigoutno].ro_outno;
- t_outconnect *oc = obj_starttraverseoutlet((t_object *)rd, &op, outno);
- while (oc)
- {
- t_object *dst;
- t_inlet *ip;
- int inno;
- oc = obj_nexttraverseoutlet(oc, &dst, &ip, &inno);
- if (dst)
- {
- int siginno = obj_siginletindex(dst, inno);
- if (siginno < 0)
- {
- /* should not happen, LATER rethink */
- break;
- }
- else if (pd_class((t_pd *)dst) != canvas_class)
- {
- loud_error((t_pd *)rd, "invalid connection (not to a canvas)");
- break;
- }
- else return ((t_canvas *)dst);
- }
- }
- return (0);
-}
-
-
-void riddle_updatedsp(void)
-{
- t_rdenvironment *re = rdenvironment_provide();
- loud_warning((t_pd *)re, 0, "...trying to reconstruct the dsp chain");
- clock_delay(re->re_updatedspclock, 0);
-}
-
int riddle_getsr(t_riddle *rd)
{
return (rd->rd_graphsr);
@@ -357,58 +115,49 @@ int riddle_getsourceblock(t_riddle *rd, int siginno)
}
else
{
- t_rdsource *slot = (siginno >= 0 ?
- rd->rd_inslots + siginno :
- rd->rd_remoteslots - ++siginno);
- return (slot->ri_pattern ? 0 : slot->ri_block);
+ t_rdsource *so = (siginno >= 0 ?
+ rd->rd_inslots + siginno :
+ rd->rd_remoteslots - ++siginno);
+ return (so->so_pattern ? 0 : so->so_block); /* FIXME disable? */
}
}
-t_symbol *riddle_getsourcepattern(t_riddle *rd, int siginno, int *maxblockp)
+t_symbol *riddle_getsourcelayout(t_riddle *rd, int siginno, int *maxblockp)
{
if (siginno >= rd->rd_nsiginlets || -siginno > rd->rd_nremoteslots)
{
- loudbug_bug("riddle_getsourcepattern");
+ loudbug_bug("riddle_getsourcelayout");
return (0);
}
else
{
- t_rdsource *slot = (siginno >= 0 ?
- rd->rd_inslots + siginno :
- rd->rd_remoteslots - ++siginno);
+ t_rdsource *so = (siginno >= 0 ?
+ rd->rd_inslots + siginno :
+ rd->rd_remoteslots - ++siginno);
if (maxblockp)
- *maxblockp = slot->ri_block;
- return (slot->ri_pattern);
+ *maxblockp = so->so_block;
+ return (so->so_pattern);
}
}
-int riddle_getoutblock(t_riddle *rd, int sigoutno)
+int riddle_getsourceflags(t_riddle *rd, int siginno)
{
- if (sigoutno >= rd->rd_nsigoutlets || sigoutno < 0)
- {
- loudbug_bug("riddle_getoutblock");
- return (0);
- }
- else return (rd->rd_outslots[sigoutno].ro_pattern ?
- 0 : rd->rd_outslots[sigoutno].ro_block);
-}
-
-t_symbol *riddle_getoutpattern(t_riddle *rd, int sigoutno, int *maxblockp)
-{
- if (sigoutno >= rd->rd_nsigoutlets || sigoutno < 0)
+ if (siginno >= rd->rd_nsiginlets || -siginno > rd->rd_nremoteslots)
{
- loudbug_bug("riddle_getoutpattern");
+ loudbug_bug("riddle_getsourceflags");
return (0);
}
else
{
- if (maxblockp)
- *maxblockp = rd->rd_outslots[sigoutno].ro_block;
- return (rd->rd_outslots[sigoutno].ro_pattern);
+ t_rdsource *so = (siginno >= 0 ?
+ rd->rd_inslots + siginno :
+ rd->rd_remoteslots - ++siginno);
+ return (so->so_flags);
}
}
-static void riddle_setsourceblock(t_riddle *rd, int siginno, int newblock)
+/* LATER rethink the remote case */
+void riddle_setsourceblock(t_riddle *rd, int siginno, int newblock)
{
int slotno = (siginno < 0 ? rd->rd_nsiginlets - siginno - 1 : siginno);
#ifdef RIDDLE_DEBUG
@@ -422,128 +171,186 @@ static void riddle_setsourceblock(t_riddle *rd, int siginno, int newblock)
"invalid source block on inlet %d: %d", siginno, newblock);
else
{
- t_rdsource *slot = rd->rd_inslots + slotno;
- /* LATER if (slot->ri_newpattern) complain */
- if (newblock == slot->ri_newblock)
- slot->ri_sourcecount++;
- else if (slot->ri_sourcecount > 0)
+ t_rdsource *so = rd->rd_inslots + slotno;
+ /* LATER if (so->so_newpattern) complain */
+ if (newblock == so->so_newblock)
+ so->so_sourcecount++;
+ else if (so->so_sourcecount > 0)
loud_error((t_pd *)rd,
"source block mismatch on inlet %d: %d != %d",
- siginno, newblock, slot->ri_newblock);
+ siginno, newblock, so->so_newblock);
else
{
- slot->ri_newblock = newblock;
- slot->ri_sourcecount = 1;
- if (siginno < 0)
- rd->rd_remotesource = 1;
+ so->so_newblock = newblock;
+ so->so_sourcecount = 1;
}
}
}
-/* LATER pattern validation and normalization (e.g. xXXX -> aAAA */
-static void riddle_setsourcepattern(t_riddle *rd, int siginno,
- t_symbol *newpattern, int maxblock)
+#define RDLAYOUT_MAXNVECTORS 32
+
+/* apart from normalization, this is used only as a sanity check; patterns
+ are never interpreted, they just have to match (after normalization) */
+static t_symbol *riddle_validatepattern(t_symbol *pattern)
+{
+ char *p = pattern->s_name, lc, uc;
+ switch (*p)
+ {
+ case 'a':
+ case 'A':
+ lc = 'b'; uc = 'A'; break;
+ case 'b':
+ lc = 'c'; uc = 'B'; break;
+ default:
+ lc = 0;
+ }
+ if (lc)
+ {
+ /* we require at least one vector for each size element */
+ int vused[RDLAYOUT_MAXNVECTORS], i;
+ for (i = 0; i < RDLAYOUT_MAXNVECTORS; i++)
+ vused[i] = 0;
+ if (*p == 'A')
+ vused[0] = 1;
+ for (p++; *p; p++)
+ {
+ if (*p == lc)
+ {
+ if (lc - 'a' < RDLAYOUT_MAXNVECTORS)
+ lc++, uc++;
+ else
+ break;
+ }
+ else if (*p >= 'A' && *p <= uc)
+ vused[*p - 'A'] = 1;
+ else
+ break;
+ }
+ if (!*p)
+ {
+ for (i = 0; i < lc - 'a'; i++)
+ if (!vused[i])
+ break;
+ if (i == lc - 'a')
+ {
+ if (*pattern->s_name == 'a') /* normalization */
+ pattern = gensym(pattern->s_name + 1);
+ return (pattern);
+ }
+ }
+ }
+ loudbug_bug("riddle_validatepattern");
+ return (0);
+}
+
+void riddle_setsourcelayout(t_riddle *rd, int siginno,
+ t_symbol *newpattern, int maxblock)
{
int slotno = (siginno < 0 ? rd->rd_nsiginlets - siginno - 1 : siginno);
#ifdef RIDDLE_DEBUG
- riddlebug_post(rd, "setsourcepattern", "%d (%d) %s %d",
+ riddlebug_post(rd, "setsourcelayout", "%d (%d) %s %d",
siginno, slotno, newpattern->s_name, maxblock);
#endif
if (siginno >= rd->rd_nsiginlets || -siginno > rd->rd_nremoteslots)
- loudbug_bug("riddle_setsourcepattern");
+ loudbug_bug("riddle_setsourcelayout");
else
{
- t_rdsource *slot = rd->rd_inslots + slotno;
- if (newpattern == slot->ri_newpattern)
- slot->ri_sourcecount++;
- else if (slot->ri_sourcecount > 0)
+ t_rdsource *so = rd->rd_inslots + slotno;
+ if (newpattern == so->so_newpattern)
+ so->so_sourcecount++;
+ else if (so->so_sourcecount > 0)
{
- if (slot->ri_newpattern)
+ if (so->so_newpattern)
loud_error((t_pd *)rd,
- "source pattern mismatch on inlet %d: %s != %s",
+ "source layout mismatch on inlet %d: %s != %s",
siginno, newpattern->s_name,
- slot->ri_newpattern->s_name);
+ so->so_newpattern->s_name);
else
loud_error((t_pd *)rd,
- "source pattern/block mismatch on inlet %d");
+ "source layout/block mismatch on inlet %d");
}
- else
+ else if (newpattern = riddle_validatepattern(newpattern))
{
- slot->ri_newpattern = newpattern;
+ so->so_newpattern = newpattern;
if (maxblock)
{
- if (maxblock > slot->ri_newblock)
- slot->ri_newblock = maxblock;
+ if (maxblock > so->so_newblock)
+ so->so_newblock = maxblock;
}
- else slot->ri_newblock = rd->rd_graphblock;
- slot->ri_sourcecount = 1;
- if (siginno < 0)
- rd->rd_remotesource = 1;
+ else so->so_newblock = rd->rd_graphblock;
+ so->so_sourcecount = 1;
}
}
}
+void riddle_setsourceflags(t_riddle *rd, int siginno, int flags)
+{
+ int slotno = (siginno < 0 ? rd->rd_nsiginlets - siginno - 1 : siginno);
+#ifdef RIDDLE_DEBUG
+ riddlebug_post(rd, "setsourceflags", "%d (%d) %d",
+ siginno, slotno, flags);
+#endif
+ if (siginno >= rd->rd_nsiginlets || -siginno > rd->rd_nremoteslots)
+ loudbug_bug("riddle_setsourceflags");
+ else
+ {
+ t_rdsource *so = rd->rd_inslots + slotno;
+ so->so_flags = flags;
+ }
+}
+
void riddle_setoutblock(t_riddle *rd, int sigoutno, int block)
{
- t_rdsink *slot;
#ifdef RIDDLE_DEBUG
riddlebug_post(rd, "setoutblock", "%d %d", sigoutno, block);
#endif
- if (sigoutno >= rd->rd_nsigoutlets)
+ if (sigoutno < 0 || sigoutno >= rd->rd_nsigoutlets)
loudbug_bug("riddle_setoutblock");
- else if (sigoutno < 0)
- {
- for (sigoutno = 0, slot = rd->rd_outslots;
- sigoutno < rd->rd_nsigoutlets; sigoutno++, slot++)
- {
- slot->ro_pattern = 0;
- slot->ro_block = block;
- slot->ro_outbuf[1].a_w.w_symbol = rdps__;
- slot->ro_outbuf[2].a_w.w_float = (t_float)block;
- slot->ro_isready = 1;
- }
- }
else
{
- slot = rd->rd_outslots + sigoutno;
- slot->ro_pattern = 0;
- slot->ro_block = block;
- slot->ro_outbuf[1].a_w.w_symbol = rdps__;
- slot->ro_outbuf[2].a_w.w_float = (t_float)block;
- slot->ro_isready = 1;
+ t_rdsink *si = rd->rd_outslots + sigoutno;
+ si->si_pattern = 0;
+ si->si_block = block;
+ si->si_outbuf[1].a_w.w_symbol = rdps__;
+ si->si_outbuf[2].a_w.w_float = (t_float)block;
+ si->si_isready = 1;
}
}
-void riddle_setoutpattern(t_riddle *rd, int sigoutno,
- t_symbol *pattern, int maxblock)
+void riddle_setoutlayout(t_riddle *rd, int sigoutno,
+ t_symbol *pattern, int maxblock)
{
- t_rdsink *slot;
#ifdef RIDDLE_DEBUG
- riddlebug_post(rd, "setoutpattern", "%d %s %d",
+ riddlebug_post(rd, "setoutlayout", "%d %s %d",
sigoutno, pattern->s_name, maxblock);
#endif
- if (sigoutno >= rd->rd_nsigoutlets)
- loudbug_bug("riddle_setoutpattern");
- else if (sigoutno < 0)
+ if (sigoutno < 0 || sigoutno >= rd->rd_nsigoutlets)
+ loudbug_bug("riddle_setoutlayout");
+ else if (pattern = riddle_validatepattern(pattern))
{
- for (sigoutno = 0, slot = rd->rd_outslots;
- sigoutno < rd->rd_nsigoutlets; sigoutno++, slot++)
- {
- slot->ro_pattern = pattern;
- slot->ro_block = maxblock;
- slot->ro_outbuf[1].a_w.w_symbol = pattern;
- slot->ro_outbuf[2].a_w.w_float = (t_float)maxblock;
- slot->ro_isready = 1;
- }
+ t_rdsink *si = rd->rd_outslots + sigoutno;
+ if (maxblock <= 0)
+ maxblock = rd->rd_graphblock;
+ si->si_pattern = pattern;
+ si->si_block = maxblock;
+ si->si_outbuf[1].a_w.w_symbol = pattern;
+ si->si_outbuf[2].a_w.w_float = (t_float)maxblock;
+ si->si_isready = 1;
}
+}
+
+void riddle_setoutflags(t_riddle *rd, int sigoutno, int flags)
+{
+#ifdef RIDDLE_DEBUG
+ riddlebug_post(rd, "setoutflags", "%d %d", sigoutno, flags);
+#endif
+ if (sigoutno < 0 || sigoutno >= rd->rd_nsigoutlets)
+ loudbug_bug("riddle_setoutflags");
else
{
- slot = rd->rd_outslots;
- slot->ro_pattern = pattern;
- slot->ro_block = maxblock;
- slot->ro_outbuf[1].a_w.w_symbol = pattern;
- slot->ro_outbuf[2].a_w.w_float = (t_float)maxblock;
- slot->ro_isready = 1;
+ t_rdsink *si = rd->rd_outslots + sigoutno;
+ si->si_flags = flags;
+ si->si_outbuf[3].a_w.w_float = (t_float)flags;
}
}
@@ -554,7 +361,7 @@ int riddle_checksourceblock(t_riddle *rd, int siginno, int reqblock)
return (1);
else
{
- if (!rd->rd_wasdisabled && rd->rd_inslots[siginno].ri_sourcecount)
+ if (!rd->rd_wasdisabled && rd->rd_inslots[siginno].so_sourcecount)
loud_error((t_pd *)rd,
"invalid source block on inlet %d: %d (%d expected)",
siginno, block, reqblock);
@@ -563,24 +370,24 @@ int riddle_checksourceblock(t_riddle *rd, int siginno, int reqblock)
}
}
-/* LATER pattern normalization (e.g. xXXX -> aAAA */
-int riddle_checksourcepattern(t_riddle *rd, int siginno,
- t_symbol *reqpattern, int *maxblockp)
+int riddle_checksourcelayout(t_riddle *rd, int siginno,
+ t_symbol *reqpattern, int *maxblockp)
{
- t_symbol *pattern = riddle_getsourcepattern(rd, siginno, maxblockp);
- if (pattern == reqpattern)
+ t_symbol *pattern = riddle_getsourcelayout(rd, siginno, maxblockp);
+ if (reqpattern == pattern ||
+ riddle_validatepattern(reqpattern) == pattern)
return (1);
else
{
- if (!rd->rd_wasdisabled && rd->rd_inslots[siginno].ri_sourcecount)
+ if (!rd->rd_wasdisabled && rd->rd_inslots[siginno].so_sourcecount)
{
if (pattern)
loud_error((t_pd *)rd,
- "wrong source pattern on inlet %d: %s (%s expected)",
+ "wrong source layout on inlet %d: %s (%s expected)",
siginno, pattern->s_name, reqpattern->s_name);
else
loud_error((t_pd *)rd,
- "invalid source on inlet %d: pattern %s expected",
+ "invalid source on inlet %d: layout %s expected",
siginno, reqpattern->s_name);
}
rd->rd_disabled = 1;
@@ -594,10 +401,10 @@ int riddle_checkanysource(t_riddle *rd, int siginno)
loudbug_bug("riddle_checkanysource");
else
{
- t_rdsource *slot = (siginno >= 0 ?
- rd->rd_inslots + siginno :
- rd->rd_remoteslots - ++siginno);
- if (slot->ri_sourcecount > 0)
+ t_rdsource *so = (siginno >= 0 ?
+ rd->rd_inslots + siginno :
+ rd->rd_remoteslots - ++siginno);
+ if (so->so_sourcecount > 0)
return (1);
}
rd->rd_disabled = 1;
@@ -611,9 +418,35 @@ int riddle_isdisabled(t_riddle *rd)
void riddle_disable(t_riddle *rd)
{
+ /* FIXME allow calling from the dsp routine (mute then) */
rd->rd_disabled = 1;
}
+t_rdfeedchain *riddle_getfeedchain(t_riddle *rd, int sigoutno)
+{
+ if (sigoutno < 0 || sigoutno >= rd->rd_nsigoutlets)
+ {
+ loudbug_bug("riddle_getfeedchain 1");
+ return (0);
+ }
+ else
+ {
+ t_rdsink *si = rd->rd_outslots + sigoutno;
+ if (si->si_outno >= 0)
+ {
+ /* LATER update ch_outno */
+ return (si->si_feedchain);
+ }
+ else
+ {
+ loudbug_bug("riddle_getfeedchain 2");
+ return (0);
+ }
+ }
+}
+
+/* ensures that sinks match signal outlets -- this is needed in the constructor,
+ but is called before each push, perhaps too defensively... LATER rethink */
static int riddle_validatesinks(t_riddle *rd)
{
t_object *x = (t_object *)rd;
@@ -624,10 +457,10 @@ static int riddle_validatesinks(t_riddle *rd)
{
if (sigoutno < rd->rd_nsigoutlets)
{
- if (rd->rd_outslots[sigoutno].ro_outno != outno)
+ if (rd->rd_outslots[sigoutno].si_outno != outno)
{
- if (rd->rd_outslots[sigoutno].ro_outno < 0)
- rd->rd_outslots[sigoutno].ro_outno = outno;
+ if (rd->rd_outslots[sigoutno].si_outno < 0)
+ rd->rd_outslots[sigoutno].si_outno = outno;
else
{
loudbug_bug("riddle_validatesinks 1");
@@ -653,12 +486,46 @@ static int riddle_validatesinks(t_riddle *rd)
return (1);
}
-static int rdsink_push(t_rdsink *slot)
+t_canvas *riddle_nextgraph(t_riddle *rd)
+{
+ while (rd->rd_private->pr_oc)
+ {
+ t_object *dst;
+ t_inlet *ip;
+ int inno;
+ rd->rd_private->pr_oc =
+ obj_nexttraverseoutlet(rd->rd_private->pr_oc, &dst, &ip, &inno);
+ if (dst)
+ {
+ int siginno = obj_siginletindex(dst, inno);
+ if (siginno < 0)
+ {
+ /* should not happen, LATER rethink */
+ break;
+ }
+ else if (pd_class((t_pd *)dst) != canvas_class)
+ {
+ loud_error((t_pd *)rd, "invalid connection (not to a canvas)");
+ break;
+ }
+ else return ((t_canvas *)dst);
+ }
+ }
+ return (0);
+}
+
+t_canvas *riddle_firstgraph(t_riddle *rd, int outno)
+{
+ t_outlet *op;
+ rd->rd_private->pr_oc = obj_starttraverseoutlet((t_object *)rd, &op, outno);
+ return (rd->rd_private->pr_oc ? riddle_nextgraph(rd) : 0);
+}
+
+static int rdsink_push(t_rdsink *si, t_object *x, int outno)
{
int result = 1;
- t_object *x = (t_object *)slot->ro_riddle;
t_outlet *op;
- t_outconnect *oc = obj_starttraverseoutlet(x, &op, slot->ro_outno);
+ t_outconnect *oc = obj_starttraverseoutlet(x, &op, outno);
while (oc)
{
t_object *dst;
@@ -672,18 +539,83 @@ static int rdsink_push(t_rdsink *slot)
{
/* should not happen, LATER rethink */
}
- /* LATER unify isriddle test as zgetfn(..., gensym("dspblock")) */
else if (zgetfn((t_pd *)dst, rdps__reblock))
{
- slot->ro_outbuf->a_w.w_float = (t_float)siginno;
- typedmess((t_pd *)dst, rdps__reblock, 3, slot->ro_outbuf);
+ si->si_outbuf->a_w.w_float = (t_float)siginno;
+ typedmess((t_pd *)dst, rdps__reblock, 4, si->si_outbuf);
}
- else if (slot->ro_isstrict)
+ else if (pd_class((t_pd *)dst) == canvas_class)
+ {
+ t_gobj *ob;
+ int i;
+ for (i = 0, ob = ((t_canvas *)dst)->gl_list;
+ ob; ob = ob->g_next)
+ {
+ if (pd_class((t_pd *)ob) == vinlet_class)
+ {
+ if (i == inno)
+ break;
+ else
+ i++;
+ }
+ }
+ if (ob)
+ {
+#ifdef RIDDLE_DEBUG
+ riddlebug_post(si->si_riddle, "PUSH-SUBCANVAS",
+ "vinlet %d (\"%s\")",
+ inno, class_getname(*(t_pd *)ob));
+#endif
+ rdsink_push(si, (t_object *)ob, 0);
+ }
+ else loudbug_bug("rdsink_push 1");
+ }
+ else if (pd_class((t_pd *)dst) == voutlet_class)
+ {
+ t_rdvoutlet *vout = (t_rdvoutlet *)dst;
+ if (vout->x_canvas)
+ {
+ int n;
+ t_outlet *o;
+ for (o = ((t_object *)vout->x_canvas)->ob_outlet, n = 0;
+ o; o = (t_outlet *)(((t_rdoutlet *)o)->o_next), n++)
+ if (o == vout->x_parentoutlet)
+ break;
+ if (o)
+ {
+#ifdef RIDDLE_DEBUG
+ riddlebug_post(si->si_riddle, "PUSH-OUTLET",
+ "outno %d, graph %x",
+ n, (int)vout->x_canvas);
+#endif
+ rdsink_push(si, (t_object *)vout->x_canvas, n);
+ }
+ else loudbug_bug("rdsink_push 2");
+ }
+#ifdef RIDDLE_DEBUG
+ else riddlebug_post(si->si_riddle, "PUSH-OUTLET",
+ "void canvas...");
+#endif
+ }
+ else
{
char *dstname = class_getname(*(t_pd *)dst);
- if (strcmp(dstname, "print~"))
+#ifdef RIDDLE_DEBUG
+ riddlebug_post(si->si_riddle, "PUSH-RIDDLESS",
+ "inlet %d (\"%s\")", inno, dstname);
+#endif
+ if (si->si_flags & RIDDLE_STRICTNESSMASK)
{
- loud_error((t_pd *)x, "not a riddle: \"%s\"", dstname);
+ if (strcmp(dstname, "print~"))
+ {
+ loud_error((t_pd *)x, "not a riddle: \"%s\"", dstname);
+ result = 0;
+ }
+ }
+ else if (!strcmp(dstname, "send~") ||
+ !strcmp(dstname, "throw~"))
+ {
+ loud_error((t_pd *)x, "bad destination: \"%s\"", dstname);
result = 0;
}
}
@@ -692,10 +624,10 @@ static int rdsink_push(t_rdsink *slot)
return (result);
}
-void riddle_mute(t_riddle *rd, t_signal **sp)
+static void riddle_mute(t_riddle *rd, t_signal **sp)
{
int i, j, nouts = obj_nsigoutlets((t_object *)rd);
- t_rdsink *slot = rd->rd_outslots;
+ t_rdsink *si = rd->rd_outslots;
#ifdef RIDDLE_DEBUG
riddlebug_post(rd, "MUTE", 0);
#endif
@@ -710,14 +642,14 @@ void riddle_mute(t_riddle *rd, t_signal **sp)
j = obj_nsiginlets((t_object *)rd);
while (nouts--)
{
- slot->ro_pattern = 0;
- slot->ro_block = sp[j]->s_n;
- slot->ro_outbuf[1].a_w.w_symbol = rdps__;
- slot->ro_outbuf[2].a_w.w_float = (t_float)slot->ro_block;
- slot->ro_isready = 1;
+ si->si_pattern = 0;
+ si->si_block = sp[j]->s_n;
+ si->si_outbuf[1].a_w.w_symbol = rdps__;
+ si->si_outbuf[2].a_w.w_float = (t_float)si->si_block;
+ si->si_isready = 1;
dsp_add_zero(sp[j]->s_vec, sp[j]->s_n);
i++; j++;
- slot++;
+ si++;
}
}
@@ -736,13 +668,14 @@ static void riddle_dsp(t_riddle *rd, t_signal **sp)
for (inslotno = 0, inslot = rd->rd_inslots;
inslotno < ninslots; inslotno++, inslot++)
loudbug_post("%d sources: %d reblocks of %d -> %d",
- inslotno, inslot->ri_sourcecount,
- inslot->ri_block, inslot->ri_newblock);
+ inslotno, inslot->so_sourcecount,
+ inslot->so_block, inslot->so_newblock);
#endif
rd->rd_graphsr = (int)sp[0]->s_sr;
rd->rd_graphblock = sp[0]->s_n;
+ /* this belongs to step 2., but should precede all "muteandreset" gotos */
if (rd->rd_wasdisabled = rd->rd_disabled)
{
rd->rd_disabled = 0;
@@ -750,53 +683,71 @@ static void riddle_dsp(t_riddle *rd, t_signal **sp)
doreblock = 1;
else
{
- loudbug_bug("riddle_dsp 2");
+ loudbug_bug("riddle_dsp 1");
goto muteandreset;
}
}
- /* verify all source slots */
+ /* step 1: verify all source slots */
+
for (inslotno = 0, inslot = rd->rd_inslots;
inslotno < ninslots; inslotno++, inslot++)
{
- if (inslot->ri_newblock > rd->rd_graphblock)
+ if (inslot->so_newblock > rd->rd_graphblock)
{
- loud_error((t_pd *)rd,
- "inslot %d: source block too large (%d > %d)",
- inslotno, inslot->ri_newblock, rd->rd_graphblock);
- failed = 1;
+ if (inslotno < rd->rd_nsiginlets)
+ {
+ loud_error((t_pd *)rd,
+ "inslot %d: source block too large (%d > %d)",
+ inslotno, inslot->so_newblock, rd->rd_graphblock);
+ failed = 1;
+ }
}
- else if (inslot->ri_sourcecount <= 0)
+ else if (inslot->so_sourcecount <= 0)
{
- if (rd->rd_remotesource) /* this is an `issticky' flag -- it tells
- if unconfirmed sourceblock should be
- preserved or bashed to graphblock */
+ if (inslotno < rd->rd_nsiginlets)
{
- inslot->ri_newpattern = inslot->ri_pattern;
- if (inslot->ri_block > 0)
- inslot->ri_newblock = inslot->ri_block;
- else
- inslot->ri_newblock = rd->rd_graphblock;
+ /* bash unconfirmed declarations to graphblock */
+ inslot->so_newpattern = 0;
+ inslot->so_newblock = rd->rd_graphblock;
}
- else
+ else if (inslot->so_remote)
{
- inslot->ri_newpattern = 0;
- inslot->ri_newblock = rd->rd_graphblock;
+ if (rdremote_getwriter(inslot->so_remote))
+ {
+ loud_warning((t_pd *)rd, 0, "misplaced buffer reader...");
+ riddle_updatedsp();
+ failed = 1; /* LATER rethink */
+ }
+ else
+ {
+ loud_warning((t_pd *)rd, 0, "orphaned buffer reader");
+
+ /* remote slots preserve unconfirmed declarations */
+ inslot->so_newpattern = inslot->so_pattern;
+ if (inslot->so_block > 0)
+ inslot->so_newblock = inslot->so_block;
+ else
+ inslot->so_newblock = rd->rd_graphblock;
+ }
}
+ else loudbug_bug("riddle_dsp 2");
}
- else if (inslot->ri_newblock <= 0) /* should not happen */
+ else if (inslot->so_newblock <= 0) /* should not happen */
{
- loudbug_bug("riddle_dsp 1");
+ loudbug_bug("riddle_dsp 3");
failed = 1;
}
}
if (failed)
goto muteandreset;
- /* determine outblock sizes -- blockfn fires on the very first call
- to riddle_dsp(), and then after any change of block or sr,
- and each time the object is disabled...
- LATER reconsider reblocking during every dsp call... */
+ /* step 2: determine outslot sizes/layouts -- blockfn fires on the very
+ first call to riddle_dsp(), and then after any change of block or sr,
+ and each time the object is disabled... LATER reconsider the pros
+ and cons of performing the reblocking during every dsp call */
+
+ /* 2a: was there any change of inslot size/layout or graph block/sr? */
if (!doreblock && rd->rd_blockfn)
{
if (rd->rd_graphsr != oldgraphsr ||
@@ -805,8 +756,8 @@ static void riddle_dsp(t_riddle *rd, t_signal **sp)
else for (inslotno = 0, inslot = rd->rd_inslots;
inslotno < ninslots; inslotno++, inslot++)
{
- if (inslot->ri_newpattern != inslot->ri_pattern ||
- inslot->ri_newblock != inslot->ri_block)
+ if (inslot->so_newpattern != inslot->so_pattern ||
+ inslot->so_newblock != inslot->so_block)
{
doreblock = 1;
break;
@@ -814,23 +765,25 @@ static void riddle_dsp(t_riddle *rd, t_signal **sp)
}
}
+ /* 2b: update the inslots, reset the outslots */
if (doreblock || !rd->rd_blockfn)
{
- for (outslotno = 0, outslot = rd->rd_outslots;
- outslotno < rd->rd_nsigoutlets; outslotno++, outslot++)
- {
- outslot->ro_pattern = 0;
- outslot->ro_block = 0;
- outslot->ro_isready = 0;
- }
for (inslotno = 0, inslot = rd->rd_inslots;
inslotno < ninslots; inslotno++, inslot++)
{
- inslot->ri_pattern = inslot->ri_newpattern;
- inslot->ri_block = inslot->ri_newblock;
+ inslot->so_pattern = inslot->so_newpattern;
+ inslot->so_block = inslot->so_newblock;
+ }
+ for (outslotno = 0, outslot = rd->rd_outslots;
+ outslotno < rd->rd_nsigoutlets; outslotno++, outslot++)
+ {
+ outslot->si_pattern = 0;
+ outslot->si_block = 0;
+ outslot->si_isready = 0;
}
}
+ /* 2c: call the instance-specific method which redeclares the outslots */
if (doreblock)
{
#ifdef RIDDLE_DEBUG
@@ -841,20 +794,24 @@ static void riddle_dsp(t_riddle *rd, t_signal **sp)
goto muteandreset;
}
+ /* 2d: assign defaults to undeclared outslots */
for (outslotno = 0, outslot = rd->rd_outslots;
outslotno < rd->rd_nsigoutlets; outslotno++, outslot++)
{
- if (outslot->ro_block < 0)
+ if (outslot->si_block < 0)
{
- loudbug_bug("riddle_dsp 3");
+ loudbug_bug("riddle_dsp 4");
failed = 1;
}
- else if (outslot->ro_block == 0)
- outslot->ro_block = rd->rd_graphblock;
+ else if (outslot->si_block == 0)
+ outslot->si_block = rd->rd_graphblock;
}
+ /* LATER think about not redeclared remote writers */
if (failed)
goto muteandreset;
+ /* step 3: transfer outslot declarations down to destination objects */
+
#ifdef RIDDLE_DEBUG
riddlebug_post(rd, "PUSH", 0);
#endif
@@ -862,19 +819,27 @@ static void riddle_dsp(t_riddle *rd, t_signal **sp)
{
for (outslotno = 0, outslot = rd->rd_outslots;
outslotno < rd->rd_nsigoutlets; outslotno++, outslot++)
- if (outslot->ro_isready && rdsink_push(outslot) == 0)
+ if (outslot->si_isready &&
+ rdsink_push(outslot, (t_object *)rd, outslot->si_outno) == 0)
failed = 1;
}
else failed = 1;
+ /* remote declarations are propagated directly from within
+ rdremote_setoutblock/layout(), cf. rdremote_pushblock/layout() */
if (failed)
goto muteandreset;
+
+ /* step 4: call the wrappee */
+
if (rd->rd_dspfn)
{
rd->rd_dspfn(rd, sp);
unarmed = 0;
}
- else loudbug_bug("riddle_dsp 4");
+ else loudbug_bug("riddle_dsp 5");
+
+ /* step 5: mute if disabled, then reset the inslots */
muteandreset:
if (unarmed)
@@ -885,40 +850,54 @@ muteandreset:
for (inslotno = 0, inslot = rd->rd_inslots;
inslotno < ninslots; inslotno++, inslot++)
{
- inslot->ri_newpattern = 0;
- inslot->ri_newblock = 0;
- inslot->ri_sourcecount = 0;
+ inslot->so_newpattern = 0;
+ inslot->so_newblock = 0;
+ inslot->so_sourcecount = 0;
}
- rd->rd_remotesource = 0;
}
-static void riddle__reblock(t_riddle *rd,
- t_symbol *pattern, t_floatarg f1, t_floatarg f2)
+static void riddle__reblock(t_riddle *rd, t_symbol *pattern,
+ t_floatarg f1, t_floatarg f2, t_floatarg f3)
{
+ riddle_setsourceflags(rd, (int)f1, (int)f3);
if (pattern == rdps__)
riddle_setsourceblock(rd, (int)f1, (int)f2);
- /* LATER replace with full validation done in riddle_setsourcepattern() */
- else if (pattern && *pattern->s_name == 'a')
- riddle_setsourcepattern(rd, (int)f1, pattern, (int)f2);
+ else if (pattern)
+ riddle_setsourcelayout(rd, (int)f1, pattern, (int)f2);
else
loud_error((t_pd *)rd, "bad arguments to '_reblock'");
}
static void riddle_free(t_riddle *rd)
{
- int nslots;
t_gotfn freefn = zgetfn((t_pd *)rd, gensym("_free"));
if (freefn)
freefn(rd);
- rdpool_detach(rd->rd_graphpool, rdenvironment_provide());
+ if (rd->rd_private)
+ freebytes(rd->rd_private, sizeof(*rd->rd_private));
- nslots = rd->rd_nsiginlets + rd->rd_nremoteslots;
if (rd->rd_inslots)
+ {
+ int nslots = rd->rd_nsiginlets + rd->rd_nremoteslots;
freebytes(rd->rd_inslots, nslots * sizeof(*rd->rd_inslots));
+ }
+
if (rd->rd_outslots)
+ {
+ t_rdsink *si;
+ int i;
+ for (i = 0, si = rd->rd_outslots; i < rd->rd_nsigoutlets; i++, si++)
+ if (si->si_feedchain)
+ rdfeedchain_free(si->si_feedchain);
freebytes(rd->rd_outslots,
rd->rd_nsigoutlets * sizeof(*rd->rd_outslots));
+ }
+
+ rdremote_freeports(rd->rd_remoteports);
+
+ if (rd->rd_idlepicker)
+ rdpicker_detach(rd->rd_idlepicker, rd);
}
typedef t_pd *(*t_newgimme)(t_symbol *s, int argc, t_atom *argv);
@@ -926,8 +905,8 @@ typedef t_pd *(*t_newgimme)(t_symbol *s, int argc, t_atom *argv);
static void *riddle_new(t_symbol *s, int ac, t_atom *av)
{
/* IFBUILTIN remove: this is a bad hack */
- t_rdenvironment *re = rdenvironment_provide();
- t_newgimme newfn = (t_newgimme)zgetfn((t_pd *)re, s);
+ t_pd *en = riddle_getenvironment();
+ t_newgimme newfn = (t_newgimme)zgetfn(en, s);
if (!newfn)
{
loudbug_bug("riddle_new 1");
@@ -939,8 +918,12 @@ static void *riddle_new(t_symbol *s, int ac, t_atom *av)
int i, nslots;
t_rdsource *inslot;
t_rdsink *outslot;
+ t_rdremote *re;
if (!rd)
return (0);
+
+ rd->rd_private = getbytes(sizeof(*rd->rd_private));
+
rd->rd_disabled = 0;
rd->rd_wasdisabled = 0;
rd->rd_blockfn = (t_rdblockfn)zgetfn((t_pd *)rd, gensym("dspblock"));
@@ -948,53 +931,77 @@ static void *riddle_new(t_symbol *s, int ac, t_atom *av)
if (!rd->rd_dspfn)
loudbug_bug("riddle_new 2");
- rd->rd_graphpool = rdpool_attach(re, canvas_getcurrent());
-
rd->rd_graphsr = (int)sys_getsr();
rd->rd_graphblock = sys_getblksize();
rd->rd_nsiginlets = obj_nsiginlets((t_object *)rd);
rd->rd_nsigoutlets = obj_nsigoutlets((t_object *)rd);
- nslots = rd->rd_nsiginlets + rd->rd_nremoteslots;
+ /* currently, rd_nremoteslots is incremented in rdbuffer_newreader(),
+ which relies on calloc in pd_new(), LATER rethink */
+
+ nslots = rd->rd_nsiginlets + rd->rd_nremoteslots;
rd->rd_inslots = getbytes(nslots * sizeof(*rd->rd_inslots));
for (i = 0, inslot = rd->rd_inslots; i < nslots; i++, inslot++)
{
- inslot->ri_riddle = rd;
- inslot->ri_sourcecount = 0;
- inslot->ri_pattern = 0;
- inslot->ri_newpattern = 0;
- inslot->ri_block = 0;
- inslot->ri_newblock = 0;
+ inslot->so_riddle = rd;
+ inslot->so_remote = 0;
+ inslot->so_sourcecount = 0;
+ inslot->so_pattern = 0;
+ inslot->so_newpattern = 0;
+ inslot->so_block = 0;
+ inslot->so_newblock = 0;
+ inslot->so_flags = 0;
}
rd->rd_remoteslots = rd->rd_inslots + rd->rd_nsiginlets;
+ for (i = 0, inslot = rd->rd_remoteslots, re = rd->rd_remoteports;
+ i < rd->rd_nremoteslots; i++, inslot++)
+ {
+ if (re = rdremote_nextreader(re))
+ inslot->so_remote = re;
+ else
+ {
+ loudbug_bug("riddle_new 3");
+ break; /* FIXME this is fatal */
+ }
+ }
+
rd->rd_outslots =
getbytes(rd->rd_nsigoutlets * sizeof(*rd->rd_outslots));
for (i = 0, outslot = rd->rd_outslots;
i < rd->rd_nsigoutlets; i++, outslot++)
{
- outslot->ro_riddle = rd;
- outslot->ro_outno = -1;
- outslot->ro_pattern = 0;
- outslot->ro_block = 0;
- outslot->ro_outbuf[0].a_type = A_FLOAT;
- outslot->ro_outbuf[1].a_type = A_SYMBOL;
- outslot->ro_outbuf[1].a_w.w_symbol = rdps__;
- outslot->ro_outbuf[2].a_type = A_FLOAT;
- outslot->ro_isready = 0;
- outslot->ro_isstrict = 0; /* LATER rethink */
+ outslot->si_riddle = rd;
+ outslot->si_outno = -1;
+ outslot->si_pattern = 0;
+ outslot->si_block = 0;
+ outslot->si_flags = 0;
+ outslot->si_outbuf[0].a_type = A_FLOAT;
+ outslot->si_outbuf[1].a_type = A_SYMBOL;
+ outslot->si_outbuf[1].a_w.w_symbol = rdps__;
+ outslot->si_outbuf[2].a_type = A_FLOAT;
+ outslot->si_outbuf[3].a_type = A_FLOAT;
+ outslot->si_outbuf[3].a_w.w_float = 0.;
+ outslot->si_feedchain = 0;
+ outslot->si_isready = 0;
}
+
riddle_validatesinks(rd);
- /* currently, rd->rd_nremoteslots is incremented in
- rdbuffer_newreader(), LATER rethink */
+ for (i = 0, outslot = rd->rd_outslots;
+ i < rd->rd_nsigoutlets; i++, outslot++)
+ if (outslot->si_outno >= 0)
+ outslot->si_feedchain = rdfeedchain_new(outslot->si_outno);
+
+ rd->rd_idlepicker = rdpicker_attach(rd, gensym("_idle"));
- rd->rd_remotesource = 0;
return (rd);
}
}
/* IFBUILTIN remove: classes would use explicit class_addmethod calls */
+/* obligatory: newfn, dspfn */
+/* optional: freefn, blockfn, floatfn */
t_class *riddle_setup(t_symbol *name, t_newmethod newfn, t_method freefn,
size_t sz, t_method floatfn,
t_rdblockfn blockfn, t_rddspfn dspfn)
@@ -1003,327 +1010,43 @@ t_class *riddle_setup(t_symbol *name, t_newmethod newfn, t_method freefn,
(t_method)riddle_free, sz, 0, A_GIMME, 0);
/* IFBUILTIN remove: this is a bad hack */
- t_rdenvironment *re = rdenvironment_provide();
- class_addmethod(*(t_pd *)re, (t_method)newfn, name, 0);
+ t_pd *en = riddle_getenvironment();
+ class_addmethod(*en, (t_method)newfn, name, 0);
if (strlen(name->s_name) < 60)
{
char rdstr[64];
sprintf(rdstr, "rd.%s", name->s_name);
class_addcreator((t_newmethod)riddle_new, gensym(rdstr), A_GIMME, 0);
- class_addmethod(*(t_pd *)re, (t_method)newfn, gensym(rdstr), 0);
+ class_addmethod(*en, (t_method)newfn, gensym(rdstr), 0);
}
rdps__reblock = gensym("_reblock");
- rdps__idle = gensym("_idle");
rdps__ = gensym("_");
sic_setup(c, riddle_dsp, floatfn);
- class_addmethod(c, (t_method)blockfn, gensym("dspblock"), 0);
+ if (blockfn)
+ class_addmethod(c, (t_method)blockfn, gensym("dspblock"), 0);
/* IFBUILTIN "_dsp" -> "dsp" */
class_addmethod(c, (t_method)dspfn, gensym("_dsp"), 0);
/* IFBUILTIN remove these two */
class_addmethod(c, (t_method)newfn, gensym("_new"), 0);
- class_addmethod(c, (t_method)freefn, gensym("_free"), 0);
+ if (freefn)
+ class_addmethod(c, (t_method)freefn, gensym("_free"), 0);
class_addmethod(c, (t_method)riddle__reblock,
- rdps__reblock, A_FLOAT, A_SYMBOL, A_FLOAT, 0);
+ rdps__reblock, A_FLOAT, A_SYMBOL, A_FLOAT, A_FLOAT, 0);
return (c);
}
-static t_rdbuffer *rdenvironment_getbuffer(t_rdenvironment *re, t_symbol *name)
-{
- t_rdbuffer *rb = re->re_writers;
- while (rb)
- {
- if (rb->rb_name == name)
- return (rb);
- rb = rb->rb_next;
- }
- return (0);
-}
-
-t_rdbuffer *riddle_getbuffer(t_symbol *name)
-{
- t_rdenvironment *re = rdenvironment_provide();
- return (rdenvironment_getbuffer(re, name));
-}
-
-t_rdbuffer *rdbuffer_getwriter(t_rdbuffer *rb)
-{
- t_rdenvironment *re = rdenvironment_provide();
- return (rdenvironment_getbuffer(re, rb->rb_name));
-}
-
-static void rdbuffer_updatereaders(t_rdbuffer *rb)
-{
- t_rdbuffer *reader;
- for (reader = rb->rb_readers; reader; reader = reader->rb_next)
- {
- reader->rb_nframes = rb->rb_nframes;
- reader->rb_framesize = rb->rb_framesize;
- reader->rb_npoints = rb->rb_npoints;
- reader->rb_maxphase = rb->rb_maxphase;
- reader->rb_buf = rb->rb_buf;
- reader->rb_phase = 0; /* LATER adjust */
- if (reader->rb_owner)
- /* FIXME -1 - reader->rb_slotno */
- riddle_setsourceblock(reader->rb_owner, -1, rb->rb_framesize);
- }
-}
-
-/* FIXME return the actually allocated size */
-/* LATER optionally use old contents by zero-padding, interpolating, etc. */
-void rdbuffer_validate(t_rdbuffer *rb, int nblock)
-{
- if (rb->rb_bufini == 0)
- {
- loudbug_bug("rdbuffer_validate 1");
- return;
- }
- rb->rb_npoints = nblock * rb->rb_nframes;
- if (rb->rb_npoints > rb->rb_bufsize)
- {
- int reqsize = rb->rb_npoints;
- /* LATER use grow_withdata() */
- rb->rb_buf = grow_nodata(&rb->rb_npoints, &rb->rb_bufsize, rb->rb_buf,
- RDBUFFER_INISIZE, rb->rb_bufini,
- sizeof(*rb->rb_buf));
- if (rb->rb_npoints != reqsize)
- {
- rb->rb_nframes = rb->rb_npoints / nblock;
- if (rb->rb_nframes < 1)
- {
- loudbug_bug("rdbuffer_validate 2");
- rb->rb_nframes = 1;
- nblock = rb->rb_npoints;
- }
- }
- }
- /* LATER convert old buffer's contents of rb->rb_framesize * rb->rb_nframes
- points into the new buffer of nblock * rb->rb_nframes points */
- memset(rb->rb_buf, 0, rb->rb_npoints * sizeof(*rb->rb_buf));
- rb->rb_phase = 0; /* LATER adjust */
- rb->rb_maxphase = rb->rb_npoints - nblock;
- rb->rb_framesize = nblock;
- rdbuffer_updatereaders(rb);
-}
-
-void rdbuffer_reset(t_rdbuffer *rb)
-{
- if (rb->rb_bufini)
- memset(rb->rb_buf, 0, rb->rb_npoints * sizeof(*rb->rb_buf));
- rb->rb_phase = 0;
-}
-
-int rdbuffer_getframesize(t_rdbuffer *rb)
-{
- return (rb->rb_framesize);
-}
-
-t_float *rdbuffer_gethead(t_rdbuffer *rb)
-{
- return (rb->rb_buf + rb->rb_phase);
-}
-
-void rdbuffer_stephead(t_rdbuffer *rb)
-{
- rb->rb_phase += rb->rb_framesize;
- if (rb->rb_phase > rb->rb_maxphase)
- rb->rb_phase = 0;
-}
-
-void rdbuffer_movehead(t_rdbuffer *rb, int nframes)
-{
- if (rb->rb_nframes <= 0)
- {
- loudbug_bug("rdbuffer_movehead");
- }
- else if (nframes > 0)
- {
- if (nframes >= rb->rb_nframes)
- nframes = rb->rb_nframes - 1;
- rb->rb_phase += nframes * rb->rb_framesize;
- while (rb->rb_phase > rb->rb_maxphase)
- rb->rb_phase -= rb->rb_npoints;
- }
- else if (nframes < 0)
- {
- nframes = -nframes;
- if (nframes >= rb->rb_nframes)
- nframes = rb->rb_nframes - 1;
- rb->rb_phase -= nframes * rb->rb_framesize;
- while (rb->rb_phase < 0)
- rb->rb_phase += rb->rb_npoints;
- }
-}
-
-void rdbuffer_delayhead(t_rdbuffer *rb, int nframes)
-{
- if (rb->rb_bufini)
- loudbug_bug("rdbuffer_delayhead 1");
- else
- {
- t_rdbuffer *writer = riddle_getbuffer(rb->rb_name);
- if (writer)
- {
- rb->rb_phase = writer->rb_phase;
- rdbuffer_movehead(rb, -nframes);
- }
- else loudbug_bug("rdbuffer_delayhead 2");
- }
-}
-
-void rdbuffer_free(t_rdbuffer *rb)
-{
- if (rb->rb_bufini)
- {
- if (rb->rb_buf != rb->rb_bufini)
- freebytes(rb->rb_buf, rb->rb_bufsize * sizeof(*rb->rb_buf));
- if (rb->rb_name)
- {
- t_rdbuffer *reader;
- t_rdenvironment *re = rdenvironment_provide();
- /* remove from the environment */
- if (rb->rb_next)
- rb->rb_next->rb_prev = rb->rb_prev;
- if (rb->rb_prev)
- rb->rb_prev->rb_next = rb->rb_next;
- else
- re->re_writers = rb->rb_next;
- /* move all readers to the orphanage */
- if (reader = rb->rb_readers)
- {
- while (reader->rb_next)
- reader = reader->rb_next;
- if (re->re_readers)
- re->re_readers->rb_prev = reader;
- reader->rb_next = re->re_readers;
- re->re_readers = rb->rb_readers;
- }
- }
- }
- else
- {
- if (rb->rb_name)
- {
- /* remove from writer's list or orphanage */
- if (rb->rb_next)
- rb->rb_next->rb_prev = rb->rb_prev;
- if (rb->rb_prev)
- rb->rb_prev->rb_next = rb->rb_next;
- else
- {
- t_rdenvironment *re = rdenvironment_provide();
- t_rdbuffer *writer = rdenvironment_getbuffer(re, rb->rb_name);
- if (writer)
- writer->rb_readers = rb->rb_next;
- else
- re->re_readers = rb->rb_next;
- }
- }
- }
- freebytes(rb, sizeof(*rb));
-}
-
-t_rdbuffer *rdbuffer_new(t_riddle *owner, t_symbol *name, int nframes)
-{
- t_rdbuffer *rb = (t_rdbuffer *)getbytes(sizeof(*rb));
- rb->rb_name = (name && *name->s_name ? name : 0);
- rb->rb_owner = owner;
- rb->rb_phase = 0;
- rb->rb_nframes = (nframes > 1 ? nframes : 1);
- rb->rb_framesize = 0;
- rb->rb_npoints = 0;
- rb->rb_maxphase = 0;
- rb->rb_bufsize = RDBUFFER_INISIZE;
- rb->rb_bufini = getbytes(rb->rb_bufsize * sizeof(*rb->rb_bufini));
- rb->rb_buf = rb->rb_bufini;
- rb->rb_readers = 0;
- rb->rb_prev = 0;
- rb->rb_next = 0;
- if (rb->rb_name)
- {
- t_rdenvironment *re = rdenvironment_provide();
- if (rdenvironment_getbuffer(re, rb->rb_name))
- {
- loud_error((t_pd *)owner, "duplicate buffer name \"%s\"",
- rb->rb_name->s_name);
- }
- else
- {
- t_rdbuffer *reader;
- /* store in the environment */
- if (re->re_writers)
- re->re_writers->rb_prev = rb;
- rb->rb_next = re->re_writers;
- re->re_writers = rb;
- /* recover readers from the orphanage */
- for (reader = re->re_readers; reader; reader = reader->rb_next)
- {
- if (reader->rb_name == rb->rb_name)
- {
- if (reader->rb_next)
- reader->rb_next->rb_prev = reader->rb_prev;
- if (reader->rb_prev)
- reader->rb_prev->rb_next = reader->rb_next;
- else
- re->re_readers = reader->rb_next;
- if (rb->rb_readers)
- rb->rb_readers->rb_prev = reader;
- reader->rb_next = rb->rb_readers;
- rb->rb_readers = reader;
- }
- }
- }
- }
- return (rb);
-}
-
-t_rdbuffer *rdbuffer_newreader(t_riddle *owner, t_symbol *name)
-{
- t_rdbuffer *rb = (t_rdbuffer *)getbytes(sizeof(*rb));
- /* FIXME do not rely on pd_new() callocing owner->rd_nremoteslots to zero */
- owner->rd_nremoteslots++;
- rb->rb_name = (name && *name->s_name ? name : 0);
- rb->rb_owner = owner;
- rb->rb_phase = 0;
- rb->rb_nframes = 0;
- rb->rb_framesize = 0;
- rb->rb_npoints = 0;
- rb->rb_maxphase = 0;
- rb->rb_buf = 0;
- rb->rb_bufini = 0;
- rb->rb_prev = 0;
- rb->rb_next = 0;
- if (rb->rb_name)
- {
- t_rdenvironment *re = rdenvironment_provide();
- t_rdbuffer *writer = rdenvironment_getbuffer(re, rb->rb_name);
- if (writer)
- {
- /* register to the writer */
- if (writer->rb_readers)
- writer->rb_readers->rb_prev = rb;
- rb->rb_next = writer->rb_readers;
- writer->rb_readers = rb;
- }
- else
- {
- /* store in the orphanage */
- if (re->re_readers)
- re->re_readers->rb_prev = rb;
- rb->rb_next = re->re_readers;
- re->re_readers = rb;
- }
- }
- return (rb);
-}
-
-int riddle_erbfill(int nbands, int *buf, int nblock, int sr)
+/* Fills an array of band sizes, in bins, which partition an nbins-point power
+ spectrum into nbands or less ERB bands (nbands is a requested number of
+ bands, the actual number is returned). The buffer is then zero-terminated
+ (and zero-padded if necessary), so its size has to be at least nbands+1. */
+int riddle_erbfill(int nbands, int *buf, int nbins, int sr)
{
static double coef = 9.293902; /* 21.4 / log(10) */
- double df = (double)sr / (double)nblock;
- double fmax = .5 * (nblock + 1) * df;
+ double df = (double)sr / (double)nbins;
+ double fmax = .5 * (nbins + 1) * df;
double fc = df;
int i, erbcount = 0, bincount = 0, lastbin = 0;
int bufsize = nbands + 1;
diff --git a/riddle/riddle.h b/riddle/riddle.h
index 12d5907..0795f5f 100644
--- a/riddle/riddle.h
+++ b/riddle/riddle.h
@@ -2,103 +2,132 @@
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+/* these are the riddle external API declarations */
+
#ifndef __RIDDLE_H__
#define __RIDDLE_H__
EXTERN_STRUCT _riddle;
#define t_riddle struct _riddle
+EXTERN_STRUCT _rdprivate;
+#define t_rdprivate struct _rdprivate
+
EXTERN_STRUCT _rdsource;
#define t_rdsource struct _rdsource
EXTERN_STRUCT _rdsink;
#define t_rdsink struct _rdsink
-EXTERN_STRUCT _rdpool;
-#define t_rdpool struct _rdpool
+EXTERN_STRUCT _rdpicker;
+#define t_rdpicker struct _rdpicker
+
+EXTERN_STRUCT _rdfeedchain;
+#define t_rdfeedchain struct _rdfeedchain
-EXTERN_STRUCT _rdbuffer;
-#define t_rdbuffer struct _rdbuffer
+EXTERN_STRUCT _rdremote;
+#define t_rdremote struct _rdremote
typedef void (*t_rdblockfn)(t_riddle *);
typedef void (*t_rddspfn)(t_riddle *, t_signal **);
struct _riddle
{
- t_sic rd_sic;
+ t_sic rd_sic;
+
+ /* LATER rethink: indirection cost vs. abi stability */
+ t_rdprivate *rd_private;
/* designed for system-level control: block mismatches, etc.
- (user-level control via '_idle' slot in graphpool) */
- int rd_disabled;
- int rd_wasdisabled;
+ (user-level control possible via the '_idle' slot in graphpool) */
+ int rd_disabled;
+ int rd_wasdisabled;
t_rdblockfn rd_blockfn;
t_rddspfn rd_dspfn;
- t_rdpool *rd_graphpool;
-
- int rd_graphsr;
- int rd_graphblock;
+ int rd_graphsr;
+ int rd_graphblock;
int rd_nsiginlets;
int rd_nremoteslots;
- t_rdsource *rd_inslots; /* rd_nsiginlets + rd_nremoteslots elements */
- t_rdsource *rd_remoteslots; /* == rd_inslots + rd_nsiginlets */
+ t_rdsource *rd_inslots; /* nsiginlets + nremoteslots elements */
+ t_rdsource *rd_remoteslots; /* == inslots + nsiginlets (readers only) */
+ t_rdremote *rd_remoteports; /* the list of all remotes */
- int rd_nsigoutlets;
- t_rdsink *rd_outslots; /* rd_nsigoutlets elements */
+ int rd_nsigoutlets;
+ t_rdsink *rd_outslots; /* nsigoutlets elements */
- int rd_remotesource; /* LATER consider storing remote sources here */
+ t_rdpicker *rd_idlepicker;
};
-void riddlebug_post(t_riddle *rd, char *pfx, char *fmt, ...);
+#define RIDDLE_STRICTNESSMASK 1 /* if set: non-riddle sinks are rejected */
-int riddle_getsr(t_riddle *rd);
-int riddle_getgraphblock(t_riddle *rd);
+/* the main part of the API */
int riddle_getsourceblock(t_riddle *rd, int siginno);
-t_symbol *riddle_getsourcepattern(t_riddle *rd, int siginno, int *maxblockp);
-int riddle_getoutblock(t_riddle *rd, int sigoutno);
-t_symbol *riddle_getoutpattern(t_riddle *rd, int sigoutno, int *maxblockp);
+t_symbol *riddle_getsourcelayout(t_riddle *rd, int siginno, int *maxblockp);
+int riddle_getsourceflags(t_riddle *rd, int siginno);
+/* or perhaps, IFBUILTIN, int inlet_getblock(t_inlet *)... */
void riddle_setoutblock(t_riddle *rd, int sigoutno, int newblock);
-void riddle_setoutpattern(t_riddle *rd, int sigoutno,
- t_symbol *pattern, int maxblock);
+void riddle_setoutlayout(t_riddle *rd, int sigoutno,
+ t_symbol *pattern, int maxblock);
+void riddle_setoutflags(t_riddle *rd, int sigoutno, int flags);
+/* or perhaps, IFBUILTIN, void outlet_setblock(t_outlet *, int)... */
int riddle_checksourceblock(t_riddle *rd, int siginno, int reqblock);
-int riddle_checksourcepattern(t_riddle *rd, int siginno,
- t_symbol *reqpattern, int *maxblockp);
-int riddle_checkanysource(t_riddle *rd, int siginno);
+int riddle_checksourcelayout(t_riddle *rd, int siginno,
+ t_symbol *reqpattern, int *maxblockp);
int riddle_isdisabled(t_riddle *rd);
void riddle_disable(t_riddle *rd);
-void riddle_mute(t_riddle *rd, t_signal **sp);
+
+/* this part is specific to the library implementation */
t_class *riddle_setup(t_symbol *name, t_newmethod newfn, t_method freefn,
size_t sz, t_method floatfn,
t_rdblockfn blockfn, t_rddspfn dspfn);
-void riddle_updatedsp(void);
-
-void rdpool_set(t_rdpool *rp, t_symbol *key, int size, t_float *data);
-void rdpool_setbygraph(t_canvas *graph, t_symbol *key, int size, t_float *data);
-t_float *rdpool_get(t_rdpool *rp, t_symbol *key, int *sizep);
-t_float *riddle_getlink(t_riddle *rd, t_symbol *key, int *sizep);
-t_canvas *riddle_getgraph(t_riddle *rd, int sigoutno);
-
-t_rdbuffer *riddle_getbuffer(t_symbol *name);
-t_rdbuffer *rdbuffer_getwriter(t_rdbuffer *rb);
-void rdbuffer_validate(t_rdbuffer *rb, int nblock);
-void rdbuffer_reset(t_rdbuffer *rb);
-int rdbuffer_getframesize(t_rdbuffer *rb);
-t_float *rdbuffer_gethead(t_rdbuffer *rb);
-void rdbuffer_stephead(t_rdbuffer *rb);
-void rdbuffer_movehead(t_rdbuffer *rb, int nframes);
-void rdbuffer_delayhead(t_rdbuffer *rb, int nframes);
-void rdbuffer_free(t_rdbuffer *rb);
-t_rdbuffer *rdbuffer_new(t_riddle *owner, t_symbol *name, int nframes);
-t_rdbuffer *rdbuffer_newreader(t_riddle *owner, t_symbol *name);
-
-int riddle_erbfill(int nbands, int *buf, int nblock, int sr);
+/* this part is very experimental: remote connections */
+
+t_rdremote *rdremote_newwriter(t_riddle *owner, t_symbol *name, int nframes);
+t_rdremote *rdremote_newreader(t_riddle *owner, t_symbol *name);
+t_rdremote *rdremote_newbuffer(t_riddle *owner, int nframes);
+
+int rdremote_getsourceblock(t_rdremote *re);
+t_symbol *rdremote_getsourcelayout(t_rdremote *re, int *maxblockp);
+int rdremote_getsourceflags(t_rdremote *re);
+
+void rdremote_setoutblock(t_rdremote *re, int nblock);
+void rdremote_setoutlayout(t_rdremote *re, t_symbol *pattern, int maxblock);
+void rdremote_setoutflags(t_rdremote *re, int flags);
+
+void rdremote_reset(t_rdremote *re);
+t_float *rdremote_gethead(t_rdremote *re);
+void rdremote_stephead(t_rdremote *re);
+void rdremote_movehead(t_rdremote *re, int nframes);
+void rdremote_delayhead(t_rdremote *re, int nframes);
+
+t_rdpicker *rdpicker_attach(t_riddle *rd, t_symbol *key);
+void rdpicker_detach(t_rdpicker *pi, t_riddle *rd);
+t_float *rdpicker_pick(t_rdpicker *pi, int *sizep);
+t_float rdpicker_pick1(t_rdpicker *pi);
+int riddle_isidle(t_riddle *rd);
+
+t_rdfeedchain *riddle_usefeedchain(t_riddle *rd,
+ int sigoutno, t_symbol *key, int size);
+t_rdfeedchain *riddle_useidlechain(t_riddle *rd, int sigoutno);
+void rdfeedchain_feed(t_rdfeedchain *ch, int size, t_float *data);
+void rdfeedchain_feed1(t_rdfeedchain *ch, t_float v);
+
+/* utilities */
+
+void riddlebug_post(t_riddle *rd, char *pfx, char *fmt, ...);
+
+int riddle_getsr(t_riddle *rd);
+int riddle_getgraphblock(t_riddle *rd);
+
+int riddle_erbfill(int nbands, int *buf, int nbins, int sr);
#endif
diff --git a/riddle/riddleguts.h b/riddle/riddleguts.h
new file mode 100644
index 0000000..b6354e2
--- /dev/null
+++ b/riddle/riddleguts.h
@@ -0,0 +1,35 @@
+/* Copyright (c) 2007 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* these declarations do not belong to the riddle API
+ and should not be used by riddle externals */
+
+#ifndef __RIDDLEGUTS_H__
+#define __RIDDLEGUTS_H__
+
+/* from riddle.c */
+
+void riddle_setsourceblock(t_riddle *rd, int siginno, int newblock);
+void riddle_setsourcelayout(t_riddle *rd, int siginno,
+ t_symbol *newpattern, int maxblock);
+void riddle_setsourceflags(t_riddle *rd, int siginno, int flags);
+
+t_canvas *riddle_nextgraph(t_riddle *rd);
+t_canvas *riddle_firstgraph(t_riddle *rd, int outno);
+
+t_rdfeedchain *riddle_getfeedchain(t_riddle *rd, int sigoutno);
+
+/* from rdremote.c */
+
+t_pd *riddle_getenvironment(void);
+void riddle_updatedsp(void);
+
+void rdfeedchain_free(t_rdfeedchain *ch);
+t_rdfeedchain *rdfeedchain_new(int outno);
+
+t_rdremote *rdremote_getwriter(t_rdremote *re);
+t_rdremote *rdremote_nextreader(t_rdremote *re);
+void rdremote_freeports(t_rdremote *re);
+
+#endif