vaporget 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. VERSION_INFOTEXT="$PROGRAM_NAME $PROGRAM_VERSION
  37. git upstream $PROGRAM_UPSTREAM
  38. Copyright (C) 2020 $AUTHOR_NAME.
  39. License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
  40. This is free software: you are free to change and redistribute it.
  41. There is NO WARRANTY, to the extent permitted by law.
  42. Written by $AUTHOR_NAME."
  43. WEBSITE="https://vaporwave.ivan.moe/list/"
  44. ###############################################################################
  45. # USEFUL FUNCTIONS #
  46. ###############################################################################
  47. # Check options
  48. # Arguments: none
  49. # Analize ARGVs in this order of precedence:
  50. # Look for -h; If found, return 2
  51. # Look for incompatible options; if found, return 1
  52. # Look for -V; if found, return 2
  53. check_options()
  54. {
  55. local OPTIONS_STRING=$(printf -- "$CMDLINE" | sed -e 's/ [^-]*//g' -e 's/-//g')
  56. if [ "${OPTIONS_STRING#*h}" != "$OPTIONS_STRING" ]
  57. then
  58. printf "$HELP_TEXT\n"
  59. return 2
  60. fi
  61. if [ "${OPTIONS_STRING#*m}" != "$OPTIONS_STRING" -a \( "${OPTIONS_STRING#*d}" != "$OPTIONS_STRING" -o "${OPTIONS_STRING#*p}" != "$OPTIONS_STRING" \) ]
  62. then
  63. printf "$PROGRAM_NAME: incompatible options -- m, pd\n$USAGE\n" >&2
  64. return 1
  65. fi
  66. if [ "${OPTIONS_STRING#*V}" != "$OPTIONS_STRING" ]
  67. then
  68. printf "$VERSION_INFOTEXT\n"
  69. return 2
  70. fi
  71. return 0
  72. }
  73. # Download the html list of artists and urls
  74. # Arguments: $1 = music library website
  75. # Write to standard output a file made like this:
  76. # "[url]\n[artist]\noff\n"... (repeat for each artist)
  77. # The "off" at the end is needed by dialog.
  78. get_library()
  79. {
  80. wget -qO- "$1" 2>/dev/null \
  81. | grep "^<a href" \
  82. | sed -e 's/<a href="//' \
  83. -e 's/">/\n/' \
  84. -e 's/&gt;<\/a>.*/\noff/' \
  85. -e 's/\/<\/a>.*/\noff/'
  86. }
  87. # Let the user select the artists he likes using a dialog checklist
  88. # Arguments: $1 = music library website
  89. # Write to standard output a '\n' separated list of the url of the selected artists.
  90. # If the user selects cancel or presses ESC, send a SIGTERM to the script and all its subprocesses.
  91. select_artist_list()
  92. {
  93. { 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 -$$; } \
  94. | sed -e 's/ /\n/g' -e '$a\' \
  95. | sed -e 's,^,'"$1"','
  96. }
  97. # Prepare a list of song urls
  98. # Arguments: $1 = list of selected artist urls
  99. # Write to standard output and error the urls of all the songs by the selected artists.
  100. prepare_playlist()
  101. {
  102. wget --spider -r -l inf --no-parent --no-directories $1 2>&1 \
  103. | grep --line-buffered '^--' \
  104. | stdbuf -oL cut -d' ' -f4 \
  105. | grep --line-buffered '\.\(flac\|mp3\|wav\)$' \
  106. | tee /dev/stderr
  107. }
  108. # Plays the playlist it recieves via standard input
  109. play_music()
  110. {
  111. mpv --no-video --playlist=- $MPV_CMDLINE
  112. }
  113. # TERM signal handler
  114. handle_term()
  115. {
  116. clear
  117. exit 0
  118. }
  119. ###############################################################################
  120. # MAIN SECTION #
  121. ###############################################################################
  122. # Look for incompatible command line options
  123. check_options
  124. case $? in
  125. 1)
  126. exit 1
  127. ;;
  128. 2)
  129. exit 0
  130. ;;
  131. esac
  132. # Parse command line
  133. while getopts pdm:Vh f; do
  134. case $f in
  135. p)
  136. MODE="playlist"
  137. ;;
  138. d)
  139. MODE="download"
  140. ;;
  141. m)
  142. MPV_CMDLINE=$(printf "${OPTARG}" | sed -e 's/[[:space:]]//g' -e 's/[^,]\{2,\}/--& /g' -e 's/\(^\|,\)[[:alnum:]]\($\|,\)/ -& /g' -e 's/,//g')
  143. ;;
  144. \?)
  145. printf "${USAGE}\n" >&2 && exit 1
  146. ;;
  147. esac
  148. done
  149. shift $(( $OPTIND - 1 ))
  150. # Use our custom handler for the TERM signal
  151. trap handle_term TERM
  152. # Fetch the artist list from the website and let the user select from a menu
  153. CHOICES=$(get_library "${WEBSITE}" | select_artist_list "${WEBSITE}")
  154. clear
  155. if [ -z "${CHOICES}" ]; then # User didn't select any artist
  156. printf "Please, select at least one artist.\n" >&2
  157. exit 1
  158. fi
  159. # Play the music
  160. case $MODE in
  161. "play")
  162. prepare_playlist "${CHOICES}" | play_music
  163. ;;
  164. "playlist")
  165. prepare_playlist "${CHOICES}" 2>/dev/null
  166. ;;
  167. "download")
  168. prepare_playlist "${CHOICES}" | wget -i -
  169. ;;
  170. esac