aboutsummaryrefslogtreecommitdiff
path: root/riddle/riddle.c
diff options
context:
space:
mode:
Diffstat (limited to 'riddle/riddle.c')
-rw-r--r--riddle/riddle.c1317
1 files changed, 520 insertions, 797 deletions
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;