161 lines
3.4 KiB
Bash
Executable File
161 lines
3.4 KiB
Bash
Executable File
#! /bin/bash
|
|
#
|
|
# jptgdp - Just Play the Goddamn Playlist
|
|
# Copyright (C) 2019 Vintage Salt <rehashedsalt@cock.li>
|
|
#
|
|
# Distributed under terms of the MIT license.
|
|
#
|
|
|
|
# TODO:
|
|
# * Provide integration with other players, like mpd
|
|
# * Actually add that rofi support cuz I want it
|
|
# * Add a quick way to append to a playlist
|
|
|
|
# Variables
|
|
_name="$(basename -- "$0")"
|
|
_tmpdir="${XDG_CACHE_HOME:-$HOME/.cache}/$_name"
|
|
_tmpfile="$_tmpdir/tmpfile"
|
|
_xdguserdirs="${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs"
|
|
[ -f "$_xdguserdirs" ] && source "$_xdguserdirs"
|
|
_musicdir="${XDG_MUSIC_DIR:-$HOME/Music}/JPTGDP Songs"
|
|
|
|
# Helper functions
|
|
log() {
|
|
[ -z "$1" ] && return 1
|
|
printf "%s: %s\\n" \
|
|
"$_name" \
|
|
"$1"
|
|
}
|
|
error() {
|
|
[ -z "$1" ] && return 1
|
|
[ -z "$2" ] && return 2
|
|
log "$1"
|
|
exit "${2:-1}"
|
|
}
|
|
validatedeps() {
|
|
for prog in "$@"; do
|
|
if ! command -v "$prog" > /dev/null 2>&1; then
|
|
_return="$prog"
|
|
return 1
|
|
fi
|
|
done
|
|
return 0
|
|
}
|
|
|
|
# Traps
|
|
trapexit() {
|
|
kill $(jobs -p) > /dev/null 2>&1
|
|
[ -n "$_tmpdir" ] && rm "$_tmpfile"* > /dev/null 2>&1
|
|
}
|
|
|
|
# Critical functions
|
|
clearcache() {
|
|
[ -n "$_musicdir" ] && rm "$_musicdir"/* > /dev/null 2>&1
|
|
log "Cache has been emptied"
|
|
}
|
|
helptext() {
|
|
cat << EOF
|
|
Usage: $_name [OPTION]
|
|
Use youtube-dl and audacious to queue up a playlist given a file of only search
|
|
queries.
|
|
-f <file> The playlist file to load
|
|
|
|
-c Clears the cache (which can become quite large)
|
|
-d Download only; don't queue anything up
|
|
-s Shuffle the playlist
|
|
|
|
-r <directory> Start up rofi, if installed, and present a listing of
|
|
all .ytp files in the given directory
|
|
|
|
-h Print this help text
|
|
|
|
Copyright (c) 2019 rehashedsalt@cock.li
|
|
Licensed under the MIT license
|
|
EOF
|
|
}
|
|
rofimenu() {
|
|
validatedeps rofi || error "$_return is not currently installed" 1
|
|
error "Not yet implemented" 1
|
|
return 0
|
|
}
|
|
playlist() {
|
|
[ -z "$1" ] && return 1
|
|
[ -f "$1" ] || error "Attempted to access non-file playlist \"$1\"" 50
|
|
[ -r "$1" ] || error "Cannot read playlist \"$1\"" 51
|
|
while read line; do
|
|
[ -z "$line" ] && continue
|
|
rm "$_tmpfile"* > /dev/null 2>&1
|
|
filename="$_musicdir/${line//[^ a-zA-Z0-9\[\]|()_-]/}"
|
|
if ! [ -f "$filename" ]; then
|
|
log "Finding a song for \"$line\""
|
|
youtube-dl \
|
|
--add-metadata \
|
|
--audio-format "best" \
|
|
--geo-bypass \
|
|
--playlist-items 1 \
|
|
-x \
|
|
-o "$_tmpfile.%(ext)s" \
|
|
ytsearch:"$line" \
|
|
> /dev/null 2>&1 &
|
|
if wait $!; then
|
|
mv "$_tmpfile"* "$filename"
|
|
else
|
|
log "No results found for \"$line\""
|
|
fi
|
|
fi
|
|
[ -z "$_optdownloadonly" ] && audacious -e "$filename"
|
|
done < <(if [ -n "$_optshuffle" ]; then shuf "$1"; else cat "$1"; fi)
|
|
if [ -z "$_optdownloadonly" ]; then
|
|
log "Finished building queue"
|
|
else
|
|
log "Finished downloading"
|
|
fi
|
|
}
|
|
|
|
# Main
|
|
main() {
|
|
# Boostrapping and setup
|
|
validatedeps basename mktemp || error "Critical dependency $_return was not met" 1
|
|
mkdir -p "$_tmpdir"
|
|
mkdir -p "$_musicdir"
|
|
trap trapexit EXIT
|
|
|
|
# Actual program stuff
|
|
while getopts ":cdf:r:sh" opt; do
|
|
case $opt in
|
|
c)
|
|
clearcache
|
|
exit $?
|
|
;;
|
|
d)
|
|
_optdownloadonly=1
|
|
;;
|
|
f)
|
|
_optfile="$OPTARG"
|
|
;;
|
|
r)
|
|
_optrofi=1
|
|
;;
|
|
s)
|
|
_optshuffle=1
|
|
;;
|
|
h)
|
|
helptext
|
|
exit $?
|
|
;;
|
|
:)
|
|
error "Option requires argument: -$OPTARG" 2
|
|
;;
|
|
*)
|
|
error "Invalid option: -$OPTARG" 2
|
|
;;
|
|
esac
|
|
done
|
|
if [ -n "$_optrofi" ]; then rofimenu; exit $?; fi
|
|
if [ -n "$_optfile" ]; then playlist "$_optfile"; exit $?; fi
|
|
error "Nothing to do" 0
|
|
}
|
|
|
|
main "$@"
|
|
|