2024-10-09 02:01:23 +02:00
|
|
|
#pragma once
|
2024-10-28 19:24:18 +01:00
|
|
|
#include <libremidi/config.hpp>
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
#include <tuple>
|
|
|
|
|
|
|
|
|
|
#if !__has_include(<weak_libjack.h>) && !__has_include(<jack/jack.h>)
|
|
|
|
|
#if defined(LIBREMIDI_JACK)
|
|
|
|
|
#undef LIBREMIDI_JACK
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
#if !defined(LIBREMIDI_ALSA) && !defined(LIBREMIDI_JACK) && !defined(LIBREMIDI_COREMIDI) \
|
|
|
|
|
&& !defined(LIBREMIDI_WINMM)
|
|
|
|
|
#define LIBREMIDI_DUMMY
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_ALSA)
|
|
|
|
|
#include <libremidi/backends/alsa_seq.hpp>
|
|
|
|
|
#include <libremidi/backends/linux/alsa.hpp>
|
|
|
|
|
|
|
|
|
|
#if LIBREMIDI_ALSA_HAS_RAMWIDI
|
|
|
|
|
#include <libremidi/backends/alsa_raw.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if LIBREMIDI_ALSA_HAS_UMP
|
|
|
|
|
#include <libremidi/backends/alsa_raw_ump.hpp>
|
|
|
|
|
#include <libremidi/backends/alsa_seq_ump.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_JACK)
|
|
|
|
|
#include <libremidi/backends/jack.hpp>
|
2025-06-13 19:16:35 +02:00
|
|
|
#include <libremidi/backends/jack_ump.hpp>
|
2024-10-09 02:01:23 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_PIPEWIRE)
|
|
|
|
|
#include <libremidi/backends/pipewire.hpp>
|
2025-06-13 19:16:35 +02:00
|
|
|
#if defined(LIBREMIDI_PIPEWIRE_UMP)
|
|
|
|
|
#include <libremidi/backends/pipewire_ump.hpp>
|
|
|
|
|
#endif
|
2024-10-09 02:01:23 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_COREMIDI)
|
|
|
|
|
#include <libremidi/backends/coremidi.hpp>
|
|
|
|
|
#include <libremidi/backends/coremidi_ump.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_WINMM)
|
|
|
|
|
#include <libremidi/backends/winmm.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_WINUWP)
|
|
|
|
|
#include <libremidi/backends/winuwp.hpp>
|
2024-10-28 19:24:18 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_WINMIDI)
|
|
|
|
|
#include <libremidi/backends/winmidi.hpp>
|
2024-10-09 02:01:23 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_EMSCRIPTEN)
|
|
|
|
|
#include <libremidi/backends/emscripten.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <libremidi/backends/dummy.hpp>
|
|
|
|
|
|
2024-10-28 19:24:18 +01:00
|
|
|
#if defined(LIBREMIDI_KEYBOARD)
|
|
|
|
|
#include <libremidi/backends/keyboard.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(LIBREMIDI_NETWORK)
|
|
|
|
|
#include <libremidi/backends/network.hpp>
|
|
|
|
|
#include <libremidi/backends/network_ump.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
namespace libremidi
|
|
|
|
|
{
|
|
|
|
|
// The order here will control the order of the API search in
|
|
|
|
|
// the constructor.
|
|
|
|
|
template <typename unused, typename... Args>
|
|
|
|
|
constexpr auto make_tl(unused, Args...)
|
|
|
|
|
{
|
|
|
|
|
return std::tuple<Args...>{};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace midi1
|
|
|
|
|
{
|
|
|
|
|
static constexpr auto available_backends = make_tl(
|
|
|
|
|
0
|
|
|
|
|
#if defined(LIBREMIDI_ALSA)
|
|
|
|
|
,
|
|
|
|
|
alsa_seq::backend{}
|
|
|
|
|
#if LIBREMIDI_ALSA_HAS_RAMWIDI
|
|
|
|
|
,
|
|
|
|
|
alsa_raw::backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_COREMIDI)
|
|
|
|
|
,
|
|
|
|
|
core_backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_WINMM)
|
|
|
|
|
,
|
|
|
|
|
winmm_backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_WINUWP)
|
|
|
|
|
,
|
|
|
|
|
winuwp_backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_EMSCRIPTEN)
|
|
|
|
|
,
|
|
|
|
|
emscripten_backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_JACK)
|
|
|
|
|
,
|
|
|
|
|
jack_backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_PIPEWIRE)
|
|
|
|
|
,
|
|
|
|
|
pipewire::backend{}
|
2024-10-28 19:24:18 +01:00
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_KEYBOARD)
|
|
|
|
|
,
|
|
|
|
|
kbd_backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_NETWORK)
|
|
|
|
|
,
|
|
|
|
|
net::backend{}
|
2024-10-09 02:01:23 +02:00
|
|
|
#endif
|
|
|
|
|
,
|
|
|
|
|
dummy_backend{});
|
|
|
|
|
|
|
|
|
|
// There should always be at least one back-end.
|
|
|
|
|
static_assert(std::tuple_size_v<decltype(available_backends)> >= 1);
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
auto for_all_backends(F&& f)
|
|
|
|
|
{
|
|
|
|
|
std::apply([&](auto&&... x) { ((x.available() && (f(x), true)), ...); }, available_backends);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
auto for_backend(libremidi::API api, F&& f)
|
|
|
|
|
{
|
|
|
|
|
static constexpr auto is_api = [](auto& backend, libremidi::API api) {
|
|
|
|
|
return backend.available() && backend.API == api;
|
|
|
|
|
};
|
|
|
|
|
std::apply([&](auto&&... b) { ((is_api(b, api) && (f(b), true)) || ...); }, available_backends);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace midi2
|
|
|
|
|
{
|
|
|
|
|
static constexpr auto available_backends = make_tl(
|
|
|
|
|
0
|
|
|
|
|
#if defined(LIBREMIDI_ALSA) && LIBREMIDI_ALSA_HAS_UMP
|
|
|
|
|
,
|
|
|
|
|
alsa_seq_ump::backend{}, alsa_raw_ump::backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_COREMIDI)
|
|
|
|
|
,
|
|
|
|
|
coremidi_ump::backend{}
|
|
|
|
|
#endif
|
2024-10-28 19:24:18 +01:00
|
|
|
#if defined(LIBREMIDI_WINMIDI)
|
2024-10-09 02:01:23 +02:00
|
|
|
,
|
|
|
|
|
winmidi::backend{}
|
|
|
|
|
#endif
|
2024-10-28 19:24:18 +01:00
|
|
|
#if defined(LIBREMIDI_NETWORK)
|
|
|
|
|
,
|
|
|
|
|
net_ump::backend{}
|
2025-06-13 19:16:35 +02:00
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_JACK)
|
|
|
|
|
,
|
|
|
|
|
jack_ump::backend{}
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(LIBREMIDI_PIPEWIRE_UMP)
|
|
|
|
|
,
|
|
|
|
|
pipewire_ump::backend{}
|
2024-10-09 02:01:23 +02:00
|
|
|
#endif
|
|
|
|
|
,
|
|
|
|
|
dummy_backend{});
|
|
|
|
|
|
|
|
|
|
// There should always be at least one back-end.
|
|
|
|
|
static_assert(std::tuple_size_v<decltype(available_backends)> >= 1);
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
auto for_all_backends(F&& f)
|
|
|
|
|
{
|
2025-06-13 19:16:35 +02:00
|
|
|
std::apply([&](auto&&... x) { ((x.available() && (f(x), true)), ...); }, available_backends);
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
auto for_backend(libremidi::API api, F&& f)
|
|
|
|
|
{
|
|
|
|
|
static constexpr auto is_api
|
|
|
|
|
= [](auto& backend, libremidi::API api) { return backend.API == api; };
|
|
|
|
|
std::apply([&](auto&&... b) { ((is_api(b, api) && (f(b), true)) || ...); }, available_backends);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
namespace midi_any
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
auto for_all_backends(F&& f)
|
|
|
|
|
{
|
|
|
|
|
midi1::for_all_backends(f);
|
|
|
|
|
midi2::for_all_backends(f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename F>
|
|
|
|
|
auto for_backend(libremidi::API api, F&& f)
|
|
|
|
|
{
|
|
|
|
|
midi1::for_backend(api, f);
|
|
|
|
|
midi2::for_backend(api, f);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-13 19:16:35 +02:00
|
|
|
void for_input_configuration(auto f, libremidi::input_api_configuration& api_conf)
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
auto from_api = [&]<typename T>(T& /*backend*/) mutable {
|
2025-06-13 19:16:35 +02:00
|
|
|
if (auto conf = std::get_if<typename T::midi_in_configuration>(&api_conf))
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
f(*conf);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
if (std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi1::available_backends))
|
|
|
|
|
return;
|
|
|
|
|
std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi2::available_backends);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-13 19:16:35 +02:00
|
|
|
void for_output_configuration(auto f, libremidi::output_api_configuration& api_conf)
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
auto from_api = [&]<typename T>(T& /*backend*/) mutable {
|
2025-06-13 19:16:35 +02:00
|
|
|
if (auto conf = std::get_if<typename T::midi_out_configuration>(&api_conf))
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
f(*conf);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
if (std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi1::available_backends))
|
|
|
|
|
return;
|
|
|
|
|
std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi2::available_backends);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-13 19:16:35 +02:00
|
|
|
void for_observer_configuration(auto f, libremidi::observer_api_configuration& api_conf)
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
auto from_api = [&]<typename T>(T& /*backend*/) mutable {
|
2025-06-13 19:16:35 +02:00
|
|
|
if (auto conf = std::get_if<typename T::midi_observer_configuration>(&api_conf))
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
f(*conf);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
if (std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi1::available_backends))
|
|
|
|
|
return;
|
|
|
|
|
std::apply([&](auto&&... b) { return (from_api(b) || ...); }, midi2::available_backends);
|
|
|
|
|
}
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
}
|