From ea79eaceb0375a8a2ebdd55c60bf89c4167b264d Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sat, 11 Oct 2025 21:42:58 -0700 Subject: [PATCH] services/pipewire: do not use device for pro audio node controls Note that the device object is currently still bound. This should not be necessary. Fixes #178 --- changelog/next.md | 4 ++++ src/services/pipewire/node.cpp | 19 +++++++++++++++---- src/services/pipewire/node.hpp | 3 +++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/changelog/next.md b/changelog/next.md index 62a730f..13123b8 100644 --- a/changelog/next.md +++ b/changelog/next.md @@ -2,3 +2,7 @@ - Added support for creating wayland idle inhibitors. - Added support for wayland idle timeouts. + +## Bug Fixes + +- Fixed volume control breaking with pipewire pro audio mode. diff --git a/src/services/pipewire/node.cpp b/src/services/pipewire/node.cpp index 031a68f..f336558 100644 --- a/src/services/pipewire/node.cpp +++ b/src/services/pipewire/node.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "../../core/logcat.hpp" @@ -195,6 +196,16 @@ void PwNode::onInfo(void* data, const pw_node_info* info) { if ((info->change_mask & PW_NODE_CHANGE_MASK_PROPS) != 0) { auto properties = QMap(); + bool proAudio = false; + if (const auto* proAudioStr = spa_dict_lookup(info->props, "device.profile.pro")) { + proAudio = spa_atob(proAudioStr); + } + + if (proAudio != self->proAudio) { + qCDebug(logNode) << self << "pro audio state changed:" << proAudio; + self->proAudio = proAudio; + } + if (self->device) { if (const auto* routeDevice = spa_dict_lookup(info->props, "card.profile.device")) { auto ok = false; @@ -286,7 +297,7 @@ void PwNodeBoundAudio::onInfo(const pw_node_info* info) { void PwNodeBoundAudio::onSpaParam(quint32 id, quint32 index, const spa_pod* param) { if (id == SPA_PARAM_Props && index == 0) { - if (this->node->device) { + if (this->node->shouldUseDevice()) { qCDebug(logNode) << "Skipping node volume props update for" << this->node << "in favor of device updates."; return; @@ -358,7 +369,7 @@ void PwNodeBoundAudio::setMuted(bool muted) { if (muted == this->mMuted) return; - if (this->node->device) { + if (this->node->shouldUseDevice()) { qCInfo(logNode) << "Changing muted state of" << this->node << "to" << muted << "via device"; if (!this->node->device->setMuted(this->node->routeDevice, muted)) { return; @@ -431,7 +442,7 @@ void PwNodeBoundAudio::setVolumes(const QVector& volumes) { return; } - if (this->node->device) { + if (this->node->shouldUseDevice()) { if (this->node->device->waitingForDevice()) { qCInfo(logNode) << "Waiting to change volumes of" << this->node << "to" << realVolumes << "via device"; @@ -511,7 +522,7 @@ void PwNodeBoundAudio::onDeviceVolumesChanged( qint32 routeDevice, const PwVolumeProps& volumeProps ) { - if (this->node->device && this->node->routeDevice == routeDevice) { + if (this->node->shouldUseDevice() && this->node->routeDevice == routeDevice) { qCDebug(logNode) << "Got updated device volume props for" << this->node << "via" << this->node->device; diff --git a/src/services/pipewire/node.hpp b/src/services/pipewire/node.hpp index b53015f..359c0f3 100644 --- a/src/services/pipewire/node.hpp +++ b/src/services/pipewire/node.hpp @@ -240,6 +240,9 @@ public: PwDevice* device = nullptr; qint32 routeDevice = -1; + bool proAudio = false; + + [[nodiscard]] bool shouldUseDevice() const { return this->device && !this->proAudio; } signals: void propertiesChanged();