Krolyxon
Commit 85941a2

Branches

Refs →

aurora.configquickshellwal-controlMediaCard.qml

152 lines · 5.0 KB · QML

1import QtQuick
2import QtQuick.Layouts
3import Quickshell.Services.Mpris
4
5Rectangle {
6 id: card
7
8 function pick() {
9 var l = Mpris.players.values, first = null
10 for (var i = 0; i < l.length; i++) {
11 if (l[i].isPlaying) return l[i]
12 if (first === null) first = l[i]
13 }
14 return first
15 }
16 function fmt(s) {
17 s = Math.max(0, Math.floor(s))
18 var m = Math.floor(s / 60), r = s % 60
19 return m + ":" + (r < 10 ? "0" : "") + r
20 }
21
22 readonly property var player: pick()
23 readonly property bool has: player !== null
24 readonly property bool seekable: has && player.lengthSupported && player.length > 0
25
26 implicitHeight: has ? (seekable ? 156 : 122) : 56
27 color: Theme.surface
28 border.width: 1
29 border.color: Theme.line
30
31 // MPRIS doesn't push position updates, so poke it while playing
32 Timer {
33 running: card.has && card.player.isPlaying && card.visible
34 interval: 500
35 repeat: true
36 onTriggered: card.player.positionChanged()
37 }
38
39 Text {
40 visible: !card.has
41 anchors.centerIn: parent
42 text: Theme.iMusic + " nothing playing"
43 color: Theme.dim
44 font.family: Theme.font
45 font.pixelSize: Theme.fontSize
46 }
47
48 ColumnLayout {
49 visible: card.has
50 anchors.fill: parent
51 anchors.margins: 10
52 spacing: 6
53
54 RowLayout {
55 spacing: 10
56 Rectangle {
57 Layout.preferredWidth: 60
58 Layout.preferredHeight: 60
59 color: Theme.surfaceHi
60 Text {
61 anchors.centerIn: parent
62 text: Theme.iMusic
63 color: Theme.dim
64 font.family: Theme.font
65 font.pixelSize: 24
66 }
67 Image {
68 id: art
69 anchors.fill: parent
70 source: card.has ? card.player.trackArtUrl : ""
71 fillMode: Image.PreserveAspectCrop
72 asynchronous: true
73 visible: status === Image.Ready
74 }
75 }
76 ColumnLayout {
77 Layout.fillWidth: true
78 spacing: 2
79 Text {
80 Layout.fillWidth: true
81 elide: Text.ElideRight
82 text: card.has ? (card.player.trackTitle || "unknown title") : ""
83 color: Theme.fg
84 font.family: Theme.font
85 font.pixelSize: Theme.fontSize + 1
86 font.bold: true
87 }
88 Text {
89 Layout.fillWidth: true
90 elide: Text.ElideRight
91 text: card.has ? (card.player.trackArtist || "unknown artist") : ""
92 color: Theme.accent
93 font.family: Theme.font
94 font.pixelSize: Theme.fontSize
95 }
96 Text {
97 Layout.fillWidth: true
98 elide: Text.ElideRight
99 text: card.has ? ((card.player.trackAlbum ? card.player.trackAlbum + " · " : "") + card.player.identity) : ""
100 color: Theme.dim
101 font.family: Theme.font
102 font.pixelSize: Theme.fontSize - 2
103 }
104 }
105 }
106
107 RowLayout {
108 visible: card.seekable
109 spacing: 8
110 Text {
111 text: card.seekable ? card.fmt(card.player.position) : ""
112 color: Theme.dim
113 font.family: Theme.font
114 font.pixelSize: Theme.fontSize - 2
115 }
116 BarSlider {
117 Layout.fillWidth: true
118 from: 0
119 to: card.seekable ? card.player.length : 1
120 value: card.seekable ? card.player.position : 0
121 onMoved: v => { if (card.player.canSeek) card.player.position = v }
122 }
123 Text {
124 text: card.seekable ? card.fmt(card.player.length) : ""
125 color: Theme.dim
126 font.family: Theme.font
127 font.pixelSize: Theme.fontSize - 2
128 }
129 }
130
131 RowLayout {
132 Layout.alignment: Qt.AlignHCenter
133 spacing: 8
134 IconBtn {
135 icon: Theme.iPrev
136 opacity: card.has && card.player.canGoPrevious ? 1 : 0.4
137 onClicked: if (card.player.canGoPrevious) card.player.previous()
138 }
139 IconBtn {
140 icon: card.has && card.player.isPlaying ? Theme.iPause : Theme.iPlay
141 active: true
142 implicitWidth: 44
143 onClicked: if (card.player.canTogglePlaying) card.player.togglePlaying()
144 }
145 IconBtn {
146 icon: Theme.iNext
147 opacity: card.has && card.player.canGoNext ? 1 : 0.4
148 onClicked: if (card.player.canGoNext) card.player.next()
149 }
150 }
151 }
152}