# This files provides a high-level access to the MusicBrainz databse. The only # IDs used here are MusicBrainz IDs # The following methods are local methods that combines the MusicBrainz API # with the caching methods. # Retrieve MusicBrainz data for artist from cache (if it exists), and otherwise # download it using the MusicBrainz API. # # @argument $1: MusicBrainz artist ID __mb_artist_cache_or_fetch() { if ! cache_get_artist "$1"; then api_mb_artist "$1" | cache_put_artist "$1" cache_get_artist "$1" fi } # Retrieve MusicBrainz data for release group from cache (if it exists), and # otherwise download it using the MusicBrainz API. # # @argument $1: MusicBrainz release-group ID __mb_releasegroup_cache_or_fetch() { if ! cache_get_releasegroup "$1"; then api_mb_releasegroup "$1" | cache_put_releasegroup "$1" cache_get_releasegroup "$1" fi } # Retrieve MusicBrainz data for release from cache (if it exists), and # otherwise download it using the MusicBrainz API. # # @argument $1: MusicBrainz release ID __mb_release_cache_or_fetch() { if ! cache_get_release "$1"; then api_mb_release "$1" | cache_put_release "$1" cache_get_release "$1" fi } # Retrieve MusicBrainz data for release groups of given artist from cache (if # it exists), and otherwise download it using the MusicBrainz API. # # @argument $1: MusicBrainz artist ID __mb_artist_cache_or_fetch_releasegroups() { if ! cache_get_artist_releasegroups "$1"; then api_mb_browse_artist_releasegroups "$1" | cache_put_artist_releasegroups "$1" rg="$(cache_get_artist_releasegroups "$1")" total=$(printf "%s" "$rg" | $JQ '."release-group-count"') seen=$MB_BROWSE_STEPS while [ "$total" -gt "$seen" ]; do # Fetch remaning release groups, and append to cache sleep 1 # Make sure we don't get blocked (we prefer not to handle failed requests...) api_mb_browse_artist_releasegroups "$1" "$seen" | cache_append_artist_releasegroups "$1" seen=$((seen + MB_BROWSE_STEPS)) done cache_get_artist_releasegroups "$1" fi } # Retrieve MusicBrainz data for releases of given release group from cache (if # it exists), and otherwise download it using the MusicBrainz API. # # @argument $1: MusicBrainz release-group ID __mb_releasegroup_cache_or_fetch_releases() { if ! cache_get_releasegroup_releases "$1"; then api_mb_browse_releasegroup_releases "$1" | cache_put_releasegroup_releases "$1" releases="$(cache_get_releasegroup_releases "$1")" total=$(printf "%s" "$releases" | $JQ '."release-count"') seen=$MB_BROWSE_STEPS while [ "$total" -gt "$seen" ]; do # Fetch remaning releases, and append to cache sleep 1 # Make sure we don't get blocked (we prefer not to handle failed requests...) api_mb_browse_releasegroup_releases "$1" "$seen" | cache_append_releasegroup_releases "$1" seen=$((seen + MB_BROWSE_STEPS)) done cache_get_releasegroup_releases "$1" fi } # The following methods provide the external interface # Retrieve MusicBrainz data for artist # # @argument $1: MusicBrainz artist ID mb_artist() { __mb_artist_cache_or_fetch "$1" } # Retrieve Wikidata data for artist # # @argument $1: MusicBrainz artist ID mb_artist_wikidata() { if ! cache_get_artist_wikidata "$1"; then wikidataid=$(mb_artist "$1" | $JQ '.relations | map(select(.type=="wikidata")) | .[0].url.resource // ""' | awk -F "/" '{print $NF}') [ ! "$wikidataid" ] && return api_wikidata_sitelinks "$wikidataid" | cache_put_artist_wikidata "$1" cache_get_artist_wikidata "$1" fi } # Retrieve Wikipedia (English) summary json for artist # # @argument $1: MusicBrainz artist ID mb_artist_enwikipedia() { if ! cache_get_artist_enwikipedia "$1"; then # To fetch the wikipedia data, we need the wikipedia URL # There are two possibly ways to get the wikipedia URL # 1. From the website relations in MB (MB artists donw have wiki rels) # 2. MB website relations -> Wikidata -> Wikipedia # Lately, Wikipedia pages are not stored in the MB artist url relations. # For obvious reasons it is recommended to link to wikidata only. So, we # take the second route. wikidata=$(mb_artist_wikidata "$1" || true) wikiid=$(printf "%s" "$wikidata" | $JQ '.enwiki.url // ""' | awk -F "/" '{print $NF}') [ ! "$wikiid" ] && return api_wikipedia_en_summary "$wikiid" | cache_put_artist_enwikipedia "$1" cache_get_artist_enwikipedia "$1" fi } # Retrieve Discogs json for artist # # @argument $1: MusicBrainz artist ID mb_artist_discogs() { if ! cache_get_artist_discogs "$1"; then discogsid=$(mb_artist "$1" | $JQ '.relations | map(select(.type=="discogs")) | .[0].url.resource // ""' | awk -F "/" '{print $NF}') [ ! "$discogsid" ] && return api_discogs_artist "$discogsid" | cache_put_artist_discogs "$1" cache_get_artist_discogs "$1" fi } # Retrieve release groups for artist # # @argument $1: MusicBrainz artist ID mb_artist_releasegroups() { __mb_artist_cache_or_fetch_releasegroups "$1" } # Retrieve MusicBrainz release group # # @argument $1: MusicBrainz release-group ID mb_releasegroup() { __mb_releasegroup_cache_or_fetch "$1" } # Retrieve MusicBrainz releases of release group # # @argument $1: MusicBrainz release-group ID mb_releasegroup_releases() { __mb_releasegroup_cache_or_fetch_releases "$1" } # Retrieve MusicBrainz release # # @argument $1: MusicBrainz release ID mb_release() { __mb_release_cache_or_fetch "$1" } # Reload hook that is used after a change in the query (when searching # MusicBrainz). # # This method waits for the search to complete, then it parses the search # results and prints them. mb_results_async() { # Wait for async. process to terminate sleep 1 while [ -f "$LOCKFILE" ]; do sleep 1 done # Show results column -t -s "$(printf '\t')" "$RESULTS" | sed 's| \+\([0-9a-f-]\+\) \+\([0-9a-f-]\+\)$|\t\1\t\2|' } # Initiate search on MusicBrainz # # @argument $1: view # # This methods initiates an asynchronous search for both views # (VIEW_SEARCH_ARTIST and VIEW_SEARCH_ALBUM). If a running query is detected, # that one is killed first. The search results are then stored and become # retrievable using `mb_results_async`. mb_search_async() { view="$1" # Kill any running search if [ -f "$PIDFILE" ]; then pid=$(cat "$PIDFILE") rm -f "$PIDFILE" kill -9 "$pid" >/dev/null 2>&1 || true fi # Stop, if no search string is given [ "$FZF_QUERY" ] || exit 0 # Store PID of current process echo "$$" >"$PIDFILE" touch "$LOCKFILE" sleep 1 if [ "$view" = "$VIEW_SEARCH_ARTIST" ]; then api_mb_search_artist "$FZF_QUERY" | $JQ '.artists[] | [ .id, .type, .name, .disambiguation, .["life-span"].begin, .["life-span"].end ] | join("\t")' | awk \ -F "\t" \ -v file_local_artists="${LOCALDATA_ARTISTS:-}" \ -v format_person="$AV_PERSON" \ -v format_group="$AV_GROUP" \ -v format_disambiguation="$AV_DISAMBIGUATION" \ -v format_local="$FORMAT_LOCAL" \ "$AWK_ARTISTS" >"$RESULTS" || true else api_mb_search_releasegroup "$FZF_QUERY" | $JQ '."release-groups"[] | [ .id, ."primary-type", (."secondary-types" // []|join(";")), ."first-release-date", .title, (."artist-credit" | map(([.name, .joinphrase]|join(""))) | join("")) ] | join("\t")' | awk \ -F "\t" \ -v file_local_releasegroups="${LOCALDATA_RELEASEGROUPS:-}" \ -v format_release="$RGV_RELEASE" \ -v format_release_w_artist="$RGV_RELEASE_W_ARTIST" \ -v format_year="$RGV_YEAR" \ -v format_album="$FORMAT_TYPE_ALBUM" \ -v format_single="$FORMAT_TYPE_SINGLE" \ -v format_ep="$FORMAT_TYPE_EP" \ -v format_broadcast="$FORMAT_TYPE_BROADCAST" \ -v format_other="$FORMAT_TYPE_OTHER" \ -v format_has_secondary="$FORMAT_TYPE_HAS_SECONDARY" \ -v format_secondary="$FORMAT_TYPE_SECONDARY" \ -v format_compilation="$FORMAT_TYPE_SECONDARY_COMPILATION" \ -v format_soundtrack="$FORMAT_TYPE_SECONDARY_SOUNDTRACK" \ -v format_spokenword="$FORMAT_TYPE_SECONDARY_SPOKENWORD" \ -v format_interview="$FORMAT_TYPE_SECONDARY_INTERVIEW" \ -v format_audiobook="$FORMAT_TYPE_SECONDARY_AUDIOBOOK" \ -v format_audiodrama="$FORMAT_TYPE_SECONDARY_AUDIODRAMA" \ -v format_live="$FORMAT_TYPE_SECONDARY_LIVE" \ -v format_remix="$FORMAT_TYPE_SECONDARY_REMIX" \ -v format_djmix="$FORMAT_TYPE_SECONDARY_DJMIX" \ -v format_mixtape="$FORMAT_TYPE_SECONDARY_MIXTAPE" \ -v format_demo="$FORMAT_TYPE_SECONDARY_DEMO" \ -v format_fieldrec="$FORMAT_TYPE_SECONDARY_FIELDREC" \ -v format_local="$FORMAT_LOCAL" \ "$AWK_RELEASEGROUPS" | cut -d "$(printf '\t')" -f 2- >"$RESULTS" || true fi # Process ends now: Display and quit rm -f "$LOCKFILE" "$PIDFILE" }