questzdoom/Projects/Android/jni/SupportLibs/fluidsynth/fluid_winmidi.c
2021-04-20 21:09:02 +01:00

227 lines
5.7 KiB
C

/* FluidSynth - A Software Synthesizer
*
* Copyright (C) 2003 Peter Hanappe and others.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
/* fluid_winmidi.c
*
* Drivers for Windows MIDI
*/
#include "fluidsynth_priv.h"
#if WINMIDI_SUPPORT
#include "fluid_midi.h"
#include "fluid_mdriver.h"
#include "fluid_settings.h"
#include <windows.h>
#define BUFFER_LENGTH 512
typedef struct {
fluid_midi_driver_t driver;
HMIDIIN hmidiin;
} 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)
fluid_midi_driver_t* new_fluid_winmidi_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler, void* data);
int delete_fluid_winmidi_driver(fluid_midi_driver_t* p);
void CALLBACK fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD dwInstance,
DWORD msg, DWORD extra);
static char* fluid_winmidi_input_error(int no);
int fluid_winmidi_driver_status(fluid_midi_driver_t* p);
void fluid_winmidi_midi_driver_settings(fluid_settings_t* settings)
{
MMRESULT res;
MIDIINCAPS in_caps;
UINT i, num;
fluid_settings_register_str(settings, "midi.winmidi.device", "default", 0, NULL, NULL);
num = midiInGetNumDevs();
if (num > 0) {
fluid_settings_add_option(settings, "midi.winmidi.device", "default");
for (i = 0; i < num; i++) {
res = midiInGetDevCaps(i, &in_caps, sizeof(MIDIINCAPS));
if (res == MMSYSERR_NOERROR) {
fluid_settings_add_option(settings, "midi.winmidi.device", in_caps.szPname);
}
}
}
}
/*
* new_fluid_winmidi_driver
*/
fluid_midi_driver_t*
new_fluid_winmidi_driver(fluid_settings_t* settings,
handle_midi_event_func_t handler, void* data)
{
fluid_winmidi_driver_t* dev;
MMRESULT res;
UINT i, err, num;
MIDIINCAPS in_caps;
int midi_num = 0;
char* devname = NULL;
/* not much use doing anything */
if (handler == NULL) {
FLUID_LOG(FLUID_ERR, "Invalid argument");
return NULL;
}
dev = FLUID_MALLOC(sizeof(fluid_winmidi_driver_t));
if (dev == NULL) {
return NULL;
}
dev->hmidiin = NULL;
dev->driver.handler = handler;
dev->driver.data = data;
/* get the device name. if none is specified, use the default device. */
if(!fluid_settings_getstr(settings, "midi.winmidi.device", &devname)) {
devname = "default";
}
/* 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 (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 (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 */
err = midiInOpen(&dev->hmidiin, midi_num,
(DWORD) fluid_winmidi_callback,
(DWORD) dev, CALLBACK_FUNCTION);
if (err != MMSYSERR_NOERROR) {
FLUID_LOG(FLUID_WARN, "Couldn't open MIDI input: %s (error %d)",
fluid_winmidi_input_error(err), err);
goto error_recovery;
}
if (midiInStart(dev->hmidiin) != MMSYSERR_NOERROR) {
FLUID_LOG(FLUID_ERR, "Failed to start the MIDI input. MIDI input not available.");
goto error_recovery;
}
return (fluid_midi_driver_t*) dev;
error_recovery:
delete_fluid_winmidi_driver((fluid_midi_driver_t*) dev);
return NULL;
}
/*
* delete_fluid_winmidi_driver
*/
int
delete_fluid_winmidi_driver(fluid_midi_driver_t* p)
{
fluid_winmidi_driver_t* dev = (fluid_winmidi_driver_t*) p;
if (dev->hmidiin != NULL) {
midiInStop(dev->hmidiin);
midiInReset(dev->hmidiin);
midiInClose(dev->hmidiin);
}
FLUID_FREE(dev);
return 0;
}
void CALLBACK
fluid_winmidi_callback(HMIDIIN hmi, UINT wMsg, DWORD dwInstance, DWORD msg, DWORD extra)
{
fluid_winmidi_driver_t* dev = (fluid_winmidi_driver_t *) dwInstance;
switch (wMsg) {
case MIM_OPEN:
break;
case MIM_CLOSE:
break;
case MIM_DATA:
{
fluid_midi_event_t event;
event.type = msg_type(msg);
event.channel = msg_chan(msg);
event.param1 = msg_p1(msg);
event.param2 = msg_p2(msg);
(*dev->driver.handler)(dev->driver.data, &event);
}
break;
case MIM_LONGDATA:
break;
case MIM_ERROR:
break;
case MIM_LONGERROR:
break;
case MIM_MOREDATA:
break;
}
}
int
fluid_winmidi_driver_status(fluid_midi_driver_t* p)
{
return 0;
}
static char*
fluid_winmidi_input_error(int no)
{
midiInGetErrorText(no, fluid_winmidi_error_buffer, 256);
return fluid_winmidi_error_buffer;
}
#endif /* WINMIDI_SUPPORT */