upgrade to libremidi 5.1, raylib and raygui latest

This commit is contained in:
Sebastian @ HfG
2025-06-13 19:16:35 +02:00
parent 62454960d1
commit 2cc6839009
112 changed files with 6484 additions and 1946 deletions
@@ -2,6 +2,7 @@
#include <libremidi/config.hpp>
#include <chrono>
#include <cstdint>
#include <functional>
#include <optional>
#include <span>
@@ -2,10 +2,17 @@
#include <libremidi/backends/linux/alsa.hpp>
#include <libremidi/config.hpp>
#include <libremidi/detail/observer.hpp>
#include <libremidi/observer_configuration.hpp>
#include <functional>
#include <alsa/asoundlib.h>
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <string_view>
#include <system_error>
#include <vector>
// Credits: greatly inspired from
@@ -27,14 +34,14 @@ struct alsa_raw_port_id
};
inline constexpr port_handle raw_to_port_handle(alsa_raw_port_id id) noexcept
{
return (uint64_t(id.card) << 32) + (uint64_t(id.dev) << 16) + id.port;
return (uint64_t(id.port) << 32) + (uint64_t(id.dev) << 16) + id.card;
}
inline constexpr alsa_raw_port_id raw_from_port_handle(port_handle p) noexcept
{
alsa_raw_port_id ret;
ret.card = (p & 0x00'00'FF'FF'00'00'00'00) >> 32;
ret.port = (p & 0x00'00'FF'FF'00'00'00'00) >> 32;
ret.dev = (p & 0x00'00'00'00'FF'FF'00'00) >> 16;
ret.port = (p & 0x00'00'00'00'00'00'FF'FF);
ret.card = (p & 0x00'00'00'00'00'00'FF'FF);
return ret;
}
static_assert(raw_from_port_handle(raw_to_port_handle({102, 7, 3})).card == 102);
+12 -12
View File
@@ -200,7 +200,7 @@ public:
midi_in_alsa_raw_threaded(input_configuration&& conf, alsa_raw_input_configuration&& apiconf)
: midi_in_impl{std::move(conf), std::move(apiconf)}
{
if (this->termination_event < 0)
if (this->m_termination_event < 0)
{
libremidi_handle_error(this->configuration, "error creating eventfd.");
return;
@@ -220,7 +220,7 @@ public:
private:
void run_thread(auto parse_func)
{
fds_.push_back(this->termination_event);
fds_.push_back(this->m_termination_event);
const auto period
= std::chrono::duration_cast<std::chrono::milliseconds>(this->configuration.poll_period)
.count();
@@ -228,12 +228,12 @@ private:
for (;;)
{
// Poll
ssize_t err = poll(fds_.data(), fds_.size(), period);
ssize_t err = poll(fds_.data(), fds_.size(), static_cast<int32_t>(period));
if (err == -EAGAIN)
continue;
else if (err < 0)
return;
else if (termination_event.ready(fds_.back()))
else if (m_termination_event.ready(fds_.back()))
break;
err = do_read_events(parse_func, {fds_.data(), fds_.size() - 1});
@@ -250,11 +250,11 @@ private:
{
if (configuration.timestamps == timestamp_mode::NoTimestamp)
{
this->thread_ = std::thread{[this] { run_thread(&midi_in_impl::read_input_buffer); }};
this->m_thread = std::thread{[this] { run_thread(&midi_in_impl::read_input_buffer); }};
}
else
{
this->thread_ = std::thread{
this->m_thread = std::thread{
[this] { run_thread(&midi_in_impl::read_input_buffer_with_timestamps); }};
}
return stdx::error{};
@@ -282,16 +282,16 @@ private:
stdx::error close_port() override
{
termination_event.notify();
if (thread_.joinable())
thread_.join();
termination_event.consume(); // Reset to zero
m_termination_event.notify();
if (m_thread.joinable())
m_thread.join();
m_termination_event.consume(); // Reset to zero
return midi_in_impl::close_port();
}
std::thread thread_;
eventfd_notifier termination_event{};
std::thread m_thread;
eventfd_notifier m_termination_event{};
};
class midi_in_alsa_raw_manual : public midi_in_impl
@@ -6,7 +6,8 @@
#if LIBREMIDI_HAS_UDEV
#include <libremidi/backends/linux/helpers.hpp>
#include <libremidi/backends/linux/udev.hpp>
#include <libremidi/detail/observer.hpp>
#endif
#include <libremidi/detail/observer.hpp>
namespace libremidi::alsa_raw
{
@@ -31,24 +32,30 @@ public:
if (!configuration.has_callbacks())
return;
fds[0] = this->udev;
fds[1] = termination_event;
fds[2] = timer_fd;
#if LIBREMIDI_HAS_UDEV
m_fds[0] = this->m_udev;
m_fds[1] = m_termination_event;
m_fds[2] = m_timer_fd;
#endif
// Set-up initial state
if (configuration.notify_in_constructor)
this->check_devices();
#if LIBREMIDI_HAS_UDEV
// Start thread
thread = std::thread{[this] { this->run(); }};
m_thread = std::thread{[this] { this->run(); }};
#endif
}
~observer_impl_base()
{
termination_event.notify();
#if LIBREMIDI_HAS_UDEV
m_termination_event.notify();
if (thread.joinable())
thread.join();
if (m_thread.joinable())
m_thread.join();
#endif
}
std::vector<libremidi::input_port> get_input_ports() const noexcept override
@@ -78,11 +85,12 @@ public:
}
private:
#if LIBREMIDI_HAS_UDEV
void run()
{
for (;;)
{
if (int err = poll(fds, 3, -1); err < 0)
if (int err = poll(m_fds, 3, -1); err < 0)
{
if (err == -EAGAIN)
continue;
@@ -91,58 +99,77 @@ private:
}
// Check udev
if (fds[0].revents & POLLIN)
if (m_fds[0].revents & POLLIN)
{
udev_device* dev = udev.udev.monitor_receive_device(udev.monitor);
udev_device* dev = m_udev.udev.monitor_receive_device(m_udev.monitor);
if (!dev)
continue;
std::string_view act = udev.udev.device_get_action(dev);
std::string_view ss = udev.udev.device_get_subsystem(dev);
std::string_view act = m_udev.udev.device_get_action(dev);
std::string_view ss = m_udev.udev.device_get_subsystem(dev);
if (!act.empty() && ss == "snd_seq")
{
if (act == "add" || act == "remove")
{
// Check every 100 milliseconds for ten seconds
this->timer_fd.restart(configuration.poll_period.count());
timer_check_counts = 100;
this->m_timer_fd.restart(configuration.poll_period.count());
m_timer_check_counts = 100;
}
}
udev.udev.device_unref(dev);
m_udev.udev.device_unref(dev);
fds[0].revents = 0;
m_fds[0].revents = 0;
}
// Check eventfd
if (fds[1].revents & POLLIN)
if (m_fds[1].revents & POLLIN)
{
break;
}
// Check timer
if (fds[2].revents & POLLIN)
if (m_fds[2].revents & POLLIN)
{
if (this->timer_check_counts-- <= 0)
this->timer_fd.cancel();
fds[2].revents = 0;
if (this->m_timer_check_counts-- <= 0)
this->m_timer_fd.cancel();
m_fds[2].revents = 0;
check_devices();
}
}
}
#endif
template <bool Input>
auto to_port_info(alsa_raw::alsa_raw_port_info p) const noexcept
auto to_port_info(const alsa_raw::alsa_raw_port_info& p) const noexcept
-> std::conditional_t<Input, input_port, output_port>
{
#if LIBREMIDI_HAS_UDEV
auto [container, device, type] = get_udev_soundcard_info(m_udev, p.card);
#else
container_identifier container{};
device_identifier device{};
libremidi::port_information::port_type type{};
#endif
std::string display_name = p.subdevice_name;
if (display_name.empty())
display_name = p.device_name;
if (display_name.empty())
display_name = p.card_name;
if (display_name.empty())
display_name = "unknown";
return {
{.client = 0,
.container = container,
.device = device,
.port = raw_to_port_handle({p.card, p.dev, p.sub}),
.manufacturer = p.card_name,
.device_name = p.device_name,
.port_name = p.subdevice_name,
.display_name = p.subdevice_name}};
.display_name = std::move(display_name),
.type = type}};
}
void check_devices()
@@ -151,7 +178,7 @@ private:
new_devs.enumerate_cards();
for (auto& in_prev : current_inputs)
for (auto& in_prev : m_current_inputs)
{
if (auto it = std::find(new_devs.inputs.begin(), new_devs.inputs.end(), in_prev);
it == new_devs.inputs.end())
@@ -165,8 +192,8 @@ private:
for (auto& in_next : new_devs.inputs)
{
if (auto it = std::find(current_inputs.begin(), current_inputs.end(), in_next);
it == current_inputs.end())
if (auto it = std::find(m_current_inputs.begin(), m_current_inputs.end(), in_next);
it == m_current_inputs.end())
{
if (auto& cb = this->configuration.input_added)
{
@@ -175,7 +202,7 @@ private:
}
}
for (auto& out_prev : current_outputs)
for (auto& out_prev : m_current_outputs)
{
if (auto it = std::find(new_devs.outputs.begin(), new_devs.outputs.end(), out_prev);
it == new_devs.outputs.end())
@@ -189,8 +216,8 @@ private:
for (auto& out_next : new_devs.outputs)
{
if (auto it = std::find(current_outputs.begin(), current_outputs.end(), out_next);
it == current_outputs.end())
if (auto it = std::find(m_current_outputs.begin(), m_current_outputs.end(), out_next);
it == m_current_outputs.end())
{
if (auto& cb = this->configuration.output_added)
{
@@ -198,38 +225,24 @@ private:
}
}
}
current_inputs = std::move(new_devs.inputs);
current_outputs = std::move(new_devs.outputs);
m_current_inputs = std::move(new_devs.inputs);
m_current_outputs = std::move(new_devs.outputs);
}
udev_helper udev{};
eventfd_notifier termination_event{};
timerfd_timer timer_fd{};
int timer_check_counts = 0;
std::thread thread;
std::vector<alsa_raw_port_info> current_inputs;
std::vector<alsa_raw_port_info> current_outputs;
pollfd fds[3]{};
};
}
#else
#include <libremidi/backends/dummy.hpp>
namespace libremidi::alsa_raw
{
template <typename Enumerator>
struct observer_impl_base : observer_dummy
{
explicit observer_impl_base(
[[maybe_unused]] observer_configuration&& conf,
[[maybe_unused]] alsa_raw_observer_configuration&& apiconf)
: observer_dummy{dummy_configuration{}, dummy_configuration{}}
{
}
};
}
#if LIBREMIDI_HAS_UDEV
udev_helper m_udev{};
eventfd_notifier m_termination_event{};
timerfd_timer m_timer_fd{};
int m_timer_check_counts = 0;
std::thread m_thread;
pollfd m_fds[3]{};
#endif
std::vector<alsa_raw_port_info> m_current_inputs;
std::vector<alsa_raw_port_info> m_current_outputs;
};
}
namespace libremidi::alsa_raw
{
struct observer_impl : observer_impl_base<alsa_raw::midi1_enumerator>