feat: --decorate-as
This commit is contained in:
16
src/main.sh
16
src/main.sh
@@ -360,6 +360,21 @@ case "${1:-}" in
|
||||
fi
|
||||
exit 0
|
||||
;;
|
||||
"--decorate-as")
|
||||
# Decorate the specified directory as given MusicBrainz release
|
||||
#
|
||||
# @argument $2: path
|
||||
# @argument $3: MusicBrainz release ID
|
||||
[ ! "${2:-}" ] && err "You did not specify a directory." && exit 1
|
||||
[ ! -d "$2" ] && err "Path $2 does not point to a directory." && exit 1
|
||||
[ ! "${3:-}" ] && err "You did not specify a MusicBrainz release ID." && exit 1
|
||||
[ ! "$(mb_release "$3" | $JQ '.title // ""')" ] && err "Did you specify a correct MusicBrainz release ID?" && exit 1
|
||||
if ! decorate_as "$2" "$3"; then
|
||||
err "Something went wrong."
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
;;
|
||||
"--reload-database")
|
||||
# Reload database of local music
|
||||
#
|
||||
@@ -392,6 +407,7 @@ GENERAL OPTIONS:
|
||||
|
||||
MANAGE LOCAL MUSIC:
|
||||
--decorate <path> Decorate directory containing a tagged release
|
||||
--decorate-as <path> <mbid> Decorate directory as the relase <mbid>
|
||||
--reload-database <path> Populate database with decorated local music from <path>
|
||||
EOF
|
||||
exit 0
|
||||
|
@@ -103,7 +103,8 @@ __api_mb() {
|
||||
errormsg=$($JQ -e '.error // ""' "$tmpout")
|
||||
if [ "$errormsg" ]; then
|
||||
err "Failed to fetch MusicBrainz data for $1 $2: $errormsg"
|
||||
[ "$errormsg" = "Not Found" ] && break
|
||||
echo "$errormsg" | grep -q -i "not found" && break
|
||||
echo "$errormsg" | grep -q -i "invalid" && break
|
||||
sleep "$SLEEP_ON_ERROR"
|
||||
else
|
||||
cat "$tmpout"
|
||||
|
@@ -83,6 +83,97 @@ decorate() {
|
||||
fi
|
||||
}
|
||||
|
||||
# Decorate locally available music with specified MusicBrainz release
|
||||
#
|
||||
# @input $1: Path to directory with album
|
||||
# @input $2: MusicBrainz release ID
|
||||
#
|
||||
# Similar as `decorate`, but the MusicBrainz IDs are not inferred from the
|
||||
# tags, but passed as argument.
|
||||
decorate_as() {
|
||||
if [ -f "$1/$DECORATION_FILENAME" ]; then
|
||||
rid="$($JQ '.releaseid' "$1/$DECORATION_FILENAME")"
|
||||
title="$(mb_release "$rid" | $JQ '.title // ""')"
|
||||
artist="$(mb_release "$rid" | $JQ '."artist-credit" | map([.name, .joinphrase] | join("")) | join("")')"
|
||||
[ "$rid" = "$2" ] &&
|
||||
info "Directory $1 has already been decorated as the release '$title' - '$artist' with the identical MusicBrainz release ID." ||
|
||||
info "Directory $1 has already been decorated as the release '$title' - '$artist' with the MusicBrainz release ID $rid."
|
||||
while true; do
|
||||
infonn "Do you want to redecorate $1? (yes/no)"
|
||||
read -r yn
|
||||
case $yn in
|
||||
"yes") break ;;
|
||||
"no") return 0 ;;
|
||||
*) info "Please answer \"yes\" or \"no\"." ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
# Print info
|
||||
title="$(mb_release "$2" | $JQ '.title // ""')"
|
||||
artist="$(mb_release "$2" | $JQ '."artist-credit" | map([.name, .joinphrase] | join("")) | join("")')"
|
||||
info "Decorating $1 as the release $title by $artist"
|
||||
# Start decoration
|
||||
decoration=$($JQ -n '.tracks = {}')
|
||||
tmpf=$(mktemp)
|
||||
(cd "$1" && find . -type f -iname '*.mp3' -o -iname '*.mp4' -o -iname '*.flac' -o -iname '*.m4a' | sort) >"$tmpf"
|
||||
# Compare number of tracks with release
|
||||
rcnt="$(mb_release "$2" | $JQ '.media | map(."track-count") | add')"
|
||||
dcnt="$(wc -l "$tmpf" | cut -d ' ' -f 1)"
|
||||
if [ ! "$rcnt" -eq "$dcnt" ]; then
|
||||
err "Number of tracks in directory ($dcnt) does not match number of tracks in release ($rcnt)."
|
||||
return 1
|
||||
fi
|
||||
#
|
||||
tmpj=$(mktemp)
|
||||
mb_release "$2" |
|
||||
$JQ '.media[] |
|
||||
.position as $pos |
|
||||
.tracks |
|
||||
map({
|
||||
$pos,
|
||||
"id": .id,
|
||||
"n": .number,
|
||||
"t": .title
|
||||
}) |
|
||||
map(if(.n | type == "string" and test("^[0-9]+$")) then .n |= tonumber else . end) |
|
||||
sort_by([.pos, .n])[] |
|
||||
[.t, .id] |
|
||||
join("\t")' >"$tmpj"
|
||||
assocfile=$(mktemp)
|
||||
awk -F '\t' '
|
||||
BEGIN { OFS = "\t" }
|
||||
FNR == NR { title[FNR] = $1; id[FNR] = $2 }
|
||||
FNR != NR { fname[FNR] = $1 }
|
||||
END { for (i in id) print title[i], id[i], fname[i] }
|
||||
' "$tmpj" "$tmpf" >"$assocfile"
|
||||
rm -f "$tmpj" "$tmpf"
|
||||
# Ask user if this is ok
|
||||
info "We discovered the following associatoin:"
|
||||
while IFS= read -r line; do
|
||||
t="$(echo "$line" | cut -d "$(printf '\t')" -f 1)"
|
||||
f="$(echo "$line" | cut -d "$(printf '\t')" -f 3)"
|
||||
printf "Track '%s'\tFile '%s'\n" "$t" "$f"
|
||||
done <"$assocfile" | column -t -s "$(printf '\t')"
|
||||
while true; do
|
||||
infonn "Are the track correctly associated to the audio files? (yes/no)"
|
||||
read -r yn
|
||||
case $yn in
|
||||
"yes") break ;;
|
||||
"no") return 0 ;;
|
||||
*) info "Please answer \"yes\" or \"no\"." ;;
|
||||
esac
|
||||
done
|
||||
# Construct decoration
|
||||
decoration=$($JQ -n '.tracks = {}')
|
||||
while IFS= read -r line; do
|
||||
i="$(echo "$line" | cut -d "$(printf '\t')" -f 2)"
|
||||
f="$(echo "$line" | cut -d "$(printf '\t')" -f 3)"
|
||||
decoration=$(echo "$decoration" | $JQ ".tracks += {\"$i\": \"$f\"}")
|
||||
done <"$assocfile"
|
||||
echo "$decoration" | $JQ ".releaseid = \"$2\"" >"$1/$DECORATION_FILENAME"
|
||||
return 0
|
||||
}
|
||||
|
||||
# Load missing cache entries (batch mode)
|
||||
#
|
||||
# argument $1: type
|
||||
|
@@ -25,3 +25,8 @@ err() {
|
||||
info() {
|
||||
echo "$(date) [$$]>${INFO}Info:${OFF} ${1:-}" | tee -a "$LOGFILE" | cut -d ">" -f 2- >/dev/stderr
|
||||
}
|
||||
|
||||
# Like `info` but without newlnes on stderr.
|
||||
infonn() {
|
||||
echo "$(date) [$$]>${INFO}Info:${OFF} ${1:-}" | tee -a "$LOGFILE" | cut -d ">" -f 2- | tr '\n' ' ' >/dev/stderr
|
||||
}
|
||||
|
Reference in New Issue
Block a user