replace polling with signal-based mpris state tracking via raw player list
This commit is contained in:
parent
09c2de136c
commit
0ca190a4a6
1 changed files with 47 additions and 38 deletions
|
|
@ -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();
|
||||
|
||||
const raw = Mpris.players.values ?? [];
|
||||
const newWatchers = [];
|
||||
for (const p of raw) {
|
||||
const conn = _watcherComp.createObject(root, {
|
||||
target: p
|
||||
});
|
||||
newWatchers.push(conn);
|
||||
}
|
||||
_watchers = newWatchers;
|
||||
}
|
||||
|
||||
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 isPlaying = p.playbackState === MprisPlaybackState.Playing;
|
||||
nextWas[identity] = isPlaying;
|
||||
|
||||
if (isPlaying && !prevWas[identity]) {
|
||||
// This player just started playing
|
||||
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) {
|
||||
playerIdx = i;
|
||||
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()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue