Files
86Box/src/win/win_midi.c
David Hrdlička a505894a10 Move all include files to src/include
- 86Box's own headers go to /86box
- munt's public interface goes to /mt32emu
- all slirp headers go to /slirp (might want to consider using only its public inteface)
- single file headers from other projects go in include root
2020-03-29 19:53:29 +02:00

242 lines
4.8 KiB
C

#include <windows.h>
#include <mmsystem.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/config.h>
#include <86box/midi.h>
#include <86box/plat.h>
#include <86box/plat_midi.h>
typedef struct
{
int midi_id, midi_input_id;
HANDLE m_event;
HMIDIOUT midi_out_device;
HMIDIIN midi_in_device;
MIDIHDR m_hdr;
} plat_midi_t;
plat_midi_t *pm = NULL, *pm_in = NULL;
void
plat_midi_init(void)
{
MMRESULT hr;
pm = (plat_midi_t *) malloc(sizeof(plat_midi_t));
memset(pm, 0, sizeof(plat_midi_t));
pm->midi_id = config_get_int(SYSTEM_MIDI_NAME, "midi", 0);
hr = MMSYSERR_NOERROR;
pm->m_event = CreateEvent(NULL, TRUE, TRUE, NULL);
hr = midiOutOpen(&pm->midi_out_device, pm->midi_id,
(uintptr_t) pm->m_event, 0, CALLBACK_EVENT);
if (hr != MMSYSERR_NOERROR) {
printf("midiOutOpen error - %08X\n", hr);
pm->midi_id = 0;
hr = midiOutOpen(&pm->midi_out_device, pm->midi_id,
(uintptr_t) pm->m_event, 0, CALLBACK_EVENT);
if (hr != MMSYSERR_NOERROR) {
printf("midiOutOpen error - %08X\n", hr);
return;
}
}
midiOutReset(pm->midi_out_device);
}
void
plat_midi_close(void)
{
if (pm) {
if (pm->midi_out_device != NULL) {
midiOutReset(pm->midi_out_device);
midiOutClose(pm->midi_out_device);
CloseHandle(pm->m_event);
}
free(pm);
pm = NULL;
}
}
int
plat_midi_get_num_devs(void)
{
return midiOutGetNumDevs();
}
void
plat_midi_get_dev_name(int num, char *s)
{
MIDIOUTCAPS caps;
midiOutGetDevCaps(num, &caps, sizeof(caps));
strcpy(s, caps.szPname);
}
void
plat_midi_play_msg(uint8_t *msg)
{
if (!pm)
return;
midiOutShortMsg(pm->midi_out_device, *(uint32_t *) msg);
}
void
plat_midi_play_sysex(uint8_t *sysex, unsigned int len)
{
MMRESULT result;
if (!pm)
return;
if (WaitForSingleObject(pm->m_event, 2000) == WAIT_TIMEOUT)
return;
midiOutUnprepareHeader(pm->midi_out_device, &pm->m_hdr, sizeof(pm->m_hdr));
pm->m_hdr.lpData = (char *) sysex;
pm->m_hdr.dwBufferLength = len;
pm->m_hdr.dwBytesRecorded = len;
pm->m_hdr.dwUser = 0;
result = midiOutPrepareHeader(pm->midi_out_device, &pm->m_hdr, sizeof(pm->m_hdr));
if (result != MMSYSERR_NOERROR)
return;
ResetEvent(pm->m_event);
result = midiOutLongMsg(pm->midi_out_device, &pm->m_hdr, sizeof(pm->m_hdr));
if (result != MMSYSERR_NOERROR) {
SetEvent(pm->m_event);
return;
}
}
int
plat_midi_write(uint8_t val)
{
return 0;
}
void CALLBACK
plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
uint8_t msg[4] = { ((dwParam1 & 0xff)), (((dwParam1 & 0xff00) >> 8)),
(((dwParam1 & 0xff0000) >> 16)), MIDI_evt_len[((dwParam1 & 0xff))]};
uint8_t *sysex;
uint32_t len;
MIDIHDR *hdr;
switch (wMsg) {
case MM_MIM_DATA: /* 0x3C3 - midi message */
midi_in_msg(msg);
break;
case MM_MIM_OPEN: /* 0x3C1 */
break;
case MM_MIM_CLOSE: /* 0x3C2 */
break;
case MM_MIM_LONGDATA: /* 0x3C4 - sysex */
/* It is midi_in_sysex() that now does the loop. */
hdr = (MIDIHDR *) dwParam1;
sysex = (uint8_t *) hdr->lpData;
len = (uint32_t) hdr->dwBytesRecorded;
midi_in_sysex(sysex, len);
midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr));
hdr->dwBytesRecorded = 0;
midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr));
break;
case MM_MIM_ERROR:
case MM_MIM_LONGERROR:
break;
default:
break;
}
}
void
plat_midi_input_init(void)
{
MMRESULT hr;
pm_in = (plat_midi_t *) malloc(sizeof(plat_midi_t));
memset(pm_in, 0, sizeof(plat_midi_t));
pm_in->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0);
hr = MMSYSERR_NOERROR;
hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id,
(uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION);
if (hr != MMSYSERR_NOERROR) {
printf("midiInOpen error - %08X\n", hr);
pm_in->midi_input_id = 0;
hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id,
(uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION);
if (hr != MMSYSERR_NOERROR) {
printf("midiInOpen error - %08X\n", hr);
return;
}
}
pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0];
pm_in->m_hdr.dwBufferLength = SYSEX_SIZE;
pm_in->m_hdr.dwBytesRecorded = 0;
pm_in->m_hdr.dwUser = 0;
midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr));
midiInStart(pm_in->midi_in_device);
}
void
plat_midi_input_close(void)
{
if (pm_in) {
if (pm_in->midi_in_device != NULL) {
midiInStop(pm_in->midi_in_device);
midiInClose(pm_in->midi_in_device);
}
free(pm_in);
pm_in = NULL;
}
}
int
plat_midi_in_get_num_devs(void)
{
return midiInGetNumDevs();
}
void
plat_midi_in_get_dev_name(int num, char *s)
{
MIDIINCAPS caps;
midiInGetDevCaps(num, &caps, sizeof(caps));
strcpy(s, caps.szPname);
}