@@ -228,10 +228,10 @@ void PwNodeBoundAudio::onInfo(const pw_node_info* info) {
228228
229229 if (param.id == SPA_PARAM_Props) {
230230 if ((param.flags & SPA_PARAM_INFO_READWRITE) == SPA_PARAM_INFO_READWRITE) {
231- qCDebug (logNode) << " Enumerating props param for" << this ;
231+ qCDebug (logNode) << " Enumerating props param for" << this -> node ;
232232 pw_node_enum_params (this ->node ->proxy (), 0 , param.id , 0 , UINT32_MAX, nullptr );
233233 } else {
234- qCWarning (logNode) << " Unable to enumerate props param for" << this
234+ qCWarning (logNode) << " Unable to enumerate props param for" << this -> node
235235 << " as the param does not have read+write permissions." ;
236236 }
237237 }
@@ -266,6 +266,10 @@ void PwNodeBoundAudio::updateVolumeProps(const spa_pod* param) {
266266 qCInfo (logNode) << " Got updated channels of" << this ->node << ' -' << this ->mChannels ;
267267 }
268268
269+ if (this ->mServerVolumes != volumeProps.volumes ) {
270+ this ->mServerVolumes = volumeProps.volumes ;
271+ }
272+
269273 if (this ->mVolumes != volumeProps.volumes ) {
270274 this ->mVolumes = volumeProps.volumes ;
271275 volumesChanged = true ;
@@ -286,6 +290,7 @@ void PwNodeBoundAudio::updateVolumeProps(const spa_pod* param) {
286290void PwNodeBoundAudio::onUnbind () {
287291 this ->mChannels .clear ();
288292 this ->mVolumes .clear ();
293+ this ->mServerVolumes .clear ();
289294 this ->mDeviceVolumes .clear ();
290295 this ->waitingVolumes .clear ();
291296 emit this ->channelsChanged ();
@@ -381,13 +386,32 @@ void PwNodeBoundAudio::setVolumes(const QVector<float>& volumes) {
381386 << " via device" ;
382387 this ->waitingVolumes = realVolumes;
383388 } else {
384- qCInfo (logNode) << " Changing volumes of" << this ->node << " to" << realVolumes << " via device" ;
385- if (!this ->node ->device ->setVolumes (this ->node ->routeDevice , realVolumes)) {
386- return ;
389+ auto significantChange = this ->mServerVolumes .isEmpty ();
390+ for (auto i = 0 ; i < this ->mServerVolumes .length (); i++) {
391+ auto serverVolume = this ->mServerVolumes .value (i);
392+ auto targetVolume = realVolumes.value (i);
393+ if (targetVolume == 0 || abs (targetVolume - serverVolume) >= 0.0001 ) {
394+ significantChange = true ;
395+ break ;
396+ }
387397 }
388398
389- this ->mDeviceVolumes = realVolumes;
390- this ->node ->device ->waitForDevice ();
399+ if (significantChange) {
400+ qCInfo (logNode) << " Changing volumes of" << this ->node << " to" << realVolumes
401+ << " via device" ;
402+ if (!this ->node ->device ->setVolumes (this ->node ->routeDevice , realVolumes)) {
403+ return ;
404+ }
405+
406+ this ->mDeviceVolumes = realVolumes;
407+ this ->node ->device ->waitForDevice ();
408+ } else {
409+ // Insignificant changes won't cause an info event on the device, leaving qs hung in the
410+ // "waiting for acknowledgement" state forever.
411+ qCInfo (logNode) << " Ignoring volume change for" << this ->node << " to" << realVolumes
412+ << " from" << this ->mServerVolumes
413+ << " as it is a device node and the change is too small." ;
414+ }
391415 }
392416 } else {
393417 auto buffer = std::array<quint8, 1024 >();
0 commit comments