diff --git a/shell/services/MprisService.qml b/shell/services/MprisService.qml index 5c3ea0a..b4eeff2 100644 --- a/shell/services/MprisService.qml +++ b/shell/services/MprisService.qml @@ -17,6 +17,9 @@ QtObject { // Track which player played most recently (by identity) property var _lastPlayedTime: ({}) + // Track previous playing state per player to detect transitions + property var _wasPlaying: ({}) + onPlayerChanged: { if (player) _selectedIdentity = player.identity ?? ""; @@ -28,83 +31,58 @@ QtObject { const idx = players.findIndex(p => (p.identity ?? "") === _selectedIdentity); if (idx >= 0) { playerIdx = idx; - return; + } else { + // Selected player disappeared - switch to best alternative + _switchToBest(); } - // Selected player disappeared - switch to best alternative - _switchToBest(); } else if (playerIdx >= players.length) { playerIdx = 0; } } - // Watch playback state changes on all players - property Connections _mprisConn: Connections { - target: Mpris - - function onPlayersChanged() { - // Re-evaluate when the global player list changes - Qt.callLater(_reconnectWatchers); - } + // 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() } - property var _watchedPlayers: [] + function _checkStates() { + const prevWas = _wasPlaying; + const nextWas = {}; - function _reconnectWatchers() { - // Clean up old watchers - for (const w of _watchedPlayers) { - if (w.conn) - w.conn.destroy(); - } - _watchedPlayers = []; + 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; - // Watch each player's playback state - for (const p of players) { - const conn = _watcherComp.createObject(root, { - target: p - }); - _watchedPlayers.push({ - player: p, - conn: conn - }); - } - } + 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); - } - } - } - - function _onPlaybackStateChanged(p) { - if (!p) - return; - - const identity = p.identity ?? ""; - - if (p.playbackState === MprisPlaybackState.Playing) { - // Record this as the most recently 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; + // Always switch to the newly playing player + if (player !== p) { + playerIdx = i; _selectedIdentity = identity; } } - } else if (p.playbackState === MprisPlaybackState.Paused && p === player) { - // Current player paused - switch to a playing one if available + } + + // Check if current player just paused + const curIdentity = player?.identity ?? ""; + if (prevWas[curIdentity] && !nextWas[curIdentity]) { _switchToPlaying(); } + + _wasPlaying = nextWas; } function _switchToPlaying() { - // Find a playing player, prefer most recently started let best = -1; let bestTime = 0; for (let i = 0; i < players.length; i++) { @@ -123,7 +101,6 @@ QtObject { } function _switchToBest() { - // Switch to playing player, or most recently played let best = -1; let bestTime = 0; let bestPlaying = -1; @@ -155,6 +132,4 @@ QtObject { if (players[idx]) _selectedIdentity = players[idx].identity ?? ""; } - - Component.onCompleted: Qt.callLater(_reconnectWatchers) }