forked from quickshell/quickshell
		
	service/pipewire: ignore insignificant device volume changes
Fixes devices getting stuck in a "waiting for volume change acknowledgement" state forever.
This commit is contained in:
		
							parent
							
								
									a116f39c63
								
							
						
					
					
						commit
						f6ad617b67
					
				
					 2 changed files with 32 additions and 7 deletions
				
			
		| 
						 | 
					@ -228,10 +228,10 @@ void PwNodeBoundAudio::onInfo(const pw_node_info* info) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (param.id == SPA_PARAM_Props) {
 | 
								if (param.id == SPA_PARAM_Props) {
 | 
				
			||||||
				if ((param.flags & SPA_PARAM_INFO_READWRITE) == SPA_PARAM_INFO_READWRITE) {
 | 
									if ((param.flags & SPA_PARAM_INFO_READWRITE) == SPA_PARAM_INFO_READWRITE) {
 | 
				
			||||||
					qCDebug(logNode) << "Enumerating props param for" << this;
 | 
										qCDebug(logNode) << "Enumerating props param for" << this->node;
 | 
				
			||||||
					pw_node_enum_params(this->node->proxy(), 0, param.id, 0, UINT32_MAX, nullptr);
 | 
										pw_node_enum_params(this->node->proxy(), 0, param.id, 0, UINT32_MAX, nullptr);
 | 
				
			||||||
				} else {
 | 
									} else {
 | 
				
			||||||
					qCWarning(logNode) << "Unable to enumerate props param for" << this
 | 
										qCWarning(logNode) << "Unable to enumerate props param for" << this->node
 | 
				
			||||||
					                   << "as the param does not have read+write permissions.";
 | 
										                   << "as the param does not have read+write permissions.";
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -266,6 +266,10 @@ void PwNodeBoundAudio::updateVolumeProps(const spa_pod* param) {
 | 
				
			||||||
		qCInfo(logNode) << "Got updated channels of" << this->node << '-' << this->mChannels;
 | 
							qCInfo(logNode) << "Got updated channels of" << this->node << '-' << this->mChannels;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (this->mServerVolumes != volumeProps.volumes) {
 | 
				
			||||||
 | 
							this->mServerVolumes = volumeProps.volumes;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (this->mVolumes != volumeProps.volumes) {
 | 
						if (this->mVolumes != volumeProps.volumes) {
 | 
				
			||||||
		this->mVolumes = volumeProps.volumes;
 | 
							this->mVolumes = volumeProps.volumes;
 | 
				
			||||||
		volumesChanged = true;
 | 
							volumesChanged = true;
 | 
				
			||||||
| 
						 | 
					@ -286,6 +290,7 @@ void PwNodeBoundAudio::updateVolumeProps(const spa_pod* param) {
 | 
				
			||||||
void PwNodeBoundAudio::onUnbind() {
 | 
					void PwNodeBoundAudio::onUnbind() {
 | 
				
			||||||
	this->mChannels.clear();
 | 
						this->mChannels.clear();
 | 
				
			||||||
	this->mVolumes.clear();
 | 
						this->mVolumes.clear();
 | 
				
			||||||
 | 
						this->mServerVolumes.clear();
 | 
				
			||||||
	this->mDeviceVolumes.clear();
 | 
						this->mDeviceVolumes.clear();
 | 
				
			||||||
	this->waitingVolumes.clear();
 | 
						this->waitingVolumes.clear();
 | 
				
			||||||
	emit this->channelsChanged();
 | 
						emit this->channelsChanged();
 | 
				
			||||||
| 
						 | 
					@ -381,13 +386,32 @@ void PwNodeBoundAudio::setVolumes(const QVector<float>& volumes) {
 | 
				
			||||||
			                << "via device";
 | 
								                << "via device";
 | 
				
			||||||
			this->waitingVolumes = realVolumes;
 | 
								this->waitingVolumes = realVolumes;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			qCInfo(logNode) << "Changing volumes of" << this->node << "to" << realVolumes << "via device";
 | 
								auto significantChange = this->mServerVolumes.isEmpty();
 | 
				
			||||||
			if (!this->node->device->setVolumes(this->node->routeDevice, realVolumes)) {
 | 
								for (auto i = 0; i < this->mServerVolumes.length(); i++) {
 | 
				
			||||||
				return;
 | 
									auto serverVolume = this->mServerVolumes.value(i);
 | 
				
			||||||
 | 
									auto targetVolume = realVolumes.value(i);
 | 
				
			||||||
 | 
									if (targetVolume == 0 || abs(targetVolume - serverVolume) >= 0.0001) {
 | 
				
			||||||
 | 
										significantChange = true;
 | 
				
			||||||
 | 
										break;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			this->mDeviceVolumes = realVolumes;
 | 
								if (significantChange) {
 | 
				
			||||||
			this->node->device->waitForDevice();
 | 
									qCInfo(logNode) << "Changing volumes of" << this->node << "to" << realVolumes
 | 
				
			||||||
 | 
									                << "via device";
 | 
				
			||||||
 | 
									if (!this->node->device->setVolumes(this->node->routeDevice, realVolumes)) {
 | 
				
			||||||
 | 
										return;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									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) << "Ignoring volume change for" << this->node << "to" << realVolumes
 | 
				
			||||||
 | 
									                << "from" << this->mServerVolumes
 | 
				
			||||||
 | 
									                << "as it is a device node and the change is too small.";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		auto buffer = std::array<quint8, 1024>();
 | 
							auto buffer = std::array<quint8, 1024>();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,6 +150,7 @@ private:
 | 
				
			||||||
	bool mMuted = false;
 | 
						bool mMuted = false;
 | 
				
			||||||
	QVector<PwAudioChannel::Enum> mChannels;
 | 
						QVector<PwAudioChannel::Enum> mChannels;
 | 
				
			||||||
	QVector<float> mVolumes;
 | 
						QVector<float> mVolumes;
 | 
				
			||||||
 | 
						QVector<float> mServerVolumes;
 | 
				
			||||||
	QVector<float> mDeviceVolumes;
 | 
						QVector<float> mDeviceVolumes;
 | 
				
			||||||
	QVector<float> waitingVolumes;
 | 
						QVector<float> waitingVolumes;
 | 
				
			||||||
	PwNode* node;
 | 
						PwNode* node;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue