working on win32 uwp! and libremidi update

This commit is contained in:
Sebastian @ HfG
2024-10-28 19:24:18 +01:00
parent 06cb6d8319
commit 1e3755148c
106 changed files with 8474 additions and 2198 deletions
+77 -103
View File
@@ -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();
}
};
}