Midi now uses midi device classes.
Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@808
This commit is contained in:
parent
cf27af6f8b
commit
bd50a564f0
3 changed files with 172 additions and 91 deletions
|
@ -16,10 +16,17 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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<Section_prop *>(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,44 +17,60 @@
|
|||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -19,46 +19,55 @@
|
|||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
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;
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue