updated hyprlock
This commit is contained in:
1 parent
a86ca3deeb
commit
2e47a60f15
4 files changed
+567
-7
No files matched your search
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
|
||||
background=$(ls ~/Pictures/wallpaper/*.png | shuf -n 1)
|
||||
background=$(ls ~/Pictures/wallpaper/* | shuf -n 1)
|
||||
sed -i "s|.*Pictures.*|\tpath = $background|" ~/dotfiles/hypr/hyprlock.conf
|
||||
hyprlock
|
||||
Executable
+421
@@ -0,0 +1,421 @@
|
||||
#!/usr/bin/env bash
|
||||
# hyprlock-music.sh - Music player integration for Hyprlock
|
||||
# Displays current track info, album art, and playback controls
|
||||
# Dependencies: playerctl (required), curl (for remote art), ImageMagick (for cropping)
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
# ============================================================================
|
||||
# Configuration
|
||||
# ============================================================================
|
||||
|
||||
# Player priority order (first available will be used)
|
||||
PREFERRED_PLAYERS="spotify,mpv,vlc,firefox,chromium,brave,chrome"
|
||||
|
||||
# Album art cache settings
|
||||
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/hyprlock-art"
|
||||
SQUARE_SIZE=1024
|
||||
mkdir -p "$CACHE_DIR"
|
||||
|
||||
# Progress bar appearance
|
||||
BAR_LENGTH=16
|
||||
BAR_CHAR="━"
|
||||
BAR_HANDLE="⦿"
|
||||
COLOR_PLAYED="ffffff99"
|
||||
COLOR_REMAINING="ffffff30"
|
||||
|
||||
# ============================================================================
|
||||
# Helper Functions
|
||||
# ============================================================================
|
||||
|
||||
# Check if command exists
|
||||
have() { command -v "$1" >/dev/null 2>&1; }
|
||||
|
||||
# Select the best available player
|
||||
select_player() {
|
||||
if have playerctl && playerctl -p "$PREFERRED_PLAYERS" status >/dev/null 2>&1; then
|
||||
echo "$PREFERRED_PLAYERS"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
}
|
||||
|
||||
# Get metadata from active player
|
||||
get_metadata() {
|
||||
local key="$1"
|
||||
local fmt="{{ $key }}"
|
||||
local player
|
||||
player="$(select_player)"
|
||||
|
||||
if [[ -n "$player" ]]; then
|
||||
playerctl -p "$player" metadata --format "$fmt" 2>/dev/null || true
|
||||
else
|
||||
playerctl metadata --format "$fmt" 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Get player status (Playing/Paused/Stopped)
|
||||
get_status() {
|
||||
local player
|
||||
player="$(select_player)"
|
||||
|
||||
if [[ -n "$player" ]]; then
|
||||
playerctl -p "$player" status 2>/dev/null || true
|
||||
else
|
||||
playerctl status 2>/dev/null || true
|
||||
fi
|
||||
}
|
||||
|
||||
# Truncate string with ellipsis if too long
|
||||
trim_string() {
|
||||
local str="${1:-}"
|
||||
local max_len="${2:-30}"
|
||||
local str_len=${#str}
|
||||
|
||||
if ((str_len <= max_len)); then
|
||||
printf '%s' "$str"
|
||||
else
|
||||
printf '%s…' "${str:0:max_len}"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Time Conversion Functions
|
||||
# ============================================================================
|
||||
|
||||
# Convert microseconds to mm:ss format
|
||||
microseconds_to_mmss() {
|
||||
local us="$1"
|
||||
|
||||
[[ "$us" =~ ^[0-9]+$ ]] || {
|
||||
printf "0:00"
|
||||
return
|
||||
}
|
||||
|
||||
local seconds=$((us / 1000000))
|
||||
printf '%d:%02d' $((seconds / 60)) $((seconds % 60))
|
||||
}
|
||||
|
||||
# Get track length in mm:ss
|
||||
get_track_length() {
|
||||
local us
|
||||
us="$(get_metadata 'mpris:length')"
|
||||
|
||||
if [[ -z "$us" || "$us" == "0" ]]; then
|
||||
printf '0:00'
|
||||
else
|
||||
microseconds_to_mmss "$us"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get current position in mm:ss
|
||||
get_current_position() {
|
||||
local us
|
||||
local player
|
||||
player="$(select_player)"
|
||||
|
||||
if [[ -n "$player" ]]; then
|
||||
us="$(playerctl -p "$player" position 2>/dev/null | awk '{print int($1 * 1000000)}')" || true
|
||||
else
|
||||
us="$(playerctl position 2>/dev/null | awk '{print int($1 * 1000000)}')" || true
|
||||
fi
|
||||
|
||||
if [[ -z "$us" || "$us" == "0" ]]; then
|
||||
printf '0:00'
|
||||
else
|
||||
microseconds_to_mmss "$us"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Progress Functions
|
||||
# ============================================================================
|
||||
|
||||
# Calculate progress percentage (0-100)
|
||||
calculate_progress_percent() {
|
||||
local pos_us length_us
|
||||
local player
|
||||
player="$(select_player)"
|
||||
|
||||
if [[ -n "$player" ]]; then
|
||||
pos_us="$(playerctl -p "$player" position 2>/dev/null | awk '{print int($1 * 1000000)}')" || true
|
||||
length_us="$(playerctl -p "$player" metadata mpris:length 2>/dev/null)" || true
|
||||
else
|
||||
pos_us="$(playerctl position 2>/dev/null | awk '{print int($1 * 1000000)}')" || true
|
||||
length_us="$(playerctl metadata mpris:length 2>/dev/null)" || true
|
||||
fi
|
||||
|
||||
if [[ -n "$pos_us" && -n "$length_us" && "$length_us" -gt 0 ]]; then
|
||||
local percent=$((pos_us * 100 / length_us))
|
||||
printf '%d' "$percent"
|
||||
else
|
||||
printf '0'
|
||||
fi
|
||||
}
|
||||
|
||||
# Generate progress bar with Pango markup
|
||||
generate_progress_bar() {
|
||||
local percent
|
||||
percent="$(calculate_progress_percent)"
|
||||
|
||||
local current_status
|
||||
current_status="$(get_status)"
|
||||
|
||||
# Return empty bar if nothing is playing
|
||||
if [[ -z "$current_status" || "$current_status" == "Stopped" ]]; then
|
||||
local empty_bar=""
|
||||
for ((i = 0; i < BAR_LENGTH; i++)); do
|
||||
empty_bar+="$BAR_CHAR"
|
||||
done
|
||||
printf '<span foreground="#%s">%s</span>' "$COLOR_REMAINING" "$empty_bar"
|
||||
return
|
||||
fi
|
||||
|
||||
# Treat 95%+ as 100% to handle players switching tracks early
|
||||
[[ $percent -ge 95 ]] && percent=100
|
||||
|
||||
# Calculate filled segments
|
||||
local progress=$((percent * BAR_LENGTH / 100))
|
||||
[[ $progress -gt $BAR_LENGTH ]] && progress=$BAR_LENGTH
|
||||
[[ $progress -lt 0 ]] && progress=0
|
||||
|
||||
# Build bar segments
|
||||
local bar_played=""
|
||||
local bar_remaining=""
|
||||
|
||||
for ((i = 0; i < progress; i++)); do
|
||||
bar_played+="$BAR_CHAR"
|
||||
done
|
||||
|
||||
for ((i = progress; i < BAR_LENGTH; i++)); do
|
||||
bar_remaining+="$BAR_CHAR"
|
||||
done
|
||||
|
||||
# Generate Pango markup based on position
|
||||
if [[ $progress -eq $BAR_LENGTH ]]; then
|
||||
# Track complete - handle at end
|
||||
printf '<span foreground="#%s">%s</span><span foreground="#ffffff99">%s</span>' \
|
||||
"$COLOR_PLAYED" "$bar_played" "$BAR_HANDLE"
|
||||
elif [[ $progress -eq 0 ]]; then
|
||||
# Track just started - handle at beginning
|
||||
printf '<span foreground="#ffffff99">%s</span><span foreground="#%s">%s</span>' \
|
||||
"$BAR_HANDLE" "$COLOR_REMAINING" "${bar_remaining}"
|
||||
else
|
||||
# In progress - played + handle + remaining
|
||||
printf '<span foreground="#%s">%s</span><span foreground="#ffffff99">%s</span><span foreground="#%s">%s</span>' \
|
||||
"$COLOR_PLAYED" "$bar_played" "$BAR_HANDLE" "$COLOR_REMAINING" "$bar_remaining"
|
||||
fi
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Album Art Functions
|
||||
# ============================================================================
|
||||
|
||||
# Download remote URL to cache
|
||||
download_to_cache() {
|
||||
local url="$1"
|
||||
local filename
|
||||
filename="$(printf '%s' "$url" | sha256sum | awk '{print $1}').img"
|
||||
local output="$CACHE_DIR/$filename"
|
||||
|
||||
if [[ ! -s "$output" ]]; then
|
||||
have curl && curl -fsSL --max-time 5 "$url" -o "$output" || true
|
||||
fi
|
||||
|
||||
printf '%s' "$output"
|
||||
}
|
||||
|
||||
# Create square-cropped album art
|
||||
create_square_cover() {
|
||||
local input="$1"
|
||||
local basename
|
||||
basename="$(basename "$input")"
|
||||
local output="$CACHE_DIR/${basename%.*}_sq_${SQUARE_SIZE}.jpg"
|
||||
|
||||
# Return cached version if it exists and is newer
|
||||
if [[ -s "$output" && "$output" -nt "$input" ]]; then
|
||||
printf '%s' "$output"
|
||||
return
|
||||
fi
|
||||
|
||||
# Create square crop with ImageMagick
|
||||
if have convert; then
|
||||
convert "$input" -auto-orient -gravity center \
|
||||
-thumbnail "${SQUARE_SIZE}x${SQUARE_SIZE}^" \
|
||||
-extent "${SQUARE_SIZE}x${SQUARE_SIZE}" \
|
||||
-quality 90 "$output" && printf '%s' "$output" && return
|
||||
fi
|
||||
|
||||
# Fallback to original if ImageMagick unavailable
|
||||
printf '%s' "$input"
|
||||
}
|
||||
|
||||
# Get path to square album art
|
||||
get_album_art_path() {
|
||||
local url
|
||||
url="$(get_metadata 'mpris:artUrl')"
|
||||
|
||||
[[ -n "$url" ]] || {
|
||||
printf ''
|
||||
return
|
||||
}
|
||||
|
||||
local local_path=""
|
||||
|
||||
case "$url" in
|
||||
file://*)
|
||||
local_path="${url#file://}"
|
||||
;;
|
||||
http://* | https://*)
|
||||
local_path="$(download_to_cache "$url")"
|
||||
;;
|
||||
*)
|
||||
printf ''
|
||||
return
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ -n "$local_path" && -s "$local_path" ]] || {
|
||||
printf ''
|
||||
return
|
||||
}
|
||||
|
||||
create_square_cover "$local_path"
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Display Functions
|
||||
# ============================================================================
|
||||
|
||||
# Get player status icon
|
||||
get_status_icon() {
|
||||
case "$(get_status | tr '[:upper:]' '[:lower:]')" in
|
||||
playing)
|
||||
printf ''
|
||||
;;
|
||||
paused)
|
||||
printf ''
|
||||
;;
|
||||
stopped | *)
|
||||
printf ''
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get active player name
|
||||
get_active_player() {
|
||||
local active_player=""
|
||||
local player
|
||||
player="$(select_player)"
|
||||
|
||||
if [[ -n "$player" ]]; then
|
||||
active_player="$(playerctl -p "$player" -l 2>/dev/null | head -n1)"
|
||||
else
|
||||
active_player="$(playerctl -l 2>/dev/null | head -n1)"
|
||||
fi
|
||||
|
||||
printf '%s' "$active_player"
|
||||
}
|
||||
|
||||
# Get formatted player name with icon
|
||||
get_player_display() {
|
||||
local player
|
||||
player="$(get_active_player)"
|
||||
|
||||
case "${player,,}" in
|
||||
spotify*)
|
||||
printf ' Spotify'
|
||||
;;
|
||||
firefox*)
|
||||
printf ' Firefox'
|
||||
;;
|
||||
chromium*)
|
||||
printf ' Chromium'
|
||||
;;
|
||||
brave*)
|
||||
printf ' Brave'
|
||||
;;
|
||||
chrome*)
|
||||
printf ' Chrome'
|
||||
;;
|
||||
mpv*)
|
||||
printf ' mpv'
|
||||
;;
|
||||
vlc*)
|
||||
printf ' VLC'
|
||||
;;
|
||||
*)
|
||||
printf '%s' "${player:-Unknown}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Command-Line Interface
|
||||
# ============================================================================
|
||||
|
||||
case "${1:-}" in
|
||||
--title)
|
||||
title="$(get_metadata 'xesam:title')"
|
||||
printf '%s\n' "$(trim_string "${title:-Nothing Playing}" 29)"
|
||||
;;
|
||||
|
||||
--artist)
|
||||
artist="$(get_metadata 'xesam:artist')"
|
||||
printf '%s\n' "$(trim_string "${artist:-}" 26)"
|
||||
;;
|
||||
|
||||
--status)
|
||||
printf '%s\n' "$(get_status_icon)"
|
||||
;;
|
||||
|
||||
--length)
|
||||
printf '%s\n' "$(get_track_length)"
|
||||
;;
|
||||
|
||||
--position)
|
||||
printf '%s\n' "$(get_current_position)"
|
||||
;;
|
||||
|
||||
--progress)
|
||||
printf '%s\n' "$(calculate_progress_percent)"
|
||||
;;
|
||||
|
||||
--progress-bar)
|
||||
printf '%s\n' "$(generate_progress_bar)"
|
||||
;;
|
||||
|
||||
--art)
|
||||
printf '%s\n' "$(get_album_art_path)"
|
||||
;;
|
||||
|
||||
--player)
|
||||
printf '%s\n' "$(get_player_display)"
|
||||
;;
|
||||
|
||||
--help | *)
|
||||
cat <<EOF
|
||||
Usage: $(basename "$0") [OPTION]
|
||||
|
||||
Music player information for Hyprlock.
|
||||
|
||||
Options:
|
||||
--title Display song title (truncated to 29 chars)
|
||||
--artist Display artist name (truncated to 26 chars)
|
||||
--status Display play/pause/stop icon
|
||||
--length Display total track length (mm:ss)
|
||||
--position Display current position (mm:ss)
|
||||
--progress Display progress percentage (0-100)
|
||||
--progress-bar Display colored progress bar with Pango markup
|
||||
--art Display path to square-cropped album art
|
||||
--player Display player name with icon
|
||||
--help Show this help message
|
||||
|
||||
Examples:
|
||||
$(basename "$0") --title
|
||||
$(basename "$0") --progress-bar
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
+145
-6
@@ -1,6 +1,6 @@
|
||||
background {
|
||||
monitor =
|
||||
path = /home/tola/Pictures/wallpaper/3d-tech.png
|
||||
path = /home/tola/Pictures/wallpaper/johannes-plenio-hvrpOmuMrAI-unsplash.jpg
|
||||
color = rgba(25, 20, 20, 1.0)
|
||||
blur_passes = 3
|
||||
blur_size = 3
|
||||
@@ -14,6 +14,13 @@ general {
|
||||
no_fade_in = false
|
||||
grace = 0
|
||||
disable_loading_bar = false
|
||||
ignore_empty_input = true
|
||||
# hide_cursor = true
|
||||
}
|
||||
animations {
|
||||
animation = fade, 1, 6, default
|
||||
animation = fadeIn, 1, 6, default
|
||||
animation = fadeOut, 1, 6, default
|
||||
}
|
||||
image {
|
||||
monitor =
|
||||
@@ -94,13 +101,145 @@ input-field {
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
# label {
|
||||
# monitor =
|
||||
# text = cmd[update:1000] echo "$(~/dotfiles/hypr/bin/songdetail.sh)"
|
||||
# color = rgba(255, 255, 255, 0.6)
|
||||
# font_size = 18
|
||||
# font_family = JetBrainsMonoNerd Font Mono Bold
|
||||
# position = 0, 50
|
||||
# halign = center
|
||||
# valign = bottom
|
||||
# }
|
||||
image {
|
||||
monitor =
|
||||
path = ~/dotfiles/hypr/pictures/music.webp
|
||||
size = 100
|
||||
rounding = 5
|
||||
burder_size = 3
|
||||
border_color = rgba(216, 222, 233, 0.70)
|
||||
rotate = 0
|
||||
reload_time = 2
|
||||
reload_cmd = ~/dotfiles/hypr/bin/hyprlock-music.sh --art
|
||||
position = 730, 57
|
||||
halign = left
|
||||
valign = bottom
|
||||
zindex = 1
|
||||
}
|
||||
shape {
|
||||
monitor =
|
||||
color = rgba(100, 114, 125, 0.4)
|
||||
size = 500, 140
|
||||
rounding = 10
|
||||
position = 0, 40
|
||||
halign = center
|
||||
valign = bottom
|
||||
zindex = 0
|
||||
}
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] echo "$(~/dotfiles/hypr/bin/songdetail.sh)"
|
||||
color = rgba(255, 255, 255, 0.6)
|
||||
font_size = 18
|
||||
font_family = JetBrainsMonoNerd Font Mono Bold
|
||||
position = 0, 50
|
||||
text = cmd[update:1000] echo "$(~/dotfiles/hypr/bin/hyprlock-music.sh --title)"
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 16
|
||||
font_family = SF Pro Display Heavy
|
||||
position = 55, 138
|
||||
halign = center
|
||||
valign = bottom
|
||||
zindex = 1
|
||||
}
|
||||
|
||||
# Player source (e.g., Spotify, Firefox)
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] echo "$(~/dotfiles/hypr/bin/hyprlock-music.sh --player)"
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 13
|
||||
font_family = SF Pro Display Bold
|
||||
position = 205, 45
|
||||
halign = center
|
||||
valign = bottom
|
||||
zindex = 1
|
||||
}
|
||||
|
||||
# Artist name
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] echo " $(~/dotfiles/hypr/bin/hyprlock-music.sh --artist)"
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 12
|
||||
font_family = SF Pro Display Semibold
|
||||
position = 55, 118
|
||||
halign = center
|
||||
valign = bottom
|
||||
zindex = 1
|
||||
}
|
||||
# Previous track button
|
||||
label {
|
||||
monitor =
|
||||
text =
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 25
|
||||
onclick = playerctl previous
|
||||
position = -5, 55
|
||||
halign = center
|
||||
valign = bottom
|
||||
}
|
||||
|
||||
# Play/Pause button
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] ~/dotfiles/hypr/bin/hyprlock-music.sh --status
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 25
|
||||
onclick = playerctl play-pause
|
||||
position = 55, 55
|
||||
halign = center
|
||||
valign = bottom
|
||||
}
|
||||
|
||||
# Next track button
|
||||
label {
|
||||
monitor =
|
||||
text =
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 25
|
||||
onclick = playerctl next
|
||||
position = 110, 55
|
||||
halign = center
|
||||
valign = bottom
|
||||
}
|
||||
# Current position timestamp
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] echo "$(~/dotfiles/hypr/bin/hyprlock-music.sh --position)"
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 10
|
||||
font_family = SF Pro Display Medium
|
||||
position = -100, 95
|
||||
halign = center
|
||||
valign = bottom
|
||||
}
|
||||
|
||||
# Total length timestamp
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] echo "$(~/dotfiles/hypr/bin/hyprlock-music.sh --length)"
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 10
|
||||
font_family = SF Pro Display Medium
|
||||
position = 210, 95
|
||||
halign = center
|
||||
valign = bottom
|
||||
}
|
||||
|
||||
# Progress bar (with Pango markup for colored segments)
|
||||
label {
|
||||
monitor =
|
||||
text = cmd[update:1000] ~/dotfiles/hypr/bin/hyprlock-music.sh --progress-bar
|
||||
color = rgba(216, 222, 233, 0.70)
|
||||
font_size = 12
|
||||
font_family = SF Pro Display Medium
|
||||
position = 55, 95
|
||||
halign = center
|
||||
valign = bottom
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 228 KiB |
Reference in new issue
Block a user