#!/bin/sh
#
# Copyright (C) 2020 Matteo Savatteri and Matteo Zeccoli Marazzini.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# Global Variables
PROGRAM_NAME="vaporget"
PROGRAM_VERSION="0.1-alpha"
PROGRAM_UPSTREAM="https://lcm.mi.infn.it/gogs/matteozeccolimarazzini/vaporget.git"
AUTHOR_NAME="Matteo Savatteri and Matteo Zeccoli Marazzini"
CMDLINE="$@"
MODE="play"
USAGE="Usage: $PROGRAM_NAME [-Vh] [-pd | -m MPV_OPTION,...]"
HELP_TEXT="$USAGE
Get and play music from the Vaporwave Library Project.
Play music with mpv(1) if none of -pd is specified.
-p only print selected URLs to standard output
-d donwload selected songs in current working directory
-m MPV_OPTION,... pass options to mpv(1) (incompatible with -pd)
-V output version information and exit
-h display this extremely helpful text and exit
Exit Status:
0 if OK,
1 some errors occurred."
VERSION_INFOTEXT="$PROGRAM_NAME $PROGRAM_VERSION
git upstream $PROGRAM_UPSTREAM
Copyright (C) 2020 $AUTHOR_NAME.
License GPLv3+: GNU GPL version 3 or later .
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by $AUTHOR_NAME."
WEBSITE="https://vaporwave.ivan.moe/list/"
###############################################################################
# USEFUL FUNCTIONS #
###############################################################################
# Check options
# Arguments: none
# Analize ARGVs in this order of precedence:
# Look for -h; If found, return 2
# Look for incompatible options; if found, return 1
# Look for -V; if found, return 2
check_options()
{
local OPTIONS_STRING=$(printf -- "$CMDLINE" | sed -e 's/ [^-]*//g' -e 's/-//g')
if [ "${OPTIONS_STRING#*h}" != "$OPTIONS_STRING" ]
then
printf "$HELP_TEXT\n"
return 2
fi
if [ "${OPTIONS_STRING#*m}" != "$OPTIONS_STRING" -a \( "${OPTIONS_STRING#*d}" != "$OPTIONS_STRING" -o "${OPTIONS_STRING#*p}" != "$OPTIONS_STRING" \) ]
then
printf "$PROGRAM_NAME: incompatible options -- m, pd\n$USAGE\n" >&2
return 1
fi
if [ "${OPTIONS_STRING#*V}" != "$OPTIONS_STRING" ]
then
printf "$VERSION_INFOTEXT\n"
return 2
fi
return 0
}
# Download the html list of artists and urls
# Arguments: $1 = music library website
# Write to standard output a file made like this:
# "[url]\n[artist]\noff\n"... (repeat for each artist)
# The "off" at the end is needed by dialog.
get_library()
{
wget -qO- "$1" 2>/dev/null \
| grep "^/\n/' \
-e 's/><\/a>.*/\noff/' \
-e 's/\/<\/a>.*/\noff/'
}
# Let the user select the artists he likes using a dialog checklist
# Arguments: $1 = music library website
# Write to standard output a '\n' separated list of the url of the selected artists.
# If the user selects cancel or presses ESC, send a SIGTERM to the script and all its subprocesses.
select_artist_list()
{
{ xargs -d '\n' dialog --title "VAPORGET" --no-tags --checklist "Please, select an artist:" 0 0 0 3>&1 1>&2 2>&3 3>&- || kill -TERM -$$; } \
| sed -e 's/ /\n/g' -e '$a\' \
| sed -e 's,^,'"$1"','
}
# Prepare a list of song urls
# Arguments: $1 = list of selected artist urls
# Write to standard output and error the urls of all the songs by the selected artists.
prepare_playlist()
{
wget --spider -r -l inf --no-parent --no-directories $1 2>&1 \
| grep --line-buffered '^--' \
| stdbuf -oL cut -d' ' -f4 \
| grep --line-buffered '\.\(flac\|mp3\|wav\)$' \
| tee /dev/stderr
}
# Plays the playlist it recieves via standard input
play_music()
{
mpv --no-video --playlist=- $MPV_CMDLINE
}
# TERM signal handler
handle_term()
{
clear
exit 0
}
###############################################################################
# MAIN SECTION #
###############################################################################
# Look for incompatible command line options
check_options
case $? in
1)
exit 1
;;
2)
exit 0
;;
esac
# Parse command line
while getopts pdm:Vh f; do
case $f in
p)
MODE="playlist"
;;
d)
MODE="download"
;;
m)
MPV_CMDLINE=$(printf "${OPTARG}" | sed -e 's/[[:space:]]//g' -e 's/[^,]\{2,\}/--& /g' -e 's/\(^\|,\)[[:alnum:]]\($\|,\)/ -& /g' -e 's/,//g')
;;
\?)
printf "${USAGE}\n" >&2 && exit 1
;;
esac
done
shift $(( $OPTIND - 1 ))
# Use our custom handler for the TERM signal
trap handle_term TERM
# Fetch the artist list from the website and let the user select from a menu
CHOICES=$(get_library "${WEBSITE}" | select_artist_list "${WEBSITE}")
clear
if [ -z "${CHOICES}" ]; then # User didn't select any artist
printf "Please, select at least one artist.\n" >&2
exit 1
fi
# Play the music
case $MODE in
"play")
prepare_playlist "${CHOICES}" | play_music
;;
"playlist")
prepare_playlist "${CHOICES}" 2>/dev/null
;;
"download")
prepare_playlist "${CHOICES}" | wget -i -
;;
esac