shithub: orca

Download patch

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;
 					}
 				}
 			}