mirror of https://github.com/ericonr/sndio.git
Merge branch 'master' into mixer
This commit is contained in:
commit
5536f474fe
228
sndiod/dev.c
228
sndiod/dev.c
|
@ -58,10 +58,10 @@ int dev_getpos(struct dev *);
|
||||||
struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
|
struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
|
||||||
unsigned int, unsigned int, unsigned int, unsigned int);
|
unsigned int, unsigned int, unsigned int, unsigned int);
|
||||||
void dev_adjpar(struct dev *, int, int, int);
|
void dev_adjpar(struct dev *, int, int, int);
|
||||||
int dev_open_do(struct dev *);
|
int dev_allocbufs(struct dev *);
|
||||||
int dev_open(struct dev *);
|
int dev_open(struct dev *);
|
||||||
void dev_exitall(struct dev *);
|
void dev_exitall(struct dev *);
|
||||||
void dev_close_do(struct dev *);
|
void dev_freebufs(struct dev *);
|
||||||
void dev_close(struct dev *);
|
void dev_close(struct dev *);
|
||||||
int dev_ref(struct dev *);
|
int dev_ref(struct dev *);
|
||||||
void dev_unref(struct dev *);
|
void dev_unref(struct dev *);
|
||||||
|
@ -83,6 +83,7 @@ void slot_attach(struct slot *);
|
||||||
void slot_ready(struct slot *);
|
void slot_ready(struct slot *);
|
||||||
void slot_allocbufs(struct slot *);
|
void slot_allocbufs(struct slot *);
|
||||||
void slot_freebufs(struct slot *);
|
void slot_freebufs(struct slot *);
|
||||||
|
void slot_initconv(struct slot *);
|
||||||
void slot_start(struct slot *);
|
void slot_start(struct slot *);
|
||||||
void slot_detach(struct slot *);
|
void slot_detach(struct slot *);
|
||||||
void slot_stop(struct slot *);
|
void slot_stop(struct slot *);
|
||||||
|
@ -1047,15 +1048,8 @@ dev_adjpar(struct dev *d, int mode,
|
||||||
* monitor, midi control, and any necessary conversions.
|
* monitor, midi control, and any necessary conversions.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dev_open_do(struct dev *d)
|
dev_allocbufs(struct dev *d)
|
||||||
{
|
{
|
||||||
if (!dev_sio_open(d)) {
|
|
||||||
if (log_level >= 1) {
|
|
||||||
dev_log(d);
|
|
||||||
log_puts(": failed to open audio device\n");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (d->mode & MODE_REC) {
|
if (d->mode & MODE_REC) {
|
||||||
/*
|
/*
|
||||||
* Create device <-> demuxer buffer
|
* Create device <-> demuxer buffer
|
||||||
|
@ -1089,7 +1083,6 @@ dev_open_do(struct dev *d)
|
||||||
} else
|
} else
|
||||||
d->encbuf = NULL;
|
d->encbuf = NULL;
|
||||||
}
|
}
|
||||||
d->pstate = DEV_INIT;
|
|
||||||
if (log_level >= 2) {
|
if (log_level >= 2) {
|
||||||
dev_log(d);
|
dev_log(d);
|
||||||
log_puts(": ");
|
log_puts(": ");
|
||||||
|
@ -1133,9 +1126,15 @@ dev_open(struct dev *d)
|
||||||
d->pchan = 2;
|
d->pchan = 2;
|
||||||
if (d->rchan == 0)
|
if (d->rchan == 0)
|
||||||
d->rchan = 2;
|
d->rchan = 2;
|
||||||
if (!dev_open_do(d))
|
if (!dev_sio_open(d)) {
|
||||||
|
if (log_level >= 1) {
|
||||||
|
dev_log(d);
|
||||||
|
log_puts(": failed to open audio device\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!dev_allocbufs(d))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we use the "sndiod" group name. find a unused
|
* we use the "sndiod" group name. find a unused
|
||||||
|
@ -1163,6 +1162,8 @@ dev_open(struct dev *d)
|
||||||
}
|
}
|
||||||
dev_addctl(d, "sndiod", gunit, CTL_NUM,
|
dev_addctl(d, "sndiod", gunit, CTL_NUM,
|
||||||
CTLADDR_MASTER, "master", -1, "level", NULL, -1, d->master);
|
CTLADDR_MASTER, "master", -1, "level", NULL, -1, d->master);
|
||||||
|
|
||||||
|
d->pstate = DEV_INIT;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1195,31 +1196,14 @@ dev_exitall(struct dev *d)
|
||||||
* ensure buffers are drained
|
* ensure buffers are drained
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
dev_close_do(struct dev *d)
|
dev_freebufs(struct dev *d)
|
||||||
{
|
{
|
||||||
struct ctl *c, **pc;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (log_level >= 3) {
|
if (log_level >= 3) {
|
||||||
dev_log(d);
|
dev_log(d);
|
||||||
log_puts(": closing\n");
|
log_puts(": closing\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pc = &d->ctl_list;
|
|
||||||
while ((c = *pc) != NULL) {
|
|
||||||
if (c->addr >= CTLADDR_END) {
|
|
||||||
if (c->refs_mask == 0) {
|
|
||||||
*pc = c->next;
|
|
||||||
xfree(c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
c->type = CTL_NONE;
|
|
||||||
c->desc_mask = ~0;
|
|
||||||
}
|
|
||||||
pc = &c->next;
|
|
||||||
}
|
|
||||||
d->pstate = DEV_CFG;
|
|
||||||
dev_sio_close(d);
|
|
||||||
if (d->mode & MODE_PLAY) {
|
if (d->mode & MODE_PLAY) {
|
||||||
if (d->encbuf != NULL)
|
if (d->encbuf != NULL)
|
||||||
xfree(d->encbuf);
|
xfree(d->encbuf);
|
||||||
|
@ -1241,7 +1225,9 @@ dev_close(struct dev *d)
|
||||||
struct ctl *c;
|
struct ctl *c;
|
||||||
|
|
||||||
dev_exitall(d);
|
dev_exitall(d);
|
||||||
dev_close_do(d);
|
d->pstate = DEV_CFG;
|
||||||
|
dev_sio_close(d);
|
||||||
|
dev_freebufs(d);
|
||||||
|
|
||||||
/* there are no clients, just free remaining local controls */
|
/* there are no clients, just free remaining local controls */
|
||||||
while ((c = d->ctl_list) != NULL) {
|
while ((c = d->ctl_list) != NULL) {
|
||||||
|
@ -1254,67 +1240,43 @@ dev_close(struct dev *d)
|
||||||
* Close the device, but attempt to migrate everything to a new sndio
|
* Close the device, but attempt to migrate everything to a new sndio
|
||||||
* device.
|
* device.
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
dev_reopen(struct dev *d)
|
dev_reopen(struct dev *d)
|
||||||
{
|
{
|
||||||
struct slot *s;
|
struct slot *s;
|
||||||
|
struct ctl *c, **pc;
|
||||||
long long pos;
|
long long pos;
|
||||||
unsigned int mode, round, bufsz, rate, pstate;
|
unsigned int pstate;
|
||||||
int delta;
|
int delta;
|
||||||
|
|
||||||
/* not opened */
|
/* not opened */
|
||||||
if (d->pstate == DEV_CFG)
|
if (d->pstate == DEV_CFG)
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
if (log_level >= 1) {
|
|
||||||
dev_log(d);
|
|
||||||
log_puts(": reopening device\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save state */
|
/* save state */
|
||||||
mode = d->mode;
|
|
||||||
round = d->round;
|
|
||||||
bufsz = d->bufsz;
|
|
||||||
rate = d->rate;
|
|
||||||
delta = d->delta;
|
delta = d->delta;
|
||||||
pstate = d->pstate;
|
pstate = d->pstate;
|
||||||
|
|
||||||
/* close device */
|
if (!dev_sio_reopen(d))
|
||||||
dev_close_do(d);
|
return 0;
|
||||||
|
|
||||||
/* open device */
|
/* reopen returns a stopped device */
|
||||||
if (!dev_open_do(d)) {
|
d->pstate = DEV_INIT;
|
||||||
if (log_level >= 1) {
|
|
||||||
dev_log(d);
|
|
||||||
log_puts(": found no working alternate device\n");
|
|
||||||
}
|
|
||||||
dev_exitall(d);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if new parameters are compatible with old ones */
|
/* reallocate new buffers, with new parameters */
|
||||||
if (d->mode != mode ||
|
dev_freebufs(d);
|
||||||
d->round != round ||
|
dev_allocbufs(d);
|
||||||
d->bufsz != bufsz ||
|
|
||||||
d->rate != rate) {
|
|
||||||
if (log_level >= 1) {
|
|
||||||
dev_log(d);
|
|
||||||
log_puts(": alternate device not compatible\n");
|
|
||||||
}
|
|
||||||
dev_close(d);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* adjust time positions, make anything go back delta ticks, so
|
* adjust time positions, make anything go back delta ticks, so
|
||||||
* that the new device can start at zero
|
* that the new device can start at zero
|
||||||
*/
|
*/
|
||||||
for (s = d->slot_list; s != NULL; s = s->next) {
|
for (s = d->slot_list; s != NULL; s = s->next) {
|
||||||
pos = (long long)(d->round - delta) * s->round + s->delta_rem;
|
pos = (long long)s->delta * d->round + s->delta_rem;
|
||||||
s->delta_rem = pos % d->round;
|
pos -= (long long)delta * s->round;
|
||||||
s->delta += pos / (int)d->round;
|
s->delta_rem = pos % (int)d->round;
|
||||||
s->delta -= s->round;
|
s->delta = pos / (int)d->round;
|
||||||
if (log_level >= 2) {
|
if (log_level >= 3) {
|
||||||
slot_log(s);
|
slot_log(s);
|
||||||
log_puts(": adjusted: delta -> ");
|
log_puts(": adjusted: delta -> ");
|
||||||
log_puti(s->delta);
|
log_puti(s->delta);
|
||||||
|
@ -1322,6 +1284,9 @@ dev_reopen(struct dev *d)
|
||||||
log_puti(s->delta_rem);
|
log_puti(s->delta_rem);
|
||||||
log_puts("\n");
|
log_puts("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reinitilize the format conversion chain */
|
||||||
|
slot_initconv(s);
|
||||||
}
|
}
|
||||||
if (d->tstate == MMC_RUN) {
|
if (d->tstate == MMC_RUN) {
|
||||||
d->mtc.delta -= delta * MTC_SEC;
|
d->mtc.delta -= delta * MTC_SEC;
|
||||||
|
@ -1333,9 +1298,29 @@ dev_reopen(struct dev *d)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* remove controls of old device */
|
||||||
|
pc = &d->ctl_list;
|
||||||
|
while ((c = *pc) != NULL) {
|
||||||
|
if (c->addr >= CTLADDR_END) {
|
||||||
|
if (c->refs_mask == 0) {
|
||||||
|
*pc = c->next;
|
||||||
|
xfree(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
c->type = CTL_NONE;
|
||||||
|
c->desc_mask = ~0;
|
||||||
|
}
|
||||||
|
pc = &c->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add new device controls */
|
||||||
|
dev_siomix_open(d);
|
||||||
|
|
||||||
/* start the device if needed */
|
/* start the device if needed */
|
||||||
if (pstate == DEV_RUN)
|
if (pstate == DEV_RUN)
|
||||||
dev_wakeup(d);
|
dev_wakeup(d);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1591,31 +1576,15 @@ dev_mmcloc(struct dev *d, unsigned int origin)
|
||||||
dev_mmcstart(d);
|
dev_mmcstart(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* allocate buffers & conversion chain
|
* allocate buffers & conversion chain
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
slot_allocbufs(struct slot *s)
|
slot_initconv(struct slot *s)
|
||||||
{
|
{
|
||||||
unsigned int dev_nch;
|
|
||||||
struct dev *d = s->dev;
|
struct dev *d = s->dev;
|
||||||
|
|
||||||
if (s->mode & MODE_PLAY) {
|
if (s->mode & MODE_PLAY) {
|
||||||
s->mix.bpf = s->par.bps * s->mix.nch;
|
|
||||||
abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
|
|
||||||
|
|
||||||
dev_nch = s->opt->pmax - s->opt->pmin + 1;
|
|
||||||
s->mix.decbuf = NULL;
|
|
||||||
s->mix.resampbuf = NULL;
|
|
||||||
s->mix.join = 1;
|
|
||||||
s->mix.expand = 1;
|
|
||||||
if (s->opt->dup) {
|
|
||||||
if (dev_nch > s->mix.nch)
|
|
||||||
s->mix.expand = dev_nch / s->mix.nch;
|
|
||||||
else if (dev_nch < s->mix.nch)
|
|
||||||
s->mix.join = s->mix.nch / dev_nch;
|
|
||||||
}
|
|
||||||
cmap_init(&s->mix.cmap,
|
cmap_init(&s->mix.cmap,
|
||||||
s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
|
s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
|
||||||
s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
|
s->opt->pmin, s->opt->pmin + s->mix.nch - 1,
|
||||||
|
@ -1623,32 +1592,22 @@ slot_allocbufs(struct slot *s)
|
||||||
s->opt->pmin, s->opt->pmax);
|
s->opt->pmin, s->opt->pmax);
|
||||||
if (!aparams_native(&s->par)) {
|
if (!aparams_native(&s->par)) {
|
||||||
dec_init(&s->mix.dec, &s->par, s->mix.nch);
|
dec_init(&s->mix.dec, &s->par, s->mix.nch);
|
||||||
s->mix.decbuf =
|
|
||||||
xmalloc(s->round * s->mix.nch * sizeof(adata_t));
|
|
||||||
}
|
}
|
||||||
if (s->rate != d->rate) {
|
if (s->rate != d->rate) {
|
||||||
resamp_init(&s->mix.resamp, s->round, d->round,
|
resamp_init(&s->mix.resamp, s->round, d->round,
|
||||||
s->mix.nch);
|
s->mix.nch);
|
||||||
s->mix.resampbuf =
|
}
|
||||||
xmalloc(d->round * s->mix.nch * sizeof(adata_t));
|
s->mix.join = 1;
|
||||||
|
s->mix.expand = 1;
|
||||||
|
if (s->opt->dup) {
|
||||||
|
if (s->mix.cmap.nch > s->mix.nch)
|
||||||
|
s->mix.expand = s->mix.cmap.nch / s->mix.nch;
|
||||||
|
else if (s->mix.cmap.nch > 0)
|
||||||
|
s->mix.join = s->mix.nch / s->mix.cmap.nch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->mode & MODE_RECMASK) {
|
if (s->mode & MODE_RECMASK) {
|
||||||
s->sub.bpf = s->par.bps * s->sub.nch;
|
|
||||||
abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
|
|
||||||
|
|
||||||
dev_nch = s->opt->rmax - s->opt->rmin + 1;
|
|
||||||
s->sub.encbuf = NULL;
|
|
||||||
s->sub.resampbuf = NULL;
|
|
||||||
s->sub.join = 1;
|
|
||||||
s->sub.expand = 1;
|
|
||||||
if (s->opt->dup) {
|
|
||||||
if (dev_nch > s->sub.nch)
|
|
||||||
s->sub.join = dev_nch / s->sub.nch;
|
|
||||||
else if (dev_nch < s->sub.nch)
|
|
||||||
s->sub.expand = s->sub.nch / dev_nch;
|
|
||||||
}
|
|
||||||
cmap_init(&s->sub.cmap,
|
cmap_init(&s->sub.cmap,
|
||||||
0, ((s->mode & MODE_MON) ? d->pchan : d->rchan) - 1,
|
0, ((s->mode & MODE_MON) ? d->pchan : d->rchan) - 1,
|
||||||
s->opt->rmin, s->opt->rmax,
|
s->opt->rmin, s->opt->rmax,
|
||||||
|
@ -1657,13 +1616,17 @@ slot_allocbufs(struct slot *s)
|
||||||
if (s->rate != d->rate) {
|
if (s->rate != d->rate) {
|
||||||
resamp_init(&s->sub.resamp, d->round, s->round,
|
resamp_init(&s->sub.resamp, d->round, s->round,
|
||||||
s->sub.nch);
|
s->sub.nch);
|
||||||
s->sub.resampbuf =
|
|
||||||
xmalloc(d->round * s->sub.nch * sizeof(adata_t));
|
|
||||||
}
|
}
|
||||||
if (!aparams_native(&s->par)) {
|
if (!aparams_native(&s->par)) {
|
||||||
enc_init(&s->sub.enc, &s->par, s->sub.nch);
|
enc_init(&s->sub.enc, &s->par, s->sub.nch);
|
||||||
s->sub.encbuf =
|
}
|
||||||
xmalloc(s->round * s->sub.nch * sizeof(adata_t));
|
s->sub.join = 1;
|
||||||
|
s->sub.expand = 1;
|
||||||
|
if (s->opt->dup) {
|
||||||
|
if (s->sub.cmap.nch > s->sub.nch)
|
||||||
|
s->sub.join = s->sub.cmap.nch / s->sub.nch;
|
||||||
|
else if (s->sub.cmap.nch > 0)
|
||||||
|
s->sub.expand = s->sub.nch / s->sub.cmap.nch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1683,6 +1646,49 @@ slot_allocbufs(struct slot *s)
|
||||||
s->appbufsz * s->sub.nch * sizeof(adata_t));
|
s->appbufsz * s->sub.nch * sizeof(adata_t));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* allocate buffers & conversion chain
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
slot_allocbufs(struct slot *s)
|
||||||
|
{
|
||||||
|
struct dev *d = s->dev;
|
||||||
|
|
||||||
|
if (s->mode & MODE_PLAY) {
|
||||||
|
s->mix.bpf = s->par.bps * s->mix.nch;
|
||||||
|
abuf_init(&s->mix.buf, s->appbufsz * s->mix.bpf);
|
||||||
|
|
||||||
|
s->mix.decbuf = NULL;
|
||||||
|
s->mix.resampbuf = NULL;
|
||||||
|
if (!aparams_native(&s->par)) {
|
||||||
|
s->mix.decbuf =
|
||||||
|
xmalloc(s->round * s->mix.nch * sizeof(adata_t));
|
||||||
|
}
|
||||||
|
if (s->rate != d->rate) {
|
||||||
|
s->mix.resampbuf =
|
||||||
|
xmalloc(d->round * s->mix.nch * sizeof(adata_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->mode & MODE_RECMASK) {
|
||||||
|
s->sub.bpf = s->par.bps * s->sub.nch;
|
||||||
|
abuf_init(&s->sub.buf, s->appbufsz * s->sub.bpf);
|
||||||
|
|
||||||
|
s->sub.encbuf = NULL;
|
||||||
|
s->sub.resampbuf = NULL;
|
||||||
|
if (s->rate != d->rate) {
|
||||||
|
s->sub.resampbuf =
|
||||||
|
xmalloc(d->round * s->sub.nch * sizeof(adata_t));
|
||||||
|
}
|
||||||
|
if (!aparams_native(&s->par)) {
|
||||||
|
s->sub.encbuf =
|
||||||
|
xmalloc(s->round * s->sub.nch * sizeof(adata_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slot_initconv(s);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (log_level >= 3) {
|
if (log_level >= 3) {
|
||||||
|
|
|
@ -254,7 +254,7 @@ extern struct dev *dev_list;
|
||||||
|
|
||||||
void dev_log(struct dev *);
|
void dev_log(struct dev *);
|
||||||
void dev_close(struct dev *);
|
void dev_close(struct dev *);
|
||||||
void dev_reopen(struct dev *);
|
int dev_reopen(struct dev *);
|
||||||
struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
|
struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
|
||||||
unsigned int, unsigned int, unsigned int, unsigned int);
|
unsigned int, unsigned int, unsigned int, unsigned int);
|
||||||
struct dev *dev_bynum(int);
|
struct dev *dev_bynum(int);
|
||||||
|
|
|
@ -95,14 +95,13 @@ dev_siomix_onctl(void *arg, unsigned int addr, unsigned int val)
|
||||||
* open the mixer device.
|
* open the mixer device.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
dev_siomix_open(struct dev *d, char *path)
|
dev_siomix_open(struct dev *d)
|
||||||
{
|
{
|
||||||
d->siomix.hdl = siomix_open(path, SIOMIX_READ | SIOMIX_WRITE, 0);
|
|
||||||
if (d->siomix.hdl == NULL)
|
if (d->siomix.hdl == NULL)
|
||||||
return;
|
return;
|
||||||
siomix_ondesc(d->siomix.hdl, dev_siomix_ondesc, d);
|
siomix_ondesc(d->siomix.hdl, dev_siomix_ondesc, d);
|
||||||
siomix_onctl(d->siomix.hdl, dev_siomix_onctl, d);
|
siomix_onctl(d->siomix.hdl, dev_siomix_onctl, d);
|
||||||
d->siomix.file = file_new(&dev_siomix_ops, d, path,
|
d->siomix.file = file_new(&dev_siomix_ops, d, "mix",
|
||||||
siomix_nfds(d->siomix.hdl));
|
siomix_nfds(d->siomix.hdl));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,8 +114,6 @@ dev_siomix_close(struct dev *d)
|
||||||
if (d->siomix.hdl == NULL)
|
if (d->siomix.hdl == NULL)
|
||||||
return;
|
return;
|
||||||
file_del(d->siomix.file);
|
file_del(d->siomix.file);
|
||||||
siomix_close(d->siomix.hdl);
|
|
||||||
d->siomix.hdl = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct dev_siomix {
|
||||||
struct file *file;
|
struct file *file;
|
||||||
};
|
};
|
||||||
|
|
||||||
void dev_siomix_open(struct dev *, char *);
|
void dev_siomix_open(struct dev *);
|
||||||
void dev_siomix_close(struct dev *);
|
void dev_siomix_close(struct dev *);
|
||||||
|
|
||||||
#endif /* !defined(DEV_SIOMIX_H) */
|
#endif /* !defined(DEV_SIOMIX_H) */
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
*/
|
*/
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/signal.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
|
||||||
|
|
|
@ -596,25 +596,14 @@ port_done(struct port *c)
|
||||||
port_drain(c);
|
port_drain(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
port_reopen(struct port *p)
|
port_reopen(struct port *p)
|
||||||
{
|
{
|
||||||
if (p->state == PORT_CFG)
|
if (p->state == PORT_CFG)
|
||||||
return;
|
return 1;
|
||||||
|
|
||||||
if (log_level >= 1) {
|
if (!port_mio_reopen(p))
|
||||||
port_log(p);
|
return 0;
|
||||||
log_puts(": reopening port\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
port_mio_close(p);
|
return 1;
|
||||||
|
|
||||||
if (!port_mio_open(p)) {
|
|
||||||
if (log_level >= 1) {
|
|
||||||
port_log(p);
|
|
||||||
log_puts(": found no working alternate port\n");
|
|
||||||
}
|
|
||||||
p->state = PORT_CFG;
|
|
||||||
port_exitall(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,6 @@ int port_init(struct port *);
|
||||||
void port_done(struct port *);
|
void port_done(struct port *);
|
||||||
void port_drain(struct port *);
|
void port_drain(struct port *);
|
||||||
int port_close(struct port *);
|
int port_close(struct port *);
|
||||||
void port_reopen(struct port *);
|
int port_reopen(struct port *);
|
||||||
|
|
||||||
#endif /* !defined(MIDI_H) */
|
#endif /* !defined(MIDI_H) */
|
||||||
|
|
|
@ -47,18 +47,26 @@ struct fileops port_mio_ops = {
|
||||||
/*
|
/*
|
||||||
* open the port using one of the provided paths
|
* open the port using one of the provided paths
|
||||||
*/
|
*/
|
||||||
static char *
|
static struct mio_hdl *
|
||||||
port_mio_openlist(struct port *c, unsigned int mode)
|
port_mio_openlist(struct port *c, unsigned int mode)
|
||||||
{
|
{
|
||||||
|
struct mio_hdl *hdl;
|
||||||
struct name *n;
|
struct name *n;
|
||||||
|
|
||||||
n = c->path_list;
|
n = c->path_list;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
break;
|
break;
|
||||||
c->mio.hdl = mio_open(n->str, mode, 1);
|
hdl = mio_open(n->str, mode, 1);
|
||||||
if (c->mio.hdl != NULL)
|
if (hdl != NULL) {
|
||||||
return n->str;
|
if (log_level >= 2) {
|
||||||
|
port_log(c);
|
||||||
|
log_puts(": using ");
|
||||||
|
log_puts(n->str);
|
||||||
|
log_puts("\n");
|
||||||
|
}
|
||||||
|
return hdl;
|
||||||
|
}
|
||||||
n = n->next;
|
n = n->next;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -67,12 +75,37 @@ port_mio_openlist(struct port *c, unsigned int mode)
|
||||||
int
|
int
|
||||||
port_mio_open(struct port *p)
|
port_mio_open(struct port *p)
|
||||||
{
|
{
|
||||||
char *path;
|
p->mio.hdl = port_mio_openlist(p, p->midi->mode);
|
||||||
|
|
||||||
path = port_mio_openlist(p, p->midi->mode);
|
|
||||||
if (p->mio.hdl == NULL)
|
if (p->mio.hdl == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
p->mio.file = file_new(&port_mio_ops, p, path, mio_nfds(p->mio.hdl));
|
p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(p->mio.hdl));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open an alternate port. Upon success, close the old port
|
||||||
|
* and continue using the new one.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
port_mio_reopen(struct port *p)
|
||||||
|
{
|
||||||
|
struct mio_hdl *hdl;
|
||||||
|
|
||||||
|
hdl = port_mio_openlist(p, p->midi->mode);
|
||||||
|
if (hdl == NULL) {
|
||||||
|
if (log_level >= 1) {
|
||||||
|
port_log(p);
|
||||||
|
log_puts(": couldn't open an alternate port\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close unused device */
|
||||||
|
file_del(p->mio.file);
|
||||||
|
mio_close(p->mio.hdl);
|
||||||
|
|
||||||
|
p->mio.hdl = hdl;
|
||||||
|
p->mio.file = file_new(&port_mio_ops, p, "port", mio_nfds(hdl));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,5 +183,6 @@ port_mio_hup(void *arg)
|
||||||
{
|
{
|
||||||
struct port *p = arg;
|
struct port *p = arg;
|
||||||
|
|
||||||
port_reopen(p);
|
if (!port_reopen(p))
|
||||||
|
port_close(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct port_mio {
|
||||||
};
|
};
|
||||||
|
|
||||||
int port_mio_open(struct port *);
|
int port_mio_open(struct port *);
|
||||||
|
int port_mio_reopen(struct port *);
|
||||||
void port_mio_close(struct port *);
|
void port_mio_close(struct port *);
|
||||||
|
|
||||||
#endif /* !defined(MIOFILE_H) */
|
#endif /* !defined(MIOFILE_H) */
|
||||||
|
|
145
sndiod/siofile.c
145
sndiod/siofile.c
|
@ -87,18 +87,36 @@ dev_sio_timeout(void *arg)
|
||||||
/*
|
/*
|
||||||
* open the device using one of the provided paths
|
* open the device using one of the provided paths
|
||||||
*/
|
*/
|
||||||
static char *
|
static struct sio_hdl *
|
||||||
dev_sio_openlist(struct dev *d, unsigned int mode)
|
dev_sio_openlist(struct dev *d, unsigned int mode, struct siomix_hdl **rmixhdl)
|
||||||
{
|
{
|
||||||
struct name *n;
|
struct name *n;
|
||||||
|
struct sio_hdl *hdl;
|
||||||
|
struct siomix_hdl *mixhdl;
|
||||||
|
|
||||||
n = d->path_list;
|
n = d->path_list;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (n == NULL)
|
if (n == NULL)
|
||||||
break;
|
break;
|
||||||
d->sio.hdl = sio_open(n->str, mode, 1);
|
hdl = sio_open(n->str, mode, 1);
|
||||||
if (d->sio.hdl != NULL)
|
if (hdl != NULL) {
|
||||||
return n->str;
|
if (log_level >= 2) {
|
||||||
|
dev_log(d);
|
||||||
|
log_puts(": using ");
|
||||||
|
log_puts(n->str);
|
||||||
|
log_puts("\n");
|
||||||
|
}
|
||||||
|
mixhdl = siomix_open(n->str,
|
||||||
|
SIOMIX_READ | SIOMIX_WRITE, 0);
|
||||||
|
if (mixhdl == NULL) {
|
||||||
|
if (log_level >= 1) {
|
||||||
|
dev_log(d);
|
||||||
|
log_puts(": no mixer\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*rmixhdl = mixhdl;
|
||||||
|
return hdl;
|
||||||
|
}
|
||||||
n = n->next;
|
n = n->next;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -112,18 +130,18 @@ dev_sio_open(struct dev *d)
|
||||||
{
|
{
|
||||||
struct sio_par par;
|
struct sio_par par;
|
||||||
unsigned int mode = d->mode & (MODE_PLAY | MODE_REC);
|
unsigned int mode = d->mode & (MODE_PLAY | MODE_REC);
|
||||||
char *path;
|
|
||||||
|
|
||||||
path = dev_sio_openlist(d, mode);
|
d->sio.hdl = dev_sio_openlist(d, mode, &d->siomix.hdl);
|
||||||
if (path == NULL) {
|
if (d->sio.hdl == NULL) {
|
||||||
if (mode != (SIO_PLAY | SIO_REC))
|
if (mode != (SIO_PLAY | SIO_REC))
|
||||||
return 0;
|
return 0;
|
||||||
path = dev_sio_openlist(d, SIO_PLAY);
|
d->sio.hdl = dev_sio_openlist(d, SIO_PLAY, &d->siomix.hdl);
|
||||||
if (path != NULL)
|
if (d->sio.hdl != NULL)
|
||||||
mode = SIO_PLAY;
|
mode = SIO_PLAY;
|
||||||
else {
|
else {
|
||||||
path = dev_sio_openlist(d, SIO_REC);
|
d->sio.hdl = dev_sio_openlist(d,
|
||||||
if (path != NULL)
|
SIO_REC, &d->siomix.hdl);
|
||||||
|
if (d->sio.hdl != NULL)
|
||||||
mode = SIO_REC;
|
mode = SIO_REC;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -233,18 +251,98 @@ dev_sio_open(struct dev *d)
|
||||||
if (!(mode & MODE_REC))
|
if (!(mode & MODE_REC))
|
||||||
d->mode &= ~MODE_REC;
|
d->mode &= ~MODE_REC;
|
||||||
sio_onmove(d->sio.hdl, dev_sio_onmove, d);
|
sio_onmove(d->sio.hdl, dev_sio_onmove, d);
|
||||||
d->sio.file = file_new(&dev_sio_ops, d, path, sio_nfds(d->sio.hdl));
|
d->sio.file = file_new(&dev_sio_ops, d, "dev", sio_nfds(d->sio.hdl));
|
||||||
timo_set(&d->sio.watchdog, dev_sio_timeout, d);
|
timo_set(&d->sio.watchdog, dev_sio_timeout, d);
|
||||||
if (log_level >= 1) {
|
dev_siomix_open(d);
|
||||||
dev_log(d);
|
|
||||||
log_puts(": using ");
|
|
||||||
log_puts(path);
|
|
||||||
log_puts("\n");
|
|
||||||
}
|
|
||||||
dev_siomix_open(d, path);
|
|
||||||
return 1;
|
return 1;
|
||||||
bad_close:
|
bad_close:
|
||||||
sio_close(d->sio.hdl);
|
sio_close(d->sio.hdl);
|
||||||
|
if (d->siomix.hdl) {
|
||||||
|
siomix_close(d->siomix.hdl);
|
||||||
|
d->siomix.hdl = NULL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open an alternate device. Upon success and if the new device is
|
||||||
|
* compatible with the old one, close the old device and continue
|
||||||
|
* using the new one. The new device is not started.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
dev_sio_reopen(struct dev *d)
|
||||||
|
{
|
||||||
|
struct siomix_hdl *mixhdl;
|
||||||
|
struct sio_par par;
|
||||||
|
struct sio_hdl *hdl;
|
||||||
|
|
||||||
|
hdl = dev_sio_openlist(d, d->mode & (MODE_PLAY | MODE_REC), &mixhdl);
|
||||||
|
if (hdl == NULL) {
|
||||||
|
if (log_level >= 1) {
|
||||||
|
dev_log(d);
|
||||||
|
log_puts(": couldn't open an alternate device\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sio_initpar(&par);
|
||||||
|
par.bits = d->par.bits;
|
||||||
|
par.bps = d->par.bps;
|
||||||
|
par.sig = d->par.sig;
|
||||||
|
par.le = d->par.le;
|
||||||
|
par.msb = d->par.msb;
|
||||||
|
if (d->mode & SIO_PLAY)
|
||||||
|
par.pchan = d->pchan;
|
||||||
|
if (d->mode & SIO_REC)
|
||||||
|
par.rchan = d->rchan;
|
||||||
|
par.appbufsz = d->bufsz;
|
||||||
|
par.round = d->round;
|
||||||
|
par.rate = d->rate;
|
||||||
|
if (!sio_setpar(hdl, &par))
|
||||||
|
goto bad_close;
|
||||||
|
if (!sio_getpar(hdl, &par))
|
||||||
|
goto bad_close;
|
||||||
|
|
||||||
|
/* check if new parameters are compatible with old ones */
|
||||||
|
if (par.round != d->round || par.bufsz != d->bufsz ||
|
||||||
|
par.rate != d->rate) {
|
||||||
|
if (log_level >= 1) {
|
||||||
|
dev_log(d);
|
||||||
|
log_puts(": alternate device not compatible\n");
|
||||||
|
}
|
||||||
|
goto bad_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close unused device */
|
||||||
|
timo_del(&d->sio.watchdog);
|
||||||
|
file_del(d->sio.file);
|
||||||
|
sio_close(d->sio.hdl);
|
||||||
|
dev_siomix_close(d);
|
||||||
|
if (d->siomix.hdl) {
|
||||||
|
siomix_close(d->siomix.hdl);
|
||||||
|
d->siomix.hdl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* update parameters */
|
||||||
|
d->par.bits = par.bits;
|
||||||
|
d->par.bps = par.bps;
|
||||||
|
d->par.sig = par.sig;
|
||||||
|
d->par.le = par.le;
|
||||||
|
d->par.msb = par.msb;
|
||||||
|
if (d->mode & SIO_PLAY)
|
||||||
|
d->pchan = par.pchan;
|
||||||
|
if (d->mode & SIO_REC)
|
||||||
|
d->rchan = par.rchan;
|
||||||
|
|
||||||
|
d->sio.hdl = hdl;
|
||||||
|
d->siomix.hdl = mixhdl;
|
||||||
|
d->sio.file = file_new(&dev_sio_ops, d, "dev", sio_nfds(hdl));
|
||||||
|
sio_onmove(hdl, dev_sio_onmove, d);
|
||||||
|
return 1;
|
||||||
|
bad_close:
|
||||||
|
sio_close(hdl);
|
||||||
|
if (mixhdl)
|
||||||
|
siomix_close(mixhdl);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +359,10 @@ dev_sio_close(struct dev *d)
|
||||||
timo_del(&d->sio.watchdog);
|
timo_del(&d->sio.watchdog);
|
||||||
file_del(d->sio.file);
|
file_del(d->sio.file);
|
||||||
sio_close(d->sio.hdl);
|
sio_close(d->sio.hdl);
|
||||||
|
if (d->siomix.hdl) {
|
||||||
|
siomix_close(d->siomix.hdl);
|
||||||
|
d->siomix.hdl = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -523,5 +625,6 @@ dev_sio_hup(void *arg)
|
||||||
log_puts(": disconnected\n");
|
log_puts(": disconnected\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
dev_reopen(d);
|
if (!dev_reopen(d))
|
||||||
|
dev_close(d);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct dev_sio {
|
||||||
};
|
};
|
||||||
|
|
||||||
int dev_sio_open(struct dev *);
|
int dev_sio_open(struct dev *);
|
||||||
|
int dev_sio_reopen(struct dev *);
|
||||||
void dev_sio_close(struct dev *);
|
void dev_sio_close(struct dev *);
|
||||||
void dev_sio_log(struct dev *);
|
void dev_sio_log(struct dev *);
|
||||||
void dev_sio_start(struct dev *);
|
void dev_sio_start(struct dev *);
|
||||||
|
|
|
@ -186,7 +186,7 @@ Examples:
|
||||||
.Va u8 , s16le , s24le3 , s24le4lsb .
|
.Va u8 , s16le , s24le3 , s24le4lsb .
|
||||||
.It Fl F Ar device
|
.It Fl F Ar device
|
||||||
Specify an alternate device to use.
|
Specify an alternate device to use.
|
||||||
If doesn't work, the one given with the last
|
If it doesn't work, the one given with the last
|
||||||
.Fl f
|
.Fl f
|
||||||
or
|
or
|
||||||
.Fl F
|
.Fl F
|
||||||
|
@ -261,7 +261,7 @@ The default is
|
||||||
(i.e. full-duplex).
|
(i.e. full-duplex).
|
||||||
.It Fl Q Ar port
|
.It Fl Q Ar port
|
||||||
Specify an alternate MIDI port to use.
|
Specify an alternate MIDI port to use.
|
||||||
If doesn't work, the one given with the last
|
If it doesn't work, the one given with the last
|
||||||
.Fl Q
|
.Fl Q
|
||||||
or
|
or
|
||||||
.Fl q
|
.Fl q
|
||||||
|
|
Loading…
Reference in New Issue