tc-audio-trancode: proper variable substitution

master
Pierre Neidhardt 2013-10-28 02:12:49 +01:00
parent 9582d19583
commit 0b71f5e5de
1 changed files with 75 additions and 57 deletions

View File

@ -24,8 +24,6 @@
## -q9 320 kbit/s
## -q10 500 kbit/s
## TODO: use "eval" more securely. eval "$ref"'=$value'
_printhelp ()
{
cat <<EOF | less
@ -67,7 +65,8 @@ Tags:
-r : library root folder
-t : title
You can use the following variables to refer to existing values:
Everything tag you set from command-line will not get titlecased.
You can use the following variables to refer to the titlecased values:
\$ALBUM
\$ALBUMARTIST
\$ARTIST
@ -78,6 +77,9 @@ You can use the following variables to refer to existing values:
\$TRACK
\$TYER
If bitrate argument is not provided, we use the bitrate of the source. If
bitrate argument is 0, we leave FFmpeg chose the value.
Default output folder:
OUTPUT_FOLDER="\$OUTPUT_ROOT/\$OUTPUT_ARTIST/\${OUTPUT_ALBUM:+\${OUTPUT_DATE:+\$OUTPUT_DATE - }\$OUTPUT_ALBUM/}"
@ -95,10 +97,8 @@ Examples:
Set track number to first field in file name:
${1##*/} -n '${FILENAME%% }'
IMPORTANT: you *must* use single quotes when using variables. Also note that the
string parameters are all evaluated using 'eval', which means that some
characters may need escaping with '\'. Since parenthesis '()' are often used, a
backslash is prepended before eval is called.
IMPORTANT: you *must* use single quotes when using variables.
EOF
}
@ -220,7 +220,7 @@ INPUT_BITRATE=$(echo "$STREAM" | sed -n '/Duration/ {s|.* \([[:digit:]]\+\) kb/s
## Extension needs to be set in case we skip encoding so that ffmpeg will not be
## disturbed by unappropriate extension.
if $SKIP &&[ -z "$INPUT_EXT" ]; then
if $SKIP && [ -z "$INPUT_EXT" ]; then
echo "ERROR: Extension missing [$1]."
exit
fi
@ -251,13 +251,15 @@ INPUT_TYER=$(_metadata_filter "TYER")
# => '
# : => -
# / => -
# \ => -
# & => \&
_string_cleanser()
{
echo "$@" | awk -v capital=$CAPITAL -f "$TITLECASE_SCRIPT" \
| sed -n -e "s//'/g ; s/ *: */ - /g ; s| */ *| - |g; p; q"
| sed -e "s//'/g ; s| *[/\\:] *| - |g" -e 's/ \+/ /g' -e 's|&|\\\\&|g;'
}
## These are the user-accessible variables.
## These are the "titlecased" variables.
TITLE=$(_string_cleanser "$INPUT_TITLE")
ARTIST=$(_string_cleanser "$INPUT_ARTIST")
ALBUM=$(_string_cleanser "$INPUT_ALBUM")
@ -271,69 +273,86 @@ TYER=$(_string_cleanser "$INPUT_TYER")
FILENAME=$(_string_cleanser "$INPUT_FILE")
## We also convert spaces to underscores.
GENRE=$(echo "$GENRE" | tr '[:upper:] ' '[:lower:]_')
case $GENRE in
ost) GENRE="Soundtrack" ;;
soundtrack) GENRE="Soundtrack";;
original_soundtrack) GENRE="Soundtrack";;
classical) GENRE="Classical";;
classics) GENRE="Classical";;
classic) GENRE="Classical";;
humour) GENRE="Humour";;
*) GENRE="";;
esac
##================================================================================
## OUTPUT variables.
## In this part we prepend backslashes to parentheses when there is an 'eval'
## call to prevent parsing error.
OUTPUT_TITLE=$(eval echo $(echo ${OUTPUT_TITLE:-Unknown Title} | sed 's/[()]/\\&/g'))
OUTPUT_ALBUM=$(eval echo $(echo ${OUTPUT_ALBUM:-Unknown Album} | sed 's/[()]/\\&/g'))
## The following function replaces all variables with their value. This is much
## safer than using shell expansion through 'eval.'
_revar()
{
echo "$1" | awk \
-v title="$TITLE" \
-v artist="$ARTIST" \
-v album="$ALBUM" \
-v albumartist="$ALBUMARTIST" \
-v composer="$COMPOSER" \
-v disc="$DISC" \
-v genre="$GENRE" \
-v track="$TRACK" \
-v date="$DATE" \
-v tyer="$TYER" \
-v filename="$FILENAME" \
'{ \
gsub(/\$TITLE/, title); \
gsub(/\$ARTIST/, artist); \
gsub(/\$ALBUM/, album); \
gsub(/\$ALBUMARTIST/, albumartist); \
gsub(/\$COMPOSER/, composer); \
gsub(/\$DISC/, disc); \
gsub(/\$GENRE/, genre); \
gsub(/\$TRACK/, track); \
gsub(/\$DATE/, date); \
gsub(/\$TYER/, tyer); \
gsub(/\$FILENAME/, filename); \
print}'
}
OUTPUT_TITLE=$(_revar "${OUTPUT_TITLE:-Unknown Title}")
OUTPUT_ALBUM=$(_revar "${OUTPUT_ALBUM:-Unknown Album}")
## We use album artist if artist is empty.
[ -z "$OUTPUT_ARTIST" ] && [ -n "$ALBUMARTIST" ] && OUTPUT_ARTIST="$ALBUMARTIST"
OUTPUT_ARTIST=$(eval echo $(echo ${OUTPUT_ARTIST:-Unknown Artist} | sed 's/[()]/\\&/g'))
[ -z "$OUTPUT_ARTIST" ] && OUTPUT_ARTIST="$ALBUMARTIST"
OUTPUT_ARTIST=$(_revar "${OUTPUT_ARTIST:-Unknown Artist}")
## If OUTPUT_GENRE is set from command-line parameters, we use the
## string. Otherwise we put GENRE in lower case and underscore to ease matching.
## If it matches, we use the Title Case match. If it does not, we set it to
## empty.
if [ ! "$OUTPUT_GENRE" = '$GENRE' ]; then
OUTPUT_GENRE=$(eval echo $(echo $OUTPUT_GENRE | sed 's/[()]/\\&/g'))
else
## We also convert spaces to underscores.
GENRE=$(echo "$GENRE" | tr '[:upper:] ' '[:lower:]_')
case $GENRE in
ost) OUTPUT_GENRE="Soundtrack" ;;
soundtrack) OUTPUT_GENRE="Soundtrack";;
original_soundtrack) OUTPUT_GENRE="Soundtrack";;
classical) OUTPUT_GENRE="Classical";;
classics) OUTPUT_GENRE="Classical";;
classic) OUTPUT_GENRE="Classical";;
humour) OUTPUT_GENRE="Humour";;
*) OUTPUT_GENRE="";;
esac
fi
OUTPUT_GENRE=$(_revar "$OUTPUT_GENRE")
## We remove the track count if any, we suppress leading zeros, we suppress all
## non-digit characters.
OUTPUT_TRACK=$(eval _string_cleanser $(echo $OUTPUT_TRACK | sed 's/[()]/\\&/g') | sed -e 's/^0*//' -e 's|[^[:digit:]].*||')
OUTPUT_TRACK=$(_revar "$OUTPUT_TRACK" | sed -e 's/^0*//' -e 's|[^[:digit:]].*||')
## We extract the four-digits number from the date.
OUTPUT_DATE=$(eval _string_cleanser $(echo $OUTPUT_DATE | sed 's/[()]/\\&/g'))
OUTPUT_DATE=$(_revar "$OUTPUT_DATE")
OUTPUT_DATE=$(echo "$OUTPUT_DATE" | sed -n 's/.*\([[:digit:]]\{4\}\).*/\1/p')
## If DATE is not a year, we use TYER if it is a year.
TYER_REG=$(echo "$TYER" | sed -n 's/.*\([[:digit:]]\{4\}\).*/\1/p')
if [ ${#DATE} -ne 4 ] && [ ${#TYER_REG} -eq 4 ]; then
OUTPUT_DATE="$TYER_REG"
fi
TYER_REG=$(_revar "$TYER" | sed -n 's/.*\([[:digit:]]\{4\}\).*/\1/p')
[ ${#DATE} -ne 4 ] && [ ${#TYER_REG} -eq 4 ] && OUTPUT_DATE="$TYER_REG"
## QUALITY
## If bitrate argument is not provided, we use INPUT_BITRATE value.
## If bitrate argument is 0, we leave FFmpeg chose the value.
[ $OUTPUT_BITRATE -lt 0 ] && OUTPUT_BITRATE=${INPUT_BITRATE}
[ $OUTPUT_BITRATE -eq 0 ] && OGG_PARAM="-c:a libvorbis"
## If OUTPUT_BITRATE is beyond OGG's limit, we trim it.
[ $OUTPUT_BITRATE -gt 500 ] && OUTPUT_BITRATE=500
## Only reencode if not in OGG and if SKIP not set.
## Only reencode if not in OGG and if SKIP not set, or if explicitly specified.
INPUT_EXT_LOW="$(echo $INPUT_EXT | tr [:upper:] [:lower:])"
if $SKIP; then
OGG_PARAM="-c:a copy"
OUTPUT_EXT="$INPUT_EXT_LOW"
fi
[ "$INPUT_EXT_LOW" = "ogg" ] && OGG_PARAM="-c:a copy"
OGG_PARAM=$(eval echo "$OGG_PARAM")
[ "$INPUT_EXT_LOW" = "ogg" ] && [ $OUTPUT_BITRATE -lt 0 ] && OGG_PARAM="-c:a copy"
[ $OUTPUT_BITRATE -lt 0 ] && OGG_PARAM="-c:a libvorbis ${INPUT_BITRATE}"
[ $OUTPUT_BITRATE -eq 0 ] && OGG_PARAM="-c:a libvorbis"
## If OUTPUT_BITRATE is beyond OGG's limit, we trim it.
[ $OUTPUT_BITRATE -gt 500 ] && OGG_PARAM="-c:a libvorbis 500"
## Make sure track number has two digits for file name only.
OUTPUT_PADDEDTRACK=$OUTPUT_TRACK
@ -341,8 +360,8 @@ if [ -n "$OUTPUT_PADDEDTRACK" ]; then
[ ${OUTPUT_PADDEDTRACK} -lt 10 ] && OUTPUT_PADDEDTRACK="0$OUTPUT_PADDEDTRACK"
fi
OUTPUT_FOLDER=$(eval echo $OUTPUT_FOLDER)
OUTPUT_FILE=$(eval echo $OUTPUT_FILE)
OUTPUT_FOLDER=$(_revar "$OUTPUT_FOLDER")
OUTPUT_FILE=$(_revar "$OUTPUT_FILE")
unset OUTPUT_FILE_ORIGINAL
if [ -e "$OUTPUT_FOLDER/$OUTPUT_FILE.$OUTPUT_EXT" ]; then
@ -451,7 +470,7 @@ _cover()
if [ -z "$COVER_WIDTH" ] || [ $COVER_WIDTH -lt $COVER_LIMIT ] || \
[ -z "$COVER_HEIGHT" ] || [ $COVER_HEIGHT -lt $COVER_LIMIT ]; then
echo -n " $(tput setf 4)$(tput bold)(Warning: bad quality cover!)$(tput sgr0)"
echo -n " $(tput setf 1)$(tput bold)(Warning: bad quality cover.)$(tput sgr0)"
fi
fi
@ -512,4 +531,3 @@ echo
[ "$STATUS" = "off" ] && set +o shwordsplit
echo ":: Process finished!"