Created
January 24, 2020 16:02
-
-
Save fearphage/7ddfbecf80e26ea33825898b41ba93c7 to your computer and use it in GitHub Desktop.
Command Line Audio Playlist
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Requirements: dialog mpv | |
# Optional: youtube-dl wget hq | |
# Arguments: none | |
# | |
# Changelog: | |
# > + from function to standalone script | |
# + menu stack for saving previous menu command | |
# + choices stack for saving previous menu choice | |
# + "require" function | |
# + "niceinfo" function | |
# + back to menu on player close | |
# + autofetch for http://musicforprogramming.net | |
# + automatic requirements check | |
# | |
# > + dialog menu entries via associative array | |
# + key array support for keeping custom order | |
# + nice "addentry" function | |
# + selection title shows up before playing | |
# + internal functions unsetting before close | |
declare next back out err keys label defitem | |
declare stackmenu=("quit c") stackchoice=(-) | |
declare -A options | |
clearOptions() { | |
keys=() | |
options=() | |
} | |
addentry() { | |
keys+=("${1:?Missing key}") | |
options["$1"]="$2" | |
} | |
print() { | |
printf '%b\n' "${@}" | |
} | |
niceinfo() { | |
local text="${1:?Missing info text.}" | |
if [[ "${text: -1}" != $'\n' ]]; then | |
text+=$'\n' | |
fi | |
if ! which dialog &>/dev/null; then | |
echo "$text" | |
return | |
fi | |
local width height | |
IFS=' ' read -r height width <<< $(wc -l -L <<< "$text") | |
dialog --infobox "$text" $((height+1)) $((width+4)) | |
} | |
nicemenu() { | |
local oldnext="$next" | |
next="${1:?Missing next cmd}" | |
back="$3" | |
local title="$2" | |
shift 3 | |
local list=() | |
for k in "${keys[@]}"; do | |
list+=("$k" "${options[$k]}") | |
done | |
out=$(dialog ${defitem:+--default-item "$defitem"} --menu "$title" 0 0 0 "${list[@]}" 3>&2 2>&1 1>&3) | |
local err=$? | |
defitem="" | |
if let "${#out} == 0"; then | |
err=1 | |
fi | |
if let "!err"; then | |
stackmenu+=("$oldnext") | |
stackchoice+=("$out") | |
label="${options[$out]}" | |
fi | |
clearOptions | |
next="${next} '$out'" | |
return $err | |
} | |
require() { | |
local notfound=() | |
for pkg in "$@"; do | |
if ! which "$pkg" &>/dev/null; then | |
notfound+=("$pkg") | |
fi | |
done | |
if let "${#notfound[@]} > 0"; then | |
local msg="Unable to find these required executables:" | |
local wait=0 | |
for missing in "${notfound[@]}"; do | |
msg+=$'\n'" - $missing" | |
let 'wait++' | |
done | |
niceinfo "$msg" | |
sleep "$wait.7" | |
return 1 | |
fi | |
return 0 | |
} | |
mmenu() { | |
addentry ytvideo "Youtube" | |
addentry mfp "musicforprogramming.net" | |
addentry direct "Direct links" | |
nicemenu 'eval' "Select source" | |
} | |
ytvideo() { | |
if ! require youtube-dl; then return 1; fi | |
addentry nxWxC0DffG8 "Power Outage During Thunderstorm ASMR Ambience" | |
addentry mlQmCfjXApM "Mario Kart Wii - Main Menu Medley (Extended)" | |
addentry ebhoaxFyDuM "Relaxation music 12 hours - Vol 3" | |
addentry zT_zEAVFrNo "Study and DayDream #1 | Retrowave - Synthwave - Chillwave Mix 2019" | |
addentry j5edzGidnPA "Best of Relaxing Synthwave Mix" | |
nicemenu 'play yt' "Select video" | |
} | |
mfp_error() { | |
niceinfo "Unable to fetch website content." | |
sleep 1.7 | |
return 1 | |
} | |
mfp() { | |
if ! require hq wget; then return 1; fi | |
niceinfo "Fetching website content..." | |
local page=$(mktemp) | |
if ! wget -q -O "$page" https://musicforprogramming.net/?about &>/dev/null; then | |
mfp_error | |
rm -f "$page" | |
return | |
fi | |
while read -r entry; do | |
IFS=$'\t' read -r url title <<< "$entry" | |
addentry "$url" "$title" | |
done <<< "$(paste \ | |
<(hq -f "$page" '#episodes > a' attr href) \ | |
<(hq -f "$page" '#episodes > a' text) \ | |
| tac | |
)" | |
rm -f "$page" | |
nicemenu 'mfp_entry' "musicforprogramming.net" | |
} | |
mfp_entry() { | |
niceinfo "Fetching website content..." | |
local page=$(mktemp) | |
if ! wget -q -O "$page" \ | |
"https://musicforprogramming.net/${1:?Missing url part.}" \ | |
&>/dev/null; then | |
mfp_error | |
rm -f "$page" | |
return | |
fi | |
local url | |
url=$(hq -f "$page" '#player' attr src) | |
next="play - ${url@Q}" | |
rm -f "$page" | |
} | |
direct() { | |
addentry http://radio.plaza.one/opus_64 "Plaza One" | |
nicemenu 'play -' "Select link" | |
} | |
play() { | |
clear | |
print "\e[1mTitle: \e[36m$label\e[0m" | |
echo "(Please wait)" | |
local args=() | |
case "$1" in | |
yt) args+=( | |
"--ytdl-format=bestaudio[ext=m4a]/best[ext=mp4]/best" | |
"https://www.youtube.com/watch?v=$2" | |
);; | |
*) args+=("$2") | |
esac | |
mpv --no-video --hwdec=yes --volume=50 "${args[@]}" | |
if let 'err'; then | |
sleep 1.7 | |
fi | |
return 1 | |
} | |
quit() { | |
${1:+clear} | |
exit | |
} | |
signal() { :; } | |
if ! require dialog mpv; then return 1; fi | |
trap signal SIGINT | |
next=mmenu | |
while true; do | |
if ! eval "$next"; then | |
if [[ "$back" != "" ]]; then | |
next="$back" | |
else | |
next="${stackmenu[-1]}" | |
defitem="${stackchoice[-1]}" | |
unset stackmenu[-1] | |
unset stackchoice[-1] | |
fi | |
fi | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment