diff --git a/shell/services/MprisService.qml b/shell/services/MprisService.qml index b4eeff2..d5941d5 100644 --- a/shell/services/MprisService.qml +++ b/shell/services/MprisService.qml @@ -11,14 +11,9 @@ QtObject { readonly property MprisPlayer player: players[playerIdx] ?? players[0] ?? null readonly property bool playing: player?.playbackState === MprisPlaybackState.Playing - // Track the identity of the selected player so we can find it after list changes property string _selectedIdentity: "" - - // Track which player played most recently (by identity) property var _lastPlayedTime: ({}) - - // Track previous playing state per player to detect transitions - property var _wasPlaying: ({}) + property var _watchers: [] onPlayerChanged: { if (player) @@ -26,13 +21,11 @@ QtObject { } onPlayersChanged: { - // Try to find the previously selected player by identity if (_selectedIdentity) { const idx = players.findIndex(p => (p.identity ?? "") === _selectedIdentity); if (idx >= 0) { playerIdx = idx; } else { - // Selected player disappeared - switch to best alternative _switchToBest(); } } else if (playerIdx >= players.length) { @@ -40,46 +33,60 @@ QtObject { } } - // Poll playback states to detect transitions - Connections on dynamic - // targets get destroyed during list re-evaluation, losing the signal - property Timer _statePoll: Timer { - interval: 250 - running: root.players.length > 0 - repeat: true - onTriggered: root._checkStates() + // Watch raw Mpris.players for add/remove - this does NOT fire on state changes + property Connections _mprisConn: Connections { + target: Mpris + function onPlayersChanged() { + root._reconnectWatchers(); + } } - function _checkStates() { - const prevWas = _wasPlaying; - const nextWas = {}; + function _reconnectWatchers() { + for (const w of _watchers) + w.destroy(); - for (let i = 0; i < players.length; i++) { - const p = players[i]; - const identity = p.identity ?? ""; - const isPlaying = p.playbackState === MprisPlaybackState.Playing; - nextWas[identity] = isPlaying; + const raw = Mpris.players.values ?? []; + const newWatchers = []; + for (const p of raw) { + const conn = _watcherComp.createObject(root, { + target: p + }); + newWatchers.push(conn); + } + _watchers = newWatchers; + } - if (isPlaying && !prevWas[identity]) { - // This player just started playing - const times = Object.assign({}, _lastPlayedTime); - times[identity] = Date.now(); - _lastPlayedTime = times; + property Component _watcherComp: Component { + Connections { + function onPlaybackStateChanged() { + root._onPlaybackStateChanged(target); + } + } + } - // Always switch to the newly playing player - if (player !== p) { - playerIdx = i; + function _onPlaybackStateChanged(p) { + if (!p) + return; + + const identity = p.identity ?? ""; + + if (p.playbackState === MprisPlaybackState.Playing) { + const times = Object.assign({}, _lastPlayedTime); + times[identity] = Date.now(); + _lastPlayedTime = times; + + // Always switch to the newly playing player + if (player !== p) { + const idx = players.indexOf(p); + if (idx >= 0) { + playerIdx = idx; _selectedIdentity = identity; } } - } - - // Check if current player just paused - const curIdentity = player?.identity ?? ""; - if (prevWas[curIdentity] && !nextWas[curIdentity]) { + } else if (p.playbackState === MprisPlaybackState.Paused && p === player) { + // Current player paused - switch to a playing one if available _switchToPlaying(); } - - _wasPlaying = nextWas; } function _switchToPlaying() { @@ -132,4 +139,6 @@ QtObject { if (players[idx]) _selectedIdentity = players[idx].identity ?? ""; } + + Component.onCompleted: _reconnectWatchers() }