mirror of https://github.com/ericonr/sndio.git
move mmc/mtc and volume control bits from struct aproc to struct dev
This commit is contained in:
parent
a34a843352
commit
37baea58d8
|
@ -1002,8 +1002,6 @@ mix_opos(struct aproc *p, struct abuf *obuf, int delta)
|
||||||
dbg_puts("\n");
|
dbg_puts("\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (APROC_OK(p->u.mix.ctl))
|
|
||||||
ctl_ontick(p->u.mix.ctl, delta);
|
|
||||||
aproc_opos(p, obuf, delta);
|
aproc_opos(p, obuf, delta);
|
||||||
if (APROC_OK(p->u.mix.mon))
|
if (APROC_OK(p->u.mix.mon))
|
||||||
p->u.mix.mon->ops->ipos(p->u.mix.mon, NULL, delta);
|
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.lat = 0;
|
||||||
p->u.mix.round = round;
|
p->u.mix.round = round;
|
||||||
p->u.mix.maxlat = maxlat;
|
p->u.mix.maxlat = maxlat;
|
||||||
p->u.mix.ctl = NULL;
|
|
||||||
p->u.mix.mon = NULL;
|
p->u.mix.mon = NULL;
|
||||||
p->u.mix.autovol = autovol;
|
p->u.mix.autovol = autovol;
|
||||||
return p;
|
return p;
|
||||||
|
@ -1425,8 +1422,6 @@ sub_ipos(struct aproc *p, struct abuf *ibuf, int delta)
|
||||||
dbg_puts("\n");
|
dbg_puts("\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (APROC_OK(p->u.sub.ctl))
|
|
||||||
ctl_ontick(p->u.sub.ctl, delta);
|
|
||||||
aproc_ipos(p, ibuf, 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.lat = 0;
|
||||||
p->u.sub.round = round;
|
p->u.sub.round = round;
|
||||||
p->u.sub.maxlat = maxlat;
|
p->u.sub.maxlat = maxlat;
|
||||||
p->u.sub.ctl = NULL;
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,6 @@ struct aproc {
|
||||||
int lat; /* current latency */
|
int lat; /* current latency */
|
||||||
int maxlat; /* max latency allowed */
|
int maxlat; /* max latency allowed */
|
||||||
unsigned abspos; /* frames produced */
|
unsigned abspos; /* frames produced */
|
||||||
struct aproc *ctl; /* MIDI control/sync */
|
|
||||||
struct aproc *mon; /* snoop output */
|
struct aproc *mon; /* snoop output */
|
||||||
unsigned autovol; /* adjust volume dynamically */
|
unsigned autovol; /* adjust volume dynamically */
|
||||||
} mix;
|
} mix;
|
||||||
|
@ -148,7 +147,6 @@ struct aproc {
|
||||||
int lat; /* current latency */
|
int lat; /* current latency */
|
||||||
int maxlat; /* max latency allowed */
|
int maxlat; /* max latency allowed */
|
||||||
unsigned abspos; /* frames consumed */
|
unsigned abspos; /* frames consumed */
|
||||||
struct aproc *ctl;
|
|
||||||
} sub;
|
} sub;
|
||||||
struct {
|
struct {
|
||||||
int delta; /* time position */
|
int delta; /* time position */
|
||||||
|
@ -176,15 +174,6 @@ struct aproc {
|
||||||
} thru;
|
} thru;
|
||||||
struct {
|
struct {
|
||||||
struct dev *dev; /* controlled device */
|
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 */
|
unsigned fps; /* MTC frames per second */
|
||||||
#define MTC_FPS_24 0
|
#define MTC_FPS_24 0
|
||||||
#define MTC_FPS_25 1
|
#define MTC_FPS_25 1
|
||||||
|
@ -196,21 +185,6 @@ struct aproc {
|
||||||
unsigned fr; /* MTC frames */
|
unsigned fr; /* MTC frames */
|
||||||
unsigned qfr; /* MTC quarter frames */
|
unsigned qfr; /* MTC quarter frames */
|
||||||
int delta; /* rel. to the last MTC tick */
|
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;
|
} ctl;
|
||||||
} u;
|
} u;
|
||||||
};
|
};
|
||||||
|
|
|
@ -583,7 +583,7 @@ main(int argc, char **argv)
|
||||||
if (!dev_init(d))
|
if (!dev_init(d))
|
||||||
exit(1);
|
exit(1);
|
||||||
if (d->autostart && (d->mode & MODE_AUDIOMASK))
|
if (d->autostart && (d->mode & MODE_AUDIOMASK))
|
||||||
ctl_start(d->midi);
|
dev_mmcstart(d);
|
||||||
}
|
}
|
||||||
for (l = listen_list; l != NULL; l = l->next) {
|
for (l = listen_list; l != NULL; l = l->next) {
|
||||||
if (!listen_init(l))
|
if (!listen_init(l))
|
||||||
|
@ -609,8 +609,7 @@ main(int argc, char **argv)
|
||||||
dnext = d->next;
|
dnext = d->next;
|
||||||
if (!dev_run(d))
|
if (!dev_run(d))
|
||||||
goto fatal;
|
goto fatal;
|
||||||
if ((d->mode & MODE_THRU) ||
|
if (!dev_idle(d))
|
||||||
(d->pstate != DEV_CLOSED && !ctl_idle(d->midi)))
|
|
||||||
active = 1;
|
active = 1;
|
||||||
}
|
}
|
||||||
if (dev_list == NULL)
|
if (dev_list == NULL)
|
||||||
|
|
486
aucat/dev.c
486
aucat/dev.c
|
@ -64,6 +64,7 @@
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "abuf.h"
|
#include "abuf.h"
|
||||||
|
@ -84,6 +85,7 @@ void dev_close(struct dev *);
|
||||||
void dev_start(struct dev *);
|
void dev_start(struct dev *);
|
||||||
void dev_stop(struct dev *);
|
void dev_stop(struct dev *);
|
||||||
void dev_clear(struct dev *);
|
void dev_clear(struct dev *);
|
||||||
|
void dev_onmove(void *, int);
|
||||||
int devctl_open(struct dev *, struct devctl *);
|
int devctl_open(struct dev *, struct devctl *);
|
||||||
|
|
||||||
struct dev *dev_list = NULL;
|
struct dev *dev_list = NULL;
|
||||||
|
@ -111,7 +113,7 @@ dev_new(char *path, unsigned mode,
|
||||||
unsigned bufsz, unsigned round, unsigned hold, unsigned autovol)
|
unsigned bufsz, unsigned round, unsigned hold, unsigned autovol)
|
||||||
{
|
{
|
||||||
struct dev *d;
|
struct dev *d;
|
||||||
unsigned *pnum;
|
unsigned *pnum, i;
|
||||||
|
|
||||||
d = malloc(sizeof(struct dev));
|
d = malloc(sizeof(struct dev));
|
||||||
if (d == NULL) {
|
if (d == NULL) {
|
||||||
|
@ -140,6 +142,17 @@ dev_new(char *path, unsigned mode,
|
||||||
d->autovol = autovol;
|
d->autovol = autovol;
|
||||||
d->autostart = 0;
|
d->autostart = 0;
|
||||||
d->pstate = DEV_CLOSED;
|
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;
|
d->next = dev_list;
|
||||||
dev_list = d;
|
dev_list = d;
|
||||||
return d;
|
return d;
|
||||||
|
@ -393,16 +406,10 @@ dev_open(struct dev *d)
|
||||||
if (d->mode & MODE_PLAY) {
|
if (d->mode & MODE_PLAY) {
|
||||||
d->mix = mix_new("play", d->bufsz, d->round, d->autovol);
|
d->mix = mix_new("play", d->bufsz, d->round, d->autovol);
|
||||||
d->mix->refs++;
|
d->mix->refs++;
|
||||||
d->mix->u.mix.ctl = d->midi;
|
|
||||||
}
|
}
|
||||||
if (d->mode & MODE_REC) {
|
if (d->mode & MODE_REC) {
|
||||||
d->sub = sub_new("rec", d->bufsz, d->round);
|
d->sub = sub_new("rec", d->bufsz, d->round);
|
||||||
d->sub->refs++;
|
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) {
|
if (d->mode & MODE_LOOP) {
|
||||||
/*
|
/*
|
||||||
|
@ -657,6 +664,13 @@ dev_close(struct dev *d)
|
||||||
void
|
void
|
||||||
dev_drain(struct dev *d)
|
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)
|
if (d->pstate != DEV_CLOSED)
|
||||||
dev_close(d);
|
dev_close(d);
|
||||||
}
|
}
|
||||||
|
@ -728,10 +742,10 @@ dev_start(struct dev *d)
|
||||||
d->submon->flags |= APROC_DROP;
|
d->submon->flags |= APROC_DROP;
|
||||||
if (APROC_OK(d->play) && d->play->u.io.file) {
|
if (APROC_OK(d->play) && d->play->u.io.file) {
|
||||||
f = 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) {
|
} else if (APROC_OK(d->rec) && d->rec->u.io.file) {
|
||||||
f = 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) ||
|
(!APROC_OK(d->submon) ||
|
||||||
d->submon->u.sub.idle > 2 * d->bufsz) &&
|
d->submon->u.sub.idle > 2 * d->bufsz) &&
|
||||||
(!APROC_OK(d->midi) ||
|
(!APROC_OK(d->midi) ||
|
||||||
d->midi->u.ctl.tstate != CTL_RUN)) {
|
d->tstate != CTL_RUN)) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (debug_level >= 3) {
|
if (debug_level >= 3) {
|
||||||
dev_dbg(d);
|
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
|
* return the current latency (in frames), ie the latency that
|
||||||
* a stream would have if dev_attach() is called on it.
|
* a stream would have if dev_attach() is called on it.
|
||||||
|
*
|
||||||
|
* XXX: return a "unsigned", since result is always positive, isn't it?
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dev_getpos(struct dev *d)
|
dev_getpos(struct dev *d)
|
||||||
|
@ -1263,3 +1279,453 @@ dev_clear(struct dev *d)
|
||||||
mon_clear(d->mon);
|
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);
|
||||||
|
}
|
||||||
|
|
38
aucat/dev.h
38
aucat/dev.h
|
@ -60,6 +60,32 @@ struct dev {
|
||||||
unsigned mode;
|
unsigned mode;
|
||||||
char *path;
|
char *path;
|
||||||
} *ctl_list;
|
} *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;
|
extern struct dev *dev_list;
|
||||||
|
@ -84,4 +110,16 @@ void dev_attach(struct dev *, char *, unsigned,
|
||||||
unsigned, int);
|
unsigned, int);
|
||||||
void dev_setvol(struct dev *, struct abuf *, 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) */
|
#endif /* !define(DEV_H) */
|
||||||
|
|
|
@ -38,7 +38,7 @@ struct fileops {
|
||||||
void (*close)(struct file *);
|
void (*close)(struct file *);
|
||||||
unsigned (*read)(struct file *, unsigned char *, unsigned);
|
unsigned (*read)(struct file *, unsigned char *, unsigned);
|
||||||
unsigned (*write)(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 *);
|
void (*stop)(struct file *);
|
||||||
int (*nfds)(struct file *);
|
int (*nfds)(struct file *);
|
||||||
int (*pollfd)(struct file *, struct pollfd *, int);
|
int (*pollfd)(struct file *, struct pollfd *, int);
|
||||||
|
|
684
aucat/midi.c
684
aucat/midi.c
|
@ -355,42 +355,6 @@ thru_new(char *name)
|
||||||
return p;
|
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
|
* 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
|
* send a quarter frame MTC message
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ctl_qfr(struct aproc *p)
|
ctl_qfr(struct aproc *p, unsigned rate, int delta)
|
||||||
{
|
{
|
||||||
unsigned char buf[2];
|
unsigned char buf[2];
|
||||||
unsigned data;
|
unsigned data;
|
||||||
|
int qfrlen;
|
||||||
|
|
||||||
switch (p->u.ctl.qfr) {
|
p->u.ctl.delta += delta * MTC_SEC;
|
||||||
case 0:
|
|
||||||
data = p->u.ctl.fr & 0xf;
|
/*
|
||||||
break;
|
* don't send ticks during the count-down
|
||||||
case 1:
|
* XXX: test not useful, given while() condition
|
||||||
data = p->u.ctl.fr >> 4;
|
*/
|
||||||
break;
|
if (p->u.ctl.delta < 0)
|
||||||
case 2:
|
return;
|
||||||
data = p->u.ctl.sec & 0xf;
|
|
||||||
break;
|
qfrlen = rate * (MTC_SEC / (4 * p->u.ctl.fps));
|
||||||
case 3:
|
while (p->u.ctl.delta >= qfrlen) {
|
||||||
data = p->u.ctl.sec >> 4;
|
switch (p->u.ctl.qfr) {
|
||||||
break;
|
case 0:
|
||||||
case 4:
|
data = p->u.ctl.fr & 0xf;
|
||||||
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;
|
break;
|
||||||
p->u.ctl.fr -= p->u.ctl.fps;
|
case 1:
|
||||||
p->u.ctl.sec++;
|
data = p->u.ctl.fr >> 4;
|
||||||
if (p->u.ctl.sec < 60)
|
|
||||||
break;
|
break;
|
||||||
p->u.ctl.sec = 0;
|
case 2:
|
||||||
p->u.ctl.min++;
|
data = p->u.ctl.sec & 0xf;
|
||||||
if (p->u.ctl.min < 60)
|
|
||||||
break;
|
break;
|
||||||
p->u.ctl.min = 0;
|
case 3:
|
||||||
p->u.ctl.hr++;
|
data = p->u.ctl.sec >> 4;
|
||||||
if (p->u.ctl.hr < 24)
|
|
||||||
break;
|
break;
|
||||||
p->u.ctl.hr = 0;
|
case 4:
|
||||||
break;
|
data = p->u.ctl.min & 0xf;
|
||||||
default:
|
break;
|
||||||
/* NOTREACHED */
|
case 5:
|
||||||
data = 0;
|
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
|
* send a full frame MTC message
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ctl_full(struct aproc *p)
|
ctl_full(struct aproc *p, unsigned origin, unsigned rate, unsigned round, unsigned pos)
|
||||||
{
|
{
|
||||||
unsigned char buf[10];
|
unsigned char buf[10];
|
||||||
unsigned origin = p->u.ctl.origin;
|
unsigned fps;
|
||||||
unsigned fps = p->u.ctl.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.hr = (origin / (3600 * MTC_SEC)) % 24;
|
||||||
p->u.ctl.min = (origin / (60 * MTC_SEC)) % 60;
|
p->u.ctl.min = (origin / (60 * MTC_SEC)) % 60;
|
||||||
p->u.ctl.sec = (origin / 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 ctl_slot *s;
|
||||||
struct sysex *x = (struct sysex *)msg;
|
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));
|
memset(x, 0, sizeof(struct sysex));
|
||||||
x->start = SYSEX_START;
|
x->start = SYSEX_START;
|
||||||
x->type = SYSEX_TYPE_EDU;
|
x->type = SYSEX_TYPE_EDU;
|
||||||
|
@ -568,7 +567,7 @@ ctl_msg_vol(struct aproc *p, int slot, char *msg)
|
||||||
{
|
{
|
||||||
struct ctl_slot *s;
|
struct ctl_slot *s;
|
||||||
|
|
||||||
s = p->u.ctl.slot + slot;
|
s = p->u.ctl.dev->slot + slot;
|
||||||
msg[0] = MIDI_CTL | slot;
|
msg[0] = MIDI_CTL | slot;
|
||||||
msg[1] = MIDI_CTLVOL;
|
msg[1] = MIDI_CTLVOL;
|
||||||
msg[2] = s->vol;
|
msg[2] = s->vol;
|
||||||
|
@ -581,7 +580,7 @@ ctl_dump(struct aproc *p, struct abuf *obuf)
|
||||||
unsigned char msg[sizeof(struct sysex)];
|
unsigned char msg[sizeof(struct sysex)];
|
||||||
struct ctl_slot *s;
|
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_msg_info(p, i, msg);
|
||||||
ctl_copymsg(obuf, msg, SYSEX_SIZE(mixinfo));
|
ctl_copymsg(obuf, msg, SYSEX_SIZE(mixinfo));
|
||||||
ctl_msg_vol(p, i, msg);
|
ctl_msg_vol(p, i, msg);
|
||||||
|
@ -597,462 +596,27 @@ ctl_dump(struct aproc *p, struct abuf *obuf)
|
||||||
abuf_flush(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
|
* 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
|
* ctl_slotnew(). Note: it doesn't make sens to call this from within the
|
||||||
* call-back.
|
* call-back.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ctl_slotvol(struct aproc *p, int slot, unsigned vol)
|
ctl_vol(struct aproc *p, int slot, unsigned vol)
|
||||||
{
|
{
|
||||||
unsigned char msg[3];
|
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_msg_vol(p, slot, msg);
|
||||||
ctl_sendmsg(p, NULL, msg, 3);
|
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
|
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))
|
ctl_msg_info(p, slot, msg);
|
||||||
return;
|
ctl_sendmsg(p, NULL, msg, SYSEX_SIZE(mixinfo));
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1083,7 +647,7 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
|
||||||
chan = ibuf->r.midi.msg[0] & MIDI_CHANMASK;
|
chan = ibuf->r.midi.msg[0] & MIDI_CHANMASK;
|
||||||
if (chan >= CTL_NSLOT)
|
if (chan >= CTL_NSLOT)
|
||||||
return;
|
return;
|
||||||
slot = p->u.ctl.slot + chan;
|
slot = p->u.ctl.dev->slot + chan;
|
||||||
slot->vol = ibuf->r.midi.msg[2];
|
slot->vol = ibuf->r.midi.msg[2];
|
||||||
if (slot->ops == NULL)
|
if (slot->ops == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -1110,7 +674,7 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
|
||||||
dbg_puts(": mmc stop\n");
|
dbg_puts(": mmc stop\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ctl_stop(p);
|
dev_mmcstop(p->u.ctl.dev);
|
||||||
break;
|
break;
|
||||||
case SYSEX_MMC_START:
|
case SYSEX_MMC_START:
|
||||||
if (len != SYSEX_SIZE(start))
|
if (len != SYSEX_SIZE(start))
|
||||||
|
@ -1121,7 +685,7 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
|
||||||
dbg_puts(": mmc start\n");
|
dbg_puts(": mmc start\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ctl_start(p);
|
dev_mmcstart(p->u.ctl.dev);
|
||||||
break;
|
break;
|
||||||
case SYSEX_MMC_LOC:
|
case SYSEX_MMC_LOC:
|
||||||
if (len != SYSEX_SIZE(loc) ||
|
if (len != SYSEX_SIZE(loc) ||
|
||||||
|
@ -1139,10 +703,10 @@ ctl_ev(struct aproc *p, struct abuf *ibuf)
|
||||||
fps = 30;
|
fps = 30;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
p->u.ctl.origin = 0;
|
/* XXX: should dev_mmcstop() here */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctl_loc(p,
|
dev_loc(p->u.ctl.dev,
|
||||||
(x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
|
(x->u.loc.hr & 0x1f) * 3600 * MTC_SEC +
|
||||||
x->u.loc.min * 60 * MTC_SEC +
|
x->u.loc.min * 60 * MTC_SEC +
|
||||||
x->u.loc.sec * MTC_SEC +
|
x->u.loc.sec * MTC_SEC +
|
||||||
|
@ -1216,32 +780,14 @@ ctl_out(struct aproc *p, struct abuf *obuf)
|
||||||
void
|
void
|
||||||
ctl_eof(struct aproc *p, struct abuf *ibuf)
|
ctl_eof(struct aproc *p, struct abuf *ibuf)
|
||||||
{
|
{
|
||||||
unsigned i;
|
if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
|
||||||
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))
|
|
||||||
aproc_del(p);
|
aproc_del(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ctl_hup(struct aproc *p, struct abuf *obuf)
|
ctl_hup(struct aproc *p, struct abuf *obuf)
|
||||||
{
|
{
|
||||||
unsigned i;
|
if ((p->flags & APROC_QUIT) && LIST_EMPTY(&p->ins))
|
||||||
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))
|
|
||||||
aproc_del(p);
|
aproc_del(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1254,18 +800,6 @@ ctl_newin(struct aproc *p, struct abuf *ibuf)
|
||||||
ibuf->r.midi.st = 0;
|
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 = {
|
struct aproc_ops ctl_ops = {
|
||||||
"ctl",
|
"ctl",
|
||||||
ctl_in,
|
ctl_in,
|
||||||
|
@ -1276,27 +810,15 @@ struct aproc_ops ctl_ops = {
|
||||||
NULL, /* newout */
|
NULL, /* newout */
|
||||||
NULL, /* ipos */
|
NULL, /* ipos */
|
||||||
NULL, /* opos */
|
NULL, /* opos */
|
||||||
ctl_done
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct aproc *
|
struct aproc *
|
||||||
ctl_new(char *name, struct dev *dev)
|
ctl_new(char *name, struct dev *dev)
|
||||||
{
|
{
|
||||||
struct aproc *p;
|
struct aproc *p;
|
||||||
struct ctl_slot *s;
|
|
||||||
unsigned i;
|
|
||||||
|
|
||||||
p = aproc_new(&ctl_ops, name);
|
p = aproc_new(&ctl_ops, name);
|
||||||
p->u.ctl.dev = dev;
|
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;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
15
aucat/midi.h
15
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 <alex@caoua.org>
|
* Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
|
||||||
*
|
*
|
||||||
|
@ -22,15 +22,10 @@ struct dev;
|
||||||
struct aproc *thru_new(char *);
|
struct aproc *thru_new(char *);
|
||||||
struct aproc *ctl_new(char *, struct dev *);
|
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_ontick(struct aproc *, int);
|
||||||
|
void ctl_slot(struct aproc *, int);
|
||||||
void ctl_stop(struct aproc *);
|
void ctl_vol(struct aproc *, int, unsigned);
|
||||||
void ctl_start(struct aproc *);
|
void ctl_full(struct aproc *, unsigned, unsigned, unsigned, unsigned);
|
||||||
int ctl_idle(struct aproc *);
|
void ctl_qfr(struct aproc *, unsigned, int);
|
||||||
|
|
||||||
#endif /* !defined(MIDI_H) */
|
#endif /* !defined(MIDI_H) */
|
||||||
|
|
|
@ -42,6 +42,8 @@ struct siofile {
|
||||||
unsigned rtickets, rbpf;
|
unsigned rtickets, rbpf;
|
||||||
unsigned bufsz;
|
unsigned bufsz;
|
||||||
int started;
|
int started;
|
||||||
|
void (*onmove)(void *, int);
|
||||||
|
void *arg;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
long long wtime, utime;
|
long long wtime, utime;
|
||||||
#endif
|
#endif
|
||||||
|
@ -50,7 +52,7 @@ struct siofile {
|
||||||
void siofile_close(struct file *);
|
void siofile_close(struct file *);
|
||||||
unsigned siofile_read(struct file *, unsigned char *, unsigned);
|
unsigned siofile_read(struct file *, unsigned char *, unsigned);
|
||||||
unsigned siofile_write(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 *);
|
void siofile_stop(struct file *);
|
||||||
int siofile_nfds(struct file *);
|
int siofile_nfds(struct file *);
|
||||||
int siofile_pollfd(struct file *, struct pollfd *, int);
|
int siofile_pollfd(struct file *, struct pollfd *, int);
|
||||||
|
@ -189,12 +191,12 @@ siofile_cb(void *addr, int delta)
|
||||||
p = f->file.wproc;
|
p = f->file.wproc;
|
||||||
if (p && p->ops->opos)
|
if (p && p->ops->opos)
|
||||||
p->ops->opos(p, NULL, delta);
|
p->ops->opos(p, NULL, delta);
|
||||||
}
|
|
||||||
if (delta != 0) {
|
|
||||||
p = f->file.rproc;
|
p = f->file.rproc;
|
||||||
if (p && p->ops->ipos)
|
if (p && p->ops->ipos)
|
||||||
p->ops->ipos(p, NULL, delta);
|
p->ops->ipos(p, NULL, delta);
|
||||||
}
|
}
|
||||||
|
if (f->onmove)
|
||||||
|
f->onmove(f->arg, delta);
|
||||||
f->wtickets += delta * f->wbpf;
|
f->wtickets += delta * f->wbpf;
|
||||||
f->rtickets += delta * f->rbpf;
|
f->rtickets += delta * f->rbpf;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +307,7 @@ siofile_new(struct fileops *ops, char *path, unsigned *rmode,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
siofile_start(struct file *file)
|
siofile_start(struct file *file, void (*cb)(void *, int), void *arg)
|
||||||
{
|
{
|
||||||
struct siofile *f = (struct siofile *)file;
|
struct siofile *f = (struct siofile *)file;
|
||||||
|
|
||||||
|
@ -328,6 +330,8 @@ siofile_start(struct file *file)
|
||||||
dbg_puts(": started\n");
|
dbg_puts(": started\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
f->onmove = cb;
|
||||||
|
f->arg = arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -336,6 +340,7 @@ siofile_stop(struct file *file)
|
||||||
struct siofile *f = (struct siofile *)file;
|
struct siofile *f = (struct siofile *)file;
|
||||||
|
|
||||||
f->started = 0;
|
f->started = 0;
|
||||||
|
f->onmove = NULL;
|
||||||
if (!sio_eof(f->hdl) && !sio_stop(f->hdl)) {
|
if (!sio_eof(f->hdl) && !sio_stop(f->hdl)) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
dbg_puts(f->file.name);
|
dbg_puts(f->file.name);
|
||||||
|
|
37
aucat/sock.c
37
aucat/sock.c
|
@ -62,12 +62,10 @@ sock_dbg(struct sock *f)
|
||||||
};
|
};
|
||||||
static char *rstates[] = { "rdat", "rmsg", "rret" };
|
static char *rstates[] = { "rdat", "rmsg", "rret" };
|
||||||
static char *wstates[] = { "widl", "wmsg", "wdat" };
|
static char *wstates[] = { "widl", "wmsg", "wdat" };
|
||||||
struct aproc *midi;
|
|
||||||
|
|
||||||
midi = f->dev ? f->dev->midi : NULL;
|
if (f->slot >= 0) {
|
||||||
if (f->slot >= 0 && APROC_OK(midi)) {
|
dbg_puts(f->dev->slot[f->slot].name);
|
||||||
dbg_puts(midi->u.ctl.slot[f->slot].name);
|
dbg_putu(f->dev->slot[f->slot].unit);
|
||||||
dbg_putu(midi->u.ctl.slot[f->slot].unit);
|
|
||||||
} else
|
} else
|
||||||
dbg_puts(f->pipe.file.name);
|
dbg_puts(f->pipe.file.name);
|
||||||
dbg_puts("/");
|
dbg_puts("/");
|
||||||
|
@ -121,7 +119,7 @@ rsock_done(struct aproc *p)
|
||||||
f->pipe.file.rproc = NULL;
|
f->pipe.file.rproc = NULL;
|
||||||
if (f->pipe.file.wproc) {
|
if (f->pipe.file.wproc) {
|
||||||
if (f->slot >= 0)
|
if (f->slot >= 0)
|
||||||
ctl_slotdel(f->dev->midi, f->slot);
|
dev_slotdel(f->dev, f->slot);
|
||||||
aproc_del(f->pipe.file.wproc);
|
aproc_del(f->pipe.file.wproc);
|
||||||
file_del(&f->pipe.file);
|
file_del(&f->pipe.file);
|
||||||
}
|
}
|
||||||
|
@ -226,7 +224,7 @@ wsock_done(struct aproc *p)
|
||||||
f->pipe.file.wproc = NULL;
|
f->pipe.file.wproc = NULL;
|
||||||
if (f->pipe.file.rproc) {
|
if (f->pipe.file.rproc) {
|
||||||
if (f->slot >= 0)
|
if (f->slot >= 0)
|
||||||
ctl_slotdel(f->dev->midi, f->slot);
|
dev_slotdel(f->dev, f->slot);
|
||||||
aproc_del(f->pipe.file.rproc);
|
aproc_del(f->pipe.file.rproc);
|
||||||
file_del(&f->pipe.file);
|
file_del(&f->pipe.file);
|
||||||
}
|
}
|
||||||
|
@ -375,7 +373,7 @@ sock_freebuf(struct sock *f)
|
||||||
wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
|
wbuf = LIST_FIRST(&f->pipe.file.wproc->ins);
|
||||||
rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
|
rbuf = LIST_FIRST(&f->pipe.file.rproc->outs);
|
||||||
if (rbuf || wbuf)
|
if (rbuf || wbuf)
|
||||||
ctl_slotstop(f->dev->midi, f->slot);
|
dev_slotstop(f->dev, f->slot);
|
||||||
if (rbuf)
|
if (rbuf)
|
||||||
abuf_eof(rbuf);
|
abuf_eof(rbuf);
|
||||||
if (wbuf)
|
if (wbuf)
|
||||||
|
@ -428,7 +426,7 @@ sock_allocbuf(struct sock *f)
|
||||||
f->pstate = SOCK_START;
|
f->pstate = SOCK_START;
|
||||||
} else {
|
} else {
|
||||||
f->pstate = SOCK_READY;
|
f->pstate = SOCK_READY;
|
||||||
if (ctl_slotstart(f->dev->midi, f->slot))
|
if (dev_slotstart(f->dev, f->slot))
|
||||||
(void)sock_attach(f, 0);
|
(void)sock_attach(f, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,7 +584,7 @@ sock_reset(struct sock *f)
|
||||||
switch (f->pstate) {
|
switch (f->pstate) {
|
||||||
case SOCK_START:
|
case SOCK_START:
|
||||||
case SOCK_READY:
|
case SOCK_READY:
|
||||||
if (ctl_slotstart(f->dev->midi, f->slot)) {
|
if (dev_slotstart(f->dev, f->slot)) {
|
||||||
(void)sock_attach(f, 1);
|
(void)sock_attach(f, 1);
|
||||||
f->pstate = SOCK_RUN;
|
f->pstate = SOCK_RUN;
|
||||||
}
|
}
|
||||||
|
@ -926,11 +924,8 @@ sock_setpar(struct sock *f)
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (debug_level >= 2) {
|
if (debug_level >= 2) {
|
||||||
if (APROC_OK(f->dev->midi)) {
|
dbg_puts(f->dev->slot[f->slot].name);
|
||||||
dbg_puts(f->dev->midi->u.ctl.slot[f->slot].name);
|
dbg_putu(f->dev->slot[f->slot].unit);
|
||||||
dbg_putu(f->dev->midi->u.ctl.slot[f->slot].unit);
|
|
||||||
} else
|
|
||||||
dbg_puts(f->pipe.file.name);
|
|
||||||
dbg_puts(": buffer size = ");
|
dbg_puts(": buffer size = ");
|
||||||
dbg_putu(f->bufsz);
|
dbg_putu(f->bufsz);
|
||||||
if (f->mode & MODE_PLAY) {
|
if (f->mode & MODE_PLAY) {
|
||||||
|
@ -1082,9 +1077,7 @@ sock_hello(struct sock *f)
|
||||||
f->xrun = (f->opt->mmc) ? XRUN_SYNC : XRUN_IGNORE;
|
f->xrun = (f->opt->mmc) ? XRUN_SYNC : XRUN_IGNORE;
|
||||||
f->bufsz = f->dev->bufsz;
|
f->bufsz = f->dev->bufsz;
|
||||||
f->round = f->dev->round;
|
f->round = f->dev->round;
|
||||||
f->slot = ctl_slotnew(f->dev->midi, p->who,
|
f->slot = dev_slotnew(f->dev, p->who, &ctl_sockops, f, f->opt->mmc);
|
||||||
&ctl_sockops, f,
|
|
||||||
f->opt->mmc);
|
|
||||||
if (f->slot < 0)
|
if (f->slot < 0)
|
||||||
return 0;
|
return 0;
|
||||||
f->pstate = SOCK_INIT;
|
f->pstate = SOCK_INIT;
|
||||||
|
@ -1225,7 +1218,7 @@ sock_execmsg(struct sock *f)
|
||||||
* see how this is fixed in wav.c
|
* see how this is fixed in wav.c
|
||||||
*/
|
*/
|
||||||
if ((f->pstate == SOCK_START || f->pstate == SOCK_READY) &&
|
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);
|
(void)sock_attach(f, 1);
|
||||||
if (f->wstate != SOCK_WDATA || f->wtodo == 0)
|
if (f->wstate != SOCK_WDATA || f->wtodo == 0)
|
||||||
sock_freebuf(f);
|
sock_freebuf(f);
|
||||||
|
@ -1336,7 +1329,7 @@ sock_execmsg(struct sock *f)
|
||||||
}
|
}
|
||||||
sock_setvol(f, ctl);
|
sock_setvol(f, ctl);
|
||||||
if (f->slot >= 0)
|
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->rtodo = sizeof(struct amsg);
|
||||||
f->rstate = SOCK_RMSG;
|
f->rstate = SOCK_RMSG;
|
||||||
break;
|
break;
|
||||||
|
@ -1585,10 +1578,10 @@ sock_read(struct sock *f)
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* XXX: sock_attach() may not start if there's not enough
|
* 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.
|
* 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);
|
(void)sock_attach(f, 0);
|
||||||
break;
|
break;
|
||||||
case SOCK_RRET:
|
case SOCK_RRET:
|
||||||
|
|
25
aucat/wav.c
25
aucat/wav.c
|
@ -185,12 +185,11 @@ void
|
||||||
wav_dbg(struct wav *f)
|
wav_dbg(struct wav *f)
|
||||||
{
|
{
|
||||||
static char *pstates[] = { "cfg", "ini", "sta", "rdy", "run", "mid" };
|
static char *pstates[] = { "cfg", "ini", "sta", "rdy", "run", "mid" };
|
||||||
struct aproc *midi = f->dev ? f->dev->midi : NULL;
|
|
||||||
|
|
||||||
dbg_puts("wav(");
|
dbg_puts("wav(");
|
||||||
if (f->slot >= 0 && APROC_OK(midi)) {
|
if (f->slot >= 0) {
|
||||||
dbg_puts(midi->u.ctl.slot[f->slot].name);
|
dbg_puts(f->dev->slot[f->slot].name);
|
||||||
dbg_putu(midi->u.ctl.slot[f->slot].unit);
|
dbg_putu(f->dev->slot[f->slot].unit);
|
||||||
} else
|
} else
|
||||||
dbg_puts(f->pipe.file.name);
|
dbg_puts(f->pipe.file.name);
|
||||||
dbg_puts(")/");
|
dbg_puts(")/");
|
||||||
|
@ -407,7 +406,7 @@ wav_allocbuf(struct wav *f)
|
||||||
dbg_puts(": allocating buffers\n");
|
dbg_puts(": allocating buffers\n");
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
(void)wav_attach(f, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +430,7 @@ wav_freebuf(struct wav *f)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (rbuf || wbuf)
|
if (rbuf || wbuf)
|
||||||
ctl_slotstop(f->dev->midi, f->slot);
|
dev_slotstop(f->dev, f->slot);
|
||||||
if (rbuf)
|
if (rbuf)
|
||||||
abuf_eof(rbuf);
|
abuf_eof(rbuf);
|
||||||
if (wbuf)
|
if (wbuf)
|
||||||
|
@ -448,7 +447,7 @@ wav_reset(struct wav *f)
|
||||||
switch (f->pstate) {
|
switch (f->pstate) {
|
||||||
case WAV_START:
|
case WAV_START:
|
||||||
case WAV_READY:
|
case WAV_READY:
|
||||||
if (ctl_slotstart(f->dev->midi, f->slot))
|
if (dev_slotstart(f->dev, f->slot))
|
||||||
(void)wav_attach(f, 1);
|
(void)wav_attach(f, 1);
|
||||||
/* PASSTHROUGH */
|
/* PASSTHROUGH */
|
||||||
case WAV_RUN:
|
case WAV_RUN:
|
||||||
|
@ -493,7 +492,7 @@ wav_init(struct wav *f)
|
||||||
wav_midiattach(f);
|
wav_midiattach(f);
|
||||||
return 1;
|
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;
|
f->pstate = WAV_INIT;
|
||||||
if ((f->mode & f->dev->mode) != f->mode) {
|
if ((f->mode & f->dev->mode) != f->mode) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -527,14 +526,14 @@ wav_seekmmc(struct wav *f)
|
||||||
* don't make other stream wait for us
|
* don't make other stream wait for us
|
||||||
*/
|
*/
|
||||||
if (f->slot >= 0)
|
if (f->slot >= 0)
|
||||||
ctl_slotstart(f->dev->midi, f->slot);
|
dev_slotstart(f->dev, f->slot);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
|
if (!pipe_seek(&f->pipe.file, f->mmcpos)) {
|
||||||
wav_exit(f);
|
wav_exit(f);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (f->mode & MODE_RECMASK)
|
if ((f->mode & MODE_RECMASK) && f->mmcpos > f->endpos)
|
||||||
f->endpos = f->mmcpos;
|
f->endpos = f->mmcpos;
|
||||||
if (f->hdr == HDR_WAV)
|
if (f->hdr == HDR_WAV)
|
||||||
f->wbytes = WAV_DATAMAX - f->mmcpos;
|
f->wbytes = WAV_DATAMAX - f->mmcpos;
|
||||||
|
@ -567,7 +566,7 @@ wav_rdata(struct wav *f)
|
||||||
f->pstate = WAV_READY;
|
f->pstate = WAV_READY;
|
||||||
/* PASSTHROUGH */
|
/* PASSTHROUGH */
|
||||||
case WAV_READY:
|
case WAV_READY:
|
||||||
if (ctl_slotstart(f->dev->midi, f->slot))
|
if (dev_slotstart(f->dev, f->slot))
|
||||||
(void)wav_attach(f, 0);
|
(void)wav_attach(f, 0);
|
||||||
break;
|
break;
|
||||||
case WAV_RUN:
|
case WAV_RUN:
|
||||||
|
@ -928,7 +927,7 @@ rwav_done(struct aproc *p)
|
||||||
struct wav *f = (struct wav *)p->u.io.file;
|
struct wav *f = (struct wav *)p->u.io.file;
|
||||||
|
|
||||||
if (f->slot >= 0)
|
if (f->slot >= 0)
|
||||||
ctl_slotdel(f->dev->midi, f->slot);
|
dev_slotdel(f->dev, f->slot);
|
||||||
f->slot = -1;
|
f->slot = -1;
|
||||||
rfile_done(p);
|
rfile_done(p);
|
||||||
}
|
}
|
||||||
|
@ -981,7 +980,7 @@ wwav_done(struct aproc *p)
|
||||||
struct wav *f = (struct wav *)p->u.io.file;
|
struct wav *f = (struct wav *)p->u.io.file;
|
||||||
|
|
||||||
if (f->slot >= 0)
|
if (f->slot >= 0)
|
||||||
ctl_slotdel(f->dev->midi, f->slot);
|
dev_slotdel(f->dev, f->slot);
|
||||||
f->slot = -1;
|
f->slot = -1;
|
||||||
wfile_done(p);
|
wfile_done(p);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue