ref: ca65bd1678c46df10637aa2c9d961108363552e0
parent: 390569e0185d717594413aa0e7ce7265529d25e8
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Feb 24 17:44:02 EST 2020
plan9: refactor midi output, support mono mode
--- a/plan9.c
+++ b/plan9.c
@@ -76,6 +76,7 @@
static char *midipath;
static int midi = -1;
+static u8int noteoff[16][128]; /* 16 channels, 128 notes each */
static Rune *linebuf;
static Rune cursor = '@';
@@ -120,11 +121,6 @@
},
};
-static struct {
- u8int u[4];
- Usz at;
-}noteoff[16*128]; /* 16 channels, 128 notes each */
-
static u32int theme[Numcolors] = {
[Dback] = 0x000000ff,
[Dfhigh] = 0xffffffff,
@@ -526,29 +522,46 @@
static void
process(Oevent_list *events)
{
- int i, off, t;
+ int c, n, t;
Oevent *e;
u8int u[4];
char tmp[64];
- for (e = events->buffer, i = 0; i < events->count; i++, e++) {
+ for (e = events->buffer; e != events->buffer+events->count; e++) {
t = e->any.oevent_type;
if (midi >= 0) {
+ /*
+ * USB MIDI allegedly receives bulk transfers of a certain max size
+ * so a smarter thing to do would be to buffer up all notes on/off
+ * and write them in bulk after that.
+ * But a better way to do it would be through midifs, so it's
+ * implemented once. Still need to list available midi devices anyway.
+ */
if (t == Oevent_type_midi_note) {
- Oevent_midi_note *n = &e->midi_note;
+ Oevent_midi_note *m = &e->midi_note;
+
+ if (m->mono) {
+ /* idk if that's the right thing to do, just stop what's been playing on that channel */
+ u[0] = Midicn | 0x8;
+ u[1] = 0x80 | m->channel;
+ u[3] = 0;
+ for (n = 0; n < nelem(noteoff[m->channel]); n++) {
+ if (noteoff[m->channel][n] > 0) {
+ noteoff[m->channel][n] = 0;
+ u[2] = n;
+ write(midi, u, 4);
+ }
+ }
+ }
+
u[0] = Midicn | 0x9;
- u[1] = 0x90 | n->channel;
- u[2] = (n->octave + 1)*12 + n->note;
- u[3] = n->velocity;
+ u[1] = 0x90 | m->channel;
+ u[2] = (m->octave + 1)*12 + m->note;
+ u[3] = m->velocity;
write(midi, u, 4);
- off = n->channel*128 + u[2];
- noteoff[off].u[0] = Midicn | 0x8;
- noteoff[off].u[1] = 0x80 | n->channel;
- noteoff[off].u[2] = u[2];
- noteoff[off].u[3] = 0;
- noteoff[off].at = tick + n->duration;
+ noteoff[m->channel][u[2]] = m->duration + 1;
continue;
} else if (t == Oevent_type_midi_cc) {
Oevent_midi_cc *c = &e->midi_cc;
@@ -569,15 +582,11 @@
}
}
- if (udp >= 0) {
- if (t == Oevent_type_udp_string) {
- Oevent_udp_string *u = &e->udp_string;
- write(udp, u->chars, u->count); /* FIXME show errors */
- continue;
- }
- }
-
- if (t == Oevent_type_cmd_string) {
+ if (t == Oevent_type_udp_string && udp >= 0) {
+ Oevent_udp_string *u = &e->udp_string;
+ write(udp, u->chars, u->count); /* FIXME show errors */
+ continue;
+ } else if (t == Oevent_type_cmd_string) {
Oevent_cmd_string *c = &e->cmd_string;
memmove(tmp, c->chars, c->count);
tmp[c->count] = 0;
@@ -585,10 +594,17 @@
}
}
- for (i = 0; midi >= 0 && i < nelem(noteoff); i++) {
- if (noteoff[i].at > 0 && noteoff[i].at < tick) {
- write(midi, noteoff[i].u, 4);
- noteoff[i].at = 0;
+ if (midi >= 0) {
+ u[3] = 0;
+ for (c = 0; c < nelem(noteoff); c++) {
+ for (n = 0; n < nelem(noteoff[c]); n++) {
+ if (noteoff[c][n] > 0 && --noteoff[c][n] == 0) {
+ u[0] = Midicn | 0x8;
+ u[1] = 0x80 | c;
+ u[2] = n;
+ write(midi, u, 4);
+ }
+ }
}
}
}
@@ -1092,7 +1108,7 @@
shiftdown = true;
} else if (r == Kctl) {
ctldown = true;
- move = Pt(rulers.x, rulers.y);
+ move = rulers;
}
}
}