pragma Singleton import Quickshell import Quickshell.Io import Quickshell.Services.Mpris Singleton { readonly property list activePlayers: Mpris.players.values readonly property var meaningfulPlayers: filterDuplicatePlayers(activePlayers) readonly property bool hasPlayers: meaningfulPlayers.length > 0 property int playerIndex: 0 function activePlayer() { if (!hasPlayers) { return null; } assertIndex(); return meaningfulPlayers[playerIndex]; } function shiftPlayer(shift) { playerIndex = (playerIndex + shift + activePlayers.length) % activePlayers.length } function assertIndex() { if (playerIndex < 0 || playerIndex >= meaningfulPlayers.length) { playerIndex = (playerIndex + activePlayers.length) % activePlayers.length } } function filterDuplicatePlayers(players) { let filtered = []; let used = new Set(); for (let i = 0; i < players.length; ++i) { if (used.has(i)) { continue; } let p1 = players[i]; let group = [i]; // find duplicates for (let j = i + 1; j < players.length; ++j) { let p2 = players[j]; if (p1.trackTitle && p2.trackTitle && ( p1.trackTitle.includes(p2.trackTitle) || p2.trackTitle.includes(p1.trackTitle) || (p1.position - p2.position <= 2 && p1.length - p2.length <= 2) )) { group.push(j); } } // pick with non-empty trackArtUrl let chosenIdx = group.find(idx => players[idx].trackArtUrl && players[idx].trackArtUrl.length > 0); if (chosenIdx === undefined) { chosenIdx = group[0]; } filtered.push(players[chosenIdx]); group.forEach(idx => used.add(idx)); } return filtered; } }