From 37baea58d881bfc7242e68dbec0729a132407df0 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Mon, 21 Nov 2011 09:06:25 +0100 Subject: [PATCH] move mmc/mtc and volume control bits from struct aproc to struct dev --- aucat/aproc.c | 6 - aucat/aproc.h | 26 -- aucat/aucat.c | 5 +- aucat/dev.c | 486 +++++++++++++++++++++++++++++++++- aucat/dev.h | 38 +++ aucat/file.h | 2 +- aucat/midi.c | 684 ++++++++---------------------------------------- aucat/midi.h | 15 +- aucat/siofile.c | 13 +- aucat/sock.c | 37 ++- aucat/wav.c | 25 +- 11 files changed, 661 insertions(+), 676 deletions(-) diff --git a/aucat/aproc.c b/aucat/aproc.c index c06c650..9014032 100644 --- a/aucat/aproc.c +++ b/aucat/aproc.c @@ -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/aucat/aproc.h b/aucat/aproc.h index 51b1954..c87f40d 100644 --- a/aucat/aproc.h +++ b/aucat/aproc.h @@ -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/aucat/aucat.c b/aucat/aucat.c index 6d4ec37..5c7fc79 100644 --- a/aucat/aucat.c +++ b/aucat/aucat.c @@ -583,7 +583,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)) @@ -609,8 +609,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/aucat/dev.c b/aucat/dev.c index 3b5b47a..6292271 100644 --- a/aucat/dev.c +++ b/aucat/dev.c @@ -64,6 +64,7 @@ */ #include #include +#include #include #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/aucat/dev.h b/aucat/dev.h index 7fe829e..f95d6b8 100644 --- a/aucat/dev.h +++ b/aucat/dev.h @@ -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/aucat/file.h b/aucat/file.h index 1c09f7e..2ac4bc0 100644 --- a/aucat/file.h +++ b/aucat/file.h @@ -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/aucat/midi.c b/aucat/midi.c index dabe4fe..8282c43 100644 --- a/aucat/midi.c +++ b/aucat/midi.c @@ -355,42 +355,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 */ @@ -454,76 +418,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; @@ -549,7 +548,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; @@ -568,7 +567,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; @@ -581,7 +580,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,462 +596,27 @@ ctl_dump(struct aproc *p, struct abuf *obuf) abuf_flush(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) +ctl_slot(struct aproc *p, int slot) { - struct ctl_slot *s = p->u.ctl.slot + slot; + unsigned char msg[sizeof(struct sysex)]; - 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) -{ - unsigned i; - struct ctl_slot *s; - - 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)); } /* @@ -1083,7 +647,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; @@ -1110,7 +674,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)) @@ -1121,7 +685,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) || @@ -1139,10 +703,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 + @@ -1216,32 +780,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); } @@ -1254,18 +800,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, @@ -1276,27 +810,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/aucat/midi.h b/aucat/midi.h index d55fb42..00eb7d3 100644 --- a/aucat/midi.h +++ b/aucat/midi.h @@ -1,4 +1,4 @@ -/* $OpenBSD: midi.h,v 1.9 2010/06/04 06:15:28 ratchov Exp $ */ +/* $OpenBSD$ */ /* * Copyright (c) 2008 Alexandre Ratchov * @@ -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/aucat/siofile.c b/aucat/siofile.c index a85ee75..76d9e09 100644 --- a/aucat/siofile.c +++ b/aucat/siofile.c @@ -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/aucat/sock.c b/aucat/sock.c index df3cca6..72eee07 100644 --- a/aucat/sock.c +++ b/aucat/sock.c @@ -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/aucat/wav.c b/aucat/wav.c index 20c1dc7..5db66df 100644 --- a/aucat/wav.c +++ b/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); }