summaryrefslogtreecommitdiff
path: root/usr.bin/sndiod/dev.c
diff options
context:
space:
mode:
authorEdd Barrett <edd@cvs.openbsd.org>2021-03-02 12:15:47 +0000
committerEdd Barrett <edd@cvs.openbsd.org>2021-03-02 12:15:47 +0000
commite53aa3e7141c84d0315bdb55785bd1e5f3d95b4a (patch)
tree8b1d86406ffbce126220d772c42f317f2c4305f1 /usr.bin/sndiod/dev.c
parent6477c169747735d05dca0840e56751a3fcd50343 (diff)
sndiod: Allow alternative devices to support different modes.
Currently sndiod does not allow you to use alternative devices (-F devices) which support only a subset of the modes of the main (-f) device. For example, if you do `sndiod -f rsnd/0 -F rsnd/1` and: - rsnd/0 is full-duplex (rec + play). - rsnd/1 is play-only. Then you will be unable to use rsnd/1 as sndiod deems it incompatible and refuses to use it (similarly if rsnd/1 is record-only). This is annoying. It means if you want to use a record-only or play-only device, you will either have to kill sndiod and restart it specifying only that device (`sndiod -f rsnd/1` for the above example), or failing that, downgrade the functionality of the main device (`-m play`). This diff (a joint effort between ratchov@ and myself) makes mixing devices with different modes possible. It does this by making both recording and playing available for all devices, even if the underlying hardware doesn't support both modes. For example, if I try to record from a play-only device, then recording will succeed, but the captured PCM data will be pure silence. Similarly, if I try to play to a record-only device, then the audio stream will disappear into the ether. This is mostly a no-op for sndiod in the default configuration (except that play-only devices now accept recording clients). If you use alternative devices (-F), then it's possible for a record-only device to be found first, which may be confusing if you just want to hear sound. We can only assume that if you deviate from defaults, then you know what you are doing. With guidance from, and OK ratchov@, thanks!
Diffstat (limited to 'usr.bin/sndiod/dev.c')
-rw-r--r--usr.bin/sndiod/dev.c82
1 files changed, 41 insertions, 41 deletions
diff --git a/usr.bin/sndiod/dev.c b/usr.bin/sndiod/dev.c
index 6e2e1a6fa6e..7dc8bac2a0b 100644
--- a/usr.bin/sndiod/dev.c
+++ b/usr.bin/sndiod/dev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dev.c,v 1.90 2021/02/02 11:18:57 ratchov Exp $ */
+/* $OpenBSD: dev.c,v 1.91 2021/03/02 12:15:46 edd Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -1142,43 +1142,51 @@ dev_adjpar(struct dev *d, int mode,
/*
* Open the device with the dev_reqxxx capabilities. Setup a mixer, demuxer,
* monitor, midi control, and any necessary conversions.
+ *
+ * Note that record and play buffers are always allocated, even if the
+ * underlying device doesn't support both modes.
*/
int
dev_allocbufs(struct dev *d)
{
- if (d->mode & MODE_REC) {
- /*
- * Create device <-> demuxer buffer
- */
- d->rbuf = xmalloc(d->round * d->rchan * sizeof(adata_t));
+ /*
+ * Create record buffer.
+ */
- /*
- * Insert a converter, if needed.
- */
- if (!aparams_native(&d->par)) {
- dec_init(&d->dec, &d->par, d->rchan);
- d->decbuf = xmalloc(d->round * d->rchan * d->par.bps);
- } else
- d->decbuf = NULL;
- }
- if (d->mode & MODE_PLAY) {
- /*
- * Create device <-> mixer buffer
- */
- d->poffs = 0;
- d->psize = d->bufsz + d->round;
- d->pbuf = xmalloc(d->psize * d->pchan * sizeof(adata_t));
- d->mode |= MODE_MON;
+ /* Create device <-> demuxer buffer */
+ d->rbuf = xmalloc(d->round * d->rchan * sizeof(adata_t));
+
+ /* Insert a converter, if needed. */
+ if (!aparams_native(&d->par)) {
+ dec_init(&d->dec, &d->par, d->rchan);
+ d->decbuf = xmalloc(d->round * d->rchan * d->par.bps);
+ } else
+ d->decbuf = NULL;
+
+ /*
+ * Create play buffer
+ */
+
+ /* Create device <-> mixer buffer */
+ d->poffs = 0;
+ d->psize = d->bufsz + d->round;
+ d->pbuf = xmalloc(d->psize * d->pchan * sizeof(adata_t));
+ d->mode |= MODE_MON;
+
+ /* Append a converter, if needed. */
+ if (!aparams_native(&d->par)) {
+ enc_init(&d->enc, &d->par, d->pchan);
+ d->encbuf = xmalloc(d->round * d->pchan * d->par.bps);
+ } else
+ d->encbuf = NULL;
+
+ /*
+ * Initially fill the record buffer with zeroed samples. This ensures
+ * that when a client records from a play-only device the client just
+ * gets silence.
+ */
+ memset(d->rbuf, 0, d->round * d->rchan * sizeof(adata_t));
- /*
- * Append a converter, if needed.
- */
- if (!aparams_native(&d->par)) {
- enc_init(&d->enc, &d->par, d->pchan);
- d->encbuf = xmalloc(d->round * d->pchan * d->par.bps);
- } else
- d->encbuf = NULL;
- }
if (log_level >= 2) {
dev_log(d);
log_puts(": ");
@@ -1935,8 +1943,6 @@ found:
slot_log(s);
log_puts(": requested mode not supported\n");
}
- dev_unref(opt->dev);
- return NULL;
}
s->opt = opt;
s->ops = ops;
@@ -2055,13 +2061,7 @@ slot_attach(struct slot *s)
* because dev_xxx() functions are supposed to
* work (i.e., not to crash)
*/
-#ifdef DEBUG
- if ((s->mode & d->mode) != s->mode) {
- slot_log(s);
- log_puts(": mode beyond device mode, not attaching\n");
- panic();
- }
-#endif
+
s->next = d->slot_list;
d->slot_list = s;
if (s->mode & MODE_PLAY) {