mirror of
https://github.com/ZDoom/fluidsynth.git
synced 2025-04-15 20:30:49 +00:00
Merge pull request #473 from carlo-bramini/winmidi-fixes-1
Minor Winmidi fixes
This commit is contained in:
commit
b9c253b6d9
1 changed files with 142 additions and 142 deletions
|
@ -57,17 +57,93 @@ typedef struct
|
|||
|
||||
} fluid_winmidi_driver_t;
|
||||
|
||||
static char fluid_winmidi_error_buffer[256];
|
||||
|
||||
#define msg_type(_m) ((unsigned char)(_m & 0xf0))
|
||||
#define msg_chan(_m) ((unsigned char)(_m & 0x0f))
|
||||
#define msg_p1(_m) ((_m >> 8) & 0x7f)
|
||||
#define msg_p2(_m) ((_m >> 16) & 0x7f)
|
||||
|
||||
void CALLBACK fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
|
||||
DWORD_PTR msg, DWORD_PTR extra);
|
||||
static char *fluid_winmidi_input_error(MMRESULT no);
|
||||
static char *
|
||||
fluid_winmidi_input_error(char *strError, MMRESULT no)
|
||||
{
|
||||
#ifdef _UNICODE
|
||||
WCHAR wStr[MAXERRORLENGTH];
|
||||
|
||||
midiInGetErrorText(no, wStr, MAXERRORLENGTH);
|
||||
WideCharToMultiByte(CP_UTF8, 0, wStr, -1, strError, MAXERRORLENGTH, 0, 0);
|
||||
#else
|
||||
midiInGetErrorText(no, strError, MAXERRORLENGTH);
|
||||
#endif
|
||||
|
||||
return strError;
|
||||
}
|
||||
|
||||
static void CALLBACK
|
||||
fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
|
||||
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
||||
{
|
||||
fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *) dwInstance;
|
||||
fluid_midi_event_t event;
|
||||
LPMIDIHDR pMidiHdr;
|
||||
unsigned char *data;
|
||||
unsigned int msg_param = (unsigned int) dwParam1;
|
||||
|
||||
switch(wMsg)
|
||||
{
|
||||
case MIM_OPEN:
|
||||
break;
|
||||
|
||||
case MIM_CLOSE:
|
||||
break;
|
||||
|
||||
case MIM_DATA:
|
||||
event.type = msg_type(msg_param);
|
||||
event.channel = msg_chan(msg_param);
|
||||
|
||||
if(event.type != PITCH_BEND)
|
||||
{
|
||||
event.param1 = msg_p1(msg_param);
|
||||
event.param2 = msg_p2(msg_param);
|
||||
}
|
||||
else /* Pitch bend is a 14 bit value */
|
||||
{
|
||||
event.param1 = (msg_p2(msg_param) << 7) | msg_p1(msg_param);
|
||||
event.param2 = 0;
|
||||
}
|
||||
|
||||
(*dev->driver.handler)(dev->driver.data, &event);
|
||||
break;
|
||||
|
||||
case MIM_LONGDATA: /* SYSEX data */
|
||||
if(dev->hThread == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pMidiHdr = (LPMIDIHDR)dwParam1;
|
||||
data = (unsigned char *)(pMidiHdr->lpData);
|
||||
|
||||
/* We only process complete SYSEX messages (discard those that are too small or too large) */
|
||||
if(pMidiHdr->dwBytesRecorded > 2 && data[0] == 0xF0
|
||||
&& data[pMidiHdr->dwBytesRecorded - 1] == 0xF7)
|
||||
{
|
||||
fluid_midi_event_set_sysex(&event, pMidiHdr->lpData + 1,
|
||||
pMidiHdr->dwBytesRecorded - 2, FALSE);
|
||||
(*dev->driver.handler)(dev->driver.data, &event);
|
||||
}
|
||||
|
||||
PostThreadMessage(dev->dwThread, MM_MIM_LONGDATA, 0, dwParam1);
|
||||
break;
|
||||
|
||||
case MIM_ERROR:
|
||||
break;
|
||||
|
||||
case MIM_LONGERROR:
|
||||
break;
|
||||
|
||||
case MIM_MOREDATA:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void fluid_winmidi_midi_driver_settings(fluid_settings_t *settings)
|
||||
{
|
||||
|
@ -138,7 +214,8 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
|
|||
MMRESULT res;
|
||||
UINT i, num, midi_num = 0;
|
||||
MIDIINCAPS in_caps;
|
||||
char *devname = NULL;
|
||||
char strError[MAXERRORLENGTH];
|
||||
char dev_name[MAXPNAMELEN];
|
||||
|
||||
/* not much use doing anything */
|
||||
if(handler == NULL)
|
||||
|
@ -147,6 +224,49 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* get the device name. if none is specified, use the default device. */
|
||||
if(fluid_settings_copystr(settings, "midi.winmidi.device", dev_name, MAXPNAMELEN) != FLUID_OK)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "No MIDI in device selected, using \"default\"");
|
||||
FLUID_STRCPY(dev_name, "default");
|
||||
}
|
||||
|
||||
/* check if there any midi devices installed */
|
||||
num = midiInGetNumDevs();
|
||||
|
||||
if(num == 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "no MIDI in devices found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* find the device */
|
||||
if(FLUID_STRCASECMP("default", dev_name) != 0)
|
||||
{
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS));
|
||||
|
||||
if(res == MMSYSERR_NOERROR)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Testing midi device: %s\n", in_caps.szPname);
|
||||
|
||||
if(FLUID_STRCASECMP(dev_name, in_caps.szPname) == 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Selected midi device number: %d\n", i);
|
||||
midi_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(midi_num != i)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", dev_name);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
dev = FLUID_MALLOC(sizeof(fluid_winmidi_driver_t));
|
||||
|
||||
if(dev == NULL)
|
||||
|
@ -160,54 +280,6 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
|
|||
dev->driver.handler = handler;
|
||||
dev->driver.data = data;
|
||||
|
||||
/* get the device name. if none is specified, use the default device. */
|
||||
if(fluid_settings_dupstr(settings, "midi.winmidi.device", &devname) != FLUID_OK || !devname)
|
||||
{
|
||||
devname = FLUID_STRDUP("default");
|
||||
|
||||
if(!devname)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto error_recovery;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if there any midi devices installed */
|
||||
num = midiInGetNumDevs();
|
||||
|
||||
if(num == 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "no MIDI in devices found");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
/* find the device */
|
||||
if(FLUID_STRCASECMP("default", devname) != 0)
|
||||
{
|
||||
for(i = 0; i < num; i++)
|
||||
{
|
||||
res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS));
|
||||
|
||||
if(res == MMSYSERR_NOERROR)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Testing midi device: %s\n", in_caps.szPname);
|
||||
|
||||
if(FLUID_STRCASECMP(devname, in_caps.szPname) == 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Selected midi device number: %d\n", i);
|
||||
midi_num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(midi_num != i)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Device <%s> does not exists", devname);
|
||||
goto error_recovery;
|
||||
}
|
||||
}
|
||||
|
||||
/* try opening the device */
|
||||
res = midiInOpen(&dev->hmidiin, midi_num,
|
||||
(DWORD_PTR) fluid_winmidi_callback,
|
||||
|
@ -216,7 +288,7 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
|
|||
if(res != MMSYSERR_NOERROR)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Couldn't open MIDI input: %s (error %d)",
|
||||
fluid_winmidi_input_error(res), res);
|
||||
fluid_winmidi_input_error(strError, res), res);
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
|
@ -238,13 +310,13 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
|
|||
if(res != MMSYSERR_NOERROR)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)",
|
||||
fluid_winmidi_input_error(res), res);
|
||||
fluid_winmidi_input_error(strError, res), res);
|
||||
midiInUnprepareHeader(dev->hmidiin, hdr, sizeof(MIDIHDR));
|
||||
}
|
||||
}
|
||||
else
|
||||
FLUID_LOG(FLUID_WARN, "Failed to prepare MIDI SYSEX buffer: %s (error %d)",
|
||||
fluid_winmidi_input_error(res), res);
|
||||
fluid_winmidi_input_error(strError, res), res);
|
||||
}
|
||||
|
||||
/* Create thread which processes re-adding SYSEX buffers */
|
||||
|
@ -270,20 +342,10 @@ new_fluid_winmidi_driver(fluid_settings_t *settings,
|
|||
goto error_recovery;
|
||||
}
|
||||
|
||||
if(devname)
|
||||
{
|
||||
FLUID_FREE(devname); /* -- free device name */
|
||||
}
|
||||
|
||||
return (fluid_midi_driver_t *) dev;
|
||||
|
||||
error_recovery:
|
||||
|
||||
if(devname)
|
||||
{
|
||||
FLUID_FREE(devname); /* -- free device name */
|
||||
}
|
||||
|
||||
delete_fluid_winmidi_driver((fluid_midi_driver_t *) dev);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -294,6 +356,8 @@ error_recovery:
|
|||
void
|
||||
delete_fluid_winmidi_driver(fluid_midi_driver_t *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *) p;
|
||||
fluid_return_if_fail(dev != NULL);
|
||||
|
||||
|
@ -310,85 +374,21 @@ delete_fluid_winmidi_driver(fluid_midi_driver_t *p)
|
|||
{
|
||||
midiInStop(dev->hmidiin);
|
||||
midiInReset(dev->hmidiin);
|
||||
|
||||
for(i = 0; i < MIDI_SYSEX_BUF_COUNT; i++)
|
||||
{
|
||||
MIDIHDR *hdr = &dev->sysExHdrs[i];
|
||||
|
||||
if ((hdr->dwFlags & MHDR_PREPARED))
|
||||
{
|
||||
midiInUnprepareHeader(dev->hmidiin, hdr, sizeof(MIDIHDR));
|
||||
}
|
||||
}
|
||||
|
||||
midiInClose(dev->hmidiin);
|
||||
}
|
||||
|
||||
FLUID_FREE(dev);
|
||||
}
|
||||
|
||||
void CALLBACK
|
||||
fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD_PTR dwInstance,
|
||||
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
||||
{
|
||||
fluid_winmidi_driver_t *dev = (fluid_winmidi_driver_t *) dwInstance;
|
||||
fluid_midi_event_t event;
|
||||
LPMIDIHDR pMidiHdr;
|
||||
unsigned char *data;
|
||||
unsigned int msg_param = (unsigned int) dwParam1;
|
||||
|
||||
switch(wMsg)
|
||||
{
|
||||
case MIM_OPEN:
|
||||
break;
|
||||
|
||||
case MIM_CLOSE:
|
||||
break;
|
||||
|
||||
case MIM_DATA:
|
||||
event.type = msg_type(msg_param);
|
||||
event.channel = msg_chan(msg_param);
|
||||
|
||||
if(event.type != PITCH_BEND)
|
||||
{
|
||||
event.param1 = msg_p1(msg_param);
|
||||
event.param2 = msg_p2(msg_param);
|
||||
}
|
||||
else /* Pitch bend is a 14 bit value */
|
||||
{
|
||||
event.param1 = (msg_p2(msg_param) << 7) | msg_p1(msg_param);
|
||||
event.param2 = 0;
|
||||
}
|
||||
|
||||
(*dev->driver.handler)(dev->driver.data, &event);
|
||||
break;
|
||||
|
||||
case MIM_LONGDATA: /* SYSEX data */
|
||||
if(dev->hThread == NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
pMidiHdr = (LPMIDIHDR)dwParam1;
|
||||
data = (unsigned char *)(pMidiHdr->lpData);
|
||||
|
||||
/* We only process complete SYSEX messages (discard those that are too small or too large) */
|
||||
if(pMidiHdr->dwBytesRecorded > 2 && data[0] == 0xF0
|
||||
&& data[pMidiHdr->dwBytesRecorded - 1] == 0xF7)
|
||||
{
|
||||
fluid_midi_event_set_sysex(&event, pMidiHdr->lpData + 1,
|
||||
pMidiHdr->dwBytesRecorded - 2, FALSE);
|
||||
(*dev->driver.handler)(dev->driver.data, &event);
|
||||
}
|
||||
|
||||
PostThreadMessage(dev->dwThread, MM_MIM_LONGDATA, 0, dwParam1);
|
||||
break;
|
||||
|
||||
case MIM_ERROR:
|
||||
break;
|
||||
|
||||
case MIM_LONGERROR:
|
||||
break;
|
||||
|
||||
case MIM_MOREDATA:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
fluid_winmidi_input_error(MMRESULT no)
|
||||
{
|
||||
midiInGetErrorText(no, fluid_winmidi_error_buffer, 256);
|
||||
return fluid_winmidi_error_buffer;
|
||||
}
|
||||
|
||||
#endif /* WINMIDI_SUPPORT */
|
||||
|
|
Loading…
Reference in a new issue