ptgdp: More modularization, add individual song selection mode
This commit is contained in:
parent
dd24705821
commit
d7b8c7e392
179
ptgdp
179
ptgdp
@ -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
|
||||||
|
if [ -z "$_optrofisong" ]; then
|
||||||
playlist "$_optrofi"/"$choice".gdp
|
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)
|
||||||
# Downloaded
|
|
||||||
log "Downloaded song \"$line\""
|
|
||||||
dlsuccess+=1
|
dlsuccess+=1
|
||||||
;;
|
;;
|
||||||
100)
|
100)
|
||||||
# Cached
|
|
||||||
log "Using cached song \"$line\""
|
|
||||||
dlexist+=1
|
dlexist+=1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
# Failed
|
|
||||||
dlfailure+=1
|
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
|
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
|
||||||
;;
|
;;
|
||||||
|
Loading…
Reference in New Issue
Block a user