mirror of
https://git.outfoxxed.me/quickshell/quickshell.git
synced 2025-11-04 19:04:56 +11:00
services/pipewire: consider device volume step when sending updates
Previously a hardcoded 0.0001 offset was used to determine if a volume change was significant enough to send to a device, however some devices have a much more granular step size, which caused future volume updates to be blocked. This change replaces the hardcoded offset with the volumeStep device route property which should be large enough for the device to work with. Fixes #279
This commit is contained in:
parent
475856b767
commit
9662234759
3 changed files with 39 additions and 23 deletions
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
## Bug Fixes
|
## Bug Fixes
|
||||||
|
|
||||||
|
- Fixed volumes getting stuck on change for pipewire devices with few volume steps.
|
||||||
- Fixed a crash when running out of disk space to write log files.
|
- Fixed a crash when running out of disk space to write log files.
|
||||||
- Fixed a rare crash when disconnecting a monitor.
|
- Fixed a rare crash when disconnecting a monitor.
|
||||||
- Fixed build issues preventing cross compilation from working.
|
- Fixed build issues preventing cross compilation from working.
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,8 @@ void PwNodeBoundAudio::updateVolumeProps(const PwVolumeProps& volumeProps) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->volumeStep = volumeProps.volumeStep;
|
||||||
|
|
||||||
// It is important that the lengths of channels and volumes stay in sync whenever you read them.
|
// It is important that the lengths of channels and volumes stay in sync whenever you read them.
|
||||||
auto channelsChanged = false;
|
auto channelsChanged = false;
|
||||||
auto volumesChanged = false;
|
auto volumesChanged = false;
|
||||||
|
|
@ -435,31 +437,35 @@ void PwNodeBoundAudio::setVolumes(const QVector<float>& volumes) {
|
||||||
<< "via device";
|
<< "via device";
|
||||||
this->waitingVolumes = realVolumes;
|
this->waitingVolumes = realVolumes;
|
||||||
} else {
|
} else {
|
||||||
auto significantChange = this->mServerVolumes.isEmpty();
|
if (this->volumeStep != -1) {
|
||||||
for (auto i = 0; i < this->mServerVolumes.length(); i++) {
|
auto significantChange = this->mServerVolumes.isEmpty();
|
||||||
auto serverVolume = this->mServerVolumes.value(i);
|
for (auto i = 0; i < this->mServerVolumes.length(); i++) {
|
||||||
auto targetVolume = realVolumes.value(i);
|
auto serverVolume = this->mServerVolumes.value(i);
|
||||||
if (targetVolume == 0 || abs(targetVolume - serverVolume) >= 0.0001) {
|
auto targetVolume = realVolumes.value(i);
|
||||||
significantChange = true;
|
if (targetVolume == 0 || abs(targetVolume - serverVolume) >= this->volumeStep) {
|
||||||
break;
|
significantChange = true;
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (significantChange) {
|
|
||||||
qCInfo(logNode) << "Changing volumes of" << this->node << "to" << realVolumes
|
|
||||||
<< "via device";
|
|
||||||
if (!this->node->device->setVolumes(this->node->routeDevice, realVolumes)) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->mDeviceVolumes = realVolumes;
|
if (significantChange) {
|
||||||
this->node->device->waitForDevice();
|
qCInfo(logNode) << "Changing volumes of" << this->node << "to" << realVolumes
|
||||||
} else {
|
<< "via device";
|
||||||
// Insignificant changes won't cause an info event on the device, leaving qs hung in the
|
if (!this->node->device->setVolumes(this->node->routeDevice, realVolumes)) {
|
||||||
// "waiting for acknowledgement" state forever.
|
return;
|
||||||
qCInfo(logNode) << "Ignoring volume change for" << this->node << "to" << realVolumes
|
}
|
||||||
<< "from" << this->mServerVolumes
|
|
||||||
<< "as it is a device node and the change is too small.";
|
this->mDeviceVolumes = realVolumes;
|
||||||
|
this->node->device->waitForDevice();
|
||||||
|
} else {
|
||||||
|
// Insignificant changes won't cause an info event on the device, leaving qs hung in the
|
||||||
|
// "waiting for acknowledgement" state forever.
|
||||||
|
qCInfo(logNode).nospace()
|
||||||
|
<< "Ignoring volume change for " << this->node << " to " << realVolumes << " from "
|
||||||
|
<< this->mServerVolumes
|
||||||
|
<< " as it is a device node and the change is too small (min step: "
|
||||||
|
<< this->volumeStep << ").";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -519,6 +525,7 @@ PwVolumeProps PwVolumeProps::parseSpaPod(const spa_pod* param) {
|
||||||
const auto* volumesProp = spa_pod_find_prop(param, nullptr, SPA_PROP_channelVolumes);
|
const auto* volumesProp = spa_pod_find_prop(param, nullptr, SPA_PROP_channelVolumes);
|
||||||
const auto* channelsProp = spa_pod_find_prop(param, nullptr, SPA_PROP_channelMap);
|
const auto* channelsProp = spa_pod_find_prop(param, nullptr, SPA_PROP_channelMap);
|
||||||
const auto* muteProp = spa_pod_find_prop(param, nullptr, SPA_PROP_mute);
|
const auto* muteProp = spa_pod_find_prop(param, nullptr, SPA_PROP_mute);
|
||||||
|
const auto* volumeStepProp = spa_pod_find_prop(param, nullptr, SPA_PROP_volumeStep);
|
||||||
|
|
||||||
const auto* volumes = reinterpret_cast<const spa_pod_array*>(&volumesProp->value);
|
const auto* volumes = reinterpret_cast<const spa_pod_array*>(&volumesProp->value);
|
||||||
const auto* channels = reinterpret_cast<const spa_pod_array*>(&channelsProp->value);
|
const auto* channels = reinterpret_cast<const spa_pod_array*>(&channelsProp->value);
|
||||||
|
|
@ -537,6 +544,12 @@ PwVolumeProps PwVolumeProps::parseSpaPod(const spa_pod* param) {
|
||||||
|
|
||||||
spa_pod_get_bool(&muteProp->value, &props.mute);
|
spa_pod_get_bool(&muteProp->value, &props.mute);
|
||||||
|
|
||||||
|
if (volumeStepProp) {
|
||||||
|
spa_pod_get_float(&volumeStepProp->value, &props.volumeStep);
|
||||||
|
} else {
|
||||||
|
props.volumeStep = -1;
|
||||||
|
}
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ struct PwVolumeProps {
|
||||||
QVector<PwAudioChannel::Enum> channels;
|
QVector<PwAudioChannel::Enum> channels;
|
||||||
QVector<float> volumes;
|
QVector<float> volumes;
|
||||||
bool mute = false;
|
bool mute = false;
|
||||||
|
float volumeStep = -1;
|
||||||
|
|
||||||
static PwVolumeProps parseSpaPod(const spa_pod* param);
|
static PwVolumeProps parseSpaPod(const spa_pod* param);
|
||||||
};
|
};
|
||||||
|
|
@ -214,6 +215,7 @@ private:
|
||||||
QVector<float> mServerVolumes;
|
QVector<float> mServerVolumes;
|
||||||
QVector<float> mDeviceVolumes;
|
QVector<float> mDeviceVolumes;
|
||||||
QVector<float> waitingVolumes;
|
QVector<float> waitingVolumes;
|
||||||
|
float volumeStep = -1;
|
||||||
PwNode* node;
|
PwNode* node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue