libremidi update to v5.4.3 and added virtual midi out as default

This commit is contained in:
Sebastian
2026-06-23 00:05:41 +02:00
parent dc0003232a
commit 51cd271b6f
166 changed files with 8135 additions and 2009 deletions
@@ -15,7 +15,7 @@ typedef struct snd_seq_addr
}
#endif
namespace libremidi::alsa_seq
NAMESPACE_LIBREMIDI::alsa_seq
{
// Possible parameters:
+42 -13
View File
@@ -9,7 +9,7 @@
#include <optional>
#include <string>
namespace libremidi::alsa_seq
NAMESPACE_LIBREMIDI::alsa_seq
{
struct event_handle
{
@@ -42,23 +42,39 @@ struct event_handle
~event_handle() { snd.seq.free_event(ev); }
};
namespace
{
inline constexpr port_handle seq_to_port_handle(uint64_t client, uint64_t port) noexcept
{
return (client << 32) + port;
return (port << 32) + client;
}
inline constexpr std::pair<int, int> seq_from_port_handle(port_handle p) noexcept
{
int client = p >> 32;
int port = p & 0xFFFFFFFF;
int port = p >> 32;
int client = p & 0xFFFFFFFF;
return {client, port};
}
inline void for_all_clients(
const libasound& snd, snd_seq_t* seq, const std::function<void(snd_seq_client_info_t&)>& func)
{
snd_seq_client_info_t* cinfo{};
snd_seq_client_info_alloca(&cinfo);
snd_seq_port_info_t* pinfo{};
snd_seq_port_info_alloca(&pinfo);
snd.seq.client_info_set_client(cinfo, -1);
while (snd.seq.query_next_client(seq, cinfo) >= 0)
{
int client = snd.seq.client_info_get_client(cinfo);
if (client == 0)
continue;
func(*cinfo);
}
}
inline void for_all_ports(
const libasound& snd, snd_seq_t* seq,
std::function<void(snd_seq_client_info_t&, snd_seq_port_info_t&)> func)
const std::function<void(snd_seq_client_info_t&, snd_seq_port_info_t&)>& func)
{
snd_seq_client_info_t* cinfo{};
snd_seq_client_info_alloca(&cinfo);
@@ -82,6 +98,21 @@ inline void for_all_ports(
}
}
inline void for_all_ports(
const libasound& snd, snd_seq_t* seq, int client,
const std::function<void(snd_seq_port_info_t&)>& func)
{
snd_seq_port_info_t* pinfo{};
snd_seq_port_info_alloca(&pinfo);
snd.seq.port_info_set_client(pinfo, client);
snd.seq.port_info_set_port(pinfo, -1);
while (snd.seq.query_next_port(seq, pinfo) >= 0)
{
func(*pinfo);
}
}
// This function is used to count or get the pinfo structure for a given port
// number.
inline unsigned int iterate_port_info(
@@ -125,7 +156,6 @@ inline unsigned int iterate_port_info(
return count;
return 0;
}
}
// A structure to hold variables related to the ALSA API
// implementation.
@@ -159,15 +189,15 @@ struct alsa_data
snd.seq.set_client_name(seq, configuration.client_name.data());
#if __has_include(<alsa/ump.h>)
if (snd.seq.ump.set_client_midi_version)
if (snd.seq.set_client_midi_version)
{
switch (configuration.midi_version)
{
case 1:
snd.seq.ump.set_client_midi_version(seq, SND_SEQ_CLIENT_LEGACY_MIDI);
snd.seq.set_client_midi_version(seq, SND_SEQ_CLIENT_LEGACY_MIDI);
break;
case 2:
snd.seq.ump.set_client_midi_version(seq, SND_SEQ_CLIENT_UMP_MIDI_2_0);
snd.seq.set_client_midi_version(seq, SND_SEQ_CLIENT_UMP_MIDI_2_0);
break;
}
}
@@ -272,8 +302,7 @@ struct alsa_data
// Make subscription
if (int err = snd.seq.port_subscribe_malloc(&this->subscription); err < 0)
{
self.libremidi_handle_error(
self.configuration, "ALSA error allocation port subscription.");
self.libremidi_handle_error(self.configuration, "ALSA error allocation port subscription.");
return err;
}
+25 -30
View File
@@ -5,7 +5,7 @@
#include <libremidi/detail/midi_in.hpp>
#include <libremidi/detail/midi_stream_decoder.hpp>
namespace libremidi::alsa_seq
NAMESPACE_LIBREMIDI::alsa_seq
{
struct dummy_processing
{
@@ -195,11 +195,6 @@ public:
return stdx::error{};
}
stdx::error set_client_name(std::string_view clientName) override
{
return alsa_data::set_client_name(clientName);
}
stdx::error set_port_name(std::string_view portName) override
{
return alsa_data::set_port_name(portName);
@@ -212,7 +207,7 @@ public:
.count();
}
int process_event(const snd_seq_event_t& ev)
int64_t process_event(const snd_seq_event_t& ev)
{
if constexpr (ConfigurationImpl::midi_version == 1)
{
@@ -258,17 +253,17 @@ public:
return 0;
}
int process_events()
int64_t process_events()
{
if constexpr (ConfigurationImpl::midi_version == 1)
{
snd_seq_event_t* ev{};
event_handle handle{snd};
int result = 0;
int64_t result = 0;
if ((result = snd.seq.event_input(seq, &ev)) > 0)
{
handle.reset(ev);
if (int err = process_event(*ev); err < 0)
if (auto err = process_event(*ev); err < 0)
{
return err;
}
@@ -353,7 +348,7 @@ public:
midi_in_alsa_threaded(ConfigurationBase&& conf, ConfigurationImpl&& apiconf)
: midi_in_impl<ConfigurationBase, ConfigurationImpl>{std::move(conf), std::move(apiconf)}
{
if (this->termination_event < 0)
if (this->m_termination_event < 0)
{
this->libremidi_handle_error(this->configuration, "error creating eventfd.");
return;
@@ -364,7 +359,7 @@ public:
~midi_in_alsa_threaded()
{
this->close_port();
midi_in_alsa_threaded::close_port();
this->client_open_ = std::errc::not_connected;
}
@@ -399,7 +394,7 @@ private:
{
try
{
this->thread = std::thread([this] { thread_handler(); });
this->m_thread = std::thread([this] { thread_handler(); });
return stdx::error{};
}
catch (const std::system_error& e)
@@ -415,12 +410,12 @@ private:
stdx::error stop_thread()
{
termination_event.notify();
m_termination_event.notify();
if (this->thread.joinable())
this->thread.join();
if (this->m_thread.joinable())
this->m_thread.join();
termination_event.consume();
m_termination_event.consume();
return stdx::error{};
}
@@ -428,7 +423,7 @@ private:
{
int poll_fd_count = alsa_data::snd.seq.poll_descriptors_count(this->seq, POLLIN) + 1;
auto poll_fds = (struct pollfd*)alloca(poll_fd_count * sizeof(struct pollfd));
poll_fds[0] = this->termination_event;
poll_fds[0] = this->m_termination_event;
alsa_data::snd.seq.poll_descriptors(this->seq, poll_fds + 1, poll_fd_count - 1, POLLIN);
const auto period
@@ -439,10 +434,10 @@ private:
if (alsa_data::snd.seq.event_input_pending(this->seq, 1) == 0)
{
// No data pending
if (poll(poll_fds, poll_fd_count, period) >= 0)
if (poll(poll_fds, poll_fd_count, static_cast<int32_t>(period)) >= 0)
{
// We got our stop-thread signal
if (termination_event.ready(poll_fds[0]))
if (m_termination_event.ready(poll_fds[0]))
{
break;
}
@@ -450,7 +445,7 @@ private:
continue;
}
int res{};
int64_t res{};
if constexpr (ConfigurationImpl::midi_version == 1)
{
res = this->process_events();
@@ -467,8 +462,8 @@ private:
}
}
std::thread thread{};
eventfd_notifier termination_event{};
std::thread m_thread{};
eventfd_notifier m_termination_event{};
};
template <typename ConfigurationBase, typename ConfigurationImpl>
@@ -487,17 +482,17 @@ public:
using poll_params = typename ConfigurationImpl::poll_parameters_type;
this->configuration.manual_poll(
poll_params{.addr = this->vaddr, .callback = [this](const auto& ev) {
if constexpr (ConfigurationImpl::midi_version == 1)
return this->process_event(ev);
if constexpr (ConfigurationImpl::midi_version == 1)
return this->process_event(ev);
#if __has_include(<alsa/ump.h>)
else
return this->process_ump_event(ev);
else
return this->process_ump_event(ev);
#endif
}});
}});
return 0;
}
~midi_in_alsa_manual() { this->close_port(); }
~midi_in_alsa_manual() { midi_in_alsa_manual::close_port(); }
stdx::error open_port(const input_port& pt, std::string_view local_port_name) override
{
@@ -530,7 +525,7 @@ public:
};
}
namespace libremidi
NAMESPACE_LIBREMIDI
{
template <>
inline std::unique_ptr<midi_in_api>
@@ -3,7 +3,7 @@
#include <libremidi/backends/alsa_seq/helpers.hpp>
#include <libremidi/detail/midi_out.hpp>
namespace libremidi::alsa_seq
NAMESPACE_LIBREMIDI::alsa_seq
{
class midi_out_impl final
@@ -30,7 +30,7 @@ public:
return;
}
if (snd.midi.event_new(this->bufferSize, &this->coder) < 0)
if (snd.midi.event_new(this->m_bufferSize, &this->coder) < 0)
{
libremidi_handle_error(this->configuration, "error initializing MIDI event parser.");
return;
@@ -68,8 +68,9 @@ public:
stdx::error open_port(const output_port& p, std::string_view portName) override
{
unsigned int nSrc = this->get_port_count(SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE);
if (nSrc < 1)
unsigned int n_src
= this->get_port_count(SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE);
if (n_src < 1)
{
libremidi_handle_error(this->configuration, "no MIDI output sources found!");
return make_error_code(std::errc::no_such_device);
@@ -109,11 +110,6 @@ public:
return stdx::error{};
}
stdx::error set_client_name(std::string_view clientName) override
{
return alsa_data::set_client_name(clientName);
}
stdx::error set_port_name(std::string_view portName) override
{
return alsa_data::set_port_name(portName);
@@ -122,9 +118,9 @@ public:
stdx::error send_message(const unsigned char* message, std::size_t size) override
{
int64_t result{};
if (size > this->bufferSize)
if (size > this->m_bufferSize)
{
this->bufferSize = size;
this->m_bufferSize = size;
result = snd.midi.event_resize_buffer(this->coder, size);
if (result != 0)
{
@@ -146,8 +142,8 @@ public:
// FIXME direct is set but snd_seq_event_output_direct is not used...
snd_seq_ev_set_direct(&ev);
const int64_t nBytes = size; // signed to avoir potential overflow with size - offset below
result = snd.midi.event_encode(this->coder, message + offset, (long)(nBytes - offset), &ev);
const int64_t n_bytes = size; // signed to avoir potential overflow with size - offset below
result = snd.midi.event_encode(this->coder, message + offset, (long)(n_bytes - offset), &ev);
if (result < 0)
{
libremidi_handle_warning(this->configuration, "event parsing error!");
@@ -174,6 +170,6 @@ public:
}
private:
uint64_t bufferSize{32};
uint64_t m_bufferSize{32};
};
}
+223 -74
View File
@@ -7,20 +7,32 @@
#include <alsa/asoundlib.h>
#include <bitset>
#if LIBREMIDI_HAS_UDEV
#include <libremidi/backends/linux/udev.hpp>
#endif
#include <map>
namespace libremidi::alsa_seq
NAMESPACE_LIBREMIDI::alsa_seq
{
struct client_info
{
std::string client_name;
int client_id{};
std::optional<int> card{};
};
struct port_info
{
std::string client_name;
std::string port_name;
int client{};
int port{};
bool isInput{};
bool isOutput{};
bool is_input{};
bool is_output{};
std::optional<int> card{};
libremidi::transport_type type{};
};
template <typename ConfigurationImpl>
@@ -88,12 +100,69 @@ public:
}
}
std::optional<port_info> get_info(int client, int port) const noexcept
std::optional<client_info>
get_client_info(int client, snd_seq_client_info_t& cinfo) const noexcept
{
client_info p;
p.client_id = client;
if (auto name = snd.seq.client_info_get_name(&cinfo))
p.client_name = name;
if (int card = snd.seq.client_info_get_card(&cinfo); card >= 0)
p.card = card;
return p;
}
std::optional<port_info> get_info(
int client, int port, snd_seq_client_info_t& cinfo,
snd_seq_port_info_t& pinfo) const noexcept
{
const auto tp = snd.seq.port_info_get_type(&pinfo);
const auto cap = snd.seq.port_info_get_capability(&pinfo);
if ((cap & SND_SEQ_PORT_CAP_NO_EXPORT) != 0)
return std::nullopt;
port_info p;
p.client = client;
p.port = port;
bool ok = this->configuration.track_any;
static constexpr auto virtual_port = SND_SEQ_PORT_TYPE_SOFTWARE | SND_SEQ_PORT_TYPE_SYNTHESIZER
| SND_SEQ_PORT_TYPE_APPLICATION;
if ((tp & SND_SEQ_PORT_TYPE_HARDWARE) && this->configuration.track_hardware)
{
p.type = libremidi::transport_type::hardware;
ok = true;
}
else if ((tp & virtual_port) && this->configuration.track_virtual)
{
p.type = libremidi::transport_type::software;
ok = true;
}
if (!ok)
return {};
if (auto name = snd.seq.client_info_get_name(&cinfo))
p.client_name = name;
if (auto name = snd.seq.port_info_get_name(&pinfo))
p.port_name = name;
if (int card = snd.seq.client_info_get_card(&cinfo); card >= 0)
p.card = card;
p.is_input = (cap & SND_SEQ_PORT_CAP_DUPLEX) | (cap & SND_SEQ_PORT_CAP_READ);
p.is_output = (cap & SND_SEQ_PORT_CAP_DUPLEX) | (cap & SND_SEQ_PORT_CAP_WRITE);
return p;
}
std::optional<port_info> get_info(int client, int port) const noexcept
{
snd_seq_client_info_t* cinfo;
snd_seq_client_info_alloca(&cinfo);
if (int err = snd.seq.get_any_client_info(seq, client, cinfo); err < 0)
@@ -104,55 +173,57 @@ public:
if (int err = snd.seq.get_any_port_info(seq, client, port, pinfo); err < 0)
return std::nullopt;
const auto tp = snd.seq.port_info_get_type(pinfo);
bool ok = this->configuration.track_any;
static constexpr auto virtual_port
= SND_SEQ_PORT_TYPE_SOFTWARE | SND_SEQ_PORT_TYPE_SYNTHESIZER;
if ((tp & SND_SEQ_PORT_TYPE_HARDWARE) && this->configuration.track_hardware)
ok = true;
else if ((tp & virtual_port) && this->configuration.track_virtual)
ok = true;
if (!ok)
return {};
if (auto name = snd.seq.client_info_get_name(cinfo))
p.client_name = name;
if (auto name = snd.seq.port_info_get_name(pinfo))
p.port_name = name;
auto cap = snd.seq.port_info_get_capability(pinfo);
p.isInput = (cap & SND_SEQ_PORT_CAP_DUPLEX) | (cap & SND_SEQ_PORT_CAP_READ);
p.isOutput = (cap & SND_SEQ_PORT_CAP_DUPLEX) | (cap & SND_SEQ_PORT_CAP_WRITE);
return p;
return get_info(client, port, *cinfo, *pinfo);
}
template <bool Input>
auto to_port_info(port_info p) const noexcept
auto to_port_info(const port_info& p) const noexcept
-> std::conditional_t<Input, input_port, output_port>
{
static_assert(sizeof(this->seq) <= sizeof(libremidi::client_handle));
static_assert(sizeof(std::uintptr_t) <= sizeof(libremidi::client_handle));
container_identifier container{};
device_identifier device{};
libremidi::transport_type type = p.type;
std::string manufacturer;
std::string product;
std::string serial;
#if LIBREMIDI_HAS_UDEV
if (p.card)
{
auto res = get_udev_soundcard_info(m_udev, *p.card);
container = res.container;
device = res.path;
type = res.type;
manufacturer = res.vendor;
product = res.product;
serial = res.serial;
}
#endif
return {
{.client = std::uintptr_t(this->seq),
{.api = get_current_api(),
.client = std::uintptr_t(this->seq),
.container = container,
.device = device,
.port = alsa_seq::seq_to_port_handle(p.client, p.port),
.manufacturer = "",
.manufacturer = manufacturer,
.product = product,
.serial = serial,
.device_name = p.client_name,
.port_name = p.port_name,
.display_name = p.port_name}};
.display_name = p.port_name,
.type = type}};
}
void init_all_ports()
{
alsa_seq::for_all_ports(
snd, this->seq, [this](snd_seq_client_info_t& client, snd_seq_port_info_t& port) {
int clt = snd.seq.client_info_get_client(&client);
int pt = snd.seq.port_info_get_port(&port);
register_port(clt, pt);
});
int clt = snd.seq.client_info_get_client(&client);
int pt = snd.seq.port_info_get_port(&port);
register_port(clt, pt);
});
}
libremidi::API get_current_api() const noexcept override
@@ -168,12 +239,12 @@ public:
std::vector<libremidi::input_port> ret;
alsa_seq::for_all_ports(
snd, this->seq, [this, &ret](snd_seq_client_info_t& client, snd_seq_port_info_t& port) {
int clt = snd.seq.client_info_get_client(&client);
int pt = snd.seq.port_info_get_port(&port);
if (auto p = get_info(clt, pt))
if (p->isInput)
ret.push_back(to_port_info<true>(*p));
});
int clt = snd.seq.client_info_get_client(&client);
int pt = snd.seq.port_info_get_port(&port);
if (auto p = get_info(clt, pt, client, port))
if (p->is_input)
ret.push_back(to_port_info<true>(*p));
});
return ret;
}
@@ -182,12 +253,12 @@ public:
std::vector<libremidi::output_port> ret;
alsa_seq::for_all_ports(
snd, this->seq, [this, &ret](snd_seq_client_info_t& client, snd_seq_port_info_t& port) {
int clt = snd.seq.client_info_get_client(&client);
int pt = snd.seq.port_info_get_port(&port);
if (auto p = get_info(clt, pt))
if (p->isOutput)
ret.push_back(to_port_info<false>(*p));
});
int clt = snd.seq.client_info_get_client(&client);
int pt = snd.seq.port_info_get_port(&port);
if (auto p = get_info(clt, pt, client, port))
if (p->is_output)
ret.push_back(to_port_info<false>(*p));
});
return ret;
}
@@ -200,13 +271,13 @@ public:
if (p.client == snd.seq.client_id(seq))
return;
knownClients_[{p.client, p.port}] = p;
if (p.isInput && configuration.input_added)
m_knownClients[{p.client, p.port}] = p;
if (p.is_input && configuration.input_added)
{
configuration.input_added(to_port_info<true>(p));
}
if (p.isOutput && configuration.output_added)
if (p.is_output && configuration.output_added)
{
configuration.output_added(to_port_info<false>(p));
}
@@ -214,37 +285,61 @@ public:
void unregister_port(int client, int port)
{
auto it = knownClients_.find({client, port});
if (it != knownClients_.end())
auto it = m_knownClients.find({client, port});
if (it != m_knownClients.end())
{
auto p = it->second;
knownClients_.erase(it);
m_knownClients.erase(it);
if (p.isInput && configuration.input_removed)
if (p.is_input && configuration.input_removed)
{
configuration.input_removed(to_port_info<true>(p));
}
if (p.isOutput && configuration.output_removed)
if (p.is_output && configuration.output_removed)
{
configuration.output_removed(to_port_info<false>(p));
}
}
}
void handle_event(const snd_seq_event_t& ev)
void handle_event_direct(const snd_seq_event_t& ev)
{
switch (ev.type)
{
case SND_SEQ_EVENT_CLIENT_START: {
// TODO
break;
}
case SND_SEQ_EVENT_CLIENT_EXIT: {
// TODO
break;
}
case SND_SEQ_EVENT_CLIENT_CHANGE: {
// TODO
break;
}
#if LIBREMIDI_ALSA_HAS_UMP_SEQ_EVENTS
case SND_SEQ_EVENT_UMP_EP_CHANGE: {
// TODO
break;
}
case SND_SEQ_EVENT_UMP_BLOCK_CHANGE: {
// TODO
break;
}
#endif
case SND_SEQ_EVENT_PORT_START: {
register_port(ev.data.addr.client, ev.data.addr.port);
this->register_port(ev.data.addr.client, ev.data.addr.port);
break;
}
case SND_SEQ_EVENT_PORT_EXIT: {
unregister_port(ev.data.addr.client, ev.data.addr.port);
this->unregister_port(ev.data.addr.client, ev.data.addr.port);
break;
}
case SND_SEQ_EVENT_PORT_CHANGE:
// TODO
break;
default:
break;
}
@@ -263,7 +358,11 @@ public:
}
private:
std::map<std::pair<int, int>, port_info> knownClients_;
std::map<std::pair<int, int>, port_info> m_knownClients;
#if LIBREMIDI_HAS_UDEV
udev_helper m_udev{};
#endif
};
template <typename ConfigurationImpl>
@@ -275,38 +374,87 @@ public:
{
// Create relevant descriptors
auto& snd = alsa_data::snd;
const auto N = snd.seq.poll_descriptors_count(this->seq, POLLIN);
descriptors_.resize(N + 1);
snd.seq.poll_descriptors(this->seq, descriptors_.data(), N, POLLIN);
descriptors_.back() = this->termination_event;
// 1. Descriptor count
const auto n = snd.seq.poll_descriptors_count(this->seq, POLLIN);
int total_descriptors = n;
total_descriptors++; // eventfd for terminating the thread
// 2. Create storage
descriptors.resize(total_descriptors);
// 3. Store descriptors
snd.seq.poll_descriptors(this->seq, descriptors.data(), n, POLLIN);
descriptors[n] = this->termination_event;
// Start the listening thread
thread = std::thread{[this] {
thread = std::thread{[this, n] {
auto& snd = alsa_data::snd;
const auto period
= std::chrono::duration_cast<std::chrono::milliseconds>(this->configuration.poll_period)
.count();
for (;;)
{
int err = poll(descriptors_.data(), descriptors_.size(), period);
int err = poll(descriptors.data(), descriptors.size(), static_cast<int32_t>(period));
if (err >= 0)
{
// We got our stop-thread signal
if (descriptors_.back().revents & POLLIN)
if (descriptors[n].revents & POLLIN)
break;
// Put ALSA event in our queue
snd_seq_event_t* ev{};
event_handle handle{snd};
while (snd.seq.event_input(this->seq, &ev) >= 0)
{
handle.reset(ev);
this->handle_event(*ev);
this->handle_event_delayed(*ev);
}
// Process the events in a deferred way.
// This is because udev takes some milliseconds to populate its field after a
// port was added
auto tm = std::chrono::steady_clock::now();
for (auto it = queued_events.begin(); it != queued_events.end();)
{
if ((tm - it->second) >= this->configuration.poll_period)
{
this->handle_event_direct(it->first);
it = queued_events.erase(it);
}
else
{
break;
}
}
}
}
}};
}
void handle_event_delayed(const snd_seq_event_t& ev)
{
switch (ev.type)
{
case SND_SEQ_EVENT_CLIENT_START:
case SND_SEQ_EVENT_CLIENT_EXIT:
case SND_SEQ_EVENT_CLIENT_CHANGE:
#if LIBREMIDI_ALSA_HAS_UMP_SEQ_EVENTS
case SND_SEQ_EVENT_UMP_EP_CHANGE:
case SND_SEQ_EVENT_UMP_BLOCK_CHANGE:
#endif
case SND_SEQ_EVENT_PORT_START:
case SND_SEQ_EVENT_PORT_EXIT:
case SND_SEQ_EVENT_PORT_CHANGE:
queued_events.emplace_back(ev, std::chrono::steady_clock::now());
break;
default:
break;
}
}
~observer_threaded()
{
termination_event.notify();
@@ -317,7 +465,8 @@ public:
eventfd_notifier termination_event{};
std::thread thread;
std::vector<pollfd> descriptors_;
std::vector<pollfd> descriptors;
std::vector<std::pair<snd_seq_event_t, std::chrono::steady_clock::time_point>> queued_events;
};
template <typename ConfigurationImpl>
@@ -329,16 +478,16 @@ public:
{
this->configuration.manual_poll(
poll_parameters{.addr = this->vaddr, .callback = [this](const auto& v) {
this->handle_event(v);
return 0;
}});
this->handle_event_direct(v);
return 0;
}});
}
~observer_manual() { this->configuration.stop_poll(this->vaddr); }
};
}
namespace libremidi
NAMESPACE_LIBREMIDI
{
template <>
inline std::unique_ptr<observer_api>
@@ -9,7 +9,7 @@
#include <variant>
namespace libremidi::alsa_seq
NAMESPACE_LIBREMIDI::alsa_seq
{
struct shared_handler : public libremidi::shared_context
@@ -61,7 +61,7 @@ struct shared_handler : public libremidi::shared_context
{
auto clt = std::make_shared<shared_handler>(client_name);
auto cb = [client = std::weak_ptr{clt}](const libremidi::alsa_seq::poll_parameters& params) {
auto cb = [client = std::weak_ptr{clt}](libremidi::alsa_seq::poll_parameters params) {
if (auto clt = client.lock())
{
clt->events.push(
@@ -74,8 +74,7 @@ struct shared_handler : public libremidi::shared_context
auto stop_cb = [client = std::weak_ptr{clt}](snd_seq_addr_t id) {
if (auto clt = client.lock())
{
clt->events.push(
{.type = shared_handler::event_type::callback_removed, .payload = std::move(id)});
clt->events.push({.type = shared_handler::event_type::callback_removed, .payload = id});
clt->queue_event.notify();
}
return true;
@@ -128,13 +127,13 @@ struct shared_handler : public libremidi::shared_context
{
case callback_added: {
auto [addr, cb]
= std::move(*std::get_if<libremidi::alsa_seq::poll_parameters>(&ev.payload));
= std::move(*get_if<libremidi::alsa_seq::poll_parameters>(&ev.payload));
addresses.push_back(addr);
callbacks.push_back(std::move(cb));
break;
}
case callback_removed:
auto addr = std::move(*std::get_if<snd_seq_addr_t>(&ev.payload));
auto addr = *get_if<snd_seq_addr_t>(&ev.payload);
if (auto index = index_of_address(addr); index >= 0)
{
addresses.erase(addresses.begin() + index);
@@ -146,15 +145,14 @@ struct shared_handler : public libremidi::shared_context
}
// Look for who's ready
for (int64_t i = 0, N = std::ssize(fds) - 2; i < N; i++)
for (int64_t i = 0, n = std::ssize(fds) - 2; i < n; i++)
{
if (fds[i].revents & POLLIN)
{
// Read alsa event
snd_seq_event_t* ev{};
event_handle handle{snd};
int result = 0;
while ((result = snd.seq.event_input(client, &ev)) > 0)
while (snd.seq.event_input(client, &ev) > 0)
{
handle.reset(ev);
@@ -181,7 +179,7 @@ struct shared_handler : public libremidi::shared_context
struct event
{
event_type type;
std::variant<libremidi::alsa_seq::poll_parameters, snd_seq_addr_t> payload;
libremidi_variant_alias::variant<libremidi::alsa_seq::poll_parameters, snd_seq_addr_t> payload;
};
snd_seq_t* client{};