working on win32 uwp! and libremidi update
This commit is contained in:
@@ -38,6 +38,7 @@ struct input_configuration
|
||||
snd_seq_t* context{};
|
||||
std::function<bool(const poll_parameters&)> manual_poll;
|
||||
std::function<bool(snd_seq_addr_t)> stop_poll;
|
||||
std::chrono::milliseconds poll_period{2};
|
||||
|
||||
static constexpr int midi_version = 1;
|
||||
};
|
||||
@@ -56,6 +57,7 @@ struct observer_configuration
|
||||
snd_seq_t* context{};
|
||||
std::function<bool(const poll_parameters&)> manual_poll;
|
||||
std::function<bool(snd_seq_addr_t)> stop_poll;
|
||||
std::chrono::milliseconds poll_period{100};
|
||||
|
||||
static constexpr int midi_version = 1;
|
||||
};
|
||||
|
||||
@@ -177,18 +177,20 @@ struct alsa_data
|
||||
}
|
||||
}
|
||||
|
||||
void set_client_name(std::string_view clientName)
|
||||
stdx::error set_client_name(std::string_view clientName)
|
||||
{
|
||||
snd.seq.set_client_name(seq, clientName.data());
|
||||
int ret = snd.seq.set_client_name(seq, clientName.data());
|
||||
return from_errc(ret);
|
||||
}
|
||||
|
||||
void set_port_name(std::string_view portName)
|
||||
stdx::error set_port_name(std::string_view portName)
|
||||
{
|
||||
snd_seq_port_info_t* pinfo;
|
||||
snd_seq_port_info_alloca(&pinfo);
|
||||
snd.seq.get_port_info(seq, vport, pinfo);
|
||||
snd.seq.port_info_set_name(pinfo, portName.data());
|
||||
snd.seq.set_port_info(seq, vport, pinfo);
|
||||
int ret = snd.seq.set_port_info(seq, vport, pinfo);
|
||||
return from_errc(ret);
|
||||
}
|
||||
|
||||
unsigned int get_port_count(int caps) const
|
||||
@@ -209,9 +211,9 @@ struct alsa_data
|
||||
// snd.seq.port_info_set_port(src_pinfo, port);
|
||||
|
||||
// {
|
||||
// self.template error<invalid_parameter_error>(
|
||||
// self.libremidi_handle_error(
|
||||
// self.configuration,
|
||||
// "alsa::get_port_info: invalid 'portNumber' argument: " + std::to_string(portNumber));
|
||||
// "invalid 'portNumber' argument: " + std::to_string(portNumber));
|
||||
// return {};
|
||||
// }
|
||||
snd_seq_addr_t addr;
|
||||
@@ -270,8 +272,8 @@ struct alsa_data
|
||||
// Make subscription
|
||||
if (int err = snd.seq.port_subscribe_malloc(&this->subscription); err < 0)
|
||||
{
|
||||
self.template error<driver_error>(
|
||||
self.configuration, "create_connection: ALSA error allocation port subscription.");
|
||||
self.libremidi_handle_error(
|
||||
self.configuration, "ALSA error allocation port subscription.");
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ using midi_in_base
|
||||
= std::conditional_t<ConfigurationImpl::midi_version == 1, midi1::in_api, midi2::in_api>;
|
||||
template <typename ConfigurationImpl>
|
||||
using midi_in_processing = std::conditional_t<
|
||||
ConfigurationImpl::midi_version == 1, midi1::input_state_machine, dummy_processing>;
|
||||
ConfigurationImpl::midi_version == 1, midi1::input_state_machine, midi2::input_state_machine>;
|
||||
|
||||
template <typename ConfigurationBase, typename ConfigurationImpl>
|
||||
class midi_in_impl
|
||||
@@ -55,9 +55,9 @@ public:
|
||||
{
|
||||
if (init_client(configuration) < 0)
|
||||
{
|
||||
error<driver_error>(
|
||||
libremidi_handle_error(
|
||||
this->configuration,
|
||||
"midi_in_alsa::initialize: error creating ALSA sequencer client "
|
||||
"error creating ALSA sequencer client "
|
||||
"object.");
|
||||
return;
|
||||
}
|
||||
@@ -80,8 +80,7 @@ public:
|
||||
int result = snd.midi.event_new(0, &coder);
|
||||
if (result < 0)
|
||||
{
|
||||
error<driver_error>(
|
||||
this->configuration, "midi_in_alsa::initialize: error during snd_midi_event_new.");
|
||||
libremidi_handle_error(this->configuration, "error during snd_midi_event_new.");
|
||||
return;
|
||||
}
|
||||
snd.midi.event_init(coder);
|
||||
@@ -105,7 +104,13 @@ public:
|
||||
snd.seq.close(this->seq);
|
||||
}
|
||||
|
||||
libremidi::API get_current_api() const noexcept override { return libremidi::API::ALSA_SEQ; }
|
||||
libremidi::API get_current_api() const noexcept override
|
||||
{
|
||||
if constexpr (ConfigurationImpl::midi_version == 1)
|
||||
return libremidi::API::ALSA_SEQ;
|
||||
else
|
||||
return libremidi::API::ALSA_SEQ_UMP;
|
||||
}
|
||||
|
||||
[[nodiscard]] int create_port(std::string_view portName)
|
||||
{
|
||||
@@ -157,14 +162,13 @@ public:
|
||||
|
||||
if (int ret = create_port(portName); ret < 0)
|
||||
{
|
||||
error<driver_error>(configuration, "midi_in_alsa::create_port: ALSA error creating port.");
|
||||
libremidi_handle_error(configuration, "ALSA error creating port.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (int ret = connect_port(*source); ret < 0)
|
||||
{
|
||||
error<driver_error>(
|
||||
configuration, "midi_in_alsa::create_port: ALSA error making port connection.");
|
||||
libremidi_handle_error(configuration, "ALSA error making port connection.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -184,63 +188,21 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_port() override
|
||||
stdx::error close_port() override
|
||||
{
|
||||
unsubscribe();
|
||||
stop_queue();
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void set_client_name(std::string_view clientName) override
|
||||
stdx::error set_client_name(std::string_view clientName) override
|
||||
{
|
||||
alsa_data::set_client_name(clientName);
|
||||
return alsa_data::set_client_name(clientName);
|
||||
}
|
||||
|
||||
void set_port_name(std::string_view portName) override { alsa_data::set_port_name(portName); }
|
||||
|
||||
protected:
|
||||
void set_timestamp(const auto& ev, auto& msg) noexcept
|
||||
stdx::error set_port_name(std::string_view portName) override
|
||||
{
|
||||
static constexpr int64_t nanos = 1e9;
|
||||
switch (configuration.timestamps)
|
||||
{
|
||||
case timestamp_mode::NoTimestamp:
|
||||
msg.timestamp = 0;
|
||||
return;
|
||||
case timestamp_mode::Relative: {
|
||||
const auto t1 = static_cast<int64_t>(ev.time.time.tv_sec) * nanos
|
||||
+ static_cast<int64_t>(ev.time.time.tv_nsec);
|
||||
const auto t0 = static_cast<int64_t>(last_time.tv_sec) * nanos
|
||||
+ static_cast<int64_t>(last_time.tv_nsec);
|
||||
const auto time = t1 - t0;
|
||||
|
||||
last_time = ev.time.time;
|
||||
|
||||
if (this->firstMessage == true)
|
||||
{
|
||||
this->firstMessage = false;
|
||||
msg.timestamp = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.timestamp = time;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case timestamp_mode::Absolute: {
|
||||
msg.timestamp = ev.time.time.tv_sec * nanos + ev.time.time.tv_nsec;
|
||||
break;
|
||||
}
|
||||
case timestamp_mode::Custom: {
|
||||
msg.timestamp
|
||||
= configuration.get_timestamp(ev.time.time.tv_sec * nanos + ev.time.time.tv_nsec);
|
||||
break;
|
||||
}
|
||||
case timestamp_mode::SystemMonotonic: {
|
||||
namespace clk = std::chrono;
|
||||
msg.timestamp = system_ns();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return alsa_data::set_port_name(portName);
|
||||
}
|
||||
|
||||
timestamp absolute_timestamp() const noexcept override
|
||||
@@ -303,11 +265,13 @@ protected:
|
||||
snd_seq_event_t* ev{};
|
||||
event_handle handle{snd};
|
||||
int result = 0;
|
||||
while ((result = snd.seq.event_input(seq, &ev)) > 0)
|
||||
if ((result = snd.seq.event_input(seq, &ev)) > 0)
|
||||
{
|
||||
handle.reset(ev);
|
||||
if (int err = process_event(*ev); err < 0)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -346,11 +310,17 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
// MIDI 2 : no decoder, we can just send the UMP data directly, yay
|
||||
libremidi::ump ump;
|
||||
std::memcpy(ump.data, ev.ump, sizeof(ev.ump));
|
||||
set_timestamp(ev, ump);
|
||||
configuration.on_message(std::move(ump));
|
||||
static constexpr timestamp_backend_info timestamp_info{
|
||||
.has_absolute_timestamps = true,
|
||||
.absolute_is_monotonic = false,
|
||||
.has_samples = false,
|
||||
};
|
||||
const auto to_ns = [ts = ev.time.time] {
|
||||
return static_cast<int64_t>(ts.tv_sec) * 1'000'000'000 + static_cast<int64_t>(ts.tv_nsec);
|
||||
};
|
||||
|
||||
m_processing.on_bytes_multi(
|
||||
{ev.ump, ev.ump + 4}, m_processing.template timestamp<timestamp_info>(to_ns, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -370,7 +340,6 @@ protected:
|
||||
#endif
|
||||
|
||||
int queue_id{}; // an input queue is needed to get timestamped events
|
||||
snd_seq_real_time_t last_time{};
|
||||
|
||||
// Only needed for midi 1
|
||||
std::vector<unsigned char> decoding_buffer = std::vector<unsigned char>(4096);
|
||||
@@ -386,62 +355,65 @@ public:
|
||||
{
|
||||
if (this->termination_event < 0)
|
||||
{
|
||||
this->template error<driver_error>(
|
||||
this->configuration, "midi_in_alsa::initialize: error creating eventfd.");
|
||||
this->libremidi_handle_error(this->configuration, "error creating eventfd.");
|
||||
return;
|
||||
}
|
||||
|
||||
this->client_open_ = stdx::error{};
|
||||
}
|
||||
|
||||
~midi_in_alsa_threaded() { this->close_port(); }
|
||||
~midi_in_alsa_threaded()
|
||||
{
|
||||
this->close_port();
|
||||
this->client_open_ = std::errc::not_connected;
|
||||
}
|
||||
|
||||
private:
|
||||
bool open_port(const input_port& pt, std::string_view local_port_name) override
|
||||
stdx::error open_port(const input_port& pt, std::string_view local_port_name) override
|
||||
{
|
||||
if (int err = this->init_port(this->to_address(pt), local_port_name); err < 0)
|
||||
return false;
|
||||
return from_errc(err);
|
||||
|
||||
if (!start_thread())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return this->start_thread();
|
||||
}
|
||||
|
||||
bool open_virtual_port(std::string_view portName) override
|
||||
stdx::error open_virtual_port(std::string_view portName) override
|
||||
{
|
||||
if (int err = this->init_virtual_port(portName); err < 0)
|
||||
return false;
|
||||
return from_errc(err);
|
||||
|
||||
if (!this->start_thread())
|
||||
return false;
|
||||
return true;
|
||||
return this->start_thread();
|
||||
}
|
||||
|
||||
void close_port() override
|
||||
stdx::error close_port() override
|
||||
{
|
||||
midi_in_impl<ConfigurationBase, ConfigurationImpl>::close_port();
|
||||
// FIXME shouldn't we always close the thread
|
||||
auto err = midi_in_impl<ConfigurationBase, ConfigurationImpl>::close_port();
|
||||
|
||||
stop_thread();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
[[nodiscard]] int start_thread()
|
||||
[[nodiscard]] stdx::error start_thread()
|
||||
{
|
||||
try
|
||||
{
|
||||
this->thread = std::thread([this] { thread_handler(); });
|
||||
return stdx::error{};
|
||||
}
|
||||
catch (const std::system_error& e)
|
||||
{
|
||||
using namespace std::literals;
|
||||
this->unsubscribe();
|
||||
|
||||
this->template error<thread_error>(
|
||||
this->configuration,
|
||||
"midi_in_alsa::start_thread: error starting MIDI input thread: "s + e.what());
|
||||
return false;
|
||||
this->libremidi_handle_error(
|
||||
this->configuration, "error starting MIDI input thread: "s + e.what());
|
||||
return e.code();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void stop_thread()
|
||||
stdx::error stop_thread()
|
||||
{
|
||||
termination_event.notify();
|
||||
|
||||
@@ -449,6 +421,7 @@ private:
|
||||
this->thread.join();
|
||||
|
||||
termination_event.consume();
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void thread_handler()
|
||||
@@ -458,12 +431,15 @@ private:
|
||||
poll_fds[0] = this->termination_event;
|
||||
alsa_data::snd.seq.poll_descriptors(this->seq, poll_fds + 1, poll_fd_count - 1, POLLIN);
|
||||
|
||||
const auto period
|
||||
= std::chrono::duration_cast<std::chrono::milliseconds>(this->configuration.poll_period)
|
||||
.count();
|
||||
for (;;)
|
||||
{
|
||||
if (alsa_data::snd.seq.event_input_pending(this->seq, 1) == 0)
|
||||
{
|
||||
// No data pending
|
||||
if (poll(poll_fds, poll_fd_count, -1) >= 0)
|
||||
if (poll(poll_fds, poll_fd_count, period) >= 0)
|
||||
{
|
||||
// We got our stop-thread signal
|
||||
if (termination_event.ready(poll_fds[0]))
|
||||
@@ -486,12 +462,8 @@ private:
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)res;
|
||||
#if defined(__LIBREMIDI_DEBUG__)
|
||||
if (res < 0)
|
||||
std::cerr << "midi_in_alsa::thread_handler: MIDI input error: " << snd.strerror(res)
|
||||
<< "\n";
|
||||
#endif
|
||||
LIBREMIDI_LOG("MIDI input error: ", this->snd.strerror(res));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -527,31 +499,33 @@ public:
|
||||
|
||||
~midi_in_alsa_manual() { this->close_port(); }
|
||||
|
||||
bool open_port(const input_port& pt, std::string_view local_port_name) override
|
||||
stdx::error open_port(const input_port& pt, std::string_view local_port_name) override
|
||||
{
|
||||
if (int err = this->init_port(this->to_address(pt), local_port_name); err < 0)
|
||||
return false;
|
||||
return from_errc(err);
|
||||
|
||||
if (int err = init_callback(); err < 0)
|
||||
return false;
|
||||
return true;
|
||||
return from_errc(err);
|
||||
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
bool open_virtual_port(std::string_view name) override
|
||||
stdx::error open_virtual_port(std::string_view name) override
|
||||
{
|
||||
if (int err = this->init_virtual_port(name); err < 0)
|
||||
return false;
|
||||
return from_errc(err);
|
||||
|
||||
if (int err = init_callback(); err < 0)
|
||||
return false;
|
||||
return true;
|
||||
return from_errc(err);
|
||||
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void close_port() override
|
||||
stdx::error close_port() override
|
||||
{
|
||||
this->configuration.stop_poll(this->vaddr);
|
||||
|
||||
midi_in_impl<ConfigurationBase, ConfigurationImpl>::close_port();
|
||||
return midi_in_impl<ConfigurationBase, ConfigurationImpl>::close_port();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,22 +23,21 @@ public:
|
||||
{
|
||||
if (init_client(configuration) < 0)
|
||||
{
|
||||
error<driver_error>(
|
||||
libremidi_handle_error(
|
||||
this->configuration,
|
||||
"midi_in_alsa::initialize: error creating ALSA sequencer client "
|
||||
"error creating ALSA sequencer client "
|
||||
"object.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (snd.midi.event_new(this->bufferSize, &this->coder) < 0)
|
||||
{
|
||||
error<driver_error>(
|
||||
this->configuration,
|
||||
"midi_out_alsa::initialize: error initializing MIDI event "
|
||||
"parser.");
|
||||
libremidi_handle_error(this->configuration, "error initializing MIDI event parser.");
|
||||
return;
|
||||
}
|
||||
snd.midi.event_init(this->coder);
|
||||
|
||||
this->client_open_ = stdx::error{};
|
||||
}
|
||||
|
||||
~midi_out_impl() override
|
||||
@@ -54,6 +53,8 @@ public:
|
||||
|
||||
if (!configuration.context)
|
||||
snd.seq.close(this->seq);
|
||||
|
||||
client_open_ = std::errc::not_connected;
|
||||
}
|
||||
|
||||
libremidi::API get_current_api() const noexcept override { return libremidi::API::ALSA_SEQ; }
|
||||
@@ -65,55 +66,60 @@ public:
|
||||
SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION, std::nullopt);
|
||||
}
|
||||
|
||||
bool open_port(const output_port& p, std::string_view portName) override
|
||||
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)
|
||||
{
|
||||
error<no_devices_found_error>(
|
||||
this->configuration, "midi_out_alsa::open_port: no MIDI output sources found!");
|
||||
return false;
|
||||
libremidi_handle_error(this->configuration, "no MIDI output sources found!");
|
||||
return make_error_code(std::errc::no_such_device);
|
||||
}
|
||||
|
||||
auto sink = get_port_info(p);
|
||||
if (!sink)
|
||||
return false;
|
||||
return std::errc::invalid_argument;
|
||||
|
||||
if (int err = create_port(portName); err < 0)
|
||||
{
|
||||
error<driver_error>(configuration, "midi_out_alsa::create_port: ALSA error creating port.");
|
||||
return false;
|
||||
libremidi_handle_error(configuration, "ALSA error creating port.");
|
||||
return from_errc(err);
|
||||
}
|
||||
|
||||
snd_seq_addr_t source{
|
||||
.client = (unsigned char)snd.seq.client_id(this->seq), .port = (unsigned char)this->vport};
|
||||
if (int err = create_connection(*this, source, *sink, true); err < 0)
|
||||
{
|
||||
error<driver_error>(
|
||||
configuration, "midi_out_alsa::create_port: ALSA error making port connection.");
|
||||
return false;
|
||||
libremidi_handle_error(configuration, "ALSA error making port connection.");
|
||||
return from_errc(err);
|
||||
}
|
||||
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
bool open_virtual_port(std::string_view portName) override
|
||||
stdx::error open_virtual_port(std::string_view portName) override
|
||||
{
|
||||
if (int err = create_port(portName); err < 0)
|
||||
return false;
|
||||
return true;
|
||||
return from_errc(err);
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void close_port() override { unsubscribe(); }
|
||||
|
||||
void set_client_name(std::string_view clientName) override
|
||||
stdx::error close_port() override
|
||||
{
|
||||
alsa_data::set_client_name(clientName);
|
||||
unsubscribe();
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void set_port_name(std::string_view portName) override { alsa_data::set_port_name(portName); }
|
||||
stdx::error set_client_name(std::string_view clientName) override
|
||||
{
|
||||
return alsa_data::set_client_name(clientName);
|
||||
}
|
||||
|
||||
void send_message(const unsigned char* message, std::size_t size) override
|
||||
stdx::error set_port_name(std::string_view portName) override
|
||||
{
|
||||
return alsa_data::set_port_name(portName);
|
||||
}
|
||||
|
||||
stdx::error send_message(const unsigned char* message, std::size_t size) override
|
||||
{
|
||||
int64_t result{};
|
||||
if (size > this->bufferSize)
|
||||
@@ -122,11 +128,11 @@ public:
|
||||
result = snd.midi.event_resize_buffer(this->coder, size);
|
||||
if (result != 0)
|
||||
{
|
||||
error<driver_error>(
|
||||
libremidi_handle_error(
|
||||
this->configuration,
|
||||
"midi_out_alsa::send_message: ALSA error resizing MIDI event "
|
||||
"ALSA error resizing MIDI event "
|
||||
"buffer.");
|
||||
return;
|
||||
return std::errc::no_buffer_space;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,14 +150,14 @@ public:
|
||||
result = snd.midi.event_encode(this->coder, message + offset, (long)(nBytes - offset), &ev);
|
||||
if (result < 0)
|
||||
{
|
||||
warning(this->configuration, "midi_out_alsa::send_message: event parsing error!");
|
||||
return;
|
||||
libremidi_handle_warning(this->configuration, "event parsing error!");
|
||||
return std::errc::bad_message;
|
||||
}
|
||||
|
||||
if (ev.type == SND_SEQ_EVENT_NONE)
|
||||
{
|
||||
warning(this->configuration, "midi_out_alsa::send_message: incomplete message!");
|
||||
return;
|
||||
libremidi_handle_warning(this->configuration, "incomplete message!");
|
||||
return std::errc::message_size;
|
||||
}
|
||||
|
||||
offset += result;
|
||||
@@ -159,13 +165,12 @@ public:
|
||||
result = snd.seq.event_output(this->seq, &ev);
|
||||
if (result < 0)
|
||||
{
|
||||
warning(
|
||||
this->configuration,
|
||||
"midi_out_alsa::send_message: error sending MIDI message to port.");
|
||||
return;
|
||||
libremidi_handle_warning(this->configuration, "error sending MIDI message to port.");
|
||||
return std::errc::io_error;
|
||||
}
|
||||
}
|
||||
snd.seq.drain_output(this->seq);
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <libremidi/backends/alsa_seq/config.hpp>
|
||||
#include <libremidi/backends/alsa_seq/helpers.hpp>
|
||||
#include <libremidi/backends/linux/helpers.hpp>
|
||||
#include <libremidi/detail/midi_api.hpp>
|
||||
#include <libremidi/detail/observer.hpp>
|
||||
|
||||
#include <alsa/asoundlib.h>
|
||||
@@ -26,6 +27,7 @@ template <typename ConfigurationImpl>
|
||||
class observer_impl
|
||||
: public observer_api
|
||||
, public alsa_data
|
||||
, public error_handler
|
||||
{
|
||||
public:
|
||||
struct
|
||||
@@ -40,7 +42,11 @@ public:
|
||||
using namespace std::literals;
|
||||
if (int err = init_client(configuration); err < 0)
|
||||
{
|
||||
throw driver_error("observer_alsa: snd_seq_open failed");
|
||||
libremidi_handle_error(
|
||||
this->configuration,
|
||||
"error creating ALSA sequencer client "
|
||||
"object.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!configuration.has_callbacks())
|
||||
@@ -65,7 +71,8 @@ public:
|
||||
*this, "libremidi-observe", caps, SND_SEQ_PORT_TYPE_APPLICATION, false);
|
||||
if (err < 0)
|
||||
{
|
||||
throw driver_error("observer: ALSA error creating port.");
|
||||
libremidi_handle_error(this->configuration, "error creating ALSA sequencer port.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +82,8 @@ public:
|
||||
= snd.seq.connect_from(seq, vport, SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE);
|
||||
if (err < 0)
|
||||
{
|
||||
throw driver_error("observer_alsa: snd_seq_connect_from failed");
|
||||
libremidi_handle_error(this->configuration, "error connecting to ALSA sequencer.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,9 +106,13 @@ public:
|
||||
|
||||
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 & SND_SEQ_PORT_TYPE_SOFTWARE) && this->configuration.track_virtual)
|
||||
else if ((tp & virtual_port) && this->configuration.track_virtual)
|
||||
ok = true;
|
||||
if (!ok)
|
||||
return {};
|
||||
@@ -271,9 +283,12 @@ public:
|
||||
// Start the listening thread
|
||||
thread = std::thread{[this] {
|
||||
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(), -1);
|
||||
int err = poll(descriptors_.data(), descriptors_.size(), period);
|
||||
if (err >= 0)
|
||||
{
|
||||
// We got our stop-thread signal
|
||||
|
||||
Reference in New Issue
Block a user