diff --git a/src/gui/midi.cpp b/src/gui/midi.cpp index 241f688e..692784ec 100644 --- a/src/gui/midi.cpp +++ b/src/gui/midi.cpp @@ -16,10 +16,17 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include +#include #include "dosbox.h" +#include "cross.h" +#include "support.h" #include "setup.h" +#define SYSEX_SIZE 1024 + Bit8u MIDI_evt_len[256] = { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x10 @@ -43,25 +50,42 @@ Bit8u MIDI_evt_len[256] = { 0,2,3,2, 0,0,1,1, 1,0,1,1, 1,0,1,1 // 0xf0 }; -#define SYSEX_SIZE 1024 - -#if defined (WIN32) +class MidiHandler; + +MidiHandler * handler_list=0; + +class MidiHandler { +public: + MidiHandler() { + next=handler_list; + handler_list=this; + }; + virtual bool Open(const char * conf) { return true; }; + virtual void Close(void) {}; + virtual void PlayMsg(Bit32u msg) {}; + virtual void PlaySysex(Bit8u * sysex,Bitu len) {}; + virtual char * GetName(void) { return "none"; }; + MidiHandler * next; +}; + +MidiHandler Midi_none; + +/* Include different midi drivers, lowest ones get checked first for default */ + +#if defined(MACOSX) + +#include "midi_coreaudio.h" + +#elif defined (WIN32) #include "midi_win32.h" -#elif defined (UNIX) && !defined(__BEOS__) +#elif #include "midi_oss.h" -#else /* Fall back to no device playing */ - -static void MIDI_PlayMsg(Bit32u msg) {} -static void MIDI_PlaySysex(Bit8u * sysex,Bitu len) {}; -static bool MIDI_StartUp(void) { return false;} - #endif - static struct { Bitu status; Bitu cmd_len; @@ -75,9 +99,9 @@ static struct { bool active; } sysex; bool available; + MidiHandler * handler; } midi; - void MIDI_RawOutByte(Bit8u data) { /* Test for a new status byte */ if (midi.sysex.active && !(data&0x80)) { @@ -87,7 +111,7 @@ void MIDI_RawOutByte(Bit8u data) { if (midi.sysex.active) { /* Play a sysex message */ midi.sysex.buf[midi.sysex.used++]=0xf7; - MIDI_PlaySysex(midi.sysex.buf,midi.sysex.used); + midi.handler->PlaySysex(midi.sysex.buf,midi.sysex.used); LOG(0,"Sysex message size %d",midi.sysex.used); midi.sysex.active=false; if (data==0xf7) return; @@ -106,7 +130,7 @@ void MIDI_RawOutByte(Bit8u data) { midi.cmd_msg|=data << (8 * midi.cmd_pos); midi.cmd_pos++; if (midi.cmd_pos >= midi.cmd_len) { - MIDI_PlayMsg(midi.cmd_msg); + midi.handler->PlayMsg(midi.cmd_msg); midi.cmd_msg=midi.status; midi.cmd_pos=1; } @@ -116,9 +140,41 @@ bool MIDI_Available(void) { return midi.available; } - -void MIDI_Init(Section * sect) { - MSG_Add("MIDI_CONFIGFILE_HELP","Nothing to setup yet!\n"); - midi.available=MIDI_StartUp(); +void MIDI_Init(Section * sec) { + Section_prop * section=static_cast(sec); + MSG_Add("MIDI_CONFIGFILE_HELP","Set midi output device,alsa,oss,win32,coreaudio,none\n"); + const char * dev=section->Get_string("device"); + const char * conf=section->Get_string("config"); + /* If device = "default" go for first handler that works */ + MidiHandler * handler; + if (!strcasecmp(dev,"default")) goto getdefault; + handler=handler_list; + while (handler) { + if (!strcasecmp(dev,handler->GetName())) { + if (!handler->Open(conf)) { + LOG_MSG("MIDI:Can't open device:%s with config:%s.",dev,conf); + goto getdefault; + } + midi.handler=handler; + midi.available=true; + LOG_MSG("MIDI:Opened device:%s",handler->GetName()); + return; + } + handler=handler->next; + } + LOG_MSG("MIDI:Can't find device:%s, finding default handler.",dev); +getdefault: + handler=handler_list; + while (handler) { + if (handler->Open(conf)) { + midi.available=true; + midi.handler=handler; + LOG_MSG("MIDI:Opened device:%s",handler->GetName()); + return; + } + handler=handler->next; + } + /* This shouldn't be possible */ + midi.available=false; } diff --git a/src/gui/midi_oss.h b/src/gui/midi_oss.h index a45e25bc..d4a1c8a5 100644 --- a/src/gui/midi_oss.h +++ b/src/gui/midi_oss.h @@ -17,44 +17,60 @@ */ #include - -static int m_device; - #define SEQ_MIDIPUTC 5 -static void MIDI_PlaySysex(Bit8u * sysex,Bitu len) { - Bit8u buf[SYSEX_SIZE*4];Bitu pos=0; - for (;len>0;len--) { - buf[pos++] = SEQ_MIDIPUTC; - buf[pos++] = *sysex++; - buf[pos++] = 0; //Device 0? - buf[pos++] = 0; +class MidiHandler_oss: public MidiHandler { +private: + int device; + Bit8u device_num; + bool isOpen; +public: + MidiHandler_oss() : isOpen(false),MidiHandler() {}; + char * GetName(void) { return "oss";}; + bool Open(const char * conf) { + char devname[512]; + if (conf && conf[0]) strncpy(devname,conf,512); + else strcpy(devname,"/dev/midi"); + char * devfind=(strrchr(devname,',')); + if (devfind) { + *devfind++=0; + device_num=atoi(devfind); + } else device_num=0; + if (isOpen) return false; + device=open(devname, O_WRONLY, 0); + if (device<0) return false; + return true; + }; + void Close(void) { + if (!isOpen) return; + if (device>0) close(device); + }; + void PlayMsg(Bit32u msg) { + Bit8u buf[128];Bitu pos=0; + Bitu len=MIDI_evt_len[msg & 0xff]; + for (;len>0;len--) { + buf[pos++] = SEQ_MIDIPUTC; + buf[pos++] = msg & 0xff; + buf[pos++] = device_num; + buf[pos++] = 0; + msg >>=8; + } + write(device,buf,pos); + }; + void PlaySysex(Bit8u * sysex,Bitu len) { + Bit8u buf[SYSEX_SIZE*4];Bitu pos=0; + for (;len>0;len--) { + buf[pos++] = SEQ_MIDIPUTC; + buf[pos++] = *sysex++; + buf[pos++] = device_num; + buf[pos++] = 0; + } + write(device,buf,pos); } - write(m_device,buf,pos); -} +}; + +MidiHandler_oss Midi_oss; + -static void MIDI_PlayMsg(Bit32u msg) { - Bit8u buf[128];Bitu pos=0; - - Bitu len=MIDI_evt_len[msg & 0xff]; - for (;len>0;len--) { - buf[pos++] = SEQ_MIDIPUTC; - buf[pos++] = msg & 0xff; - buf[pos++] = 0; //Device 0? - buf[pos++] = 0; - msg >>=8; - } - write(m_device,buf,pos); -} - -static void MIDI_ShutDown(void) { - if (m_device>0) close(m_device); -} - -static bool MIDI_StartUp(void) { - m_device=open("/dev/midi", O_WRONLY, 0); - if (m_device<0) return false; - return true; -} diff --git a/src/gui/midi_win32.h b/src/gui/midi_win32.h index 5f6e1d1d..54d33179 100644 --- a/src/gui/midi_win32.h +++ b/src/gui/midi_win32.h @@ -19,46 +19,55 @@ #include #include -static HMIDIOUT m_out; -static MIDIHDR m_hdr; -static HANDLE m_event; +class MidiHandler_win32: public MidiHandler { +private: + HMIDIOUT m_out; + MIDIHDR m_hdr; + HANDLE m_event; + bool isOpen; +public: + MidiHandler_win32() : isOpen(false),MidiHandler() {}; + char * GetName(void) { return "win32";}; + bool Open(const char * conf) { + if (isOpen) return false; + m_event = CreateEvent (NULL, true, true, NULL); + MMRESULT res = midiOutOpen(&m_out, MIDI_MAPPER, (DWORD)m_event, 0, CALLBACK_EVENT); + if (res != MMSYSERR_NOERROR) return false; + isOpen=true; + return true; + }; + void Close(void) { + if (!isOpen) return; + isOpen=false; + midiOutClose(m_out); + CloseHandle (m_event); + }; + void PlayMsg(Bit32u msg) { + midiOutShortMsg(m_out, msg); + }; + void PlaySysex(Bit8u * sysex,Bitu len) { + if (WaitForSingleObject (m_event, 2000) == WAIT_TIMEOUT) { + LOG(LOG_MISC|LOG_ERROR,"Can't send midi message"); + return; + } + midiOutUnprepareHeader (m_out, &m_hdr, sizeof (m_hdr)); + + m_hdr.lpData = (char *) sysex; + m_hdr.dwBufferLength = len ; + m_hdr.dwBytesRecorded = len ; + m_hdr.dwUser = 0; - -static void MIDI_PlaySysex(Bit8u * sysex,Bitu len) { - - if (WaitForSingleObject (m_event, 2000) == WAIT_TIMEOUT) { - LOG(LOG_MISC|LOG_ERROR,"Can't send midi message"); - return; - } - midiOutUnprepareHeader (m_out, &m_hdr, sizeof (m_hdr)); - - m_hdr.lpData = (char *) sysex; - m_hdr.dwBufferLength = len ; - m_hdr.dwBytesRecorded = len ; - m_hdr.dwUser = 0; - - MMRESULT result = midiOutPrepareHeader (m_out, &m_hdr, sizeof (m_hdr)); - if (result != MMSYSERR_NOERROR) return; - ResetEvent (m_event); - result = midiOutLongMsg (m_out,&m_hdr,sizeof(m_hdr)); - if (result != MMSYSERR_NOERROR) { - SetEvent (m_event); - return; + MMRESULT result = midiOutPrepareHeader (m_out, &m_hdr, sizeof (m_hdr)); + if (result != MMSYSERR_NOERROR) return; + ResetEvent (m_event); + result = midiOutLongMsg (m_out,&m_hdr,sizeof(m_hdr)); + if (result != MMSYSERR_NOERROR) { + SetEvent (m_event); + return; + } } -} - -static void MIDI_PlayMsg(Bit32u msg) { - MMRESULT ret=midiOutShortMsg(m_out, msg); -} - - - -static bool MIDI_StartUp(void) { - m_event = CreateEvent (NULL, true, true, NULL); - MMRESULT res = midiOutOpen(&m_out, MIDI_MAPPER, (DWORD)m_event, 0, CALLBACK_EVENT); - if (res != MMSYSERR_NOERROR) return false; - return true; -} +}; +MidiHandler_win32 Midi_win32;