Files
music_tools/usr/lib/rx3/music.bash

598 lines
13 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
if [[ "${MUSIC_BASH}" != "" ]]
then
return
fi
# Includes
#-----------------------------------------------------------------------------------------------------------------------------------
. /usr/global/lib/default.bash
# Global Variable
#-----------------------------------------------------------------------------------------------------------------------------------
declare -g MUSIC_BASH=1
declare -Ag FLAC_2_MP3_TAB=(
[TRACKNUMBER]=TRCK
[TRACKTOTAL]=TRCK
[TITLE]=TIT2
[ALBUM]=TALB
[ARTIST]=TPE1
[COMPOSER]=TCOM
[ARRANGER]=IPLS
[CONDUCTOR]=TPE3
[REMIXER]=TPE4
[AUTHOR]=TEXT
[WRITER]=TEXT
[LYRICIST]=TEXT
[ALBUMARTIST]=TPE2
[DATE]=TDRC
[GENRE]=TCON
[COMPILATION]=TCMP
[DISCTOTAL]=TPOS
[DISCNUMBER]=TPOS
[LABEL]=XXXX
[PUBLISHER]=TPUB
[ISRC]=TSRC
[BARCODE]=TXXX
[CATALOGNUMBER]=TXXX
[COPYRIGHT]=TCOP
[LICENSE]=USER
[COMMENT]=COMM
[DESCRIPTION]=TIT3
[ENCODER]=TSSE
[MEDIA]=TMED
[LANGUAGE]=TLAN
[LYRICS]=USLT
)
declare -Ag MP3_2_FLAC_TAB=(
[TRCK]=TRACKNUMBER:TRACKTOTAL
[TIT2]=TITLE
[TALB]=ALBUM
[TPE1]=ARTIST
[TCOM]=COMPOSER
[IPLS]=ARRANGER
[TPE3]=CONDUCTOR
[TPE4]=REMIXER
[TEXT]=AUTHOR:WRITER:LYRICIST
[TPE2]=ALBUMARTIST
[TDRC]=DATE
[TCON]=GENRE
[TCMP]=COMPILATION
[TPOS]=DISCNUMBER:DISCTOTAL
[TPUB]=PUBLISHER
[TSRC]=ISRC
[TXXX]=BARCODE:CATALOGNUMBER
[TCOP]=COPYRIGHT
[USER]=LICENSE
[COMM]=COMMENT
[TIT3]=DESCRIPTION
[TSSE]=ENCODER
[TMED]=MEDIA
[TLAN]=LANGUAGE
[USLT]=LYRICS
)
declare -g FLAC_TAG_LIST="TRACKNUMBER TRACKTOTAL TITLE ALBUM ARTIST COMPOSER ARRANGER CONDUCTOR REMIXER AUTHOR WRITER LYRICIST ALBUMARTIST DATE GENRE COMPILATION LABEL PUBLISHER ISRC BARCODE UPC COPYRIGHT LICENSE COMMENT DESCRIPTION ENCODER MEDIA LANGUAGE LYRICS"
declare -g FLAC_TAG_COND=$(echo '('${FLAC_TAG_LIST}')' | sed -e 's/ /|/g')
declare -g NODEF_TAG_LIST="TRACKNUMBER TITLE ISRC LYRICS"
declare -g NODEF_TAG_COND=$(echo '('${NODEF_TAG_LIST}')' | sed -e 's/ /|/g')
#-----------------------------------------------------------------------------------------------------------------------------------
# Fix Name
#-----------------------------------------------------------------------------------------------------------------------------------
# Standardise Name
#-----------------------------------------------------------------------------------------------------------------------------------
# $1: Input Name
# $2: SED Substitute Patern
# Out: Output Name
#-----------------------------------------------------------------------------------------------------------------------------------
function fix_name
{
input_name="$1"
ssp="$2"
if [[ "${ssp}" != "" ]]
then
sse="s/${ssp}"
else
sse="s/^//"
fi
echo ${input_name} |
sed -e 's/[ ,!/?:]/_/g' \
-e "s/['´]/_/g" \
-e 's/\[/-/g' -e 's/\]//g' \
-e 's/(/-/g' -e 's/)//g' \
-e 's/__/_/g' -e 's/_\././g' -e 's/_-/-/g' -e 's/--/-/g' -e 's/-_/-/g' \
-e 's/à/a/g' -e 's/á/a/g' -e 's/ä/a/g' -e 's/â/a/g' -e 's/ã/a/g' -e 's/é/e/g' -e 's/è/e/g' -e 's/ê/e/g' -e 's/ë/e/g' -e 's/ï/i/g' -e 's/î/i/g' -e 's/í/i/g' -e 's/ô/o/g' -e 's/ö/o/g' -e 's/ó/o/g' -e 's/ù/u/g' -e 's/ü/u/g' -e 's/û/u/g' -e 's/ú/u/g' -e 's/ç/c/g' -e 's/ñ/n/g' \
-e 's/À/a/g' -e 's/Á/a/g' -e 's/Ä/a/g' -e 's/Â/a/g' -e 's/Ã/a/g' -e 's/É/e/g' -e 's/È/e/g' -e 's/Ê/e/g' -e 's/Ë/e/g' -e 's/Ï/i/g' -e 's/Î/i/g' -e 's/Í/i/g' -e 's/Ô/o/g' -e 's/Ö/o/g' -e 's/Ó/o/g' -e 's/Ù/u/g' -e 's/Ü/u/g' -e 's/Û/u/g' -e 's/Ú/u/g' -e 's/Ç/c/g' -e 's/Ñ/n/g' \
-e 's/¿//g' \
-e 's/[+&]/and/g' -e 's/"/_inch/g' \
-e 's/#//g' \
-e 's/^[_-]*//' \
-e 's/[_-]*$//' \
-e "${sse}" |
tr '[:upper:]' '[:lower:]'
}
#-----------------------------------------------------------------------------------------------------------------------------------
# Fix File Name
#-----------------------------------------------------------------------------------------------------------------------------------
# Standardise File Name
#-----------------------------------------------------------------------------------------------------------------------------------
# $1: Input File Name
# $2: SED Substitute Patern
# Out: Output File Name
#-----------------------------------------------------------------------------------------------------------------------------------
function fix_file_name
{
input_file_name="$1"
ssp="$2"
fix_name "${input_file_name}" "${ssp}" |
sed -e 's/\(^[0-9]*\)./\1-/'
}
# TagTab Alloc
#-----------------------------------------------------------------------------------------------------------------------------------
function tagtab_alloc
{
unset tagtab
declare -Ag tagtab
declare -g taglist
taglist=":"
}
# Tag Exist
#-----------------------------------------------------------------------------------------------------------------------------------
function tag_exist
{
tag="$1"
echo ${taglist} | grep -e ":${tag}:"
}
# TagTab Read
#-----------------------------------------------------------------------------------------------------------------------------------
function tagtab_read
{
track_id="$1"
track_file="$2"
mode="$3"
tmp_file=$(mktemp)
case "${track_file}"
in
*.flac)
metaflac --export-tags-to=- "${track_file}" | sed -e 's/^[^=]*=/\U&\E/' > ${tmp_file}
while read line
do
tag="${line/=*}"
if [[ ${line/*=*/=} == "=" ]] && [[ "${tag}" != "" ]]
then
value="$(tag_read "${track_file}" "${tag}")"
if [[ "$(tag_exist ${tag})" == "" ]]
then
taglist="${taglist}${tag}:"
fi
if [[ ( "${mode}" != "FACTORING" ) || ( "${tag}" =~ ^${NODEF_TAG_COND}$ ) || ( "${tagtab["0,${tag}"]}" != "" ) ]]
then
if [[ "${tagtab["0,${tag}"]}" != "${value}" ]]
then
tagtab["${track_id},${tag}"]="$value"
fi
else
tagtab["0,${tag}"]="${value}"
fi
fi
done < ${tmp_file}
;;
*.mp3)
mid3v2 --list "${track_file}" | tail -n +2 | sed -e 's/^[^=]*=/\U&\E/' > ${tmp_file}
while read line
do
mp3tag="${line/=*}"
value="$(tag_read "${track_file}" "${mp3tag}")"
if [[ "${line/*=*/=}" == "=" ]] && [[ "${mp3tag}" != "" ]] && [[ "${MP3_2_FLAC_TAB["${mp3tag}"]}" != "" ]]
then
tag="${MP3_2_FLAC_TAB["${mp3tag}"]}"
if [[ "$(tag_exist ${tag})" == "" ]]
then
taglist="${taglist}${tag}:"
fi
if [[ ( "${mode}" != "FACTORING" ) || ( "${tag}" =~ ^${NODEF_TAG_COND}$ ) || ( "${tagtab["0,${tag}"]}" != "" ) ]]
then
if [[ "${tagtab["0,${tag}"]}" != "${value}" ]]
then
tagtab["${track_id},${tag}"]="$value"
fi
else
tagtab["0,${tag}"]="${value}"
fi
fi
done < ${tmp_file}
;;
*)
err_echo "tagtab_read: Unknown file format: ${track_file}"
;;
esac
if [[ ${taglist} == ":" ]]
then
taglist=""
fi
\rm -f ${tmp_file}
}
# TagTab Load
#-----------------------------------------------------------------------------------------------------------------------------------
function tagtab_load
{
metadata_file="$1"
mode="$2"
track_id=0
eoa="false"
while read -r line && [[ "${eoa}" != "true" ]]
do
tag="${line/=*}"
value="${line/${tag}=}"
case "${tag}"
in
@${FLAC_TAG_COND})
tagtab["${track_id},${tag}"]="$value"
;;
DEF)
;;
SOT)
track_id=$((${track_id} + 1))
;;
EOT)
;;
EOA)
eoa="true"
;;
*)
err_echo "tagtab_load: Unkwown tag: '${tag}'"
;;
esac
done < "${metadata_file}"
}
# TagTab Dump
#-----------------------------------------------------------------------------------------------------------------------------------
function tagtab_dump
{
track_id="$1"
dump_mode="$2"
case "${dump_mode}" in
"STANDARD")
dump_list="${FLAC_TAG_LIST}"
;;
"PASSTHROUGH")
dump_list="${taglist//:/ }"
;;
"CUSTOM")
dump_list="$3"
;;
esac
for tag in ${dump_list}
do
if [[ "${tagtab["${track_id},${tag}"]}" != "" ]]
then
echo "${tag}=${tagtab["${track_id},${tag}"]}"
fi
done
}
# Tag Get
#-----------------------------------------------------------------------------------------------------------------------------------
function tag_get
{
declare -n return=$1
track_id=$2
tag=$3
return="${tagtab["${track_id},${tag}"]}"
if [[ "${return}" == "" ]]
then
return="${tagtab["0,${tag}"]}"
if [[ "${return}" == "" ]] && [[ "${tag}" == "TRACKNUMBER" ]]
then
return="$(printf "%02d" ${track_id})"
fi
fi
}
# Tag Save
#-----------------------------------------------------------------------------------------------------------------------------------
function tag_save
{
target_file=$1
track_id=$2
mode=$3
if [[ "${mode}" == "CLEAN" ]]
then
tag_all_delete "${target_file}" ""
fi
for tag in ${FLAC_TAG_LIST}
do
# if [[ "${tagtab["${track_id},${tag}"]}" == "" ]]
# then
# value="${tagtab["0,${tag}"]}"
#
# if [[ "${value}" == "" ]] && [[ "${tag}" == "TRACKNUMBER" ]]
# then
# value="$(printf "%02d" ${track_id})"
# fi
# else
# value="${tagtab["${track_id},${tag}"]}"
# fi
tag_get value "${track_id}" "${tag}"
tag_delete "${target_file}" "${tag}"
if [[ "${value}" != "" ]]
then
tag_write "${target_file}" "${tag}" "${value}"
fi
done
}
# Tag Read
#-----------------------------------------------------------------------------------------------------------------------------------
function tag_read
{
track_file="$1"
tag="$2"
case "${track_file}"
in
*.flac)
metaflac --show-tag="${tag}" "${track_file}" | sed -e 's/^[^=]*=//' -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g'
;;
*.mp3)
# mid3v2 --list "${track_file}" | tail -n +2 | sed -e 's/^[^=]*=/\U&\E/' | grep -e "^${FLAC_2_MP3_TAB["${tag}"]}" | sed -e 's/^[^=]*=//' -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g'
mid3v2 --list "${track_file}" | tail -n +2 | grep -e "^${tag}" | sed -e 's/^[^=]*=//' -e ':a' -e 'N' -e '$!ba' -e 's/\n/\\n/g'
;;
*)
err_echo "tag_read: Unknown file format: ${track_file}"
;;
esac
}
# Tag Write
#-----------------------------------------------------------------------------------------------------------------------------------
function tag_write
{
track_file="$1"
tag="$2"
value="$3"
value="$(echo -e "$(escape_str "${value}")")"
case "${track_file}"
in
*.flac)
cmd="metaflac --set-tag=\"${tag}=${value}\" \"${track_file}\""
exec_cmd "${cmd}"
;;
*.mp3)
cmd="mid3v2 --\"${FLAC_2_MP3_TAB["${tag}"]}\" \"${value}\" \"${track_file}\""
exec_cmd "${cmd}"
;;
*)
err_echo "tag_write: Unknown file format: ${track_file}"
;;
esac
}
# Tag Delete
#-----------------------------------------------------------------------------------------------------------------------------------
function tag_delete
{
track_file="$1"
tag="$2"
case "${track_file}"
in
*.flac)
cmd="metaflac --remove-tag=\"${tag}\" \"${track_file}\""
exec_cmd "${cmd}"
;;
*.mp3)
cmd="mid3v2 --delete-frames=\"${FLAC_2_MP3_TAB["${tag}"]}\" \"${track_file}\""
exec_cmd "${cmd}"
;;
*)
err_echo "tag_delete: Unknown file format: ${track_file}"
;;
esac
}
# Tag All Delete
#-----------------------------------------------------------------------------------------------------------------------------------
function tag_all_delete
{
track_file="$1"
header_type="$2"
if [[ "${header_type}" == "" ]]
then
case "${track_file##*.}"
in
flac)
header_type="ogg"
;;
mp3)
header_type="id3"
;;
esac
fi
if [[ ( "${header_type}" == "ogg") && ( "${track_file##*.}" == "mp3") ]]
then
err_echo "tag_all_delete: Can't remove ogg tags from mp3 file!"
else
case "${header_type}"
in
ogg)
cmd="metaflac --remove-all-tags \"${track_file}\""
exec_cmd "${cmd}"
;;
id3)
cmd="mid3v2 --delete-all \"${track_file}\""
exec_cmd "${cmd}"
;;
*)
err_echo "tag_all_delete: Unknown header type: ${header_type}"
;;
esac
fi
}
# Album Type Get
#-----------------------------------------------------------------------------------------------------------------------------------
function album_type_get
{
track_file="$1"
for type in various_artists tribute original_soundtrack child
do
if [[ ${track_file} == */${type}/* ]]
then
echo "${type}"
fi
done
}