Revert "fix(audio): potential desync fix"

This reverts commit 76ad00596f.
This commit is contained in:
Lysec
2026-03-24 03:21:23 +01:00
parent 508f2b6ec8
commit b725f32e27
+46 -50
View File
@@ -296,18 +296,16 @@ Singleton {
objects: [...root.sinks, ...root.sources]
}
// Per-app volume state for the panel (updated when dragging sliders). As in
// 0c79aed, we only push overrides onto PipeWire for *new* stream node IDs —
// never for already-known IDs (fixes pause / notification fighting since 4.7).
// Debounced PipeWire → overrides sync keeps overrides aligned with in-app
// volume so overrides are not stale when a new node appears after quit/reload.
// Per-app volume persistence (survives stream recreation on track change/seek)
property var appVolumeOverrides: ({})
property var _knownAppStreamIds: ({})
property bool _isApplyingAppOverride: false
PwObjectTracker {
objects: root.appStreams
}
// Keep appVolumeOverrides aligned with PipeWire when apps change volume/mute.
Item {
width: 0
height: 0
@@ -322,46 +320,28 @@ Singleton {
target: modelData?.audio ?? null
function onVolumeChanged() {
root._schedulePipewireOverrideSync();
if (root._isApplyingAppOverride || !modelData?.audio) {
return;
}
var key = root.getAppKey(modelData);
if (key) {
root.setAppStreamVolume(key, modelData.audio.volume);
}
}
function onMutedChanged() {
root._schedulePipewireOverrideSync();
if (root._isApplyingAppOverride || !modelData?.audio) {
return;
}
var key = root.getAppKey(modelData);
if (key) {
root.setAppStreamMuted(key, modelData.audio.muted);
}
}
}
}
}
function _flushPipewireOverrideSync(): void {
var streams = root.appStreams;
if (!streams) {
return;
}
for (var i = 0; i < streams.length; i++) {
var s = streams[i];
if (!s || !s.audio) {
continue;
}
var key = getAppKey(s);
if (!key) {
continue;
}
setAppStreamVolume(key, s.audio.volume);
setAppStreamMuted(key, s.audio.muted);
}
}
function _schedulePipewireOverrideSync(): void {
_pipewireOverrideSyncDebounce.restart();
}
Timer {
id: _pipewireOverrideSyncDebounce
interval: 450
repeat: false
onTriggered: root._flushPipewireOverrideSync()
}
function getAppKey(node): string {
if (!node || !node.properties) {
return "";
@@ -421,40 +401,48 @@ Singleton {
var prevKnown = root._knownAppStreamIds;
var currentIds = {};
_isApplyingAppOverride = true;
for (var i = 0; i < streams.length; i++) {
var s = streams[i];
if (!s) {
continue;
}
var isNewStream = !prevKnown[s.id];
currentIds[s.id] = true;
var key = getAppKey(s);
var ov = key ? appVolumeOverrides[key] : null;
// New stream node (reload, app restart, etc.): adopt PipeWire state into
// overrides so we do not force an outdated Noctalia-only value.
if (key && s.audio && !prevKnown[s.id]) {
var seeded = appVolumeOverrides;
if (!seeded[key]) {
seeded[key] = {};
}
seeded[key].volume = s.audio.volume;
seeded[key].muted = s.audio.muted;
appVolumeOverrides = seeded;
ov = seeded[key];
}
if (!ov || !s.audio) {
continue;
}
// Same logic as 0c79aed: only apply stored levels when PipeWire exposes a
// new stream node (new track, reload, app restart). Existing nodes keep
// whatever volume the app / PipeWire reports — avoids pause desync.
if (isNewStream) {
if (ov.volume !== undefined && Math.abs(s.audio.volume - ov.volume) > root.epsilon) {
s.audio.volume = ov.volume;
}
if (ov.muted !== undefined && s.audio.muted !== ov.muted) {
s.audio.muted = ov.muted;
}
if (ov.volume !== undefined && Math.abs(s.audio.volume - ov.volume) > root.epsilon) {
s.audio.volume = ov.volume;
}
if (ov.muted !== undefined && s.audio.muted !== ov.muted) {
s.audio.muted = ov.muted;
}
}
_knownAppStreamIds = currentIds;
_isApplyingAppOverride = false;
}
Connections {
target: root
function onAppStreamsChanged() {
_appOverrideTimer.restart();
root._schedulePipewireOverrideSync();
}
}
@@ -464,6 +452,14 @@ Singleton {
onTriggered: root._applyAppOverrides()
}
Timer {
id: _appOverrideEnforcer
interval: 1000
running: Object.keys(root.appVolumeOverrides).length > 0 && root.appStreams.length > 0
repeat: true
onTriggered: root._applyAppOverrides()
}
Component.onCompleted: {
wpctlAvailabilityProcess.running = true;
}