Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions include/libremidi/backends/linux/pipewire/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1130,10 +1130,9 @@ class context : public std::enable_shared_from_this<context>
void fill_port_from_props(port_info& p, const spa_dict* props) noexcept
{
if (auto v = dict_get(props, "format.dsp"); !v.empty())
{
p.format = std::string{v};
p.kind = classify_format_dsp(p.format);
}
if (auto k = classify_port_props(props); k != media_class::other)
p.kind = k;
if (auto v = dict_get(props, PW_KEY_PORT_NAME); !v.empty())
p.port_name = std::string{v};
if (auto v = dict_get(props, PW_KEY_PORT_ALIAS); !v.empty())
Expand Down
7 changes: 7 additions & 0 deletions include/libremidi/backends/linux/pipewire/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ inline media_class classify_node_props(const spa_dict* props) noexcept
return classify_media_class(dict_get(props, PW_KEY_MEDIA_CLASS));
}

inline media_class classify_port_props(const spa_dict* props) noexcept
{
if (dict_get(props, "control.ump") == "true")
return media_class::ump;
return classify_format_dsp(dict_get(props, "format.dsp"));
}

struct port_info
{
std::uint32_t id{};
Expand Down
23 changes: 16 additions & 7 deletions include/libremidi/backends/pipewire/helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,22 @@ struct pipewire_helpers
this->flt->update_params(this->port, params, 1);
}

static bool port_matches(
const libremidi::pipewire::port_info& port, libremidi::pipewire::media_class kind) noexcept
{
if (kind == libremidi::pipewire::media_class::ump)
return port.kind == libremidi::pipewire::media_class::ump;
return libremidi::pipewire::is_midi_like(port.kind);
}

template <libremidi::API Api>
void add_callbacks(std::string format, const observer_configuration& conf)
void add_callbacks(libremidi::pipewire::media_class kind, const observer_configuration& conf)
{
assert(this->ctx);

sub_added = this->ctx->on_port_added(
[this, format, &conf](const libremidi::pipewire::port_info& port) {
if (port.format.find(format) == std::string::npos)
[this, kind, &conf](const libremidi::pipewire::port_info& port) {
if (!port_matches(port, kind))
return;
this->port_cache[port.id] = port;

Expand All @@ -239,14 +247,14 @@ struct pipewire_helpers
});

sub_removed = this->ctx->on_port_removed(
[this, format, &conf](std::uint32_t port_id) {
[this, kind, &conf](std::uint32_t port_id) {
auto it = this->port_cache.find(port_id);
if (it == this->port_cache.end())
return;
const auto port = it->second;
this->port_cache.erase(it);

if (port.format.find(format) == std::string::npos)
if (!port_matches(port, kind))
return;
bool unfiltered = conf.track_any;
unfiltered |= (port.physical && conf.track_hardware);
Expand Down Expand Up @@ -420,7 +428,8 @@ struct pipewire_helpers
// user-facing input port carries Direction=OUTPUT.
template <spa_direction Direction, libremidi::API Api>
static auto get_ports(
std::string_view format, const observer_configuration& conf, const context_t& ctx) noexcept
libremidi::pipewire::media_class kind, const observer_configuration& conf,
const context_t& ctx) noexcept
-> std::vector<
std::conditional_t<Direction == SPA_DIRECTION_OUTPUT, input_port, output_port>>
{
Expand All @@ -433,7 +442,7 @@ struct pipewire_helpers
const auto& bucket = (Direction == SPA_DIRECTION_INPUT ? node.inputs : node.outputs);
for (const auto& port : bucket)
{
if (port.format.find(format) == std::string::npos)
if (!port_matches(port, kind))
continue;
bool unfiltered = conf.track_any;
unfiltered |= (port.physical && conf.track_hardware);
Expand Down
7 changes: 4 additions & 3 deletions include/libremidi/backends/pipewire/observer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class observer_pipewire final
// Hold thread_loop_lock so a port arriving between subscription
// install and the snapshot walk doesn't fire twice.
this->ctx->with_lock([this] {
this->add_callbacks<libremidi::API::PIPEWIRE>("midi", configuration);
this->add_callbacks<libremidi::API::PIPEWIRE>(
libremidi::pipewire::media_class::midi, configuration);

if (configuration.notify_in_constructor)
{
Expand All @@ -49,15 +50,15 @@ class observer_pipewire final
if (!this->ctx)
return {};
return get_ports<SPA_DIRECTION_OUTPUT, libremidi::API::PIPEWIRE>(
"midi", this->configuration, *this->ctx);
libremidi::pipewire::media_class::midi, this->configuration, *this->ctx);
}

std::vector<libremidi::output_port> get_output_ports() const noexcept override
{
if (!this->ctx)
return {};
return get_ports<SPA_DIRECTION_INPUT, libremidi::API::PIPEWIRE>(
"midi", this->configuration, *this->ctx);
libremidi::pipewire::media_class::midi, this->configuration, *this->ctx);
}

~observer_pipewire() { destroy_context(); }
Expand Down
7 changes: 4 additions & 3 deletions include/libremidi/backends/pipewire_ump/observer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class observer_pipewire final

// Atomic subscribe + initial walk (see pipewire/observer.hpp).
this->ctx->with_lock([this] {
this->add_callbacks<libremidi::API::PIPEWIRE_UMP>("UMP", configuration);
this->add_callbacks<libremidi::API::PIPEWIRE_UMP>(
libremidi::pipewire::media_class::ump, configuration);

if (configuration.notify_in_constructor)
{
Expand All @@ -52,15 +53,15 @@ class observer_pipewire final
if (!this->ctx)
return {};
return get_ports<SPA_DIRECTION_OUTPUT, libremidi::API::PIPEWIRE_UMP>(
"UMP", this->configuration, *this->ctx);
libremidi::pipewire::media_class::ump, this->configuration, *this->ctx);
}

std::vector<libremidi::output_port> get_output_ports() const noexcept override
{
if (!this->ctx)
return {};
return get_ports<SPA_DIRECTION_INPUT, libremidi::API::PIPEWIRE_UMP>(
"UMP", this->configuration, *this->ctx);
libremidi::pipewire::media_class::ump, this->configuration, *this->ctx);
}

~observer_pipewire() { destroy_context(); }
Expand Down
Loading