#pragma once #include #if !__has_include() && !__has_include() #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 #include #if LIBREMIDI_ALSA_HAS_RAMWIDI #include #endif #if LIBREMIDI_ALSA_HAS_UMP #include #include #endif #endif #if defined(LIBREMIDI_JACK) #include #endif #if defined(LIBREMIDI_PIPEWIRE) #include #endif #if defined(LIBREMIDI_COREMIDI) #include #include #endif #if defined(LIBREMIDI_WINMM) #include #endif #if defined(LIBREMIDI_WINUWP) #include #if __has_include() #include #endif #endif #if defined(LIBREMIDI_EMSCRIPTEN) #include #endif #include namespace libremidi { // The order here will control the order of the API search in // the constructor. template constexpr auto make_tl(unused, Args...) { return std::tuple{}; } 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{} #endif , dummy_backend{}); // There should always be at least one back-end. static_assert(std::tuple_size_v >= 1); template auto for_all_backends(F&& f) { std::apply([&](auto&&... x) { ((x.available() && (f(x), true)), ...); }, available_backends); } template 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 #if defined(LIBREMIDI_JACK) #endif #if defined(LIBREMIDI_WINUWP) #if __has_include() , winmidi::backend{} #endif #endif #if defined(LIBREMIDI_EMSCRIPTEN) #endif , dummy_backend{}); // There should always be at least one back-end. static_assert(std::tuple_size_v >= 1); template auto for_all_backends(F&& f) { std::apply([&](auto&&... x) { (f(x), ...); }, available_backends); } template 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 auto for_all_backends(F&& f) { midi1::for_all_backends(f); midi2::for_all_backends(f); } template auto for_backend(libremidi::API api, F&& f) { midi1::for_backend(api, f); midi2::for_backend(api, f); } } }