libremidi update to v5.4.3 and added virtual midi out as default
This commit is contained in:
@@ -11,7 +11,7 @@ typedef uint32_t jack_nframes_t;
|
||||
typedef int (*JackProcessCallback)(jack_nframes_t nframes, void* arg);
|
||||
}
|
||||
|
||||
namespace libremidi
|
||||
NAMESPACE_LIBREMIDI
|
||||
{
|
||||
using jack_callback_function = std::function<void(int nframes)>;
|
||||
struct jack_callback
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <jack/ringbuffer.h>
|
||||
#endif
|
||||
|
||||
namespace libremidi
|
||||
NAMESPACE_LIBREMIDI
|
||||
{
|
||||
struct jack_error_domain : public stdx::error_domain
|
||||
{
|
||||
@@ -34,36 +34,36 @@ public:
|
||||
stdx::string_ref message(const stdx::error& e) const noexcept override
|
||||
{
|
||||
const auto status = error_cast<jack_status_t>(e);
|
||||
if(status == jack_status_t{})
|
||||
if (status == jack_status_t{})
|
||||
return "Success";
|
||||
|
||||
if(status & JackInvalidOption)
|
||||
if (status & JackInvalidOption)
|
||||
return "The operation contained an invalid or unsupported option";
|
||||
if(status & JackServerFailed)
|
||||
if (status & JackServerFailed)
|
||||
return "Unable to connect to the JACK server";
|
||||
if(status & JackServerError)
|
||||
if (status & JackServerError)
|
||||
return "Communication error with the JACK server";
|
||||
if(status & JackNoSuchClient)
|
||||
if (status & JackNoSuchClient)
|
||||
return "Requested client does not exist";
|
||||
if(status & JackLoadFailure)
|
||||
if (status & JackLoadFailure)
|
||||
return "Unable to load internal client";
|
||||
if(status & JackInitFailure)
|
||||
if (status & JackInitFailure)
|
||||
return "Unable to initialize client";
|
||||
if(status & JackShmFailure)
|
||||
if (status & JackShmFailure)
|
||||
return "Unable to access shared memory";
|
||||
if(status & JackVersionError)
|
||||
if (status & JackVersionError)
|
||||
return "Client's protocol version does not match";
|
||||
if(status & JackBackendError)
|
||||
if (status & JackBackendError)
|
||||
return "Backend error";
|
||||
if(status & JackClientZombie)
|
||||
if (status & JackClientZombie)
|
||||
return "Client zombified failure";
|
||||
if(status & JackFailure)
|
||||
if (status & JackFailure)
|
||||
return "Failure";
|
||||
if(status & JackNameNotUnique)
|
||||
if (status & JackNameNotUnique)
|
||||
return "The desired client name was not unique";
|
||||
|
||||
// Can't happen in libremidi as we set JackNoStartServer
|
||||
if(status & JackServerStarted)
|
||||
if (status & JackServerStarted)
|
||||
return "Server was started";
|
||||
|
||||
return "Unknown JACK status code";
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
#include <libremidi/detail/semaphore.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <semaphore>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
namespace libremidi
|
||||
NAMESPACE_LIBREMIDI
|
||||
{
|
||||
struct jack_client
|
||||
{
|
||||
@@ -39,31 +41,32 @@ struct jack_client
|
||||
}
|
||||
}
|
||||
|
||||
template <bool Input>
|
||||
template <bool Input, libremidi::API Api>
|
||||
static auto to_port_info(jack_client_t* client, jack_port_t* port)
|
||||
-> std::conditional_t<Input, input_port, output_port>
|
||||
{
|
||||
return {{
|
||||
.api = Api,
|
||||
.client = reinterpret_cast<std::uintptr_t>(client),
|
||||
.port = 0,
|
||||
.manufacturer = "",
|
||||
.device_name = "",
|
||||
.device_name = jack_get_client_name(client),
|
||||
.port_name = jack_port_name(port),
|
||||
.display_name = get_port_display_name(port),
|
||||
}};
|
||||
}
|
||||
|
||||
template <bool Input>
|
||||
static auto
|
||||
get_ports(jack_client_t* client, const char* pattern, const JackPortFlags flags) noexcept
|
||||
-> std::vector<std::conditional_t<Input, input_port, output_port>>
|
||||
template <bool Input, libremidi::API Api>
|
||||
static auto get_ports(
|
||||
jack_client_t* client, const char* pattern, const char* type, const JackPortFlags flags,
|
||||
bool midi2) noexcept -> std::vector<std::conditional_t<Input, input_port, output_port>>
|
||||
{
|
||||
std::vector<std::conditional_t<Input, input_port, output_port>> ret;
|
||||
|
||||
if (!client)
|
||||
return {};
|
||||
|
||||
const char** ports = jack_get_ports(client, pattern, JACK_DEFAULT_MIDI_TYPE, flags);
|
||||
const char** ports = jack_get_ports(client, pattern, type, flags);
|
||||
|
||||
if (ports == nullptr)
|
||||
return {};
|
||||
@@ -73,7 +76,11 @@ struct jack_client
|
||||
{
|
||||
// FIXME this does not take into account filtering sw / hw ports
|
||||
auto port = jack_port_by_name(client, ports[i]);
|
||||
ret.push_back(to_port_info<Input>(client, port));
|
||||
if (port)
|
||||
{
|
||||
if (bool(midi2) == bool(jack_port_flags(port) & 0x20))
|
||||
ret.push_back(to_port_info<Input, Api>(client, port));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
@@ -131,13 +138,13 @@ struct jack_helpers : jack_client
|
||||
configuration.set_process_func(
|
||||
{.token = this_instance,
|
||||
.callback = [&self, p = std::weak_ptr{this->port.impl}](jack_nframes_t nf) -> int {
|
||||
if (auto pt = p.lock())
|
||||
if (auto ppt = pt->load())
|
||||
self.process(nf);
|
||||
if (auto pt = p.lock())
|
||||
if (pt->load())
|
||||
self.process(nf);
|
||||
|
||||
self.thread_lock.check_client_released();
|
||||
return 0;
|
||||
}});
|
||||
self.thread_lock.check_client_released();
|
||||
return 0;
|
||||
}});
|
||||
|
||||
this->client = configuration.context;
|
||||
return jack_status_t{};
|
||||
@@ -149,26 +156,25 @@ struct jack_helpers : jack_client
|
||||
= jack_client_open(configuration.client_name.c_str(), JackNoStartServer, &status);
|
||||
if (this->client != nullptr)
|
||||
{
|
||||
if(status & JackNameNotUnique) {
|
||||
self.libremidi_handle_warning(self.configuration, "JACK client with the same name already exists, renamed.");
|
||||
if (status & JackNameNotUnique)
|
||||
{
|
||||
self.libremidi_handle_warning(
|
||||
self.configuration, "JACK client with the same name already exists, renamed.");
|
||||
}
|
||||
|
||||
jack_set_process_callback(
|
||||
this->client,
|
||||
+[](jack_nframes_t nf, void* ctx) -> int {
|
||||
auto& self = *static_cast<Self*>(ctx);
|
||||
jack_port_t* port = self.port;
|
||||
jack_set_process_callback(this->client, +[](jack_nframes_t nf, void* ctx) -> int {
|
||||
auto& self = *static_cast<Self*>(ctx);
|
||||
jack_port_t* port = self.port;
|
||||
|
||||
// Is port created?
|
||||
if (port == nullptr)
|
||||
return 0;
|
||||
// Is port created?
|
||||
if (port == nullptr)
|
||||
return 0;
|
||||
|
||||
self.process(nf);
|
||||
self.process(nf);
|
||||
|
||||
self.thread_lock.check_client_released();
|
||||
return 0;
|
||||
},
|
||||
&self);
|
||||
self.thread_lock.check_client_released();
|
||||
return 0;
|
||||
}, &self);
|
||||
jack_activate(this->client);
|
||||
}
|
||||
return status;
|
||||
@@ -192,8 +198,8 @@ struct jack_helpers : jack_client
|
||||
self.client_open_ = std::errc::not_connected;
|
||||
}
|
||||
|
||||
stdx::error
|
||||
create_local_port(const auto& self, std::string_view portName, JackPortFlags flags)
|
||||
stdx::error create_local_port(
|
||||
const auto& self, std::string_view portName, const char* type, JackPortFlags flags)
|
||||
{
|
||||
// full name: "client_name:port_name\0"
|
||||
if (portName.empty())
|
||||
@@ -202,15 +208,13 @@ struct jack_helpers : jack_client
|
||||
if (self.configuration.client_name.size() + portName.size() + 2u
|
||||
>= static_cast<size_t>(jack_port_name_size()))
|
||||
{
|
||||
self.libremidi_handle_error(
|
||||
self.configuration, "port name length limit exceeded");
|
||||
self.libremidi_handle_error(self.configuration, "port name length limit exceeded");
|
||||
return std::errc::invalid_argument;
|
||||
}
|
||||
|
||||
if (!this->port)
|
||||
{
|
||||
this->port
|
||||
= jack_port_register(this->client, portName.data(), JACK_DEFAULT_MIDI_TYPE, flags, 0);
|
||||
this->port = jack_port_register(this->client, portName.data(), type, flags, 0);
|
||||
}
|
||||
|
||||
if (!this->port)
|
||||
@@ -238,4 +242,77 @@ struct jack_helpers : jack_client
|
||||
return from_errc(err);
|
||||
}
|
||||
};
|
||||
|
||||
struct jack_queue
|
||||
{
|
||||
public:
|
||||
static constexpr auto size_sz = sizeof(int32_t);
|
||||
|
||||
jack_queue() = default;
|
||||
jack_queue(const jack_queue&) = delete;
|
||||
jack_queue(jack_queue&&) = delete;
|
||||
jack_queue& operator=(const jack_queue&) = delete;
|
||||
|
||||
jack_queue& operator=(jack_queue&& other) noexcept
|
||||
{
|
||||
ringbuffer = other.ringbuffer;
|
||||
ringbuffer_space = other.ringbuffer_space;
|
||||
other.ringbuffer = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit jack_queue(int64_t sz) noexcept
|
||||
{
|
||||
ringbuffer = jack_ringbuffer_create(sz);
|
||||
ringbuffer_space = jack_ringbuffer_write_space(ringbuffer);
|
||||
}
|
||||
|
||||
~jack_queue() noexcept
|
||||
{
|
||||
if (ringbuffer)
|
||||
jack_ringbuffer_free(ringbuffer);
|
||||
}
|
||||
|
||||
stdx::error write(const unsigned char* data, int64_t sz) const noexcept
|
||||
{
|
||||
if (static_cast<std::size_t>(sz + size_sz) > ringbuffer_space)
|
||||
return std::errc::no_buffer_space;
|
||||
|
||||
while (jack_ringbuffer_write_space(ringbuffer) < sz + size_sz)
|
||||
sched_yield();
|
||||
|
||||
jack_ringbuffer_write(ringbuffer, reinterpret_cast<char*>(&sz), size_sz);
|
||||
jack_ringbuffer_write(ringbuffer, reinterpret_cast<const char*>(data), sz);
|
||||
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void read(void* jack_events) const noexcept
|
||||
{
|
||||
int32_t sz;
|
||||
while (jack_ringbuffer_peek(ringbuffer, reinterpret_cast<char*>(&sz), size_sz) == size_sz
|
||||
&& jack_ringbuffer_read_space(ringbuffer) >= size_sz + sz)
|
||||
{
|
||||
jack_ringbuffer_read_advance(ringbuffer, size_sz);
|
||||
|
||||
if (auto midi = jack_midi_event_reserve(jack_events, 0, sz))
|
||||
jack_ringbuffer_read(ringbuffer, reinterpret_cast<char*>(midi), sz);
|
||||
else
|
||||
jack_ringbuffer_read_advance(ringbuffer, sz);
|
||||
}
|
||||
}
|
||||
|
||||
jack_ringbuffer_t* ringbuffer{};
|
||||
std::size_t ringbuffer_space{}; // actual writable size, usually 1 less than ringbuffer
|
||||
};
|
||||
|
||||
struct jack_midi1
|
||||
{
|
||||
static constexpr const char* port_type = "8 bit raw midi";
|
||||
};
|
||||
|
||||
struct jack_midi2
|
||||
{
|
||||
static constexpr const char* port_type = "32 bit raw UMP";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
#include <libremidi/detail/midi_in.hpp>
|
||||
#include <libremidi/detail/midi_stream_decoder.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace libremidi
|
||||
NAMESPACE_LIBREMIDI
|
||||
{
|
||||
class midi_in_jack final
|
||||
: public midi1::in_api
|
||||
, public jack_helpers
|
||||
, public jack_midi1
|
||||
, public error_handler
|
||||
{
|
||||
public:
|
||||
@@ -46,15 +45,16 @@ public:
|
||||
|
||||
stdx::error open_port(const input_port& port, std::string_view portName) override
|
||||
{
|
||||
if (auto err = create_local_port(*this, portName, JackPortIsInput); err != stdx::error{})
|
||||
if (auto err = create_local_port(*this, portName, port_type, JackPortIsInput);
|
||||
err != stdx::error{})
|
||||
return err;
|
||||
|
||||
if (int err = jack_connect(this->client, port.port_name.c_str(), jack_port_name(this->port));
|
||||
err != 0 && err != EEXIST)
|
||||
{
|
||||
libremidi_handle_error(
|
||||
configuration, "could not connect to port: " + port.port_name + " -> "
|
||||
+ jack_port_name(this->port));
|
||||
configuration,
|
||||
"could not connect to port: " + port.port_name + " -> " + jack_port_name(this->port));
|
||||
return from_errc(err);
|
||||
}
|
||||
return stdx::error{};
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
|
||||
stdx::error open_virtual_port(std::string_view portName) override
|
||||
{
|
||||
return create_local_port(*this, portName, JackPortIsInput);
|
||||
return create_local_port(*this, portName, port_type, JackPortIsInput);
|
||||
}
|
||||
|
||||
stdx::error close_port() override { return do_close_port(); }
|
||||
@@ -96,8 +96,8 @@ public:
|
||||
this->client, ¤t_frames, ¤t_usecs, &next_usecs, &period_usecs);
|
||||
|
||||
// We have midi events in buffer
|
||||
uint32_t evCount = jack_midi_get_event_count(buff);
|
||||
for (uint32_t j = 0; j < evCount; j++)
|
||||
uint32_t ev_count = jack_midi_get_event_count(buff);
|
||||
for (uint32_t j = 0; j < ev_count; j++)
|
||||
{
|
||||
jack_midi_event_t event{};
|
||||
jack_midi_event_get(&event, buff, j);
|
||||
|
||||
@@ -3,76 +3,12 @@
|
||||
#include <libremidi/backends/jack/helpers.hpp>
|
||||
#include <libremidi/detail/midi_out.hpp>
|
||||
|
||||
#include <semaphore>
|
||||
|
||||
namespace libremidi
|
||||
NAMESPACE_LIBREMIDI
|
||||
{
|
||||
struct jack_queue
|
||||
{
|
||||
public:
|
||||
static constexpr auto size_sz = sizeof(int32_t);
|
||||
|
||||
jack_queue() = default;
|
||||
jack_queue(const jack_queue&) = delete;
|
||||
jack_queue(jack_queue&&) = delete;
|
||||
jack_queue& operator=(const jack_queue&) = delete;
|
||||
|
||||
jack_queue& operator=(jack_queue&& other) noexcept
|
||||
{
|
||||
ringbuffer = other.ringbuffer;
|
||||
ringbuffer_space = other.ringbuffer_space;
|
||||
other.ringbuffer = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit jack_queue(int64_t sz) noexcept
|
||||
{
|
||||
ringbuffer = jack_ringbuffer_create(sz);
|
||||
ringbuffer_space = jack_ringbuffer_write_space(ringbuffer);
|
||||
}
|
||||
|
||||
~jack_queue() noexcept
|
||||
{
|
||||
if (ringbuffer)
|
||||
jack_ringbuffer_free(ringbuffer);
|
||||
}
|
||||
|
||||
stdx::error write(const unsigned char* data, int64_t sz) const noexcept
|
||||
{
|
||||
if (static_cast<std::size_t>(sz + size_sz) > ringbuffer_space)
|
||||
return std::errc::no_buffer_space;
|
||||
|
||||
while (jack_ringbuffer_write_space(ringbuffer) < sz + size_sz)
|
||||
sched_yield();
|
||||
|
||||
jack_ringbuffer_write(ringbuffer, reinterpret_cast<char*>(&sz), size_sz);
|
||||
jack_ringbuffer_write(ringbuffer, reinterpret_cast<const char*>(data), sz);
|
||||
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void read(void* jack_events) const noexcept
|
||||
{
|
||||
int32_t sz;
|
||||
while (jack_ringbuffer_peek(ringbuffer, reinterpret_cast<char*>(&sz), size_sz) == size_sz
|
||||
&& jack_ringbuffer_read_space(ringbuffer) >= size_sz + sz)
|
||||
{
|
||||
jack_ringbuffer_read_advance(ringbuffer, size_sz);
|
||||
|
||||
if (auto midi = jack_midi_event_reserve(jack_events, 0, sz))
|
||||
jack_ringbuffer_read(ringbuffer, reinterpret_cast<char*>(midi), sz);
|
||||
else
|
||||
jack_ringbuffer_read_advance(ringbuffer, sz);
|
||||
}
|
||||
}
|
||||
|
||||
jack_ringbuffer_t* ringbuffer{};
|
||||
std::size_t ringbuffer_space{}; // actual writable size, usually 1 less than ringbuffer
|
||||
};
|
||||
|
||||
class midi_out_jack
|
||||
: public midi1::out_api
|
||||
, public jack_helpers
|
||||
, public jack_midi1
|
||||
, public error_handler
|
||||
{
|
||||
public:
|
||||
@@ -94,15 +30,15 @@ public:
|
||||
|
||||
stdx::error open_port(const output_port& port, std::string_view portName) override
|
||||
{
|
||||
if (auto err = create_local_port(*this, portName, JackPortIsOutput); err != stdx::error{})
|
||||
if (auto err = create_local_port(*this, portName, port_type, JackPortIsOutput);
|
||||
err != stdx::error{})
|
||||
return err;
|
||||
|
||||
// Connecting to the output
|
||||
if (int err = jack_connect(this->client, jack_port_name(this->port), port.port_name.c_str());
|
||||
err != 0 && err != EEXIST)
|
||||
{
|
||||
libremidi_handle_error(
|
||||
configuration, "could not connect to port" + port.port_name);
|
||||
libremidi_handle_error(configuration, "could not connect to port" + port.port_name);
|
||||
return from_errc(err);
|
||||
}
|
||||
|
||||
@@ -111,7 +47,7 @@ public:
|
||||
|
||||
stdx::error open_virtual_port(std::string_view portName) override
|
||||
{
|
||||
return create_local_port(*this, portName, JackPortIsOutput);
|
||||
return create_local_port(*this, portName, port_type, JackPortIsOutput);
|
||||
}
|
||||
|
||||
stdx::error close_port() override { return do_close_port(); }
|
||||
@@ -128,7 +64,7 @@ class midi_out_jack_queued final : public midi_out_jack
|
||||
public:
|
||||
midi_out_jack_queued(output_configuration&& conf, jack_output_configuration&& apiconf)
|
||||
: midi_out_jack{std::move(conf), std::move(apiconf)}
|
||||
, queue{configuration.ringbuffer_size}
|
||||
, m_queue{configuration.ringbuffer_size}
|
||||
{
|
||||
auto status = connect(*this);
|
||||
if (!this->client)
|
||||
@@ -150,7 +86,7 @@ public:
|
||||
|
||||
stdx::error send_message(const unsigned char* message, std::size_t size) override
|
||||
{
|
||||
return queue.write(message, size);
|
||||
return m_queue.write(message, size);
|
||||
}
|
||||
|
||||
int process(jack_nframes_t nframes)
|
||||
@@ -158,13 +94,13 @@ public:
|
||||
void* buff = jack_port_get_buffer(this->port, nframes);
|
||||
jack_midi_clear_buffer(buff);
|
||||
|
||||
this->queue.read(buff);
|
||||
this->m_queue.read(buff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
jack_queue queue;
|
||||
jack_queue m_queue;
|
||||
};
|
||||
|
||||
class midi_out_jack_direct final : public midi_out_jack
|
||||
@@ -230,7 +166,7 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
namespace libremidi
|
||||
NAMESPACE_LIBREMIDI
|
||||
{
|
||||
template <>
|
||||
inline std::unique_ptr<midi_out_api> make<midi_out_jack>(
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
namespace libremidi
|
||||
NAMESPACE_LIBREMIDI
|
||||
{
|
||||
class observer_jack final
|
||||
: public observer_api
|
||||
, private jack_client
|
||||
, public jack_midi1
|
||||
, private error_handler
|
||||
{
|
||||
public:
|
||||
@@ -48,8 +49,7 @@ public:
|
||||
void initial_callback()
|
||||
{
|
||||
{
|
||||
const char** ports
|
||||
= jack_get_ports(client, nullptr, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput);
|
||||
const char** ports = jack_get_ports(client, nullptr, port_type, JackPortIsOutput);
|
||||
|
||||
if (ports != nullptr)
|
||||
{
|
||||
@@ -70,7 +70,8 @@ public:
|
||||
{
|
||||
seen_input_ports.insert(ports[i]);
|
||||
if (this->configuration.input_added && configuration.notify_in_constructor)
|
||||
this->configuration.input_added(to_port_info<true>(client, port));
|
||||
this->configuration.input_added(
|
||||
to_port_info<true, libremidi::API::JACK_MIDI>(client, port));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -80,8 +81,7 @@ public:
|
||||
}
|
||||
|
||||
{
|
||||
const char** ports
|
||||
= jack_get_ports(client, nullptr, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput);
|
||||
const char** ports = jack_get_ports(client, nullptr, port_type, JackPortIsInput);
|
||||
|
||||
if (ports != nullptr)
|
||||
{
|
||||
@@ -102,7 +102,8 @@ public:
|
||||
{
|
||||
seen_output_ports.insert(ports[i]);
|
||||
if (this->configuration.output_added && configuration.notify_in_constructor)
|
||||
this->configuration.output_added(to_port_info<false>(client, port));
|
||||
this->configuration.output_added(
|
||||
to_port_info<false, libremidi::API::JACK_MIDI>(client, port));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -119,7 +120,7 @@ public:
|
||||
if (reg)
|
||||
{
|
||||
std::string_view type = jack_port_type(port);
|
||||
if (type != JACK_DEFAULT_MIDI_TYPE)
|
||||
if (type != port_type)
|
||||
return;
|
||||
|
||||
bool physical = flags & JackPortIsPhysical;
|
||||
@@ -139,13 +140,15 @@ public:
|
||||
{
|
||||
seen_input_ports.insert(name);
|
||||
if (this->configuration.input_added)
|
||||
this->configuration.input_added(to_port_info<true>(client, port));
|
||||
this->configuration.input_added(
|
||||
to_port_info<true, libremidi::API::JACK_MIDI>(client, port));
|
||||
}
|
||||
else if (flags & JackPortIsInput)
|
||||
{
|
||||
seen_output_ports.insert(name);
|
||||
if (this->configuration.output_added)
|
||||
this->configuration.output_added(to_port_info<false>(client, port));
|
||||
this->configuration.output_added(
|
||||
to_port_info<false, libremidi::API::JACK_MIDI>(client, port));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -153,13 +156,15 @@ public:
|
||||
if (auto it = seen_input_ports.find(name); it != seen_input_ports.end())
|
||||
{
|
||||
if (this->configuration.input_removed)
|
||||
this->configuration.input_removed(to_port_info<true>(client, port));
|
||||
this->configuration.input_removed(
|
||||
to_port_info<true, libremidi::API::JACK_MIDI>(client, port));
|
||||
seen_input_ports.erase(it);
|
||||
}
|
||||
if (auto it = seen_output_ports.find(name); it != seen_output_ports.end())
|
||||
{
|
||||
if (this->configuration.output_removed)
|
||||
this->configuration.output_removed(to_port_info<false>(client, port));
|
||||
this->configuration.output_removed(
|
||||
to_port_info<false, libremidi::API::JACK_MIDI>(client, port));
|
||||
seen_output_ports.erase(it);
|
||||
}
|
||||
}
|
||||
@@ -172,39 +177,37 @@ public:
|
||||
if (!configuration.has_callbacks())
|
||||
return;
|
||||
|
||||
jack_set_port_registration_callback(
|
||||
this->client,
|
||||
+[](jack_port_id_t p, int r, void* arg) {
|
||||
auto& self = *(observer_jack*)arg;
|
||||
if (auto port = jack_port_by_id(self.client, p))
|
||||
{
|
||||
self.on_port_callback(port, r != 0);
|
||||
}
|
||||
},
|
||||
this);
|
||||
jack_set_port_registration_callback(this->client, +[](jack_port_id_t p, int r, void* arg) {
|
||||
auto& self = *(observer_jack*)arg;
|
||||
if (auto port = jack_port_by_id(self.client, p))
|
||||
{
|
||||
self.on_port_callback(port, r != 0);
|
||||
}
|
||||
}, this);
|
||||
|
||||
jack_set_port_rename_callback(
|
||||
this->client,
|
||||
+[](jack_port_id_t p, const char* /*old_name*/, const char* /*new_name*/, void* arg) {
|
||||
const auto& self = *static_cast<observer_jack*>(arg);
|
||||
const auto& self = *static_cast<observer_jack*>(arg);
|
||||
|
||||
auto port = jack_port_by_id(self.client, p);
|
||||
if (!port)
|
||||
return;
|
||||
},
|
||||
this);
|
||||
auto port = jack_port_by_id(self.client, p);
|
||||
if (!port)
|
||||
return;
|
||||
}, this);
|
||||
}
|
||||
|
||||
libremidi::API get_current_api() const noexcept override { return libremidi::API::JACK_MIDI; }
|
||||
|
||||
std::vector<libremidi::input_port> get_input_ports() const noexcept override
|
||||
{
|
||||
return get_ports<true>(this->client, nullptr, JackPortIsOutput);
|
||||
return get_ports<true, libremidi::API::JACK_MIDI>(
|
||||
this->client, nullptr, port_type, JackPortIsOutput, false);
|
||||
}
|
||||
|
||||
std::vector<libremidi::output_port> get_output_ports() const noexcept override
|
||||
{
|
||||
return get_ports<false>(this->client, nullptr, JackPortIsInput);
|
||||
return get_ports<false, libremidi::API::JACK_MIDI>(
|
||||
this->client, nullptr, port_type, JackPortIsInput, false);
|
||||
}
|
||||
|
||||
~observer_jack()
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace libremidi::jack
|
||||
NAMESPACE_LIBREMIDI::jack
|
||||
{
|
||||
|
||||
// Create a JACK client which will be shared across objects
|
||||
@@ -23,13 +23,10 @@ struct shared_handler : public libremidi::shared_context
|
||||
client = jack_client_open(v.data(), JackNoStartServer, &status);
|
||||
assert(client);
|
||||
assert(status == 0);
|
||||
jack_set_process_callback(
|
||||
client,
|
||||
+[](jack_nframes_t cnt, void* ctx) -> int {
|
||||
((shared_handler*)ctx)->jack_callback(cnt);
|
||||
return 0;
|
||||
},
|
||||
this);
|
||||
jack_set_process_callback(client, +[](jack_nframes_t cnt, void* ctx) -> int {
|
||||
((shared_handler*)ctx)->jack_callback(cnt);
|
||||
return 0;
|
||||
}, this);
|
||||
}
|
||||
|
||||
virtual void start_processing() override { jack_activate(client); }
|
||||
@@ -73,11 +70,10 @@ struct shared_handler : public libremidi::shared_context
|
||||
switch (ev.type)
|
||||
{
|
||||
case in_callback_added:
|
||||
midiin_callbacks.push_back(
|
||||
std::move(*std::get_if<libremidi::jack_callback>(&ev.payload)));
|
||||
midiin_callbacks.push_back(std::move(*get_if<libremidi::jack_callback>(&ev.payload)));
|
||||
break;
|
||||
case in_callback_removed: {
|
||||
auto idx = *std::get_if<int64_t>(&ev.payload);
|
||||
auto idx = *get_if<int64_t>(&ev.payload);
|
||||
for (auto it = midiin_callbacks.begin(); it != midiin_callbacks.end();)
|
||||
{
|
||||
if (it->token == idx)
|
||||
@@ -93,11 +89,10 @@ struct shared_handler : public libremidi::shared_context
|
||||
break;
|
||||
}
|
||||
case out_callback_added:
|
||||
midiout_callbacks.push_back(
|
||||
std::move(*std::get_if<libremidi::jack_callback>(&ev.payload)));
|
||||
midiout_callbacks.push_back(std::move(*get_if<libremidi::jack_callback>(&ev.payload)));
|
||||
break;
|
||||
case out_callback_removed:
|
||||
auto idx = *std::get_if<int64_t>(&ev.payload);
|
||||
auto idx = *get_if<int64_t>(&ev.payload);
|
||||
for (auto it = midiout_callbacks.begin(); it != midiout_callbacks.end();)
|
||||
{
|
||||
if (it->token == idx)
|
||||
@@ -141,7 +136,7 @@ struct shared_handler : public libremidi::shared_context
|
||||
struct event
|
||||
{
|
||||
event_type type;
|
||||
std::variant<libremidi::jack_callback, int64_t> payload;
|
||||
libremidi_variant_alias::variant<libremidi::jack_callback, int64_t> payload;
|
||||
};
|
||||
|
||||
boost::lockfree::spsc_queue<event> events{16};
|
||||
|
||||
Reference in New Issue
Block a user