fix mpris state detection: replace dynamic Connections with state polling
This commit is contained in:
parent
381ceaa642
commit
09c2de136c
1 changed files with 36 additions and 61 deletions
|
|
@ -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
|
||||||
|
_switchToBest();
|
||||||
}
|
}
|
||||||
// Selected player disappeared - switch to best alternative
|
|
||||||
_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;
|
||||||
|
const nextWas = {};
|
||||||
|
|
||||||
function _reconnectWatchers() {
|
for (let i = 0; i < players.length; i++) {
|
||||||
// Clean up old watchers
|
const p = players[i];
|
||||||
for (const w of _watchedPlayers) {
|
const identity = p.identity ?? "";
|
||||||
if (w.conn)
|
const isPlaying = p.playbackState === MprisPlaybackState.Playing;
|
||||||
w.conn.destroy();
|
nextWas[identity] = isPlaying;
|
||||||
}
|
|
||||||
_watchedPlayers = [];
|
|
||||||
|
|
||||||
// Watch each player's playback state
|
if (isPlaying && !prevWas[identity]) {
|
||||||
for (const p of players) {
|
// This player just started playing
|
||||||
const conn = _watcherComp.createObject(root, {
|
const times = Object.assign({}, _lastPlayedTime);
|
||||||
target: p
|
times[identity] = Date.now();
|
||||||
});
|
_lastPlayedTime = times;
|
||||||
_watchedPlayers.push({
|
|
||||||
player: p,
|
|
||||||
conn: conn
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property Component _watcherComp: Component {
|
// Always switch to the newly playing player
|
||||||
Connections {
|
if (player !== p) {
|
||||||
function onPlaybackStateChanged() {
|
playerIdx = i;
|
||||||
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;
|
|
||||||
_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)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue