Index: emu/mid.c
===================================================================
--- emu/mid.c	(revision 77d8df82f5dfc0eadc7b81c42db2c4f4773a428d)
+++ emu/mid.c	(revision 9ddbf3e3b93004ac7df85a6f7d2ae557d8dac5a9)
@@ -1,4 +1,4 @@
 /*
- *  Copyright (C) 2017 The Contributors
+ *  Copyright (C) 2017-2018 The Contributors
  *
  *  This program is free software: you can redistribute it and/or modify
@@ -17,9 +17,10 @@
 
 #include <all.h>
-#include <rtmidi/rtmidi_c.h>
 
 #define ver(...) _ver(mid_verbose, 0, __VA_ARGS__)
 #define ver2(...) _ver(mid_verbose, 1, __VA_ARGS__)
 #define ver3(...) _ver(mid_verbose, 2, __VA_ARGS__)
+
+int32_t mid_verbose = 0;
 
 #define REG_IER_ISR 0
@@ -45,7 +46,5 @@
 };
 
-int32_t mid_verbose = 0;
-
-struct RtMidiWrapper* mid_in;
+static struct RtMidiWrapper *mid_in = NULL;
 
 static void xmit(int32_t un)
@@ -74,6 +73,10 @@
 }
 
-static void out_lk(int32_t un, uint8_t c)
-{
+static void out(int32_t un, uint8_t c)
+{
+	if (SDL_LockMutex(cpu_mutex) < 0) {
+		fail("SDL_LockMutex() failed: %s", SDL_GetError());
+	}
+
 	int32_t i = state[un].buf_hd;
 	ver2("mid out %d %d 0x%02x", state[un].buf_tl, i, c);
@@ -90,13 +93,4 @@
 		xmit(un);
 	}
-}
-
-static void out(int32_t un, uint8_t c)
-{
-	if (SDL_LockMutex(cpu_mutex) < 0) {
-		fail("SDL_LockMutex() failed: %s", SDL_GetError());
-	}
-
-	out_lk(un, c);
 
 	if (SDL_UnlockMutex(cpu_mutex) < 0) {
@@ -105,13 +99,63 @@
 }
 
-static void mid_callback(double timeStamp, const unsigned char* message, size_t size, void *userData) {
-	(void) size;
-	(void) userData;
-
-	ver2("Timestamp %f\n", timeStamp);
-
-	for (uint8_t i = 0; i < sizeof(message); i++) {
-		ver2("Message %i %u", i, (uint8_t) message[i]);
-		out(0, message[i]);
+static void callback(double time, const uint8_t *midi, void *data)
+{
+	(void)data;
+
+	int32_t len;
+
+	switch (midi[0] & 0xf0) {
+	case 0x80: // note on
+	case 0x90: // note off
+	case 0xa0: // polyphonic key pressure
+	case 0xb0: // control change
+	case 0xe0: // pitch bend change
+		len = 3;
+		break;
+
+	case 0xc0: // program change
+	case 0xd0: // channel pressure
+		len = 2;
+		break;
+
+	case 0xf0:
+		switch (midi[0]) {
+		case 0xf0: // system exclusive
+		case 0xf4: // undefined
+		case 0xf5: // undefined
+		case 0xf7: // end of exclusive
+		case 0xf9: // undefined
+		case 0xfd: // undefined
+			len = -1;
+			break;
+
+		case 0xf1: // MIDI time code quarter frame
+		case 0xf3: // song select
+			len = 2;
+			break;
+
+		case 0xf2: // song position pointer
+			len = 3;
+			break;
+
+		case 0xf6: // tune request
+		case 0xf8: // timing clock
+		case 0xfa: // start
+		case 0xfb: // continue
+		case 0xfc: // stop
+		case 0xfe: // active sensing
+		case 0xff: // reset
+			len = 1;
+			break;
+		}
+
+		break;
+	}
+
+	ver2("time %f", time);
+
+	for (int32_t i = 0; i < len; ++i) {
+		ver2("midi[%d] 0x%02x", i, midi[i]);
+		out(0, midi[i]);
 	}
 }
@@ -121,33 +165,41 @@
 	ver("mid init");
 
+	if (mid_port < 0) {
+		ver("no MIDI requested");
+		return;
+	}
+
 	mid_in = rtmidi_in_create_default();
-	ver2("%p", mid_in->ptr);
-	// check if null
-
-	uint32_t portcount = rtmidi_get_port_count(mid_in);
-	if (portcount == 0) {
+
+	if (!mid_in->ok) {
+		fail("rtmidi_in_create_default() failed: %s", mid_in->msg);
+	}
+
+	int32_t n_ports = (int32_t)rtmidi_get_port_count(mid_in);
+
+	if (n_ports == 0) {
+		inf("no MIDI ports\n");
+		rtmidi_in_free(mid_in);
 		mid_in = NULL;
-		ver2("No MIDI ports\n");
-		return;
-	}
-
-	if (mid_port > portcount) {
-		mid_in = NULL;
-		ver2("Selected MIDI port larger than number of midi ports");
-		return;
-	}
-
-	rtmidi_open_port(mid_in, mid_port, rtmidi_get_port_name(mid_in, mid_port));
-
-	if(mid_in->ok == 0) {
-		fail("Failed to open MIDI port");
-	}
-
-	ver2("Using MIDI port %u", mid_port);
-
-	rtmidi_in_set_callback(mid_in, mid_callback, mid_in->data);
-
-	if(mid_in->ok == 0) {
-		fail("Failed to set MIDI Callback");
+		return;
+	}
+
+	if (mid_port >= n_ports) {
+		fail("invalid MIDI port %d selected (%d available)", mid_port, n_ports);
+	}
+
+	const char *name = rtmidi_get_port_name(mid_in, (uint32_t)mid_port);
+	rtmidi_open_port(mid_in, (uint32_t)mid_port, name);
+
+	if (!mid_in->ok) {
+		fail("error while opening MIDI port %d (%s): %s", mid_port, name, mid_in->msg);
+	}
+
+	inf("using MIDI port %d (%s)", mid_port, name);
+
+	rtmidi_in_set_callback(mid_in, callback, mid_in->data);
+
+	if (!mid_in->ok) {
+		fail("rtmidi_in_set_callback() failed: %s", mid_in->msg);
 	}
 }
@@ -155,10 +207,12 @@
 void mid_quit(void)
 {
-	if(mid_in) {
-		rtmidi_close_port(mid_in);
-		rtmidi_in_free(mid_in);
-	}
-
 	ver("mid quit");
+
+	if (mid_in == NULL) {
+		return;
+	}
+
+	rtmidi_close_port(mid_in);
+	rtmidi_in_free(mid_in);
 }
 
@@ -237,19 +291,22 @@
 }
 
-void mid_list(void) {
+void mid_list(void)
+{
 	mid_in = rtmidi_in_create_default();
 
-	uint32_t portcount = rtmidi_get_port_count(mid_in);
-
-	if (portcount == 0) {
-		mid_in = NULL;
-		ver2("no MIDI ports\n");
-		return;
-	}
-
-	fprintf(stdout, "the following MIDI ports are available:\n");
-
-	for (uint32_t i = 0; i < portcount; i++) {
-		fprintf(stdout, "port %d: %s\n", i, rtmidi_get_port_name(mid_in, i));
+	if (!mid_in->ok) {
+		fprintf(stderr, "rtmidi_in_create_default() failed: %s\n", mid_in->msg);
+		return;
+	}
+
+	uint32_t n_ports = rtmidi_get_port_count(mid_in);
+
+	if (n_ports == 0) {
+		fprintf(stdout, "no available MIDI ports\n");
+	}
+	else {
+		for (uint32_t i = 0; i < n_ports; i++) {
+			fprintf(stdout, "port %u: %s\n", i, rtmidi_get_port_name(mid_in, i));
+		}
 	}
 
