diff --git a/src/awk/artists.awk b/src/awk/artists.awk index 87d22b6..9a3c29c 100644 --- a/src/awk/artists.awk +++ b/src/awk/artists.awk @@ -16,5 +16,5 @@ BEGIN { name = name " " format_disambiguation sub("<>", $4, name) sub("<>", $3, name) - print l, name, $1 + print l, name, "0", $1 } diff --git a/src/awk/recordings.awk b/src/awk/recordings.awk index 09efc2b..5118884 100644 --- a/src/awk/recordings.awk +++ b/src/awk/recordings.awk @@ -10,12 +10,13 @@ BEGIN { } { gsub("&", "\\\\&") - id = $1 - med = $2 - nr = $3 - dur = $4 - title = $5 - artist = $6 + parentid = $1 + id = $2 + med = $3 + nr = $4 + dur = $5 + title = $6 + artist = $7 # Parse duration if (dur) { dur = int(dur / 1000) @@ -37,5 +38,5 @@ BEGIN { sub("<>", dur, line) l = local_recordings[id] ? format_local : "" sortk = med" "nr - print sortk, l, line, id ":" local_recordings[id] + print sortk, l, line, parentid, id ":" local_recordings[id] } diff --git a/src/awk/releasegroups.awk b/src/awk/releasegroups.awk index 6e65729..95dfd78 100644 --- a/src/awk/releasegroups.awk +++ b/src/awk/releasegroups.awk @@ -58,5 +58,5 @@ BEGIN { line_year = year ? format_year : "" sub("<>", year, line_year) sortk = year ? year : 0 - print sortk, l, line_type, line_release, line_year, line_sectype, id + print sortk, l, line_type, line_release, line_year, line_sectype, "0", id } diff --git a/src/awk/releases.awk b/src/awk/releases.awk index 1d8484a..52ab75c 100644 --- a/src/awk/releases.awk +++ b/src/awk/releases.awk @@ -9,17 +9,18 @@ BEGIN { } } { - id = $1 - status = $2 - year = substr($3, 1, 4) + 0 + parentid = $1 + id = $2 + status = $3 + year = substr($4, 1, 4) + 0 year = year == 0 ? "" : year - covercount = $4 - label = $5 - trackcnt = $6 - media = $7 - country = $8 - title = $9 - artist = $10 + covercount = $5 + label = $6 + trackcnt = $7 + media = $8 + country = $9 + title = $10 + artist = $11 switch (status) { case "Official": line_status = release_official; break case "Promotion": line_status = release_promotion; break @@ -53,5 +54,5 @@ BEGIN { sub("<>", country, line) sortk = year ? year : 0 l = local_releases[id] ? format_local : "" - print sortk, l, line, id ":" local_releases[id] + print sortk, l, line, parentid, id ":" local_releases[id] } diff --git a/src/main.sh b/src/main.sh index 8891417..e049354 100755 --- a/src/main.sh +++ b/src/main.sh @@ -26,6 +26,9 @@ set -eu # Load MusicBrainz and Discogs methods . "sh/api.sh" +# Load mpv methods +. "sh/mpv.sh" + # Load preview methods . "sh/preview.sh" @@ -79,6 +82,7 @@ if [ "${1:-}" = "--fzf-load" ]; then $JQ -r '.title')" artist="$(mb_releasegroup "$args" | $JQ -r '."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")')" + QUERY="$(printf "%s " "$FORMAT_STATUS_OFFICIAL")" PROMPT=$(printf "$FULL_PROMPT" "$artist" "$title") ;; "$MODE_RELEASE") @@ -148,7 +152,7 @@ if [ "${1:-}" = "--fzf-change-reload" ]; then done # Show results column -t -s "$(printf '\t')" "$RESULTS" | - sed 's| \+\([0-9a-f-]\+\)$|\t\1|' + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' exit 0 fi @@ -231,9 +235,9 @@ if [ "${1:-}" = "--fzf-change" ]; then fi if [ "${1:-}" = "--fzf-key" ]; then - foo "KEY: $*; FZF_KEY=$FZF_KEY" - mbid="${2:-}" - path="${3:-}" + parentmbid="${2:-}" + mbid="${3:-}" + path="${4:-}" mode=$(cut -d "#" -f 1 "$MODEFILE") args=$(cut -d "#" -f 2- "$MODEFILE") @@ -517,10 +521,10 @@ case "${1:-}" in printf "%s#%s" "$MODE_SEARCH_ALBUM" "${2:-}" >"$MODEFILE" ;; "--artists" | "") - printf "%s" "$MODE_LIST_ARTISTS" >"$MODEFILE" + printf "%s#" "$MODE_LIST_ARTISTS" >"$MODEFILE" ;; "--albums") - printf "%s" "$MODE_LIST_ALBUMS" >"$MODEFILE" + printf "%s#" "$MODE_LIST_ALBUMS" >"$MODEFILE" ;; *) err "Unknown option $1 (see --help)" @@ -543,7 +547,7 @@ while true; do $FZF \ --bind="$KEYS_HALFPAGE_DOWN,$KEYS_HALFPAGE_UP,\ $KEYS_BROWSE,\ -$KEYS_FILTER_LOCAL:transform:$0 --fzf-key {2} {3}" \ +$KEYS_FILTER_LOCAL:transform:$0 --fzf-key {2} {3} {4}" \ -1 \ --border="bold" \ --border-label="Select artist" \ @@ -551,7 +555,7 @@ $KEYS_FILTER_LOCAL:transform:$0 --fzf-key {2} {3}" \ --prompt="$SEARCH_PROMPT" \ --margin="5%,20%" \ --bind="$KEYS_FILTER_LOCAL:change-query($FORMAT_LOCAL )" \ - --accept-nth="{2}" \ + --accept-nth="{3}" \ --with-nth="{1}" ) printf "%s#%s" "$MODE_ARTIST" "$sel" >"$MODEFILE" @@ -583,11 +587,11 @@ $KEYS_SELECT_ARTIST,\ $KEYS_FILTER_LOCAL,$KEYS_FILTER_PRIMARY,$KEYS_FILTER_SECONDARY,\ $KEYS_SWITCH_ARTIST_ALBUM,$KEYS_SWITCH_LOCAL_REMOTE,\ $KEYS_PLAY,$KEYS_QUEUE,\ -$KEYS_SHOW_PLAYLIST:transform:$0 --fzf-key {2} {3}" \ +$KEYS_SHOW_PLAYLIST:transform:$0 --fzf-key {2} {3} {4}" \ --info="inline-right" \ --info-command="$0 --fzf-info" \ --preview-window="right,25%,border-left,wrap,<30(hidden)" \ - --preview="$0 --internal-preview-artist {2}" \ + --preview="$0 --internal-preview-artist {3}" \ --delimiter="\t" \ --with-nth="{1}" >/dev/null ;; diff --git a/src/sh/api.sh b/src/sh/api.sh index f7405f8..33ba37d 100644 --- a/src/sh/api.sh +++ b/src/sh/api.sh @@ -4,76 +4,6 @@ USER_AGENT="$APP_NAME/$APP_VERSION ($APP_WEBSITE)" SLEEP_ON_ERROR=1 export MB_BROWSE_STEPS -__mpv_command() { - printf "{ \"command\": [\"%s\"] }\n" "$1" | $SOCAT - "$MPV_SOCKET" -} - -__mpv_command_with_arg() { - printf "{ \"command\": [\"%s\", \"%s\"] }\n" "$1" "$2" | $SOCAT - "$MPV_SOCKET" -} - -__mpv_command_with_args2() { - printf "{ \"command\": [\"%s\", \"%s\", \"%s\"] }\n" "$1" "$2" "$3" | $SOCAT - "$MPV_SOCKET" -} - -__mpv_get() { - __mpv_command_with_arg "expand-text" "$1" | $JQ -r '.data' -} - -mpv_playlist_count() { - __mpv_get '${playlist/count}' -} - -mpv_playlist_position() { - __mpv_get '${playlist-pos}' -} - -mpv_quit() { - __mpv_command "quit" -} - -mpv_start() { - MPV_SOCKET="$(mktemp --suffix=.sock)" - trap 'mpv_quit >/dev/null; rm -f "$MPV_SOCKET"' EXIT INT - $MPV --no-config --no-terminal --input-ipc-server="$MPV_SOCKET" --idle --no-osc --no-input-default-bindings & -} - -mpv_play_file() { - __mpv_command_with_arg "loadfile" "$1" -} - -mpv_queue_file() { - __mpv_command_with_args2 "loadfile" "$1" "append-play" -} - -mpv_play_list() { - __mpv_command_with_arg "loadlist" "$1" -} - -mpv_queue_list() { - __mpv_command_with_arg "loadlist" "$1" "append-play" -} - -mpv_next() { - __mpv_command "playlist-next" -} - -mpv_prev() { - __mpv_command "playlist-prev" -} - -mpv_seek_forward() { - __mpv_command_with_arg "seek" "10" -} - -mpv_seek_backward() { - __mpv_command_with_arg "seek" "-10" -} - -mpv_toggle_pause() { - __mpv_command_with_arg "cycle" "pause" -} - __api_mb() { tmpout=$(mktemp) for _ in $(seq "$MB_MAX_RETRIES"); do diff --git a/src/sh/lists.sh b/src/sh/lists.sh index e428e7c..20c90e0 100644 --- a/src/sh/lists.sh +++ b/src/sh/lists.sh @@ -42,7 +42,7 @@ list_releasegroups() { sort -n -r | cut -d "$(printf '\t')" -f 2- | column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\)$|\t\1|' + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' } # List releases in given relese group @@ -53,7 +53,8 @@ list_releases() { artist="$(mb_releasegroup "$1" | $JQ -r '."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")')" mb_releasegroup_releases "$1" | - $JQ -r '."releases"[] | [ + $JQ -r --arg rid "$1" '."releases"[] | [ + $rid, .id, .status, .date, @@ -86,7 +87,7 @@ list_releases() { sort -n -r | cut -d "$(printf '\t')" -f 2- | column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2|' + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2\t\3|' } # List recordings of given release @@ -99,9 +100,10 @@ list_recordings() { $JQ -r --arg base "$base/" '.tracks | to_entries | map(.key + "\t" + $base + .value) | join("\n")' "$deco" >"$rectmp" fi mb_release "$1" | - $JQ -r '.media[] | + $JQ -r --arg rid "$1" '.media[] | .position as $pos | .tracks[] | [ + $rid, .id, $pos, .number, @@ -119,7 +121,7 @@ list_recordings() { sort -k1,1n -k2,2g | cut -d "$(printf '\t')" -f 2- | column -t -s "$(printf '\t')" -R 2,3,6 | - sed 's| \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2|' + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2\t\3|' if [ "${rectmp:-}" ] && [ -f "$rectmp" ]; then rm -f "$rectmp" fi @@ -143,27 +145,33 @@ list_local_releases() { # Generate playlist from MB release ID and path to decoration # @argument $1: MusicBrainz Release ID # @argument $2: Path to decoration file +# @argument $3: MusicBrainz Track ID to select (optional) generate_playlist() { + printf "#EXTM3U\n" dir="$(dirname "$2")" mb_release "$1" | - $JQ -r --slurpfile deco "$2" --arg base "$dir" '$deco[].tracks as $filenames | + $JQ -r --slurpfile deco "$2" --arg base "$dir" --arg tid "${3:-}" '$deco[].tracks as $filenames | + . | + .id as $rid | .media[] | .position as $pos | .tracks | + if ($tid == "") then . else map(select(.id == $tid)) end | map({ + t: [ + .title, + (."artist-credit" | map([.name, .joinphrase] | join("")) | join("")), + .id, + $rid + ] | join("\t"), + length: (.length / 1000 | round | tostring), $pos, number: .number, file: $filenames[.id] }) | - map( - if(.number | type == "string" and test("^[0-9]+$")) then - .number |= tonumber - else - . - end - ) | + map(if(.number | type == "string" and test("^[0-9]+$")) then .number |= tonumber else . end) | sort_by([.pos, .number]) | - map($base + "/" + .file)[]' + map("#EXTINF:" + .length + "," + .t + "\n" + $base + "/" + .file)[]' } # Generate artist list from JSON @@ -179,10 +187,10 @@ list_artists_from_json() { -v format_local="$FORMAT_LOCAL" \ "$AWK_ARTISTS" | column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\)$|\t\1|' + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' } -# Generate playlist +# Generate playlist view list_playlist() { count=$(mpv_playlist_count) # mb_release "$1" | diff --git a/src/sh/local.sh b/src/sh/local.sh index c57403d..c17eece 100644 --- a/src/sh/local.sh +++ b/src/sh/local.sh @@ -150,7 +150,7 @@ load_local() { "$AWK_ARTISTS" | sort | column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\)$|\t\1|' >"$LOCALDATA_ARTISTS_VIEW" + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' >"$LOCALDATA_ARTISTS_VIEW" info "Precomputing releasegroup view" while IFS= read -r rgid; do mb_releasegroup "$rgid" | $JQ -r '[ @@ -192,11 +192,12 @@ load_local() { sort -n -r | cut -d "$(printf '\t')" -f 2- | column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\)$|\t\1|' >"$LOCALDATA_RELEASEGROUPS_VIEW" + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' >"$LOCALDATA_RELEASEGROUPS_VIEW" info "Precomputing release view" cut -d "$(printf '\t')" -f 1 "$LOCALDATA_RELEASES" | while IFS= read -r rid; do mb_release "$rid" | $JQ -r '[ + "0", .id, .status, .date, @@ -228,5 +229,5 @@ load_local() { sort -n -r | cut -d "$(printf '\t')" -f 2- | column -t -s "$(printf '\t')" | - sed 's| \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2|' >"$LOCALDATA_RELEASES_VIEW" + sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\):\(.*$\)$|\t\1\t\2\t\3|' >"$LOCALDATA_RELEASES_VIEW" } diff --git a/src/sh/mpv.sh b/src/sh/mpv.sh new file mode 100644 index 0000000..64be3fa --- /dev/null +++ b/src/sh/mpv.sh @@ -0,0 +1,69 @@ +__mpv_command() { + printf "{ \"command\": [\"%s\"] }\n" "$1" | $SOCAT - "$MPV_SOCKET" +} + +__mpv_command_with_arg() { + printf "{ \"command\": [\"%s\", \"%s\"] }\n" "$1" "$2" | $SOCAT - "$MPV_SOCKET" +} + +__mpv_command_with_args2() { + printf "{ \"command\": [\"%s\", \"%s\", \"%s\"] }\n" "$1" "$2" "$3" | $SOCAT - "$MPV_SOCKET" +} + +__mpv_get() { + __mpv_command_with_arg "expand-text" "$1" | $JQ -r '.data' +} + +mpv_playlist_count() { + __mpv_get '${playlist-count}' +} + +mpv_playlist_position() { + __mpv_get '${playlist-pos}' +} + +mpv_quit() { + __mpv_command "quit" +} + +mpv_start() { + MPV_SOCKET="$(mktemp --suffix=.sock)" + trap 'mpv_quit >/dev/null; rm -f "$MPV_SOCKET"' EXIT INT + $MPV --no-config --no-terminal --input-ipc-server="$MPV_SOCKET" --idle --no-osc --no-input-default-bindings & +} + +mpv_play_file() { + __mpv_command_with_arg "loadfile" "$1" +} + +mpv_queue_file() { + __mpv_command_with_args2 "loadfile" "$1" "append-play" +} + +mpv_play_list() { + __mpv_command_with_arg "loadlist" "$1" +} + +mpv_queue_list() { + __mpv_command_with_arg "loadlist" "$1" "append-play" +} + +mpv_next() { + __mpv_command "playlist-next" +} + +mpv_prev() { + __mpv_command "playlist-prev" +} + +mpv_seek_forward() { + __mpv_command_with_arg "seek" "10" +} + +mpv_seek_backward() { + __mpv_command_with_arg "seek" "-10" +} + +mpv_toggle_pause() { + __mpv_command_with_arg "cycle" "pause" +}