summaryrefslogtreecommitdiff
path: root/usr.bin
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 /usr.bin
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.
Diffstat (limited to 'usr.bin')
-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);
}