diff --git a/sndiod/file.c b/sndiod/file.c index 255e822..9323367 100644 --- a/sndiod/file.c +++ b/sndiod/file.c @@ -235,6 +235,7 @@ file_new(struct fileops *ops, void *arg, char *name, unsigned int nfds) } f = xmalloc(sizeof(struct file)); f->max_nfds = nfds; + f->nfds = 0; f->ops = ops; f->arg = arg; f->name = name; diff --git a/sndiod/midi.c b/sndiod/midi.c index cf7aa74..7c91ec9 100644 --- a/sndiod/midi.c +++ b/sndiod/midi.c @@ -93,6 +93,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; @@ -306,7 +307,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; @@ -316,7 +328,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/sndiod/midi.h b/sndiod/midi.h index 9d7c9f5..e2ce168 100644 --- a/sndiod/midi.h +++ b/sndiod/midi.h @@ -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 */