summaryrefslogtreecommitdiff
path: root/usr.bin/sndiod/dev.c
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2019-09-21 04:42:47 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2019-09-21 04:42:47 +0000
commit17f4ff917df990429b0ed07dffebb9b61351c9e5 (patch)
treed01111f6def9c42c9fcb83c3bf5b1dfeee18667d /usr.bin/sndiod/dev.c
parent5b30a703918faae856027a3d979171bac718aae6 (diff)
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@
Diffstat (limited to 'usr.bin/sndiod/dev.c')
-rw-r--r--usr.bin/sndiod/dev.c75
1 files changed, 72 insertions, 3 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);
}