summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorratchov <ratchov@openbsd.org>2019-09-21 04:42:46 +0000
committerratchov <ratchov@openbsd.org>2019-09-21 04:42:46 +0000
commit731605d74e40baf38ff90558526d98b93c326088 (patch)
treeed81648641a0cb9aed9152e0927a2da698458e58
parentExpand scsi_inquiry_data to 96 bytes to include new fields. If the (diff)
downloadwireguard-openbsd-731605d74e40baf38ff90558526d98b93c326088.tar.xz
wireguard-openbsd-731605d74e40baf38ff90558526d98b93c326088.zip
Allow switching between devices without disconnecting clients.
The new -F option allows alternate device to be specified. If the device is disconnected, the one given with the last -f or -F options will be used instead. Similarly, the new -Q option allows an alternate MIDI port to be specified. ok mpi@
-rw-r--r--usr.bin/sndiod/dev.c75
-rw-r--r--usr.bin/sndiod/dev.h5
-rw-r--r--usr.bin/sndiod/fdpass.c15
-rw-r--r--usr.bin/sndiod/midi.c19
-rw-r--r--usr.bin/sndiod/midi.h5
-rw-r--r--usr.bin/sndiod/miofile.c34
-rw-r--r--usr.bin/sndiod/miofile.h3
-rw-r--r--usr.bin/sndiod/siofile.c80
-rw-r--r--usr.bin/sndiod/siofile.h3
-rw-r--r--usr.bin/sndiod/sndiod.833
-rw-r--r--usr.bin/sndiod/sndiod.c63
-rw-r--r--usr.bin/sndiod/utils.c29
-rw-r--r--usr.bin/sndiod/utils.h10
13 files changed, 336 insertions, 38 deletions
diff --git a/usr.bin/sndiod/dev.c b/usr.bin/sndiod/dev.c
index 7fe63983083..1e289f82545 100644
--- a/usr.bin/sndiod/dev.c
+++ b/usr.bin/sndiod/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.61 2019/09/19 05:10:19 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.62 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -969,7 +969,8 @@ dev_new(char *path, struct aparams *par,
return NULL;
}
d = xmalloc(sizeof(struct dev));
- d->path = xstrdup(path);
+ d->path_list = NULL;
+ namelist_add(&d->path_list, path);
d->num = dev_sndnum++;
d->opt_list = NULL;
@@ -1174,6 +1175,74 @@ dev_close(struct dev *d)
dev_freebufs(d);
}
+/*
+ * Close the device, but attempt to migrate everything to a new sndio
+ * device.
+ */
+int
+dev_reopen(struct dev *d)
+{
+ struct slot *s;
+ long long pos;
+ unsigned int pstate;
+ int delta;
+
+ /* not opened */
+ if (d->pstate == DEV_CFG)
+ return 1;
+
+ /* save state */
+ delta = d->delta;
+ pstate = d->pstate;
+
+ if (!dev_sio_reopen(d))
+ return 0;
+
+ /* reopen returns a stopped device */
+ d->pstate = DEV_INIT;
+
+ /* reallocate new buffers, with new parameters */
+ dev_freebufs(d);
+ dev_allocbufs(d);
+
+ /*
+ * 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)s->delta * d->round + s->delta_rem;
+ pos -= (long long)delta * s->round;
+ s->delta_rem = pos % (int)d->round;
+ s->delta = pos / (int)d->round;
+ if (log_level >= 3) {
+ slot_log(s);
+ log_puts(": adjusted: delta -> ");
+ log_puti(s->delta);
+ log_puts(", delta_rem -> ");
+ log_puti(s->delta_rem);
+ log_puts("\n");
+ }
+
+ /* reinitilize the format conversion chain */
+ slot_initconv(s);
+ }
+ 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);
+
+ return 1;
+}
+
int
dev_ref(struct dev *d)
{
@@ -1280,7 +1349,7 @@ dev_del(struct dev *d)
}
midi_del(d->midi);
*p = d->next;
- xfree(d->path);
+ namelist_clear(&d->path_list);
xfree(d);
}
diff --git a/usr.bin/sndiod/dev.h b/usr.bin/sndiod/dev.h
index bd909060bdf..69a51297f72 100644
--- a/usr.bin/sndiod/dev.h
+++ b/usr.bin/sndiod/dev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.h,v 1.21 2019/07/12 06:30:55 ratchov Exp $ */
+/* $OpenBSD: dev.h,v 1.22 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -159,7 +159,7 @@ struct dev {
#define DEV_INIT 1 /* stopped */
#define DEV_RUN 2 /* playin & recording */
unsigned int pstate; /* one of above */
- char *path; /* sio path */
+ struct name *path_list;
/*
* actual parameters and runtime state (i.e. once opened)
@@ -201,6 +201,7 @@ extern struct dev *dev_list;
void dev_log(struct dev *);
void dev_close(struct dev *);
+int 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);
diff --git a/usr.bin/sndiod/fdpass.c b/usr.bin/sndiod/fdpass.c
index 42de8e7502f..30ed39f1e14 100644
--- a/usr.bin/sndiod/fdpass.c
+++ b/usr.bin/sndiod/fdpass.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fdpass.c,v 1.6 2019/06/28 13:35:03 deraadt Exp $ */
+/* $OpenBSD: fdpass.c,v 1.7 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org>
*
@@ -300,6 +300,7 @@ fdpass_in_helper(void *arg)
struct fdpass *f = arg;
struct dev *d;
struct port *p;
+ struct name *path;
if (!fdpass_recv(f, &cmd, &num, &mode, &fd))
return;
@@ -314,7 +315,11 @@ fdpass_in_helper(void *arg)
fdpass_close(f);
return;
}
- fd = sio_sun_getfd(d->path, mode, 1);
+ for (path = d->path_list; path != NULL; path = path->next) {
+ fd = sio_sun_getfd(path->str, mode, 1);
+ if (fd != -1)
+ break;
+ }
break;
case FDPASS_OPEN_MIDI:
p = port_bynum(num);
@@ -326,7 +331,11 @@ fdpass_in_helper(void *arg)
fdpass_close(f);
return;
}
- fd = mio_rmidi_getfd(p->path, mode, 1);
+ for (path = p->path_list; path != NULL; path = path->next) {
+ fd = mio_rmidi_getfd(path->str, mode, 1);
+ if (fd != -1)
+ break;
+ }
break;
default:
fdpass_close(f);
diff --git a/usr.bin/sndiod/midi.c b/usr.bin/sndiod/midi.c
index c2287f826f3..46ac3929f24 100644
--- a/usr.bin/sndiod/midi.c
+++ b/usr.bin/sndiod/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.21 2019/08/29 07:19:15 ratchov Exp $ */
+/* $OpenBSD: midi.c,v 1.22 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -438,7 +438,8 @@ port_new(char *path, unsigned int mode, int hold)
struct port *c;
c = xmalloc(sizeof(struct port));
- c->path = xstrdup(path);
+ c->path_list = NULL;
+ namelist_add(&c->path_list, path);
c->state = PORT_CFG;
c->hold = hold;
c->midi = midi_new(&port_midiops, c, mode);
@@ -468,7 +469,7 @@ port_del(struct port *c)
#endif
}
*p = c->next;
- xfree(c->path);
+ namelist_clear(&c->path_list);
xfree(c);
}
@@ -593,3 +594,15 @@ port_done(struct port *c)
if (c->state == PORT_INIT)
port_drain(c);
}
+
+int
+port_reopen(struct port *p)
+{
+ if (p->state == PORT_CFG)
+ return 1;
+
+ if (!port_mio_reopen(p))
+ return 0;
+
+ return 1;
+}
diff --git a/usr.bin/sndiod/midi.h b/usr.bin/sndiod/midi.h
index 91fa81c133d..c9f48875d70 100644
--- a/usr.bin/sndiod/midi.h
+++ b/usr.bin/sndiod/midi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.h,v 1.9 2019/08/29 07:11:28 ratchov Exp $ */
+/* $OpenBSD: midi.h,v 1.10 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -88,7 +88,7 @@ struct port {
#define PORT_DRAIN 2
unsigned int state;
unsigned int num; /* port serial number */
- char *path;
+ struct name *path_list;
int hold; /* hold the port open ? */
struct midi *midi;
};
@@ -121,5 +121,6 @@ int port_init(struct port *);
void port_done(struct port *);
void port_drain(struct port *);
int port_close(struct port *);
+int port_reopen(struct port *);
#endif /* !defined(MIDI_H) */
diff --git a/usr.bin/sndiod/miofile.c b/usr.bin/sndiod/miofile.c
index ab32639e00c..3c2d56db4aa 100644
--- a/usr.bin/sndiod/miofile.c
+++ b/usr.bin/sndiod/miofile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: miofile.c,v 1.4 2015/12/20 11:38:33 ratchov Exp $ */
+/* $OpenBSD: miofile.c,v 1.5 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -51,7 +51,34 @@ port_mio_open(struct port *p)
p->mio.hdl = fdpass_mio_open(p->num, p->midi->mode);
if (p->mio.hdl == NULL)
return 0;
- p->mio.file = file_new(&port_mio_ops, p, 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 = fdpass_mio_open(p->num, 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;
}
@@ -129,5 +156,6 @@ port_mio_hup(void *arg)
{
struct port *p = arg;
- port_close(p);
+ if (!port_reopen(p))
+ port_close(p);
}
diff --git a/usr.bin/sndiod/miofile.h b/usr.bin/sndiod/miofile.h
index 128bd32ff08..703caa023d5 100644
--- a/usr.bin/sndiod/miofile.h
+++ b/usr.bin/sndiod/miofile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: miofile.h,v 1.1 2012/11/23 07:03:28 ratchov Exp $ */
+/* $OpenBSD: miofile.h,v 1.2 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -25,6 +25,7 @@ struct port_mio {
};
int port_mio_open(struct port *);
+int port_mio_reopen(struct port *);
void port_mio_close(struct port *);
#endif /* !defined(MIOFILE_H) */
diff --git a/usr.bin/sndiod/siofile.c b/usr.bin/sndiod/siofile.c
index aacf2a1de0c..c720c61bab6 100644
--- a/usr.bin/sndiod/siofile.c
+++ b/usr.bin/sndiod/siofile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: siofile.c,v 1.15 2019/08/29 07:05:47 ratchov Exp $ */
+/* $OpenBSD: siofile.c,v 1.16 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -212,7 +212,7 @@ 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, 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);
return 1;
bad_close:
@@ -220,6 +220,79 @@ dev_sio_open(struct dev *d)
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 sio_par par;
+ struct sio_hdl *hdl;
+
+ hdl = fdpass_sio_open(d->num, d->mode & (MODE_PLAY | MODE_REC));
+ 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);
+
+ /* 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->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);
+ return 0;
+}
+
void
dev_sio_close(struct dev *d)
{
@@ -494,5 +567,6 @@ dev_sio_hup(void *arg)
log_puts(": disconnected\n");
}
#endif
- dev_close(d);
+ if (!dev_reopen(d))
+ dev_close(d);
}
diff --git a/usr.bin/sndiod/siofile.h b/usr.bin/sndiod/siofile.h
index a763b3adef2..4cebf879730 100644
--- a/usr.bin/sndiod/siofile.h
+++ b/usr.bin/sndiod/siofile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: siofile.h,v 1.3 2013/09/28 18:49:32 ratchov Exp $ */
+/* $OpenBSD: siofile.h,v 1.4 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -38,6 +38,7 @@ struct dev_sio {
};
int dev_sio_open(struct dev *);
+int dev_sio_reopen(struct dev *);
void dev_sio_close(struct dev *);
void dev_sio_log(struct dev *);
void dev_sio_start(struct dev *);
diff --git a/usr.bin/sndiod/sndiod.8 b/usr.bin/sndiod/sndiod.8
index 2945dff5b70..cd643dd08e3 100644
--- a/usr.bin/sndiod/sndiod.8
+++ b/usr.bin/sndiod/sndiod.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sndiod.8,v 1.2 2016/01/18 11:38:07 ratchov Exp $
+.\" $OpenBSD: sndiod.8,v 1.3 2019/09/21 04:42:46 ratchov Exp $
.\"
.\" Copyright (c) 2006-2012 Alexandre Ratchov <alex@caoua.org>
.\"
@@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: January 18 2016 $
+.Dd $Mdocdate: September 21 2019 $
.Dt SNDIOD 8
.Os
.Sh NAME
@@ -29,10 +29,12 @@
.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
@@ -182,6 +184,18 @@ 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
@@ -245,6 +259,15 @@ 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.
@@ -376,11 +399,15 @@ 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,
diff --git a/usr.bin/sndiod/sndiod.c b/usr.bin/sndiod/sndiod.c
index 18f171a315a..2046b6c13ad 100644
--- a/usr.bin/sndiod/sndiod.c
+++ b/usr.bin/sndiod/sndiod.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sndiod.c,v 1.35 2019/06/29 21:23:18 ratchov Exp $ */
+/* $OpenBSD: sndiod.c,v 1.36 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -93,6 +93,7 @@
#endif
void sigint(int);
+void sighup(int);
void opt_ch(int *, int *);
void opt_enc(struct aparams *);
int opt_mmc(void);
@@ -109,12 +110,13 @@ 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;
+volatile sig_atomic_t quit_flag = 0, reopen_flag = 0;
char usagestr[] = "usage: sndiod [-d] [-a flag] [-b nframes] "
- "[-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";
+ "[-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";
/*
* SIGINT handler, it raises the quit flag. If the flag is already set,
@@ -129,6 +131,16 @@ 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)
{
@@ -231,6 +243,7 @@ setsig(void)
struct sigaction sa;
quit_flag = 0;
+ reopen_flag = 0;
sigfillset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = sigint;
@@ -238,6 +251,7 @@ 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");
}
@@ -294,7 +308,8 @@ mkdev(char *path, struct aparams *par,
struct dev *d;
for (d = dev_list; d != NULL; d = d->next) {
- if (strcmp(d->path, path) == 0)
+ if (d->path_list->next == NULL &&
+ strcmp(d->path_list->str, path) == 0)
return d;
}
if (!bufsz && !round) {
@@ -316,7 +331,8 @@ mkport(char *path, int hold)
struct port *c;
for (c = port_list; c != NULL; c = c->next) {
- if (strcmp(c->path, path) == 0)
+ if (c->path_list->next == NULL &&
+ strcmp(c->path_list->str, path) == 0)
return c;
}
c = port_new(path, MODE_MIDIMASK, hold);
@@ -361,6 +377,7 @@ start_helper(int background)
struct dev *d;
struct port *p;
struct passwd *pw;
+ struct name *n;
int s[2];
pid_t pid;
@@ -395,10 +412,14 @@ start_helper(int background)
setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
err(1, "cannot drop privileges");
}
- for (d = dev_list; d != NULL; d = d->next)
- dounveil(d->path, "rsnd/", "/dev/audio");
- for (p = port_list; p != NULL; p = p->next)
- dounveil(p->path, "rmidi/", "/dev/rmidi");
+ for (d = dev_list; d != NULL; d = d->next) {
+ for (n = d->path_list; n != NULL; n = n->next)
+ dounveil(n->str, "rsnd/", "/dev/audio");
+ }
+ for (p = port_list; p != NULL; p = p->next) {
+ for (n = p->path_list; n != NULL; n = n->next)
+ dounveil(n->str, "rmidi/", "/dev/rmidi");
+ }
if (pledge("stdio sendfd rpath wpath", NULL) == -1)
err(1, "pledge");
while (file_poll())
@@ -461,7 +482,8 @@ main(int argc, char **argv)
mode = MODE_PLAY | MODE_REC;
tcpaddr_list = NULL;
- while ((c = getopt(argc, argv, "a:b:c:C:de:f:j:L:m:q:r:s:t:U:v:w:x:z:")) != -1) {
+ 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) {
switch (c) {
case 'd':
log_level++;
@@ -518,6 +540,11 @@ 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;
@@ -538,6 +565,11 @@ 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;
@@ -617,6 +649,13 @@ 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 (!fdpass_peer)
break;
if (!file_poll())
diff --git a/usr.bin/sndiod/utils.c b/usr.bin/sndiod/utils.c
index 175b61bae79..75b709ed612 100644
--- a/usr.bin/sndiod/utils.c
+++ b/usr.bin/sndiod/utils.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: utils.c,v 1.5 2019/07/05 07:34:40 ratchov Exp $ */
+/* $OpenBSD: utils.c,v 1.6 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2003-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -188,3 +188,30 @@ 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);
+ }
+}
diff --git a/usr.bin/sndiod/utils.h b/usr.bin/sndiod/utils.h
index f108ed56c63..62042c96164 100644
--- a/usr.bin/sndiod/utils.h
+++ b/usr.bin/sndiod/utils.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: utils.h,v 1.3 2013/05/12 04:58:41 ratchov Exp $ */
+/* $OpenBSD: utils.h,v 1.4 2019/09/21 04:42:46 ratchov Exp $ */
/*
* Copyright (c) 2003-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -20,6 +20,11 @@
#include <stddef.h>
+struct name {
+ struct name *next;
+ char str[];
+};
+
void log_puts(char *);
void log_putx(unsigned long);
void log_putu(unsigned long);
@@ -31,6 +36,9 @@ void *xmalloc(size_t);
char *xstrdup(char *);
void xfree(void *);
+void namelist_add(struct name **, char *);
+void namelist_clear(struct name **);
+
/*
* Log levels:
*