ptgdp: More modularization, add individual song selection mode

This commit is contained in:
Salt 2019-08-18 01:26:53 -05:00
parent dd24705821
commit d7b8c7e392

203
ptgdp
View File

@ -17,6 +17,7 @@ _xdguserdirs="${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs"
[ -z "$XDG_MUSIC_DIR" ] && [ -f "$_xdguserdirs" ] && source "$_xdguserdirs" [ -z "$XDG_MUSIC_DIR" ] && [ -f "$_xdguserdirs" ] && source "$_xdguserdirs"
_musicdir="${XDG_MUSIC_DIR:-$HOME/Music}" _musicdir="${XDG_MUSIC_DIR:-$HOME/Music}"
_ptgdpmusicdir="$_musicdir/${PTGDP_MUSIC_DIR:-PTGDP Songs}" _ptgdpmusicdir="$_musicdir/${PTGDP_MUSIC_DIR:-PTGDP Songs}"
declare -a _queue
# Helper functions # Helper functions
log() { log() {
@ -123,6 +124,64 @@ cachesong() {
return 0 return 0
fi fi
} }
queuesong() {
# $1: A song query to queue
# returns 0 if successful, 100 if cached, 1 if error
# Adds a song to $_queue
[ -z "$1" ] && return 2
cachesong "$1"
local errorcode=$?
if [ -z "$_optdryrun" ]; then
case $errorcode in
0)
# Downloaded
log "Downloaded song \"$1\""
;;
100)
# Cached
log "Using cached song \"$1\""
;;
*)
# Failed
dlfailure+=1
notify "Could not download song" \
"youtube-dl did not download a song for \"$1\"" \
normal dialog-error 3000
error "Could not download song \"$1\""
continue
;;
esac
_queue+=("$_return")
else
case $errorcode in
0)
# Success
if [ -n "$_return" ]; then
log "$1 - \"$output\""
else
log "$1 parsed, but title could not be extracted"
fi
;;
*)
# Failure
error "Could not find song \"$1\""
;;
esac
fi
return $errorcode
}
execqueue() {
# Plays all songs in _queue
mpc update --wait > /dev/null 2>&1
for file in "${_queue[@]}"; do
file=${file##$_musicdir/}
mpc add "$file" > /dev/null 2>&1 || error "Could not add file: \"$file\""
done
if [ -n "$_optautoplay" ]; then
mpc play > /dev/null 2>&1
unset _optautoplay
fi
}
validatedeps() { validatedeps() {
# $@: Dependencies to validate # $@: Dependencies to validate
for prog in "$@"; do for prog in "$@"; do
@ -135,12 +194,26 @@ validatedeps() {
} }
validateline() { validateline() {
# $1: A line to check for comments or whitespace # $1: A line to check for comments or whitespace
# Strictly speaking, this removes all whitespace from the line
# While not *exactly* what I'm looking for, it's sufficient for trimming whitespace lines
local linenows=${1//[[:space:]]} local linenows=${1//[[:space:]]}
if ! [ "${1#\#}" = "$1" ] || [ -z "$linenows" ]; then if ! [ "${1#\#}" = "$1" ] || [ -z "$linenows" ]; then
return 1 return 1
fi fi
return 0 return 0
} }
validateplaylistenv() {
[ -z "$1" ] && return 1
[ -e "$1" ] || error "Playlist \"$1\" does not exist" 50
[ -f "$1" ] || error "Playlist \"$1\" is not a file" 50
[ -r "$1" ] || error "Cannot read playlist \"$1\"" 51
if [ -z "$_optdownloadonly" ] && ! mpc status > /dev/null 2>&1; then
notify "Could not communicate with MPD" \
"MPD connection was refused. Ensure your configuration is correct and the daemon is currently running." \
normal dialog-error 3000
error "Failed to communicate with MPD" 52
fi
}
sanitize() { sanitize() {
[ -z "$1" ] && return 1 # String to strip special chars from [ -z "$1" ] && return 1 # String to strip special chars from
_return="${1//[^ a-zA-Z0-9\[\]|()_-]/}" _return="${1//[^ a-zA-Z0-9\[\]|()_-]/}"
@ -181,6 +254,9 @@ files are cached in your Music folder under "PTGDP Songs" for offline use.
all .gdp files in the given directory. If notify-send all .gdp files in the given directory. If notify-send
is installed, this will also send notifications is installed, this will also send notifications
pertaining to playlist status. pertaining to playlist status.
-R <directory|file> As above, but also parse out the selected playlist and
present a listing of individual songs. The argument can
be a file in this mode
-h Print this help text -h Print this help text
@ -197,7 +273,13 @@ EOF
} }
rofimenu() { rofimenu() {
validatedeps rofi || error "$_return is not currently installed" 1 validatedeps rofi || error "$_return is not currently installed" 1
[ -d "$_optrofi" ] || error "Could not open directory \"$_optrofi\"" 2 if ! [ -d "$_optrofi" ]; then
if [ -z "$_optrofisong" ]; then
error "Could not open directory \"$_optrofi\"" 2
else
[ -f "$_optrofi" ] || error "Could not open file \"$_optrofi\"" 2
fi
fi
files=$(find "$_optrofi" -type f -name \*.gdp) files=$(find "$_optrofi" -type f -name \*.gdp)
if [ -n "$files" ]; then if [ -n "$files" ]; then
# Strip file suffixes for a cleaner menu # Strip file suffixes for a cleaner menu
@ -214,30 +296,51 @@ rofimenu() {
normal dialog-error 5000 normal dialog-error 5000
error "No playlists found" 61 error "No playlists found" 61
fi fi
choice="$(rofi -dmenu -i -p "$_name" <<< "$playlists" 2>/dev/null)" prompt="$_name list"
[ -n "$_optautplay" ] && prompt="$prompt ap"
choice="$(rofi -dmenu -i -p "$prompt" <<< "$playlists" 2>/dev/null)"
[ -z "$choice" ] && error "User aborted at selection" 62 [ -z "$choice" ] && error "User aborted at selection" 62
playlist "$_optrofi"/"$choice".gdp if [ -z "$_optrofisong" ]; then
playlist "$_optrofi"/"$choice".gdp
else
rofiplaysong "$_optrofi"/"$choice".gdp
fi
return 0
}
rofiplaysong() {
validateplaylistenv "$1" || return $?
local songs=""
while read line; do
validateline "$line" || continue
if [ -z "$songs" ]; then
songs="$line"
else
songs="$songs"$'\n'"$line"
fi
done < "$1"
IFS=$'\n'
prompt="$_name song"
[ -n "$_optautplay" ] && prompt="$prompt ap"
choice="$(rofi -dmenu -i -p "$prompt" <<< "$songs" 2>/dev/null)"
if [ -z "$choice" ]; then
# Assume user is looking for another list
# Kick him back to the main menu
rofimenu
fi
log "User picked: $choice"
queuesong "$choice"
[ "$?" = "1" ] && return 62
execqueue
return 0 return 0
} }
playlist() { playlist() {
[ -z "$1" ] && return 1 validateplaylistenv "$1" || return $?
[ -e "$1" ] || error "Playlist \"$1\" does not exist" 50
[ -f "$1" ] || error "Playlist \"$1\" is not a file" 50
[ -r "$1" ] || error "Cannot read playlist \"$1\"" 51
if [ -z "$_optdownloadonly" ] && ! mpc status > /dev/null 2>&1; then
notify "Could not communicate with MPD" \
"MPD connection was refused. Ensure your configuration is correct and the daemon is currently running." \
normal dialog-error 3000
error "Failed to communicate with MPD" 52
fi
[ -z "$_optdryrun" ] && local -a queue # An array of songs to later enqueue into mpd [ -z "$_optdryrun" ] && local -a queue # An array of songs to later enqueue into mpd
local -i dlexist=0 local -i dlexist=0
local -i dlsuccess=0 local -i dlsuccess=0
local -i dlfailure=0 local -i dlfailure=0
local -i maxlines=0 local -i maxlines=0
while read line; do while read line; do
# Strictly speaking, this removes all whitespace from the line
# While not *exactly* what I'm looking for, it's sufficient for trimming whitespace lines
validateline "$line" || continue validateline "$line" || continue
maxlines+=1 maxlines+=1
done < "$1" done < "$1"
@ -247,50 +350,20 @@ playlist() {
validateline "$line" || continue validateline "$line" || continue
rm "$_tmpfile"* > /dev/null 2>&1 rm "$_tmpfile"* > /dev/null 2>&1
# Do the do # Do the do
cachesong "$line" queuesong "$line"
# What did we do? # What did we do?
local errorcode=$? local errorcode=$?
if [ -z "$_optdryrun" ]; then case $errorcode in
case $errorcode in 0)
0) dlsuccess+=1
# Downloaded ;;
log "Downloaded song \"$line\"" 100)
dlsuccess+=1 dlexist+=1
;; ;;
100) *)
# Cached dlfailure+=1
log "Using cached song \"$line\"" ;;
dlexist+=1 esac
;;
*)
# Failed
dlfailure+=1
notify "Could not download song" \
"youtube-dl did not download a song for \"$line\"" \
normal dialog-error 3000
error "Could not download song \"$line\""
continue
;;
esac
queue+=("$_return")
else
case $errorcode in
0)
# Success
if [ -n "$_return" ]; then
log "$line - \"$output\""
else
log "$line parsed, but title could not be extracted"
fi
dlsuccess+=1
;;
*)
# Failure
error "Could not find song \"$line\""
dlerror+=1
;;
esac
fi
done < <(if [ -n "$_optshuffle" ]; then shuf "$1"; else cat "$1"; fi) done < <(if [ -n "$_optshuffle" ]; then shuf "$1"; else cat "$1"; fi)
if [ "$dlexist" = "0" ] && [ "$dlsuccess" = "0" ] && [ -z "$_optdryrun" ]; then if [ "$dlexist" = "0" ] && [ "$dlsuccess" = "0" ] && [ -z "$_optdryrun" ]; then
notify "Failed to download playlist" \ notify "Failed to download playlist" \
@ -301,15 +374,7 @@ playlist() {
notify "Finished downloading playlist" \ notify "Finished downloading playlist" \
"The playlist has been downloaded and will be added to mpd shortly" "The playlist has been downloaded and will be added to mpd shortly"
log "Finished downloading: $dlexist cached, $dlsuccess downloaded, $dlfailure failed" log "Finished downloading: $dlexist cached, $dlsuccess downloaded, $dlfailure failed"
mpc update --wait > /dev/null 2>&1 execqueue
for file in "${queue[@]}"; do
file=${file##$_musicdir/}
mpc add "$file" > /dev/null 2>&1 || error "Could not add file: \"$file\""
done
if [ -n "$_optautoplay" ]; then
mpc play > /dev/null 2>&1
unset _optautoplay
fi
else else
notify "Finished precaching" \ notify "Finished precaching" \
"Your songs have been cached and are ready for offline playback" "Your songs have been cached and are ready for offline playback"
@ -329,7 +394,7 @@ main() {
trap trapexit EXIT trap trapexit EXIT
# Actual program stuff # Actual program stuff
while getopts ":cdDf:pr:sh" opt; do while getopts ":cdDf:pr:R:sh" opt; do
case $opt in case $opt in
c) c)
clearcache clearcache
@ -350,6 +415,10 @@ main() {
r) r)
_optrofi="$OPTARG" _optrofi="$OPTARG"
;; ;;
R)
_optrofi="$OPTARG"
_optrofisong=1
;;
s) s)
_optshuffle=1 _optshuffle=1
;; ;;