summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2011-11-20 22:54:52 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2011-11-20 22:54:52 +0000
commitcdd1d1ee24e161dd2cf1e3ae33cd3014431ebd12 (patch)
tree487a7a440edeabd365a255c012645b82b247bbfd
parent96c77bdb257f1973b17a828034fa3a269854e7db (diff)
Move mmc/mtc and volume control bits from struct aproc to struct
dev. Allows volume settings to be saved while the device is kept closed. Besides that, no behabiour changes.
-rw-r--r--usr.bin/aucat/aproc.c8
-rw-r--r--usr.bin/aucat/aproc.h28
-rw-r--r--usr.bin/aucat/aucat.c7
-rw-r--r--usr.bin/aucat/dev.c488
-rw-r--r--usr.bin/aucat/dev.h40
-rw-r--r--usr.bin/aucat/file.h4
-rw-r--r--usr.bin/aucat/midi.c686
-rw-r--r--usr.bin/aucat/midi.h15
-rw-r--r--usr.bin/aucat/siofile.c15
-rw-r--r--usr.bin/aucat/sock.c39
-rw-r--r--usr.bin/aucat/wav.c25
11 files changed, 670 insertions, 685 deletions
diff --git a/usr.bin/aucat/aproc.c b/usr.bin/aucat/aproc.c
index 7a69b143b78..76051b9eee1 100644
--- a/usr.bin/aucat/aproc.c
+++ b/usr.bin/aucat/aproc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.c,v 1.67 2011/11/16 08:03:34 ratchov Exp $ */
+/* $OpenBSD: aproc.c,v 1.68 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -1002,8 +1002,6 @@ mix_opos(struct aproc *p, struct abuf *obuf, int delta)
dbg_puts("\n");
}
#endif
- if (APROC_OK(p->u.mix.ctl))
- ctl_ontick(p->u.mix.ctl, delta);
aproc_opos(p, obuf, delta);
if (APROC_OK(p->u.mix.mon))
p->u.mix.mon->ops->ipos(p->u.mix.mon, NULL, delta);
@@ -1032,7 +1030,6 @@ mix_new(char *name, int maxlat, unsigned round, unsigned autovol)
p->u.mix.lat = 0;
p->u.mix.round = round;
p->u.mix.maxlat = maxlat;
- p->u.mix.ctl = NULL;
p->u.mix.mon = NULL;
p->u.mix.autovol = autovol;
return p;
@@ -1425,8 +1422,6 @@ sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
dbg_puts("\n");
}
#endif
- if (APROC_OK(p->u.sub.ctl))
- ctl_ontick(p->u.sub.ctl, delta);
aproc_ipos(p, ibuf, delta);
}
@@ -1453,7 +1448,6 @@ sub_new(char *name, int maxlat, unsigned round)
p->u.sub.lat = 0;
p->u.sub.round = round;
p->u.sub.maxlat = maxlat;
- p->u.sub.ctl = NULL;
return p;
}
diff --git a/usr.bin/aucat/aproc.h b/usr.bin/aucat/aproc.h
index 1f507ecc527..0a1ac3f7d5b 100644
--- a/usr.bin/aucat/aproc.h
+++ b/usr.bin/aucat/aproc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: aproc.h,v 1.40 2011/11/15 20:41:54 ratchov Exp $ */
+/* $OpenBSD: aproc.h,v 1.41 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -138,7 +138,6 @@ struct aproc {
int lat; /* current latency */
int maxlat; /* max latency allowed */
unsigned abspos; /* frames produced */
- struct aproc *ctl; /* MIDI control/sync */
struct aproc *mon; /* snoop output */
unsigned autovol; /* adjust volume dynamically */
} mix;
@@ -148,7 +147,6 @@ struct aproc {
int lat; /* current latency */
int maxlat; /* max latency allowed */
unsigned abspos; /* frames consumed */
- struct aproc *ctl;
} sub;
struct {
int delta; /* time position */
@@ -176,15 +174,6 @@ struct aproc {
} thru;
struct {
struct dev *dev; /* controlled device */
-#define CTL_NSLOT 8
-#define CTL_NAMEMAX 8
- unsigned serial;
-#define CTL_OFF 0 /* ignore MMC messages */
-#define CTL_STOP 1 /* stopped, can't start */
-#define CTL_START 2 /* attempting to start */
-#define CTL_RUN 3 /* started */
- unsigned tstate;
- unsigned origin; /* MTC start time */
unsigned fps; /* MTC frames per second */
#define MTC_FPS_24 0
#define MTC_FPS_25 1
@@ -196,21 +185,6 @@ struct aproc {
unsigned fr; /* MTC frames */
unsigned qfr; /* MTC quarter frames */
int delta; /* rel. to the last MTC tick */
- struct ctl_slot {
- struct ctl_ops {
- void (*vol)(void *, unsigned);
- void (*start)(void *);
- void (*stop)(void *);
- void (*loc)(void *, unsigned);
- void (*quit)(void *);
- } *ops;
- void *arg;
- unsigned unit;
- char name[CTL_NAMEMAX];
- unsigned serial;
- unsigned vol;
- unsigned tstate;
- } slot[CTL_NSLOT];
} ctl;
} u;
};
diff --git a/usr.bin/aucat/aucat.c b/usr.bin/aucat/aucat.c
index ce80ccad1b5..ceb3c06bc37 100644
--- a/usr.bin/aucat/aucat.c
+++ b/usr.bin/aucat/aucat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: aucat.c,v 1.125 2011/11/15 08:05:22 ratchov Exp $ */
+/* $OpenBSD: aucat.c,v 1.126 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -582,7 +582,7 @@ main(int argc, char **argv)
if (!dev_init(d))
exit(1);
if (d->autostart && (d->mode & MODE_AUDIOMASK))
- ctl_start(d->midi);
+ dev_mmcstart(d);
}
for (l = listen_list; l != NULL; l = l->next) {
if (!listen_init(l))
@@ -608,8 +608,7 @@ main(int argc, char **argv)
dnext = d->next;
if (!dev_run(d))
goto fatal;
- if ((d->mode & MODE_THRU) ||
- (d->pstate != DEV_CLOSED && !ctl_idle(d->midi)))
+ if (!dev_idle(d))
active = 1;
}
if (dev_list == NULL)
diff --git a/usr.bin/aucat/dev.c b/usr.bin/aucat/dev.c
index ef851ca85d7..2b0f5f2e9e3 100644
--- a/usr.bin/aucat/dev.c
+++ b/usr.bin/aucat/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.70 2011/11/16 21:26:55 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.71 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -64,6 +64,7 @@
*/
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include "abuf.h"
@@ -84,6 +85,7 @@ void dev_close(struct dev *);
void dev_start(struct dev *);
void dev_stop(struct dev *);
void dev_clear(struct dev *);
+void dev_onmove(void *, int);
int devctl_open(struct dev *, struct devctl *);
struct dev *dev_list = NULL;
@@ -111,7 +113,7 @@ dev_new(char *path, unsigned mode,
unsigned bufsz, unsigned round, unsigned hold, unsigned autovol)
{
struct dev *d;
- unsigned *pnum;
+ unsigned *pnum, i;
d = malloc(sizeof(struct dev));
if (d == NULL) {
@@ -140,6 +142,17 @@ dev_new(char *path, unsigned mode,
d->autovol = autovol;
d->autostart = 0;
d->pstate = DEV_CLOSED;
+ d->serial = 0;
+ for (i = 0; i < CTL_NSLOT; i++) {
+ d->slot[i].unit = i;
+ d->slot[i].ops = NULL;
+ d->slot[i].vol = MIDI_MAXCTL;
+ d->slot[i].tstate = CTL_OFF;
+ d->slot[i].serial = d->serial++;
+ d->slot[i].name[0] = '\0';
+ }
+ d->origin = 0;
+ d->tstate = CTL_STOP;
d->next = dev_list;
dev_list = d;
return d;
@@ -393,16 +406,10 @@ dev_open(struct dev *d)
if (d->mode & MODE_PLAY) {
d->mix = mix_new("play", d->bufsz, d->round, d->autovol);
d->mix->refs++;
- d->mix->u.mix.ctl = d->midi;
}
if (d->mode & MODE_REC) {
d->sub = sub_new("rec", d->bufsz, d->round);
d->sub->refs++;
- /*
- * If not playing, use the record end as clock source
- */
- if (!(d->mode & MODE_PLAY))
- d->sub->u.sub.ctl = d->midi;
}
if (d->mode & MODE_LOOP) {
/*
@@ -657,6 +664,13 @@ dev_close(struct dev *d)
void
dev_drain(struct dev *d)
{
+ unsigned i;
+ struct ctl_slot *s;
+
+ for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
+ if (s->ops)
+ s->ops->quit(s->arg);
+ }
if (d->pstate != DEV_CLOSED)
dev_close(d);
}
@@ -728,10 +742,10 @@ dev_start(struct dev *d)
d->submon->flags |= APROC_DROP;
if (APROC_OK(d->play) && d->play->u.io.file) {
f = d->play->u.io.file;
- f->ops->start(f);
+ f->ops->start(f, dev_onmove, d);
} else if (APROC_OK(d->rec) && d->rec->u.io.file) {
f = d->rec->u.io.file;
- f->ops->start(f);
+ f->ops->start(f, dev_onmove, d);
}
}
@@ -852,7 +866,7 @@ dev_run(struct dev *d)
(!APROC_OK(d->submon) ||
d->submon->u.sub.idle > 2 * d->bufsz) &&
(!APROC_OK(d->midi) ||
- d->midi->u.ctl.tstate != CTL_RUN)) {
+ d->tstate != CTL_RUN)) {
#ifdef DEBUG
if (debug_level >= 3) {
dev_dbg(d);
@@ -1009,6 +1023,8 @@ dev_sync(struct dev *d, unsigned mode, struct abuf *ibuf, struct abuf *obuf)
/*
* return the current latency (in frames), ie the latency that
* a stream would have if dev_attach() is called on it.
+ *
+ * XXX: return a "unsigned", since result is always positive, isn't it?
*/
int
dev_getpos(struct dev *d)
@@ -1263,3 +1279,453 @@ dev_clear(struct dev *d)
mon_clear(d->mon);
}
}
+
+#ifdef DEBUG
+void
+dev_slotdbg(struct dev *d, int slot)
+{
+ struct ctl_slot *s;
+
+ if (slot < 0) {
+ dbg_puts("none");
+ } else {
+ s = d->slot + slot;
+ dbg_puts(s->name);
+ dbg_putu(s->unit);
+ dbg_puts("(");
+ dbg_putu(s->vol);
+ dbg_puts(")/");
+ switch (s->tstate) {
+ case CTL_OFF:
+ dbg_puts("off");
+ break;
+ case CTL_RUN:
+ dbg_puts("run");
+ break;
+ case CTL_START:
+ dbg_puts("sta");
+ break;
+ case CTL_STOP:
+ dbg_puts("stp");
+ break;
+ default:
+ dbg_puts("unk");
+ break;
+ }
+ }
+}
+#endif
+
+/*
+ * find the best matching free slot index (ie midi channel).
+ * return -1, if there are no free slots anymore
+ */
+int
+dev_mkslot(struct dev *d, char *who)
+{
+ char *s;
+ struct ctl_slot *slot;
+ char name[CTL_NAMEMAX];
+ unsigned i, unit, umap = 0;
+ unsigned ser, bestser, bestidx;
+
+ /*
+ * create a ``valid'' control name (lowcase, remove [^a-z], trucate)
+ */
+ for (i = 0, s = who; ; s++) {
+ if (i == CTL_NAMEMAX - 1 || *s == '\0') {
+ name[i] = '\0';
+ break;
+ } else if (*s >= 'A' && *s <= 'Z') {
+ name[i++] = *s + 'a' - 'A';
+ } else if (*s >= 'a' && *s <= 'z')
+ name[i++] = *s;
+ }
+ if (i == 0)
+ strlcpy(name, "noname", CTL_NAMEMAX);
+
+ /*
+ * find the instance number of the control name
+ */
+ for (i = 0, slot = d->slot; i < CTL_NSLOT; i++, slot++) {
+ if (slot->ops == NULL)
+ continue;
+ if (strcmp(slot->name, name) == 0)
+ umap |= (1 << i);
+ }
+ for (unit = 0; ; unit++) {
+ if (unit == CTL_NSLOT) {
+#ifdef DEBUG
+ if (debug_level >= 1) {
+ dbg_puts(name);
+ dbg_puts(": too many instances\n");
+ }
+#endif
+ return -1;
+ }
+ if ((umap & (1 << unit)) == 0)
+ break;
+ }
+
+ /*
+ * find a free controller slot with the same name/unit
+ */
+ for (i = 0, slot = d->slot; i < CTL_NSLOT; i++, slot++) {
+ if (slot->ops == NULL &&
+ strcmp(slot->name, name) == 0 &&
+ slot->unit == unit) {
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dbg_puts(name);
+ dbg_putu(unit);
+ dbg_puts(": found slot ");
+ dbg_putu(i);
+ dbg_puts("\n");
+ }
+#endif
+ return i;
+ }
+ }
+
+ /*
+ * couldn't find a matching slot, pick oldest free slot
+ * and set its name/unit
+ */
+ bestser = 0;
+ bestidx = CTL_NSLOT;
+ for (i = 0, slot = d->slot; i < CTL_NSLOT; i++, slot++) {
+ if (slot->ops != NULL)
+ continue;
+ ser = d->serial - slot->serial;
+ if (ser > bestser) {
+ bestser = ser;
+ bestidx = i;
+ }
+ }
+ if (bestidx == CTL_NSLOT) {
+#ifdef DEBUG
+ if (debug_level >= 1) {
+ dbg_puts(name);
+ dbg_putu(unit);
+ dbg_puts(": out of mixer slots\n");
+ }
+#endif
+ return -1;
+ }
+ slot = d->slot + bestidx;
+ if (slot->name[0] != '\0')
+ slot->vol = MIDI_MAXCTL;
+ strlcpy(slot->name, name, CTL_NAMEMAX);
+ slot->serial = d->serial++;
+ slot->unit = unit;
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dbg_puts(name);
+ dbg_putu(unit);
+ dbg_puts(": overwritten slot ");
+ dbg_putu(bestidx);
+ dbg_puts("\n");
+ }
+#endif
+ return bestidx;
+}
+
+/*
+ * allocate a new slot and register the given call-backs
+ */
+int
+dev_slotnew(struct dev *d, char *who, struct ctl_ops *ops, void *arg, int mmc)
+{
+ int slot;
+ struct ctl_slot *s;
+
+ slot = dev_mkslot(d, who);
+ if (slot < 0)
+ return -1;
+
+ s = d->slot + slot;
+ s->ops = ops;
+ s->arg = arg;
+ s->tstate = mmc ? CTL_STOP : CTL_OFF;
+ s->ops->vol(s->arg, s->vol);
+
+ if (APROC_OK(d->midi)) {
+ ctl_slot(d->midi, slot);
+ ctl_vol(d->midi, slot, s->vol);
+ } else {
+#ifdef DEBUG
+ if (debug_level >= 2) {
+ dev_slotdbg(d, slot);
+ dbg_puts(": MIDI control not available\n");
+ }
+#endif
+ }
+ return slot;
+}
+
+/*
+ * release the given slot
+ */
+void
+dev_slotdel(struct dev *d, int slot)
+{
+ struct ctl_slot *s;
+
+ s = d->slot + slot;
+ s->ops = NULL;
+}
+
+/*
+ * notifty the mixer that volume changed, called by whom allocad the slot using
+ * ctl_slotnew(). Note: it doesn't make sens to call this from within the
+ * call-back.
+ *
+ * XXX: set actual volume here and use only this interface. Now, this
+ * can work because all streams have a slot
+ */
+void
+dev_slotvol(struct dev *d, int slot, unsigned vol)
+{
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dev_slotdbg(d, slot);
+ dbg_puts(": changing volume to ");
+ dbg_putu(vol);
+ dbg_puts("\n");
+ }
+#endif
+ d->slot[slot].vol = vol;
+ if (APROC_OK(d->midi))
+ ctl_vol(d->midi, slot, vol);
+}
+
+
+/*
+ * check if there are controlled streams
+ */
+int
+dev_idle(struct dev *d)
+{
+ unsigned i;
+ struct ctl_slot *s;
+
+ /*
+ * XXX: this conditions breaks -aoff for thru boxes
+ */
+ if (d->mode & MODE_THRU)
+ return 0;
+
+ if (d->pstate != DEV_CLOSED)
+ return 0;
+
+ /*
+ * XXX: if the device is closed, we're sure there are no
+ * slots in use, so the following test is useless
+ */
+ for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
+ if (s->ops)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * check that all clients controlled by MMC are ready to start,
+ * if so, start them all but the caller
+ */
+int
+dev_try(struct dev *d, int slot)
+{
+ unsigned i;
+ struct ctl_slot *s;
+
+ if (d->tstate != CTL_START) {
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dev_slotdbg(d, slot);
+ dbg_puts(": server not started, delayd\n");
+ }
+#endif
+ return 0;
+ }
+ for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
+ if (!s->ops || i == slot)
+ continue;
+ if (s->tstate != CTL_OFF && s->tstate != CTL_START) {
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dev_slotdbg(d, i);
+ dbg_puts(": not ready, server delayed\n");
+ }
+#endif
+ return 0;
+ }
+ }
+ for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
+ if (!s->ops || i == slot)
+ continue;
+ if (s->tstate == CTL_START) {
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dev_slotdbg(d, i);
+ dbg_puts(": started\n");
+ }
+#endif
+ s->tstate = CTL_RUN;
+ s->ops->start(s->arg);
+ }
+ }
+ if (slot >= 0)
+ d->slot[slot].tstate = CTL_RUN;
+ d->tstate = CTL_RUN;
+ if (APROC_OK(d->midi))
+ ctl_full(d->midi, d->origin, d->rate, d->round, dev_getpos(d));
+ dev_wakeup(d);
+ return 1;
+}
+
+/*
+ * notify the MMC layer that the stream is attempting
+ * to start. If other streams are not ready, 0 is returned meaning
+ * that the stream should wait. If other streams are ready, they
+ * are started, and the caller should start immediately.
+ */
+int
+dev_slotstart(struct dev *d, int slot)
+{
+ struct ctl_slot *s = d->slot + slot;
+
+ if (s->tstate == CTL_OFF || d->tstate == CTL_OFF)
+ return 1;
+
+ /*
+ * if the server already started (the client missed the
+ * start rendez-vous) or the server is stopped, then
+ * tag the client as ``wanting to start''
+ */
+ s->tstate = CTL_START;
+ return dev_try(d, slot);
+}
+
+/*
+ * notify the MMC layer that the stream no longer is trying to
+ * start (or that it just stopped), meaning that its ``start'' call-back
+ * shouldn't be called anymore
+ */
+void
+dev_slotstop(struct dev *d, int slot)
+{
+ struct ctl_slot *s = d->slot + slot;
+
+ /*
+ * tag the stream as not trying to start,
+ * unless MMC is turned off
+ */
+ if (s->tstate != CTL_OFF)
+ s->tstate = CTL_STOP;
+}
+
+/*
+ * start all slots simultaneously
+ */
+void
+dev_mmcstart(struct dev *d)
+{
+ if (d->tstate == CTL_STOP) {
+ d->tstate = CTL_START;
+ (void)dev_try(d, -1);
+#ifdef DEBUG
+ } else {
+ if (debug_level >= 3) {
+ dev_dbg(d);
+ dbg_puts(": ignoring mmc start\n");
+ }
+#endif
+ }
+}
+
+/*
+ * stop all slots simultaneously
+ */
+void
+dev_mmcstop(struct dev *d)
+{
+ unsigned i;
+ struct ctl_slot *s;
+
+ switch (d->tstate) {
+ case CTL_START:
+ d->tstate = CTL_STOP;
+ return;
+ case CTL_RUN:
+ d->tstate = CTL_STOP;
+ break;
+ default:
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dev_dbg(d);
+ dbg_puts(": ignored mmc stop\n");
+ }
+#endif
+ return;
+ }
+ for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
+ if (!s->ops)
+ continue;
+ if (s->tstate == CTL_RUN) {
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ dev_slotdbg(d, i);
+ dbg_puts(": requested to stop\n");
+ }
+#endif
+ s->ops->stop(s->arg);
+ }
+ }
+}
+
+/*
+ * relocate all slots simultaneously
+ */
+void
+dev_loc(struct dev *d, unsigned origin)
+{
+ unsigned i;
+ struct ctl_slot *s;
+
+#ifdef DEBUG
+ if (debug_level >= 2) {
+ dbg_puts("server relocated to ");
+ dbg_putu(origin);
+ dbg_puts("\n");
+ }
+#endif
+ if (d->tstate == CTL_RUN)
+ dev_mmcstop(d);
+ d->origin = origin;
+ for (i = 0, s = d->slot; i < CTL_NSLOT; i++, s++) {
+ if (!s->ops)
+ continue;
+ s->ops->loc(s->arg, d->origin);
+ }
+ if (d->tstate == CTL_RUN)
+ dev_mmcstart(d);
+}
+
+/*
+ * called at every clock tick by the mixer, delta is positive, unless
+ * there's an overrun/underrun
+ */
+void
+dev_onmove(void *arg, int delta)
+{
+ struct dev *d = (struct dev *)arg;
+
+ /*
+ * don't send ticks before the start signal
+ */
+ if (d->tstate != CTL_RUN)
+ return;
+ if (APROC_OK(d->midi))
+ ctl_qfr(d->midi, d->rate, delta);
+}
diff --git a/usr.bin/aucat/dev.h b/usr.bin/aucat/dev.h
index a572401d9db..79909acc759 100644
--- a/usr.bin/aucat/dev.h
+++ b/usr.bin/aucat/dev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.h,v 1.31 2011/11/15 08:05:22 ratchov Exp $ */
+/* $OpenBSD: dev.h,v 1.32 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -60,6 +60,32 @@ struct dev {
unsigned mode;
char *path;
} *ctl_list;
+
+ /* volume control and MMC/MTC */
+#define CTL_NSLOT 8
+#define CTL_NAMEMAX 8
+ unsigned serial;
+ struct ctl_slot {
+ struct ctl_ops {
+ void (*vol)(void *, unsigned);
+ void (*start)(void *);
+ void (*stop)(void *);
+ void (*loc)(void *, unsigned);
+ void (*quit)(void *);
+ } *ops;
+ void *arg;
+ unsigned unit;
+ char name[CTL_NAMEMAX];
+ unsigned serial;
+ unsigned vol;
+ unsigned tstate;
+ } slot[CTL_NSLOT];
+#define CTL_OFF 0 /* ignore MMC messages */
+#define CTL_STOP 1 /* stopped, can't start */
+#define CTL_START 2 /* attempting to start */
+#define CTL_RUN 3 /* started */
+ unsigned tstate; /* one of above */
+ unsigned origin; /* MTC start time */
};
extern struct dev *dev_list;
@@ -84,4 +110,16 @@ void dev_attach(struct dev *, char *, unsigned,
unsigned, int);
void dev_setvol(struct dev *, struct abuf *, int);
+void dev_slotdbg(struct dev *, int);
+int dev_slotnew(struct dev *, char *, struct ctl_ops *, void *, int);
+void dev_slotdel(struct dev *, int);
+void dev_slotvol(struct dev *, int, unsigned);
+
+int dev_slotstart(struct dev *, int);
+void dev_slotstop(struct dev *, int);
+void dev_mmcstart(struct dev *);
+void dev_mmcstop(struct dev *);
+void dev_loc(struct dev *, unsigned);
+int dev_idle(struct dev *);
+
#endif /* !define(DEV_H) */
diff --git a/usr.bin/aucat/file.h b/usr.bin/aucat/file.h
index 844900d5606..094d62fb092 100644
--- a/usr.bin/aucat/file.h
+++ b/usr.bin/aucat/file.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.h,v 1.11 2011/06/27 07:22:00 ratchov Exp $ */
+/* $OpenBSD: file.h,v 1.12 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -38,7 +38,7 @@ struct fileops {
void (*close)(struct file *);
unsigned (*read)(struct file *, unsigned char *, unsigned);
unsigned (*write)(struct file *, unsigned char *, unsigned);
- void (*start)(struct file *);
+ void (*start)(struct file *, void (*)(void *, int), void *);
void (*stop)(struct file *);
int (*nfds)(struct file *);
int (*pollfd)(struct file *, struct pollfd *, int);
diff --git a/usr.bin/aucat/midi.c b/usr.bin/aucat/midi.c
index fcf24cf3a77..d23be92e929 100644
--- a/usr.bin/aucat/midi.c
+++ b/usr.bin/aucat/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.38 2011/11/15 20:41:54 ratchov Exp $ */
+/* $OpenBSD: midi.c,v 1.39 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -354,42 +354,6 @@ thru_new(char *name)
return p;
}
-#ifdef DEBUG
-void
-ctl_slotdbg(struct aproc *p, int slot)
-{
- struct ctl_slot *s;
-
- if (slot < 0) {
- dbg_puts("none");
- } else {
- s = p->u.ctl.slot + slot;
- dbg_puts(s->name);
- dbg_putu(s->unit);
- dbg_puts("(");
- dbg_putu(s->vol);
- dbg_puts(")/");
- switch (s->tstate) {
- case CTL_OFF:
- dbg_puts("off");
- break;
- case CTL_RUN:
- dbg_puts("run");
- break;
- case CTL_START:
- dbg_puts("sta");
- break;
- case CTL_STOP:
- dbg_puts("stp");
- break;
- default:
- dbg_puts("unk");
- break;
- }
- }
-}
-#endif
-
/*
* send a message to the given output
*/
@@ -453,76 +417,111 @@ ctl_sendmsg(struct aproc *p, struct abuf *ibuf, unsigned char *msg, unsigned len
* send a quarter frame MTC message
*/
void
-ctl_qfr(struct aproc *p)
+ctl_qfr(struct aproc *p, unsigned rate, int delta)
{
unsigned char buf[2];
unsigned data;
+ int qfrlen;
- switch (p->u.ctl.qfr) {
- case 0:
- data = p->u.ctl.fr & 0xf;
- break;
- case 1:
- data = p->u.ctl.fr >> 4;
- break;
- case 2:
- data = p->u.ctl.sec & 0xf;
- break;
- case 3:
- data = p->u.ctl.sec >> 4;
- break;
- case 4:
- data = p->u.ctl.min & 0xf;
- break;
- case 5:
- data = p->u.ctl.min >> 4;
- break;
- case 6:
- data = p->u.ctl.hr & 0xf;
- break;
- case 7:
- data = (p->u.ctl.hr >> 4) | (p->u.ctl.fps_id << 1);
- /*
- * tick messages are sent 2 frames ahead
- */
- p->u.ctl.fr += 2;
- if (p->u.ctl.fr < p->u.ctl.fps)
+ p->u.ctl.delta += delta * MTC_SEC;
+
+ /*
+ * don't send ticks during the count-down
+ * XXX: test not useful, given while() condition
+ */
+ if (p->u.ctl.delta < 0)
+ return;
+
+ qfrlen = rate * (MTC_SEC / (4 * p->u.ctl.fps));
+ while (p->u.ctl.delta >= qfrlen) {
+ switch (p->u.ctl.qfr) {
+ case 0:
+ data = p->u.ctl.fr & 0xf;
break;
- p->u.ctl.fr -= p->u.ctl.fps;
- p->u.ctl.sec++;
- if (p->u.ctl.sec < 60)
+ case 1:
+ data = p->u.ctl.fr >> 4;
break;
- p->u.ctl.sec = 0;
- p->u.ctl.min++;
- if (p->u.ctl.min < 60)
+ case 2:
+ data = p->u.ctl.sec & 0xf;
break;
- p->u.ctl.min = 0;
- p->u.ctl.hr++;
- if (p->u.ctl.hr < 24)
+ case 3:
+ data = p->u.ctl.sec >> 4;
break;
- p->u.ctl.hr = 0;
- break;
- default:
- /* NOTREACHED */
- data = 0;
+ case 4:
+ data = p->u.ctl.min & 0xf;
+ break;
+ case 5:
+ data = p->u.ctl.min >> 4;
+ break;
+ case 6:
+ data = p->u.ctl.hr & 0xf;
+ break;
+ case 7:
+ data = (p->u.ctl.hr >> 4) | (p->u.ctl.fps_id << 1);
+ /*
+ * tick messages are sent 2 frames ahead
+ */
+ p->u.ctl.fr += 2;
+ if (p->u.ctl.fr < p->u.ctl.fps)
+ break;
+ p->u.ctl.fr -= p->u.ctl.fps;
+ p->u.ctl.sec++;
+ if (p->u.ctl.sec < 60)
+ break;
+ p->u.ctl.sec = 0;
+ p->u.ctl.min++;
+ if (p->u.ctl.min < 60)
+ break;
+ p->u.ctl.min = 0;
+ p->u.ctl.hr++;
+ if (p->u.ctl.hr < 24)
+ break;
+ p->u.ctl.hr = 0;
+ break;
+ default:
+ /* NOTREACHED */
+ data = 0;
+ }
+ buf[0] = 0xf1;
+ buf[1] = (p->u.ctl.qfr << 4) | data;
+ p->u.ctl.qfr++;
+ p->u.ctl.qfr &= 7;
+ ctl_sendmsg(p, NULL, buf, 2);
+ p->u.ctl.delta -= qfrlen;
}
- buf[0] = 0xf1;
- buf[1] = (p->u.ctl.qfr << 4) | data;
- p->u.ctl.qfr++;
- p->u.ctl.qfr &= 7;
- ctl_sendmsg(p, NULL, buf, 2);
}
/*
* send a full frame MTC message
*/
void
-ctl_full(struct aproc *p)
+ctl_full(struct aproc *p, unsigned origin, unsigned rate, unsigned round, unsigned pos)
{
unsigned char buf[10];
- unsigned origin = p->u.ctl.origin;
- unsigned fps = p->u.ctl.fps;
+ unsigned fps;
+ p->u.ctl.delta = MTC_SEC * pos;
+ if (rate % (30 * 4 * round) == 0) {
+ p->u.ctl.fps_id = MTC_FPS_30;
+ p->u.ctl.fps = 30;
+ } else if (rate % (25 * 4 * round) == 0) {
+ p->u.ctl.fps_id = MTC_FPS_25;
+ p->u.ctl.fps = 25;
+ } else {
+ p->u.ctl.fps_id = MTC_FPS_24;
+ p->u.ctl.fps = 24;
+ }
+#ifdef DEBUG
+ if (debug_level >= 3) {
+ aproc_dbg(p);
+ dbg_puts(": mtc full frame at ");
+ dbg_puti(p->u.ctl.delta);
+ dbg_puts(", ");
+ dbg_puti(p->u.ctl.fps);
+ dbg_puts(" fps\n");
+ }
+#endif
+ fps = p->u.ctl.fps;
p->u.ctl.hr = (origin / (3600 * MTC_SEC)) % 24;
p->u.ctl.min = (origin / (60 * MTC_SEC)) % 60;
p->u.ctl.sec = (origin / MTC_SEC) % 60;
@@ -548,7 +547,7 @@ ctl_msg_info(struct aproc *p, int slot, char *msg)
struct ctl_slot *s;
struct sysex *x = (struct sysex *)msg;
- s = p->u.ctl.slot + slot;
+ s = p->u.ctl.dev->slot + slot;
memset(x, 0, sizeof(struct sysex));
x->start = SYSEX_START;
x->type = SYSEX_TYPE_EDU;
@@ -567,7 +566,7 @@ ctl_msg_vol(struct aproc *p, int slot, char *msg)
{
struct ctl_slot *s;
- s = p->u.ctl.slot + slot;
+ s = p->u.ctl.dev->slot + slot;
msg[0] = MIDI_CTL | slot;
msg[1] = MIDI_CTLVOL;
msg[2] = s->vol;
@@ -580,7 +579,7 @@ ctl_dump(struct aproc *p, struct abuf *obuf)
unsigned char msg[sizeof(struct sysex)];
struct ctl_slot *s;
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
+ for (i = 0, s = p->u.ctl.dev->slot; i < CTL_NSLOT; i++, s++) {
ctl_msg_info(p, i, msg);
ctl_copymsg(obuf, msg, SYSEX_SIZE(mixinfo));
ctl_msg_vol(p, i, msg);
@@ -597,461 +596,26 @@ ctl_dump(struct aproc *p, struct abuf *obuf)
}
/*
- * find the best matching free slot index (ie midi channel).
- * return -1, if there are no free slots anymore
- */
-int
-ctl_getidx(struct aproc *p, char *who)
-{
- char *s;
- struct ctl_slot *slot;
- char name[CTL_NAMEMAX];
- unsigned i, unit, umap = 0;
- unsigned ser, bestser, bestidx;
-
- /*
- * create a ``valid'' control name (lowcase, remove [^a-z], trucate)
- */
- for (i = 0, s = who; ; s++) {
- if (i == CTL_NAMEMAX - 1 || *s == '\0') {
- name[i] = '\0';
- break;
- } else if (*s >= 'A' && *s <= 'Z') {
- name[i++] = *s + 'a' - 'A';
- } else if (*s >= 'a' && *s <= 'z')
- name[i++] = *s;
- }
- if (i == 0)
- strlcpy(name, "noname", CTL_NAMEMAX);
-
- /*
- * find the instance number of the control name
- */
- for (i = 0, slot = p->u.ctl.slot; i < CTL_NSLOT; i++, slot++) {
- if (slot->ops == NULL)
- continue;
- if (strcmp(slot->name, name) == 0)
- umap |= (1 << i);
- }
- for (unit = 0; ; unit++) {
- if (unit == CTL_NSLOT) {
-#ifdef DEBUG
- if (debug_level >= 1) {
- dbg_puts(name);
- dbg_puts(": too many instances\n");
- }
-#endif
- return -1;
- }
- if ((umap & (1 << unit)) == 0)
- break;
- }
-
- /*
- * find a free controller slot with the same name/unit
- */
- for (i = 0, slot = p->u.ctl.slot; i < CTL_NSLOT; i++, slot++) {
- if (slot->ops == NULL &&
- strcmp(slot->name, name) == 0 &&
- slot->unit == unit) {
-#ifdef DEBUG
- if (debug_level >= 3) {
- dbg_puts(name);
- dbg_putu(unit);
- dbg_puts(": found slot ");
- dbg_putu(i);
- dbg_puts("\n");
- }
-#endif
- return i;
- }
- }
-
- /*
- * couldn't find a matching slot, pick oldest free slot
- * and set its name/unit
- */
- bestser = 0;
- bestidx = CTL_NSLOT;
- for (i = 0, slot = p->u.ctl.slot; i < CTL_NSLOT; i++, slot++) {
- if (slot->ops != NULL)
- continue;
- ser = p->u.ctl.serial - slot->serial;
- if (ser > bestser) {
- bestser = ser;
- bestidx = i;
- }
- }
- if (bestidx == CTL_NSLOT) {
-#ifdef DEBUG
- if (debug_level >= 1) {
- dbg_puts(name);
- dbg_putu(unit);
- dbg_puts(": out of mixer slots\n");
- }
-#endif
- return -1;
- }
- slot = p->u.ctl.slot + bestidx;
- if (slot->name[0] != '\0')
- slot->vol = MIDI_MAXCTL;
- strlcpy(slot->name, name, CTL_NAMEMAX);
- slot->serial = p->u.ctl.serial++;
- slot->unit = unit;
-#ifdef DEBUG
- if (debug_level >= 3) {
- dbg_puts(name);
- dbg_putu(unit);
- dbg_puts(": overwritten slot ");
- dbg_putu(bestidx);
- dbg_puts("\n");
- }
-#endif
- return bestidx;
-}
-
-/*
- * check that all clients controlled by MMC are ready to start,
- * if so, start them all but the caller
- */
-int
-ctl_trystart(struct aproc *p, int caller)
-{
- unsigned i;
- struct ctl_slot *s;
-
- if (p->u.ctl.tstate != CTL_START) {
-#ifdef DEBUG
- if (debug_level >= 3) {
- ctl_slotdbg(p, caller);
- dbg_puts(": server not started, delayd\n");
- }
-#endif
- return 0;
- }
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (!s->ops || i == caller)
- continue;
- if (s->tstate != CTL_OFF && s->tstate != CTL_START) {
-#ifdef DEBUG
- if (debug_level >= 3) {
- ctl_slotdbg(p, i);
- dbg_puts(": not ready, server delayed\n");
- }
-#endif
- return 0;
- }
- }
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (!s->ops || i == caller)
- continue;
- if (s->tstate == CTL_START) {
-#ifdef DEBUG
- if (debug_level >= 3) {
- ctl_slotdbg(p, i);
- dbg_puts(": started\n");
- }
-#endif
- s->tstate = CTL_RUN;
- s->ops->start(s->arg);
- }
- }
- if (caller >= 0)
- p->u.ctl.slot[caller].tstate = CTL_RUN;
- p->u.ctl.tstate = CTL_RUN;
- p->u.ctl.delta = MTC_SEC * dev_getpos(p->u.ctl.dev);
- if (p->u.ctl.dev->rate % (30 * 4 * p->u.ctl.dev->round) == 0) {
- p->u.ctl.fps_id = MTC_FPS_30;
- p->u.ctl.fps = 30;
- } else if (p->u.ctl.dev->rate % (25 * 4 * p->u.ctl.dev->round) == 0) {
- p->u.ctl.fps_id = MTC_FPS_25;
- p->u.ctl.fps = 25;
- } else {
- p->u.ctl.fps_id = MTC_FPS_24;
- p->u.ctl.fps = 24;
- }
-#ifdef DEBUG
- if (debug_level >= 3) {
- ctl_slotdbg(p, caller);
- dbg_puts(": started server at ");
- dbg_puti(p->u.ctl.delta);
- dbg_puts(", ");
- dbg_puti(p->u.ctl.fps);
- dbg_puts(" mtc fps\n");
- }
-#endif
- dev_wakeup(p->u.ctl.dev);
- ctl_full(p);
- return 1;
-}
-
-/*
- * allocate a new slot and register the given call-backs
- */
-int
-ctl_slotnew(struct aproc *p, char *who, struct ctl_ops *ops, void *arg, int mmc)
-{
- int idx;
- struct ctl_slot *s;
- unsigned char msg[sizeof(struct sysex)];
-
- if (!APROC_OK(p)) {
-#ifdef DEBUG
- if (debug_level >= 2) {
- dbg_puts(who);
- dbg_puts(": MIDI control not available\n");
- }
-#endif
- return -1;
- }
- idx = ctl_getidx(p, who);
- if (idx < 0)
- return -1;
-
- s = p->u.ctl.slot + idx;
- s->ops = ops;
- s->arg = arg;
- s->tstate = mmc ? CTL_STOP : CTL_OFF;
- s->ops->vol(s->arg, s->vol);
- ctl_msg_info(p, idx, msg);
- ctl_sendmsg(p, NULL, msg, SYSEX_SIZE(mixinfo));
- ctl_msg_vol(p, idx, msg);
- ctl_sendmsg(p, NULL, msg, 3);
- return idx;
-}
-
-/*
- * release the given slot
- */
-void
-ctl_slotdel(struct aproc *p, int index)
-{
- unsigned i;
- struct ctl_slot *s;
-
- if (!APROC_OK(p))
- return;
- p->u.ctl.slot[index].ops = NULL;
- if (!(p->flags & APROC_QUIT))
- return;
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (s->ops)
- return;
- }
- if (LIST_EMPTY(&p->ins))
- aproc_del(p);
-}
-
-/*
- * called at every clock tick by the mixer, delta is positive, unless
- * there's an overrun/underrun
- */
-void
-ctl_ontick(struct aproc *p, int delta)
-{
- int qfrlen;
-
- /*
- * don't send ticks before the start signal
- */
- if (p->u.ctl.tstate != CTL_RUN)
- return;
-
- p->u.ctl.delta += delta * MTC_SEC;
-
- /*
- * don't send ticks during the count-down
- */
- if (p->u.ctl.delta < 0)
- return;
-
- qfrlen = p->u.ctl.dev->rate * (MTC_SEC / (4 * p->u.ctl.fps));
- while (p->u.ctl.delta >= qfrlen) {
- ctl_qfr(p);
- p->u.ctl.delta -= qfrlen;
- }
-}
-
-/*
* notifty the mixer that volume changed, called by whom allocad the slot using
* ctl_slotnew(). Note: it doesn't make sens to call this from within the
* call-back.
*/
void
-ctl_slotvol(struct aproc *p, int slot, unsigned vol)
+ctl_vol(struct aproc *p, int slot, unsigned vol)
{
unsigned char msg[3];
- if (!APROC_OK(p))
- return;
-#ifdef DEBUG
- if (debug_level >= 3) {
- ctl_slotdbg(p, slot);
- dbg_puts(": changing volume to ");
- dbg_putu(vol);
- dbg_puts("\n");
- }
-#endif
- p->u.ctl.slot[slot].vol = vol;
ctl_msg_vol(p, slot, msg);
ctl_sendmsg(p, NULL, msg, 3);
}
-/*
- * notify the MMC layer that the stream is attempting
- * to start. If other streams are not ready, 0 is returned meaning
- * that the stream should wait. If other streams are ready, they
- * are started, and the caller should start immediately.
- */
-int
-ctl_slotstart(struct aproc *p, int slot)
-{
- struct ctl_slot *s = p->u.ctl.slot + slot;
-
- if (!APROC_OK(p))
- return 1;
- if (s->tstate == CTL_OFF || p->u.ctl.tstate == CTL_OFF)
- return 1;
-
- /*
- * if the server already started (the client missed the
- * start rendez-vous) or the server is stopped, then
- * tag the client as ``wanting to start''
- */
- s->tstate = CTL_START;
- return ctl_trystart(p, slot);
-}
-
-/*
- * notify the MMC layer that the stream no longer is trying to
- * start (or that it just stopped), meaning that its ``start'' call-back
- * shouldn't be called anymore
- */
-void
-ctl_slotstop(struct aproc *p, int slot)
-{
- struct ctl_slot *s = p->u.ctl.slot + slot;
-
- if (!APROC_OK(p))
- return;
- /*
- * tag the stream as not trying to start,
- * unless MMC is turned off
- */
- if (s->tstate != CTL_OFF)
- s->tstate = CTL_STOP;
-}
-
-/*
- * start all slots simultaneously
- */
-void
-ctl_start(struct aproc *p)
-{
- if (!APROC_OK(p))
- return;
- if (p->u.ctl.tstate == CTL_STOP) {
- p->u.ctl.tstate = CTL_START;
- (void)ctl_trystart(p, -1);
-#ifdef DEBUG
- } else {
- if (debug_level >= 3) {
- aproc_dbg(p);
- dbg_puts(": ignoring mmc start\n");
- }
-#endif
- }
-}
-
-/*
- * stop all slots simultaneously
- */
-void
-ctl_stop(struct aproc *p)
-{
- unsigned i;
- struct ctl_slot *s;
-
- if (!APROC_OK(p))
- return;
- switch (p->u.ctl.tstate) {
- case CTL_START:
- p->u.ctl.tstate = CTL_STOP;
- return;
- case CTL_RUN:
- p->u.ctl.tstate = CTL_STOP;
- break;
- default:
-#ifdef DEBUG
- if (debug_level >= 3) {
- aproc_dbg(p);
- dbg_puts(": ignored mmc stop\n");
- }
-#endif
- return;
- }
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (!s->ops)
- continue;
- if (s->tstate == CTL_RUN) {
-#ifdef DEBUG
- if (debug_level >= 3) {
- ctl_slotdbg(p, i);
- dbg_puts(": requested to stop\n");
- }
-#endif
- s->ops->stop(s->arg);
- }
- }
-}
-
-/*
- * relocate all slots simultaneously
- */
void
-ctl_loc(struct aproc *p, unsigned origin)
-{
- unsigned i, tstate;
- struct ctl_slot *s;
-
- if (!APROC_OK(p))
- return;
-#ifdef DEBUG
- if (debug_level >= 2) {
- dbg_puts("server relocated to ");
- dbg_putu(origin);
- dbg_puts("\n");
- }
-#endif
- tstate = p->u.ctl.tstate;
- if (tstate == CTL_RUN)
- ctl_stop(p);
- p->u.ctl.origin = origin;
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (!s->ops)
- continue;
- s->ops->loc(s->arg, p->u.ctl.origin);
- }
- if (tstate == CTL_RUN)
- ctl_start(p);
-}
-
-/*
- * check if there are controlled streams
- */
-int
-ctl_idle(struct aproc *p)
+ctl_slot(struct aproc *p, int slot)
{
- unsigned i;
- struct ctl_slot *s;
+ unsigned char msg[sizeof(struct sysex)];
- if (!APROC_OK(p))
- return 1;
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (s->ops)
- return 0;
- }
- return 1;
+ ctl_msg_info(p, slot, msg);
+ ctl_sendmsg(p, NULL, msg, SYSEX_SIZE(mixinfo));
}
/*
@@ -1082,7 +646,7 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
chan = ibuf->r.midi.msg[0] & MIDI_CHANMASK;
if (chan >= CTL_NSLOT)
return;
- slot = p->u.ctl.slot + chan;
+ slot = p->u.ctl.dev->slot + chan;
slot->vol = ibuf->r.midi.msg[2];
if (slot->ops == NULL)
return;
@@ -1109,7 +673,7 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
dbg_puts(": mmc stop\n");
}
#endif
- ctl_stop(p);
+ dev_mmcstop(p->u.ctl.dev);
break;
case SYSEX_MMC_START:
if (len != SYSEX_SIZE(start))
@@ -1120,7 +684,7 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
dbg_puts(": mmc start\n");
}
#endif
- ctl_start(p);
+ dev_mmcstart(p->u.ctl.dev);
break;
case SYSEX_MMC_LOC:
if (len != SYSEX_SIZE(loc) ||
@@ -1138,10 +702,10 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
fps = 30;
break;
default:
- p->u.ctl.origin = 0;
+ /* XXX: should dev_mmcstop() here */
return;
}
- ctl_loc(p,
+ dev_loc(p->u.ctl.dev,
(x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
x->u.loc.min * 60 * MTC_SEC +
x->u.loc.sec * MTC_SEC +
@@ -1215,32 +779,14 @@ ctl_out(struct aproc *p, struct abuf *obuf)
void
ctl_eof(struct aproc *p, struct abuf *ibuf)
{
- unsigned i;
- struct ctl_slot *s;
-
- if (!(p->flags & APROC_QUIT))
- return;
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (s->ops != NULL)
- s->ops->quit(s->arg);
- }
- if (LIST_EMPTY(&p->ins))
+ if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
aproc_del(p);
}
void
ctl_hup(struct aproc *p, struct abuf *obuf)
{
- unsigned i;
- struct ctl_slot *s;
-
- if (!(p->flags & APROC_QUIT))
- return;
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (s->ops)
- return;
- }
- if (LIST_EMPTY(&p->ins))
+ if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
aproc_del(p);
}
@@ -1253,18 +799,6 @@ ctl_newin(struct aproc *p, struct abuf *ibuf)
ibuf->r.midi.st = 0;
}
-void
-ctl_done(struct aproc *p)
-{
- unsigned i;
- struct ctl_slot *s;
-
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- if (s->ops != NULL)
- s->ops->quit(s->arg);
- }
-}
-
struct aproc_ops ctl_ops = {
"ctl",
ctl_in,
@@ -1275,27 +809,15 @@ struct aproc_ops ctl_ops = {
NULL, /* newout */
NULL, /* ipos */
NULL, /* opos */
- ctl_done
+ NULL,
};
struct aproc *
ctl_new(char *name, struct dev *dev)
{
struct aproc *p;
- struct ctl_slot *s;
- unsigned i;
p = aproc_new(&ctl_ops, name);
p->u.ctl.dev = dev;
- p->u.ctl.serial = 0;
- p->u.ctl.tstate = CTL_STOP;
- for (i = 0, s = p->u.ctl.slot; i < CTL_NSLOT; i++, s++) {
- p->u.ctl.slot[i].unit = i;
- p->u.ctl.slot[i].ops = NULL;
- p->u.ctl.slot[i].vol = MIDI_MAXCTL;
- p->u.ctl.slot[i].tstate = CTL_OFF;
- p->u.ctl.slot[i].serial = p->u.ctl.serial++;
- p->u.ctl.slot[i].name[0] = '\0';
- }
return p;
}
diff --git a/usr.bin/aucat/midi.h b/usr.bin/aucat/midi.h
index d55fb42ab4b..87b6a0a06f3 100644
--- a/usr.bin/aucat/midi.h
+++ b/usr.bin/aucat/midi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.h,v 1.9 2010/06/04 06:15:28 ratchov Exp $ */
+/* $OpenBSD: midi.h,v 1.10 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -22,15 +22,10 @@ struct dev;
struct aproc *thru_new(char *);
struct aproc *ctl_new(char *, struct dev *);
-int ctl_slotnew(struct aproc *, char *, struct ctl_ops *, void *, int);
-void ctl_slotdel(struct aproc *, int);
-void ctl_slotvol(struct aproc *, int, unsigned);
-int ctl_slotstart(struct aproc *, int);
-void ctl_slotstop(struct aproc *, int);
void ctl_ontick(struct aproc *, int);
-
-void ctl_stop(struct aproc *);
-void ctl_start(struct aproc *);
-int ctl_idle(struct aproc *);
+void ctl_slot(struct aproc *, int);
+void ctl_vol(struct aproc *, int, unsigned);
+void ctl_full(struct aproc *, unsigned, unsigned, unsigned, unsigned);
+void ctl_qfr(struct aproc *, unsigned, int);
#endif /* !defined(MIDI_H) */
diff --git a/usr.bin/aucat/siofile.c b/usr.bin/aucat/siofile.c
index 60ad391b5d6..412bc23d813 100644
--- a/usr.bin/aucat/siofile.c
+++ b/usr.bin/aucat/siofile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siofile.c,v 1.8 2011/10/12 07:20:04 ratchov Exp $ */
+/* $OpenBSD: siofile.c,v 1.9 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -42,6 +42,8 @@ struct siofile {
unsigned rtickets, rbpf;
unsigned bufsz;
int started;
+ void (*onmove)(void *, int);
+ void *arg;
#ifdef DEBUG
long long wtime, utime;
#endif
@@ -50,7 +52,7 @@ struct siofile {
void siofile_close(struct file *);
unsigned siofile_read(struct file *, unsigned char *, unsigned);
unsigned siofile_write(struct file *, unsigned char *, unsigned);
-void siofile_start(struct file *);
+void siofile_start(struct file *, void (*)(void *, int), void *);
void siofile_stop(struct file *);
int siofile_nfds(struct file *);
int siofile_pollfd(struct file *, struct pollfd *, int);
@@ -189,12 +191,12 @@ siofile_cb(void *addr, int delta)
p = f->file.wproc;
if (p && p->ops->opos)
p->ops->opos(p, NULL, delta);
- }
- if (delta != 0) {
p = f->file.rproc;
if (p && p->ops->ipos)
p->ops->ipos(p, NULL, delta);
}
+ if (f->onmove)
+ f->onmove(f->arg, delta);
f->wtickets += delta * f->wbpf;
f->rtickets += delta * f->rbpf;
}
@@ -305,7 +307,7 @@ siofile_new(struct fileops *ops, char *path, unsigned *rmode,
}
void
-siofile_start(struct file *file)
+siofile_start(struct file *file, void (*cb)(void *, int), void *arg)
{
struct siofile *f = (struct siofile *)file;
@@ -328,6 +330,8 @@ siofile_start(struct file *file)
dbg_puts(": started\n");
}
#endif
+ f->onmove = cb;
+ f->arg = arg;
}
void
@@ -336,6 +340,7 @@ siofile_stop(struct file *file)
struct siofile *f = (struct siofile *)file;
f->started = 0;
+ f->onmove = NULL;
if (!sio_eof(f->hdl) && !sio_stop(f->hdl)) {
#ifdef DEBUG
dbg_puts(f->file.name);
diff --git a/usr.bin/aucat/sock.c b/usr.bin/aucat/sock.c
index 9bef95065a2..1b91f899c20 100644
--- a/usr.bin/aucat/sock.c
+++ b/usr.bin/aucat/sock.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sock.c,v 1.61 2011/11/15 08:05:22 ratchov Exp $ */
+/* $OpenBSD: sock.c,v 1.62 2011/11/20 22:54:51 ratchov Exp $ */
/*
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
*
@@ -62,12 +62,10 @@ sock_dbg(struct sock *f)
};
static char *rstates[] = { "rdat", "rmsg", "rret" };
static char *wstates[] = { "widl", "wmsg", "wdat" };
- struct aproc *midi;
- midi = f->dev ? f->dev->midi : NULL;
- if (f->slot >= 0 && APROC_OK(midi)) {
- dbg_puts(midi->u.ctl.slot[f->slot].name);
- dbg_putu(midi->u.ctl.slot[f->slot].unit);
+ if (f->slot >= 0) {
+ dbg_puts(f->dev->slot[f->slot].name);
+ dbg_putu(f->dev->slot[f->slot].unit);
} else
dbg_puts(f->pipe.file.name);
dbg_puts("/");
@@ -121,7 +119,7 @@ rsock_done(struct aproc *p)
f->pipe.file.rproc = NULL;
if (f->pipe.file.wproc) {
if (f->slot >= 0)
- ctl_slotdel(f->dev->midi, f->slot);
+ dev_slotdel(f->dev, f->slot);
aproc_del(f->pipe.file.wproc);
file_del(&f->pipe.file);
}
@@ -226,7 +224,7 @@ wsock_done(struct aproc *p)
f->pipe.file.wproc = NULL;
if (f->pipe.file.rproc) {
if (f->slot >= 0)
- ctl_slotdel(f->dev->midi, f->slot);
+ dev_slotdel(f->dev, f->slot);
aproc_del(f->pipe.file.rproc);
file_del(&f->pipe.file);
}
@@ -375,7 +373,7 @@ sock_freebuf(struct sock *f)
wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
if (rbuf || wbuf)
- ctl_slotstop(f->dev->midi, f->slot);
+ dev_slotstop(f->dev, f->slot);
if (rbuf)
abuf_eof(rbuf);
if (wbuf)
@@ -428,7 +426,7 @@ sock_allocbuf(struct sock *f)
f->pstate = SOCK_START;
} else {
f->pstate = SOCK_READY;
- if (ctl_slotstart(f->dev->midi, f->slot))
+ if (dev_slotstart(f->dev, f->slot))
(void)sock_attach(f, 0);
}
}
@@ -586,7 +584,7 @@ sock_reset(struct sock *f)
switch (f->pstate) {
case SOCK_START:
case SOCK_READY:
- if (ctl_slotstart(f->dev->midi, f->slot)) {
+ if (dev_slotstart(f->dev, f->slot)) {
(void)sock_attach(f, 1);
f->pstate = SOCK_RUN;
}
@@ -926,11 +924,8 @@ sock_setpar(struct sock *f)
}
#ifdef DEBUG
if (debug_level >= 2) {
- if (APROC_OK(f->dev->midi)) {
- dbg_puts(f->dev->midi->u.ctl.slot[f->slot].name);
- dbg_putu(f->dev->midi->u.ctl.slot[f->slot].unit);
- } else
- dbg_puts(f->pipe.file.name);
+ dbg_puts(f->dev->slot[f->slot].name);
+ dbg_putu(f->dev->slot[f->slot].unit);
dbg_puts(": buffer size = ");
dbg_putu(f->bufsz);
if (f->mode & MODE_PLAY) {
@@ -1082,9 +1077,7 @@ sock_hello(struct sock *f)
f->xrun = (f->opt->mmc) ? XRUN_SYNC : XRUN_IGNORE;
f->bufsz = f->dev->bufsz;
f->round = f->dev->round;
- f->slot = ctl_slotnew(f->dev->midi, p->who,
- &ctl_sockops, f,
- f->opt->mmc);
+ f->slot = dev_slotnew(f->dev, p->who, &ctl_sockops, f, f->opt->mmc);
if (f->slot < 0)
return 0;
f->pstate = SOCK_INIT;
@@ -1225,7 +1218,7 @@ sock_execmsg(struct sock *f)
* see how this is fixed in wav.c
*/
if ((f->pstate == SOCK_START || f->pstate == SOCK_READY) &&
- ctl_slotstart(f->dev->midi, f->slot))
+ dev_slotstart(f->dev, f->slot))
(void)sock_attach(f, 1);
if (f->wstate != SOCK_WDATA || f->wtodo == 0)
sock_freebuf(f);
@@ -1336,7 +1329,7 @@ sock_execmsg(struct sock *f)
}
sock_setvol(f, ctl);
if (f->slot >= 0)
- ctl_slotvol(f->dev->midi, f->slot, ctl);
+ dev_slotvol(f->dev, f->slot, ctl);
f->rtodo = sizeof(struct amsg);
f->rstate = SOCK_RMSG;
break;
@@ -1585,10 +1578,10 @@ sock_read(struct sock *f)
}
/*
* XXX: sock_attach() may not start if there's not enough
- * samples queued, if so ctl_slotstart() will trigger
+ * samples queued, if so dev_slotstart() will trigger
* other streams, but this one won't start.
*/
- if (f->pstate == SOCK_READY && ctl_slotstart(f->dev->midi, f->slot))
+ if (f->pstate == SOCK_READY && dev_slotstart(f->dev, f->slot))
(void)sock_attach(f, 0);
break;
case SOCK_RRET:
diff --git a/usr.bin/aucat/wav.c b/usr.bin/aucat/wav.c
index 20c1dc78bf6..5db66df417e 100644
--- a/usr.bin/aucat/wav.c
+++ b/usr.bin/aucat/wav.c
@@ -185,12 +185,11 @@ void
wav_dbg(struct wav *f)
{
static char *pstates[] = { "cfg", "ini", "sta", "rdy", "run", "mid" };
- struct aproc *midi = f->dev ? f->dev->midi : NULL;
dbg_puts("wav(");
- if (f->slot >= 0 && APROC_OK(midi)) {
- dbg_puts(midi->u.ctl.slot[f->slot].name);
- dbg_putu(midi->u.ctl.slot[f->slot].unit);
+ if (f->slot >= 0) {
+ dbg_puts(f->dev->slot[f->slot].name);
+ dbg_putu(f->dev->slot[f->slot].unit);
} else
dbg_puts(f->pipe.file.name);
dbg_puts(")/");
@@ -407,7 +406,7 @@ wav_allocbuf(struct wav *f)
dbg_puts(": allocating buffers\n");
}
#endif
- if (f->pstate == WAV_READY && ctl_slotstart(d->midi, f->slot))
+ if (f->pstate == WAV_READY && dev_slotstart(d, f->slot))
(void)wav_attach(f, 0);
}
@@ -431,7 +430,7 @@ wav_freebuf(struct wav *f)
}
#endif
if (rbuf || wbuf)
- ctl_slotstop(f->dev->midi, f->slot);
+ dev_slotstop(f->dev, f->slot);
if (rbuf)
abuf_eof(rbuf);
if (wbuf)
@@ -448,7 +447,7 @@ wav_reset(struct wav *f)
switch (f->pstate) {
case WAV_START:
case WAV_READY:
- if (ctl_slotstart(f->dev->midi, f->slot))
+ if (dev_slotstart(f->dev, f->slot))
(void)wav_attach(f, 1);
/* PASSTHROUGH */
case WAV_RUN:
@@ -493,7 +492,7 @@ wav_init(struct wav *f)
wav_midiattach(f);
return 1;
}
- f->slot = ctl_slotnew(f->dev->midi, "wav", &ctl_wavops, f, 1);
+ f->slot = dev_slotnew(f->dev, "wav", &ctl_wavops, f, 1);
f->pstate = WAV_INIT;
if ((f->mode & f->dev->mode) != f->mode) {
#ifdef DEBUG
@@ -527,14 +526,14 @@ wav_seekmmc(struct wav *f)
* don't make other stream wait for us
*/
if (f->slot >= 0)
- ctl_slotstart(f->dev->midi, f->slot);
+ dev_slotstart(f->dev, f->slot);
return 0;
}
if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
wav_exit(f);
return 0;
}
- if (f->mode & MODE_RECMASK)
+ if ((f->mode & MODE_RECMASK) && f->mmcpos > f->endpos)
f->endpos = f->mmcpos;
if (f->hdr == HDR_WAV)
f->wbytes = WAV_DATAMAX - f->mmcpos;
@@ -567,7 +566,7 @@ wav_rdata(struct wav *f)
f->pstate = WAV_READY;
/* PASSTHROUGH */
case WAV_READY:
- if (ctl_slotstart(f->dev->midi, f->slot))
+ if (dev_slotstart(f->dev, f->slot))
(void)wav_attach(f, 0);
break;
case WAV_RUN:
@@ -928,7 +927,7 @@ rwav_done(struct aproc *p)
struct wav *f = (struct wav *)p->u.io.file;
if (f->slot >= 0)
- ctl_slotdel(f->dev->midi, f->slot);
+ dev_slotdel(f->dev, f->slot);
f->slot = -1;
rfile_done(p);
}
@@ -981,7 +980,7 @@ wwav_done(struct aproc *p)
struct wav *f = (struct wav *)p->u.io.file;
if (f->slot >= 0)
- ctl_slotdel(f->dev->midi, f->slot);
+ dev_slotdel(f->dev, f->slot);
f->slot = -1;
wfile_done(p);
}