2024-10-09 02:01:23 +02:00
|
|
|
#if !defined(LIBREMIDI_HEADER_ONLY)
|
|
|
|
|
#include <libremidi/libremidi.hpp>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <libremidi/backends.hpp>
|
|
|
|
|
#include <libremidi/detail/midi_api.hpp>
|
|
|
|
|
|
2025-06-13 19:06:09 +02:00
|
|
|
#include <utility>
|
|
|
|
|
|
2024-10-09 02:01:23 +02:00
|
|
|
namespace libremidi
|
|
|
|
|
{
|
2024-10-28 19:24:18 +01:00
|
|
|
|
2025-06-13 19:06:09 +02:00
|
|
|
static LIBREMIDI_INLINE std::unique_ptr<observer_api> make_observer(const auto& base_conf)
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
for (const auto& api : available_apis())
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
if (auto impl = make_observer(base_conf, observer_configuration_for(api)))
|
|
|
|
|
return impl;
|
2024-10-28 19:24:18 +01:00
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (const auto& api : available_ump_apis())
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
if (auto impl = make_observer(base_conf, observer_configuration_for(api)))
|
|
|
|
|
return impl;
|
2024-10-28 19:24:18 +01:00
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return std::make_unique<observer_dummy>(observer_configuration{}, dummy_configuration{});
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-13 19:06:09 +02:00
|
|
|
LIBREMIDI_INLINE auto make_observer_impl(auto base_conf, observer_api_configuration api_conf)
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
|
|
|
|
std::unique_ptr<observer_api> ptr;
|
|
|
|
|
auto from_api = [&]<typename T>(T& /*backend*/) mutable {
|
2025-06-13 19:06:09 +02:00
|
|
|
if (auto conf = std::get_if<typename T::midi_observer_configuration>(&api_conf))
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
|
|
|
|
ptr = libremidi::make<typename T::midi_observer>(std::move(base_conf), std::move(*conf));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
std::apply([&](auto&&... b) { (from_api(b) || ...); }, midi1::available_backends);
|
2025-06-13 19:06:09 +02:00
|
|
|
if (!ptr)
|
|
|
|
|
std::apply([&](auto&&... b) { (from_api(b) || ...); }, midi2::available_backends);
|
2024-10-09 02:01:23 +02:00
|
|
|
return ptr;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-13 19:06:09 +02:00
|
|
|
LIBREMIDI_INLINE std::unique_ptr<observer_api>
|
|
|
|
|
make_observer(const auto& base_conf, observer_api_configuration api_conf)
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
if (std::get_if<unspecified_configuration>(&api_conf))
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
2024-10-28 19:24:18 +01:00
|
|
|
return make_observer(base_conf);
|
|
|
|
|
}
|
2025-06-13 19:06:09 +02:00
|
|
|
else if (auto api_p = std::get_if<libremidi::API>(&api_conf))
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
if (*api_p == libremidi::API::UNSPECIFIED)
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
2024-10-28 19:24:18 +01:00
|
|
|
return make_observer(base_conf);
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
2024-10-28 19:24:18 +01:00
|
|
|
else
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
2024-10-28 19:24:18 +01:00
|
|
|
return make_observer_impl(base_conf, observer_configuration_for(*api_p));
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-10-28 19:24:18 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (auto api = libremidi::midi_api(api_conf); api == libremidi::API::UNSPECIFIED)
|
|
|
|
|
return {};
|
|
|
|
|
else
|
|
|
|
|
return make_observer_impl(base_conf, api_conf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBREMIDI_INLINE observer::observer(const observer_configuration& base_conf) noexcept
|
2025-06-13 19:06:09 +02:00
|
|
|
: m_impl{make_observer(base_conf)}
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
2025-06-13 19:06:09 +02:00
|
|
|
LIBREMIDI_INLINE
|
|
|
|
|
observer::observer(const observer_configuration& base_conf, observer_api_configuration api_conf)
|
|
|
|
|
: m_impl{make_observer(base_conf, std::move(api_conf))}
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
if (!m_impl)
|
2024-10-28 19:24:18 +01:00
|
|
|
{
|
|
|
|
|
error_handler e;
|
|
|
|
|
e.libremidi_handle_error(base_conf, "Could not open observer for the given api");
|
2025-06-13 19:06:09 +02:00
|
|
|
m_impl = std::make_unique<observer_dummy>(observer_configuration{}, dummy_configuration{});
|
2024-10-28 19:24:18 +01:00
|
|
|
}
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBREMIDI_INLINE observer::observer(observer&& other) noexcept
|
2025-06-13 19:06:09 +02:00
|
|
|
: m_impl{std::move(other.m_impl)}
|
2024-10-09 02:01:23 +02:00
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
other.m_impl = std::make_unique<libremidi::observer_dummy>(
|
2024-10-09 02:01:23 +02:00
|
|
|
observer_configuration{}, dummy_configuration{});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBREMIDI_INLINE observer& observer::operator=(observer&& other) noexcept
|
|
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
this->m_impl = std::move(other.m_impl);
|
|
|
|
|
other.m_impl = std::make_unique<libremidi::observer_dummy>(
|
2024-10-09 02:01:23 +02:00
|
|
|
observer_configuration{}, dummy_configuration{});
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBREMIDI_INLINE
|
|
|
|
|
observer::~observer() = default;
|
|
|
|
|
|
|
|
|
|
LIBREMIDI_INLINE
|
|
|
|
|
libremidi::API observer::get_current_api() const noexcept
|
|
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
return m_impl->get_current_api();
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBREMIDI_INLINE
|
|
|
|
|
std::vector<libremidi::input_port> observer::get_input_ports() const noexcept
|
|
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
return m_impl->get_input_ports();
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LIBREMIDI_INLINE
|
|
|
|
|
std::vector<libremidi::output_port> observer::get_output_ports() const noexcept
|
|
|
|
|
{
|
2025-06-13 19:06:09 +02:00
|
|
|
return m_impl->get_output_ports();
|
2024-10-09 02:01:23 +02:00
|
|
|
}
|
|
|
|
|
}
|