From 9d04b30629f86767aef3f4b6a8991f46f9e2f2ae Mon Sep 17 00:00:00 2001 From: Sem Date: Tue, 7 Apr 2026 23:48:02 +0200 Subject: [PATCH] add now playing info --- quickshell/services/NowPlayingService.qml | 43 +++++++++++++++++++++++ quickshell/shell.qml | 7 ++++ quickshell/ui/NowPlaying.qml | 33 +++++++++++++++++ quickshell/ui/TopBar.qml | 15 +++++++- 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 quickshell/services/NowPlayingService.qml create mode 100644 quickshell/ui/NowPlaying.qml diff --git a/quickshell/services/NowPlayingService.qml b/quickshell/services/NowPlayingService.qml new file mode 100644 index 0000000..ac7101a --- /dev/null +++ b/quickshell/services/NowPlayingService.qml @@ -0,0 +1,43 @@ +import Quickshell.Io +import QtQuick + +Item { + id: root + + property string artist: "" + property string title: "" + property string artUrl: "" + property bool isPlaying: false + + Process { + id: playerctlProc + // we need a separator, so use ||| + command: ["playerctl", "metadata", "--format", "{{artist}}|||{{title}}|||{{mpris:artUrl}}|||{{status}}"] + stdout: StdioCollector { + onStreamFinished: { + var text = this.text.trim(); + if (!text) { + root.artist = ""; + root.title = ""; + root.artUrl = ""; + root.isPlaying = false; + return; + } + var parts = text.split("|||"); + root.artist = parts[0] || ""; + root.title = parts[1] || ""; + root.artUrl = parts[2] || ""; + root.isPlaying = (parts[3] || "").trim() === "Playing"; + } + } + } + + Timer { + interval: 2000 + running: true + repeat: true + onTriggered: playerctlProc.running = true + } + + Component.onCompleted: playerctlProc.running = true +} diff --git a/quickshell/shell.qml b/quickshell/shell.qml index ee07192..f0f9174 100644 --- a/quickshell/shell.qml +++ b/quickshell/shell.qml @@ -18,6 +18,10 @@ ShellRoot { id: stats } + NowPlayingService { + id: nowPlayingService + } + Variants { model: Quickshell.screens @@ -49,6 +53,9 @@ ShellRoot { cpuUsage: stats.cpuUsage memUsage: stats.memUsage gpuUsage: stats.gpuUsage + nowPlayingArtist: nowPlayingService.artist + nowPlayingTitle: nowPlayingService.title + nowPlayingArtUrl: nowPlayingService.artUrl } } } diff --git a/quickshell/ui/NowPlaying.qml b/quickshell/ui/NowPlaying.qml new file mode 100644 index 0000000..85fc560 --- /dev/null +++ b/quickshell/ui/NowPlaying.qml @@ -0,0 +1,33 @@ + +import QtQuick +import QtQuick.Layouts + +import "../constants" + +Row { + id: root + + property string artist: "" + property string title: "" + property string artUrl: "" + + visible: title !== "" + spacing: 6 + + Image { + width: 18 + height: 18 + source: root.artUrl + fillMode: Image.PreserveAspectCrop + anchors.verticalCenter: parent.verticalCenter + } + + Text { + text: root.artist !== "" ? (root.artist + " - " + root.title) : root.title + color: Colors.md3.primary + font.family: Constants.fontFamily + font.pixelSize: Constants.fontSize + elide: Text.ElideRight + anchors.verticalCenter: parent.verticalCenter + } +} \ No newline at end of file diff --git a/quickshell/ui/TopBar.qml b/quickshell/ui/TopBar.qml index 2514792..1edcc4f 100644 --- a/quickshell/ui/TopBar.qml +++ b/quickshell/ui/TopBar.qml @@ -17,6 +17,9 @@ Item { property int cpuUsage: 0 property int memUsage: 0 property int gpuUsage: 0 + property string nowPlayingArtist: "" + property string nowPlayingTitle: "" + property string nowPlayingArtUrl: "" RowLayout { anchors.fill: parent @@ -32,12 +35,22 @@ Item { id: workspacesList } + // small spacer + Item { + anchors.leftMargin: 10 + } + + NowPlaying { + artist: root.nowPlayingArtist + title: root.nowPlayingTitle + artUrl: root.nowPlayingArtUrl + } + // Spacer Item { Layout.fillWidth: true } - // ===================== // RIGHT: System info // =====================