diff --git a/include/libremidi/api.hpp b/include/libremidi/api.hpp index 208fd9d..57da702 100644 --- a/include/libremidi/api.hpp +++ b/include/libremidi/api.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -31,9 +30,6 @@ LIBREMIDI_EXPORT std::vector available_apis() noexcept; */ LIBREMIDI_EXPORT std::vector available_ump_apis() noexcept; -LIBREMIDI_EXPORT -libremidi::API midi_api(const std::any& conf); - //! A static function to determine the current version. LIBREMIDI_EXPORT std::string_view get_version() noexcept; diff --git a/include/libremidi/backends.hpp b/include/libremidi/backends.hpp index fb289eb..86b638a 100644 --- a/include/libremidi/backends.hpp +++ b/include/libremidi/backends.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include #if !__has_include() && !__has_include() @@ -202,10 +201,10 @@ auto for_backend(libremidi::API api, F&& f) midi2::for_backend(api, f); } -void for_input_configuration(auto f, std::any& api_conf) +void for_input_configuration(auto f, libremidi::input_api_configuration& api_conf) { auto from_api = [&](T& /*backend*/) mutable { - if (auto conf = std::any_cast(&api_conf)) + if (auto conf = std::get_if(&api_conf)) { f(*conf); return true; @@ -217,10 +216,10 @@ void for_input_configuration(auto f, std::any& api_conf) std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi2::available_backends); } -void for_output_configuration(auto f, std::any& api_conf) +void for_output_configuration(auto f, libremidi::output_api_configuration& api_conf) { auto from_api = [&](T& /*backend*/) mutable { - if (auto conf = std::any_cast(&api_conf)) + if (auto conf = std::get_if(&api_conf)) { f(*conf); return true; @@ -232,10 +231,10 @@ void for_output_configuration(auto f, std::any& api_conf) std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi2::available_backends); } -void for_observer_configuration(auto f, std::any& api_conf) +void for_observer_configuration(auto f, libremidi::observer_api_configuration& api_conf) { auto from_api = [&](T& /*backend*/) mutable { - if (auto conf = std::any_cast(&api_conf)) + if (auto conf = std::get_if(&api_conf)) { f(*conf); return true; diff --git a/include/libremidi/backends/alsa_raw_ump.hpp b/include/libremidi/backends/alsa_raw_ump.hpp index 7475ab5..a6316e7 100644 --- a/include/libremidi/backends/alsa_raw_ump.hpp +++ b/include/libremidi/backends/alsa_raw_ump.hpp @@ -16,9 +16,8 @@ struct backend using midi_observer = observer_impl; using midi_in_configuration = alsa_raw_ump::input_configuration; using midi_out_configuration = alsa_raw_ump::output_configuration; - struct midi_observer_configuration : alsa_raw_observer_configuration - { - }; + using midi_observer_configuration = alsa_raw_ump::observer_configuration; + static const constexpr auto API = libremidi::API::ALSA_RAW_UMP; static const constexpr std::string_view name = "alsa_raw_ump"; static const constexpr std::string_view display_name = "ALSA (raw UMP)"; diff --git a/include/libremidi/backends/alsa_raw_ump/config.hpp b/include/libremidi/backends/alsa_raw_ump/config.hpp index a89ccaf..9674b2c 100644 --- a/include/libremidi/backends/alsa_raw_ump/config.hpp +++ b/include/libremidi/backends/alsa_raw_ump/config.hpp @@ -18,8 +18,7 @@ struct output_configuration std::optional chunking; }; -struct observer_configuration +struct observer_configuration : public alsa_raw_observer_configuration { - std::chrono::milliseconds poll_period{100}; }; } diff --git a/include/libremidi/backends/keyboard/config.hpp b/include/libremidi/backends/keyboard/config.hpp index 109122e..efa565d 100644 --- a/include/libremidi/backends/keyboard/config.hpp +++ b/include/libremidi/backends/keyboard/config.hpp @@ -6,6 +6,128 @@ namespace libremidi { +enum kbd_event +{ + NOTE_0 = 0x0, // C + VEL_0 = NOTE_0 + 128, // Set velocity to 0 + OCT_0 = VEL_0 + 128, // Set octave to 0 + OCTAVE_PLUS = OCT_0 + 128, + OCTAVE_MINUS, + VELOCITY_PLUS, + VELOCITY_MINUS, +}; + +// Default map +// +// ,---,---,---,---,---,---,---,---,---,---,---,---,---,-------, +// | V0| V1| V2| V3| V4| V5| V6| V7| V8| V9|V10|V11|V12| <- | +// |---'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-----| +// | ->| | | C#| D#| | F#| G#| A#| | C#| D#| | F#| | +// |-----',--',--',--',--',--',--',--',--',--',--',--',--'| | +// | Caps | C | D | E | F | G | A | B | C | D | E | F | G | | +// |----,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'---'----| +// | -^ | | O-| O+| V-| V+| | | | | | | ----^ | +// |----'-,-',--'--,'---'---'---'---'---'---'-,-'---',--,------| +// | ctrl | | alt | |altgr | | ctrl | +// '------' '-----'--------------------------'------' '------' + +// clang-format off + +// actually based on macOS virtual codes as it seems +// impossible to get raw scan codes. +// https://eastmanreference.com/complete-list-of-applescript-key-codes +static inline const std::map& scancode_map_macos(){ + static const std::map ret{ + { 0, NOTE_0}, // C0 + { 13, NOTE_0 + 1}, + { 1, NOTE_0 + 2}, + { 14, NOTE_0 + 3}, + { 2, NOTE_0 + 4}, + { 3, NOTE_0 + 5}, + { 17, NOTE_0 + 6}, + { 5, NOTE_0 + 7}, + { 16, NOTE_0 + 8}, + { 4, NOTE_0 + 9}, + { 32, NOTE_0 + 10}, + { 38, NOTE_0 + 11}, + { 40, NOTE_0 + 12}, // C1 + { 31, NOTE_0 + 13}, + { 37, NOTE_0 + 14}, + { 35, NOTE_0 + 15}, + { 41, NOTE_0 + 16}, + { 39, NOTE_0 + 17}, + { 30, NOTE_0 + 18}, + { 42, NOTE_0 + 19}, + + { 50, VEL_0 + int(0)}, + { 18, VEL_0 + int(1 * 127 / 12)}, + { 19, VEL_0 + int(2 * 127 / 12)}, + { 20, VEL_0 + int(3 * 127 / 12)}, + { 21, VEL_0 + int(4 * 127 / 12)}, + { 23, VEL_0 + int(5 * 127 / 12)}, + { 22, VEL_0 + int(6 * 127 / 12)}, + { 26, VEL_0 + int(7 * 127 / 12)}, + { 28, VEL_0 + int(8 * 127 / 12)}, + { 25, VEL_0 + int(9 * 127 / 12)}, + { 29, VEL_0 + int(10 * 127 / 12)}, + { 27, VEL_0 + int(11 * 127 / 12)}, + { 24, VEL_0 + int(127)}, + + { 6, OCTAVE_MINUS }, + { 7, OCTAVE_PLUS }, + { 8, VELOCITY_MINUS }, + { 9, VELOCITY_PLUS}, + }; + return ret; +} + +// Use: https://kbdlayout.info/KBDUSX/scancodes +// Also valid for windows +static inline const std::map& scancode_map_linux() { + static const std::map ret{ + { 0x1E, NOTE_0}, // C0 + { 0x11, NOTE_0 + 1}, + { 0x1F, NOTE_0 + 2}, + { 0x12, NOTE_0 + 3}, + { 0x20, NOTE_0 + 4}, + { 0x21, NOTE_0 + 5}, + { 0x14, NOTE_0 + 6}, + { 0x22, NOTE_0 + 7}, + { 0x15, NOTE_0 + 8}, + { 0x23, NOTE_0 + 9}, + { 0x16, NOTE_0 + 10}, + { 0x24, NOTE_0 + 11}, + { 0x25, NOTE_0 + 12}, // C1 + { 0x18, NOTE_0 + 13}, + { 0x26, NOTE_0 + 14}, + { 0x19, NOTE_0 + 15}, + { 0x27, NOTE_0 + 16}, + { 0x28, NOTE_0 + 17}, + { 0x1B, NOTE_0 + 18}, + { 0x2B, NOTE_0 + 19}, + + { 0x29, VEL_0 + int(0)}, + { 0x02, VEL_0 + int(1 * 127 / 12)}, + { 0x03, VEL_0 + int(2 * 127 / 12)}, + { 0x04, VEL_0 + int(3 * 127 / 12)}, + { 0x05, VEL_0 + int(4 * 127 / 12)}, + { 0x06, VEL_0 + int(5 * 127 / 12)}, + { 0x07, VEL_0 + int(6 * 127 / 12)}, + { 0x08, VEL_0 + int(7 * 127 / 12)}, + { 0x09, VEL_0 + int(8 * 127 / 12)}, + { 0x0A, VEL_0 + int(9 * 127 / 12)}, + { 0x0B, VEL_0 + int(10 * 127 / 12)}, + { 0x0C, VEL_0 + int(11 * 127 / 12)}, + { 0x0D, VEL_0 + int(127)}, + + { 0x2C, OCTAVE_MINUS }, + { 0x2D, OCTAVE_PLUS }, + { 0x2E, VELOCITY_MINUS }, + { 0x2F, VELOCITY_PLUS}, + }; + return ret; +} +// clang-format on /** * Used to set up keyboard input. * Your app should pass a function that will give you a callback @@ -13,80 +135,20 @@ namespace libremidi */ struct kbd_input_configuration { + // Note that on Linux with X11 scancodes should be offset by 8 (an X11 legacy quirk) + // ex.: pass QKeyEvent::nativeScanCode() - 8 to this API using scancode_callback = std::function; + // First argument is on key press, second on key release std::function set_input_scancode_callbacks - = [](scancode_callback, scancode_callback) {}; - - enum kbd_event - { - NOTE_0 = 0x0, // C - VEL_0 = NOTE_0 + 128, // Set velocity to 0 - OCT_0 = VEL_0 + 128, // Set octave to 0 - OCTAVE_PLUS = OCT_0 + 128, - OCTAVE_MINUS, - VELOCITY_PLUS, - VELOCITY_MINUS, - }; + = [](scancode_callback, scancode_callback) { }; - // Default map - // - // ,---,---,---,---,---,---,---,---,---,---,---,---,---,-------, - // | V0| V1| V2| V3| V4| V5| V6| V7| V8| V9|V10|V11|V12| <- | - // |---'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-----| - // | ->| | | C#| D#| | F#| G#| A#| | C#| D#| | F#| | - // |-----',--',--',--',--',--',--',--',--',--',--',--',--'| | - // | Caps | C | D | E | F | G | A | B | C | D | E | F | G | | - // |----,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'-,-'---'----| - // | -^ | | O-| O+| V-| V+| | | | | | | ----^ | - // |----'-,-',--'--,'---'---'---'---'---'---'-,-'---',--,------| - // | ctrl | | alt | |altgr | | ctrl | - // '------' '-----'--------------------------'------' '------' - - // clang-format off - // Use: https://kbdlayout.info/KBDUSX/scancodes - std::map scancode_map{ - { 0x1E, NOTE_0}, // C0 - { 0x11, NOTE_0 + 1}, - { 0x1F, NOTE_0 + 2}, - { 0x12, NOTE_0 + 3}, - { 0x20, NOTE_0 + 4}, - { 0x21, NOTE_0 + 5}, - { 0x14, NOTE_0 + 6}, - { 0x22, NOTE_0 + 7}, - { 0x15, NOTE_0 + 8}, - { 0x23, NOTE_0 + 9}, - { 0x16, NOTE_0 + 10}, - { 0x24, NOTE_0 + 11}, - { 0x25, NOTE_0 + 12}, // C1 - { 0x18, NOTE_0 + 13}, - { 0x26, NOTE_0 + 14}, - { 0x19, NOTE_0 + 15}, - { 0x27, NOTE_0 + 16}, - { 0x28, NOTE_0 + 17}, - { 0x1B, NOTE_0 + 18}, - { 0x2B, NOTE_0 + 19}, - - { 0x29, VEL_0 + int(0)}, - { 0x02, VEL_0 + int(1 * 127 / 12)}, - { 0x03, VEL_0 + int(2 * 127 / 12)}, - { 0x04, VEL_0 + int(3 * 127 / 12)}, - { 0x05, VEL_0 + int(4 * 127 / 12)}, - { 0x06, VEL_0 + int(5 * 127 / 12)}, - { 0x07, VEL_0 + int(6 * 127 / 12)}, - { 0x08, VEL_0 + int(7 * 127 / 12)}, - { 0x09, VEL_0 + int(8 * 127 / 12)}, - { 0x0A, VEL_0 + int(9 * 127 / 12)}, - { 0x0B, VEL_0 + int(10 * 127 / 12)}, - { 0x0C, VEL_0 + int(11 * 127 / 12)}, - { 0x0D, VEL_0 + int(127)}, - - { 0x2C, OCTAVE_MINUS }, - { 0x2D, OCTAVE_PLUS }, - { 0x2E, VELOCITY_MINUS }, - { 0x2F, VELOCITY_PLUS}, - }; - // clang-format on + std::map scancode_map +#if defined(__APPLE__) + = scancode_map_macos() +#else + = scancode_map_linux() +#endif + ; }; - } diff --git a/include/libremidi/backends/keyboard/midi_in.hpp b/include/libremidi/backends/keyboard/midi_in.hpp index 5b11124..e77157a 100644 --- a/include/libremidi/backends/keyboard/midi_in.hpp +++ b/include/libremidi/backends/keyboard/midi_in.hpp @@ -45,7 +45,7 @@ class midi_in_kbd final void on_keypress(int scancode) { - using kevent = kbd_input_configuration::kbd_event; + using kevent = libremidi::kbd_event; auto it = configuration.scancode_map.find(scancode); if (it == configuration.scancode_map.end()) @@ -88,7 +88,7 @@ class midi_in_kbd final void on_keyrelease(int scancode) { - using kevent = kbd_input_configuration::kbd_event; + using kevent = libremidi::kbd_event; auto it = configuration.scancode_map.find(scancode); if (it == configuration.scancode_map.end()) diff --git a/include/libremidi/configurations.hpp b/include/libremidi/configurations.hpp index b872f41..7509410 100644 --- a/include/libremidi/configurations.hpp +++ b/include/libremidi/configurations.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -14,11 +15,51 @@ #include #include #include +#include +#include namespace libremidi { - +struct unspecified_configuration +{ +}; struct dummy_configuration { }; + +using input_api_configuration = std::variant< + unspecified_configuration, dummy_configuration, alsa_raw_input_configuration, + alsa_raw_ump::input_configuration, alsa_seq::input_configuration, + alsa_seq_ump::input_configuration, coremidi_input_configuration, + coremidi_ump::input_configuration, emscripten_input_configuration, jack_input_configuration, + kbd_input_configuration, libremidi::net::dgram_input_configuration, + libremidi::net_ump::dgram_input_configuration, pipewire_input_configuration, + winmidi::input_configuration, winmm_input_configuration, winuwp_input_configuration, + libremidi::API>; + +using output_api_configuration = std::variant< + unspecified_configuration, dummy_configuration, alsa_raw_output_configuration, + alsa_raw_ump::output_configuration, alsa_seq::output_configuration, + alsa_seq_ump::output_configuration, coremidi_output_configuration, + coremidi_ump::output_configuration, emscripten_output_configuration, jack_output_configuration, + libremidi::net::dgram_output_configuration, libremidi::net_ump::dgram_output_configuration, + pipewire_output_configuration, winmidi::output_configuration, winmm_output_configuration, + winuwp_output_configuration, libremidi::API>; + +using observer_api_configuration = std::variant< + unspecified_configuration, dummy_configuration, alsa_raw_observer_configuration, + alsa_raw_ump::observer_configuration, alsa_seq::observer_configuration, + alsa_seq_ump::observer_configuration, coremidi_observer_configuration, + coremidi_ump::observer_configuration, emscripten_observer_configuration, + jack_observer_configuration, libremidi::net::dgram_observer_configuration, + libremidi::net_ump::dgram_observer_configuration, pipewire_observer_configuration, + winmidi::observer_configuration, winmm_observer_configuration, winuwp_observer_configuration, + libremidi::API>; + +LIBREMIDI_EXPORT +libremidi::API midi_api(const input_api_configuration& conf); +LIBREMIDI_EXPORT +libremidi::API midi_api(const output_api_configuration& conf); +LIBREMIDI_EXPORT +libremidi::API midi_api(const observer_api_configuration& conf); } diff --git a/include/libremidi/defaults.hpp b/include/libremidi/defaults.hpp index 6d380dc..edbc888 100644 --- a/include/libremidi/defaults.hpp +++ b/include/libremidi/defaults.hpp @@ -1,11 +1,11 @@ #pragma once #include #include +#include #include #include #include -#include #include namespace libremidi @@ -16,22 +16,22 @@ class observer; //! Get the default midi in configuration object for a given API LIBREMIDI_EXPORT -std::any midi_in_configuration_for(libremidi::API); +input_api_configuration midi_in_configuration_for(libremidi::API); //! Get the default midi out configuration object for a given API LIBREMIDI_EXPORT -std::any midi_out_configuration_for(libremidi::API); +output_api_configuration midi_out_configuration_for(libremidi::API); //! Get the default observer configuration object for a given API LIBREMIDI_EXPORT -std::any observer_configuration_for(libremidi::API); +observer_api_configuration observer_configuration_for(libremidi::API); //! Get a matching midi in configuration object for a given observer instance. LIBREMIDI_EXPORT -std::any midi_in_configuration_for(const libremidi::observer&); +input_api_configuration midi_in_configuration_for(const libremidi::observer&); //! Get a matching midi out configuration object for a given observer instance. LIBREMIDI_EXPORT -std::any midi_out_configuration_for(const libremidi::observer&); +output_api_configuration midi_out_configuration_for(const libremidi::observer&); //! Get the default port for midi input (if any) in a given API. //! Note that this will only return a hardware / physical port. @@ -47,15 +47,15 @@ namespace midi1 { //! Get a default configuration for creating a MIDI 1 input LIBREMIDI_EXPORT -std::any in_default_configuration(); +input_api_configuration in_default_configuration(); //! Get a default configuration for creating a MIDI 1 output LIBREMIDI_EXPORT -std::any out_default_configuration(); +output_api_configuration out_default_configuration(); //! Get a default configuration for creating a MIDI 1 observer LIBREMIDI_EXPORT -std::any observer_default_configuration(); +observer_api_configuration observer_default_configuration(); //! Get a default MIDI 1 input port for the default API of the system inline std::optional in_default_port() noexcept @@ -74,15 +74,15 @@ namespace midi2 { //! Get a default configuration for creating a MIDI 2 input LIBREMIDI_EXPORT -std::any in_default_configuration(); +input_api_configuration in_default_configuration(); //! Get a default configuration for creating a MIDI 2 output LIBREMIDI_EXPORT -std::any out_default_configuration(); +output_api_configuration out_default_configuration(); //! Get a default configuration for creating a MIDI 2 observer LIBREMIDI_EXPORT -std::any observer_default_configuration(); +observer_api_configuration observer_default_configuration(); //! Get a default MIDI 2 input port for the default API of the system inline std::optional in_default_port() noexcept diff --git a/include/libremidi/libremidi.cpp b/include/libremidi/libremidi.cpp index 3cb79ae..b1c9dc5 100644 --- a/include/libremidi/libremidi.cpp +++ b/include/libremidi/libremidi.cpp @@ -53,14 +53,25 @@ LIBREMIDI_INLINE libremidi::API get_compiled_api_by_name(std::string_view name) midi2::for_all_backends([&](auto b) { apis.push_back(b.API); }); return apis; } + +LIBREMIDI_INLINE +libremidi::API midi_api(const input_api_configuration& conf) +{ + libremidi::API ret = libremidi::API::UNSPECIFIED; + midi_any::for_all_backends([&](T) { + if (std::get_if(&conf)) + { + ret = T::API; + } + }); + return ret; +} LIBREMIDI_INLINE -libremidi::API midi_api(const std::any& conf) +libremidi::API midi_api(const output_api_configuration& conf) { libremidi::API ret = libremidi::API::UNSPECIFIED; midi_any::for_all_backends([&](T) { - if (std::any_cast(&conf) - || std::any_cast(&conf) - || std::any_cast(&conf)) + if (std::get_if(&conf)) { ret = T::API; } @@ -68,9 +79,22 @@ libremidi::API midi_api(const std::any& conf) return ret; } LIBREMIDI_INLINE -std::any midi_in_configuration_for(libremidi::API api) +libremidi::API midi_api(const observer_api_configuration& conf) +{ + libremidi::API ret = libremidi::API::UNSPECIFIED; + midi_any::for_all_backends([&](T) { + if (std::get_if(&conf)) + { + ret = T::API; + } + }); + return ret; +} + +LIBREMIDI_INLINE +input_api_configuration midi_in_configuration_for(libremidi::API api) { - std::any ret; + input_api_configuration ret; midi_any::for_backend(api, [&](T) { using conf_type = typename T::midi_in_configuration; ret = conf_type{}; @@ -79,9 +103,9 @@ std::any midi_in_configuration_for(libremidi::API api) } LIBREMIDI_INLINE -std::any midi_out_configuration_for(libremidi::API api) +output_api_configuration midi_out_configuration_for(libremidi::API api) { - std::any ret; + output_api_configuration ret; midi_any::for_backend(api, [&](T) { using conf_type = typename T::midi_out_configuration; ret = conf_type{}; @@ -90,9 +114,9 @@ std::any midi_out_configuration_for(libremidi::API api) } LIBREMIDI_INLINE -std::any observer_configuration_for(libremidi::API api) +observer_api_configuration observer_configuration_for(libremidi::API api) { - std::any ret; + observer_api_configuration ret; midi_any::for_backend(api, [&](T) { using conf_type = typename T::midi_observer_configuration; ret = conf_type{}; @@ -101,13 +125,13 @@ std::any observer_configuration_for(libremidi::API api) } LIBREMIDI_INLINE -std::any midi_in_configuration_for(const libremidi::observer& obs) +input_api_configuration midi_in_configuration_for(const libremidi::observer& obs) { return midi_in_configuration_for(obs.get_current_api()); } LIBREMIDI_INLINE -std::any midi_out_configuration_for(const libremidi::observer& obs) +output_api_configuration midi_out_configuration_for(const libremidi::observer& obs) { // FIXME reuse context when meaningful, e.g. ALSA, JACK... return midi_out_configuration_for(obs.get_current_api()); @@ -144,19 +168,19 @@ catch (const std::exception& e) namespace midi1 { LIBREMIDI_INLINE -std::any in_default_configuration() +input_api_configuration in_default_configuration() { return midi_in_configuration_for(default_api()); } LIBREMIDI_INLINE -std::any out_default_configuration() +output_api_configuration out_default_configuration() { return midi_out_configuration_for(default_api()); } LIBREMIDI_INLINE -std::any observer_default_configuration() +observer_api_configuration observer_default_configuration() { return observer_configuration_for(default_api()); } @@ -165,19 +189,19 @@ std::any observer_default_configuration() namespace midi2 { LIBREMIDI_INLINE -std::any in_default_configuration() +input_api_configuration in_default_configuration() { return midi_in_configuration_for(default_api()); } LIBREMIDI_INLINE -std::any out_default_configuration() +output_api_configuration out_default_configuration() { return midi_out_configuration_for(default_api()); } LIBREMIDI_INLINE -std::any observer_default_configuration() +observer_api_configuration observer_default_configuration() { return observer_configuration_for(default_api()); } diff --git a/include/libremidi/libremidi.hpp b/include/libremidi/libremidi.hpp index 4085980..29533f2 100644 --- a/include/libremidi/libremidi.hpp +++ b/include/libremidi/libremidi.hpp @@ -58,6 +58,7 @@ */ #include +#include #include #include #include @@ -68,7 +69,6 @@ #include #include #endif -#include namespace libremidi { @@ -84,7 +84,7 @@ class LIBREMIDI_EXPORT observer //! such as jack_observer_configuration, winmm_observer_configuration, etc... //! * if no callbacks are passed, no secondary thread will be created unless absolutely necessary explicit observer(const observer_configuration& conf = {}) noexcept; - explicit observer(observer_configuration conf, std::any api_conf); + explicit observer(observer_configuration conf, observer_api_configuration api_conf); observer(const observer&) = delete; observer(observer&& other) noexcept; observer& operator=(const observer&) = delete; @@ -111,7 +111,7 @@ class LIBREMIDI_EXPORT midi_in //! Construct a midi_in object with a configuration object for a specific MIDI 1 back-end //! see configuration.hpp for the available configuration types. //! An exception will be thrown if the requested back-end cannot be opened. - explicit midi_in(input_configuration conf, std::any api_conf); + explicit midi_in(input_configuration conf, input_api_configuration api_conf); //! Construct a midi_in object with the default MIDI 2 back-end for the platform explicit midi_in(ump_input_configuration conf) noexcept; @@ -119,7 +119,7 @@ class LIBREMIDI_EXPORT midi_in //! Construct a midi_in object with a configuration object for a specific MIDI 2 back-end //! see configuration.hpp for the available configuration types. //! An exception will be thrown if the requested back-end cannot be opened. - explicit midi_in(ump_input_configuration conf, std::any api_conf); + explicit midi_in(ump_input_configuration conf, input_api_configuration api_conf); midi_in(const midi_in&) = delete; midi_in(midi_in&& other) noexcept; @@ -170,7 +170,7 @@ class LIBREMIDI_EXPORT midi_out //! Construct a midi_out object with a configuration object for a specific back-end //! see configuration.hpp for the available configuration types. //! An exception will be thrown if the requested back-end cannot be opened. - explicit midi_out(output_configuration conf, std::any api_conf); + explicit midi_out(output_configuration conf, output_api_configuration api_conf); midi_out(const midi_out&) = delete; midi_out(midi_out&& other) noexcept; diff --git a/include/libremidi/midi_in.cpp b/include/libremidi/midi_in.cpp index 29ba76a..cd3c923 100644 --- a/include/libremidi/midi_in.cpp +++ b/include/libremidi/midi_in.cpp @@ -61,14 +61,14 @@ convert_midi2_to_midi1_input_configuration(const ump_input_configuration& base_c } static LIBREMIDI_INLINE std::unique_ptr -make_midi_in(auto base_conf, std::any api_conf, auto backends) +make_midi_in(auto base_conf, input_api_configuration api_conf, auto backends) { std::unique_ptr ptr; assert(base_conf.on_message || base_conf.on_raw_data); auto from_api = [&](T& /*backend*/) mutable { - if (auto conf = std::any_cast(&api_conf)) + if (auto conf = std::get_if(&api_conf)) { ptr = libremidi::make(std::move(base_conf), std::move(*conf)); return true; @@ -117,8 +117,9 @@ make_midi1_in(const input_configuration& base_conf) return std::make_unique(input_configuration{}, dummy_configuration{}); } -static LIBREMIDI_INLINE std::unique_ptr -make_midi1_in(const input_configuration& base_conf, const std::any& api_conf, libremidi::API api) +static LIBREMIDI_INLINE std::unique_ptr make_midi1_in( + const input_configuration& base_conf, const input_api_configuration& api_conf, + libremidi::API api) { if (libremidi::is_midi1(api)) { @@ -133,13 +134,13 @@ make_midi1_in(const input_configuration& base_conf, const std::any& api_conf, li } static LIBREMIDI_INLINE std::unique_ptr -make_midi1_in(const input_configuration& base_conf, const std::any& api_conf) +make_midi1_in(const input_configuration& base_conf, const input_api_configuration& api_conf) { - if (!api_conf.has_value()) + if (std::get_if(&api_conf)) { return make_midi1_in(base_conf); } - else if (auto api_p = std::any_cast(&api_conf)) + else if (auto api_p = std::get_if(&api_conf)) { if (*api_p == libremidi::API::UNSPECIFIED) { @@ -166,7 +167,7 @@ LIBREMIDI_INLINE midi_in::midi_in(const input_configuration& base_conf) noexcept } LIBREMIDI_INLINE -midi_in::midi_in(input_configuration base_conf, std::any api_conf) +midi_in::midi_in(input_configuration base_conf, input_api_configuration api_conf) : impl_{make_midi1_in(base_conf, api_conf)} { if (!impl_) @@ -214,7 +215,8 @@ make_midi2_in(const ump_input_configuration& base_conf) } static LIBREMIDI_INLINE std::unique_ptr make_midi2_in( - const ump_input_configuration& base_conf, const std::any& api_conf, libremidi::API api) + const ump_input_configuration& base_conf, const input_api_configuration& api_conf, + libremidi::API api) { if (is_midi2(api)) { @@ -230,13 +232,13 @@ static LIBREMIDI_INLINE std::unique_ptr make_midi2_in( } static LIBREMIDI_INLINE std::unique_ptr -make_midi2_in(const ump_input_configuration& base_conf, const std::any& api_conf) +make_midi2_in(const ump_input_configuration& base_conf, const input_api_configuration& api_conf) { - if (!api_conf.has_value()) + if (std::get_if(&api_conf)) { return make_midi2_in(base_conf); } - else if (auto api_p = std::any_cast(&api_conf)) + else if (auto api_p = std::get_if(&api_conf)) { if (*api_p == libremidi::API::UNSPECIFIED) { @@ -263,7 +265,7 @@ LIBREMIDI_INLINE midi_in::midi_in(ump_input_configuration base_conf) noexcept } LIBREMIDI_INLINE -midi_in::midi_in(ump_input_configuration base_conf, std::any api_conf) +midi_in::midi_in(ump_input_configuration base_conf, input_api_configuration api_conf) : impl_{make_midi2_in(base_conf, api_conf)} { if (!impl_) diff --git a/include/libremidi/midi_out.cpp b/include/libremidi/midi_out.cpp index 82b3b7a..e89b96d 100644 --- a/include/libremidi/midi_out.cpp +++ b/include/libremidi/midi_out.cpp @@ -11,11 +11,11 @@ namespace libremidi { static LIBREMIDI_INLINE std::unique_ptr -make_midi_out_impl(auto base_conf, std::any api_conf) +make_midi_out_impl(auto base_conf, output_api_configuration api_conf) { std::unique_ptr ptr; auto from_api = [&](T& /*backend*/) mutable { - if (auto conf = std::any_cast(&api_conf)) + if (auto conf = std::get_if(&api_conf)) { ptr = libremidi::make(std::move(base_conf), std::move(*conf)); return true; @@ -58,13 +58,13 @@ make_midi_out(const output_configuration& base_conf) } static LIBREMIDI_INLINE std::unique_ptr -make_midi_out(const output_configuration& base_conf, const std::any& api_conf) +make_midi_out(const output_configuration& base_conf, const output_api_configuration& api_conf) { - if (!api_conf.has_value()) + if (std::get_if(&api_conf)) { return make_midi_out(base_conf); } - else if (auto api_p = std::any_cast(&api_conf)) + else if (auto api_p = std::get_if(&api_conf)) { if (*api_p == libremidi::API::UNSPECIFIED) { @@ -90,7 +90,7 @@ LIBREMIDI_INLINE midi_out::midi_out(const output_configuration& base_conf) noexc } LIBREMIDI_INLINE -midi_out::midi_out(output_configuration base_conf, std::any api_conf) +midi_out::midi_out(output_configuration base_conf, output_api_configuration api_conf) : impl_{make_midi_out(base_conf, api_conf)} { if (!impl_) diff --git a/include/libremidi/observer.cpp b/include/libremidi/observer.cpp index 442cffb..7b3ad8f 100644 --- a/include/libremidi/observer.cpp +++ b/include/libremidi/observer.cpp @@ -37,11 +37,11 @@ static LIBREMIDI_INLINE std::unique_ptr make_observer(auto base_co return std::make_unique(observer_configuration{}, dummy_configuration{}); } -LIBREMIDI_INLINE auto make_observer_impl(auto base_conf, std::any api_conf) +LIBREMIDI_INLINE auto make_observer_impl(auto base_conf, observer_api_configuration api_conf) { std::unique_ptr ptr; auto from_api = [&](T& /*backend*/) mutable { - if (auto conf = std::any_cast(&api_conf)) + if (auto conf = std::get_if(&api_conf)) { ptr = libremidi::make(std::move(base_conf), std::move(*conf)); return true; @@ -53,13 +53,14 @@ LIBREMIDI_INLINE auto make_observer_impl(auto base_conf, std::any api_conf) return ptr; } -LIBREMIDI_INLINE std::unique_ptr make_observer(auto base_conf, std::any api_conf) +LIBREMIDI_INLINE std::unique_ptr +make_observer(auto base_conf, observer_api_configuration api_conf) { - if (!api_conf.has_value()) + if (std::get_if(&api_conf)) { return make_observer(base_conf); } - else if (auto api_p = std::any_cast(&api_conf)) + else if (auto api_p = std::get_if(&api_conf)) { if (*api_p == libremidi::API::UNSPECIFIED) { @@ -84,7 +85,8 @@ LIBREMIDI_INLINE observer::observer(const observer_configuration& base_conf) noe { } -LIBREMIDI_INLINE observer::observer(observer_configuration base_conf, std::any api_conf) +LIBREMIDI_INLINE +observer::observer(observer_configuration base_conf, observer_api_configuration api_conf) : impl_{make_observer(base_conf, api_conf)} { if (!impl_) diff --git a/include/libremidi/protocols/remote_control.hpp b/include/libremidi/protocols/remote_control.hpp index 2008b3c..32f04b1 100644 --- a/include/libremidi/protocols/remote_control.hpp +++ b/include/libremidi/protocols/remote_control.hpp @@ -703,7 +703,7 @@ struct remote_control_processor : libremidi::error_handler switch (message.get_message_type()) { case libremidi::message_type::SYSTEM_EXCLUSIVE: - if (int N = message.size(); N >= 7) + if (auto N = message.size(); N >= 7) { const uint8_t* bytes = message.bytes.data(); // strip 0xF0 & 0xF7 diff --git a/include/libremidi/shared_context.hpp b/include/libremidi/shared_context.hpp index f794aa2..ad9d9a4 100644 --- a/include/libremidi/shared_context.hpp +++ b/include/libremidi/shared_context.hpp @@ -1,8 +1,6 @@ #pragma once #include -#include - -#include +#include namespace libremidi { @@ -24,7 +22,9 @@ class shared_context struct shared_configurations { std::shared_ptr context; - std::any observer, in, out; + observer_api_configuration observer; + input_api_configuration in; + output_api_configuration out; }; LIBREMIDI_EXPORT diff --git a/tests/unit/midi_in.cpp b/tests/unit/midi_in.cpp index ee7f06b..1fa047f 100644 --- a/tests/unit/midi_in.cpp +++ b/tests/unit/midi_in.cpp @@ -50,7 +50,9 @@ TEST_CASE("creation", "[midi_in]") GIVEN("A midi input with an empty API") { - libremidi::midi_in in(libremidi::input_configuration{.on_message = [](auto) {}}, std::any{}); + libremidi::midi_in in( + libremidi::input_configuration{.on_message = [](auto) { }}, + libremidi::input_api_configuration{}); THEN("created with defaultapi") { REQUIRE(in.get_current_api() == libremidi::midi1::default_api()); @@ -66,15 +68,6 @@ TEST_CASE("creation", "[midi_in]") } } - GIVEN("A midi input with a wrong API") - { - libremidi::midi_in in(libremidi::input_configuration{.on_message = [](auto) {}}, float(1.23f)); - THEN("created with dummy api") - { - REQUIRE(in.get_current_api() == libremidi::API::DUMMY); - } - } - GIVEN("A midi input with a proper API") { libremidi::midi_in in( diff --git a/tests/unit/midi_out.cpp b/tests/unit/midi_out.cpp index 8c2affe..043858b 100644 --- a/tests/unit/midi_out.cpp +++ b/tests/unit/midi_out.cpp @@ -31,7 +31,7 @@ TEST_CASE("creation", "[midi_out]") GIVEN("A midi output with an empty API") { - libremidi::midi_out out({}, std::any{}); + libremidi::midi_out out({}, libremidi::output_api_configuration{}); THEN("created with defaultapi") { REQUIRE(out.get_current_api() == libremidi::midi1::default_api()); @@ -45,15 +45,6 @@ TEST_CASE("creation", "[midi_out]") REQUIRE(out.get_current_api() == libremidi::API::JACK_MIDI); } } - - GIVEN("A midi output with a wrong API") - { - libremidi::midi_out out({}, float(1.23f)); - THEN("created with dummy api") - { - REQUIRE(out.get_current_api() == libremidi::API::DUMMY); - } - } } TEST_CASE("sending messages with span", "[midi_out]")