diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 9a2be5a7f..45c9d1d77 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -4,9 +4,10 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) +find_package(PkgConfig) find_package(Threads REQUIRED) -add_library(plat STATIC qt.c qt_main.cpp qt_platform.cpp qt_midi.cpp cpp11_thread.cpp) +add_library(plat STATIC qt.c qt_main.cpp qt_platform.cpp cpp11_thread.cpp) add_library(ui STATIC qt_ui.cpp qt_cdrom.c @@ -101,6 +102,21 @@ if (UNIX AND NOT APPLE) find_package(X11 REQUIRED) target_link_libraries(ui PRIVATE X11::X11) find_package(ECM NO_MODULE) + if (PkgConfig_FOUND) + pkg_check_modules(RTMIDI rtmidi) + if (RTMIDI_FOUND) + target_include_directories(plat PRIVATE ${RTMIDI_INCLUDE_DIRS}) + target_link_directories(plat PRIVATE ${RTMIDI_LIBRARY_DIRS}) + target_link_libraries(plat PRIVATE ${RTMIDI_LIBRARIES}) + target_link_options(plat PRIVATE ${RTMIDI_LDFLAGS}) + target_compile_options(plat PRIVATE ${RTMIDI_CFLAGS}) + target_sources(plat PRIVATE rtmidi_midi.cpp) + else() + target_sources(plat PRIVATE qt_midi.cpp) + endif() + else() + target_sources(plat PRIVATE qt_midi.cpp) + endif() if (ECM_FOUND) list(APPEND CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) find_package(Wayland COMPONENTS Client) diff --git a/src/qt/rtmidi_midi.cpp b/src/qt/rtmidi_midi.cpp new file mode 100644 index 000000000..b8ab2ca30 --- /dev/null +++ b/src/qt/rtmidi_midi.cpp @@ -0,0 +1,143 @@ + +#include +#include +#include +extern "C" +{ +#include <86box/86box.h> +#include <86box/midi.h> +#include <86box/plat_midi.h> +#include <86box/config.h> +} + +extern "C" { + +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() +{ + try + { + 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() +{ + if (!midiout) return; + midiout->closePort(); + delete midiout; + midiout = nullptr; +} + +int plat_midi_get_num_devs() +{ + 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 *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 + { + 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) +{ + return midiin ? midiin->getPortCount() : 0; +} + +void plat_midi_in_get_dev_name(int num, char *s) +{ + strcpy(s, midiin->getPortName(num).c_str()); +} + +}