dotfiles/.local/bin/cmusctl

160 lines
3.7 KiB
Bash
Executable File

#!/bin/bash
# cmusctl
#
# Allows executing 'cmus-remote' commands and writes the currently
# playing song to a file so be consumed by e.g. i3status.
SCRIPT_NAME="$(basename -- "$0")"
function usage() {
echo "Usage: $SCRIPT_NAME [OPTIONS]"
echo
echo "Options:"
echo " -h Display help."
echo " -e [COUNT] Run forever, every [COUNT] seconds. Disabled (0) by default."
echo " -l Kill other $SCRIPT_NAME processes. Only allowed if running forever."
}
while getopts ":e:c:lh" arg; do
case $arg in
e) EVERY=$OPTARG ;;
c) COMMAND=$OPTARG ;;
l) AQUIRE_LEADER=true ;;
h)
usage
exit 0
;;
:)
echo "$SCRIPT_NAME: Must supply an argument to -$OPTARG." >&2
usage
exit 1
;;
?)
echo "Invalid option: -${OPTARG}."
echo
usage
exit 2
;;
esac
done
LOOP=false
EVERY="${EVERY:-0}"
[[ $EVERY -gt 0 ]] && LOOP=true
AQUIRE_LEADER="${AQUIRE_LEADER:-false}"
OUTPUT_FILE="/tmp/$SCRIPT_NAME.status"
PREV_STATUS=""
function multiple_instances_running() {
[[ "$(pgrep -f "$SCRIPT_NAME" | grep -cv "^$$$")" -gt 1 ]] || return 1
}
function aquire_leader() {
echo "Aquiring leadership"
if ! [[ "$EVERY" -gt 0 ]]; then
echo "ERROR: -e [COUNT] must be a positive integer for leader aquisition." 1>&2
exit 11
fi
while read -r pid; do
[[ "$pid" == "$$" ]] && continue
if ! kill "$pid"; then
echo "ERROR: Unable to kill $pid." 1>&2
exit 12
fi
done <<<"$(pgrep -f "$SCRIPT_NAME")"
echo "Leadership aquired."
}
function write_status() {
local status="$1"
# Don't write if there's no update
if [[ "$status" != "$PREV_STATUS" ]]; then
echo "$status" | tee "$OUTPUT_FILE"
killall -SIGUSR1 i3status
export PREV_STATUS="$status"
else
echo "NOCHG"
fi
! $LOOP && exit 0
sleep "$EVERY"
}
function get_field() {
local row
row="$(grep "^$1 " <<<"$QUERY_RESULT")"
echo "${row#"$1 "}"
}
function get_status() {
local tmp status
tmp="$(get_field status)"
status="$tmp"
[ "$tmp" == "playing" ] && status="▶"
[ "$tmp" == "paused" ] && status="⏸️"
[ "$tmp" == "stopped" ] && status="⏹️"
echo $status
}
function get_progress() {
local duration position
duration="$(get_field duration)"
position="$(get_field position)"
if [ -n "$duration" ] && [ -n "$position" ]; then
echo "$(((position * 100 / duration * 100) / 100))%"
fi
}
function get_artist_title() {
local tag_artist tag_title
tag_artist="$(get_field "tag artist")"
tag_title="$(get_field "tag title")"
if [ -n "$tag_artist" ] && [ -n "$tag_title" ]; then
echo "$tag_artist - $tag_title"
fi
}
function get_file_name() {
local fn
fn="$(get_field file)"
fn="${fn##*/}"
fn="${fn%.*}"
echo "$fn"
}
if $LOOP && multiple_instances_running; then
if $AQUIRE_LEADER; then
echo "Other instances have been detected."
aquire_leader
else
echo "ERROR: Other instances are running and leader aquisition not set." 1>&2
exit 10
fi
fi
# shellcheck disable=SC2086
[ -n "$COMMAND" ] && cmus-remote $COMMAND
while true; do
QUERY_RESULT="$(cmus-remote --query 2>/dev/null)"
[ -z "$QUERY_RESULT" ] && write_status "🎵❌" && continue
PROGRESS="$(get_progress)"
STATUS="$(get_status)"
NAME="$(get_artist_title)"
[ -z "$NAME" ] && NAME="$(get_file_name)"
OUT="${STATUS^}"
[ -n "$NAME" ] && OUT+=" $NAME"
[ -n "$PROGRESS" ] && [ "$STATUS" != "⏹️" ] && OUT+=" ($PROGRESS)"
write_status "$OUT"
done