#! /bin/bash # # jptgdp - Just Play the Goddamn Playlist # Copyright (C) 2019 Vintage Salt # # Distributed under terms of the MIT license. # # 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" _playlistdir="${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 "$_playlistdir" ] && rm "$_playlistdir"/* > /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. -c Clears the cache (which can become quite large) -d Download only; don't queue anything up -f The playlist file to load -r Start up rofi, if installed, and present a listing of all .ytp files in the given directory -s Shuffle the playlist -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="$_playlistdir/${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 "$_playlistdir" 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 "$@"