music.sh 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #!/bin/sh
  2. #
  3. # Copyright 2016 Sylvia van Os <iamsylvie@openmailbox.org>
  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. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. SCRIPT=$(readlink -f "$0")
  16. SCRIPTPATH=$(dirname "$SCRIPT")
  17. unset config_music_directory
  18. unset config_state_directory
  19. . "$SCRIPTPATH/config.sh"
  20. if [ ! -d "$config_music_directory" ]; then
  21. echo "config_music_directory is not a valid directory" 1>&2
  22. exit 1
  23. fi
  24. if [ ! -d "$config_queue_directory" ]; then
  25. echo "config_queue_directory is not a valid directory" 1>&2
  26. exit 1
  27. fi
  28. if [ ! -d "$config_state_directory" ]; then
  29. echo "config_state_directory is not a valid directory" 1>&2
  30. exit 1
  31. fi
  32. main() {
  33. trap cleanUp INT
  34. cleanUp() {
  35. kill "$(cat "$config_state_directory/mplayer_pid")"
  36. rm "$config_state_directory/mplayer_input"
  37. rm "$config_state_directory/mplayer_output"
  38. rm "$config_state_directory/mplayer_pid"
  39. exit
  40. }
  41. if [ ! -p "$config_state_directory/mplayer_input" ]; then
  42. mkfifo "$config_state_directory/mplayer_input"
  43. fi
  44. playSong() {
  45. getRandomSong() {
  46. find "$config_music_directory" ! -name "$(printf "*\n*")" -type f | shuf -n1
  47. }
  48. if [ -f "$config_state_directory/mplayer_pid" ]; then
  49. if ps -p "$(cat "$config_state_directory/mplayer_pid")" >/dev/null; then
  50. # Already playing a song
  51. return 1
  52. fi
  53. fi
  54. for queue_entry in "$config_queue_directory/"*; do
  55. if [ ! -e "$queue_entry" ]; then
  56. song="$(getRandomSong)"
  57. if [ ! "$?" ]; then
  58. echo "No songs in $config_music_directory" 1>&2
  59. return 2
  60. fi
  61. else
  62. song="$(readlink -f "$queue_entry")"
  63. rm "$queue_entry"
  64. fi
  65. break
  66. done
  67. mplayer "$song" -vo null -quiet -slave -input file="$config_state_directory/mplayer_input" >"$config_state_directory/mplayer_output" 2>/dev/null &
  68. echo "$!" > "$config_state_directory/mplayer_pid"
  69. }
  70. while true; do
  71. playSong
  72. sleep 1
  73. done
  74. }
  75. info() {
  76. if [ ! -f "$config_state_directory/mplayer_pid" ]; then
  77. echo "Mplayer does not appear to be running. Did you forget to start the daemon?" >&2
  78. return 1
  79. fi
  80. echo "get_file_name" >"$config_state_directory/mplayer_input"
  81. echo "get_meta_artist" >"$config_state_directory/mplayer_input"
  82. echo "get_meta_title" >"$config_state_directory/mplayer_input"
  83. echo "get_meta_album" >"$config_state_directory/mplayer_input"
  84. echo "get_time_pos" >"$config_state_directory/mplayer_input"
  85. echo "get_time_length" >"$config_state_directory/mplayer_input"
  86. echo "get_percent_pos" >"$config_state_directory/mplayer_input"
  87. sleep 1 # Hack to make sure the data is populated
  88. tail -n7 "$config_state_directory/mplayer_output"
  89. }
  90. enqueue() {
  91. for queue_number in "$config_queue_directory/"*; do
  92. if [ ! -e "$queue_number" ]; then
  93. number=-1
  94. else
  95. number="$queue_number"
  96. fi
  97. done
  98. find "$config_music_directory" ! -name "$(printf "*\n*")" -type f | sort
  99. while IFS= read -r song; do
  100. result=$(ffprobe "$song" 2>&1 | grep -A90 'Metadata:' | tr '[:upper:]' '[:lower:]')
  101. correct=1
  102. for arg in "$@"; do
  103. arg="$(echo "$arg" | tr '[:upper:]' '[:lower:]')"
  104. tag="$(echo "$arg" | cut -d'=' -f1)"
  105. query="$(echo "$arg" | cut -d'=' -f2-)"
  106. case "$(echo "$result" | sed -n -e 's/^\s*'"$tag"'.*: //p')" in
  107. *"$query"*) ;; # Still fine
  108. *) correct=0
  109. esac
  110. done
  111. if [ "$correct" = 1 ]; then
  112. number=$((number+1))
  113. ln -s "$song" "$config_queue_directory/$number"
  114. echo "Enqueued $song"
  115. fi
  116. done
  117. }
  118. next() {
  119. if kill "$(cat "$config_state_directory/mplayer_pid")" 2>/dev/null; then
  120. exit 0
  121. fi
  122. echo "Not currently playing anything. Is the daemon running?" >&2
  123. exit 1
  124. }
  125. action="info"
  126. while getopts ":den" opt; do
  127. case $opt in
  128. d)
  129. action="main"
  130. ;;
  131. e)
  132. action="enqueue"
  133. ;;
  134. n)
  135. action="next"
  136. ;;
  137. \?)
  138. echo "Invalid option: -$OPTARG" >&2
  139. exit 1
  140. ;;
  141. esac
  142. done
  143. shift # Remove the empty argument left by getopts
  144. $action "$@"