The bare $HOME repo is gone. This is now the rice: install.sh, rice-* scripts in bin/, configs in home/ linked into $HOME, theme templates, st and the particle wallpaper. Clone to ~/rice and run install.sh.
75 lines
2.7 KiB
Bash
Executable file
75 lines
2.7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# rice-media - now-playing state for the eww panel and bar.
|
|
#
|
|
# rice-media watch JSON on every track or play-state change (eww deflisten)
|
|
# rice-media position JSON {pos, text} for the seek bar (polled while the panel is open)
|
|
# rice-media seek <seconds>
|
|
#
|
|
# Album art is copied into ~/.cache/rice/art under a hash of its URL, so the
|
|
# panel only ever points at a file name it created itself.
|
|
set -uo pipefail
|
|
|
|
art_dir="${XDG_CACHE_HOME:-$HOME/.cache}/rice/art"
|
|
mkdir -p "$art_dir"
|
|
|
|
clock() { local s=$1; printf '%d:%02d' $((s / 60)) $((s % 60)); }
|
|
|
|
art_path() {
|
|
local url="$1" key file path=""
|
|
[[ -n $url ]] || return 0
|
|
key="$url"
|
|
if [[ $url == file://* ]]; then
|
|
path="${url#file://}"
|
|
path=$(printf '%b' "${path//%/\\x}")
|
|
# Browsers reuse one temp file for every track, so local art is keyed by mtime too.
|
|
key+=":$(stat -c %Y -- "$path" 2>/dev/null)"
|
|
fi
|
|
file="$art_dir/$(printf '%s' "$key" | sha1sum | cut -c1-16)"
|
|
if [[ ! -s $file ]]; then
|
|
if [[ -n $path ]]; then
|
|
cp -- "$path" "$file" 2>/dev/null
|
|
elif [[ $url == http*://* ]]; then
|
|
curl -fsSL --max-time 5 -o "$file" -- "$url" 2>/dev/null
|
|
fi
|
|
fi
|
|
[[ -s $file ]] && printf '%s' "$file"
|
|
}
|
|
|
|
emit() {
|
|
local status="$1" player="$2" title="$3" artist="$4" album="$5" url="$6" length="$7"
|
|
local secs=$(( ${length:-0} / 1000000 ))
|
|
jq -cn --arg status "$status" --arg player "$player" --arg title "$title" \
|
|
--arg artist "$artist" --arg album "$album" --arg art "$(art_path "$url")" \
|
|
--argjson length "$secs" --arg lengthText "$( (( secs > 0 )) && clock "$secs")" \
|
|
'{status: $status, player: $player, title: $title, artist: $artist, album: $album,
|
|
art: $art, length: $length, lengthText: $lengthText}'
|
|
}
|
|
|
|
watch() {
|
|
# Unit separator, not tab: read collapses runs of whitespace separators, so an
|
|
# empty field (browsers often send no album) would shift every later field.
|
|
local sep=$'\x1f'
|
|
while :; do
|
|
emit "Stopped" "" "" "" "" "" 0
|
|
playerctl --follow metadata --format \
|
|
"{{status}}${sep}{{playerName}}${sep}{{title}}${sep}{{artist}}${sep}{{album}}${sep}{{mpris:artUrl}}${sep}{{mpris:length}}" 2>/dev/null |
|
|
while IFS="$sep" read -r status player title artist album url length; do
|
|
emit "${status:-Stopped}" "$player" "$title" "$artist" "$album" "$url" "${length:-0}"
|
|
done
|
|
sleep 2
|
|
done
|
|
}
|
|
|
|
case "${1:-}" in
|
|
watch) watch ;;
|
|
position)
|
|
pos=$(playerctl position 2>/dev/null | cut -d. -f1)
|
|
pos=${pos:-0}
|
|
jq -cn --argjson pos "$pos" --arg text "$(clock "$pos")" '{pos: $pos, text: $text}'
|
|
;;
|
|
seek)
|
|
[[ ${2:-} =~ ^[0-9]+$ ]] || { echo "rice-media: seek takes seconds" >&2; exit 2; }
|
|
playerctl position "$2"
|
|
;;
|
|
*) sed -n '2,10p' "$0" | sed 's/^# \{0,1\}//'; exit 2 ;;
|
|
esac
|