added quickshell
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Services.Mpris
|
||||
|
||||
// MPRIS. Prefers whichever player is actually playing, falling back to the last
|
||||
// one that was, so the bar does not flip between Spotify and a stray browser tab.
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property string preferredId: ""
|
||||
|
||||
readonly property var players: Mpris.players?.values ?? []
|
||||
readonly property bool hasPlayer: active !== null
|
||||
|
||||
readonly property MprisPlayer active: {
|
||||
if (players.length === 0) return null;
|
||||
|
||||
// An explicit pick wins, while it still exists.
|
||||
if (root.preferredId !== "") {
|
||||
for (const p of players) if (p.dbusName === root.preferredId) return p;
|
||||
}
|
||||
for (const p of players) if (p.isPlaying) return p;
|
||||
return players[0];
|
||||
}
|
||||
|
||||
readonly property string title: active?.trackTitle || ""
|
||||
readonly property string artist: active?.trackArtist || ""
|
||||
readonly property string album: active?.trackAlbum || ""
|
||||
readonly property string artUrl: active?.trackArtUrl || ""
|
||||
readonly property string identity: active?.identity || ""
|
||||
readonly property bool playing: active?.isPlaying ?? false
|
||||
|
||||
readonly property bool canGoNext: active?.canGoNext ?? false
|
||||
readonly property bool canGoPrevious: active?.canGoPrevious ?? false
|
||||
readonly property bool canSeek: (active?.canSeek ?? false) && (active?.lengthSupported ?? false)
|
||||
|
||||
readonly property real length: active?.lengthSupported ? (active?.length ?? 0) : 0
|
||||
readonly property real position: active?.positionSupported ? (active?.position ?? 0) : 0
|
||||
readonly property real progress: length > 0 ? Math.min(1, position / length) : 0
|
||||
|
||||
readonly property string label: {
|
||||
if (!hasPlayer) return "Nothing playing";
|
||||
if (title === "") return identity || "Unknown track";
|
||||
if (artist === "") return title;
|
||||
return artist + " — " + title;
|
||||
}
|
||||
|
||||
signal trackChanged()
|
||||
|
||||
onTitleChanged: trackChanged()
|
||||
|
||||
// MPRIS position is pull-only; tick it so the seek bar moves.
|
||||
Timer {
|
||||
interval: 500
|
||||
running: root.playing && root.canSeek
|
||||
repeat: true
|
||||
onTriggered: if (root.active) root.active.positionChanged()
|
||||
}
|
||||
|
||||
function playPause() { if (active?.canTogglePlaying) active.togglePlaying(); }
|
||||
function next() { if (canGoNext) active.next(); }
|
||||
function previous() { if (canGoPrevious) active.previous(); }
|
||||
function seekTo(fraction: real) {
|
||||
if (!canSeek || length <= 0) return;
|
||||
active.position = Math.max(0, Math.min(length, fraction * length));
|
||||
}
|
||||
function raise() { if (active?.canRaise) active.raise(); }
|
||||
|
||||
function select(player: MprisPlayer) {
|
||||
root.preferredId = player ? player.dbusName : "";
|
||||
}
|
||||
|
||||
// Nerd Font glyph for the source app, so the bar reads at a glance.
|
||||
readonly property string sourceIcon: {
|
||||
const id = (identity || "").toLowerCase();
|
||||
if (id.includes("spotify")) return "";
|
||||
if (id.includes("firefox")) return "";
|
||||
if (id.includes("chrom") || id.includes("brave")) return "";
|
||||
if (id.includes("mpv")) return "";
|
||||
if (id.includes("vlc")) return "";
|
||||
if (id.includes("jellyfin")) return "";
|
||||
if (id.includes("youtube")) return "";
|
||||
return "";
|
||||
}
|
||||
|
||||
function timeString(micros: real): string {
|
||||
if (!(micros > 0)) return "0:00";
|
||||
const total = Math.floor(micros / 1000000);
|
||||
const m = Math.floor(total / 60);
|
||||
const s = total % 60;
|
||||
if (m >= 60) {
|
||||
const h = Math.floor(m / 60);
|
||||
return h + ":" + String(m % 60).padStart(2, "0") + ":" + String(s).padStart(2, "0");
|
||||
}
|
||||
return m + ":" + String(s).padStart(2, "0");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user