Regenerated
This commit is contained in:
+747
-341
File diff suppressed because it is too large
Load Diff
+405
-13
@@ -2619,6 +2619,7 @@ windowrule {
|
||||
size = 900 700
|
||||
}
|
||||
|
||||
#Quickshell powermenu
|
||||
windowrule {
|
||||
name = quickshell-powermenu
|
||||
match:title = quickshell-powermenu
|
||||
@@ -2628,6 +2629,15 @@ windowrule {
|
||||
pin = on
|
||||
}
|
||||
|
||||
#Quickshell media menu
|
||||
windowrule {
|
||||
name = quickshell-media
|
||||
match:title = quickshell-media
|
||||
float = on
|
||||
move = cursor -50% 0
|
||||
pin = on
|
||||
}
|
||||
|
||||
#+END_SRC
|
||||
|
||||
** =generated/.config/hypr/workspace-rules.conf=
|
||||
@@ -2651,8 +2661,313 @@ workspace = 9
|
||||
workspace = 10
|
||||
#+END_SRC
|
||||
|
||||
** =generated/.config/quickshell/media/shell.qml=
|
||||
offers a adio widget
|
||||
#+BEGIN_SRC qml :tangle generated/.config/quickshell/media/shell.qml :noweb yes :mkdirp yes :eval never
|
||||
// --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ShellRoot {
|
||||
QtObject {
|
||||
id: colors
|
||||
readonly property color baseAlpha: Qt.rgba(30/255, 30/255, 46/255, 0.95)
|
||||
readonly property color base: "#1e1e2e"
|
||||
readonly property color surface0: "#313244"
|
||||
readonly property color surface1: "#45475a"
|
||||
readonly property color surface2: "#585b70"
|
||||
readonly property color text: "#cdd6f4"
|
||||
readonly property color subtext0: "#a6adc8"
|
||||
readonly property color subtext1: "#bac2de"
|
||||
readonly property color blue: "#89b4fa"
|
||||
readonly property color green: "#a6e3a1"
|
||||
readonly property color teal: "#94e2d5"
|
||||
readonly property color red: "#f38ba8"
|
||||
readonly property color mauve: "#cba6f7"
|
||||
readonly property color peach: "#fab387"
|
||||
readonly property color lavender: "#b4befe"
|
||||
}
|
||||
|
||||
// State
|
||||
QtObject {
|
||||
id: media
|
||||
property string artist: ""
|
||||
property string title: ""
|
||||
property string album: ""
|
||||
property string artUrl: ""
|
||||
property string status: ""
|
||||
property string device: ""
|
||||
property real progress: 0.0
|
||||
property real duration: 0.0
|
||||
property real position: 0.0
|
||||
}
|
||||
|
||||
// Poll playerctl every second
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
artistProc.running = true
|
||||
titleProc.running = true
|
||||
albumProc.running = true
|
||||
artProc.running = true
|
||||
statusProc.running = true
|
||||
positionProc.running = true
|
||||
lengthProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: artistProc
|
||||
command: ["playerctl", "metadata", "artist"]
|
||||
stdout: StdioCollector { onStreamFinished: media.artist = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: titleProc
|
||||
command: ["playerctl", "metadata", "title"]
|
||||
stdout: StdioCollector { onStreamFinished: media.title = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: albumProc
|
||||
command: ["playerctl", "metadata", "album"]
|
||||
stdout: StdioCollector { onStreamFinished: media.album = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: artProc
|
||||
command: ["playerctl", "metadata", "mpris:artUrl"]
|
||||
stdout: StdioCollector { onStreamFinished: media.artUrl = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: statusProc
|
||||
command: ["playerctl", "status"]
|
||||
stdout: StdioCollector { onStreamFinished: media.status = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: positionProc
|
||||
command: ["playerctl", "position"]
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
media.position = parseFloat(text.trim()) || 0
|
||||
if (media.duration > 0)
|
||||
media.progress = media.position / media.duration
|
||||
}
|
||||
}
|
||||
}
|
||||
Process {
|
||||
id: lengthProc
|
||||
command: ["playerctl", "metadata", "mpris:length"]
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
media.duration = (parseFloat(text.trim()) || 0) / 1000000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
Process { id: prevProc; command: ["playerctl", "previous"] }
|
||||
Process { id: playProc; command: ["playerctl", "play-pause"] }
|
||||
Process { id: nextProc; command: ["playerctl", "next"] }
|
||||
|
||||
FloatingWindow {
|
||||
id: root
|
||||
title: "quickshell-media"
|
||||
visible: true
|
||||
width: 300
|
||||
height: 420
|
||||
color: "transparent"
|
||||
|
||||
Shortcut {
|
||||
sequence: "Escape"
|
||||
onActivated: Qt.quit()
|
||||
}
|
||||
|
||||
// Gradient border
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -2
|
||||
radius: 18
|
||||
z: -1
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: colors.blue }
|
||||
GradientStop { position: 1.0; color: colors.green }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 16
|
||||
color: colors.base
|
||||
|
||||
ColumnLayout {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: 16
|
||||
}
|
||||
spacing: 12
|
||||
|
||||
// Album art
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 200
|
||||
radius: 12
|
||||
color: colors.surface0
|
||||
clip: true
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: media.artUrl
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: media.artUrl !== ""
|
||||
}
|
||||
|
||||
// Placeholder when no art
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: ""
|
||||
font.pixelSize: 48
|
||||
color: colors.surface2
|
||||
visible: media.artUrl === ""
|
||||
}
|
||||
}
|
||||
|
||||
// Artist
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: media.artist || "Unknown artist"
|
||||
color: colors.subtext1
|
||||
font.pixelSize: 12
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Title
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: media.title || "Nothing playing"
|
||||
color: colors.text
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Album
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: media.album
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 11
|
||||
elide: Text.ElideRight
|
||||
visible: media.album !== ""
|
||||
}
|
||||
|
||||
// Device (Spotify)
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: " " + media.device
|
||||
color: colors.green
|
||||
font.pixelSize: 11
|
||||
visible: media.device !== ""
|
||||
}
|
||||
|
||||
// Progress bar
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 4
|
||||
radius: 2
|
||||
color: colors.surface1
|
||||
|
||||
Rectangle {
|
||||
width: parent.width * media.progress
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: colors.blue }
|
||||
GradientStop { position: 1.0; color: colors.green }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Time
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text {
|
||||
text: {
|
||||
var m = Math.floor(media.position / 60)
|
||||
var s = Math.floor(media.position % 60)
|
||||
return m + ":" + (s < 10 ? "0" + s : s)
|
||||
}
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 11
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Text {
|
||||
text: {
|
||||
var m = Math.floor(media.duration / 60)
|
||||
var s = Math.floor(media.duration % 60)
|
||||
return m + ":" + (s < 10 ? "0" + s : s)
|
||||
}
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 24
|
||||
|
||||
Text {
|
||||
text: ""
|
||||
font.pixelSize: 22
|
||||
color: prevHover.containsMouse ? colors.blue : colors.text
|
||||
MouseArea {
|
||||
id: prevHover
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: prevProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: media.status === "Playing" ? "" : ""
|
||||
font.pixelSize: 28
|
||||
color: playHover.containsMouse ? colors.green : colors.text
|
||||
MouseArea {
|
||||
id: playHover
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: playProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: ""
|
||||
font.pixelSize: 22
|
||||
color: nextHover.containsMouse ? colors.blue : colors.text
|
||||
MouseArea {
|
||||
id: nextHover
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: nextProc.running = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
** =generated/.config/quickshell/powermenu/shell.qml=
|
||||
This sets up the zsh in the terminal
|
||||
Provides a powermenu
|
||||
#+BEGIN_SRC qml :tangle generated/.config/quickshell/powermenu/shell.qml :noweb yes :mkdirp yes :eval never
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
@@ -2730,12 +3045,12 @@ ShellRoot {
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
{ label: " Lock", cmd: ["loginctl", "lock-session"] },
|
||||
{ label: " Shutdown", cmd: ["systemctl", "poweroff"] },
|
||||
{ label: " Reboot", cmd: ["systemctl", "reboot"] },
|
||||
{ label: " Logout", cmd: ["bash", "-c", "loginctl terminate-session $XDG_SESSION_ID"] },
|
||||
{ label: " Hibernate", cmd: ["systemctl", "hibernate"] },
|
||||
{ label: " Suspend", cmd: ["systemctl", "suspend"] },
|
||||
{ label: " Lock", cmd: ["loginctl", "lock-session"] },
|
||||
{ label: " Shutdown", cmd: ["systemctl", "poweroff"] },
|
||||
{ label: " Reboot", cmd: ["systemctl", "reboot"] },
|
||||
{ label: " Logout", cmd: ["bash", "-c", "loginctl terminate-session $XDG_SESSION_ID"] },
|
||||
{ label: " Hibernate", cmd: ["systemctl", "hibernate"] },
|
||||
{ label: " Suspend", cmd: ["systemctl", "suspend"] },
|
||||
]
|
||||
|
||||
delegate: Rectangle {
|
||||
@@ -2791,6 +3106,72 @@ ShellRoot {
|
||||
}
|
||||
#+END_SRC
|
||||
|
||||
** =generated/.config/scripts/media.sh=
|
||||
Providing an media
|
||||
#+BEGIN_SRC sh :tangle generated/.config/scripts/media.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
|
||||
#!/usr/bin/env bash
|
||||
player=$(playerctl -l 2>/dev/null | head -n1)
|
||||
|
||||
if [ -z "$player" ]; then
|
||||
jq -c -n '{text: "", tooltip: "", class: "inactive"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
status=$(playerctl --player="$player" status 2>/dev/null)
|
||||
|
||||
if [ "$status" != "Playing" ] && [ "$status" != "Paused" ]; then
|
||||
jq -c -n '{text: "", tooltip: "", class: "inactive"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
artist=$(playerctl --player="$player" metadata artist 2>/dev/null)
|
||||
title=$(playerctl --player="$player" metadata title 2>/dev/null)
|
||||
album=$(playerctl --player="$player" metadata album 2>/dev/null)
|
||||
art=$(playerctl --player="$player" metadata mpris:artUrl 2>/dev/null)
|
||||
length=$(playerctl --player="$player" metadata mpris:length 2>/dev/null)
|
||||
position=$(playerctl --player="$player" position 2>/dev/null)
|
||||
|
||||
# Progress percentage
|
||||
if [ -n "$length" ] && [ "$length" -gt 0 ] 2>/dev/null; then
|
||||
progress=$(echo "scale=0; $position * 1000000 / $length * 100 / 100" | bc)
|
||||
else
|
||||
progress=0
|
||||
fi
|
||||
|
||||
# Spotify device
|
||||
device=""
|
||||
if [[ "$player" == *"spotify"* ]]; then
|
||||
device=$(playerctl --player="$player" metadata xesam:url 2>/dev/null | grep -o 'device=[^&]*' | cut -d= -f2)
|
||||
fi
|
||||
|
||||
# Ticker text — truncate if long
|
||||
text="${artist} — ${title}"
|
||||
if [ ${#text} -gt 40 ]; then
|
||||
text="${text:0:37}..."
|
||||
fi
|
||||
|
||||
# Icon
|
||||
if [ "$status" = "Paused" ]; then
|
||||
icon="⏸ "
|
||||
else
|
||||
icon="▶ "
|
||||
fi
|
||||
|
||||
# Build tooltip
|
||||
tooltip="${artist}\n${title}\n${album}"
|
||||
if [ -n "$device" ]; then
|
||||
tooltip="${tooltip}\n ${device}"
|
||||
fi
|
||||
tooltip="${tooltip}\n$(printf '%.0f' "$progress")%"
|
||||
|
||||
jq -c -n \
|
||||
--arg text "${icon}${text}" \
|
||||
--arg tooltip "$tooltip" \
|
||||
--arg class "$player" \
|
||||
--arg art "$art" \
|
||||
'{text: $text, tooltip: $tooltip, class: $class, alt: $art}'
|
||||
#+END_SRC
|
||||
|
||||
** =generated/.config/scripts/layout-selector.sh=
|
||||
Choose your layout
|
||||
#+BEGIN_SRC bash :tangle generated/.config/scripts/layout-selector.sh :shebang "#!/usr/bin/env bash" :noweb yes :mkdirp yes :eval never
|
||||
@@ -2895,12 +3276,12 @@ A file containing color variables
|
||||
|
||||
main() {
|
||||
local list=(
|
||||
"Lock"
|
||||
"Shutdown"
|
||||
"Reboot"
|
||||
"Logout"
|
||||
"Hibernate"
|
||||
"Suspend"
|
||||
" Lock"
|
||||
" Shutdown"
|
||||
" Reboot"
|
||||
" Logout"
|
||||
" Hibernate"
|
||||
" Suspend"
|
||||
)
|
||||
|
||||
local options=(
|
||||
@@ -3490,6 +3871,7 @@ These are config files for waybar
|
||||
"group/audio": {
|
||||
"orientation": "horizontal",
|
||||
"modules": [
|
||||
"custom/media",
|
||||
"pulseaudio",
|
||||
"pulseaudio/slider",
|
||||
]
|
||||
@@ -3514,6 +3896,16 @@ These are config files for waybar
|
||||
"tooltip": true
|
||||
},
|
||||
|
||||
"custom/media": {
|
||||
"exec": "~/.config/scripts/media.sh",
|
||||
"interval": 2,
|
||||
"return-type": "json",
|
||||
"on-click": "qs -c media",
|
||||
"max-length": 40,
|
||||
"scroll-step": 1,
|
||||
"tooltip": true
|
||||
}
|
||||
|
||||
"custom/bluetooth": {
|
||||
"exec": "~/.config/scripts/bluetooth-status.sh",
|
||||
"interval": 5,
|
||||
|
||||
@@ -28,6 +28,7 @@ windowrule {
|
||||
size = 900 700
|
||||
}
|
||||
|
||||
#Quickshell powermenu
|
||||
windowrule {
|
||||
name = quickshell-powermenu
|
||||
match:title = quickshell-powermenu
|
||||
@@ -36,3 +37,12 @@ windowrule {
|
||||
move = cursor -50% 0
|
||||
pin = on
|
||||
}
|
||||
|
||||
#Quickshell media menu
|
||||
windowrule {
|
||||
name = quickshell-media
|
||||
match:title = quickshell-media
|
||||
float = on
|
||||
move = cursor -50% 0
|
||||
pin = on
|
||||
}
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
// --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---
|
||||
// --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
|
||||
ShellRoot {
|
||||
QtObject {
|
||||
id: colors
|
||||
readonly property color baseAlpha: Qt.rgba(30/255, 30/255, 46/255, 0.95)
|
||||
readonly property color base: "#1e1e2e"
|
||||
readonly property color surface0: "#313244"
|
||||
readonly property color surface1: "#45475a"
|
||||
readonly property color surface2: "#585b70"
|
||||
readonly property color text: "#cdd6f4"
|
||||
readonly property color subtext0: "#a6adc8"
|
||||
readonly property color subtext1: "#bac2de"
|
||||
readonly property color blue: "#89b4fa"
|
||||
readonly property color green: "#a6e3a1"
|
||||
readonly property color teal: "#94e2d5"
|
||||
readonly property color red: "#f38ba8"
|
||||
readonly property color mauve: "#cba6f7"
|
||||
readonly property color peach: "#fab387"
|
||||
readonly property color lavender: "#b4befe"
|
||||
}
|
||||
|
||||
// State
|
||||
QtObject {
|
||||
id: media
|
||||
property string artist: ""
|
||||
property string title: ""
|
||||
property string album: ""
|
||||
property string artUrl: ""
|
||||
property string status: ""
|
||||
property string device: ""
|
||||
property real progress: 0.0
|
||||
property real duration: 0.0
|
||||
property real position: 0.0
|
||||
}
|
||||
|
||||
// Poll playerctl every second
|
||||
Timer {
|
||||
interval: 1000
|
||||
running: true
|
||||
repeat: true
|
||||
onTriggered: {
|
||||
artistProc.running = true
|
||||
titleProc.running = true
|
||||
albumProc.running = true
|
||||
artProc.running = true
|
||||
statusProc.running = true
|
||||
positionProc.running = true
|
||||
lengthProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
Process {
|
||||
id: artistProc
|
||||
command: ["playerctl", "metadata", "artist"]
|
||||
stdout: StdioCollector { onStreamFinished: media.artist = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: titleProc
|
||||
command: ["playerctl", "metadata", "title"]
|
||||
stdout: StdioCollector { onStreamFinished: media.title = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: albumProc
|
||||
command: ["playerctl", "metadata", "album"]
|
||||
stdout: StdioCollector { onStreamFinished: media.album = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: artProc
|
||||
command: ["playerctl", "metadata", "mpris:artUrl"]
|
||||
stdout: StdioCollector { onStreamFinished: media.artUrl = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: statusProc
|
||||
command: ["playerctl", "status"]
|
||||
stdout: StdioCollector { onStreamFinished: media.status = text.trim() }
|
||||
}
|
||||
Process {
|
||||
id: positionProc
|
||||
command: ["playerctl", "position"]
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
media.position = parseFloat(text.trim()) || 0
|
||||
if (media.duration > 0)
|
||||
media.progress = media.position / media.duration
|
||||
}
|
||||
}
|
||||
}
|
||||
Process {
|
||||
id: lengthProc
|
||||
command: ["playerctl", "metadata", "mpris:length"]
|
||||
stdout: StdioCollector {
|
||||
onStreamFinished: {
|
||||
media.duration = (parseFloat(text.trim()) || 0) / 1000000
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
Process { id: prevProc; command: ["playerctl", "previous"] }
|
||||
Process { id: playProc; command: ["playerctl", "play-pause"] }
|
||||
Process { id: nextProc; command: ["playerctl", "next"] }
|
||||
|
||||
FloatingWindow {
|
||||
id: root
|
||||
title: "quickshell-media"
|
||||
visible: true
|
||||
width: 300
|
||||
height: 420
|
||||
color: "transparent"
|
||||
|
||||
Shortcut {
|
||||
sequence: "Escape"
|
||||
onActivated: Qt.quit()
|
||||
}
|
||||
|
||||
// Gradient border
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -2
|
||||
radius: 18
|
||||
z: -1
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: colors.blue }
|
||||
GradientStop { position: 1.0; color: colors.green }
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: 16
|
||||
color: colors.base
|
||||
|
||||
ColumnLayout {
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: 16
|
||||
}
|
||||
spacing: 12
|
||||
|
||||
// Album art
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 200
|
||||
radius: 12
|
||||
color: colors.surface0
|
||||
clip: true
|
||||
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
source: media.artUrl
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: media.artUrl !== ""
|
||||
}
|
||||
|
||||
// Placeholder when no art
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: ""
|
||||
font.pixelSize: 48
|
||||
color: colors.surface2
|
||||
visible: media.artUrl === ""
|
||||
}
|
||||
}
|
||||
|
||||
// Artist
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: media.artist || "Unknown artist"
|
||||
color: colors.subtext1
|
||||
font.pixelSize: 12
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Title
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: media.title || "Nothing playing"
|
||||
color: colors.text
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
// Album
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: media.album
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 11
|
||||
elide: Text.ElideRight
|
||||
visible: media.album !== ""
|
||||
}
|
||||
|
||||
// Device (Spotify)
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: " " + media.device
|
||||
color: colors.green
|
||||
font.pixelSize: 11
|
||||
visible: media.device !== ""
|
||||
}
|
||||
|
||||
// Progress bar
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
height: 4
|
||||
radius: 2
|
||||
color: colors.surface1
|
||||
|
||||
Rectangle {
|
||||
width: parent.width * media.progress
|
||||
height: parent.height
|
||||
radius: parent.radius
|
||||
gradient: Gradient {
|
||||
orientation: Gradient.Horizontal
|
||||
GradientStop { position: 0.0; color: colors.blue }
|
||||
GradientStop { position: 1.0; color: colors.green }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Time
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
|
||||
Text {
|
||||
text: {
|
||||
var m = Math.floor(media.position / 60)
|
||||
var s = Math.floor(media.position % 60)
|
||||
return m + ":" + (s < 10 ? "0" + s : s)
|
||||
}
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 11
|
||||
}
|
||||
|
||||
Item { Layout.fillWidth: true }
|
||||
|
||||
Text {
|
||||
text: {
|
||||
var m = Math.floor(media.duration / 60)
|
||||
var s = Math.floor(media.duration % 60)
|
||||
return m + ":" + (s < 10 ? "0" + s : s)
|
||||
}
|
||||
color: colors.subtext0
|
||||
font.pixelSize: 11
|
||||
}
|
||||
}
|
||||
|
||||
// Playback controls
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: 24
|
||||
|
||||
Text {
|
||||
text: ""
|
||||
font.pixelSize: 22
|
||||
color: prevHover.containsMouse ? colors.blue : colors.text
|
||||
MouseArea {
|
||||
id: prevHover
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: prevProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: media.status === "Playing" ? "" : ""
|
||||
font.pixelSize: 28
|
||||
color: playHover.containsMouse ? colors.green : colors.text
|
||||
MouseArea {
|
||||
id: playHover
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: playProc.running = true
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: ""
|
||||
font.pixelSize: 22
|
||||
color: nextHover.containsMouse ? colors.blue : colors.text
|
||||
MouseArea {
|
||||
id: nextHover
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: nextProc.running = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,12 +75,12 @@ ShellRoot {
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
{ label: " Lock", cmd: ["loginctl", "lock-session"] },
|
||||
{ label: " Shutdown", cmd: ["systemctl", "poweroff"] },
|
||||
{ label: " Reboot", cmd: ["systemctl", "reboot"] },
|
||||
{ label: " Logout", cmd: ["bash", "-c", "loginctl terminate-session $XDG_SESSION_ID"] },
|
||||
{ label: " Hibernate", cmd: ["systemctl", "hibernate"] },
|
||||
{ label: " Suspend", cmd: ["systemctl", "suspend"] },
|
||||
{ label: " Lock", cmd: ["loginctl", "lock-session"] },
|
||||
{ label: " Shutdown", cmd: ["systemctl", "poweroff"] },
|
||||
{ label: " Reboot", cmd: ["systemctl", "reboot"] },
|
||||
{ label: " Logout", cmd: ["bash", "-c", "loginctl terminate-session $XDG_SESSION_ID"] },
|
||||
{ label: " Hibernate", cmd: ["systemctl", "hibernate"] },
|
||||
{ label: " Suspend", cmd: ["systemctl", "suspend"] },
|
||||
]
|
||||
|
||||
delegate: Rectangle {
|
||||
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env bash
|
||||
# --- This file has been auto-generated. For permanent changes alter the appropriate block in the README.org. ---
|
||||
#!/usr/bin/env bash
|
||||
player=$(playerctl -l 2>/dev/null | head -n1)
|
||||
|
||||
if [ -z "$player" ]; then
|
||||
jq -c -n '{text: "", tooltip: "", class: "inactive"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
status=$(playerctl --player="$player" status 2>/dev/null)
|
||||
|
||||
if [ "$status" != "Playing" ] && [ "$status" != "Paused" ]; then
|
||||
jq -c -n '{text: "", tooltip: "", class: "inactive"}'
|
||||
exit 0
|
||||
fi
|
||||
|
||||
artist=$(playerctl --player="$player" metadata artist 2>/dev/null)
|
||||
title=$(playerctl --player="$player" metadata title 2>/dev/null)
|
||||
album=$(playerctl --player="$player" metadata album 2>/dev/null)
|
||||
art=$(playerctl --player="$player" metadata mpris:artUrl 2>/dev/null)
|
||||
length=$(playerctl --player="$player" metadata mpris:length 2>/dev/null)
|
||||
position=$(playerctl --player="$player" position 2>/dev/null)
|
||||
|
||||
# Progress percentage
|
||||
if [ -n "$length" ] && [ "$length" -gt 0 ] 2>/dev/null; then
|
||||
progress=$(echo "scale=0; $position * 1000000 / $length * 100 / 100" | bc)
|
||||
else
|
||||
progress=0
|
||||
fi
|
||||
|
||||
# Spotify device
|
||||
device=""
|
||||
if [[ "$player" == *"spotify"* ]]; then
|
||||
device=$(playerctl --player="$player" metadata xesam:url 2>/dev/null | grep -o 'device=[^&]*' | cut -d= -f2)
|
||||
fi
|
||||
|
||||
# Ticker text — truncate if long
|
||||
text="${artist} — ${title}"
|
||||
if [ ${#text} -gt 40 ]; then
|
||||
text="${text:0:37}..."
|
||||
fi
|
||||
|
||||
# Icon
|
||||
if [ "$status" = "Paused" ]; then
|
||||
icon="⏸ "
|
||||
else
|
||||
icon="▶ "
|
||||
fi
|
||||
|
||||
# Build tooltip
|
||||
tooltip="${artist}\n${title}\n${album}"
|
||||
if [ -n "$device" ]; then
|
||||
tooltip="${tooltip}\n ${device}"
|
||||
fi
|
||||
tooltip="${tooltip}\n$(printf '%.0f' "$progress")%"
|
||||
|
||||
jq -c -n \
|
||||
--arg text "${icon}${text}" \
|
||||
--arg tooltip "$tooltip" \
|
||||
--arg class "$player" \
|
||||
--arg art "$art" \
|
||||
'{text: $text, tooltip: $tooltip, class: $class, alt: $art}'
|
||||
@@ -11,12 +11,12 @@
|
||||
|
||||
main() {
|
||||
local list=(
|
||||
"Lock"
|
||||
"Shutdown"
|
||||
"Reboot"
|
||||
"Logout"
|
||||
"Hibernate"
|
||||
"Suspend"
|
||||
" Lock"
|
||||
" Shutdown"
|
||||
" Reboot"
|
||||
" Logout"
|
||||
" Hibernate"
|
||||
" Suspend"
|
||||
)
|
||||
|
||||
local options=(
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
"group/audio": {
|
||||
"orientation": "horizontal",
|
||||
"modules": [
|
||||
"custom/media",
|
||||
"pulseaudio",
|
||||
"pulseaudio/slider",
|
||||
]
|
||||
@@ -108,6 +109,16 @@
|
||||
"tooltip": true
|
||||
},
|
||||
|
||||
"custom/media": {
|
||||
"exec": "~/.config/scripts/media.sh",
|
||||
"interval": 2,
|
||||
"return-type": "json",
|
||||
"on-click": "qs -c media",
|
||||
"max-length": 40,
|
||||
"scroll-step": 1,
|
||||
"tooltip": true
|
||||
}
|
||||
|
||||
"custom/bluetooth": {
|
||||
"exec": "~/.config/scripts/bluetooth-status.sh",
|
||||
"interval": 5,
|
||||
|
||||
Reference in New Issue
Block a user