Revert "Allow switching between devices without disconnecting clients."

This change was not right: First, upon SIGHUP, next device should be
opened before the old one is closed. Second the migration code doesn't
reinitialize the conversion layer which breaks audio when switching
between devices with different channel counts.

This reverts commit 5bc17e6cea.
This commit is contained in:
Alexandre Ratchov 2019-09-18 09:16:58 +02:00
parent e453b782d1
commit 0310ad45e9
10 changed files with 26 additions and 286 deletions

View File

@ -969,8 +969,7 @@ dev_new(char *path, struct aparams *par,
return NULL;
}
d = xmalloc(sizeof(struct dev));
d->path_list = NULL;
namelist_add(&d->path_list, path);
d->path = xstrdup(path);
d->num = dev_sndnum++;
d->opt_list = NULL;
@ -1175,94 +1174,6 @@ dev_close(struct dev *d)
dev_close_do(d);
}
/*
* Close the device, but attempt to migrate everything to a new sndio
* device.
*/
void
dev_reopen(struct dev *d)
{
struct slot *s;
long long pos;
unsigned int mode, round, bufsz, rate, pstate;
int delta;
/* not opened */
if (d->pstate == DEV_CFG)
return;
if (log_level >= 1) {
dev_log(d);
log_puts(": reopening device\n");
}
/* save state */
mode = d->mode;
round = d->round;
bufsz = d->bufsz;
rate = d->rate;
delta = d->delta;
pstate = d->pstate;
/* close device */
dev_close_do(d);
/* open device */
if (!dev_open_do(d)) {
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 */
if (d->mode != mode ||
d->round != round ||
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
* that the new device can start at zero
*/
for (s = d->slot_list; s != NULL; s = s->next) {
pos = (long long)(d->round - delta) * s->round + s->delta_rem;
s->delta_rem = pos % d->round;
s->delta += pos / (int)d->round;
s->delta -= s->round;
if (log_level >= 2) {
slot_log(s);
log_puts(": adjusted: delta -> ");
log_puti(s->delta);
log_puts(", delta_rem -> ");
log_puti(s->delta_rem);
log_puts("\n");
}
}
if (d->tstate == MMC_RUN) {
d->mtc.delta -= delta * MTC_SEC;
if (log_level >= 2) {
dev_log(d);
log_puts(": adjusted mtc: delta ->");
log_puti(d->mtc.delta);
log_puts("\n");
}
}
/* start the device if needed */
if (pstate == DEV_RUN)
dev_wakeup(d);
}
int
dev_ref(struct dev *d)
{
@ -1369,7 +1280,7 @@ dev_del(struct dev *d)
}
midi_del(d->midi);
*p = d->next;
namelist_clear(&d->path_list);
xfree(d->path);
xfree(d);
}

View File

@ -159,7 +159,7 @@ struct dev {
#define DEV_INIT 1 /* stopped */
#define DEV_RUN 2 /* playin & recording */
unsigned int pstate; /* one of above */
struct name *path_list;
char *path; /* sio path */
/*
* actual parameters and runtime state (i.e. once opened)
@ -201,7 +201,6 @@ extern struct dev *dev_list;
void dev_log(struct dev *);
void dev_close(struct dev *);
void dev_reopen(struct dev *);
struct dev *dev_new(char *, struct aparams *, unsigned int, unsigned int,
unsigned int, unsigned int, unsigned int, unsigned int);
struct dev *dev_bynum(int);

View File

@ -439,8 +439,7 @@ port_new(char *path, unsigned int mode, int hold)
struct port *c;
c = xmalloc(sizeof(struct port));
c->path_list = NULL;
namelist_add(&c->path_list, path);
c->path = xstrdup(path);
c->state = PORT_CFG;
c->hold = hold;
c->midi = midi_new(&port_midiops, c, mode);
@ -470,7 +469,7 @@ port_del(struct port *c)
#endif
}
*p = c->next;
namelist_clear(&c->path_list);
xfree(c->path);
xfree(c);
}
@ -595,26 +594,3 @@ port_done(struct port *c)
if (c->state == PORT_INIT)
port_drain(c);
}
void
port_reopen(struct port *p)
{
if (p->state == PORT_CFG)
return;
if (log_level >= 1) {
port_log(p);
log_puts(": reopening port\n");
}
port_mio_close(p);
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);
}
}

View File

@ -88,7 +88,7 @@ struct port {
#define PORT_DRAIN 2
unsigned int state;
unsigned int num; /* port serial number */
struct name *path_list;
char *path;
int hold; /* hold the port open ? */
struct midi *midi;
};
@ -121,6 +121,5 @@ int port_init(struct port *);
void port_done(struct port *);
void port_drain(struct port *);
int port_close(struct port *);
void port_reopen(struct port *);
#endif /* !defined(MIDI_H) */

View File

@ -44,35 +44,13 @@ struct fileops port_mio_ops = {
port_mio_hup
};
/*
* open the port using one of the provided paths
*/
static char *
port_mio_openlist(struct port *c, unsigned int mode)
{
struct name *n;
n = c->path_list;
while (1) {
if (n == NULL)
break;
c->mio.hdl = mio_open(n->str, mode, 1);
if (c->mio.hdl != NULL)
return n->str;
n = n->next;
}
return NULL;
}
int
port_mio_open(struct port *p)
{
char *path;
path = port_mio_openlist(p, p->midi->mode);
p->mio.hdl = mio_open(p->path, p->midi->mode, 1);
if (p->mio.hdl == NULL)
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, p->path, mio_nfds(p->mio.hdl));
return 1;
}
@ -150,5 +128,5 @@ port_mio_hup(void *arg)
{
struct port *p = arg;
port_reopen(p);
port_close(p);
}

View File

@ -83,26 +83,6 @@ dev_sio_timeout(void *arg)
dev_close(d);
}
/*
* open the device using one of the provided paths
*/
static char *
dev_sio_openlist(struct dev *d, unsigned int mode)
{
struct name *n;
n = d->path_list;
while (1) {
if (n == NULL)
break;
d->sio.hdl = sio_open(n->str, mode, 1);
if (d->sio.hdl != NULL)
return n->str;
n = n->next;
}
return NULL;
}
/*
* open the device.
*/
@ -111,18 +91,17 @@ dev_sio_open(struct dev *d)
{
struct sio_par par;
unsigned int mode = d->mode & (MODE_PLAY | MODE_REC);
char *path;
path = dev_sio_openlist(d, mode);
if (path == NULL) {
d->sio.hdl = sio_open(d->path, mode, 1);
if (d->sio.hdl == NULL) {
if (mode != (SIO_PLAY | SIO_REC))
return 0;
path = dev_sio_openlist(d, SIO_PLAY);
if (path != NULL)
d->sio.hdl = sio_open(d->path, SIO_PLAY, 1);
if (d->sio.hdl != NULL)
mode = SIO_PLAY;
else {
path = dev_sio_openlist(d, SIO_REC);
if (path != NULL)
d->sio.hdl = sio_open(d->path, SIO_REC, 1);
if (d->sio.hdl != NULL)
mode = SIO_REC;
else
return 0;
@ -232,14 +211,8 @@ dev_sio_open(struct dev *d)
if (!(mode & MODE_REC))
d->mode &= ~MODE_REC;
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, d->path, sio_nfds(d->sio.hdl));
timo_set(&d->sio.watchdog, dev_sio_timeout, d);
if (log_level >= 1) {
dev_log(d);
log_puts(": using ");
log_puts(path);
log_puts("\n");
}
return 1;
bad_close:
sio_close(d->sio.hdl);
@ -520,5 +493,5 @@ dev_sio_hup(void *arg)
log_puts(": disconnected\n");
}
#endif
dev_reopen(d);
dev_close(d);
}

View File

@ -29,12 +29,10 @@
.Op Fl C Ar min : Ns Ar max
.Op Fl c Ar min : Ns Ar max
.Op Fl e Ar enc
.Op Fl F Ar device
.Op Fl f Ar device
.Op Fl j Ar flag
.Op Fl L Ar addr
.Op Fl m Ar mode
.Op Fl Q Ar port
.Op Fl q Ar port
.Op Fl r Ar rate
.Op Fl s Ar name
@ -184,18 +182,6 @@ or
Only the signedness and the precision are mandatory.
Examples:
.Va u8 , s16le , s24le3 , s24le4lsb .
.It Fl F Ar device
Specify an alternate device to use.
If doesn't work, the one given with the last
.Fl f
or
.Fl F
options will be used.
For instance, specifying a USB device following a
PCI device allows
.Nm
to use the USB one preferably when it's connected
and to fall back to the PCI one when it's disconnected.
.It Fl f Ar device
Add this
.Xr sndio 7
@ -259,15 +245,6 @@ but the same sub-device cannot be used for both recording and monitoring.
The default is
.Ar play , Ns Ar rec
(i.e. full-duplex).
.It Fl Q Ar port
Specify an alternate MIDI port to use.
If doesn't work, the one given with the last
.Fl Q
or
.Fl q
options will be used.
For instance, this allows to replace a USB MIDI controller without
the need to restart programs using it.
.It Fl q Ar port
Expose the given MIDI port.
This allows multiple programs to share the port.
@ -399,15 +376,11 @@ is
If
.Nm
is sent
.Dv SIGHUP ,
.Dv SIGINT
or
.Dv SIGTERM ,
it terminates.
If
.Nm
is sent
.Dv SIGHUP ,
it reopens all audio devices and MIDI ports.
.Pp
By default, when the program cannot accept
recorded data fast enough or cannot provide data to play fast enough,

View File

@ -68,7 +68,7 @@
* block size if neither ``-z'' nor ``-b'' is used
*/
#ifndef DEFAULT_ROUND
#define DEFAULT_ROUND 480
#define DEFAULT_ROUND 960
#endif
/*
@ -86,7 +86,6 @@
#endif
void sigint(int);
void sighup(int);
void opt_ch(int *, int *);
void opt_enc(struct aparams *);
int opt_mmc(void);
@ -103,13 +102,12 @@ struct opt *mkopt(char *, struct dev *,
int, int, int, int, int, int, int, int);
unsigned int log_level = 0;
volatile sig_atomic_t quit_flag = 0, reopen_flag = 0;
volatile sig_atomic_t quit_flag = 0;
char usagestr[] = "usage: sndiod [-d] [-a flag] [-b nframes] "
"[-C min:max] [-c min:max]\n\t"
"[-e enc] [-F device] [-f device] [-j flag] [-L addr] [-m mode]\n\t"
"[-Q port] [-q port] [-r rate] [-s name] [-t mode] [-U unit]\n\t"
"[-v volume] [-w flag] [-z nframes]\n";
"[-C min:max] [-c min:max] [-e enc]\n\t"
"[-f device] [-j flag] [-L addr] [-m mode] [-q port] [-r rate]\n\t"
"[-s name] [-t mode] [-U unit] [-v volume] [-w flag] [-z nframes]\n";
/*
* SIGINT handler, it raises the quit flag. If the flag is already set,
@ -124,16 +122,6 @@ sigint(int s)
quit_flag = 1;
}
/*
* SIGHUP handler, it raises the reopen flag, which requests devices
* to be reopened.
*/
void
sighup(int s)
{
reopen_flag = 1;
}
void
opt_ch(int *rcmin, int *rcmax)
{
@ -236,7 +224,6 @@ setsig(void)
struct sigaction sa;
quit_flag = 0;
reopen_flag = 0;
sigfillset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sigint;
@ -244,7 +231,6 @@ setsig(void)
err(1, "sigaction(int) failed");
if (sigaction(SIGTERM, &sa, NULL) == -1)
err(1, "sigaction(term) failed");
sa.sa_handler = sighup;
if (sigaction(SIGHUP, &sa, NULL) == -1)
err(1, "sigaction(hup) failed");
}
@ -301,8 +287,7 @@ mkdev(char *path, struct aparams *par,
struct dev *d;
for (d = dev_list; d != NULL; d = d->next) {
if (d->path_list->next == NULL &&
strcmp(d->path_list->str, path) == 0)
if (strcmp(d->path, path) == 0)
return d;
}
if (!bufsz && !round) {
@ -324,8 +309,7 @@ mkport(char *path, int hold)
struct port *c;
for (c = port_list; c != NULL; c = c->next) {
if (c->path_list->next == NULL &&
strcmp(c->path_list->str, path) == 0)
if (strcmp(c->path, path) == 0)
return c;
}
c = port_new(path, MODE_MIDIMASK, hold);
@ -391,8 +375,7 @@ main(int argc, char **argv)
mode = MODE_PLAY | MODE_REC;
tcpaddr_list = NULL;
while ((c = getopt(argc, argv,
"a:b:c:C:de:F:f:j:L:m:Q:q:r:s:t:U:v:w:x:z:")) != -1) {
while ((c = getopt(argc, argv, "a:b:c:C:de:f:j:L:m:q:r:s:t:U:v:w:x:z:")) != -1) {
switch (c) {
case 'd':
log_level++;
@ -449,11 +432,6 @@ main(int argc, char **argv)
case 'q':
mkport(optarg, hold);
break;
case 'Q':
if (port_list == NULL)
errx(1, "-Q %s: no ports defined", optarg);
namelist_add(&port_list->path_list, optarg);
break;
case 'a':
hold = opt_onoff();
break;
@ -474,11 +452,6 @@ main(int argc, char **argv)
mkdev(optarg, &par, 0, bufsz, round,
rate, hold, autovol);
break;
case 'F':
if (dev_list == NULL)
errx(1, "-F %s: no devices defined", optarg);
namelist_add(&dev_list->path_list, optarg);
break;
default:
fputs(usagestr, stderr);
return 1;
@ -546,13 +519,6 @@ main(int argc, char **argv)
for (;;) {
if (quit_flag)
break;
if (reopen_flag) {
reopen_flag = 0;
for (d = dev_list; d != NULL; d = d->next)
dev_reopen(d);
for (p = port_list; p != NULL; p = p->next)
port_reopen(p);
}
if (!file_poll())
break;
}

View File

@ -188,30 +188,3 @@ xstrdup(char *s)
memcpy(p, s, size);
return p;
}
/*
* copy and append the given string to the name list
*/
void
namelist_add(struct name **list, char *str)
{
struct name *n;
size_t size;
size = strlen(str) + 1;
n = xmalloc(sizeof(struct name) + size);
memcpy(n->str, str, size);
n->next = *list;
*list = n;
}
void
namelist_clear(struct name **list)
{
struct name *n;
while ((n = *list) != NULL) {
*list = n->next;
xfree(n);
}
}

View File

@ -20,11 +20,6 @@
#include <stddef.h>
struct name {
struct name *next;
char str[];
};
void log_puts(char *);
void log_putx(unsigned long);
void log_putu(unsigned long);
@ -36,9 +31,6 @@ void *xmalloc(size_t);
char *xstrdup(char *);
void xfree(void *);
void namelist_add(struct name **, char *);
void namelist_clear(struct name **);
/*
* Log levels:
*