aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMax Horn2002-04-26 13:18:49 +0000
committerMax Horn2002-04-26 13:18:49 +0000
commitd83fcb54d0b8120dc584113461416a2878c1f9a3 (patch)
tree0417f9f8fe2646c9699dda5fbae58f8f412e97c6 /sound
parentd5d06612ed9d3c7e3966f673a791ad30984cf1c6 (diff)
downloadscummvm-rg350-d83fcb54d0b8120dc584113461416a2878c1f9a3.tar.gz
scummvm-rg350-d83fcb54d0b8120dc584113461416a2878c1f9a3.tar.bz2
scummvm-rg350-d83fcb54d0b8120dc584113461416a2878c1f9a3.zip
added new style midi drivers using QuickTime (MacOS 9 & X) and CoreAudio (MacOS X)
svn-id: r4086
Diffstat (limited to 'sound')
-rw-r--r--sound/mididrv.cpp599
-rw-r--r--sound/mididrv.h18
2 files changed, 271 insertions, 346 deletions
diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp
index e1b7950fa5..50d891ae75 100644
--- a/sound/mididrv.cpp
+++ b/sound/mididrv.cpp
@@ -288,9 +288,6 @@ private:
StreamCallback *_stream_proc;
void *_stream_param;
int _mode;
- uint16 _time_div;
-
- uint32 property(int prop, uint32 param);
};
void MidiDriver_AMIDI::set_stream_callback(void *param, StreamCallback *sc) {
@@ -330,17 +327,6 @@ void MidiDriver_AMIDI::pause(bool pause) {
}
}
-uint32 MidiDriver_AMIDI::property(int prop, uint32 param) {
- switch(prop) {
- /* 16-bit time division according to standard midi specification */
- case PROP_TIMEDIV:
- _time_div = (uint16)param;
- return 1;
- }
-
- return 0;
-}
-
MidiDriver *MidiDriver_AMIDI_create() {
return new MidiDriver_AMIDI();
}
@@ -366,9 +352,7 @@ private:
StreamCallback *_stream_proc;
void *_stream_param;
int _mode;
- uint16 _time_div;
int device;
- uint32 property(int prop, uint32 param);
};
MidiDriver_SEQ::MidiDriver_SEQ(){
@@ -469,20 +453,19 @@ void MidiDriver_SEQ::destroy() {
delete this;
}
-uint32 MidiDriver_SEQ::property(int prop, uint32 param) {
- switch(prop) {
- /* 16-bit time division according to standard midi specification */
- case PROP_TIMEDIV:
- _time_div = (uint16)param;
- return 1;
- }
-
- return 0;
-}
#endif
-/* NULL driver */
-class MidiDriver_NULL : public MidiDriver {
+#if defined(__APPLE__) || defined(__APPLE_CW)
+// FIXME - this is for Mac OS X and Mac OS 9. It's not really possible
+// to check for these *cleanly* without a configure script, though..
+
+#include <QuickTime/QuickTimeComponents.h>
+#include <QuickTime/QuickTimeMusic.h>
+
+
+
+/* QuickTime MIDI driver */
+class MidiDriver_QT : public MidiDriver {
public:
void destroy();
int open(int mode);
@@ -490,264 +473,37 @@ public:
void send(uint32 b);
void pause(bool pause);
void set_stream_callback(void *param, StreamCallback *sc);
- uint32 property(int prop, uint32 param);
-private:
-};
-
-int MidiDriver_NULL::open(int mode) {
- warning("Music not enabled - MIDI support selected with no MIDI driver available. Try Adlib");
- return 0;
-}
-void MidiDriver_NULL::close() {}
-void MidiDriver_NULL::destroy() {}
-void MidiDriver_NULL::send(uint32 b) {}
-void MidiDriver_NULL::pause(bool pause) {}
-void MidiDriver_NULL::set_stream_callback(void *param, StreamCallback *sc) {}
-uint32 MidiDriver_NULL::property(int prop, uint32 param) { return 0; }
-
-MidiDriver *MidiDriver_NULL_create() {
- return new MidiDriver_NULL();
-}
-
-
-/* retrieve a string representation of an error code */
-const char *MidiDriver::get_error_name(int error_code) {
- static const char * const midi_errors[] = {
- "No error",
- "Cannot connect",
- "Streaming not available",
- "Device not available",
- "Driver already open"
- };
-
- if ((uint)error_code >= ARRAYSIZE(midi_errors))
- return "Unknown Error";
- return midi_errors[error_code];
-}
-
-
-
-
-
-
-
-
-#if 0
-
-
-void MidiDriver::midiInit()
-{
- if (MidiInitialized != true) {
- switch (DeviceType) {
- case MIDI_NULL:
- midiInitNull();
- break;
- case MIDI_WINDOWS:
- midiInitWindows();
- break;
- case MIDI_TIMIDITY:
- midiInitTimidity();
- break;
- case MIDI_SEQ:
- midiInitSeq();
- break;
- case MIDI_QTMUSIC:
- midiInitQuicktime();
- break;
- case MIDI_AMIDI:
- break;
- default:
- DeviceType = 0;
- midiInitNull();
- break;
- }
- MidiInitialized = true;
- } else {
- error("Midi driver already initialized");
- }
-}
-
-void MidiDriver::MidiOut(int b)
-{
- if (MidiInitialized != true)
- midiInit();
-
- if (MidiInitialized == true) {
- switch (DeviceType) {
- case MIDI_NULL:
- break;
- case MIDI_WINDOWS:
- MidiOutWindows(_mo, b);
- break;
- case MIDI_TIMIDITY:
- case MIDI_SEQ:
- MidiOutSeq(_mo, b);
- break;
- case MIDI_QTMUSIC:
- MidiOutQuicktime(_mo, b);
- break;
- case MIDI_AMIDI:
- MidiOutMorphOS(_mo, b);
- break;
- default:
- error("Invalid midi device type ");
- break;
- }
- } else {
- warning("Trying to write midi data without the driver being initialized");
- }
-}
-
-/*********** Windows */
-void MidiDriver::midiInitWindows()
-{
-#ifdef WIN32
- if (midiOutOpen((HMIDIOUT *) & _mo, MIDI_MAPPER, NULL, NULL, 0) !=
- MMSYSERR_NOERROR)
- error("midiOutOpen failed");
-#endif
-}
-
-void MidiDriver::MidiOutWindows(void *a, int b)
-{
-#ifdef WIN32
- midiOutShortMsg((HMIDIOUT) a, b);
-#endif
-}
-
-/*********** Raw midi support */
-void MidiDriver::midiInitSeq()
-{
- int device = open_sequencer_device();
- _mo = (void *)device;
-}
-
-int MidiDriver::open_sequencer_device()
-{
- int device = 0;
-#if !defined(__APPLE__CW) // No getenv support on Apple Carbon
- char *device_name = getenv("SCUMMVM_MIDI");
- if (device_name != NULL) {
- device = (open((device_name), O_RDWR, 0));
- } else {
- warning
- ("You need to set-up the SCUMMVM_MIDI environment variable properly (see readme.txt) ");
- }
- if ((device_name == NULL) || (device < 0)) {
- if (device_name == NULL)
- warning("Opening /dev/null (no music will be heard) ");
- else
- warning
- ("Cannot open rawmidi device %s - using /dev/null (no music will be heard) ",
- device_name);
- device = (open(("/dev/null"), O_RDWR, 0));
- if (device < 0)
- error("Cannot open /dev/null to dump midi output");
- }
-#endif
- return device;
-}
-
-/*********** Timidity */
-int MidiDriver::connect_to_timidity(int port)
-{
- int s = 0;
-#if !defined(__APPLE__CW) && !defined(__MORPHOS__) // No socket support on Apple Carbon or Morphos
- struct hostent *serverhost;
- struct sockaddr_in sadd;
-
- serverhost = gethostbyname("localhost");
- if (serverhost == NULL)
- error("Could not resolve Timidity host ('localhost')");
-
- sadd.sin_family = serverhost->h_addrtype;
- sadd.sin_port = htons(port);
- memcpy(&(sadd.sin_addr), serverhost->h_addr_list[0], serverhost->h_length);
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s < 0)
- error("Could not open Timidity socket");
-
- if (connect(s, (struct sockaddr *)&sadd, sizeof(struct sockaddr_in)) < 0)
- error("Could not connect to Timidity server");
-#endif
- return s;
-}
-void MidiDriver::midiInitTimidity()
-{
- int s, s2;
- int len;
- int dummy, newport;
- char buf[256];
-
- s = connect_to_timidity(7777);
- len = read(s, buf, 256); // buf[len] = '\0'; printf("%s", buf);
- sprintf(buf, "SETBUF %f %f\n", 0.1, 0.15);
- write(s, buf, strlen(buf));
- len = read(s, buf, 256); // buf[len] = '\0'; printf("%s", buf);
-
- sprintf(buf, "OPEN lsb\n");
- write(s, buf, strlen(buf));
- len = read(s, buf, 256); // buf[len] = '\0'; printf("%s", buf);
+private:
+ NoteAllocator qtNoteAllocator;
+ NoteChannel qtNoteChannel[16];
+ NoteRequest simpleNoteRequest;
- sscanf(buf, "%d %d", &dummy, &newport);
- printf(" => port = %d\n", newport);
+ StreamCallback *_stream_proc;
+ void *_stream_param;
+ int _mode;
+};
- s2 = connect_to_timidity(newport);
- _mo = (void *)s2;
+void MidiDriver_QT::set_stream_callback(void *param, StreamCallback *sc) {
+ _stream_param = param;
+ _stream_proc = sc;
}
-void MidiDriver::MidiOutSeq(void *a, int b)
+void MidiDriver_QT::destroy()
{
- int s = (int)a;
- unsigned char buf[256];
- int position = 0;
-
- switch (b & 0xF0) {
- case 0x80:
- case 0x90:
- case 0xA0:
- case 0xB0:
- case 0xE0:
- buf[position++] = SEQ_MIDIPUTC;
- buf[position++] = b;
- buf[position++] = DEVICE_NUM;
- buf[position++] = 0;
- buf[position++] = SEQ_MIDIPUTC;
- buf[position++] = (b >> 8) & 0x7F;
- buf[position++] = DEVICE_NUM;
- buf[position++] = 0;
- buf[position++] = SEQ_MIDIPUTC;
- buf[position++] = (b >> 16) & 0x7F;
- buf[position++] = DEVICE_NUM;
- buf[position++] = 0;
- break;
- case 0xC0:
- case 0xD0:
- buf[position++] = SEQ_MIDIPUTC;
- buf[position++] = b;
- buf[position++] = DEVICE_NUM;
- buf[position++] = 0;
- buf[position++] = SEQ_MIDIPUTC;
- buf[position++] = (b >> 8) & 0x7F;
- buf[position++] = DEVICE_NUM;
- buf[position++] = 0;
- break;
- default:
- fprintf(stderr, "Unknown : %08x\n", b);
- break;
- }
- write(s, buf, position);
+ close();
+ delete this;
}
-/* Quicktime music support */
-void MidiDriver::midiInitQuicktime()
-{
-#ifdef __APPLE__CW
+int MidiDriver_QT::open(int mode) {
ComponentResult qtErr = noErr;
qtNoteAllocator = NULL;
+ if (mode == MO_STREAMING)
+ return MERR_STREAMING_NOT_AVAILABLE;
+
+ _mode = mode;
+
for (int i = 0; i < 15; i++)
qtNoteChannel[i] = NULL;
@@ -771,31 +527,51 @@ void MidiDriver::midiInitQuicktime()
if ((qtErr != noErr) || (qtNoteChannel == NULL))
goto bail;
}
- return;
+ return 0;
bail:
- fprintf(stderr, "Init QT failed %x %x %d\n", qtNoteAllocator, qtNoteChannel,
- qtErr);
+ error("Init QT failed %x %x %d\n", (int)qtNoteAllocator, (int)qtNoteChannel,
+ (int)qtErr);
for (int i = 0; i < 15; i++) {
if (qtNoteChannel[i] != NULL)
NADisposeNoteChannel(qtNoteAllocator, qtNoteChannel[i]);
+ qtNoteChannel[i] = NULL;
}
- if (qtNoteAllocator != NULL)
+ if (qtNoteAllocator != NULL) {
CloseComponent(qtNoteAllocator);
-#endif
+ qtNoteAllocator = NULL;
+ }
+
+ return MERR_DEVICE_NOT_AVAILABLE;
}
-void MidiDriver::MidiOutQuicktime(void *a, int b)
-{
-#ifdef __APPLE__CW
+void MidiDriver_QT::close() {
+ _mode = 0;
+
+ for (int i = 0; i < 15; i++) {
+ if (qtNoteChannel[i] != NULL)
+ NADisposeNoteChannel(qtNoteAllocator, qtNoteChannel[i]);
+ qtNoteChannel[i] = NULL;
+ }
+
+ if (qtNoteAllocator != NULL) {
+ CloseComponent(qtNoteAllocator);
+ qtNoteAllocator = NULL;
+ }
+}
+
+void MidiDriver_QT::send(uint32 b) {
+ if (_mode != MO_SIMPLE)
+ error("MidiDriver_QT:send called but driver is not in simple mode");
+
MusicMIDIPacket midPacket;
unsigned char *midiCmd = midPacket.data;
midPacket.length = 3;
midiCmd[3] = (b & 0xFF000000) >> 24;
midiCmd[2] = (b & 0x00FF0000) >> 16;
midiCmd[1] = (b & 0x0000FF00) >> 8;
- midiCmd[0] = b;
+ midiCmd[0] = (b & 0x000000FF);
unsigned char chanID = midiCmd[0] & 0x0F;
switch (midiCmd[0] & 0xF0) {
@@ -804,8 +580,7 @@ void MidiDriver::MidiOutQuicktime(void *a, int b)
break;
case 0x90: // Note on
- NAPlayNote(qtNoteAllocator, qtNoteChannel[chanID], midiCmd[1],
- midiCmd[2]);
+ NAPlayNote(qtNoteAllocator, qtNoteChannel[chanID], midiCmd[1], midiCmd[2]);
break;
case 0xB0: // Effect
@@ -846,7 +621,7 @@ void MidiDriver::MidiOutQuicktime(void *a, int b)
break;
default:
- fprintf(stderr, "Unknown MIDI effect: %08x\n", b);
+ error("Unknown MIDI effect: %08x\n", (int)b);
break;
}
break;
@@ -864,79 +639,227 @@ void MidiDriver::MidiOutQuicktime(void *a, int b)
break;
default:
- fprintf(stderr, "Unknown Command: %08x\n", b);
+ error("Unknown Command: %08x\n", (int)b);
NASendMIDI(qtNoteAllocator, qtNoteChannel[chanID], &midPacket);
break;
}
-#endif
}
-/*********** MorphOS */
-void MidiDriver::MidiOutMorphOS(void *a, int b)
-{
-#ifdef __MORPHOS__
- if (ScummMidiRequest) {
- ULONG midi_data = b; // you never know about an int's size ;-)
- ScummMidiRequest->amr_Std.io_Command = CMD_WRITE;
- ScummMidiRequest->amr_Std.io_Data = &midi_data;
- ScummMidiRequest->amr_Std.io_Length = 4;
- DoIO((struct IORequest *)ScummMidiRequest);
- }
-#endif
+void MidiDriver_QT::pause(bool pause) {
+}
+
+MidiDriver *MidiDriver_QT_create() {
+ return new MidiDriver_QT();
+}
+
+#endif // __APPLE__ || __APPLE_CW
+
+
+#ifdef __APPLE__
+
+#include <AudioUnit/AudioUnit.h>
+
+/* CoreAudio MIDI driver */
+/* Based on code by Benjamin W. Zale */
+class MidiDriver_CORE : public MidiDriver {
+public:
+ void destroy();
+ int open(int mode);
+ void close();
+ void send(uint32 b);
+ void pause(bool pause);
+ void set_stream_callback(void *param, StreamCallback *sc);
+
+private:
+ AudioUnit au_MusicDevice;
+
+ StreamCallback *_stream_proc;
+ void *_stream_param;
+ int _mode;
+};
+
+void MidiDriver_CORE::set_stream_callback(void *param, StreamCallback *sc) {
+ _stream_param = param;
+ _stream_proc = sc;
+}
+
+void MidiDriver_CORE::destroy() {
+ close();
+ delete this;
+}
+
+int MidiDriver_CORE::open(int mode) {
+ _mode = mode;
+
+ AudioUnit au_output;
+
+ int err;
+ struct AudioUnitConnection auconnect;
+ ComponentDescription compdesc;
+ Component compid;
+
+ au_MusicDevice=au_output=NULL;
+
+ //Open the Music Device
+ compdesc.componentType=kAudioUnitComponentType;
+ compdesc.componentSubType=kAudioUnitSubType_MusicDevice;
+ compdesc.componentManufacturer=kAudioUnitID_DLSSynth;
+ compdesc.componentFlags=0;
+ compdesc.componentFlagsMask=0;
+ compid=FindNextComponent(NULL,&compdesc);
+ au_MusicDevice=(AudioUnit)OpenComponent(compid);
+
+ // open the output unit
+ au_output=(AudioUnit)OpenDefaultComponent(kAudioUnitComponentType,kAudioUnitSubType_Output);
+ // connect the units
+ auconnect.sourceAudioUnit=au_MusicDevice;
+ auconnect.sourceOutputNumber=0;
+ auconnect.destInputNumber=0;
+ err=AudioUnitSetProperty(au_output,kAudioUnitProperty_MakeConnection,kAudioUnitScope_Input,0,(void*)&auconnect,sizeof(struct AudioUnitConnection));
+ // initialize the units
+ AudioUnitInitialize(au_MusicDevice);
+ AudioUnitInitialize(au_output);
+ // start the output
+ AudioOutputUnitStart(au_output);
+
+ return 0;
+}
+
+void MidiDriver_CORE::close() {
+ _mode = 0;
+}
+
+void MidiDriver_CORE::send(uint32 b) {
+ if (_mode != MO_SIMPLE)
+ error("MidiDriver_CORE:send called but driver is not in simple mode");
+
+ unsigned char first_byte, seccond_byte, status_byte;
+ status_byte = (b & 0x000000FF);
+ first_byte = (b & 0x0000FF00) >> 8;
+ seccond_byte = (b & 0x00FF0000) >> 16;
+ MusicDeviceMIDIEvent(au_MusicDevice, status_byte, first_byte, seccond_byte, 0);
+}
+
+void MidiDriver_CORE::pause(bool pause) {
+}
+
+MidiDriver *MidiDriver_CORE_create() {
+ return new MidiDriver_CORE();
+}
+
+#endif // __APPLE__
+
+/* NULL driver */
+class MidiDriver_NULL : public MidiDriver {
+public:
+ void destroy();
+ int open(int mode);
+ void close();
+ void send(uint32 b);
+ void pause(bool pause);
+ void set_stream_callback(void *param, StreamCallback *sc);
+private:
+};
+
+int MidiDriver_NULL::open(int mode) {
+ warning("Music not enabled - MIDI support selected with no MIDI driver available. Try Adlib");
+ return 0;
+}
+void MidiDriver_NULL::close() {}
+void MidiDriver_NULL::destroy() {}
+void MidiDriver_NULL::send(uint32 b) {}
+void MidiDriver_NULL::pause(bool pause) {}
+void MidiDriver_NULL::set_stream_callback(void *param, StreamCallback *sc) {}
+
+MidiDriver *MidiDriver_NULL_create() {
+ return new MidiDriver_NULL();
}
-void MidiDriver::midiInitNull()
+/* Default (empty) property method */
+uint32 MidiDriver::property(int prop, uint32 param)
{
- warning
- ("Music not enabled - MIDI support selected with no MIDI driver available. Try Adlib");
+ return 0;
}
+/* retrieve a string representation of an error code */
+const char *MidiDriver::get_error_name(int error_code) {
+ static const char * const midi_errors[] = {
+ "No error",
+ "Cannot connect",
+ "Streaming not available",
+ "Device not available",
+ "Driver already open"
+ };
+
+ if ((uint)error_code >= ARRAYSIZE(midi_errors))
+ return "Unknown Error";
+ return midi_errors[error_code];
+}
-/* old header stuff.. */
-/* General Midi header file */
-#define SEQ_MIDIPUTC 5
-#define SPECIAL_CHANNEL 9
-#define DEVICE_NUM 0
-#ifdef __APPLE__CW
- #include <QuickTimeComponents.h>
- #include "QuickTimeMusic.h"
- NoteAllocator qtNoteAllocator;
- NoteChannel qtNoteChannel[16];
- NoteRequest simpleNoteRequest;
-#endif
-#ifdef WIN32
- #include <winsock.h>
-#elif (defined(UNIX) || defined(UNIX_X11))
- #include <sys/time.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-#endif
+#if 0
+
+/* Old code for timidity support, maybe somebody can rewrite this for the
+ new midi driver system?
+ */
-#ifdef __MORPHOS__
- #include <exec/types.h>
- #include <devices/amidi.h>
- #define NO_PPCINLINE_STDARG
- #define NO_PPCINLINE_VARARGS
- #include <clib/alib_protos.h>
- #include <proto/exec.h>
- #undef CMD_INVALID
+/*********** Timidity */
+int MidiDriver::connect_to_timidity(int port)
+{
+ int s = 0;
+#if !defined(__APPLE__CW) && !defined(__MORPHOS__) // No socket support on Apple Carbon or Morphos
+ struct hostent *serverhost;
+ struct sockaddr_in sadd;
+
+ serverhost = gethostbyname("localhost");
+ if (serverhost == NULL)
+ error("Could not resolve Timidity host ('localhost')");
- extern struct IOMidiRequest *ScummMidiRequest;
+ sadd.sin_family = serverhost->h_addrtype;
+ sadd.sin_port = htons(port);
+ memcpy(&(sadd.sin_addr), serverhost->h_addr_list[0], serverhost->h_length);
+
+ s = socket(AF_INET, SOCK_STREAM, 0);
+ if (s < 0)
+ error("Could not open Timidity socket");
+
+ if (connect(s, (struct sockaddr *)&sadd, sizeof(struct sockaddr_in)) < 0)
+ error("Could not connect to Timidity server");
#endif
+ return s;
+}
+
+void MidiDriver::midiInitTimidity()
+{
+ int s, s2;
+ int len;
+ int dummy, newport;
+ char buf[256];
+
+ s = connect_to_timidity(7777);
+ len = read(s, buf, 256); // buf[len] = '\0'; printf("%s", buf);
+ sprintf(buf, "SETBUF %f %f\n", 0.1, 0.15);
+ write(s, buf, strlen(buf));
+ len = read(s, buf, 256); // buf[len] = '\0'; printf("%s", buf);
+
+ sprintf(buf, "OPEN lsb\n");
+ write(s, buf, strlen(buf));
+ len = read(s, buf, 256); // buf[len] = '\0'; printf("%s", buf);
+
+ sscanf(buf, "%d %d", &dummy, &newport);
+ printf(" => port = %d\n", newport);
+
+ s2 = connect_to_timidity(newport);
+ _mo = (void *)s2;
+}
+
#endif /* 0 */
diff --git a/sound/mididrv.h b/sound/mididrv.h
index 693226b612..61bd13d5ef 100644
--- a/sound/mididrv.h
+++ b/sound/mididrv.h
@@ -66,7 +66,7 @@ public:
/* destroy the midi object */
- virtual void destroy() = 0;
+// virtual void destroy() = 0;
/* open the midi driver.
* returns 0 if successful.
@@ -91,7 +91,7 @@ public:
/* Get or set a property */
- virtual uint32 property(int prop, uint32 param) = 0;
+ virtual uint32 property(int prop, uint32 param) ;
/* retrieve a string representation of an error code */
static const char *get_error_name(int error_code);
@@ -108,14 +108,16 @@ enum {
MD_SEQ = 4,
MD_QTMUSIC = 5,
MD_AMIDI = 6,
+ MD_COREAUDIO = 7,
};
/* Factory functions => no need to include the specific classes
* in this header => faster compile */
-MidiDriver *MidiDriver_NULL_create();
-MidiDriver *MidiDriver_WIN_create();
-MidiDriver *MidiDriver_TIMIDITY_create();
-MidiDriver *MidiDriver_SEQ_create();
-MidiDriver *MidiDriver_QT_create();
-MidiDriver *MidiDriver_AMIDI_create();
+extern MidiDriver *MidiDriver_NULL_create();
+extern MidiDriver *MidiDriver_WIN_create();
+extern MidiDriver *MidiDriver_TIMIDITY_create();
+extern MidiDriver *MidiDriver_SEQ_create();
+extern MidiDriver *MidiDriver_QT_create();
+extern MidiDriver *MidiDriver_CORE_create();
+extern MidiDriver *MidiDriver_AMIDI_create();