diff options
author | N.N. <krzyszcz@users.sourceforge.net> | 2004-12-08 15:40:14 +0000 |
---|---|---|
committer | N.N. <krzyszcz@users.sourceforge.net> | 2004-12-08 15:40:14 +0000 |
commit | d5a39ff6469f8762218c00a34f4b0a120a56332b (patch) | |
tree | 8b5d6f1008f1ce09daf3e2a63b71f9c142911e80 /cyclone/hammer | |
parent | b88a64023a08ed9a0e520058ef8be200515d9639 (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.c | 121 | ||||
-rw-r--r-- | cyclone/hammer/Decode.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/Makefile.objects | 3 | ||||
-rw-r--r-- | cyclone/hammer/Table.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/bangbang.c | 3 | ||||
-rw-r--r-- | cyclone/hammer/coll.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/comment.c | 23 | ||||
-rw-r--r-- | cyclone/hammer/counter.c | 17 | ||||
-rw-r--r-- | cyclone/hammer/cycle.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/funbuff.c | 83 | ||||
-rw-r--r-- | cyclone/hammer/gate.c | 3 | ||||
-rw-r--r-- | cyclone/hammer/hammer.c | 7 | ||||
-rw-r--r-- | cyclone/hammer/maximum.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/minimum.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/mtr.c | 13 | ||||
-rw-r--r-- | cyclone/hammer/offer.c | 17 | ||||
-rw-r--r-- | cyclone/hammer/past.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/prepend.c | 255 | ||||
-rw-r--r-- | cyclone/hammer/prob.c | 1 | ||||
-rw-r--r-- | cyclone/hammer/seq.c | 574 | ||||
-rw-r--r-- | cyclone/hammer/switch.c | 3 | ||||
-rw-r--r-- | cyclone/hammer/urn.c | 1 |
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); |