working on win32 uwp! and libremidi update
This commit is contained in:
@@ -27,8 +27,8 @@ struct pipewire_input_configuration
|
||||
|
||||
pw_main_loop* context{};
|
||||
pw_filter* filter{};
|
||||
std::function<void(pipewire_callback)> set_process_func;
|
||||
std::function<void(int64_t)> clear_process_func;
|
||||
std::function<void(pipewire_callback)> set_process_func{};
|
||||
std::function<void(int64_t)> clear_process_func{};
|
||||
};
|
||||
|
||||
struct pipewire_output_configuration
|
||||
@@ -37,8 +37,8 @@ struct pipewire_output_configuration
|
||||
|
||||
pw_main_loop* context{};
|
||||
pw_filter* filter{};
|
||||
std::function<void(pipewire_callback)> set_process_func;
|
||||
std::function<void(int64_t)> clear_process_func;
|
||||
std::function<void(pipewire_callback)> set_process_func{};
|
||||
std::function<void(int64_t)> clear_process_func{};
|
||||
|
||||
int64_t output_buffer_size{65536};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <libremidi/backends/linux/pipewire.hpp>
|
||||
#include <libremidi/detail/memory.hpp>
|
||||
#include <libremidi/error.hpp>
|
||||
|
||||
#include <pipewire/filter.h>
|
||||
#include <pipewire/pipewire.h>
|
||||
@@ -128,7 +129,7 @@ struct pipewire_context
|
||||
this->main_loop = pw.main_loop_new(nullptr);
|
||||
if (!this->main_loop)
|
||||
{
|
||||
// libremidi::logger().error("PipeWire: main_loop_new failed!");
|
||||
// libremidi::logger().libremidi_handle_error("main_loop_new failed!");
|
||||
return;
|
||||
}
|
||||
initialize();
|
||||
@@ -139,28 +140,28 @@ struct pipewire_context
|
||||
this->lp = pw.main_loop_get_loop(this->main_loop);
|
||||
if (!lp)
|
||||
{
|
||||
// libremidi::logger().error("PipeWire: main_loop_get_loop failed!");
|
||||
// libremidi::logger().libremidi_handle_error("main_loop_get_loop failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
this->context = pw.context_new(lp, nullptr, 0);
|
||||
if (!this->context)
|
||||
{
|
||||
// libremidi::logger().error("PipeWire: context_new failed!");
|
||||
// libremidi::logger().libremidi_handle_error("context_new failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
this->core = pw.context_connect(this->context, nullptr, 0);
|
||||
if (!this->core)
|
||||
{
|
||||
// libremidi::logger().error("PipeWire: context_connect failed!");
|
||||
// libremidi::logger().libremidi_handle_error("context_connect failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
this->registry = pw_core_get_registry(this->core, PW_VERSION_REGISTRY, 0);
|
||||
if (!this->registry)
|
||||
{
|
||||
// libremidi::logger().error("PipeWire: core_get_registry failed!");
|
||||
// libremidi::logger().libremidi_handle_error("core_get_registry failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -297,7 +298,6 @@ struct pipewire_context
|
||||
|
||||
if (!proxy)
|
||||
{
|
||||
std::cerr << "PipeWire: could not allocate link\n";
|
||||
pw.properties_free(props);
|
||||
return nullptr;
|
||||
}
|
||||
@@ -476,7 +476,7 @@ struct pipewire_filter
|
||||
PW_KEY_MEDIA_TYPE, "Midi",
|
||||
PW_KEY_MEDIA_CATEGORY, "Filter",
|
||||
PW_KEY_MEDIA_ROLE, "DSP",
|
||||
PW_KEY_MEDIA_NAME, "libremidi",
|
||||
PW_KEY_MEDIA_NAME, "",
|
||||
#if defined(PW_KEY_NODE_LOCK_RATE)
|
||||
PW_KEY_NODE_LOCK_RATE, "true",
|
||||
#endif
|
||||
@@ -498,7 +498,7 @@ struct pipewire_filter
|
||||
pw.filter_destroy(this->filter);
|
||||
}
|
||||
|
||||
void create_local_port(std::string_view port_name, spa_direction direction)
|
||||
stdx::error create_local_port(std::string_view port_name, spa_direction direction)
|
||||
{
|
||||
// clang-format off
|
||||
this->port = (struct port*)pw.filter_add_port(
|
||||
@@ -512,7 +512,9 @@ struct pipewire_filter
|
||||
nullptr),
|
||||
nullptr, 0);
|
||||
// clang-format on
|
||||
assert(port);
|
||||
if (!port)
|
||||
return std::errc::invalid_argument;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void set_port_buffer(int bytes)
|
||||
@@ -537,31 +539,41 @@ struct pipewire_filter
|
||||
pw.filter_update_params(this->filter, this->port, params, 1);
|
||||
}
|
||||
|
||||
void remove_port()
|
||||
stdx::error remove_port()
|
||||
{
|
||||
assert(this->port);
|
||||
pw.filter_remove_port(this->port);
|
||||
int ret = pw.filter_remove_port(this->port);
|
||||
this->port = nullptr;
|
||||
return from_errc(ret);
|
||||
}
|
||||
|
||||
void rename_port(std::string_view port_name)
|
||||
stdx::error rename_port(std::string_view port_name)
|
||||
{
|
||||
assert(this->port);
|
||||
spa_dict_item items[1] = {
|
||||
SPA_DICT_ITEM_INIT(PW_KEY_PORT_NAME, port_name.data()),
|
||||
};
|
||||
|
||||
auto properties = SPA_DICT_INIT(items, 1);
|
||||
pw.filter_update_properties(this->filter, this->port, &properties);
|
||||
this->port = nullptr;
|
||||
}
|
||||
|
||||
void start_filter()
|
||||
{
|
||||
if (pw.filter_connect(this->filter, PW_FILTER_FLAG_RT_PROCESS, NULL, 0) < 0)
|
||||
if (this->port)
|
||||
{
|
||||
std::cerr << "can't connect\n";
|
||||
return;
|
||||
spa_dict_item items[1] = {
|
||||
SPA_DICT_ITEM_INIT(PW_KEY_PORT_NAME, port_name.data()),
|
||||
};
|
||||
|
||||
auto properties = SPA_DICT_INIT(items, 1);
|
||||
int ret = pw.filter_update_properties(this->filter, this->port, &properties);
|
||||
return from_errc(ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::errc::not_connected;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] stdx::error start_filter()
|
||||
{
|
||||
if (int ret = pw.filter_connect(this->filter, PW_FILTER_FLAG_RT_PROCESS, NULL, 0); ret < 0)
|
||||
{
|
||||
return from_errc(ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
return stdx::error{};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <libremidi/backends/linux/helpers.hpp>
|
||||
#include <libremidi/backends/linux/pipewire.hpp>
|
||||
#include <libremidi/backends/pipewire/config.hpp>
|
||||
#include <libremidi/backends/pipewire/context.hpp>
|
||||
#include <libremidi/detail/memory.hpp>
|
||||
#include <libremidi/detail/midi_in.hpp>
|
||||
@@ -55,10 +56,10 @@ struct pipewire_helpers
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
void create_filter(Self& self)
|
||||
stdx::error create_filter(Self& self)
|
||||
{
|
||||
if (this->filter)
|
||||
return;
|
||||
return stdx::error{};
|
||||
|
||||
auto& configuration = self.configuration;
|
||||
if (configuration.context && configuration.filter && configuration.set_process_func)
|
||||
@@ -90,8 +91,9 @@ struct pipewire_helpers
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
this->filter->create_filter(self.configuration.client_name, filter_events, &self);
|
||||
this->filter->start_filter();
|
||||
return this->filter->start_filter();
|
||||
}
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
@@ -117,10 +119,10 @@ struct pipewire_helpers
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
int create_context(Self& self)
|
||||
stdx::error create_context(Self& self)
|
||||
{
|
||||
if (this->global_context)
|
||||
return 0;
|
||||
return stdx::error{};
|
||||
|
||||
// Initialize PipeWire client
|
||||
auto& configuration = self.configuration;
|
||||
@@ -133,7 +135,10 @@ struct pipewire_helpers
|
||||
this->global_instance = std::make_shared<pipewire_instance>();
|
||||
this->global_context = std::make_shared<pipewire_context>(this->global_instance);
|
||||
}
|
||||
return 0;
|
||||
if (!this->global_context->main_loop)
|
||||
return std::errc::connection_refused;
|
||||
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void destroy_context()
|
||||
@@ -170,7 +175,9 @@ struct pipewire_helpers
|
||||
{
|
||||
int result = pw_loop_iterate(lp, 0);
|
||||
if (result < 0)
|
||||
std::cerr << "pw_loop_iterate: " << spa_strerror(result) << "\n";
|
||||
{
|
||||
LIBREMIDI_LOG(spa_strerror(result));
|
||||
}
|
||||
}
|
||||
fds[0].revents = 0;
|
||||
}
|
||||
@@ -190,7 +197,7 @@ struct pipewire_helpers
|
||||
}
|
||||
|
||||
template <typename Self>
|
||||
bool create_local_port(Self& self, std::string_view portName, spa_direction direction)
|
||||
stdx::error create_local_port(Self& self, std::string_view portName, spa_direction direction)
|
||||
{
|
||||
assert(this->global_context);
|
||||
assert(this->filter);
|
||||
@@ -200,15 +207,15 @@ struct pipewire_helpers
|
||||
|
||||
if (!this->filter->port)
|
||||
{
|
||||
this->filter->create_local_port(portName.data(), direction);
|
||||
auto ret = this->filter->create_local_port(portName.data(), direction);
|
||||
if (ret != stdx::error{})
|
||||
{
|
||||
self.libremidi_handle_error(self.configuration, "error creating port");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->filter->port)
|
||||
{
|
||||
self.template error<driver_error>(self.configuration, "PipeWire: error creating port");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void add_callbacks(const observer_configuration& conf)
|
||||
@@ -293,12 +300,12 @@ struct pipewire_helpers
|
||||
}
|
||||
}
|
||||
|
||||
void do_close_port()
|
||||
stdx::error do_close_port()
|
||||
{
|
||||
if (!this->filter)
|
||||
return;
|
||||
return stdx::error{};
|
||||
if (!this->filter->port)
|
||||
return;
|
||||
return stdx::error{};
|
||||
|
||||
if (!this->global_context->owns_main_loop)
|
||||
{
|
||||
@@ -307,13 +314,19 @@ struct pipewire_helpers
|
||||
}
|
||||
|
||||
unlink_ports();
|
||||
this->filter->remove_port();
|
||||
return this->filter->remove_port();
|
||||
}
|
||||
|
||||
void rename_port(std::string_view port_name)
|
||||
stdx::error rename_port(std::string_view port_name)
|
||||
{
|
||||
if (this->filter)
|
||||
this->filter->rename_port(port_name);
|
||||
{
|
||||
return this->filter->rename_port(port_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::errc::not_connected;
|
||||
}
|
||||
}
|
||||
|
||||
void unlink_ports()
|
||||
@@ -325,7 +338,7 @@ struct pipewire_helpers
|
||||
}
|
||||
}
|
||||
|
||||
bool link_ports(auto& self, const input_port& in_port)
|
||||
stdx::error link_ports(auto& self, const input_port& in_port)
|
||||
{
|
||||
// Wait for the pipewire server to send us back our node's info
|
||||
for (int i = 0; i < 1000; i++)
|
||||
@@ -335,19 +348,13 @@ struct pipewire_helpers
|
||||
auto& midi = this->global_context->current_graph.software_midi;
|
||||
auto node_it = midi.find(this_node);
|
||||
if (node_it == midi.end())
|
||||
{
|
||||
std::cerr << "Node " << this_node << " not found! \n";
|
||||
return false;
|
||||
}
|
||||
return std::errc::invalid_argument;
|
||||
|
||||
// Wait for the pipewire server to send us back our node's ports
|
||||
this->filter->synchronize_ports(node_it->second);
|
||||
|
||||
if (node_it->second.inputs.empty())
|
||||
{
|
||||
std::cerr << "Node " << this_node << " has no ports! \n";
|
||||
return false;
|
||||
}
|
||||
return std::errc::no_link;
|
||||
|
||||
// Link ports
|
||||
const auto& p = node_it->second.inputs.front();
|
||||
@@ -355,16 +362,16 @@ struct pipewire_helpers
|
||||
pw_loop_iterate(this->global_context->lp, 1);
|
||||
if (!link)
|
||||
{
|
||||
self.template error<invalid_parameter_error>(
|
||||
self.libremidi_handle_error(
|
||||
self.configuration,
|
||||
"PipeWire: could not connect to port: " + in_port.port_name + " -> " + p.port_name);
|
||||
return false;
|
||||
"could not connect to port: " + in_port.port_name + " -> " + p.port_name);
|
||||
return std::errc::no_link;
|
||||
}
|
||||
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
bool link_ports(auto& self, const output_port& out_port)
|
||||
stdx::error link_ports(auto& self, const output_port& out_port)
|
||||
{
|
||||
// Wait for the pipewire server to send us back our node's info
|
||||
for (int i = 0; i < 1000; i++)
|
||||
@@ -375,8 +382,7 @@ struct pipewire_helpers
|
||||
auto node_it = midi.find(this_node);
|
||||
if (node_it == midi.end())
|
||||
{
|
||||
std::cerr << "Node " << this_node << " not found! \n";
|
||||
return false;
|
||||
return std::errc::invalid_argument;
|
||||
}
|
||||
|
||||
// Wait for the pipewire server to send us back our node's ports
|
||||
@@ -384,8 +390,7 @@ struct pipewire_helpers
|
||||
|
||||
if (node_it->second.outputs.empty())
|
||||
{
|
||||
std::cerr << "Node " << this_node << " has no ports! \n";
|
||||
return false;
|
||||
return std::errc::no_link;
|
||||
}
|
||||
|
||||
// Link ports
|
||||
@@ -394,13 +399,13 @@ struct pipewire_helpers
|
||||
pw_loop_iterate(this->global_context->lp, 1);
|
||||
if (!link)
|
||||
{
|
||||
self.template error<invalid_parameter_error>(
|
||||
self.libremidi_handle_error(
|
||||
self.configuration,
|
||||
"PipeWire: could not connect to port: " + p.port_name + " -> " + out_port.port_name);
|
||||
return false;
|
||||
"could not connect to port: " + p.port_name + " -> " + out_port.port_name);
|
||||
return std::errc::no_link;
|
||||
}
|
||||
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
template <spa_direction Direction>
|
||||
@@ -432,30 +437,34 @@ struct pipewire_helpers
|
||||
// Note: keep in mind that an "input" port for us (e.g. a keyboard that goes to the computer)
|
||||
// is an "output" port from the point of view of pipewire as data will come out of it
|
||||
template <spa_direction Direction>
|
||||
static auto get_ports(const pipewire_context& ctx) noexcept -> std::vector<
|
||||
std::conditional_t<Direction == SPA_DIRECTION_OUTPUT, input_port, output_port>>
|
||||
static auto get_ports(const observer_configuration& conf, const pipewire_context& ctx) noexcept
|
||||
-> std::vector<
|
||||
std::conditional_t<Direction == SPA_DIRECTION_OUTPUT, input_port, output_port>>
|
||||
{
|
||||
std::vector<std::conditional_t<Direction == SPA_DIRECTION_OUTPUT, input_port, output_port>>
|
||||
ret;
|
||||
|
||||
{
|
||||
std::lock_guard _{ctx.current_graph.mtx};
|
||||
for (auto& node : ctx.current_graph.physical_midi)
|
||||
{
|
||||
for (auto& p :
|
||||
(Direction == SPA_DIRECTION_INPUT ? node.second.inputs : node.second.outputs))
|
||||
if (conf.track_any || conf.track_hardware)
|
||||
for (auto& node : ctx.current_graph.physical_midi)
|
||||
{
|
||||
ret.push_back(to_port_info<Direction>(p));
|
||||
for (auto& port :
|
||||
(Direction == SPA_DIRECTION_INPUT ? node.second.inputs : node.second.outputs))
|
||||
{
|
||||
ret.push_back(to_port_info<Direction>(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& node : ctx.current_graph.software_midi)
|
||||
{
|
||||
for (auto& p :
|
||||
(Direction == SPA_DIRECTION_INPUT ? node.second.inputs : node.second.outputs))
|
||||
|
||||
if (conf.track_any || conf.track_virtual)
|
||||
for (auto& node : ctx.current_graph.software_midi)
|
||||
{
|
||||
ret.push_back(to_port_info<Direction>(p));
|
||||
for (auto& port :
|
||||
(Direction == SPA_DIRECTION_INPUT ? node.second.inputs : node.second.outputs))
|
||||
{
|
||||
ret.push_back(to_port_info<Direction>(port));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#include <libremidi/detail/midi_in.hpp>
|
||||
#include <libremidi/detail/midi_stream_decoder.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
namespace libremidi
|
||||
{
|
||||
class midi_in_pipewire final
|
||||
@@ -23,8 +21,17 @@ public:
|
||||
explicit midi_in_pipewire(input_configuration&& conf, pipewire_input_configuration&& apiconf)
|
||||
: configuration{std::move(conf), std::move(apiconf)}
|
||||
{
|
||||
create_context(*this);
|
||||
create_filter(*this);
|
||||
if (auto ret = create_context(*this); ret != stdx::error{})
|
||||
{
|
||||
client_open_ = ret;
|
||||
return;
|
||||
}
|
||||
if (auto ret = create_filter(*this); ret != stdx::error{})
|
||||
{
|
||||
client_open_ = ret;
|
||||
return;
|
||||
}
|
||||
client_open_ = stdx::error{};
|
||||
}
|
||||
|
||||
~midi_in_pipewire() override
|
||||
@@ -33,43 +40,42 @@ public:
|
||||
do_close_port();
|
||||
destroy_filter(*this);
|
||||
destroy_context();
|
||||
}
|
||||
|
||||
void set_client_name(std::string_view) override
|
||||
{
|
||||
warning(configuration, "midi_in_pipewire: set_client_name unsupported");
|
||||
client_open_ = std::errc::not_connected;
|
||||
}
|
||||
|
||||
libremidi::API get_current_api() const noexcept override { return libremidi::API::PIPEWIRE; }
|
||||
|
||||
bool open_port(const input_port& in_port, std::string_view name) override
|
||||
stdx::error open_port(const input_port& in_port, std::string_view name) override
|
||||
{
|
||||
if (!create_local_port(*this, name, SPA_DIRECTION_INPUT))
|
||||
return false;
|
||||
if (auto err = create_local_port(*this, name, SPA_DIRECTION_INPUT); err != stdx::error{})
|
||||
return err;
|
||||
|
||||
if (!link_ports(*this, in_port))
|
||||
return false;
|
||||
if (auto err = link_ports(*this, in_port); err != stdx::error{})
|
||||
return err;
|
||||
|
||||
start_thread();
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
bool open_virtual_port(std::string_view name) override
|
||||
stdx::error open_virtual_port(std::string_view name) override
|
||||
{
|
||||
if (!create_local_port(*this, name, SPA_DIRECTION_INPUT))
|
||||
return false;
|
||||
if (auto err = create_local_port(*this, name, SPA_DIRECTION_INPUT); err != stdx::error{})
|
||||
return err;
|
||||
|
||||
start_thread();
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void close_port() override
|
||||
stdx::error close_port() override
|
||||
{
|
||||
stop_thread();
|
||||
do_close_port();
|
||||
return do_close_port();
|
||||
}
|
||||
|
||||
void set_port_name(std::string_view port_name) override { rename_port(port_name); }
|
||||
stdx::error set_port_name(std::string_view port_name) override
|
||||
{
|
||||
return rename_port(port_name);
|
||||
}
|
||||
|
||||
timestamp absolute_timestamp() const noexcept override { return system_ns(); }
|
||||
|
||||
|
||||
@@ -24,8 +24,17 @@ public:
|
||||
midi_out_pipewire(output_configuration&& conf, pipewire_output_configuration&& apiconf)
|
||||
: configuration{std::move(conf), std::move(apiconf)}
|
||||
{
|
||||
create_context(*this);
|
||||
create_filter(*this);
|
||||
if (auto ret = create_context(*this); ret != stdx::error{})
|
||||
{
|
||||
client_open_ = ret;
|
||||
return;
|
||||
}
|
||||
if (auto ret = create_filter(*this); ret != stdx::error{})
|
||||
{
|
||||
client_open_ = ret;
|
||||
return;
|
||||
}
|
||||
client_open_ = stdx::error{};
|
||||
}
|
||||
|
||||
~midi_out_pipewire() override
|
||||
@@ -34,47 +43,46 @@ public:
|
||||
do_close_port();
|
||||
destroy_filter(*this);
|
||||
destroy_context();
|
||||
}
|
||||
|
||||
void set_client_name(std::string_view) override
|
||||
{
|
||||
warning(configuration, "midi_out_pipewire: set_client_name unsupported");
|
||||
client_open_ = std::errc::not_connected;
|
||||
}
|
||||
|
||||
libremidi::API get_current_api() const noexcept override { return libremidi::API::PIPEWIRE; }
|
||||
|
||||
bool open_port(const output_port& out_port, std::string_view name) override
|
||||
stdx::error open_port(const output_port& out_port, std::string_view name) override
|
||||
{
|
||||
if (!create_local_port(*this, name, SPA_DIRECTION_OUTPUT))
|
||||
return false;
|
||||
if (auto err = create_local_port(*this, name, SPA_DIRECTION_OUTPUT); err != stdx::error{})
|
||||
return err;
|
||||
|
||||
this->filter->set_port_buffer(configuration.output_buffer_size);
|
||||
|
||||
if (!link_ports(*this, out_port))
|
||||
return false;
|
||||
if (auto err = link_ports(*this, out_port); err != stdx::error{})
|
||||
return err;
|
||||
|
||||
start_thread();
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
bool open_virtual_port(std::string_view name) override
|
||||
stdx::error open_virtual_port(std::string_view name) override
|
||||
{
|
||||
if (!create_local_port(*this, name, SPA_DIRECTION_OUTPUT))
|
||||
return false;
|
||||
if (auto err = create_local_port(*this, name, SPA_DIRECTION_OUTPUT); err != stdx::error{})
|
||||
return err;
|
||||
|
||||
this->filter->set_port_buffer(configuration.output_buffer_size);
|
||||
|
||||
start_thread();
|
||||
return true;
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
void close_port() override
|
||||
stdx::error close_port() override
|
||||
{
|
||||
stop_thread();
|
||||
do_close_port();
|
||||
return do_close_port();
|
||||
}
|
||||
|
||||
void set_port_name(std::string_view port_name) override { rename_port(port_name); }
|
||||
stdx::error set_port_name(std::string_view port_name) override
|
||||
{
|
||||
return rename_port(port_name);
|
||||
}
|
||||
|
||||
int process(spa_io_position* pos)
|
||||
{
|
||||
@@ -120,6 +128,8 @@ public:
|
||||
if (res == -ENOSPC)
|
||||
break;
|
||||
|
||||
// Recycle the memory
|
||||
m_gcqueue.enqueue(std::move(m));
|
||||
m_queue.pop();
|
||||
}
|
||||
spa_pod_builder_pop(&build, &f);
|
||||
@@ -141,9 +151,14 @@ public:
|
||||
return 0;
|
||||
}
|
||||
|
||||
void send_message(const unsigned char* message, size_t size) override
|
||||
stdx::error send_message(const unsigned char* message, size_t size) override
|
||||
{
|
||||
m_queue.enqueue(libremidi::message(midi_bytes{message, message + size}, 0));
|
||||
libremidi::message m;
|
||||
m_gcqueue.try_dequeue(m);
|
||||
m.bytes.assign(message, message + size);
|
||||
m.timestamp = 0;
|
||||
m_queue.enqueue(std::move(m));
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
int convert_timestamp(int64_t user) const noexcept
|
||||
@@ -159,13 +174,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void schedule_message(int64_t ts, const unsigned char* message, size_t size) override
|
||||
stdx::error schedule_message(int64_t ts, const unsigned char* message, size_t size) override
|
||||
{
|
||||
m_queue.enqueue(
|
||||
libremidi::message(midi_bytes{message, message + size}, convert_timestamp(ts)));
|
||||
return stdx::error{};
|
||||
}
|
||||
|
||||
moodycamel::ReaderWriterQueue<libremidi::message> m_queue;
|
||||
moodycamel::ReaderWriterQueue<libremidi::message> m_gcqueue;
|
||||
std::atomic_int64_t m_process_clock = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -39,18 +39,29 @@ public:
|
||||
this->add_callbacks(configuration);
|
||||
this->start_thread();
|
||||
}
|
||||
|
||||
if (configuration.notify_in_constructor)
|
||||
{
|
||||
if (configuration.input_added)
|
||||
for (const auto& p : get_input_ports())
|
||||
configuration.input_added(p);
|
||||
|
||||
if (configuration.output_added)
|
||||
for (const auto& p : get_output_ports())
|
||||
configuration.output_added(p);
|
||||
}
|
||||
}
|
||||
|
||||
libremidi::API get_current_api() const noexcept override { return libremidi::API::PIPEWIRE; }
|
||||
|
||||
std::vector<libremidi::input_port> get_input_ports() const noexcept override
|
||||
{
|
||||
return get_ports<SPA_DIRECTION_OUTPUT>(*this->global_context);
|
||||
return get_ports<SPA_DIRECTION_OUTPUT>(this->configuration, *this->global_context);
|
||||
}
|
||||
|
||||
std::vector<libremidi::output_port> get_output_ports() const noexcept override
|
||||
{
|
||||
return get_ports<SPA_DIRECTION_INPUT>(*this->global_context);
|
||||
return get_ports<SPA_DIRECTION_INPUT>(this->configuration, *this->global_context);
|
||||
}
|
||||
|
||||
~observer_pipewire()
|
||||
|
||||
Reference in New Issue
Block a user