move mmc/mtc and volume control bits from struct aproc to struct dev

This commit is contained in:
Alexandre Ratchov 2011-11-21 09:06:25 +01:00
parent a34a843352
commit 37baea58d8
11 changed files with 661 additions and 676 deletions

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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)

View File

@ -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);
}

View File

@ -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) */

View File

@ -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);

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: midi.h,v 1.9 2010/06/04 06:15:28 ratchov Exp $ */
/* $OpenBSD$ */
/*
* 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) */

View File

@ -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);

View File

@ -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:

View File

@ -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);
}