aboutsummaryrefslogtreecommitdiff
path: root/cyclone/hammer
diff options
context:
space:
mode:
authorN.N. <krzyszcz@users.sourceforge.net>2003-06-02 14:12:00 +0000
committerN.N. <krzyszcz@users.sourceforge.net>2003-06-02 14:12:00 +0000
commitb6ae9da8c7dfba6587038cac42684949bf2faaf0 (patch)
tree519a249ce1a3155daea44aae408401b63b25b729 /cyclone/hammer
parenta511e141ae18c710ec26f7dbe1b562d5835933b8 (diff)
adding pong and mtr
svn path=/trunk/externals/miXed/; revision=673
Diffstat (limited to 'cyclone/hammer')
-rw-r--r--cyclone/hammer/Makefile.sources1
-rw-r--r--cyclone/hammer/allhammers.c54
-rw-r--r--cyclone/hammer/mtr.c712
3 files changed, 741 insertions, 26 deletions
diff --git a/cyclone/hammer/Makefile.sources b/cyclone/hammer/Makefile.sources
index 5df97f5..74bda2c 100644
--- a/cyclone/hammer/Makefile.sources
+++ b/cyclone/hammer/Makefile.sources
@@ -44,6 +44,7 @@ midiparse.c \
minimum.c \
mousefilter.c \
MouseState.c \
+mtr.c \
next.c \
offer.c \
onebang.c \
diff --git a/cyclone/hammer/allhammers.c b/cyclone/hammer/allhammers.c
index e6d8235..7a28cc8 100644
--- a/cyclone/hammer/allhammers.c
+++ b/cyclone/hammer/allhammers.c
@@ -4,27 +4,33 @@
* For information on usage and redistribution, and for a DISCLAIMER OF ALL
* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+void Append_setup(void);
+void Borax_setup(void);
+void Bucket_setup(void);
+void Clip_setup(void);
+void Decode_setup(void);
+void Histo_setup(void);
+void MouseState_setup(void);
+void Peak_setup(void);
+void TogEdge_setup(void);
+void Trough_setup(void);
+void Uzi_setup(void);
void accum_setup(void);
void acos_setup(void);
void active_setup(void);
void anal_setup(void);
-void Append_setup(void);
void asin_setup(void);
void bangbang_setup(void);
void bondo_setup(void);
-void Borax_setup(void);
-void Bucket_setup(void);
void buddy_setup(void);
void capture_setup(void);
void cartopol_setup(void);
-void Clip_setup(void);
void coll_setup(void);
void comment_setup(void);
void cosh_setup(void);
void counter_setup(void);
void cycle_setup(void);
void decide_setup(void);
-void Decode_setup(void);
void drunk_setup(void);
void flush_setup(void);
void forward_setup(void);
@@ -33,7 +39,6 @@ void funbuff_setup(void);
void funnel_setup(void);
void gate_setup(void);
void grab_setup(void);
-void Histo_setup(void);
void iter_setup(void);
void match_setup(void);
void maximum_setup(void);
@@ -43,12 +48,11 @@ void midiformat_setup(void);
void midiparse_setup(void);
void minimum_setup(void);
void mousefilter_setup(void);
-void MouseState_setup(void);
+void mtr_setup(void);
void next_setup(void);
void offer_setup(void);
void onebang_setup(void);
void past_setup(void);
-void Peak_setup(void);
void poltocar_setup(void);
void prepend_setup(void);
void prob_setup(void);
@@ -66,43 +70,46 @@ void switch_setup(void);
void tanh_setup(void);
void testmess_setup(void);
void thresh_setup(void);
-void TogEdge_setup(void);
void tosymbol_setup(void);
-void Trough_setup(void);
void universal_setup(void);
void urn_setup(void);
-void Uzi_setup(void);
-void xbendin2_setup(void);
void xbendin_setup(void);
-void xbendout2_setup(void);
+void xbendin2_setup(void);
void xbendout_setup(void);
+void xbendout2_setup(void);
void xnotein_setup(void);
void xnoteout_setup(void);
void zl_setup(void);
void allhammers_setup(void)
{
+ Append_setup();
+ Borax_setup();
+ Bucket_setup();
+ Clip_setup();
+ Decode_setup();
+ Histo_setup();
+ MouseState_setup();
+ Peak_setup();
+ TogEdge_setup();
+ Trough_setup();
+ Uzi_setup();
accum_setup();
acos_setup();
active_setup();
anal_setup();
- Append_setup();
asin_setup();
bangbang_setup();
bondo_setup();
- Borax_setup();
- Bucket_setup();
buddy_setup();
capture_setup();
cartopol_setup();
- Clip_setup();
coll_setup();
comment_setup();
cosh_setup();
counter_setup();
cycle_setup();
decide_setup();
- Decode_setup();
drunk_setup();
flush_setup();
forward_setup();
@@ -111,7 +118,6 @@ void allhammers_setup(void)
funnel_setup();
gate_setup();
grab_setup();
- Histo_setup();
iter_setup();
match_setup();
maximum_setup();
@@ -121,12 +127,11 @@ void allhammers_setup(void)
midiparse_setup();
minimum_setup();
mousefilter_setup();
- MouseState_setup();
+ mtr_setup();
next_setup();
offer_setup();
onebang_setup();
past_setup();
- Peak_setup();
poltocar_setup();
prepend_setup();
prob_setup();
@@ -144,16 +149,13 @@ void allhammers_setup(void)
tanh_setup();
testmess_setup();
thresh_setup();
- TogEdge_setup();
tosymbol_setup();
- Trough_setup();
universal_setup();
urn_setup();
- Uzi_setup();
- xbendin2_setup();
xbendin_setup();
- xbendout2_setup();
+ xbendin2_setup();
xbendout_setup();
+ xbendout2_setup();
xnotein_setup();
xnoteout_setup();
zl_setup();
diff --git a/cyclone/hammer/mtr.c b/cyclone/hammer/mtr.c
new file mode 100644
index 0000000..c1fe022
--- /dev/null
+++ b/cyclone/hammer/mtr.c
@@ -0,0 +1,712 @@
+/* Copyright (c) 2002-2003 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include <stdio.h>
+#include <string.h>
+#include "m_pd.h"
+#include "shared.h"
+#include "common/loud.h"
+#include "hammer/file.h"
+
+//#define MTR_DEBUG
+
+enum { MTR_STEPMODE, MTR_RECMODE, MTR_PLAYMODE };
+
+typedef struct _mtrack
+{
+ t_pd tr_pd;
+ struct _mtr *tr_owner;
+ int tr_id;
+ int tr_listed;
+ int tr_mode;
+ int tr_muted;
+ int tr_restarted;
+ t_atom *tr_atdelta;
+ int tr_ixnext;
+ t_binbuf *tr_binbuf;
+ float tr_tempo;
+ double tr_clockdelay;
+ double tr_prevtime;
+ t_clock *tr_clock;
+ t_outlet *tr_trackout;
+ t_outlet *tr_mainout;
+ t_hammerfile *tr_filehandle;
+} t_mtrack;
+
+typedef void (*t_mtrackfn)(t_mtrack *tp);
+
+typedef struct _mtr
+{
+ t_object x_ob;
+ t_glist *x_glist;
+ int x_ntracks;
+ t_mtrack **x_tracks;
+ t_hammerfile *x_filehandle;
+} t_mtr;
+
+static t_class *mtrack_class;
+static t_class *mtr_class;
+
+static void mtrack_donext(t_mtrack *tp)
+{
+ if (tp->tr_ixnext < 0)
+ goto endoftrack;
+ while (1)
+ {
+ int natoms = binbuf_getnatom(tp->tr_binbuf);
+ int ixmess = tp->tr_ixnext;
+ t_atom *atmess;
+ if (ixmess >= natoms)
+ goto endoftrack;
+ atmess = binbuf_getvec(tp->tr_binbuf) + ixmess;
+
+ while (atmess->a_type == A_SEMI)
+ {
+ if (++ixmess >= natoms)
+ goto endoftrack;
+ atmess++;
+ }
+ if (!tp->tr_atdelta && atmess->a_type == A_FLOAT)
+ { /* delta atom */
+ float delta = atmess->a_w.w_float;
+ if (delta < 0.)
+ delta = 0.;
+ tp->tr_atdelta = atmess;
+ tp->tr_ixnext = ixmess + 1;
+ if (tp->tr_mode == MTR_PLAYMODE)
+ {
+ clock_delay(tp->tr_clock,
+ tp->tr_clockdelay = delta * tp->tr_tempo);
+ tp->tr_prevtime = clock_getlogicaltime();
+ }
+ else
+ { /* CHECKME first step */
+ t_atom at[2];
+ SETFLOAT(&at[0], tp->tr_id);
+ SETFLOAT(&at[1], delta);
+ outlet_list(tp->tr_mainout, 0, 2, at);
+ }
+ return;
+ }
+ else
+ { /* message beginning */
+ int wasrestarted = tp->tr_restarted; /* LATER rethink */
+ int ixnext = ixmess + 1;
+ t_atom *atnext = atmess + 1;
+ while (ixnext < natoms && atnext->a_type != A_SEMI)
+ ixnext++, atnext++;
+ tp->tr_restarted = 0;
+ if (!tp->tr_muted)
+ {
+ int ac = ixnext - ixmess;
+ if (ac > 1)
+ {
+ if (atmess->a_type == A_FLOAT)
+ outlet_list(tp->tr_trackout, &s_list, ac, atmess);
+ else if (atmess->a_type == A_SYMBOL)
+ outlet_anything(tp->tr_trackout,
+ atmess->a_w.w_symbol, ac-1, atmess+1);
+ }
+ else if (atmess->a_type == A_FLOAT)
+ outlet_float(tp->tr_trackout, atmess->a_w.w_float);
+ else if (atmess->a_type == A_SYMBOL)
+ outlet_symbol(tp->tr_trackout, atmess->a_w.w_symbol);
+ }
+ tp->tr_atdelta = 0;
+ tp->tr_ixnext = ixnext;
+ if (tp->tr_restarted)
+ return;
+ tp->tr_restarted = wasrestarted;
+ }
+ }
+endoftrack:
+ tp->tr_atdelta = 0;
+ tp->tr_ixnext = -1;
+ tp->tr_prevtime = 0;
+ tp->tr_mode = MTR_STEPMODE;
+}
+
+static void mtrack_tick(t_mtrack *tp)
+{
+ if (tp->tr_mode == MTR_PLAYMODE)
+ {
+ tp->tr_prevtime = 0;
+ mtrack_donext(tp);
+ }
+}
+
+static void mtrack_setmode(t_mtrack *tp, int newmode)
+{
+ if (tp->tr_mode == MTR_PLAYMODE)
+ {
+ clock_unset(tp->tr_clock);
+ tp->tr_ixnext = -1;
+ }
+ switch (tp->tr_mode = newmode)
+ {
+ case MTR_STEPMODE:
+ break;
+ case MTR_RECMODE:
+ binbuf_clear(tp->tr_binbuf);
+ tp->tr_prevtime = clock_getlogicaltime();
+ break;
+ case MTR_PLAYMODE:
+ tp->tr_atdelta = 0;
+ tp->tr_ixnext = 0;
+ tp->tr_prevtime = 0;
+ mtrack_donext(tp);
+ break;
+ default:
+ bug("mtrack_setmode");
+ }
+}
+
+static void mtrack_doadd(t_mtrack *tp, int ac, t_atom *av)
+{
+ if (tp->tr_prevtime > 0)
+ {
+ t_binbuf *bb = tp->tr_binbuf;
+ t_atom at;
+ float elapsed = clock_gettimesince(tp->tr_prevtime);
+ SETFLOAT(&at, elapsed);
+ binbuf_add(bb, 1, &at);
+ binbuf_add(bb, ac, av);
+ SETSEMI(&at);
+ binbuf_add(bb, 1, &at);
+ tp->tr_prevtime = clock_getlogicaltime();
+ }
+}
+
+static void mtrack_float(t_mtrack *tp, t_float f)
+{
+ if (tp->tr_mode == MTR_RECMODE)
+ {
+ t_atom at;
+ SETFLOAT(&at, f);
+ mtrack_doadd(tp, 1, &at);
+ }
+}
+
+static void mtrack_symbol(t_mtrack *tp, t_symbol *s)
+{
+ if (tp->tr_mode == MTR_RECMODE)
+ {
+ t_atom at;
+ SETSYMBOL(&at, s);
+ mtrack_doadd(tp, 1, &at);
+ }
+}
+
+static void mtrack_list(t_mtrack *tp, t_symbol *s, int ac, t_atom *av)
+{
+ if (tp->tr_mode == MTR_RECMODE)
+ mtrack_doadd(tp, ac, av);
+}
+
+static void mtrack_record(t_mtrack *tp)
+{
+ mtrack_setmode(tp, MTR_RECMODE);
+}
+
+static void mtrack_play(t_mtrack *tp)
+{
+ mtrack_setmode(tp, MTR_PLAYMODE);
+}
+
+static void mtrack_stop(t_mtrack *tp)
+{
+ mtrack_setmode(tp, MTR_STEPMODE);
+}
+
+static void mtrack_next(t_mtrack *tp)
+{
+ if (tp->tr_mode == MTR_STEPMODE)
+ mtrack_donext(tp);
+}
+
+static void mtrack_rewind(t_mtrack *tp)
+{
+ if (tp->tr_mode == MTR_STEPMODE)
+ {
+ tp->tr_atdelta = 0;
+ tp->tr_ixnext = 0;
+ }
+}
+
+/* CHECKME step mode */
+static void mtrack_mute(t_mtrack *tp)
+{
+ tp->tr_muted = 1;
+}
+
+/* CHECKME step mode */
+static void mtrack_unmute(t_mtrack *tp)
+{
+ tp->tr_muted = 0;
+}
+
+static void mtrack_clear(t_mtrack *tp)
+{
+ binbuf_clear(tp->tr_binbuf);
+}
+
+static t_atom *mtrack_getdelay(t_mtrack *tp)
+{
+ int natoms = binbuf_getnatom(tp->tr_binbuf);
+ if (natoms)
+ {
+ t_atom *ap = binbuf_getvec(tp->tr_binbuf);
+ while (natoms--)
+ {
+ if (ap->a_type == A_FLOAT)
+ return (ap);
+ ap++;
+ }
+ bug("mtrack_getdelay");
+ }
+ return (0);
+}
+
+static void mtrack_delay(t_mtrack *tp, t_floatarg f)
+{
+ t_atom *ap = mtrack_getdelay(tp);
+ if (ap)
+ ap->a_w.w_float = f;
+}
+
+/* CHECKME */
+static void mtrack_first(t_mtrack *tp, t_floatarg f)
+{
+ mtrack_delay(tp, f);
+}
+
+static void mtr_doread(t_mtr *x, t_symbol *fn, int trackid);
+static void mtr_dowrite(t_mtr *x, t_symbol *fn, int trackid);
+
+static void mtrack_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ t_mtrack *tp = (t_mtrack *)z;
+ mtr_doread(tp->tr_owner, fn, tp->tr_id);
+}
+
+static void mtrack_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ t_mtrack *tp = (t_mtrack *)z;
+ mtr_dowrite(tp->tr_owner, fn, tp->tr_id);
+}
+
+static void mtrack_read(t_mtrack *tp, t_symbol *s)
+{
+ if (s && s != &s_)
+ mtr_doread(tp->tr_owner, s, tp->tr_id);
+ else /* CHECKME default */
+ hammerpanel_open(tp->tr_filehandle);
+}
+
+static void mtrack_write(t_mtrack *tp, t_symbol *s)
+{
+ if (s && s != &s_)
+ mtr_dowrite(tp->tr_owner, s, tp->tr_id);
+ else /* CHECKME default */
+ hammerpanel_save(tp->tr_filehandle,
+ canvas_getdir(tp->tr_owner->x_glist), 0);
+}
+
+static void mtrack_tempo(t_mtrack *tp, t_floatarg f)
+{
+ float newtempo;
+ static int warned = 0;
+ if (!warned)
+ {
+ loud_incompatible(mtr_class, "no 'tempo' control in Max");
+ warned = 1;
+ }
+ if (f < 1e-20)
+ f = 1e-20;
+ else if (f > 1e20)
+ f = 1e20;
+ newtempo = 1. / f;
+ if (tp->tr_prevtime > 0)
+ {
+ tp->tr_clockdelay -= clock_gettimesince(tp->tr_prevtime);
+ tp->tr_clockdelay *= newtempo / tp->tr_tempo;
+ if (tp->tr_clockdelay < 0.)
+ tp->tr_clockdelay = 0.;
+ clock_delay(tp->tr_clock, tp->tr_clockdelay);
+ tp->tr_prevtime = clock_getlogicaltime();
+ }
+ tp->tr_tempo = newtempo;
+}
+
+/* CHECKME out-of-bounds and non-floats, which track goes first */
+static void mtr_callem(t_mtr *x, t_mtrackfn fn, t_symbol *s, int ac, t_atom *av)
+{
+ int ntracks = x->x_ntracks;
+ t_mtrack **tpp = x->x_tracks;
+ if (ac)
+ {
+ while (ntracks--) (*tpp++)->tr_listed = 0;
+ while (ac--)
+ {
+ if (av->a_type == A_FLOAT)
+ {
+ int id = (int)av->a_w.w_float;
+ if (id >= 0 && id < x->x_ntracks)
+ x->x_tracks[id]->tr_listed = 1;
+ }
+ av++;
+ }
+ ntracks = x->x_ntracks;
+ tpp = x->x_tracks;
+ while (ntracks--)
+ {
+ if ((*tpp)->tr_listed) fn(*tpp);
+ tpp++;
+ }
+ }
+ else while (ntracks--) fn(*tpp++);
+}
+
+static void mtr_record(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_record, s, ac, av);
+}
+
+static void mtr_play(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_play, s, ac, av);
+}
+
+static void mtr_stop(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_stop, s, ac, av);
+}
+
+static void mtr_next(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_next, s, ac, av);
+}
+
+static void mtr_rewind(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_rewind, s, ac, av);
+}
+
+static void mtr_mute(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_mute, s, ac, av);
+}
+
+static void mtr_unmute(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_unmute, s, ac, av);
+}
+
+static void mtr_clear(t_mtr *x, t_symbol *s, int ac, t_atom *av)
+{
+ mtr_callem(x, mtrack_clear, s, ac, av);
+}
+
+static void mtr_delay(t_mtr *x, t_floatarg f)
+{
+ int ntracks = x->x_ntracks;
+ t_mtrack **tpp = x->x_tracks;
+ while (ntracks--) mtrack_delay(*tpp++, f);
+}
+
+static void mtr_first(t_mtr *x, t_floatarg f)
+{
+ int ntracks = x->x_ntracks;
+ t_mtrack **tpp = x->x_tracks;
+ float delta = SHARED_FLT_MAX;
+ if (f < 0.)
+ f = 0.;
+ while (ntracks--)
+ {
+ t_atom *ap = mtrack_getdelay(*tpp);
+ if (ap)
+ {
+ if (delta > ap->a_w.w_float)
+ delta = ap->a_w.w_float;
+ (*tpp)->tr_listed = 1;
+ }
+ else (*tpp)->tr_listed = 0;
+ tpp++;
+ }
+ ntracks = x->x_ntracks;
+ tpp = x->x_tracks;
+ delta -= f;
+ while (ntracks--)
+ {
+ if ((*tpp)->tr_listed)
+ {
+ t_atom *ap = mtrack_getdelay(*tpp);
+ if (ap)
+ ap->a_w.w_float -= delta;
+ }
+ tpp++;
+ }
+}
+
+static void mtr_doread(t_mtr *x, t_symbol *fn, int trackid)
+{
+ char path[MAXPDSTRING];
+ if (x->x_glist)
+ canvas_makefilename(x->x_glist, fn->s_name, path, MAXPDSTRING);
+ else
+ {
+ strncpy(path, fn->s_name, MAXPDSTRING);
+ path[MAXPDSTRING-1] = 0;
+ }
+ post("mtr: reading %s", fn->s_name); /* CHECKME */
+
+ if (trackid > x->x_ntracks)
+ bug("mtr_doread");
+
+ else
+ {
+ FILE *fp;
+ char namebuf[MAXPDSTRING];
+ sys_bashfilename(fn->s_name, namebuf);
+ if (fp = fopen(namebuf, "r"))
+ {
+ /* FIXME */
+ fclose(fp);
+ }
+ else
+ {
+ /* CHECKME no complaint, open dialog presented */
+ hammerpanel_open(x->x_filehandle); /* LATER rethink */
+ }
+ }
+}
+
+static int mtr_writetrack(t_mtr *x, t_mtrack *tp)
+{
+ /* CHECKME complaint and FIXME */
+ loud_error((t_pd *)x, "error writing text file");
+ return (0);
+}
+
+static void mtr_dowrite(t_mtr *x, t_symbol *fn, int trackid)
+{
+ char path[MAXPDSTRING];
+ if (x->x_glist)
+ canvas_makefilename(x->x_glist, fn->s_name, path, MAXPDSTRING);
+ else
+ {
+ strncpy(path, fn->s_name, MAXPDSTRING);
+ path[MAXPDSTRING-1] = 0;
+ }
+ post("mtr: writing %s", fn->s_name); /* CHECKME */
+
+ if (trackid > x->x_ntracks)
+ bug("mtr_dowrite");
+
+ /* CHECKME empty sequence stored as an empty file */
+ else
+ {
+ FILE *fp;
+ char namebuf[MAXPDSTRING];
+ sys_bashfilename(fn->s_name, namebuf);
+ if (fp = fopen(namebuf, "w"))
+ {
+ int id;
+ t_mtrack **tpp;
+ if (trackid >= 0)
+ mtr_writetrack(x, x->x_tracks[trackid]);
+ else for (id = 0, tpp = x->x_tracks; id < x->x_ntracks; id++, tpp++)
+ if (!mtr_writetrack(x, *tpp))
+ break;
+ fclose(fp);
+ }
+ else
+ {
+ fprintf(stderr, "open: ");
+ sys_unixerror(fn->s_name);
+ }
+ }
+}
+
+static void mtr_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ mtr_doread((t_mtr *)z, fn, -1);
+}
+
+static void mtr_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av)
+{
+ mtr_dowrite((t_mtr *)z, fn, -1);
+}
+
+static void mtr_read(t_mtr *x, t_symbol *s)
+{
+ if (s && s != &s_)
+ mtr_doread(x, s, -1);
+ else /* CHECKME default */
+ hammerpanel_open(x->x_filehandle);
+}
+
+static void mtr_write(t_mtr *x, t_symbol *s)
+{
+ if (s && s != &s_)
+ mtr_dowrite(x, s, -1);
+ else /* CHECKME default */
+ hammerpanel_save(x->x_filehandle, canvas_getdir(x->x_glist), 0);
+}
+
+static void mtr_tempo(t_mtr *x, t_floatarg f)
+{
+ int ntracks = x->x_ntracks;
+ t_mtrack **tpp = x->x_tracks;
+ while (ntracks--) mtrack_tempo(*tpp++, f);
+}
+
+static void mtr_free(t_mtr *x)
+{
+ if (x->x_tracks)
+ {
+ int ntracks = x->x_ntracks;
+ t_mtrack **tpp = x->x_tracks;
+ while (ntracks--)
+ {
+ t_mtrack *tp = *tpp++;
+ if (tp->tr_binbuf) binbuf_free(tp->tr_binbuf);
+ if (tp->tr_clock) clock_free(tp->tr_clock);
+ pd_free((t_pd *)tp);
+ }
+ freebytes(x->x_tracks, x->x_ntracks * sizeof(*x->x_tracks));
+ }
+}
+
+static void *mtr_new(t_floatarg f)
+{
+ t_mtr *x = 0;
+ int ntracks = (int)f;
+ t_mtrack **tracks;
+ if (ntracks < 1)
+ ntracks = 1;
+ if (tracks = getbytes(ntracks * sizeof(*tracks)))
+ {
+ int i;
+ t_mtrack **tpp;
+ for (i = 0, tpp = tracks; i < ntracks; i++, tpp++)
+ {
+ if (!(*tpp = (t_mtrack *)pd_new(mtrack_class)) ||
+ !((*tpp)->tr_binbuf = binbuf_new()) ||
+ !((*tpp)->tr_clock = clock_new(*tpp, (t_method)mtrack_tick)))
+ {
+ if (*tpp) pd_free((t_pd *)*tpp);
+ if ((*tpp)->tr_binbuf) binbuf_free((*tpp)->tr_binbuf);
+ while (i--)
+ {
+ tpp--;
+ binbuf_free((*tpp)->tr_binbuf);
+ clock_free((*tpp)->tr_clock);
+ pd_free((t_pd *)*tpp);
+ }
+ return (0);
+ }
+ }
+ if (x = (t_mtr *)pd_new(mtr_class))
+ {
+ int id;
+ t_outlet *mainout = outlet_new((t_object *)x, &s_list);
+ x->x_glist = canvas_getcurrent();
+ x->x_filehandle = hammerfile_new((t_pd *)x, 0,
+ mtr_readhook, mtr_writehook, 0);
+ x->x_ntracks = ntracks;
+ x->x_tracks = tracks;
+ for (id = 0; id < ntracks; id++, tracks++) /* CHECKME 0-based */
+ {
+ t_mtrack *tp = *tracks;
+ inlet_new((t_object *)x, (t_pd *)tp, 0, 0);
+ tp->tr_trackout = outlet_new((t_object *)x, &s_);
+ tp->tr_mainout = mainout;
+ tp->tr_owner = x;
+ tp->tr_id = id;
+ tp->tr_listed = 0;
+ tp->tr_filehandle = /* LATER rethink */
+ hammerfile_new((t_pd *)tp, 0,
+ mtrack_readhook, mtrack_writehook, 0);
+ tp->tr_mode = MTR_STEPMODE;
+ tp->tr_muted = 0;
+ tp->tr_restarted = 0;
+ tp->tr_atdelta = 0;
+ tp->tr_ixnext = -1;
+ tp->tr_tempo = 1.;
+ tp->tr_clockdelay = 0;
+ tp->tr_prevtime = 0;
+ }
+ }
+ }
+ return (x);
+}
+
+void mtr_setup(void)
+{
+ mtrack_class = class_new(gensym("_mtrack"), 0, 0,
+ sizeof(t_mtrack), CLASS_PD | CLASS_NOINLET, 0);
+ class_addfloat(mtrack_class, mtrack_float);
+ class_addsymbol(mtrack_class, mtrack_symbol);
+ class_addlist(mtrack_class, mtrack_list);
+ class_addmethod(mtrack_class, (t_method)mtrack_record,
+ gensym("record"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_play,
+ gensym("play"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_stop,
+ gensym("stop"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_next,
+ gensym("next"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_rewind,
+ gensym("rewind"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_mute,
+ gensym("mute"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_unmute,
+ gensym("unmute"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_clear,
+ gensym("clear"), 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_delay,
+ gensym("delay"), A_FLOAT, 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_first,
+ gensym("first"), A_FLOAT, 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_read,
+ gensym("read"), A_DEFSYM, 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_write,
+ gensym("write"), A_DEFSYM, 0);
+ class_addmethod(mtrack_class, (t_method)mtrack_tempo,
+ gensym("tempo"), A_FLOAT, 0);
+
+ mtr_class = class_new(gensym("mtr"),
+ (t_newmethod)mtr_new,
+ (t_method)mtr_free,
+ sizeof(t_mtr), 0,
+ A_DEFFLOAT, 0);
+ class_addmethod(mtr_class, (t_method)mtr_record,
+ gensym("record"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_play,
+ gensym("play"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_stop,
+ gensym("stop"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_next,
+ gensym("next"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_rewind,
+ gensym("rewind"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_mute,
+ gensym("mute"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_unmute,
+ gensym("unmute"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_clear,
+ gensym("clear"), A_GIMME, 0);
+ class_addmethod(mtr_class, (t_method)mtr_delay,
+ gensym("delay"), A_FLOAT, 0);
+ class_addmethod(mtr_class, (t_method)mtr_first,
+ gensym("first"), A_FLOAT, 0);
+ class_addmethod(mtr_class, (t_method)mtr_read,
+ gensym("read"), A_DEFSYM, 0);
+ class_addmethod(mtr_class, (t_method)mtr_write,
+ gensym("write"), A_DEFSYM, 0);
+ class_addmethod(mtr_class, (t_method)mtr_tempo,
+ gensym("tempo"), A_FLOAT, 0);
+ hammerfile_setup(mtr_class, 0);
+}