Turn the RtMidi module into a full standalone MIDI module
Removes the now-redundant platform MIDI infrastructure
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
#
|
||||
|
||||
add_library(snd OBJECT sound.c openal.c snd_opl.c snd_opl_nuked.c snd_resid.cc
|
||||
midi.c midi_system.c snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c
|
||||
midi.c midi_rtmidi.cpp snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c
|
||||
snd_lpt_dss.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c
|
||||
snd_azt2316a.c snd_cms.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c
|
||||
snd_emu8k.c snd_mpu401.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c)
|
||||
|
||||
@@ -28,9 +28,7 @@
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_midi.h>
|
||||
#include <86box/midi.h>
|
||||
#include <86box/midi_input.h>
|
||||
|
||||
|
||||
int midi_device_current = 0;
|
||||
@@ -84,14 +82,14 @@ static const MIDI_DEVICE devices[] =
|
||||
{ "mt32", &mt32_device },
|
||||
{ "cm32l", &cm32l_device },
|
||||
#endif
|
||||
{ SYSTEM_MIDI_INTERNAL_NAME, &system_midi_device },
|
||||
{ SYSTEM_MIDI_INTERNAL_NAME, &rtmidi_device },
|
||||
{ "", NULL }
|
||||
};
|
||||
|
||||
static const MIDI_IN_DEVICE midi_in_devices[] =
|
||||
{
|
||||
{ "none", NULL },
|
||||
{ MIDI_INPUT_INTERNAL_NAME, &midi_input_device },
|
||||
{ MIDI_INPUT_INTERNAL_NAME, &rtmidi_input_device },
|
||||
{ "", NULL }
|
||||
};
|
||||
|
||||
|
||||
288
src/sound/midi_rtmidi.cpp
Normal file
288
src/sound/midi_rtmidi.cpp
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* 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: Cacodemon345,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2021 Cacodemon345.
|
||||
* 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 <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/midi.h>
|
||||
#include <86box/midi_rtmidi.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
|
||||
rtmidi_write(uint8_t val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtmidi_play_msg(uint8_t *msg)
|
||||
{
|
||||
if (midiout)
|
||||
midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtmidi_play_sysex(uint8_t *sysex, unsigned int len)
|
||||
{
|
||||
if (midiout)
|
||||
midiout->sendMessage(sysex, len);
|
||||
}
|
||||
|
||||
|
||||
void*
|
||||
rtmidi_init(const device_t *info)
|
||||
{
|
||||
midi_device_t* dev = (midi_device_t*)malloc(sizeof(midi_device_t));
|
||||
memset(dev, 0, sizeof(midi_device_t));
|
||||
|
||||
dev->play_msg = rtmidi_play_msg;
|
||||
dev->play_sysex = rtmidi_play_sysex;
|
||||
dev->write = rtmidi_write;
|
||||
|
||||
try {
|
||||
if (!midiout) midiout = new RtMidiOut;
|
||||
} catch (RtMidiError& error) {
|
||||
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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 nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
midi_init(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtmidi_close(void *p)
|
||||
{
|
||||
if (!midiout)
|
||||
return;
|
||||
|
||||
midiout->closePort();
|
||||
|
||||
delete midiout;
|
||||
midiout = nullptr;
|
||||
|
||||
midi_close();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rtmidi_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
|
||||
rtmidi_get_dev_name(int num, char *s)
|
||||
{
|
||||
strcpy(s, midiout->getPortName(num).c_str());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtmidi_input_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*
|
||||
rtmidi_input_init(const device_t *info)
|
||||
{
|
||||
midi_device_t* dev = (midi_device_t*)malloc(sizeof(midi_device_t));
|
||||
memset(dev, 0, sizeof(midi_device_t));
|
||||
|
||||
try {
|
||||
if (!midiin)
|
||||
midiin = new RtMidiIn;
|
||||
} catch (RtMidiError& error) {
|
||||
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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 nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
midiin->setCallback(rtmidi_input_callback);
|
||||
|
||||
midi_in_init(dev, &midi_in);
|
||||
|
||||
midi_in->midi_realtime = device_get_config_int("realtime");
|
||||
midi_in->thruchan = device_get_config_int("thruchan");
|
||||
midi_in->midi_clockout = device_get_config_int("clockout");
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rtmidi_input_close(void* p)
|
||||
{
|
||||
midiin->cancelCallback();
|
||||
midiin->closePort();
|
||||
|
||||
delete midiin;
|
||||
midiin = nullptr;
|
||||
|
||||
midi_close();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
rtmidi_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
|
||||
rtmidi_in_get_dev_name(int num, char *s)
|
||||
{
|
||||
strcpy(s, midiin->getPortName(num).c_str());
|
||||
}
|
||||
|
||||
static const device_config_t system_midi_config[] =
|
||||
{
|
||||
{
|
||||
"midi", "MIDI out device", CONFIG_MIDI, "", 0
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
static const device_config_t midi_input_config[] =
|
||||
{
|
||||
{
|
||||
"midi_input", "MIDI in device", CONFIG_MIDI_IN, "", 0
|
||||
},
|
||||
{
|
||||
"realtime", "MIDI Real time", CONFIG_BINARY, "", 0
|
||||
},
|
||||
{
|
||||
"thruchan", "MIDI Thru", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"clockout", "MIDI Clockout", CONFIG_BINARY, "", 1
|
||||
},
|
||||
{
|
||||
"", "", -1
|
||||
}
|
||||
};
|
||||
|
||||
const device_t rtmidi_device =
|
||||
{
|
||||
SYSTEM_MIDI_NAME,
|
||||
0, 0,
|
||||
rtmidi_init,
|
||||
rtmidi_close,
|
||||
NULL,
|
||||
{ rtmidi_get_num_devs },
|
||||
NULL,
|
||||
NULL,
|
||||
system_midi_config
|
||||
};
|
||||
|
||||
|
||||
const device_t rtmidi_input_device =
|
||||
{
|
||||
MIDI_INPUT_NAME,
|
||||
0, 0,
|
||||
rtmidi_input_init,
|
||||
rtmidi_input_close,
|
||||
NULL,
|
||||
{ rtmidi_in_get_num_devs },
|
||||
NULL,
|
||||
NULL,
|
||||
midi_input_config
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <86box/86box.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/plat_midi.h>
|
||||
#include <86box/midi.h>
|
||||
#include <86box/midi_input.h>
|
||||
|
||||
|
||||
void* system_midi_init(const device_t *info)
|
||||
{
|
||||
midi_device_t* dev = malloc(sizeof(midi_device_t));
|
||||
memset(dev, 0, sizeof(midi_device_t));
|
||||
|
||||
dev->play_msg = plat_midi_play_msg;
|
||||
dev->play_sysex = plat_midi_play_sysex;
|
||||
dev->write = plat_midi_write;
|
||||
|
||||
plat_midi_init();
|
||||
|
||||
midi_init(dev);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void* midi_input_init(const device_t *info)
|
||||
{
|
||||
midi_device_t* dev = malloc(sizeof(midi_device_t));
|
||||
memset(dev, 0, sizeof(midi_device_t));
|
||||
|
||||
plat_midi_input_init();
|
||||
|
||||
midi_in_init(dev, &midi_in);
|
||||
|
||||
midi_in->midi_realtime = device_get_config_int("realtime");
|
||||
midi_in->thruchan = device_get_config_int("thruchan");
|
||||
midi_in->midi_clockout = device_get_config_int("clockout");
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void system_midi_close(void* p)
|
||||
{
|
||||
plat_midi_close();
|
||||
|
||||
midi_close();
|
||||
}
|
||||
|
||||
void midi_input_close(void* p)
|
||||
{
|
||||
plat_midi_input_close();
|
||||
|
||||
midi_close();
|
||||
}
|
||||
|
||||
int system_midi_available(void)
|
||||
{
|
||||
return plat_midi_get_num_devs();
|
||||
}
|
||||
|
||||
int midi_input_available(void)
|
||||
{
|
||||
return plat_midi_in_get_num_devs();
|
||||
}
|
||||
|
||||
static const device_config_t system_midi_config[] =
|
||||
{
|
||||
{
|
||||
.name = "midi",
|
||||
.description = "MIDI out device",
|
||||
.type = CONFIG_MIDI,
|
||||
.default_int = 0
|
||||
},
|
||||
{
|
||||
.type = -1
|
||||
}
|
||||
};
|
||||
|
||||
static const device_config_t midi_input_config[] =
|
||||
{
|
||||
{
|
||||
.name = "midi_input",
|
||||
.description = "MIDI in device",
|
||||
.type = CONFIG_MIDI_IN,
|
||||
.default_int = 0
|
||||
},
|
||||
{
|
||||
.name = "realtime",
|
||||
.description = "MIDI Real time",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_int = 0
|
||||
},
|
||||
{
|
||||
.name = "thruchan",
|
||||
.description = "MIDI Thru",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_int = 1
|
||||
},
|
||||
{
|
||||
.name = "clockout",
|
||||
.description = "MIDI Clockout",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_int = 1
|
||||
},
|
||||
{
|
||||
.type = -1
|
||||
}
|
||||
};
|
||||
|
||||
const device_t system_midi_device =
|
||||
{
|
||||
SYSTEM_MIDI_NAME,
|
||||
0, 0,
|
||||
system_midi_init,
|
||||
system_midi_close,
|
||||
NULL,
|
||||
{ system_midi_available },
|
||||
NULL,
|
||||
NULL,
|
||||
system_midi_config
|
||||
};
|
||||
|
||||
|
||||
const device_t midi_input_device =
|
||||
{
|
||||
MIDI_INPUT_NAME,
|
||||
0, 0,
|
||||
midi_input_init,
|
||||
midi_input_close,
|
||||
NULL,
|
||||
{ midi_input_available },
|
||||
NULL,
|
||||
NULL,
|
||||
midi_input_config
|
||||
};
|
||||
Reference in New Issue
Block a user