mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2026-02-23 03:33:57 +11:00
services/pipewire: cache route device volumes to initialize nodes
Nodes referencing a device can be bound later than the device is bound. If this happens, the node will not receive an initial route device volume change event. This change caches the last known route device volume and initializes the device with it if present.
This commit is contained in:
parent
fc704e6b5d
commit
a00ff03944
5 changed files with 28 additions and 1 deletions
|
|
@ -24,6 +24,7 @@ set shell id.
|
||||||
|
|
||||||
- Fixed volume control breaking with pipewire pro audio mode.
|
- Fixed volume control breaking with pipewire pro audio mode.
|
||||||
- Fixed escape sequence handling in desktop entries.
|
- Fixed escape sequence handling in desktop entries.
|
||||||
|
- Fixed volumes not initializing if a pipewire device was already loaded before its node.
|
||||||
|
|
||||||
## Packaging Changes
|
## Packaging Changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,12 +125,22 @@ void PwDevice::addDeviceIndexPairs(const spa_pod* param) {
|
||||||
// Insert into the main map as well, staging's purpose is to remove old entries.
|
// Insert into the main map as well, staging's purpose is to remove old entries.
|
||||||
this->routeDeviceIndexes.insert(device, index);
|
this->routeDeviceIndexes.insert(device, index);
|
||||||
|
|
||||||
|
// Used for initial node volume if the device is bound before the node
|
||||||
|
// (e.g. multiple nodes pointing to the same device)
|
||||||
|
this->routeDeviceVolumes.insert(device, volumeProps);
|
||||||
|
|
||||||
qCDebug(logDevice).nospace() << "Registered device/index pair for " << this
|
qCDebug(logDevice).nospace() << "Registered device/index pair for " << this
|
||||||
<< ": [device: " << device << ", index: " << index << ']';
|
<< ": [device: " << device << ", index: " << index << ']';
|
||||||
|
|
||||||
emit this->routeVolumesChanged(device, volumeProps);
|
emit this->routeVolumesChanged(device, volumeProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PwDevice::tryLoadVolumeProps(qint32 routeDevice, PwVolumeProps& volumeProps) {
|
||||||
|
if (!this->routeDeviceVolumes.contains(routeDevice)) return false;
|
||||||
|
volumeProps = this->routeDeviceVolumes.value(routeDevice);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void PwDevice::polled() {
|
void PwDevice::polled() {
|
||||||
// It is far more likely that the list content has not come in yet than it having no entries,
|
// It is far more likely that the list content has not come in yet than it having no entries,
|
||||||
// and there isn't a way to check in the case that there *aren't* actually any entries.
|
// and there isn't a way to check in the case that there *aren't* actually any entries.
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,8 @@ public:
|
||||||
void waitForDevice();
|
void waitForDevice();
|
||||||
[[nodiscard]] bool waitingForDevice() const;
|
[[nodiscard]] bool waitingForDevice() const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool tryLoadVolumeProps(qint32 routeDevice, PwVolumeProps& volumeProps);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void deviceReady();
|
void deviceReady();
|
||||||
void routeVolumesChanged(qint32 routeDevice, const PwVolumeProps& volumeProps);
|
void routeVolumesChanged(qint32 routeDevice, const PwVolumeProps& volumeProps);
|
||||||
|
|
@ -46,6 +48,7 @@ private:
|
||||||
onParam(void* data, qint32 seq, quint32 id, quint32 index, quint32 next, const spa_pod* param);
|
onParam(void* data, qint32 seq, quint32 id, quint32 index, quint32 next, const spa_pod* param);
|
||||||
|
|
||||||
QHash<qint32, qint32> routeDeviceIndexes;
|
QHash<qint32, qint32> routeDeviceIndexes;
|
||||||
|
QHash<qint32, PwVolumeProps> routeDeviceVolumes;
|
||||||
QList<qint32> stagingIndexes;
|
QList<qint32> stagingIndexes;
|
||||||
void addDeviceIndexPairs(const spa_pod* param);
|
void addDeviceIndexPairs(const spa_pod* param);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,7 @@ void PwNode::onInfo(void* data, const pw_node_info* info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
self->routeDevice = id;
|
self->routeDevice = id;
|
||||||
|
if (self->boundData) self->boundData->onDeviceChanged();
|
||||||
} else {
|
} else {
|
||||||
qCCritical(logNode) << self << "has attached device" << self->device
|
qCCritical(logNode) << self << "has attached device" << self->device
|
||||||
<< "but no card.profile.device property.";
|
<< "but no card.profile.device property.";
|
||||||
|
|
@ -277,6 +278,15 @@ PwNodeBoundAudio::PwNodeBoundAudio(PwNode* node): QObject(node), node(node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PwNodeBoundAudio::onDeviceChanged() {
|
||||||
|
PwVolumeProps volumeProps;
|
||||||
|
if (this->node->device->tryLoadVolumeProps(this->node->routeDevice, volumeProps)) {
|
||||||
|
qCDebug(logNode) << "Initializing volume props for" << this->node
|
||||||
|
<< "with known values from backing device.";
|
||||||
|
this->updateVolumeProps(volumeProps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PwNodeBoundAudio::onInfo(const pw_node_info* info) {
|
void PwNodeBoundAudio::onInfo(const pw_node_info* info) {
|
||||||
if ((info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) != 0) {
|
if ((info->change_mask & PW_NODE_CHANGE_MASK_PARAMS) != 0) {
|
||||||
for (quint32 i = 0; i < info->n_params; i++) {
|
for (quint32 i = 0; i < info->n_params; i++) {
|
||||||
|
|
@ -299,7 +309,8 @@ void PwNodeBoundAudio::onSpaParam(quint32 id, quint32 index, const spa_pod* para
|
||||||
if (id == SPA_PARAM_Props && index == 0) {
|
if (id == SPA_PARAM_Props && index == 0) {
|
||||||
if (this->node->shouldUseDevice()) {
|
if (this->node->shouldUseDevice()) {
|
||||||
qCDebug(logNode) << "Skipping node volume props update for" << this->node
|
qCDebug(logNode) << "Skipping node volume props update for" << this->node
|
||||||
<< "in favor of device updates.";
|
<< "in favor of device updates from routeDevice" << this->node->routeDevice
|
||||||
|
<< "of" << this->node->device;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,7 @@ public:
|
||||||
virtual ~PwNodeBoundData() = default;
|
virtual ~PwNodeBoundData() = default;
|
||||||
Q_DISABLE_COPY_MOVE(PwNodeBoundData);
|
Q_DISABLE_COPY_MOVE(PwNodeBoundData);
|
||||||
|
|
||||||
|
virtual void onDeviceChanged() {};
|
||||||
virtual void onInfo(const pw_node_info* /*info*/) {}
|
virtual void onInfo(const pw_node_info* /*info*/) {}
|
||||||
virtual void onSpaParam(quint32 /*id*/, quint32 /*index*/, const spa_pod* /*param*/) {}
|
virtual void onSpaParam(quint32 /*id*/, quint32 /*index*/, const spa_pod* /*param*/) {}
|
||||||
virtual void onUnbind() {}
|
virtual void onUnbind() {}
|
||||||
|
|
@ -182,6 +183,7 @@ class PwNodeBoundAudio
|
||||||
public:
|
public:
|
||||||
explicit PwNodeBoundAudio(PwNode* node);
|
explicit PwNodeBoundAudio(PwNode* node);
|
||||||
|
|
||||||
|
void onDeviceChanged() override;
|
||||||
void onInfo(const pw_node_info* info) override;
|
void onInfo(const pw_node_info* info) override;
|
||||||
void onSpaParam(quint32 id, quint32 index, const spa_pod* param) override;
|
void onSpaParam(quint32 id, quint32 index, const spa_pod* param) override;
|
||||||
void onUnbind() override;
|
void onUnbind() override;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue