aboutsummaryrefslogtreecommitdiff
path: root/cyclone/hammer
diff options
context:
space:
mode:
authorN.N. <krzyszcz@users.sourceforge.net>2004-12-08 15:40:14 +0000
committerN.N. <krzyszcz@users.sourceforge.net>2004-12-08 15:40:14 +0000
commitd5a39ff6469f8762218c00a34f4b0a120a56332b (patch)
tree8b5d6f1008f1ce09daf3e2a63b71f9c142911e80 /cyclone/hammer
parentb88a64023a08ed9a0e520058ef8be200515d9639 (diff)
various bug-fixes, maxmode, toxy .#args
svn path=/trunk/externals/miXed/; revision=2360
Diffstat (limited to 'cyclone/hammer')
-rw-r--r--cyclone/hammer/Append.c121
-rw-r--r--cyclone/hammer/Decode.c1
-rw-r--r--cyclone/hammer/Makefile.objects3
-rw-r--r--cyclone/hammer/Table.c1
-rw-r--r--cyclone/hammer/bangbang.c3
-rw-r--r--cyclone/hammer/coll.c1
-rw-r--r--cyclone/hammer/comment.c23
-rw-r--r--cyclone/hammer/counter.c17
-rw-r--r--cyclone/hammer/cycle.c1
-rw-r--r--cyclone/hammer/funbuff.c83
-rw-r--r--cyclone/hammer/gate.c3
-rw-r--r--cyclone/hammer/hammer.c7
-rw-r--r--cyclone/hammer/maximum.c1
-rw-r--r--cyclone/hammer/minimum.c1
-rw-r--r--cyclone/hammer/mtr.c13
-rw-r--r--cyclone/hammer/offer.c17
-rw-r--r--cyclone/hammer/past.c1
-rw-r--r--cyclone/hammer/prepend.c255
-rw-r--r--cyclone/hammer/prob.c1
-rw-r--r--cyclone/hammer/seq.c574
-rw-r--r--cyclone/hammer/switch.c3
-rw-r--r--cyclone/hammer/urn.c1
22 files changed, 717 insertions, 414 deletions
diff --git a/cyclone/hammer/Append.c b/cyclone/hammer/Append.c
index 0cdea60..ad615d5 100644
--- a/cyclone/hammer/Append.c
+++ b/cyclone/hammer/Append.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
@@ -21,9 +21,17 @@ typedef struct _append
int x_entered;
int x_auxsize;
t_atom *x_auxbuf;
+ t_pd *x_proxy;
} t_append;
+typedef struct _appendxy
+{
+ t_pd xy_pd;
+ t_append *xy_owner;
+} t_appendxy;
+
static t_class *append_class;
+static t_class *appendxy_class;
/* Usually a preallocation method is used, except in special cases of:
1) reentrant output request, or 2) an output request which would cause
@@ -32,8 +40,7 @@ static t_class *append_class;
A separately preallocated output buffer is not used, thus avoiding
memcpying of the stored message (a small performance gain when the
preallocation method is chosen). Instead, self-invoked 'set'
- messages are postponed, using an auxiliary buffer.
-*/
+ messages are postponed, using an auxiliary buffer. */
/* Any Append's output goes through outlet_anything() -> typedmess() */
@@ -132,9 +139,11 @@ static void append_symbol(t_append *x, t_symbol *s)
/* LATER gpointer */
-static void append_set(t_append *x, t_symbol *s, int ac, t_atom *av)
+static void append_doset(t_append *x, t_symbol *s, int ac, t_atom *av)
{
int newsize = ac * 2;
+ if (s)
+ newsize += 2;
if (newsize > 0)
{
if (x->x_entered)
@@ -147,7 +156,15 @@ static void append_set(t_append *x, t_symbol *s, int ac, t_atom *av)
}
if (x->x_auxbuf = getbytes(newsize * sizeof(*x->x_auxbuf)))
{
- memcpy(x->x_auxbuf + ac, av, ac * sizeof(*x->x_auxbuf));
+ t_atom *ap = x->x_auxbuf + ac;
+ if (s)
+ {
+ ap++;
+ SETSYMBOL(ap, s);
+ ap++;
+ }
+ if (ac)
+ memcpy(ap, av, ac * sizeof(*x->x_auxbuf));
x->x_auxsize = newsize;
}
}
@@ -161,19 +178,86 @@ static void append_set(t_append *x, t_symbol *s, int ac, t_atom *av)
APPEND_INISIZE, x->x_messini,
sizeof(*x->x_messbuf));
if (sz != newsize)
+ {
ac = sz / 2; /* LATER rethink */
+ if (s)
+ ac--;
+ }
+ }
+ if (s)
+ {
+ append_setnatoms(x, ac + 1);
+ ap = x->x_message;
+ SETSYMBOL(ap, s);
+ ap++;
+ }
+ else
+ {
+ append_setnatoms(x, ac);
+ ap = x->x_message;
}
- append_setnatoms(x, ac);
- ap = x->x_message;
while (ac--) *ap++ = *av++;
}
}
}
+static void append_set(t_append *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (shared_getmaxcompatibility())
+ append_doset(x, 0, ac, av);
+ else
+ append_anything(x, s, ac, av);
+}
+
+static void appendxy_bang(t_appendxy *xy)
+{
+ append_doset(xy->xy_owner, 0, 0, 0); /* LATER rethink */
+}
+
+static void appendxy_float(t_appendxy *xy, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ append_doset(xy->xy_owner, 0, 1, &at);
+}
+
+static void appendxy_symbol(t_appendxy *xy, t_symbol *s)
+{
+ t_atom at;
+ if (!s || s == &s_)
+ s = &s_symbol; /* LATER rethink */
+ SETSYMBOL(&at, s);
+ append_doset(xy->xy_owner, 0, 1, &at);
+}
+
+static void appendxy_list(t_appendxy *xy, t_symbol *s, int ac, t_atom *av)
+{
+ if (ac)
+ append_doset(xy->xy_owner, 0, ac, av);
+ else
+ { /* LATER rethink */
+ t_atom at;
+ SETSYMBOL(&at, &s_list);
+ append_doset(xy->xy_owner, 0, 1, &at);
+ }
+}
+
+static void appendxy_anything(t_appendxy *xy, t_symbol *s, int ac, t_atom *av)
+{
+ append_doset(xy->xy_owner, s, ac, av);
+}
+
static void append_free(t_append *x)
{
if (x->x_messbuf != x->x_messini)
freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf));
+ if (x->x_auxbuf)
+ {
+ bug("append_free"); /* LATER rethink */
+ freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf));
+ }
+ if (x->x_proxy)
+ pd_free(x->x_proxy);
}
static void *append_new(t_symbol *s, int ac, t_atom *av)
@@ -184,9 +268,20 @@ static void *append_new(t_symbol *s, int ac, t_atom *av)
x->x_messbuf = x->x_messini;
x->x_auxbuf = 0;
x->x_entered = 0;
- outlet_new((t_object *)x, &s_anything);
append_setnatoms(x, 0);
- append_set(x, 0, ac, av);
+ shared_usecompatibility();
+ if (ac)
+ {
+ x->x_proxy = 0;
+ append_doset(x, 0, ac, av);
+ }
+ else
+ {
+ x->x_proxy = pd_new(appendxy_class);
+ ((t_appendxy *)x->x_proxy)->xy_owner = x;
+ inlet_new((t_object *)x, x->x_proxy, 0, 0);
+ }
+ outlet_new((t_object *)x, &s_anything);
return (x);
}
@@ -204,4 +299,12 @@ void Append_setup(void)
class_addanything(append_class, append_anything);
class_addmethod(append_class, (t_method)append_set,
gensym("set"), A_GIMME, 0);
+
+ appendxy_class = class_new(gensym("append"), 0, 0, sizeof(t_appendxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(appendxy_class, appendxy_bang);
+ class_addfloat(appendxy_class, appendxy_float);
+ class_addsymbol(appendxy_class, appendxy_symbol);
+ class_addlist(appendxy_class, appendxy_list);
+ class_addanything(appendxy_class, appendxy_anything);
}
diff --git a/cyclone/hammer/Decode.c b/cyclone/hammer/Decode.c
index 4dee7e0..77d8f38 100644
--- a/cyclone/hammer/Decode.c
+++ b/cyclone/hammer/Decode.c
@@ -78,6 +78,7 @@ static void *Decode_new(t_floatarg val)
nouts = DECODE_DEFOUTS;
if (nouts > DECODE_C74MAXOUTS)
{
+ shared_usecompatibility();
loud_incompatible_max(Decode_class, DECODE_C74MAXOUTS, "outlets");
if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
return (0);
diff --git a/cyclone/hammer/Makefile.objects b/cyclone/hammer/Makefile.objects
index 76de16f..78bff7e 100644
--- a/cyclone/hammer/Makefile.objects
+++ b/cyclone/hammer/Makefile.objects
@@ -6,9 +6,8 @@ common/loud.o \
common/grow.o \
common/rand.o \
common/vefl.o \
-common/sq.o \
-common/bifi.o \
common/mifi.o \
+common/lex.o \
common/binport.o \
common/port.o \
hammer/file.o \
diff --git a/cyclone/hammer/Table.c b/cyclone/hammer/Table.c
index e366cbb..e613293 100644
--- a/cyclone/hammer/Table.c
+++ b/cyclone/hammer/Table.c
@@ -233,6 +233,7 @@ static void tablecommon_doread(t_tablecommon *cc, t_symbol *fn, t_canvas *cv)
char buf[MAXPDSTRING];
if (!fn)
return; /* CHECKME complaint */
+ /* FIXME use open_via_path() */
if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'read' w/o arg */
canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING);
else
diff --git a/cyclone/hammer/bangbang.c b/cyclone/hammer/bangbang.c
index 695a558..d1eb53a 100644
--- a/cyclone/hammer/bangbang.c
+++ b/cyclone/hammer/bangbang.c
@@ -47,7 +47,10 @@ static void *bangbang_new(t_floatarg val)
if (nouts < BANGBANG_MINOUTS)
nouts = BANGBANG_DEFOUTS;
if (nouts > BANGBANG_C74MAXOUTS)
+ {
+ shared_usecompatibility();
loud_incompatible_max(bangbang_class, BANGBANG_C74MAXOUTS, "outlets");
+ }
if (nouts > BANGBANG_DEFOUTS)
{
if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
diff --git a/cyclone/hammer/coll.c b/cyclone/hammer/coll.c
index 850c2c7..031f6c6 100644
--- a/cyclone/hammer/coll.c
+++ b/cyclone/hammer/coll.c
@@ -591,6 +591,7 @@ static void collcommon_doread(t_collcommon *cc, t_symbol *fn, t_canvas *cv)
char buf[MAXPDSTRING];
if (!fn && !(fn = cc->c_filename)) /* !fn: 'readagain' */
return;
+ /* FIXME use open_via_path() */
if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'read' w/o arg, 'readagain' */
canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING);
else
diff --git a/cyclone/hammer/comment.c b/cyclone/hammer/comment.c
index 72e8a57..03d4d03 100644
--- a/cyclone/hammer/comment.c
+++ b/cyclone/hammer/comment.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
@@ -200,6 +200,9 @@ static void comment_validate(t_comment *x, t_glist *glist)
static void comment_grabbedkey(void *z, t_floatarg f)
{
/* LATER think about replacing #key binding/comment_float() with grabbing */
+#ifdef COMMENT_DEBUG
+ post("comment_grabbedkey %g", f);
+#endif
}
static void comment_dograb(t_comment *x)
@@ -520,7 +523,7 @@ static void comment_float(t_comment *x, t_float f)
/* LATER delete the box... this causes reentrancy
problems now. */
/* glist_delete(x->x_glist, &x->x_text->te_g); */
- return;
+ goto donefloat;
}
else if (x->x_selstart && (x->x_selstart == x->x_selend))
x->x_selstart--;
@@ -556,6 +559,10 @@ static void comment_float(t_comment *x, t_float f)
}
}
else bug("comment_float");
+ donefloat:;
+#ifdef COMMENT_DEBUG
+ post("donefloat");
+#endif
}
static void comment_list(t_comment *x, t_symbol *s, int ac, t_atom *av)
@@ -625,7 +632,7 @@ static void comment_list(t_comment *x, t_symbol *s, int ac, t_atom *av)
canvas_unsetcurrent(x->x_glist);
canvas_dirty(x->x_glist, 1);
clock_delay(x->x_transclock, 0); /* LATER rethink */
- return;
+ goto donelist;
}
else if (!strcmp(keysym->s_name, "F5"))
{
@@ -640,11 +647,15 @@ static void comment_list(t_comment *x, t_symbol *s, int ac, t_atom *av)
canvas_unsetcurrent(x->x_glist);
canvas_dirty(x->x_glist, 1);
binbuf_free(bb);
- return;
+ goto donelist;
}
- else return;
+ else goto donelist;
comment_update(x);
}
+ donelist:;
+#ifdef COMMENT_DEBUG
+ post("donelist");
+#endif
}
static void comment_free(t_comment *x)
@@ -830,6 +841,8 @@ void comment_setup(void)
pd $target _click $target [$cvname canvasx $x] [$cvname canvasy $y]\
[$cvname index $tag @$x,$y] [$cvname bbox $tag]\\;}\n");
+ /* LATER think how to conditionally (FORKY_VERSION >= 38)
+ replace puts with pdtk_post */
sys_gui("proc comment_entext {enc tt} {\n\
set rr [catch {encoding convertfrom $enc $tt} tt1]\n\
if {$rr == 0} {concat $tt1} else {\n\
diff --git a/cyclone/hammer/counter.c b/cyclone/hammer/counter.c
index 3117e6c..73cd841 100644
--- a/cyclone/hammer/counter.c
+++ b/cyclone/hammer/counter.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
@@ -11,6 +11,7 @@
of checking -- I will not bother, until there is some feedback. */
#include "m_pd.h"
+#include "common/loud.h"
#define COUNTER_UP 0
#define COUNTER_DOWN 1
@@ -315,12 +316,16 @@ static void *counter_new(t_floatarg f1, t_floatarg f2, t_floatarg f3)
int i2 = (int)f2;
int i3 = (int)f3;
int i;
- static int warned = 0;
- if (!warned)
+ shared_usecompatibility();
+ if (shared_getmaxcompatibility())
{
- post("warning: counter is not fully compatible, \
-please report differences");
- warned = 1;
+ static int warned = 0;
+ if (!warned)
+ {
+ post("warning: counter is not fully compatible,\
+ please report differences");
+ warned = 1;
+ }
}
x->x_dir = COUNTER_UP;
x->x_inc = 1; /* previous value required by counter_dir() */
diff --git a/cyclone/hammer/cycle.c b/cyclone/hammer/cycle.c
index 2e6dbd0..244a64d 100644
--- a/cyclone/hammer/cycle.c
+++ b/cyclone/hammer/cycle.c
@@ -119,6 +119,7 @@ static void *cycle_new(t_floatarg f1, t_floatarg f2)
nouts = CYCLE_DEFOUTS;
if (nouts > CYCLE_C74MAXOUTS)
{
+ shared_usecompatibility();
loud_incompatible_max(cycle_class, CYCLE_C74MAXOUTS, "outlets");
/* CHECKED: max clips with an error:
``perhaps you were trying to make an oscillator?'' */
diff --git a/cyclone/hammer/funbuff.c b/cyclone/hammer/funbuff.c
index 3ce6080..ff4773b 100644
--- a/cyclone/hammer/funbuff.c
+++ b/cyclone/hammer/funbuff.c
@@ -1,9 +1,8 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 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 "m_pd.h"
-#include "unstable/fragile.h"
#include "common/loud.h"
#include "common/vefl.h"
#include "hammer/tree.h"
@@ -49,13 +48,16 @@ static void funbuff_bang(t_funbuff *x)
{
/* LATER consider using extra fields, updated on the fly */
count = 1;
- xmin = np->n_index;
- xmax = x->x_tree.t_last->n_index;
- ymin = ymax = np->n_value;
+ xmin = np->n_key;
+ xmax = x->x_tree.t_last->n_key;
+ ymin = ymax = HAMMERNODE_GETFLOAT(np);
while (np = np->n_next)
{
- if (np->n_value < ymin) ymin = np->n_value;
- else if (np->n_value > ymax) ymax = np->n_value;
+ t_float f = HAMMERNODE_GETFLOAT(np);
+ if (f < ymin)
+ ymin = f;
+ else if (f > ymax)
+ ymax = f;
count++;
}
}
@@ -75,15 +77,14 @@ static void funbuff_float(t_funbuff *x, t_float f)
t_hammernode *np;
if (x->x_valueset)
{
- if (np = hammertree_insert(&x->x_tree, ndx))
- np->n_value = x->x_value;
+ np = hammertree_insertfloat(&x->x_tree, ndx, x->x_value, 1);
x->x_valueset = 0;
}
else if (np = hammertree_closest(&x->x_tree, ndx, 0))
- funbuff_dooutput(x, np->n_value, x->x_lastdelta);
+ funbuff_dooutput(x, HAMMERNODE_GETFLOAT(np), x->x_lastdelta);
/* CHECKED pointer is updated --
'next' outputs np also in a !valueset case (it is sent twice) */
- x->x_pointer = np;
+ x->x_pointer = np; /* FIXME */
x->x_pointerset = 0;
}
@@ -120,9 +121,10 @@ static void funbuff_min(t_funbuff *x)
t_hammernode *np;
if (np = x->x_tree.t_first) /* CHECKED nop if empty */
{
- t_float result = np->n_value;
+ t_float result = HAMMERNODE_GETFLOAT(np);
while (np = np->n_next)
- if (np->n_value < result) result = np->n_value;
+ if (HAMMERNODE_GETFLOAT(np) < result)
+ result = HAMMERNODE_GETFLOAT(np);
funbuff_dooutput(x, result, x->x_lastdelta);
/* CHECKED pointer not updated */
}
@@ -134,9 +136,10 @@ static void funbuff_max(t_funbuff *x)
t_hammernode *np;
if (np = x->x_tree.t_first) /* CHECKED nop if empty */
{
- t_float result = np->n_value;
+ t_float result = HAMMERNODE_GETFLOAT(np);
while (np = np->n_next)
- if (np->n_value > result) result = np->n_value;
+ if (HAMMERNODE_GETFLOAT(np) > result)
+ result = HAMMERNODE_GETFLOAT(np);
funbuff_dooutput(x, result, x->x_lastdelta);
/* CHECKED pointer not updated */
}
@@ -156,10 +159,10 @@ static void funbuff_next(t_funbuff *x)
if (x->x_pointerset)
x->x_lastdelta = 0;
else if (np->n_prev)
- x->x_lastdelta = np->n_index - np->n_prev->n_index;
+ x->x_lastdelta = np->n_key - np->n_prev->n_key;
else
x->x_lastdelta = 0; /* CHECKED corrupt delta sent here... */
- funbuff_dooutput(x, np->n_value, x->x_lastdelta);
+ funbuff_dooutput(x, HAMMERNODE_GETFLOAT(np), x->x_lastdelta);
x->x_pointer = np->n_next;
x->x_pointerset = 0;
}
@@ -185,10 +188,9 @@ static void funbuff_set(t_funbuff *x, t_symbol *s, int ac, t_atom *av)
funbuff_clear(x); /* CHECKED the contents is replaced */
while (ac--)
{
- t_hammernode *np;
- if (np = hammertree_insert(&x->x_tree, (int)av++->a_w.w_float))
- np->n_value = av++->a_w.w_float;
- else return;
+ int ndx = (int)av++->a_w.w_float;
+ if (!hammertree_insertfloat(&x->x_tree, ndx, av++->a_w.w_float, 1))
+ return;
ac--;
}
}
@@ -199,6 +201,7 @@ static void funbuff_doread(t_funbuff *x, t_symbol *fn)
int ac;
t_atom *av;
char buf[MAXPDSTRING];
+ /* FIXME use open_via_path() */
canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
binbuf_read(bb, buf, "", 0);
if ((ac = binbuf_getnatom(bb)) &&
@@ -226,7 +229,7 @@ static void funbuff_dowrite(t_funbuff *x, t_symbol *fn)
t_hammernode *np;
binbuf_addv(bb, "s", gensym("funbuff"));
for (np = x->x_tree.t_first; np; np = np->n_next)
- binbuf_addv(bb, "if", np->n_index, np->n_value);
+ binbuf_addv(bb, "if", np->n_key, HAMMERNODE_GETFLOAT(np));
canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
binbuf_write(bb, buf, "", 0);
binbuf_free(bb);
@@ -248,7 +251,7 @@ static void funbuff_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym)
{
binbuf_addv(bb, "ss", bindsym, gensym("set"));
for (; np; np = np->n_next)
- binbuf_addv(bb, "if", np->n_index, np->n_value);
+ binbuf_addv(bb, "if", np->n_key, HAMMERNODE_GETFLOAT(np));
binbuf_addsemi(bb);
}
}
@@ -283,11 +286,11 @@ static void funbuff_delete(t_funbuff *x, t_symbol *s, int ac, t_atom *av)
int ndx = (int)av->a_w.w_float;
t_hammernode *np;
if ((np = hammertree_search(&x->x_tree, ndx)) &&
- (ac == 1 || np->n_value == av[1].a_w.w_float))
+ (ac == 1 || HAMMERNODE_GETFLOAT(np) == av[1].a_w.w_float))
{
if (np == x->x_pointer)
x->x_pointer = 0; /* CHECKED corrupt pointer left here... */
- hammertree_delete(&x->x_tree, np);
+ hammertree_delete(&x->x_tree, np); /* FIXME */
}
/* CHECKED mismatch silently ignored */
}
@@ -302,8 +305,8 @@ static void funbuff_find(t_funbuff *x, t_floatarg f)
do
{
/* CHECKED lastdelta preserved */
- if (np->n_value == f)
- funbuff_dooutput(x, np->n_index, x->x_lastdelta);
+ if (HAMMERNODE_GETFLOAT(np) == f)
+ funbuff_dooutput(x, np->n_key, x->x_lastdelta);
}
while (np = np->n_next);
/* CHECKED no bangout, no complaint if nothing found */
@@ -318,9 +321,9 @@ static void funbuff_dump(t_funbuff *x)
{
do
{
- x->x_lastdelta = np->n_value; /* CHECKED */
+ x->x_lastdelta = HAMMERNODE_GETFLOAT(np); /* CHECKED */
/* float value preserved (this is incompatible) */
- funbuff_dooutput(x, np->n_index, np->n_value);
+ funbuff_dooutput(x, np->n_key, x->x_lastdelta);
}
while (np = np->n_next);
/* CHECKED no bangout */
@@ -336,14 +339,14 @@ static void funbuff_dointerp(t_funbuff *x, t_floatarg f, int vsz, t_float *vec)
if (trunc > f) trunc--; /* CHECKME negative floats */
if (np1 = hammertree_closest(&x->x_tree, trunc, 0))
{
- float value = np1->n_value;
+ float value = HAMMERNODE_GETFLOAT(np1);
t_hammernode *np2 = np1->n_next;
if (np2)
{
- float delta = (float)(np2->n_index - np1->n_index);
+ float delta = (float)(np2->n_key - np1->n_key);
/* this is incompatible -- CHECKED float argument is silently
truncated (which does not make much sense here), CHECKME again */
- float frac = f - np1->n_index;
+ float frac = f - np1->n_key;
if (frac < 0 || frac >= delta)
{
bug("funbuff_dointerp");
@@ -364,12 +367,14 @@ static void funbuff_dointerp(t_funbuff *x, t_floatarg f, int vsz, t_float *vec)
vec += vndx;
frac = *vec + (vec[1] - *vec) * vfrac;
}
- value += (np2->n_value - np1->n_value) * frac;
+ value +=
+ (HAMMERNODE_GETFLOAT(np2) - HAMMERNODE_GETFLOAT(np1)) * frac;
}
funbuff_dooutput(x, value, x->x_lastdelta); /* CHECKME !np2 */
}
else if (np1 = hammertree_closest(&x->x_tree, trunc, 1))
- funbuff_dooutput(x, np1->n_value, x->x_lastdelta); /* CHECKME */
+ /* CHECKME */
+ funbuff_dooutput(x, HAMMERNODE_GETFLOAT(np1), x->x_lastdelta);
}
static void funbuff_interp(t_funbuff *x, t_floatarg f)
@@ -428,7 +433,7 @@ static void funbuff_undo(t_funbuff *x)
#ifdef HAMMERTREE_DEBUG
static void funbuff_debug(t_funbuff *x, t_floatarg f)
{
- hammertree_debug(&x->x_tree, (int)f);
+ hammertree_debug(&x->x_tree, (int)f, 0);
}
#endif
@@ -447,7 +452,7 @@ static void *funbuff_new(t_symbol *s)
x->x_pointerset = 0; /* CHECKME, rename to intraversal? */
x->x_lastdelta = 0;
x->x_embedflag = 0;
- hammertree_init(&x->x_tree, 0);
+ hammertree_inittyped(&x->x_tree, HAMMERTYPE_FLOAT, 0);
inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
outlet_new((t_object *)x, &s_float);
x->x_deltaout = outlet_new((t_object *)x, &s_float);
@@ -466,9 +471,9 @@ static void *funbuff_new(t_symbol *s)
void funbuff_setup(void)
{
funbuff_class = class_new(gensym("funbuff"),
- (t_newmethod)funbuff_new,
- (t_method)funbuff_free,
- sizeof(t_funbuff), 0, A_DEFSYM, 0);
+ (t_newmethod)funbuff_new,
+ (t_method)funbuff_free,
+ sizeof(t_funbuff), 0, A_DEFSYM, 0);
class_addbang(funbuff_class, funbuff_bang);
class_addfloat(funbuff_class, funbuff_float);
class_addmethod(funbuff_class, (t_method)funbuff_ft1,
diff --git a/cyclone/hammer/gate.c b/cyclone/hammer/gate.c
index 19035a5..80210cb 100644
--- a/cyclone/hammer/gate.c
+++ b/cyclone/hammer/gate.c
@@ -100,7 +100,10 @@ static void *gate_new(t_floatarg f1, t_floatarg f2)
if (nouts < GATE_MINOUTS)
nouts = GATE_DEFOUTS;
if (nouts > GATE_C74MAXOUTS)
+ {
+ shared_usecompatibility();
loud_incompatible_max(gate_class, GATE_C74MAXOUTS, "outlets");
+ }
nouts++; /* for convenience (the cost is one pointer) */
if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs))))
return (0);
diff --git a/cyclone/hammer/hammer.c b/cyclone/hammer/hammer.c
index 3c4f3c2..ea4642c 100644
--- a/cyclone/hammer/hammer.c
+++ b/cyclone/hammer/hammer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
@@ -76,6 +76,11 @@ void hammer_setup(void)
loud_errand(0, "without having hammer library preloaded");
return;
}
+ if (zgetfn(&pd_objectmaker, gensym("hammer")))
+ {
+ loud_error(0, "hammer is already loaded");
+ return;
+ }
if (!zgetfn(&pd_objectmaker, gensym("cyclone")))
post("this is hammer %s, %s %s build",
CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE);
diff --git a/cyclone/hammer/maximum.c b/cyclone/hammer/maximum.c
index f7f01f1..b5f6069 100644
--- a/cyclone/hammer/maximum.c
+++ b/cyclone/hammer/maximum.c
@@ -75,6 +75,7 @@ static void *maximum_new(t_floatarg f)
t_maximum *x = (t_maximum *)pd_new(maximum_class);
x->x_last = 0; /* CHECKME */
x->x_test = f;
+ shared_usecompatibility();
floatinlet_new((t_object *)x, &x->x_test);
outlet_new((t_object *)x, &s_float);
return (x);
diff --git a/cyclone/hammer/minimum.c b/cyclone/hammer/minimum.c
index 415235d..71875fc 100644
--- a/cyclone/hammer/minimum.c
+++ b/cyclone/hammer/minimum.c
@@ -75,6 +75,7 @@ static void *minimum_new(t_floatarg f)
t_minimum *x = (t_minimum *)pd_new(minimum_class);
x->x_last = 0; /* CHECKME */
x->x_test = f;
+ shared_usecompatibility();
floatinlet_new((t_object *)x, &x->x_test);
outlet_new((t_object *)x, &s_float);
return (x);
diff --git a/cyclone/hammer/mtr.c b/cyclone/hammer/mtr.c
index ecc80d3..51ba856 100644
--- a/cyclone/hammer/mtr.c
+++ b/cyclone/hammer/mtr.c
@@ -336,11 +336,14 @@ static void mtrack_write(t_mtrack *tp, t_symbol *s)
static void mtrack_tempo(t_mtrack *tp, t_floatarg f)
{
float newtempo;
- static int warned = 0;
- if (!warned)
+ if (shared_getmaxcompatibility())
{
- loud_incompatible(mtr_class, "no 'tempo' control in Max");
- warned = 1;
+ static int warned = 0;
+ if (!warned)
+ {
+ loud_incompatible(mtr_class, "no 'tempo' control in Max");
+ warned = 1;
+ }
}
if (f < 1e-20)
f = 1e-20;
@@ -476,6 +479,7 @@ static void mtr_doread(t_mtr *x, t_mtrack *target, t_symbol *fname)
{
char path[MAXPDSTRING];
FILE *fp;
+ /* FIXME use open_via_path() */
if (x->x_glist)
canvas_makefilename(x->x_glist, fname->s_name, path, MAXPDSTRING);
else
@@ -756,6 +760,7 @@ static void *mtr_new(t_floatarg f)
x->x_glist = canvas_getcurrent();
x->x_filehandle = hammerfile_new((t_pd *)x, 0,
mtr_readhook, mtr_writehook, 0);
+ shared_usecompatibility();
if (ntracks > MTR_C74MAXTRACKS)
loud_incompatible_max(mtr_class, MTR_C74MAXTRACKS, "tracks");
x->x_ntracks = ntracks;
diff --git a/cyclone/hammer/offer.c b/cyclone/hammer/offer.c
index 3823c85..1e247e7 100644
--- a/cyclone/hammer/offer.c
+++ b/cyclone/hammer/offer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
@@ -7,9 +7,9 @@
#include "hammer/tree.h"
/* As a class `derived' from the common hammertree code (also in funbuff),
- offer uses the auxiliary list, generally not needed here.
- As a side-effect, it gets a bonus of a small speedup of deletion,
- and a penalty of a small slowdown of insertion. */
+ offer maintains the auxiliary list, the main purpose of which is faster
+ traversal (not needed here). As a side-effect, there is a bonus of a small
+ speedup of deletion, and a penalty of a small slowdown of insertion. */
typedef struct _offer
{
@@ -29,13 +29,12 @@ static void offer_float(t_offer *x, t_float f)
t_hammernode *np;
if (x->x_valueset)
{
- if (np = hammertree_insert(&x->x_tree, ndx))
- np->n_value = x->x_value;
+ hammertree_insertfloat(&x->x_tree, ndx, x->x_value, 1);
x->x_valueset = 0;
}
else if (np = hammertree_search(&x->x_tree, ndx))
{
- outlet_float(((t_object *)x)->ob_outlet, np->n_value);
+ outlet_float(((t_object *)x)->ob_outlet, HAMMERNODE_GETFLOAT(np));
hammertree_delete(&x->x_tree, np);
}
}
@@ -57,7 +56,7 @@ static void offer_clear(t_offer *x)
#ifdef HAMMERTREE_DEBUG
static void offer_debug(t_offer *x, t_floatarg f)
{
- hammertree_debug(&x->x_tree, (int)f);
+ hammertree_debug(&x->x_tree, (int)f, 0);
}
#endif
@@ -70,7 +69,7 @@ static void *offer_new(void)
{
t_offer *x = (t_offer *)pd_new(offer_class);
x->x_valueset = 0;
- hammertree_init(&x->x_tree, 0);
+ hammertree_inittyped(&x->x_tree, HAMMERTYPE_FLOAT, 0);
inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
outlet_new((t_object *)x, &s_float);
return (x);
diff --git a/cyclone/hammer/past.c b/cyclone/hammer/past.c
index cb0b4ef..bf4300c 100644
--- a/cyclone/hammer/past.c
+++ b/cyclone/hammer/past.c
@@ -112,6 +112,7 @@ static void past_set(t_past *x, t_symbol *s, int ac, t_atom *av)
t_atom *vp = x->x_thresh;
if (ac > x->x_size)
{
+ shared_usecompatibility();
loud_incompatible_max(past_class, PAST_C74MAXSIZE, "guard points");
x->x_thresh = grow_nodata(&ac, &x->x_size, x->x_thresh,
PAST_C74MAXSIZE, x->x_thrini,
diff --git a/cyclone/hammer/prepend.c b/cyclone/hammer/prepend.c
index 052c8d6..1b3bd73 100644
--- a/cyclone/hammer/prepend.c
+++ b/cyclone/hammer/prepend.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
@@ -21,9 +21,17 @@ typedef struct _prepend
int x_entered;
int x_auxsize;
t_atom *x_auxbuf;
+ t_pd *x_proxy;
} t_prepend;
+typedef struct _prependxy
+{
+ t_pd xy_pd;
+ t_prepend *xy_owner;
+} t_prependxy;
+
static t_class *prepend_class;
+static t_class *prependxy_class;
/* Usually a preallocation method is used, except in special cases of:
1) reentrant output request, or 2) an output request which would cause
@@ -32,83 +40,86 @@ static t_class *prepend_class;
A separately preallocated output buffer is not used, thus avoiding
memcpying of the stored message (a small performance gain when the
preallocation method is chosen). Instead, self-invoked 'set'
- messages are postponed, using an auxiliary buffer.
-*/
+ messages are postponed, using an auxiliary buffer. */
-static void prepend_dooutput(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+/* called only from prepend_doanything() */
+static void prepend_dooutput(t_prepend *x, int ac, t_atom *av)
{
- if (s == &s_float)
+ if (x->x_selector == &s_float)
{
if (ac > 1)
outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
else
outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float);
}
- else if (s == &s_list)
+ else if (x->x_selector == &s_list)
outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av);
- else if (s)
+ else /* x->x_selector guaranteed non-empty */
/* CHECKED: 'bang' is prepended -- we cannot do so...
('symbol' cannot be compatible too) */
- {
- outlet_anything(((t_object *)x)->ob_outlet, s, ac, av);
- }
+ outlet_anything(((t_object *)x)->ob_outlet, x->x_selector, ac, av);
}
-static void prepend_anything(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+static void prepend_doanything(t_prepend *x, t_symbol *s, int ac, t_atom *av)
{
int reentered = x->x_entered;
- int prealloc = !reentered;
- int ntotal = x->x_natoms + ac;
- t_atom *buf;
x->x_entered = 1;
- if (s == &s_) s = 0;
- if (s)
- ntotal++;
- if (prealloc && ntotal > x->x_size)
- {
- if (ntotal > PREPEND_MAXSIZE)
- prealloc = 0;
- else
- {
- int nrequested = ntotal;
- x->x_message = grow_withdata(&nrequested, &x->x_natoms,
- &x->x_size, x->x_message,
- PREPEND_INISIZE, x->x_messini,
- sizeof(*x->x_message));
- prealloc = (nrequested == ntotal);
- }
- }
- if (prealloc)
+ if (s == &s_)
+ s = 0;
+ if (s || x->x_natoms)
{
- buf = x->x_message + x->x_natoms;
+ int prealloc = !reentered;
+ int ntotal = x->x_natoms + ac;
+ t_atom *buf;
if (s)
+ ntotal++;
+ if (prealloc && ntotal > x->x_size)
{
- SETSYMBOL(buf, s);
- buf++;
+ if (ntotal > PREPEND_MAXSIZE)
+ prealloc = 0;
+ else
+ {
+ int nrequested = ntotal;
+ x->x_message = grow_withdata(&nrequested, &x->x_natoms,
+ &x->x_size, x->x_message,
+ PREPEND_INISIZE, x->x_messini,
+ sizeof(*x->x_message));
+ prealloc = (nrequested == ntotal);
+ }
}
- if (ac)
- memcpy(buf, av, ac * sizeof(*buf));
- prepend_dooutput(x, x->x_selector, ntotal, x->x_message);
- }
- else
- {
- /* LATER consider using the stack if ntotal <= MAXSTACK */
- if (buf = getbytes(ntotal * sizeof(*buf)))
+ if (prealloc)
{
- t_atom *bp = buf + x->x_natoms;
- if (x->x_natoms)
- memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf));
+ buf = x->x_message + x->x_natoms;
if (s)
{
- SETSYMBOL(bp, s);
- bp++;
+ SETSYMBOL(buf, s);
+ buf++;
}
if (ac)
- memcpy(bp, av, ac * sizeof(*bp));
- prepend_dooutput(x, x->x_selector, ntotal, buf);
- freebytes(buf, ntotal * sizeof(*buf));
+ memcpy(buf, av, ac * sizeof(*buf));
+ prepend_dooutput(x, ntotal, x->x_message);
+ }
+ else
+ {
+ /* LATER consider using the stack if ntotal <= MAXSTACK */
+ if (buf = getbytes(ntotal * sizeof(*buf)))
+ {
+ t_atom *bp = buf + x->x_natoms;
+ if (x->x_natoms)
+ memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf));
+ if (s)
+ {
+ SETSYMBOL(bp, s);
+ bp++;
+ }
+ if (ac)
+ memcpy(bp, av, ac * sizeof(*bp));
+ prepend_dooutput(x, ntotal, buf);
+ freebytes(buf, ntotal * sizeof(*buf));
+ }
}
}
+ else prepend_dooutput(x, ac, av);
if (!reentered)
{
x->x_entered = 0;
@@ -136,51 +147,75 @@ static void prepend_anything(t_prepend *x, t_symbol *s, int ac, t_atom *av)
static void prepend_bang(t_prepend *x)
{
- t_atom at;
- SETSYMBOL(&at, &s_bang); /* CHECKED */
- prepend_anything(x, 0, 1, &at);
+ if (x->x_selector)
+ {
+ t_atom at;
+ SETSYMBOL(&at, &s_bang); /* CHECKED */
+ prepend_doanything(x, 0, 1, &at);
+ }
+ else outlet_bang(((t_object *)x)->ob_outlet);
}
static void prepend_float(t_prepend *x, t_float f)
{
- t_atom at;
- SETFLOAT(&at, f);
- prepend_anything(x, 0, 1, &at);
+ if (x->x_selector)
+ {
+ t_atom at;
+ SETFLOAT(&at, f);
+ prepend_doanything(x, 0, 1, &at);
+ }
+ else outlet_float(((t_object *)x)->ob_outlet, f);
}
static void prepend_symbol(t_prepend *x, t_symbol *s)
{
- t_atom at;
- SETSYMBOL(&at, s);
- prepend_anything(x, 0, 1, &at);
+ if (x->x_selector)
+ {
+ t_atom at;
+ SETSYMBOL(&at, s);
+ prepend_doanything(x, 0, 1, &at);
+ }
+ else outlet_symbol(((t_object *)x)->ob_outlet, s);
}
/* LATER gpointer */
static void prepend_list(t_prepend *x, t_symbol *s, int ac, t_atom *av)
{
- prepend_anything(x, 0, ac, av);
+ if (x->x_selector)
+ prepend_doanything(x, 0, ac, av);
+ else
+ outlet_list(((t_object *)x)->ob_outlet, s, ac, av);
}
-static void prepend_set(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+static void prepend_anything(t_prepend *x, t_symbol *s, int ac, t_atom *av)
{
- if (ac)
+ if (x->x_selector)
+ prepend_doanything(x, s, ac, av);
+ else
+ outlet_anything(((t_object *)x)->ob_outlet, s, ac, av);
+}
+
+static void prepend_doset(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (s)
+ x->x_selector = s;
+ else if (ac)
{
- int newsize;
- if (av->a_type == A_FLOAT)
- {
- if (ac > 1) x->x_selector = &s_list;
- else x->x_selector = &s_float;
- }
- else if (av->a_type == A_SYMBOL)
+ if (av->a_type == A_SYMBOL)
{
x->x_selector = av->a_w.w_symbol;
- ac--;
- av++;
+ ac--; av++;
}
+ else if (av->a_type == A_FLOAT)
+ x->x_selector = (ac > 1 ? &s_list : &s_float);
else
return; /* LATER rethink */
- newsize = ac * 2;
+ }
+ else x->x_selector = 0;
+ if (ac)
+ {
+ int newsize = ac * 2;
if (x->x_entered)
{
if (x->x_auxbuf)
@@ -212,12 +247,56 @@ static void prepend_set(t_prepend *x, t_symbol *s, int ac, t_atom *av)
while (ac--) *ap++ = *av++;
}
}
+ else x->x_natoms = 0;
+}
+
+static void prepend_set(t_prepend *x, t_symbol *s, int ac, t_atom *av)
+{
+ if (shared_getmaxcompatibility())
+ prepend_doset(x, 0, ac, av);
+ else
+ prepend_anything(x, s, ac, av);
+}
+
+static void prependxy_bang(t_prependxy *xy)
+{
+ prepend_doset(xy->xy_owner, 0, 0, 0); /* LATER rethink */
+}
+
+static void prependxy_float(t_prependxy *xy, t_float f)
+{
+ t_atom at;
+ SETFLOAT(&at, f);
+ prepend_doset(xy->xy_owner, &s_float, 1, &at);
+}
+
+static void prependxy_symbol(t_prependxy *xy, t_symbol *s)
+{
+ prepend_doset(xy->xy_owner,
+ (s && s != &s_ ? s : &s_symbol), 0, 0); /* LATER rethink */
+}
+
+static void prependxy_list(t_prependxy *xy, t_symbol *s, int ac, t_atom *av)
+{
+ prepend_doset(xy->xy_owner, &s_list, ac, av); /* LATER rethink */
+}
+
+static void prependxy_anything(t_prependxy *xy, t_symbol *s, int ac, t_atom *av)
+{
+ prepend_doset(xy->xy_owner, s, ac, av);
}
static void prepend_free(t_prepend *x)
{
if (x->x_message != x->x_messini)
freebytes(x->x_message, x->x_size * sizeof(*x->x_message));
+ if (x->x_auxbuf)
+ {
+ bug("prepend_free"); /* LATER rethink */
+ freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf));
+ }
+ if (x->x_proxy)
+ pd_free(x->x_proxy);
}
static void *prepend_new(t_symbol *s, int ac, t_atom *av)
@@ -229,15 +308,25 @@ static void *prepend_new(t_symbol *s, int ac, t_atom *av)
x->x_message = x->x_messini;
x->x_auxbuf = 0;
x->x_entered = 0;
- if (!ac)
+ shared_usecompatibility();
+ if (ac)
{
- loud_incompatible(prepend_class,
- "creating an object without an argument");
- /* CHECKED: this is not compatible -- in max an object without an outlet
- is created, and there is no warning if loading from a file. */
+ x->x_proxy = 0;
+ prepend_doset(x, 0, ac, av);
+ }
+ else
+ {
+ if (shared_getmaxcompatibility())
+ /* CHECKED: this is still not compatible -- in max an object
+ without an outlet is created, and there is no warning when
+ loading from a file. */
+ loud_incompatible(prepend_class,
+ "creating an object without an argument");
+ x->x_proxy = pd_new(prependxy_class);
+ ((t_prependxy *)x->x_proxy)->xy_owner = x;
+ inlet_new((t_object *)x, x->x_proxy, 0, 0);
}
outlet_new((t_object *)x, &s_anything);
- prepend_set(x, 0, ac, av);
return (x);
}
@@ -255,4 +344,12 @@ void prepend_setup(void)
class_addanything(prepend_class, prepend_anything);
class_addmethod(prepend_class, (t_method)prepend_set,
gensym("set"), A_GIMME, 0);
+
+ prependxy_class = class_new(gensym("prepend"), 0, 0, sizeof(t_prependxy),
+ CLASS_PD | CLASS_NOINLET, 0);
+ class_addbang(prependxy_class, prependxy_bang);
+ class_addfloat(prependxy_class, prependxy_float);
+ class_addsymbol(prependxy_class, prependxy_symbol);
+ class_addlist(prependxy_class, prependxy_list);
+ class_addanything(prependxy_class, prependxy_anything);
}
diff --git a/cyclone/hammer/prob.c b/cyclone/hammer/prob.c
index e20e420..114a41d 100644
--- a/cyclone/hammer/prob.c
+++ b/cyclone/hammer/prob.c
@@ -274,6 +274,7 @@ static void *prob_new(void)
x->x_embedmode = 0; /* CHECKED */
x->x_silent = 0;
rand_seed(&x->x_seed, 0);
+ shared_usecompatibility();
outlet_new((t_object *)x, &s_float);
x->x_bangout = outlet_new((t_object *)x, &s_bang);
x->x_filehandle = hammerfile_new((t_pd *)x, prob_embedhook, 0, 0, 0);
diff --git a/cyclone/hammer/seq.c b/cyclone/hammer/seq.c
index edeff88..f29c803 100644
--- a/cyclone/hammer/seq.c
+++ b/cyclone/hammer/seq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002-2003 krzYszcz and others.
+/* Copyright (c) 2002-2004 krzYszcz and others.
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
@@ -11,26 +11,33 @@
#include "shared.h"
#include "common/loud.h"
#include "common/grow.h"
-#include "common/sq.h"
-#include "common/bifi.h"
#include "common/mifi.h"
+#include "unstable/forky.h"
#include "hammer/file.h"
-//#define SEQ_DEBUG
+#define SEQ_DEBUG
-#define SEQ_INISIZE 256 /* LATER rethink */
-#define SEQ_EOM 255 /* end of message marker, LATER rethink */
-#define SEQ_TICKSPERSEC 48
-#define SEQ_MINTICKDELAY 1. /* LATER rethink */
+#define SEQ_INISEQSIZE 256 /* LATER rethink */
+#define SEQ_INITEMPOMAPSIZE 128 /* LATER rethink */
+#define SEQ_EOM 255 /* end of message marker, LATER rethink */
+#define SEQ_TICKSPERSEC 48
+#define SEQ_MINTICKDELAY 1. /* LATER rethink */
+#define SEQ_TICKEPSILON ((double).0001)
enum { SEQ_IDLEMODE, SEQ_RECMODE, SEQ_PLAYMODE, SEQ_SLAVEMODE };
typedef struct _seqevent
{
- int e_delta;
+ double e_delta;
unsigned char e_bytes[4];
} t_seqevent;
+typedef struct _seqtempo
+{
+ double t_scoretime; /* score ticks from start */
+ double t_sr; /* score ticks per second */
+} t_seqtempo;
+
typedef struct _seq
{
t_object x_ob;
@@ -39,18 +46,24 @@ typedef struct _seq
t_hammerfile *x_filehandle;
int x_mode;
int x_playhead;
- float x_tempo;
- float x_newtempo;
+ float x_timescale;
+ float x_newtimescale;
double x_prevtime;
double x_slaveprevtime;
double x_clockdelay;
unsigned char x_status;
- int x_evesize;
- int x_expectedsize;
- int x_size; /* as allocated */
+ int x_evelength;
+ int x_expectedlength;
+ int x_eventreadhead;
+ int x_seqsize; /* as allocated */
int x_nevents; /* as used */
t_seqevent *x_sequence;
- t_seqevent x_seqini[SEQ_INISIZE];
+ t_seqevent x_seqini[SEQ_INISEQSIZE];
+ int x_temporeadhead;
+ int x_tempomapsize; /* as allocated */
+ int x_ntempi; /* as used */
+ t_seqtempo *x_tempomap;
+ t_seqtempo x_tempomapini[SEQ_INITEMPOMAPSIZE];
t_clock *x_clock;
t_clock *x_slaveclock;
t_outlet *x_bangout;
@@ -60,35 +73,85 @@ static t_class *seq_class;
static void seq_doclear(t_seq *x, int dofree)
{
- if (dofree && x->x_sequence != x->x_seqini)
+ if (dofree)
{
- freebytes(x->x_sequence, x->x_size * sizeof(*x->x_sequence));
- x->x_sequence = x->x_seqini;
- x->x_size = SEQ_INISIZE;
+ if (x->x_sequence != x->x_seqini)
+ {
+ freebytes(x->x_sequence, x->x_seqsize * sizeof(*x->x_sequence));
+ x->x_sequence = x->x_seqini;
+ x->x_seqsize = SEQ_INISEQSIZE;
+ }
+ if (x->x_tempomap != x->x_tempomapini)
+ {
+ freebytes(x->x_tempomap,
+ x->x_tempomapsize * sizeof(*x->x_tempomap));
+ x->x_tempomap = x->x_tempomapini;
+ x->x_tempomapsize = SEQ_INITEMPOMAPSIZE;
+ }
}
x->x_nevents = 0;
+ x->x_ntempi = 0;
+}
+
+static int seq_dogrowing(t_seq *x, int nevents, int ntempi)
+{
+ if (nevents > x->x_seqsize)
+ {
+ int nrequested = nevents;
+#ifdef SEQ_DEBUG
+ post("growing for %d events...", nevents);
+#endif
+ x->x_sequence =
+ grow_nodata(&nrequested, &x->x_seqsize, x->x_sequence,
+ SEQ_INISEQSIZE, x->x_seqini, sizeof(*x->x_sequence));
+ if (nrequested < nevents)
+ {
+ x->x_nevents = 0;
+ x->x_ntempi = 0;
+ return (0);
+ }
+ }
+ if (ntempi > x->x_tempomapsize)
+ {
+ int nrequested = ntempi;
+#ifdef SEQ_DEBUG
+ post("growing for %d tempi...", ntempi);
+#endif
+ x->x_tempomap =
+ grow_nodata(&nrequested, &x->x_tempomapsize, x->x_tempomap,
+ SEQ_INITEMPOMAPSIZE, x->x_tempomapini,
+ sizeof(*x->x_tempomap));
+ if (nrequested < ntempi)
+ {
+ x->x_ntempi = 0;
+ return (0);
+ }
+ }
+ x->x_nevents = nevents;
+ x->x_ntempi = ntempi;
+ return (1);
}
static void seq_complete(t_seq *x)
{
- if (x->x_evesize < x->x_expectedsize)
+ if (x->x_evelength < x->x_expectedlength)
{
/* CHECKED no warning if no data after status byte requiring data */
- if (x->x_evesize > 1)
+ if (x->x_evelength > 1)
post("seq: truncated midi message"); /* CHECKED */
/* CHECKED nothing stored */
}
else
{
t_seqevent *ep = &x->x_sequence[x->x_nevents];
- ep->e_delta = (int)clock_gettimesince(x->x_prevtime);
+ ep->e_delta = clock_gettimesince(x->x_prevtime);
x->x_prevtime = clock_getlogicaltime();
- if (x->x_evesize < 4)
- ep->e_bytes[x->x_evesize] = SEQ_EOM;
+ if (x->x_evelength < 4)
+ ep->e_bytes[x->x_evelength] = SEQ_EOM;
x->x_nevents++;
- if (x->x_nevents >= x->x_size)
+ if (x->x_nevents >= x->x_seqsize)
{
- int nexisting = x->x_size;
+ int nexisting = x->x_seqsize;
/* store-ahead scheme, LATER consider using x_currevent */
int nrequested = x->x_nevents + 1;
#ifdef SEQ_DEBUG
@@ -96,54 +159,55 @@ static void seq_complete(t_seq *x)
#endif
x->x_sequence =
grow_withdata(&nrequested, &nexisting,
- &x->x_size, x->x_sequence,
- SEQ_INISIZE, x->x_seqini, sizeof(*x->x_sequence));
+ &x->x_seqsize, x->x_sequence,
+ SEQ_INISEQSIZE, x->x_seqini,
+ sizeof(*x->x_sequence));
if (nrequested <= x->x_nevents)
x->x_nevents = 0;
}
}
- x->x_evesize = 0;
+ x->x_evelength = 0;
}
static void seq_checkstatus(t_seq *x, unsigned char c)
{
- if (x->x_status && x->x_evesize > 1) /* LATER rethink */
+ if (x->x_status && x->x_evelength > 1) /* LATER rethink */
seq_complete(x);
if (c < 192)
- x->x_expectedsize = 3;
+ x->x_expectedlength = 3;
else if (c < 224)
- x->x_expectedsize = 2;
+ x->x_expectedlength = 2;
else if (c < 240)
- x->x_expectedsize = 3;
+ x->x_expectedlength = 3;
else if (c < 248)
{
/* FIXME */
- x->x_expectedsize = -1;
+ x->x_expectedlength = -1;
}
else
{
x->x_sequence[x->x_nevents].e_bytes[0] = c;
- x->x_evesize = x->x_expectedsize = 1;
+ x->x_evelength = x->x_expectedlength = 1;
seq_complete(x);
return;
}
x->x_status = x->x_sequence[x->x_nevents].e_bytes[0] = c;
- x->x_evesize = 1;
+ x->x_evelength = 1;
}
static void seq_addbyte(t_seq *x, unsigned char c, int docomplete)
{
- x->x_sequence[x->x_nevents].e_bytes[x->x_evesize++] = c;
- if (x->x_evesize == x->x_expectedsize)
+ x->x_sequence[x->x_nevents].e_bytes[x->x_evelength++] = c;
+ if (x->x_evelength == x->x_expectedlength)
{
seq_complete(x);
if (x->x_status)
{
x->x_sequence[x->x_nevents].e_bytes[0] = x->x_status;
- x->x_evesize = 1;
+ x->x_evelength = 1;
}
}
- else if (x->x_evesize == 4)
+ else if (x->x_evelength == 4)
{
if (x->x_status != 240)
bug("seq_addbyte");
@@ -195,8 +259,8 @@ static void seq_startrecording(t_seq *x, int modechanged)
{
x->x_prevtime = clock_getlogicaltime();
x->x_status = 0;
- x->x_evesize = 0;
- x->x_expectedsize = -1; /* LATER rethink */
+ x->x_evelength = 0;
+ x->x_expectedlength = -1; /* LATER rethink */
}
/* CHECKED running status not used in playback */
@@ -210,19 +274,19 @@ static void seq_startplayback(t_seq *x, int modechanged)
x->x_playhead = 0;
/* playback data never sent within the scheduler event of
a start message (even for the first delta <= 0), LATER rethink */
- x->x_clockdelay = x->x_sequence->e_delta * x->x_newtempo;
+ x->x_clockdelay = x->x_sequence->e_delta * x->x_newtimescale;
}
else
{
- /* CHECKED tempo change */
+ /* CHECKED timescale change */
x->x_clockdelay -= clock_gettimesince(x->x_prevtime);
- x->x_clockdelay *= x->x_newtempo / x->x_tempo;
+ x->x_clockdelay *= x->x_newtimescale / x->x_timescale;
}
if (x->x_clockdelay < 0.)
x->x_clockdelay = 0.;
clock_delay(x->x_clock, x->x_clockdelay);
x->x_prevtime = clock_getlogicaltime();
- x->x_tempo = x->x_newtempo;
+ x->x_timescale = x->x_newtimescale;
}
else x->x_mode = SEQ_IDLEMODE;
}
@@ -280,14 +344,14 @@ static void seq_setmode(t_seq *x, int newmode)
}
}
-static void seq_settempo(t_seq *x, float newtempo)
+static void seq_settimescale(t_seq *x, float newtimescale)
{
- if (newtempo < 1e-20)
- x->x_newtempo = 1e-20;
- else if (newtempo > 1e20)
- x->x_newtempo = 1e20;
+ if (newtimescale < 1e-20)
+ x->x_newtimescale = 1e-20;
+ else if (newtimescale > 1e20)
+ x->x_newtimescale = 1e20;
else
- x->x_newtempo = newtempo;
+ x->x_newtimescale = newtimescale;
}
static void seq_clocktick(t_seq *x)
@@ -313,7 +377,7 @@ nextevent:
if (x->x_playhead < x->x_nevents)
{
ep++;
- if (ep->e_delta <= 0)
+ if (ep->e_delta < SEQ_TICKEPSILON)
/* continue output in the same scheduler event, LATER rethink */
{
x->x_playhead++;
@@ -322,7 +386,7 @@ nextevent:
}
else
{
- x->x_clockdelay = ep->e_delta * x->x_tempo;
+ x->x_clockdelay = ep->e_delta * x->x_timescale;
if (x->x_clockdelay < 0.)
x->x_clockdelay = 0.;
clock_delay(x->x_clock, x->x_clockdelay);
@@ -355,36 +419,36 @@ static void seq_tick(t_seq *x)
if (elapsed < SEQ_MINTICKDELAY)
return;
clock_delay(x->x_slaveclock, elapsed);
- seq_settempo(x, (float)(elapsed * (SEQ_TICKSPERSEC / 1000.)));
+ seq_settimescale(x, (float)(elapsed * (SEQ_TICKSPERSEC / 1000.)));
if (x->x_prevtime > 0)
{
x->x_clockdelay -= clock_gettimesince(x->x_prevtime);
- x->x_clockdelay *= x->x_newtempo / x->x_tempo;
+ x->x_clockdelay *= x->x_newtimescale / x->x_timescale;
}
else x->x_clockdelay =
- x->x_sequence[x->x_playhead].e_delta * x->x_newtempo;
+ x->x_sequence[x->x_playhead].e_delta * x->x_newtimescale;
if (x->x_clockdelay < 0.)
x->x_clockdelay = 0.;
clock_delay(x->x_clock, x->x_clockdelay);
x->x_prevtime = clock_getlogicaltime();
x->x_slaveprevtime = x->x_prevtime;
- x->x_tempo = x->x_newtempo;
+ x->x_timescale = x->x_newtimescale;
}
else
{
x->x_clockdelay = 0.; /* redundant */
x->x_prevtime = 0.; /* redundant */
x->x_slaveprevtime = clock_getlogicaltime();
- x->x_tempo = 1.; /* redundant */
+ x->x_timescale = 1.; /* redundant */
}
}
}
-/* CHECKED bang does the same as 'start 1024', not 'start <current-tempo>'
+/* CHECKED bang does the same as 'start 1024', not 'start <current-timescale>'
(also if already in SEQ_PLAYMODE) */
static void seq_bang(t_seq *x)
{
- seq_settempo(x, 1.);
+ seq_settimescale(x, 1.);
seq_setmode(x, SEQ_PLAYMODE); /* CHECKED 'bang' stops recording */
}
@@ -450,7 +514,7 @@ static void seq_start(t_seq *x, t_floatarg f)
}
else
{
- seq_settempo(x, (f == 0 ? 1. : 1024. / f));
+ seq_settimescale(x, (f == 0 ? 1. : 1024. / f));
seq_setmode(x, SEQ_PLAYMODE); /* CHECKED 'start' stops recording */
}
}
@@ -465,7 +529,7 @@ static void seq_delay(t_seq *x, t_floatarg f)
{
if (x->x_nevents)
/* CHECKED signed/unsigned bug (not emulated) */
- x->x_sequence->e_delta = (f > 0 ? f : 0);
+ x->x_sequence->e_delta = (f > SEQ_TICKEPSILON ? f : 0.);
}
/* CHECKED all delta times are set permanently (they are stored in a file) */
@@ -481,223 +545,177 @@ static void seq_hook(t_seq *x, t_floatarg f)
}
}
-static int seq_dogrowing(t_seq *x, int nevents)
+static int seq_eventcomparehook(const void *e1, const void *e2)
{
- if (nevents > x->x_size)
- {
- int nrequested = nevents;
-#ifdef SEQ_DEBUG
- post("growing...");
-#endif
- x->x_sequence =
- grow_nodata(&nrequested, &x->x_size, x->x_sequence,
- SEQ_INISIZE, x->x_seqini, sizeof(*x->x_sequence));
- if (nrequested < nevents)
- {
- x->x_nevents = 0;
- return (0);
- }
- }
- x->x_nevents = nevents;
- return (1);
-}
-
-static int seq_seekhook(t_squiter *it, int offset)
-{
- t_seq *x = (t_seq *)it->i_owner;
- post("seek in %d", x->x_nevents);
- it->i_nelems = x->x_nevents;
- it->i_sequence = x->x_sequence;
- if (offset < 0)
- offset += it->i_nelems;
- if (offset >= 0 && offset < it->i_nelems)
- {
- it->i_element = (t_seqevent *)it->i_sequence + offset;
- it->i_index = offset;
- return (1);
- }
- else return (0);
-}
-
-static void seq_incrhook(t_squiter *it)
-{
- ((t_seqevent *)it->i_element)++;
- it->i_index++;
+ return (((t_seqevent *)e1)->e_delta > ((t_seqevent *)e2)->e_delta ? 1 : -1);
}
-/* LATER put seq_mfwrite_doit() functionality here */
-static void seq_getevehook(t_squiter *it, t_mifi_event *mev, int *ret)
+static int seq_tempocomparehook(const void *t1, const void *t2)
{
- *ret = 1;
+ return (((t_seqtempo *)t1)->t_scoretime >
+ ((t_seqtempo *)t2)->t_scoretime ? 1 : -1);
}
-static void seq_setevehook(t_squiter *it, t_mifi_event *mev, int *ret)
+static int seq_mrhook(t_mifiread *mr, void *hookdata, int evtype)
{
- t_seqevent *sev = it->i_element;
- sev->e_delta = mev->e_delay;
- sev->e_bytes[0] = mev->e_status | mev->e_channel;
- sev->e_bytes[1] = mev->e_data[0];
- if (MIFI_ONE_DATABYTE(mev->e_status))
- sev->e_bytes[2] = SEQ_EOM;
- else
+ t_seq *x = (t_seq *)hookdata;
+ double scoretime = mifiread_getscoretime(mr);
+ if (evtype >= 0xf0)
{
- sev->e_bytes[2] = mev->e_data[1];
- sev->e_bytes[3] = SEQ_EOM;
}
- *ret = 1;
-}
-
-static t_float seq_gettimhook(t_squiter *it, int *ret)
-{
- t_seqevent *sev = it->i_element;
- *ret = 1;
- return (sev->e_delta);
-}
-
-static void seq_settimhook(t_squiter *it, t_float f, int *ret)
-{
- t_seqevent *sev = it->i_element;
- sev->e_delta = f;
- *ret = 1;
-}
-
-static t_symbol *seq_gettarhook(t_squiter *it, int *ret)
-{
- *ret = 1;
- return (0);
-}
-
-static void seq_settarhook(t_squiter *it, t_symbol *s, int *ret)
-{
- *ret = 1;
-}
-
-static int seq_make_iterator(t_seq *x, t_mifi_stream *stp)
-{
- t_squiter *it = squiter_new(stp);
- if (it)
+ else if (evtype >= 0x80)
{
- it->i_owner = x;
- it->i_nelems = x->x_nevents;
- it->i_sequence = it->i_element = x->x_sequence;
- it->i_index = 0;
- it->i_hooks[SQUITER_SEEKHOOK] = (t_squiterhook)seq_seekhook;
- it->i_hooks[SQUITER_INCRHOOK] = (t_squiterhook)seq_incrhook;
- it->i_hooks[SQUITER_GETEVEHOOK] = (t_squiterhook)seq_getevehook;
- it->i_hooks[SQUITER_SETEVEHOOK] = (t_squiterhook)seq_setevehook;
- it->i_hooks[SQUITER_GETTIMHOOK] = (t_squiterhook)seq_gettimhook;
- it->i_hooks[SQUITER_SETTIMHOOK] = (t_squiterhook)seq_settimhook;
- it->i_hooks[SQUITER_GETTARHOOK] = (t_squiterhook)seq_gettarhook;
- it->i_hooks[SQUITER_SETTARHOOK] = (t_squiterhook)seq_settarhook;
- return (1);
+ if (x->x_eventreadhead < x->x_nevents)
+ {
+ t_seqevent *sev = &x->x_sequence[x->x_eventreadhead++];
+ int status = mifiread_getstatus(mr);
+ sev->e_delta = scoretime;
+ sev->e_bytes[0] = status | mifiread_getchannel(mr);
+ sev->e_bytes[1] = mifiread_getdata1(mr);
+ if (MIFI_ONEDATABYTE(status))
+ sev->e_bytes[2] = SEQ_EOM;
+ else
+ {
+ sev->e_bytes[2] = mifiread_getdata2(mr);
+ sev->e_bytes[3] = SEQ_EOM;
+ }
+ }
+ else if (x->x_eventreadhead == x->x_nevents)
+ {
+ bug("seq_mrhook 1");
+ x->x_eventreadhead++;
+ }
}
- else return (0);
-}
-
-static t_mifi_stream *seq_makestream(t_seq *x)
-{
- t_mifi_stream *stp = 0;
- if (stp = mifi_stream_new())
+ else if (evtype == MIFIMETA_TEMPO)
{
- if (seq_make_iterator(x, stp))
- return (stp);
- else
- mifi_stream_free(stp);
+ if (x->x_temporeadhead < x->x_ntempi)
+ {
+ t_seqtempo *stm = &x->x_tempomap[x->x_temporeadhead++];
+ stm->t_scoretime = scoretime;
+ stm->t_sr = mifiread_gettempo(mr);
+#ifdef SEQ_DEBUG
+ post("tempo %g at %g", stm->t_sr, scoretime);
+#endif
+ }
+ else if (x->x_temporeadhead == x->x_ntempi)
+ {
+ bug("seq_mrhook 2");
+ x->x_temporeadhead++;
+ }
}
- return (0);
+ return (1);
}
-static int seq_comparehook(const void *e1, const void *e2)
+/* apply tempo and fold */
+static void seq_foldtime(t_seq *x, double deftempo)
{
- return (((t_seqevent *)e1)->e_delta > ((t_seqevent *)e2)->e_delta ? 1 : -1);
+ t_seqevent *sev;
+ t_seqtempo *stm = x->x_tempomap;
+ double coef = 1000. / deftempo;
+ int ex, tx = 0;
+ double prevscoretime = 0.;
+ while (tx < x->x_ntempi && stm->t_scoretime < SEQ_TICKEPSILON)
+ tx++, coef = 1000. / stm++->t_sr;
+ for (ex = 0, sev = x->x_sequence; ex < x->x_nevents; ex++, sev++)
+ {
+ double clockdelta = 0.;
+ while (tx < x->x_ntempi && stm->t_scoretime <= sev->e_delta)
+ {
+ clockdelta += (stm->t_scoretime - prevscoretime) * coef;
+ prevscoretime = stm->t_scoretime;
+ tx++;
+ coef = 1000. / stm++->t_sr;
+ }
+ clockdelta += (sev->e_delta - prevscoretime) * coef;
+ prevscoretime = sev->e_delta;
+ sev->e_delta = clockdelta;
+ }
}
-/* FIXME */
static int seq_mfread(t_seq *x, char *path)
{
int result = 0;
- t_mifi_stream *stp = 0;
- if (!(stp = seq_makestream(x)) ||
- !mifi_read_start(stp, path, "", 0))
- goto readfailed;
+ t_mifiread *mr = mifiread_new((t_pd *)x);
+ if (!mifiread_open(mr, path, "", 0))
+ goto mfreadfailed;
#ifdef SEQ_DEBUG
- if (stp->s_nframes)
- post("midifile (format %d): %d tracks, %d ticks (%d smpte frames)",
- stp->s_format, stp->s_hdtracks, stp->s_nticks, stp->s_nframes);
+ startpost("midifile (format %d): %d tracks, %d ticks",
+ mifiread_getformat(mr), mifiread_gethdtracks(mr),
+ mifiread_getbeatticks(mr));
+ if (mifiread_getnframes(mr))
+ post(" (%d smpte frames)", mifiread_getnframes(mr));
else
- post("midifile (format %d): %d tracks, %d ticks per beat",
- stp->s_format, stp->s_hdtracks, stp->s_nticks);
+ post(" per beat");
#endif
- if (mifi_read_analyse(stp) != MIFI_READ_EOF ||
- !seq_dogrowing(x, stp->s_nevents) ||
- !mifi_read_restart(stp) ||
- mifi_read_doit(stp) != MIFI_READ_EOF)
- goto readfailed;
- squmpi_sort(stp);
- qsort(x->x_sequence, stp->s_nevents, sizeof(*x->x_sequence),
- seq_comparehook);
- sq_fold_time(stp);
+ if (!seq_dogrowing(x, mifiread_getnevents(mr), mifiread_getntempi(mr)))
+ goto mfreadfailed;
+ x->x_eventreadhead = 0;
+ x->x_temporeadhead = 0;
+ if (mifiread_doit(mr, seq_mrhook, x) != MIFIREAD_EOF)
+ goto mfreadfailed;
+ if (x->x_eventreadhead < x->x_nevents)
+ {
+ bug("seq_mfread 1");
+ post("declared %d events, got %d", x->x_nevents, x->x_eventreadhead);
+ x->x_nevents = x->x_eventreadhead;
+ }
+ if (x->x_nevents)
+ qsort(x->x_sequence, x->x_nevents, sizeof(*x->x_sequence),
+ seq_eventcomparehook);
+ if (x->x_temporeadhead < x->x_ntempi)
+ {
+ bug("seq_mfread 2");
+ post("declared %d tempi, got %d", x->x_ntempi, x->x_temporeadhead);
+ x->x_ntempi = x->x_temporeadhead;
+ }
+ if (x->x_ntempi)
+ qsort(x->x_tempomap, x->x_ntempi, sizeof(*x->x_tempomap),
+ seq_tempocomparehook);
+ seq_foldtime(x, mifiread_getdeftempo(mr));
#ifdef SEQ_DEBUG
- post("finished reading %d events from midifile", stp->s_nevents);
+ post("seq: got %d events from midi file", x->x_nevents);
#endif
result = 1;
-readfailed:
- if (stp)
- {
- mifi_read_end(stp);
- mifi_stream_free(stp);
- }
+mfreadfailed:
+ mifiread_free(mr);
return (result);
}
-/* FIXME */
-static int seq_mfwrite_doit(t_seq *x, t_mifi_stream *stp)
+static int seq_mfwrite(t_seq *x, char *path)
{
- t_mifi_event *mev = stp->s_auxeve;
+ int result = 0;
t_seqevent *sev = x->x_sequence;
int nevents = x->x_nevents;
+ t_mifiwrite *mw = mifiwrite_new((t_pd *)x);
+ if (!mifiwrite_open(mw, path, "", 1, 1))
+ goto mfwritefailed;
+ if (!mifiwrite_opentrack(mw, "seq-track", 1))
+ goto mfwritefailed;
while (nevents--)
{
unsigned char *bp = sev->e_bytes;
- int i;
- mev->e_delay = (uint32)(sev->e_delta * stp->s_timecoef);
- mev->e_status = *bp & 0xf0;
- mev->e_channel = *bp & 0x0f;
- /* FIXME sysex continuation */
- for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++)
- mev->e_data[i] = *bp;
- if (!mifi_write_event(stp, mev))
- return (0);
+ unsigned status = *bp & 0xf0;
+ if (status > 127 && status < 240)
+ {
+ if (!mifiwrite_channelevent(mw, sev->e_delta, status, *bp & 0x0f,
+ bp[1], bp[2])) /* SEQ_EOM ignored */
+ {
+ loud_error((t_pd *)x, "cannot write channel event %d", status);
+ goto mfwritefailed;
+ }
+ }
+ /* FIXME system, sysex (first, and continuation) */
sev++;
}
- return (1);
-}
-
-/* FIXME */
-static int seq_mfwrite(t_seq *x, char *path)
-{
- int result = 0;
- t_mifi_stream *stp = 0;
- if (!(stp = seq_makestream(x)))
- goto writefailed;
- stp->s_ntracks = 1;
- stp->s_hdtracks = 1;
- stp->s_format = 0;
- if (!mifi_write_start(stp, path, ""))
- goto writefailed;
- mifi_event_settext(stp->s_auxeve, MIFI_META_TRACKNAME, "seq-track");
- if (!mifi_write_start_track(stp) ||
- !mifi_write_event(stp, stp->s_auxeve) ||
- !seq_mfwrite_doit(x, stp) ||
- !mifi_write_adjust_track(stp, 0))
- goto writefailed;
+ if (!mifiwrite_closetrack(mw, 0., 1))
+ goto mfwritefailed;
+ mifiwrite_close(mw);
result = 1;
-writefailed:
- if (stp)
- {
- mifi_write_end(stp);
- mifi_stream_free(stp);
- }
+mfwritefailed:
+ if (!result)
+ loud_errand((t_pd *)x,
+ "while saving sequence into midi file \"%s\"", path);
+ mifiwrite_free(mw);
return (result);
}
@@ -716,7 +734,7 @@ static int seq_frombinbuf(t_seq *x, t_binbuf *bb)
t_seqevent *ep;
float prevtime = 0;
int i = -1;
- if (!seq_dogrowing(x, nevents))
+ if (!seq_dogrowing(x, nevents, 0))
return (0);
nevents = 0;
ac = binbuf_getnatom(bb);
@@ -815,6 +833,7 @@ static void seq_textwrite(t_seq *x, char *path)
static void seq_doread(t_seq *x, t_symbol *fn, int creation)
{
char buf[MAXPDSTRING];
+ /* FIXME use open_via_path() */
if (x->x_canvas)
canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING);
else
@@ -853,7 +872,8 @@ static void seq_dowrite(t_seq *x, t_symbol *fn)
/* save as text for any extension other then ".mid" */
if ((dotp = strrchr(fn->s_name, '.')) && strcmp(dotp + 1, "mid"))
seq_textwrite(x, buf);
- else /* save as mf for ".mid" or no extension at all, LATER rethink */
+ else /* save as mf for ".mid" (FIXME ignore case?) or no extension at all,
+ LATER rethink */
seq_mfwrite(x, buf);
}
@@ -884,6 +904,23 @@ static void seq_write(t_seq *x, t_symbol *s)
canvas_getdir(x->x_canvas), x->x_defname);
}
+static void seq_eventstring(t_seq *x, char *buf, t_seqevent *ep)
+{
+ unsigned char *bp = ep->e_bytes;
+ int i;
+ if (*bp < 128 || *bp == 247)
+ sprintf(buf, "(%g)->", ep->e_delta);
+ else
+ sprintf(buf, "(%g)", ep->e_delta);
+ buf += strlen(buf);
+ sprintf(buf, " %g", (float)*bp);
+ for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++)
+ {
+ buf += strlen(buf);
+ sprintf(buf, " %g", (float)*bp);
+ }
+}
+
static void seq_print(t_seq *x)
{
int nevents = x->x_nevents;
@@ -891,39 +928,52 @@ static void seq_print(t_seq *x)
if (nevents)
{
t_seqevent *ep = x->x_sequence;
+ char buf[MAXPDSTRING+2];
int truncated;
if (nevents > 16)
nevents = 16, truncated = 1;
else
truncated = 0;
+ endpost();
while (nevents--)
{
- unsigned char *bp = ep->e_bytes;
- int i;
- if (*bp < 128 || *bp == 247)
- /* CHECKED (sysex continuation) */
- startpost("\n(%d)->", ep->e_delta);
- else
- startpost("\n(%d)", ep->e_delta);
- /* CHECKED space-separated, no semi */
- postfloat((float)*bp);
- for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++)
- postfloat((float)*bp);
+ /* CHECKED bytes are space-separated, no semi */
+ seq_eventstring(x, buf, ep);
+ post(buf);
ep++;
}
- endpost();
if (truncated) post("..."); /* CHECKED */
}
else post(" no sequence"); /* CHECKED */
}
+static void seq_properties(t_gobj *z, t_glist *glist)
+{
+ t_seq *x = (t_seq *)z;
+ t_seqevent *ep = x->x_sequence;
+ int nevents = x->x_nevents;
+ char buf[MAXPDSTRING+2];
+ sprintf(buf, "seq: %s", (x->x_defname && x->x_defname != &s_ ?
+ x->x_defname->s_name : "<anonymous>"));
+ hammereditor_open(x->x_filehandle, buf);
+ while (nevents--)
+ {
+ seq_eventstring(x, buf, ep);
+ strcat(buf, "\n");
+ hammereditor_append(x->x_filehandle, buf);
+ ep++;
+ }
+}
+
static void seq_free(t_seq *x)
{
if (x->x_clock) clock_free(x->x_clock);
if (x->x_slaveclock) clock_free(x->x_slaveclock);
- hammerfile_free(x->x_filehandle);
+ if (x->x_filehandle) hammerfile_free(x->x_filehandle);
if (x->x_sequence != x->x_seqini)
- freebytes(x->x_sequence, x->x_size * sizeof(*x->x_sequence));
+ freebytes(x->x_sequence, x->x_seqsize * sizeof(*x->x_sequence));
+ if (x->x_tempomap != x->x_tempomapini)
+ freebytes(x->x_tempomap, x->x_tempomapsize * sizeof(*x->x_tempomap));
}
static void *seq_new(t_symbol *s)
@@ -938,13 +988,16 @@ static void *seq_new(t_symbol *s)
x->x_canvas = canvas_getcurrent();
x->x_filehandle = hammerfile_new((t_pd *)x, 0,
seq_readhook, seq_writehook, 0);
- x->x_tempo = 1.;
- x->x_newtempo = 1.;
+ x->x_timescale = 1.;
+ x->x_newtimescale = 1.;
x->x_prevtime = 0.;
x->x_slaveprevtime = 0.;
- x->x_size = SEQ_INISIZE;
+ x->x_seqsize = SEQ_INISEQSIZE;
x->x_nevents = 0;
x->x_sequence = x->x_seqini;
+ x->x_tempomapsize = SEQ_INITEMPOMAPSIZE;
+ x->x_ntempi = 0;
+ x->x_tempomap = x->x_tempomapini;
outlet_new((t_object *)x, &s_anything);
x->x_bangout = outlet_new((t_object *)x, &s_bang);
if (s && s != &s_)
@@ -991,5 +1044,6 @@ void seq_setup(void)
gensym("write"), A_DEFSYM, 0);
class_addmethod(seq_class, (t_method)seq_print,
gensym("print"), 0);
+ forky_setpropertiesfn(seq_class, seq_properties);
hammerfile_setup(seq_class, 0);
}
diff --git a/cyclone/hammer/switch.c b/cyclone/hammer/switch.c
index d69660d..03c9f7f 100644
--- a/cyclone/hammer/switch.c
+++ b/cyclone/hammer/switch.c
@@ -103,7 +103,10 @@ static void *switch_new(t_floatarg f1, t_floatarg f2)
if (nproxies < SWITCH_MININLETS)
nproxies = SWITCH_DEFINLETS;
if (nproxies > SWITCH_C74MAXINLETS)
+ {
+ shared_usecompatibility();
loud_incompatible_max(switch_class, SWITCH_C74MAXINLETS, "inlets");
+ }
if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies))))
return (0);
for (ninlets = 0; ninlets < nproxies; ninlets++)
diff --git a/cyclone/hammer/urn.c b/cyclone/hammer/urn.c
index d6983a2..f496616 100644
--- a/cyclone/hammer/urn.c
+++ b/cyclone/hammer/urn.c
@@ -122,6 +122,7 @@ static void *urn_new(t_floatarg f1, t_floatarg f2)
x->x_urn = x->x_urnini;
urn_resize(x, f1, 1);
urn_seed(x, f2); /* CHECKME */
+ shared_usecompatibility();
inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1"));
outlet_new((t_object *)x, &s_float);
x->x_bangout = outlet_new((t_object *)x, &s_bang);