music 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #!/bin/sh
  2. ## usage: music [-a]
  3. # music selector_name action [action_args...]
  4. abspath() {
  5. echo "$(cd "$(dirname "$1")" >/dev/null||exit; pwd)/"
  6. }
  7. DATA_HOME=${XDG_DATA_HOME:-"$HOME/.local/share"}
  8. XDG_DATA_DIRS=${XDG_DATA_DIRS:-/usr/local/share/:/usr/share/}
  9. playlist="$DATA_HOME/music/playlist"
  10. SELECTOR_DIRS="$(abspath "$0")${SELECTOR_DIRS}"
  11. is_local() {
  12. scheme="${1%%:*}"
  13. [ "$scheme" = 'file' ]
  14. }
  15. exists() {
  16. [ -f "${1#*://}" ]
  17. }
  18. print_usage() {
  19. printf "
  20. Usage:
  21. \t%s [-a]
  22. \t%s <selector_name> <action> [action_args...]
  23. Control the music player
  24. Options:
  25. -a\t\tappend to queue
  26. -h\t\tshow this help and quit
  27. For more details see music(1) and music(8)\n" "$1" "$1"
  28. }
  29. emplace() {
  30. pid=$(cat ~/.local/share/play/pid 2>/dev/null)
  31. if [ "$pid" = '' ] || ! kill -0 "$pid" 2>/dev/null
  32. then
  33. mpv --input-ipc-server=/tmp/play-mpv-socket --idle --no-terminal --no-video 2>&1 >/dev/null & # todo log
  34. pid=$!
  35. echo $pid > ~/.local/share/play/pid
  36. fi
  37. if [ "$1" = '' ]
  38. then
  39. mode="replace"
  40. echo >"$playlist"
  41. elif [ "$1" = '-a' ]
  42. then
  43. mode="append-play"
  44. fi
  45. # stdin entries must be URI; it is assumed, not checked
  46. songs=$(cat /dev/stdin)
  47. songs_head=$(echo "$songs" | head -n1)
  48. songs_tail=$(echo "$songs" | tail -n+2)
  49. is_idle=$(echo '{"command": ["get_property", "core-idle"]}' | socat - /tmp/play-mpv-socket | jq '.data' -r)
  50. is_active_idle=$(echo '{"command": ["get_property", "idle-active"]}' | socat - /tmp/play-mpv-socket | jq '.data' -r)
  51. uri=$(echo "$songs_head" | cut -d '' -f 2)
  52. if is_local "$uri" && ! exists "$uri"
  53. then
  54. printf "No such file %s\n" "$uri" >&2
  55. else
  56. reply=$(echo '{"command": ["loadfile", "'"$uri"'", "'"$mode"'"]}' | socat - /tmp/play-mpv-socket)
  57. echo "$songs_head" >>"$playlist"
  58. # todo print error
  59. fi
  60. if [ "$is_idle" = "true" ] && [ "$is_active_idle" = 'false' ] && [ "$mode" = "replace" ]
  61. then
  62. reply=$(echo '{"command": ["keypress", "PAUSE"]}' | socat - /tmp/play-mpv-socket)
  63. # todo print error
  64. fi
  65. echo "$songs_tail" | while read -r song
  66. do
  67. if [ "$song" ]
  68. then
  69. uri=$(echo "$song" | cut -d '' -f 2)
  70. if is_local "$uri" && ! exists "$uri"
  71. then
  72. printf "No such file %s\n" "$uri" >&2
  73. else
  74. reply=$(echo '{"command": ["loadfile", "'"$uri"'", "append"]}' | socat - /tmp/play-mpv-socket)
  75. echo "$song" >>"$playlist"
  76. # todo print error
  77. fi
  78. fi
  79. done
  80. }
  81. do_action() {
  82. selector_name="$1"
  83. action="$2"
  84. shift
  85. shift
  86. IFS=':'; for dir in $SELECTOR_DIRS
  87. do
  88. if [ -d "$dir/music/selectors" ] && ls "$dir/music/selectors" | grep "$selector_name" >/dev/null
  89. then
  90. selector="$dir/music/selectors/$selector_name"
  91. break
  92. fi
  93. done
  94. if [ "$selector" ]
  95. then
  96. "$selector/actions/$action" "$@"
  97. else
  98. echo "selector ‘$selector_name’ not found"
  99. fi
  100. }
  101. if [ "$1" = '-h' ]
  102. then
  103. print_usage "$0"
  104. elif [ "$1" = '-a' ] || [ "$1" = '' ]
  105. then
  106. emplace "$1"
  107. else
  108. do_action "$@"
  109. fi