fi
}
+# On slow systems, ~.3 seconds before mpv is ready after starting. This
+# impatiently waits.
+mpvrpc-wait-idle() {
+ local -i i
+ for (( i=0; i<20; i++ )); do
+ if [[ $(mpvrpco '{ "command": ["get_property", "idle-active"] }' 2>/dev/null | jq .data) == true ]]; then
+ return
+ fi
+ sleep .1
+ done
+
+}
mpvrpc-loadfile() {
local path nextpath cachedir finalpath nextpath count
#
# Sets variables: pl_state_path pl_seed_path. Does mkdir of their directory.
#
-# Creates/recreates $pl_seed_path if needed.
+# Creates/recreates file $pl_seed_path if needed.
#
-# Input vars: random
+# Input vars: random, new_random
pl-state-init() {
local seed_num seed_file pl_state_dir pl_state_file
# note: this structure of files is rather haphazard.
pl_state_path=$pl_state_dir/$pl_state_file
pl_seed_path=$pl_state_dir/$seed_file
+ readonly pl_state_path pl_seed_path
if $new_random || [[ ! -r $pl_seed_path ]]; then
{ base64 < /dev/urandom | head -c 200 ||:; echo; } > $pl_seed_path
button_i[${buttons[i]}]=$i
done
- }
+}
# Call from beetag. Queries our songlist and parses it into variables.
#
ls_lines+=("$ls_line")
done
- }
+}
+
+# Output most of 1 page worth of playlist entries near the current song.
+#
+# I only care to see a smallish portion of the list when starting.
+#
+# Input vars: j, id_count, ls_lines
+beetag-head-playlist() {
+ local head_count head_start ls_line
+ local -i i
+ head_count=$(( LINES - 20 ))
+ head_start=$(( j - head_count / 2 ))
+ if (( head_start < 0 )); then
+ head_start=0
+ fi
+ for (( i=head_start; i < head_count && i < id_count; i++ )); do
+ ls_line="${ls_lines[$i]}"
+ if (( i == j )); then
+ echo "* $ls_line"
+ else
+ echo "$ls_line"
+ fi
+ done
+}
# tag with beets.
# usage: beetag [-r] [-s] QUERY
# todo: enter should also unpause
beetag() {
source /a/bin/ds/beet-data
- local last_genre_i tag id char new_item char_i tag remove doplay i j random path
- local read_wait line lsout ls_line skip_lookback do_rare_genres pl_state_path
- local escape_char escaped_input expected_input skip_input_regex erasable_line seek_sec
- local new_random pl_seed_path first_play repeat1
- local -a buttons button_map ids tags tmp_tags ls_lines paths beet_query
+
+ # state vars altered by user input:
+ local char do_rare_genres last_genre_i doplay=true repeat1=false
+ local -i volume=70 read_wait=2 j=0
+ local -a button_map
local -A button_i
- local -i i j volume scrolled id_count line_int skip_start pre_j_count head_count skip_lookback
- local -i overflow_lines overflow
- first_play=true
- erasable_line=false
- escape_char=$(printf "\u1b")
- scrolled=999 # more than any $LINES
+ # cli options / args
+ local new_random random
+ local -a beet_query
+
+ # constants
+ local escape_char pl_state_path pl_seed_path
+ local -ar buttons=( {a..p} {r..w} {6..8} , . / - "=")
+ local -r skip_input_regex="^[0-9]+$"
+
+ # song list vars:
+ local -a ids ls_lines paths
+ local -i id_count
+
+ # current song vars:
+ local id ls_out path
+ local -a tags
+
+ # boolean state vars
+ local expected_input remove first_play=true erasable_line=false
+
+ # iterator vars
+ local ls_line tag
+
+ # misc vars
+ local char_i escaped_input new_item seek_sec
+ local -i scrolled=999 # more than any $LINES
+ local -i i ret line_int skip_start pre_j_count skip_lookback overflow_lines overflow
+
### begin arg processing ###
random=false
- repeat1=false
new_random=false
case $1 in
-r)
beet_query=("$@")
### end arg processing ###
- readonly -a buttons=( {a..p} {r..w} {6..8} , . / - "=")
+ escape_char=$(printf "\u1b")
+ readonly escape_char
- ### begin control knob vars ###
- volume=70
- doplay=true
- ### end control knob vars ###
- read_wait=2
toggle-rare-genres
pl-state-init
beetag-ls-setup
- j=0
- if [[ $playlist ]]; then
- if [[ -r $pl_state_path ]]; then
- j=$(cat $pl_state_path)
- fi
+ if [[ $playlist && -r $pl_state_path ]]; then
+ j=$(cat $pl_state_path) # playlist position.
fi
- # i only care to see a smallish portion of the list when starting.
- head_count=$(( LINES - 20 ))
- head_start=$(( j - head_count / 2 ))
- if (( head_start < 0 )); then
- head_start=0
- fi
- for (( i=head_start; i < head_count && i < id_count; i++ )); do
- ls_line="${ls_lines[$i]}"
- if (( i == j )); then
- echo "* $ls_line"
- else
- echo "$ls_line"
- fi
- done
- if $doplay; then
- #{ mpv --profile=a --volume=$volume --idle 2>&1 & } 2>/dev/null
- mpv --profile=a --volume=$volume --idle &
- # if we dont sleep, can expect an error like this:
- # socat[1103381] E connect(5, AF=1 "/tmp/mpvsock", 14): Connection refused
- sleep .1
- fi
+ beetag-head-playlist
+
+ #{ mpv --profile=a --volume=$volume --idle 2>&1 & } 2>/dev/null # todo: consider using again
+ mpv --profile=a --volume=$volume --idle &
+ sleep .1 # or else: socat[1103381] E connect(5, AF=1 "/tmp/mpvsock", 14): Connection refused
while true; do
id=${ids[j]}
path="${paths[$j]}"
- lsout="${ls_lines[j]}"
- tags=( ${lsout%%,*} )
+ ls_out="${ls_lines[j]}"
+ tags=( ${ls_out%%,*} )
beetag-help
- printf "██ %s\n" "$lsout"
+ printf "██ %s\n" "$ls_out"
beetag-nostatus 1
if $doplay; then
- # https://stackoverflow.com/a/7687716
- # note: duplicated down below
- #
- # notes on old method of invoking mpv each time:
- # https://superuser.com/questions/305933/preventing-bash-from-displaying-done-when-a-background-command-finishes-execut
- # we can't disown or run in a subshell or set +m because all that
- # disabled job control from working properly in ways we want.
- # todo: figure out some kind of answer to this. I think the solution
- # is that we are waiting in 2 second intervals and checking if the
- # background job exists. Instead, we should make mpv just idle
- # when it is done with a song and then send it a command to play a new track.
- #{ mpv --profile=a --volume=$volume "$path" 2>&1 & } 2>/dev/null
- # old
- #{ beet play "--args=--volume=$volume" "id:$id" 2>&1 & } 2>/dev/null
-
- # on slow systems, we may need to wait like .3 seconds before mpv
- # is ready. so impatiently check until it is ready
- if $first_play; then
- first_play=false
- for (( i=0; i<20; i++ )); do
- if [[ $(mpvrpco '{ "command": ["get_property", "idle-active"] }' 2>/dev/null | jq .data) == true ]]; then
- mpvrpc-loadfile "$path"
- break
- fi
- sleep .1
- done
- else
- mpvrpc-loadfile "$path"
- fi
+ if $first_play; then first_play=false; mpvrpc-wait-idle; fi
+ mpvrpc-loadfile "$path"
erasable_line=false
fi
+
while true; do
char=
if $doplay; then
"$escape_char")
expected_input=true
read -rsn2 escaped_input
- skip_input_regex="^[0-9]+$"
case $escaped_input in
# up char: show all the songs, use less
'[A')
m beetmq "id:$id" genre=$new_item
else
remove=false
- tmp_tags=()
for tag in ${tags[@]}; do
if [[ $new_item == "$tag" ]]; then
remove=true
- else
- tmp_tags+=("$tag")
fi
done
if $remove; then