Switched MIDI to RtMidi.
This commit is contained in:
@@ -36,7 +36,12 @@ endif()
|
|||||||
# MACOSX_BUNDLE prepares a macOS application bundle including with the app icon
|
# MACOSX_BUNDLE prepares a macOS application bundle including with the app icon
|
||||||
add_executable(86Box WIN32 MACOSX_BUNDLE 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
|
add_executable(86Box WIN32 MACOSX_BUNDLE 86box.c config.c log.c random.c timer.c io.c acpi.c apm.c
|
||||||
dma.c ddma.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c
|
dma.c ddma.c nmi.c pic.c pit.c port_6x.c port_92.c ppi.c pci.c mca.c usb.c
|
||||||
device.c nvr.c nvr_at.c nvr_ps2.c ${APP_ICON_MACOSX})
|
device.c nvr.c nvr_at.c nvr_ps2.c rtmidi_midi.cpp ${APP_ICON_MACOSX})
|
||||||
|
|
||||||
|
find_package(RTMIDI REQUIRED)
|
||||||
|
target_include_directories(86Box ${RTMIDI_INCLUDE_DIRS})
|
||||||
|
target_link_directories(86Box INTERFACE ${RTMIDI_LIBRARY_DIRS})
|
||||||
|
target_link_libraries(86Box ${RTMIDI_LIBRARY_DIRS})
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
target_link_libraries(86Box "-framework AppKit")
|
target_link_libraries(86Box "-framework AppKit")
|
||||||
|
204
src/rtmidi_midi.cpp
Normal file
204
src/rtmidi_midi.cpp
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* MIDI backend implemented using the RtMidi library.
|
||||||
|
*
|
||||||
|
* Author: jgilje,
|
||||||
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
|
* Copyright 2021 jgilje.
|
||||||
|
* Copyright 2021 Miran Grca.
|
||||||
|
*/
|
||||||
|
#if defined __has_include
|
||||||
|
# if __has_include (<RtMidi.h>)
|
||||||
|
# include <RtMidi.h>
|
||||||
|
# endif
|
||||||
|
# if __has_include (<rtmidi/RtMidi.h>)
|
||||||
|
# include <rtmidi/RtMidi.h>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <86box/86box.h>
|
||||||
|
#include <86box/midi.h>
|
||||||
|
#include <86box/plat_midi.h>
|
||||||
|
#include <86box/config.h>
|
||||||
|
|
||||||
|
|
||||||
|
static RtMidiOut * midiout = nullptr;
|
||||||
|
static RtMidiIn * midiin = nullptr;
|
||||||
|
static int midi_out_id = 0, midi_in_id = 0;
|
||||||
|
static const int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1};
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_midi_write(uint8_t val)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void plat_midi_init(void)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (!midiout) midiout = new RtMidiOut;
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
midi_out_id = config_get_int((char*)SYSTEM_MIDI_NAME, (char*)"midi", 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
midiout->openPort(midi_out_id);
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Fallback to default MIDI output port: %s\n", error.getMessage().c_str());
|
||||||
|
|
||||||
|
try {
|
||||||
|
midiout->openPort(0);
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
|
||||||
|
delete midiout;
|
||||||
|
midiout = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_close(void)
|
||||||
|
{
|
||||||
|
if (!midiout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
midiout->closePort();
|
||||||
|
|
||||||
|
delete midiout;
|
||||||
|
midiout = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_midi_get_num_devs(void)
|
||||||
|
{
|
||||||
|
if (!midiout) {
|
||||||
|
try {
|
||||||
|
midiout = new RtMidiOut;
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return midiout ? midiout->getPortCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_play_msg(uint8_t *msg)
|
||||||
|
{
|
||||||
|
if (midiout)
|
||||||
|
midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_get_dev_name(int num, char *s)
|
||||||
|
{
|
||||||
|
strcpy(s, midiout->getPortName(num).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_play_sysex(uint8_t *sysex, unsigned int len)
|
||||||
|
{
|
||||||
|
if (midiout)
|
||||||
|
midiout->sendMessage(sysex, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
plat_midi_callback(double timeStamp, std::vector<unsigned char> *message, void *userData)
|
||||||
|
{
|
||||||
|
if (message->size() <= 3)
|
||||||
|
midi_in_msg(message->data());
|
||||||
|
else
|
||||||
|
midi_in_sysex(message->data(), message->size());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_input_init(void)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (!midiin)
|
||||||
|
midiin = new RtMidiIn;
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
midi_in_id = config_get_int((char*)SYSTEM_MIDI_NAME, (char*)"midi_input", 0);
|
||||||
|
|
||||||
|
try {
|
||||||
|
midiin->openPort(midi_in_id);
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Fallback to default MIDI input port: %s\n", error.getMessage().c_str());
|
||||||
|
|
||||||
|
try {
|
||||||
|
midiin->openPort(0);
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
|
||||||
|
delete midiin;
|
||||||
|
midiin = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
midiin->setCallback(plat_midi_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_input_close(void)
|
||||||
|
{
|
||||||
|
midiin->cancelCallback();
|
||||||
|
midiin->closePort();
|
||||||
|
|
||||||
|
delete midiin;
|
||||||
|
midiin = nullptr;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_midi_in_get_num_devs(void)
|
||||||
|
{
|
||||||
|
if (!midiin) {
|
||||||
|
try {
|
||||||
|
midiin = new RtMidiIn;
|
||||||
|
} catch (RtMidiError& error) {
|
||||||
|
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return midiin ? midiin->getPortCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_in_get_dev_name(int num, char *s)
|
||||||
|
{
|
||||||
|
strcpy(s, midiin->getPortName(num).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -16,7 +16,7 @@
|
|||||||
enable_language(RC)
|
enable_language(RC)
|
||||||
|
|
||||||
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_thread.c
|
add_library(plat OBJECT win.c win_dynld.c win_cdrom.c win_thread.c
|
||||||
win_keyboard.c win_crashdump.c win_midi.c win_mouse.c)
|
win_keyboard.c win_crashdump.c win_mouse.c)
|
||||||
|
|
||||||
add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c
|
add_library(ui OBJECT win_ui.c win_icon.c win_stbar.c win_sdl.c win_dialog.c win_about.c
|
||||||
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c
|
win_settings.c win_devconf.c win_snd_gain.c win_specify_dim.c win_new_floppy.c
|
||||||
|
@@ -466,7 +466,7 @@ CXXFLAGS := $(CFLAGS)
|
|||||||
#########################################################################
|
#########################################################################
|
||||||
MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
|
MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.o \
|
||||||
nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \
|
nmi.o pic.o pit.o port_6x.o port_92.o ppi.o pci.o mca.o \
|
||||||
usb.o device.o nvr.o nvr_at.o nvr_ps2.o \
|
usb.o device.o nvr.o nvr_at.o nvr_ps2.o rtmidi_midi.o \
|
||||||
$(VNCOBJ)
|
$(VNCOBJ)
|
||||||
|
|
||||||
MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o
|
MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o smram.o spd.o sst_flash.o
|
||||||
@@ -674,7 +674,7 @@ VOODOOOBJ := vid_voodoo.o vid_voodoo_banshee.o \
|
|||||||
PLATOBJ := win.o \
|
PLATOBJ := win.o \
|
||||||
win_dynld.o win_thread.o \
|
win_dynld.o win_thread.o \
|
||||||
win_cdrom.o win_keyboard.o \
|
win_cdrom.o win_keyboard.o \
|
||||||
win_crashdump.o win_midi.o \
|
win_crashdump.o \
|
||||||
win_mouse.o
|
win_mouse.o
|
||||||
|
|
||||||
UIOBJ := win_ui.o win_icon.o win_stbar.o win_discord.o \
|
UIOBJ := win_ui.o win_icon.o win_stbar.o win_discord.o \
|
||||||
@@ -704,7 +704,7 @@ LIBS := -mwindows -lcomctl32 \
|
|||||||
ifeq ($(VNC), y)
|
ifeq ($(VNC), y)
|
||||||
LIBS += $(VNCLIB) -lws2_32
|
LIBS += $(VNCLIB) -lws2_32
|
||||||
endif
|
endif
|
||||||
LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lwinmm -static -lstdc++
|
LIBS += -lpng -lz -lwsock32 -lshell32 -liphlpapi -lpsapi -lSDL2 -limm32 -lhid -lsetupapi -loleaut32 -luxtheme -lversion -lrtmidi -lwinmm -static -lstdc++
|
||||||
ifneq ($(X64), y)
|
ifneq ($(X64), y)
|
||||||
ifneq ($(ARM64), y)
|
ifneq ($(ARM64), y)
|
||||||
LIBS += -Wl,--large-address-aware
|
LIBS += -Wl,--large-address-aware
|
||||||
|
@@ -1,241 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
Reference in New Issue
Block a user