summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2024-05-03 05:18:10 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2024-05-03 05:18:10 +0000
commit614cf4f41f50326c5eb1f40dcea91606e25c822c (patch)
tree8e23f88173ea3d6269923de6392b7743a5d3ccb6
parentebbb471129a0b9ae84fcbfcda0ddd7d6c3fe1054 (diff)
sndiod: Fix SIGHUP to reopen the devices in priority order
With this commit, SIGHUP makes sndiod discover new devices and if there is a new device with higher priority (greater -F option number) than the current one, sndiod switches to it. If the current device is already the one with the highest priority (i.e. last -F), then SIGHUP does nothing.
-rw-r--r--usr.bin/sndiod/midi.c19
-rw-r--r--usr.bin/sndiod/midi.h3
-rw-r--r--usr.bin/sndiod/sndiod.c111
3 files changed, 107 insertions, 26 deletions
diff --git a/usr.bin/sndiod/midi.c b/usr.bin/sndiod/midi.c
index 371a830908f..3290e6b5f75 100644
--- a/usr.bin/sndiod/midi.c
+++ b/usr.bin/sndiod/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.29 2021/11/01 14:43:25 ratchov Exp $ */
+/* $OpenBSD: midi.c,v 1.30 2024/05/03 05:18:09 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -155,6 +155,23 @@ midi_link(struct midi *ep, struct midi *peer)
}
/*
+ * return the list of endpoints the given one receives from
+ */
+unsigned int
+midi_rxmask(struct midi *ep)
+{
+ int i, rxmask;
+
+ for (rxmask = 0, i = 0; i < MIDI_NEP; i++) {
+ if ((midi_ep[i].txmask & ep->self) == 0)
+ continue;
+ rxmask |= midi_ep[i].self;
+ }
+
+ return rxmask;
+}
+
+/*
* add the midi endpoint in the ``tag'' midi thru box
*/
void
diff --git a/usr.bin/sndiod/midi.h b/usr.bin/sndiod/midi.h
index cd398de4ca5..7872f5b7f65 100644
--- a/usr.bin/sndiod/midi.h
+++ b/usr.bin/sndiod/midi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.h,v 1.15 2021/11/01 14:43:25 ratchov Exp $ */
+/* $OpenBSD: midi.h,v 1.16 2024/05/03 05:18:09 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -112,6 +112,7 @@ void midi_send(struct midi *, unsigned char *, int);
void midi_fill(struct midi *);
void midi_tag(struct midi *, unsigned int);
unsigned int midi_tags(struct midi *);
+unsigned int midi_rxmask(struct midi *);
void midi_link(struct midi *, struct midi *);
void midi_abort(struct midi *);
void midi_migrate(struct midi *, struct midi *);
diff --git a/usr.bin/sndiod/sndiod.c b/usr.bin/sndiod/sndiod.c
index b1719f1549d..9b138b71023 100644
--- a/usr.bin/sndiod/sndiod.c
+++ b/usr.bin/sndiod/sndiod.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sndiod.c,v 1.48 2022/03/07 08:58:33 ratchov Exp $ */
+/* $OpenBSD: sndiod.c,v 1.49 2024/05/03 05:18:09 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -254,6 +254,89 @@ opt_mode(void)
return mode;
}
+/*
+ * Open all devices. Possibly switch to the new devices if they have higher
+ * priorities than the current ones.
+ */
+static void
+reopen_devs(void)
+{
+ struct opt *o;
+ struct dev *d, *a;
+
+ for (o = opt_list; o != NULL; o = o->next) {
+
+ /* skip unused logical devices and ones with fixed hardware */
+ if (o->refcnt == 0 || strcmp(o->name, o->dev->name) == 0)
+ continue;
+
+ /* circulate to the device with the highest prio */
+ a = o->alt_first;
+ for (d = a; d->alt_next != a; d = d->alt_next) {
+ if (d->num > o->alt_first->num)
+ o->alt_first = d;
+ }
+
+ /* switch to the first working one, in pririty order */
+ d = o->alt_first;
+ while (d != o->dev) {
+ if (opt_setdev(o, d))
+ break;
+ d = d->alt_next;
+ }
+ }
+
+ /*
+ * retry to open the remaining devices that are not used but need
+ * to stay open (ex. '-a on')
+ */
+ for (d = dev_list; d != NULL; d = d->next) {
+ if (d->refcnt > 0 && d->pstate == DEV_CFG)
+ dev_open(d);
+ }
+}
+
+/*
+ * For each port, open the alt with the highest priority and switch to it
+ */
+static void
+reopen_ports(void)
+{
+ struct port *p, *a, *apri;
+ int inuse;
+
+ for (p = port_list; p != NULL; p = a->next) {
+
+ /* skip unused ports */
+ inuse = 0;
+ a = p;
+ while (1) {
+ if (midi_rxmask(a->midi) || a->midi->txmask)
+ inuse = 1;
+ if (a->alt_next == p)
+ break;
+ a = a->alt_next;
+ }
+ if (!inuse)
+ continue;
+
+ /* open the alt with the highest prio */
+ apri = port_alt_ref(p->num);
+
+ /* switch to it */
+ a = p;
+ while (1) {
+ if (a != apri) {
+ midi_migrate(a->midi, apri->midi);
+ port_unref(a);
+ }
+ if (a->alt_next == p)
+ break;
+ a = a->alt_next;
+ }
+ }
+}
+
void
setsig(void)
{
@@ -461,7 +544,6 @@ main(int argc, char **argv)
char base[SOCKPATH_MAX], path[SOCKPATH_MAX];
unsigned int mode, dup, mmc, vol;
unsigned int hold, autovol, bufsz, round, rate;
- unsigned int reopen_list;
const char *str;
struct aparams par;
struct opt *o;
@@ -712,33 +794,14 @@ main(int argc, char **argv)
if (pledge("stdio audio recvfd unix", NULL) == -1)
err(1, "pledge");
}
+
for (;;) {
if (quit_flag)
break;
if (reopen_flag) {
reopen_flag = 0;
-
- reopen_list = 0;
- for (d = dev_list; d != NULL; d = d->next) {
- if (d->pstate != DEV_CFG)
- reopen_list |= (1 << d->num);
- }
- for (d = dev_list; d != NULL; d = d->next) {
- if (reopen_list & (1 << d->num))
- dev_migrate(d);
- }
-
- reopen_list = 0;
- for (p = port_list; p != NULL; p = p->next) {
- if (p->state != PORT_CFG)
- reopen_list |= (1 << p->num);
- }
- for (p = port_list; p != NULL; p = p->next) {
- if (reopen_list & (1 << p->num)) {
- if (port_migrate(p) != p)
- port_close(p);
- }
- }
+ reopen_devs();
+ reopen_ports();
}
if (!fdpass_peer)
break;