fix mpris state detection: replace dynamic Connections with state polling

This commit is contained in:
Damocles 2026-04-18 13:25:15 +02:00
parent 381ceaa642
commit 09c2de136c

View file

@ -17,6 +17,9 @@ QtObject {
// Track which player played most recently (by identity) // Track which player played most recently (by identity)
property var _lastPlayedTime: ({}) property var _lastPlayedTime: ({})
// Track previous playing state per player to detect transitions
property var _wasPlaying: ({})
onPlayerChanged: { onPlayerChanged: {
if (player) if (player)
_selectedIdentity = player.identity ?? ""; _selectedIdentity = player.identity ?? "";
@ -28,83 +31,58 @@ QtObject {
const idx = players.findIndex(p => (p.identity ?? "") === _selectedIdentity); const idx = players.findIndex(p => (p.identity ?? "") === _selectedIdentity);
if (idx >= 0) { if (idx >= 0) {
playerIdx = idx; playerIdx = idx;
return; } else {
}
// Selected player disappeared - switch to best alternative // Selected player disappeared - switch to best alternative
_switchToBest(); _switchToBest();
}
} else if (playerIdx >= players.length) { } else if (playerIdx >= players.length) {
playerIdx = 0; playerIdx = 0;
} }
} }
// Watch playback state changes on all players // Poll playback states to detect transitions - Connections on dynamic
property Connections _mprisConn: Connections { // targets get destroyed during list re-evaluation, losing the signal
target: Mpris property Timer _statePoll: Timer {
interval: 250
function onPlayersChanged() { running: root.players.length > 0
// Re-evaluate when the global player list changes repeat: true
Qt.callLater(_reconnectWatchers); onTriggered: root._checkStates()
}
} }
property var _watchedPlayers: [] function _checkStates() {
const prevWas = _wasPlaying;
function _reconnectWatchers() { const nextWas = {};
// Clean up old watchers
for (const w of _watchedPlayers) {
if (w.conn)
w.conn.destroy();
}
_watchedPlayers = [];
// Watch each player's playback state
for (const p of players) {
const conn = _watcherComp.createObject(root, {
target: p
});
_watchedPlayers.push({
player: p,
conn: conn
});
}
}
property Component _watcherComp: Component {
Connections {
function onPlaybackStateChanged() {
root._onPlaybackStateChanged(target);
}
}
}
function _onPlaybackStateChanged(p) {
if (!p)
return;
for (let i = 0; i < players.length; i++) {
const p = players[i];
const identity = p.identity ?? ""; const identity = p.identity ?? "";
const isPlaying = p.playbackState === MprisPlaybackState.Playing;
nextWas[identity] = isPlaying;
if (p.playbackState === MprisPlaybackState.Playing) { if (isPlaying && !prevWas[identity]) {
// Record this as the most recently playing // This player just started playing
const times = Object.assign({}, _lastPlayedTime); const times = Object.assign({}, _lastPlayedTime);
times[identity] = Date.now(); times[identity] = Date.now();
_lastPlayedTime = times; _lastPlayedTime = times;
// Always switch to the newly playing player // Always switch to the newly playing player
if (player !== p) { if (player !== p) {
const idx = players.indexOf(p); playerIdx = i;
if (idx >= 0) {
playerIdx = idx;
_selectedIdentity = identity; _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(); _switchToPlaying();
} }
_wasPlaying = nextWas;
} }
function _switchToPlaying() { function _switchToPlaying() {
// Find a playing player, prefer most recently started
let best = -1; let best = -1;
let bestTime = 0; let bestTime = 0;
for (let i = 0; i < players.length; i++) { for (let i = 0; i < players.length; i++) {
@ -123,7 +101,6 @@ QtObject {
} }
function _switchToBest() { function _switchToBest() {
// Switch to playing player, or most recently played
let best = -1; let best = -1;
let bestTime = 0; let bestTime = 0;
let bestPlaying = -1; let bestPlaying = -1;
@ -155,6 +132,4 @@ QtObject {
if (players[idx]) if (players[idx])
_selectedIdentity = players[idx].identity ?? ""; _selectedIdentity = players[idx].identity ?? "";
} }
Component.onCompleted: Qt.callLater(_reconnectWatchers)
} }