aboutsummaryrefslogtreecommitdiffstats
path: root/volume-osd/Player.qml
diff options
context:
space:
mode:
Diffstat (limited to 'volume-osd/Player.qml')
-rw-r--r--volume-osd/Player.qml48
1 files changed, 48 insertions, 0 deletions
diff --git a/volume-osd/Player.qml b/volume-osd/Player.qml
new file mode 100644
index 0000000..73f86af
--- /dev/null
+++ b/volume-osd/Player.qml
@@ -0,0 +1,48 @@
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+pragma Singleton
+
+import Quickshell
+import Quickshell.Services.Mpris
+import QtQuick
+
+// Which MPRIS player the OSD should describe.
+Singleton {
+ id: root
+
+ // playerctld proxies whatever is playing and publishes it under its own
+ // name, so every real player shows up twice. Its own entry is skipped:
+ // controlling the player directly works whether or not playerctld is up.
+ readonly property var real:
+ Mpris.players.values.filter(p => !p.dbusName.endsWith(".playerctld"))
+
+ // Prefer something actually playing; otherwise keep the last one seen, so
+ // pausing does not make the track row vanish mid-look.
+ readonly property var current:
+ real.find(p => p.playbackState === MprisPlaybackState.Playing)
+ ?? real.find(p => p.playbackState === MprisPlaybackState.Paused)
+ ?? real[0]
+ ?? null
+
+ readonly property bool active: current !== null
+ readonly property bool playing: current?.playbackState === MprisPlaybackState.Playing
+
+ readonly property string title: current?.trackTitle ?? ""
+ readonly property string artist: current?.trackArtist ?? ""
+
+ // Players that extract embedded art write it to a temp file they reuse
+ // per track, so the path can repeat while the image behind it changes.
+ // The cache buster makes Image reload instead of showing the last cover.
+ readonly property string artUrl:
+ (current?.trackArtUrl ?? "") === "" ? ""
+ : current.trackArtUrl + "#" + encodeURIComponent(title)
+}