summaryrefslogtreecommitdiff
path: root/usr.bin/sndiod
diff options
context:
space:
mode:
authorAlexandre Ratchov <ratchov@cvs.openbsd.org>2020-01-23 05:27:18 +0000
committerAlexandre Ratchov <ratchov@cvs.openbsd.org>2020-01-23 05:27:18 +0000
commit5a3e5935493b5d9d43d0455f911c47655fdbd78f (patch)
tree6d5202bf5174adc44a0b8cfe57d8785da3c9af9b /usr.bin/sndiod
parent83911a0cf9ebdba2116f0f04c152a4223f77dbc8 (diff)
Accept MIDI clients that don't reset status during sysex messages.
The MIDI protocol requires the status byte to be resent after common messages, including system exclusive messages. But, some MIDI clients forget to resend it; we workaround this restoring the status byte after sysex messages.
Diffstat (limited to 'usr.bin/sndiod')
-rw-r--r--usr.bin/sndiod/midi.c18
-rw-r--r--usr.bin/sndiod/midi.h3
2 files changed, 17 insertions, 4 deletions
diff --git a/usr.bin/sndiod/midi.c b/usr.bin/sndiod/midi.c
index 46ac3929f24..d84bd3aa971 100644
--- a/usr.bin/sndiod/midi.c
+++ b/usr.bin/sndiod/midi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.c,v 1.22 2019/09/21 04:42:46 ratchov Exp $ */
+/* $OpenBSD: midi.c,v 1.23 2020/01/23 05:27:17 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -92,6 +92,7 @@ midi_new(struct midiops *ops, void *arg, int mode)
ep->len = 0;
ep->idx = 0;
ep->st = 0;
+ ep->last_st = 0;
ep->txmask = 0;
ep->self = 1 << i;
ep->tickets = 0;
@@ -305,7 +306,18 @@ midi_in(struct midi *iep, unsigned char *idata, int icount)
iep->msg[iep->idx++] = c;
iep->ops->imsg(iep->arg, iep->msg, iep->idx);
}
- iep->st = 0;
+
+ /*
+ * There are bogus MIDI sources that keep
+ * state across sysex; Linux virmidi ports fed
+ * by the sequencer is an example. We
+ * workaround this by saving the current
+ * status and restoring it at the end of the
+ * sysex.
+ */
+ iep->st = iep->last_st;
+ if (iep->st)
+ iep->len = voice_len[(iep->st >> 4) & 7];
iep->idx = 0;
} else if (c >= 0xf0) {
iep->msg[0] = c;
@@ -315,7 +327,7 @@ midi_in(struct midi *iep, unsigned char *idata, int icount)
} else if (c >= 0x80) {
iep->msg[0] = c;
iep->len = voice_len[(c >> 4) & 7];
- iep->st = c;
+ iep->last_st = iep->st = c;
iep->idx = 1;
} else if (iep->st) {
if (iep->idx == 0 && iep->st != SYSEX_START)
diff --git a/usr.bin/sndiod/midi.h b/usr.bin/sndiod/midi.h
index c9f48875d70..15d293597f4 100644
--- a/usr.bin/sndiod/midi.h
+++ b/usr.bin/sndiod/midi.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: midi.h,v 1.10 2019/09/21 04:42:46 ratchov Exp $ */
+/* $OpenBSD: midi.h,v 1.11 2020/01/23 05:27:17 ratchov Exp $ */
/*
* Copyright (c) 2008-2012 Alexandre Ratchov <alex@caoua.org>
*
@@ -68,6 +68,7 @@ struct midi {
#define MIDI_MSGMAX 16 /* max size of MIDI msg */
unsigned char msg[MIDI_MSGMAX]; /* parsed input message */
unsigned int st; /* input MIDI running status */
+ unsigned int last_st; /* backup of st during sysex */
unsigned int used; /* bytes used in ``msg'' */
unsigned int idx; /* current ``msg'' size */
unsigned int len; /* expected ``msg'' length */