dam/cue2git.sh

201 lines
8.6 KiB
Bash

#!/bin/bash
source /usr/lib/bash/bunc
IFS='
'
file_name() {
local SOURCE="${1}"
local SHA256="${2}"
echo "SHA256-${SOURCE}-${SHA256}"
}
fix_apos() {
local fileList=("${@}")
for file in ${fileList[@]}; do
sed -i 's/\xc2\x92/\x27/g' "${file}"
sed -i 's/\xc2\x85/\x2e\x2e\x2e/g' "${file}"
sed -i 's/\xc2\x96/\x2d/g' "${file}"
done
return 0
}
addbom() {
local fileList=("${@}")
for file in ${fileList[@]}; do
sed -i '1s/^\(\xef\xbb\xbf\)\?/\xef\xbb\xbf/' "${file}"
done
return 0
}
deploy_split() {
local FLAC="${1}"
local CUE="${2}"
## breakpointList generator
# Generates list with cuebreakpoints utility
local breakpointList=($(cuebreakpoints "${CUE}" 2>/dev/null))
# In the event that breakpointList is empty because image represents only one track,
# no split occurs, and returns a 0.
[[ -z "${breakpointList[@]}" ]] && { cat "${FLAC}" > split-track01.flac; return 0; }
# Attempts first split. If fails because of lack of CD quality file, retries with modified breakpointList
if ! printf '%s\n' ${breakpointList[@]} | shntool split "${FLAC}" -o flac -O always ; then
printf '%s\n' ${breakpointList[@]} | sed s/$/0/ | shntool split "${FLAC}" -o flac -O always
[[ $? -eq 0 ]] && return 2 || return 1
fi
return 0
}
gen_trackid() {
FLAC="${1}"
CUE="${2}"
deploy_split ${FLAC} ${CUE} >/dev/null 2>&1
local TOTALTRACKS="$(grep -e "TRACK [0-9][0-9] AUDIO" "${CUE}" | wc -l)"
local COUNT=1
while [[ ${COUNT} -le ${TOTALTRACKS} ]]; do
local TRACKID="$(metaflac --list --block-number=0 $(printf "split-track%02d.flac" ${COUNT}) | awk 'BEGIN{FS=": "}{if($1==" MD5 signature") {print $2}}')"
printf "%s\t" ${TRACKID}
rm $(printf "split-track%02d.flac" ${COUNT})
local COUNT=$(( ${COUNT} + 1 ))
done
}
gen_mtag() {
local FILE_NAME="${1}"
local METADATA="${2}"
# Metadata Parsing
metadataList=($(echo ${METADATA} | sed 's|;| |g'))
for metadata in ${metadataList[@]}; do
eval local ${metadata}
done
for file in ${fileList[@]}; do
local trackList=(${trackList[@]} $(echo ${file} | sed 's|.*/||' | cut -d- -f2 | sed 's| ||' | sed 's|\.flac||'))
done
echo "["
local COUNT=0
while [[ ${COUNT} -lt ${#titleList[@]} ]]; do
[[ ${COUNT} -ne 0 ]] && echo " },"
echo " {"
echo " \"@\" : \"${FILE_NAME}.cue|$(( ${COUNT} + 1 ))\","
if [[ ${COUNT} -eq 0 ]]; then
[[ ! -z "${ALBUM+x}" ]] && echo " \"ALBUM\" : \"${ALBUM}\","
[[ ! -z "${PERFORMER+x}" ]] && echo " \"ARTIST\" : \"${PERFORMER}\","
[[ ! -z "${META_COMPOSER+x}" ]] && echo " \"COMPOSER\" : \"${META_COMPOSER}\","
[[ ! -z "${META_CONDUCTOR+x}" ]] && echo " \"CONDUCTOR\" : \"${META_CONDUCTOR}\","
[[ ! -z "${META_ORCHESTRA+x}" ]] && echo " \"ORCHESTRA\" : \"${META_ORCHESTRA}\","
[[ ! -z "${DATE+x}" ]] && echo " \"DATE\" : \"${DATE}\","
[[ ! -z "${DISCNUMBER+x}" ]] && echo " \"DISCNUMBER\" : \"${DISCNUMBER}\","
[[ ! -z "${TOTALDISCS+x}" ]] && echo " \"TOTALDISCS\" : \"${TOTALDISCS}\","
[[ ! -z "${BATCHNUMBER+x}" ]] && echo " \"BATCHNUMBER\" : \"${BATCHNUMBER}\","
echo " \"TOTALTRACKS\" : \"${#titleList[@]}\","
fi
[[ ! -z "${performerList[${COUNT}]+x}" ]] && echo " \"PERFORMER\" : \"${performerList[${COUNT}]}\","
echo " \"TITLE\" : \"${titleList[${COUNT}]}\","
echo " \"TRACKID\" : \"${trackidList[${COUNT}]}\","
echo " \"TRACKNUMBER\" : \"$(( ${COUNT} + 1 ))\""
local COUNT=$(( ${COUNT} + 1 ))
done
echo " }"
echo "]"
return 0
}
cueparser() {
local FLAC="${1}"
local CUE="${2}"
dos2unix -q -R "${CUE}"
## [Input] metaList generator
# Generates lists that are later used for the parsing of the cuesheet. This is necessary
# because cue sheets are have two sections: a general metadata section that applies to the
# whole disc, and a track-specific section that applies to each track. PERFORMER defined
# in the general section gets overriden by a PERFORMER defined in a track, thus it is
# important to seperate the two. Another thing of import is seperating the different tracks
# so they can be parsed as seperate elements. The trackmetaList uses tr to remove the new
# line, and then uses awk to have every line have a specific track's information
local trackmetaList=($( sed -n '/TRACK 01/,$p' ${CUE} | tr -d '\n' | awk 'BEGIN {RS="TRACK"}{print $0}' | tail -n +2))
local trackidList=($(gen_trackid ${FLAC} ${CUE}))
# [Output] variable generator
echo -n "PERFORMER=\"$(sed 's|\ \ .*||' "${CUE}" | grep -a "PERFORMER" | sed 's|PERFORMER ||' | sed 's|\"||g')\";"
echo -n "ALBUM=\"$(sed 's|\ \ .*||' "${CUE}" | grep -a "TITLE" | sed 's|TITLE ||' | sed 's|\"||g')\";"
echo -n "DATE=$(sed 's|\ \ .*||' "${CUE}" | grep -a "REM DATE" | sed 's|REM DATE ||');"
echo -n "DISCNUMBER=$(sed 's|\ \ .*||' "${CUE}" | grep -a "REM DISCNUMBER" | sed 's|REM DISCNUMBER ||');"
echo -n "TOTALDISCS=$(sed 's|\ \ .*||' "${CUE}" | grep -a "REM TOTALDISCS" | sed 's|REM TOTALDISCS ||');"
local COUNT=0
for trackmeta in ${trackmetaList[@]}; do
echo -n "titleList[${COUNT}]=\"$(echo ${trackmeta} | awk 'BEGIN {RS=" "}{print $0}' | grep -a TITLE | sed 's|TITLE ||' | sed 's|\"||g')\";"
echo -n "performerList[${COUNT}]=\"$(echo ${trackmeta} | awk 'BEGIN {RS=" "}{print $0}' | grep -a PERFORMER | sed 's|PERFORMER ||' | sed 's|\"||g')\";"
echo -n "trackidList[${COUNT}]=\"${trackidList[${COUNT}]}\";"
local COUNT=$(( ${COUNT} + 1 ))
done
}
gen_cover() {
local FOLDER="${1}"
[[ -f "${FOLDER}/folder.jpg" ]] && convert "${FOLDER}/folder.jpg" "${FOLDER}/folder.png" || { convert -size 480x480 xc:white "${FOLDER}/folder.png"; local ERROR=1; }
cat "${FOLDER}/folder.png"
[[ ${ERROR} -eq 1 ]] && return 1
local IMG_SIZE="$(identify -format "%wx%h" "${FOLDER}/folder.jpg")"
local IMG_WIDTH=$(echo ${IMG_SIZE} | cut -dx -f1)
local IMG_HEIGHT=$(echo ${IMG_SIZE} | cut -dx -f2)
if [[ ${IMG_WIDTH} -lt 480 ]] && [[ ${IMG_HEIGHT} -lt 480 ]]; then return 2; fi
return 0
}
gen() {
local FOLDER="${1}"
_msg EXEC "Processing ${FOLDER}"
local flacList=($(find "${FOLDER}" -name '*.flac' | sed 's|.flac||'))
[[ ${#flacList[@]} -eq 0 ]] && { _msg FAIL "No such file or directory"; return 1; }
for flac in ${flacList[@]}; do
# Sanity check
[[ -f "${flac}.cue" ]] || { _msg FAIL "No cue file present"; return 1; }
[[ -f "${flac}.accurip" ]] || { _msg FAIL "No accurip file present"; return 1; }
[[ -f "${flac}.log" ]] || { _msg FAIL "No EAC log file present"; return 1; }
# Determines file name based on image's CHKSUM and acts accordingly
cat ${flac}.flac > output.flac 2>/dev/null
metaflac --remove-all --dont-use-padding "output.flac"
local SHA256=$(sha256sum ${flac}.flac 2>/dev/null | cut -d' ' -f1)
local SOURCE=$(grep "CTDB TOCID:" ${flac}.accurip 2>/dev/null | cut -d' ' -f3 | sed 's|]||')
local FILE_NAME=$(file_name ${SOURCE} ${SHA256})
mv "output.flac" ${FILE_NAME}.flac > /dev/null 2>&1
cat "${flac}.cue" | iconv -f ISO-8859-1 -t UTF-8 | sed '1s/^\(\xef\xbb\xbf\)\?/\xef\xbb\xbf/' | awk "!/FILE/{print} /FILE/{print \"FILE ${FILE_NAME}.flac WAVE\"}" > ${FILE_NAME}.cue 2> /dev/null
cat "${flac}.accurip" | iconv -f ISO-8859-1 -t UTF-8 > ${FILE_NAME}.accurip
cat "${flac}.log" | iconv -f ISO-8859-1 -t UTF-8 > ${FILE_NAME}.log
addbom ${FILE_NAME}.cue
# Generates METADATA and MTAG
local METADATA="$(cueparser ${FILE_NAME}.flac ${FILE_NAME}.cue);BATCHNUMBER=$(echo "${FOLDER}" | awk 'BEGIN{RS="/";}{print $0}' | grep batch | sed 's|.*_|_|' | sed -e 's/_0*//g');"
gen_mtag "${FILE_NAME}" ${METADATA} > ${FILE_NAME}.tags
addbom ${FILE_NAME}.tags
fix_apos ${FILE_NAME}.tags
gen_cover "${FOLDER}" > ${FILE_NAME}.png
local EXIT="$?"
if [[ ${EXIT} -eq 1 ]]; then
_msg WARN "No folder.jpg in directory. Placeholder created"
elif [[ ${EXIT} -eq 2 ]]; then
_msg WARN "folder.jpg is under 480x480 in quality"
else
_msg OK
fi
done
}
dirList=("${@}")
for dir in ${dirList[@]}; do
folderList=($(find "${dir}" -name '*.cue' -printf '%h\n' | awk '!seen[$0]++'))
for folder in ${folderList[@]}; do
gen "${folder}"
done
done