diff options
Diffstat (limited to 'cyclone')
34 files changed, 776 insertions, 541 deletions
diff --git a/cyclone/Makefile.objects b/cyclone/Makefile.objects index db4f7f3..5199008 100644 --- a/cyclone/Makefile.objects +++ b/cyclone/Makefile.objects @@ -12,12 +12,13 @@ HTREE_OBJECTS = hammer/tree.o common/loud.o HTREEFILEVEFL_OBJECTS = hammer/tree.o hammer/file.o \ common/vefl.o common/loud.o unstable/forky.o unstable/fragile.o HGUI_OBJECTS = hammer/gui.o common/loud.o -HSEQ_OBJECTS = common/sq.o common/bifi.o common/mifi.o \ - hammer/file.o common/grow.o common/loud.o unstable/forky.o +HSEQ_OBJECTS = common/mifi.o hammer/file.o \ + common/grow.o common/loud.o unstable/forky.o SSIC_OBJECTS = sickle/sic.o common/loud.o SFORKY_OBJECTS = sickle/sic.o common/loud.o unstable/forky.o SFRAGILE_OBJECTS = sickle/sic.o common/loud.o unstable/fragile.o SGROW_OBJECTS = common/grow.o sickle/sic.o common/loud.o +SGROWCLC_OBJECTS = common/grow.o common/clc.o sickle/sic.o common/loud.o SGROWFORKY_OBJECTS = common/grow.o sickle/sic.o common/loud.o unstable/forky.o SVEFL_OBJECTS = common/vefl.o sickle/sic.o common/loud.o unstable/fragile.o SARSIC_OBJECTS = sickle/sic.o sickle/arsic.o common/vefl.o \ diff --git a/cyclone/Makefile.sources b/cyclone/Makefile.sources index e9aacd5..0c338fe 100644 --- a/cyclone/Makefile.sources +++ b/cyclone/Makefile.sources @@ -11,7 +11,6 @@ hammer/asin.c \ hammer/Bucket.c \ hammer/cartopol.c \ hammer/cosh.c \ -hammer/counter.c \ hammer/flush.c \ hammer/forward.c \ hammer/fromsymbol.c \ @@ -40,6 +39,7 @@ HLOUD_SOURCES = \ hammer/anal.c \ hammer/bangbang.c \ hammer/Borax.c \ +hammer/counter.c \ hammer/cycle.c \ hammer/decide.c \ hammer/Decode.c \ @@ -182,11 +182,14 @@ sickle/poltocar.c SGROW_TILDE = $(TILDE) SGROW_SOURCES = \ sickle/click.c \ -sickle/curve.c \ sickle/frameaccum.c \ sickle/framedelta.c \ sickle/Line.c +SGROWCLC_TILDE = $(TILDE) +SGROWCLC_SOURCES = \ +sickle/curve.c + SGROWFORKY_TILDE = $(TILDE) SGROWFORKY_SOURCES = \ sickle/Scope.c diff --git a/cyclone/build_counter b/cyclone/build_counter index fa90455..acc65a6 100644 --- a/cyclone/build_counter +++ b/cyclone/build_counter @@ -1,7 +1,7 @@ #define CYCLONE_VERSION "0.1" #define CYCLONE_RELEASE "alpha" -#define CYCLONE_BUILD 49 +#define CYCLONE_BUILD 50 #if 0 -CYCLONE_SNAPSHOT = 0.1-alpha49 +CYCLONE_SNAPSHOT = 0.1-alpha50 #endif diff --git a/cyclone/cyclone-shared.include b/cyclone/cyclone-shared.include index 6604d19..26662ac 100644 --- a/cyclone/cyclone-shared.include +++ b/cyclone/cyclone-shared.include @@ -21,10 +21,8 @@ shared/common/rand.c shared/common/rand.h shared/common/vefl.c shared/common/vefl.h -shared/common/sq.c -shared/common/sq.h -shared/common/bifi.c -shared/common/bifi.h +shared/common/clc.c +shared/common/clc.h shared/common/mifi.c shared/common/mifi.h shared/hammer/file.c 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); diff --git a/cyclone/shadow/Makefile b/cyclone/shadow/Makefile index b700e5e..dc39772 100644 --- a/cyclone/shadow/Makefile +++ b/cyclone/shadow/Makefile @@ -2,6 +2,6 @@ ROOT_DIR = ../.. redefault: default $(ROOT_DIR)/bin/cyclist include $(ROOT_DIR)/Makefile.common -$(ROOT_DIR)/bin/cyclist: $(SHARED_DIR)/common/binport.c - $(CC) -DBINPORT_STANDALONE -o $@ $< - +$(ROOT_DIR)/bin/cyclist: $(SHARED_DIR)/common/binport.c \ + $(SHARED_DIR)/common/lex.c $(SHARED_DIR)/unstable/standalone.c + $(CC) $(CFLAGS) -DMIXED_STANDALONE -o $@ $^ diff --git a/cyclone/shadow/Makefile.objects b/cyclone/shadow/Makefile.objects index f1449e0..dd8fb57 100644 --- a/cyclone/shadow/Makefile.objects +++ b/cyclone/shadow/Makefile.objects @@ -1,6 +1,7 @@ SHARED_OBJECTS = \ common/loud.o \ common/grow.o \ +common/lex.o \ common/binport.o \ common/port.o \ hammer/file.o \ diff --git a/cyclone/shadow/Makefile.sources b/cyclone/shadow/Makefile.sources index 061f37b..be9a840 100644 --- a/cyclone/shadow/Makefile.sources +++ b/cyclone/shadow/Makefile.sources @@ -1,5 +1,6 @@ CX_SOURCES = \ cyclone.c \ +maxmode.c \ dummies.c OTHER_SOURCES = \ diff --git a/cyclone/shadow/cyclone.c b/cyclone/shadow/cyclone.c index 20d1396..a702074 100644 --- a/cyclone/shadow/cyclone.c +++ b/cyclone/shadow/cyclone.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003 krzYszcz and others. +/* Copyright (c) 2003-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. */ @@ -122,6 +122,11 @@ void cyclone_setup(void) loud_errand(0, "without having cyclone library preloaded"); return; } + if (zgetfn(&pd_objectmaker, gensym("cyclone"))) + { + loud_error(0, "cyclone is already loaded"); + return; + } post("this is cyclone %s, %s %s build", CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE); cyclone_class = class_new(gensym("cyclone"), diff --git a/cyclone/sickle/Makefile.objects b/cyclone/sickle/Makefile.objects index f9d4ae7..4528d83 100644 --- a/cyclone/sickle/Makefile.objects +++ b/cyclone/sickle/Makefile.objects @@ -5,6 +5,8 @@ unstable/fringe.o \ common/loud.o \ common/grow.o \ common/vefl.o \ +common/clc.o \ +common/lex.o \ common/binport.o \ common/port.o \ hammer/file.o \ diff --git a/cyclone/sickle/buffir.c b/cyclone/sickle/buffir.c index 0551501..ee42af9 100644 --- a/cyclone/sickle/buffir.c +++ b/cyclone/sickle/buffir.c @@ -38,11 +38,14 @@ static void buffir_setrange(t_buffir *x, t_floatarg f1, t_floatarg f2) { int newsize, pos = x->x_lohead - x->x_histlo; int oldbytes = x->x_histsize * sizeof(*x->x_histlo); - static int warned = 0; - if (!warned) + if (shared_getmaxcompatibility()) { - loud_incompatible(buffir_class, "stretching history buffer"); - warned = 1; + static int warned = 0; + if (!warned) + { + loud_incompatible(buffir_class, "stretching history buffer"); + warned = 1; + } } newsize = x->x_histsize * 2; while (newsize < siz) newsize *= 2; @@ -194,6 +197,7 @@ static void *buffir_new(t_symbol *s, t_floatarg f1, t_floatarg f2) x->x_histlo = x->x_histini; buffir_clear(x); buffir_setrange(x, f1, f2); + shared_usecompatibility(); } return (x); } diff --git a/cyclone/sickle/curve.c b/cyclone/sickle/curve.c index e6bade1..2bad587 100644 --- a/cyclone/sickle/curve.c +++ b/cyclone/sickle/curve.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2003 krzYszcz and others. +/* Copyright (c) 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,54 +7,14 @@ #include "shared.h" #include "common/grow.h" #include "common/loud.h" +#include "common/clc.h" #include "sickle/sic.h" //#define CURVE_DEBUG -/* CHECKED apparently c74's formula was not very carefully tuned. It has 5% - deviation from the straight line for ccinput=0 (ccinput is user's curve - control parameter, <0..1>) at half-domain, range=1. It generates nans for - ccinput > .995. - - The formula below generates curves with < .000004% deviation and no nans. - - Problem: find a function f : ccinput -> cc, such that the curves will bend - in a semi-linear way over the ccinput's range of 0..1. The curve function - is then g(x, p) = (exp(f(p) * x) - 1) / (exp(f(p)) - 1), where x is curve's - domain, and p is ccinput. If, for example, the points g(0.5, p) are to make - a semi-linear pattern, then the solution is a function f that minimizes - the integral of the error function e(p) = sqr(((1-p)/2)-g(.5, p)) over 0..1. - Until someone does this analytically, we are left with a lame formula, which - has been tweaked and tested in gnuplot: f(p) = h(p) / (1 - h(p)), where - h(p) = (((p + 1e-20) * 1.2) ** .41) * .91. The file curve.gp, in the - sickle's source directory, may come handy, in case there is anyone, who - fancy tweaking it even further. - - To implement this, start from these equations: - bb * mm ^ npoints = bb + 1 - (bb ^ 2) * (mm ^ npoints) = ((exp(ff/2) - 1) / (exp(ff) - 1)) ^ 2 - - and calculate: - hh = pow(((ccinput + c1) * c2), c3) * c4 - ff = hh / (1 - hh) - eff = exp(ff) - 1 - gh = (exp(ff * .5) - 1) / eff - bb = gh * (gh / (1 - (gh + gh))) - mm = ((exp(ff * (1/npoints)) - 1) / (eff * bb)) + 1 - - The loop is: - for (vv = bb, i = 0; i < n; vv *= mm, i++) - result = (vv - bb) * (y1 - y0) + y0 - where y0, y1 are start and destination values -*/ - -#define CURVE_C1 1e-20 -#define CURVE_C2 1.2 -#define CURVE_C3 0.41 -#define CURVE_C4 0.91 - -#define CURVE_MINCCINPUT -1. -#define CURVE_MAXCCINPUT 1. +/* CHECKED apparently c74's formula has not been carefully tuned (yet?). + It has 5% deviation from the straight line for ccinput = 0 at half-domain, + range 1, and generates nans for ccinput > .995 (cf comment in clc.h). */ #define CURVE_INISIZE 64 /* LATER rethink */ #define CURVE_MAXSIZE 64 @@ -63,7 +23,7 @@ typedef struct _curveseg { float s_target; float s_delta; - int s_npoints; + int s_nhops; float s_ccinput; double s_bb; double s_mm; @@ -95,7 +55,7 @@ typedef struct _curve #ifdef CURVE_DEBUG int dbg_nretargets; int dbg_exitpoint; - int dbg_npoints; + int dbg_nhops; #endif } t_curve; @@ -104,42 +64,10 @@ static double curve_coef; static void curve_cc(t_curve *x, t_curveseg *segp, float f) { - int npoints = segp->s_delta * x->x_ksr + 0.5; /* LATER rethink */ + int nhops = segp->s_delta * x->x_ksr + 0.5; /* LATER rethink */ segp->s_ccinput = f; - if (npoints > 0) - { - double hh, ff, eff, gh; - segp->s_npoints = npoints; - if (f < 0) - { - if (f < CURVE_MINCCINPUT) - f = CURVE_MINCCINPUT; - hh = pow(((CURVE_C1 - f) * CURVE_C2), CURVE_C3) * CURVE_C4; - ff = hh / (1. - hh); - eff = exp(ff) - 1.; - gh = (exp(ff * .5) - 1.) / eff; - segp->s_bb = gh * (gh / (1. - (gh + gh))); - segp->s_mm = 1. / (((exp(ff * (1. / (double)npoints)) - 1.) / - (eff * segp->s_bb)) + 1.); - } - else - { - if (f > CURVE_MAXCCINPUT) - f = CURVE_MAXCCINPUT; - hh = pow(((f + CURVE_C1) * CURVE_C2), CURVE_C3) * CURVE_C4; - ff = hh / (1. - hh); - eff = exp(ff) - 1.; - gh = (exp(ff * .5) - 1.) / eff; - segp->s_bb = gh * (gh / (1. - (gh + gh))); - segp->s_mm = ((exp(ff * (1. / (double)npoints)) - 1.) / - (eff * segp->s_bb)) + 1.; - } - } - else - { - segp->s_npoints = 0; - segp->s_bb = segp->s_mm = 1.; - } + segp->s_nhops = (nhops > 0 ? nhops : 0); + clccurve_coefs(segp->s_nhops, (double)f, &segp->s_bb, &segp->s_mm); #ifdef CURVE_DEBUG post("%g %g %g %g", segp->s_target, segp->s_delta, segp->s_bb, segp->s_mm); @@ -152,9 +80,9 @@ static void curve_tick(t_curve *x) #ifdef CURVE_DEBUG post("exit point %d, after %d retarget calls", x->dbg_exitpoint, x->dbg_nretargets); - post("at value %g, after last %d npoints, with bb %g, mm %g", - x->x_value, x->dbg_npoints, x->x_bb, x->x_mm); - x->dbg_nretargets = x->dbg_exitpoint = x->dbg_npoints = 0; + post("at value %g, after last %d nhops, with bb %g, mm %g", + x->x_value, x->dbg_nhops, x->x_bb, x->x_mm); + x->dbg_nretargets = x->dbg_exitpoint = x->dbg_nhops = 0; #endif } @@ -177,42 +105,32 @@ retarget: { float target = x->x_curseg->s_target; float delta = x->x_curseg->s_delta; - int npoints = x->x_curseg->s_npoints; + int nhops = x->x_curseg->s_nhops; + bb = x->x_curseg->s_bb; mm = x->x_curseg->s_mm; if (x->x_curseg->s_ccinput < 0) - { - bb = x->x_curseg->s_bb + 1.; dy = x->x_value - target; - } else - { - bb = x->x_curseg->s_bb; dy = target - x->x_value; - } #ifdef CURVE_DEBUG x->dbg_nretargets++; #endif x->x_nsegs--; x->x_curseg++; - while (npoints <= 0) + while (nhops <= 0) { curval = x->x_value = target; if (x->x_nsegs) { target = x->x_curseg->s_target; delta = x->x_curseg->s_delta; - npoints = x->x_curseg->s_npoints; + nhops = x->x_curseg->s_nhops; + bb = x->x_curseg->s_bb; mm = x->x_curseg->s_mm; if (x->x_curseg->s_ccinput < 0) - { - bb = x->x_curseg->s_bb + 1.; dy = x->x_value - target; - } else - { - bb = x->x_curseg->s_bb; dy = target - x->x_value; - } x->x_nsegs--; x->x_curseg++; } @@ -228,7 +146,7 @@ retarget: return (w + 4); } } - nxfer = x->x_nleft = npoints; + nxfer = x->x_nleft = nhops; x->x_vv = vv = bb; x->x_bb = bb; x->x_mm = mm; @@ -237,7 +155,7 @@ retarget: x->x_target = target; x->x_retarget = 0; #ifdef CURVE_DEBUG - x->dbg_npoints = npoints; + x->dbg_nhops = nhops; #endif } if (nxfer >= nblock) @@ -422,13 +340,7 @@ static void curve_free(t_curve *x) static void *curve_new(t_floatarg f1, t_floatarg f2) { - static int initialized = 0; t_curve *x = (t_curve *)pd_new(curve_class); - if (!initialized) - { - curve_coef = CURVE_C2 / exp(CURVE_C3); - initialized = 1; - } x->x_value = x->x_target = f1; x->x_ccinput = f2; x->x_deltaset = 0; diff --git a/cyclone/sickle/sickle.c b/cyclone/sickle/sickle.c index 8df7974..807c2ad 100644 --- a/cyclone/sickle/sickle.c +++ b/cyclone/sickle/sickle.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 sickle_setup(void) loud_errand(0, "without having sickle library preloaded"); return; } + if (zgetfn(&pd_objectmaker, gensym("sickle"))) + { + loud_error(0, "sickle is already loaded"); + return; + } if (!zgetfn(&pd_objectmaker, gensym("cyclone"))) post("this is sickle %s, %s %s build", CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE); |