vaporget 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #!/bin/sh
  2. #
  3. # Copyright (C) 2020 Matteo Savatteri and Matteo Zeccoli Marazzini.
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. # Global Variables
  18. PROGRAM_NAME="vaporget"
  19. PROGRAM_VERSION="0.1-alpha"
  20. PROGRAM_UPSTREAM="https://lcm.mi.infn.it/gogs/matteozeccolimarazzini/vaporget.git"
  21. AUTHOR_NAME="Matteo Savatteri and Matteo Zeccoli Marazzini"
  22. CMDLINE="$@"
  23. MODE="play"
  24. USAGE="Usage: $PROGRAM_NAME [-Vh] [-pd | -m MPV_OPTION,...]"
  25. HELP_TEXT="$USAGE
  26. Get and play music from the Vaporwave Library Project.
  27. Play music with mpv(1) if none of -pd is specified.
  28. -p only print selected URLs to standard output
  29. -d donwload selected songs in current working directory
  30. -m MPV_OPTION,... pass options to mpv(1) (incompatible with -pd)
  31. -V output version information and exit
  32. -h display this extremely helpful text and exit
  33. Exit Status:
  34. 0 if OK,
  35. 1 some errors occurred."
  36. LOGO_MONOCHROME=" _______________
  37. /-------------/|
  38. | _ _ ||
  39. | (_) VG (_) ||
  40. |______________||
  41. |==============|/"
  42. LOGO_8_COLORS="\
  43. \033[35;44m _______________ \033[0m
  44. \033[35;44m /-------------/| \033[0m
  45. \033[35;44m | _ _ || \033[0m
  46. \033[35;44m | (_) \033[37mVG\033[35m (_) || \033[0m
  47. \033[35;44m |______________|| \033[0m
  48. \033[35;44m |==============|/ \033[0m"
  49. LOGO_256_COLORS=" _______________
  50. /-------------/|
  51. | _ _ ||
  52. | (_) VG (_) ||
  53. |______________||
  54. |==============|/"
  55. VERSION_INFOTEXT="$PROGRAM_NAME $PROGRAM_VERSION
  56. git upstream $PROGRAM_UPSTREAM
  57. Copyright (C) 2020 $AUTHOR_NAME.
  58. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
  59. This is free software: you are free to change and redistribute it.
  60. There is NO WARRANTY, to the extent permitted by law.
  61. Written by $AUTHOR_NAME."
  62. WEBSITE="https://vaporwave.ivan.moe/list/"
  63. ###############################################################################
  64. # USEFUL FUNCTIONS #
  65. ###############################################################################
  66. # Check options
  67. # Arguments: none
  68. # Analize ARGVs in this order of precedence:
  69. # Look for -h; If found, return 2
  70. # Look for incompatible options; if found, return 1
  71. # Look for -V; if found, return 2
  72. check_options()
  73. {
  74. local OPTIONS_STRING=$(printf -- "$CMDLINE" | sed -e 's/ [^-]*//g' -e 's/-//g')
  75. if [ "${OPTIONS_STRING#*h}" != "$OPTIONS_STRING" ]
  76. then
  77. printf "$HELP_TEXT\n"
  78. return 2
  79. fi
  80. if [ "${OPTIONS_STRING#*m}" != "$OPTIONS_STRING" -a \( "${OPTIONS_STRING#*d}" != "$OPTIONS_STRING" -o "${OPTIONS_STRING#*p}" != "$OPTIONS_STRING" \) ]
  81. then
  82. printf "$PROGRAM_NAME: incompatible options -- m, pd\n$USAGE\n" >&2
  83. return 1
  84. fi
  85. if [ "${OPTIONS_STRING#*V}" != "$OPTIONS_STRING" ]
  86. then
  87. COLORS=$(tput colors)
  88. if [ $COLORS -lt 8 ]
  89. then
  90. LOGO=$LOGO_MONOCHROME
  91. elif [ $COLORS -lt 256 ]
  92. then
  93. LOGO=$LOGO_8_COLORS
  94. else
  95. LOGO=$LOGO_256_COLORS
  96. fi
  97. printf "$LOGO\n\n$VERSION_INFOTEXT\n"
  98. return 2
  99. fi
  100. return 0
  101. }
  102. # Download the html list of artists and urls
  103. # Arguments: $1 = music library website
  104. # Write to standard output a file made like this:
  105. # "[url]\n[artist]\noff\n"... (repeat for each artist)
  106. # The "off" at the end is needed by dialog.
  107. get_library()
  108. {
  109. wget -qO- "$1" 2>/dev/null \
  110. | grep "^<a href" \
  111. | sed -e 's/<a href="//' \
  112. -e 's/">/\n/' \
  113. -e 's/&gt;<\/a>.*/\noff/' \
  114. -e 's/\/<\/a>.*/\noff/'
  115. }
  116. # Let the user select the artists he likes using a dialog checklist
  117. # Arguments: $1 = music library website
  118. # Write to standard output a '\n' separated list of the url of the selected artists.
  119. # If the user selects cancel or presses ESC, send a SIGTERM to the script and all its subprocesses.
  120. select_artist_list()
  121. {
  122. { 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 -$$; } \
  123. | sed -e 's/ /\n/g' -e '$a\' \
  124. | sed -e 's,^,'"$1"','
  125. }
  126. # Prepare a list of song urls
  127. # Arguments: $1 = list of selected artist urls
  128. # Write to standard output and error the urls of all the songs by the selected artists.
  129. prepare_playlist()
  130. {
  131. wget --spider -r -l inf --no-parent --no-directories $1 2>&1 \
  132. | grep --line-buffered '^--' \
  133. | stdbuf -oL cut -d' ' -f4 \
  134. | grep --line-buffered '\.\(flac\|mp3\|wav\)$' \
  135. | tee /dev/stderr
  136. }
  137. # Plays the playlist it recieves via standard input
  138. play_music()
  139. {
  140. mpv --no-video --playlist=- $MPV_CMDLINE
  141. }
  142. # TERM signal handler
  143. handle_term()
  144. {
  145. clear
  146. exit 0
  147. }
  148. ###############################################################################
  149. # MAIN SECTION #
  150. ###############################################################################
  151. # Look for incompatible command line options
  152. check_options
  153. case $? in
  154. 1)
  155. exit 1
  156. ;;
  157. 2)
  158. exit 0
  159. ;;
  160. esac
  161. # Parse command line
  162. while getopts pdm:Vh f; do
  163. case $f in
  164. p)
  165. MODE="playlist"
  166. ;;
  167. d)
  168. MODE="download"
  169. ;;
  170. m)
  171. MPV_CMDLINE=$(printf "${OPTARG}" | sed -e 's/[[:space:]]//g' -e 's/[^,]\{2,\}/--& /g' -e 's/\(^\|,\)[[:alnum:]]\($\|,\)/ -& /g' -e 's/,//g')
  172. ;;
  173. \?)
  174. printf "${USAGE}\n" >&2 && exit 1
  175. ;;
  176. esac
  177. done
  178. shift $(( $OPTIND - 1 ))
  179. # Use our custom handler for the TERM signal
  180. trap handle_term TERM
  181. # Fetch the artist list from the website and let the user select from a menu
  182. CHOICES=$(get_library "${WEBSITE}" | select_artist_list "${WEBSITE}")
  183. clear
  184. if [ -z "${CHOICES}" ]; then # User didn't select any artist
  185. printf "Please, select at least one artist.\n" >&2
  186. exit 1
  187. fi
  188. # Play the music
  189. case $MODE in
  190. "play")
  191. prepare_playlist "${CHOICES}" | play_music
  192. ;;
  193. "playlist")
  194. prepare_playlist "${CHOICES}" 2>/dev/null
  195. ;;
  196. "download")
  197. prepare_playlist "${CHOICES}" | wget -i -
  198. ;;
  199. esac