Merge branch 'master' into video

This commit is contained in:
Vincent Riquer 2013-05-31 22:21:27 +02:00
commit 95e7bbbbf6
37 changed files with 1374 additions and 526 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.ex
*.EX
trace.log

47
README
View File

@ -19,21 +19,26 @@ Required:
Optional:
* vorbis-tools
http://www.vorbis.com/
* ogginfo (Ogg Vorbis tags support)
* oggenc (Ogg Vorbis destination)
* ogginfo (Ogg Vorbis metadata)
* oggenc (Ogg Vorbis encoding)
* opus-tools
http://opus-codec.org/
* opusinfo (Opus tags support)
* opusenc (Opus destination)
* opusinfo (Opus metadata)
* opusenc (Opus encoding)
* opusdec (Opus decoding)
* LAME MP3 Encoder
http://lame.sourceforge.net/
* lame (MP3 destination)
* lame (MP3 encoding)
* FLAC
http://flac.sourceforge.net/
* metaflac (FLAC tags support)
* metaflac (FLAC metadata)
* Musepack
http://www.musepack.net/
* mpcdec (Musepack decoding)
* FFmpeg
http://ffmpeg.org/
* ffprobe (ID3v2, Musepack, Windows Media and video metadata)
* ffmpeg (Windows Media and video decoding)
==================
Using the software
@ -41,3 +46,33 @@ Using the software
Configuration:
Please read doc/config before anything else.
====
Toys
----
AtOM requires a database to function. Now that we have a database containing
various information about our media files, why not use it?
AtOM comes with a small set of tools in the toys/ directory. These are
documented in toys/README.
========================
Shameless Self Promotion
------------------------
I am the author of free (Creative Commons CC-By-SA) music which you can stream
for free, or buy to get high quality and bonuses from Bandcamp
(http://djblackred.bandcamp.com). If you like electronic music taking its
inspiration from Trance, Drum & Bass, Ambient and (rarely) Free Jazz, please
check it out!
Downloads are available in FLAC, Ogg, MP3, and more, and includes the "source
code" (sequencer files and the likes) for most tracks.
I am receiving 85% of the money you'll spend, so you won't be feeding some
greedy BigCorp producer or distributor.
And if you don't like it, you can still spread the word to friends who may like.
You can see this as a way to thank me for this piece of code.
=====
Legal
-----
Some of the format and/or tool names cited above are trademarks belonging to
their rightful owners. AtOM and its authors are not linked in any way to
those companies or individuals. Said companies do not endorse nor support
AtOM in any way.

396
atom
View File

@ -96,8 +96,6 @@ do
esac
done
#FIXME: check sanity
if [ ! -f "$cffile" ]
then
if [ ! -d ~/.atom ]
@ -117,9 +115,143 @@ fi
getConfig
set +H
# Apply CLI overrides
[ -n "$cliload" ] && maxload=$cliload
[ -n "$cliltimer" ] && loadinterval=$cliltimer
(( debug || cfgdump )) && printConfig
(( cfgdump )) && exit
# check sanity
if [ ! -d "$tempdir" ] && ! mkdir -p "$tempdir"
then
echo "[FATAL] Could not create temp directory $tempdir" >&2
(( sanityfail++ ))
fi
if [ ! -f "$database" ] && [ ! -d "${database%/*}" ] && ! mkdir -p "${database%/*}"
then
echo "[FATAL] Directory holding database file does not exist and could" \
"not be created" >&2
(( sanityfail++ ))
fi
if [ ! -d "$sourcepath" ]
then
echo "[FATAL] Source path $sourcepath does not exist or is not a directory" >&2
(( sanityfail++ ))
fi
if ! which sed >/dev/null
then
echo "[FATAL] Required tool sed is not installed or not in PATH
I never thought this would actually hit someone..." >&2
(( sanityfail++ ))
fi
if ! which sox >/dev/null
then
echo "[FATAL] Required tool sox is not installed or not in PATH" >&2
(( sanityfail++ ))
fi
if ! which ogginfo >/dev/null
then
echo "[WARNING] Tool ogginfo (from vorbis-tools) is not" \
"installed or not in PATH
Vorbis metadata disabled" >&2
disableogginfo=1
(( sanitywarn++ ))
fi
if (( oggencneeded )) && ! which oggenc >/dev/null
then
echo "[WARNING] Tool oggenc (from vorbis-tools) is not" \
"installed or not in PATH
Vorbis targets disabled" >&2
disableoggenc=1
(( sanitywarn++ ))
fi
if ! which opusinfo >/dev/null
then
echo "[WARNING] Tool opusinfo (from opus-tools) is not" \
"installed or not in PATH
Opus metadata disabled" >&2
disableopusinfo=1
(( sanitywarn++ ))
fi
if (( opusencneeded )) && ! which opusenc >/dev/null
then
echo "[WARNING] Tool opusenc (from opus-tools) is not" \
"installed or not in PATH
Opus targets disabled" >&2
disableopusenc=1
(( sanitywarn++ ))
fi
if ! which opusdec >/dev/null
then
echo "[WARNING] Tool opusdec (from opus-tools) is not" \
"installed or not in PATH
Opus support disabled" >&2
disableopusdec=1
(( sanitywarn++ ))
fi
if (( lameneeded )) && ! which lame >/dev/null
then
echo "[WARNING] Tool lame is not installed or not in PATH
MP3 targets disabled" >&2
disablelame=1
(( sanitywarn++ ))
fi
if ! which metaflac >/dev/null
then
echo "[WARNING] Tool metaflac (from FLAC) is not installed" \
"or not in PATH
FLAC metadata disabled" >&2
disableflac=1
(( sanitywarn++ ))
fi
if ! which mpcdec >/dev/null
then
echo "[WARNING] Tool mpcdec (from Musepack) is not" \
"installed or not in PATH
Musepack support disabled" >&2
disablempcdec=1
(( sanitywarn++ ))
fi
if ! which ffprobe >/dev/null
then
echo "[WARNING] Tool ffprobe (from FFmpeg) is not installed or not in PATH
Video metadata disabled
MPEG metadata disabled
MusePack metadata disabled
Unknown format metadata disabled" >&2
disableffprobe=1
(( sanitywarn++ ))
fi
if ! which ffmpeg >/dev/null
then
echo "[WARNING] Tool ffmpeg is not installed or not in PATH
Video support disabled" >&2
disablevideo=1
(( sanitywarn++ ))
fi
if (( sanityfail ))
then
echo "
Sanity checks raised ${sanitywarn:-0} warnings, $sanityfail failures. Dying now." >&2
exit $ESANITY
elif (( sanitywarn ))
then
echo "
Sanity checks raised $sanitywarn warnings... Hit Control-C to abort." >&2
timeout=$(( sanitywarn * 10 ))
echo -n "Starting in $(printf %3i $timeout)" \
$'seconds...\b\b\b\b\b\b\b\b\b\b\b' >&2
while (( timeout ))
do
echo -n $'\b\b\b'"$(printf %3i $timeout)" >&2
sleep 1
(( timeout-- ))
done
echo -en "\r\033[K"
fi
openDatabase
createDestinations
@ -144,8 +276,8 @@ removed=0
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
id=${line%|*}
filename=${line#*|}
id=${line%::AtOM:SQL:Sep::*}
filename=${line#*::AtOM:SQL:Sep::}
if [ -n "$filename" ]
then
if rm -f "$filename"
@ -161,115 +293,20 @@ do
done
echo "Suppressed $deleted files, $removed removed from database"
# get files
for reader in "${tagreaders[@]}"
do
tagreaderclause+="${tagreaderclause:+ AND }NOT tags.tagreader = \"$reader\""
done
echo '
SELECT COUNT(DISTINCT source_files.filename)
FROM source_files
INNER JOIN destination_files
ON destination_files.source_file_id=source_files.id
INNER JOIN destinations
ON destination_files.destination_id=destinations.id
INNER JOIN mime_type_actions
ON destinations.id=mime_type_actions.destination_id
INNER JOIN tags
ON source_files.id=tags.source_file
WHERE mime_type_actions.id = source_files.mime_type
AND (
CAST(tags.last_change AS TEXT)
<>
CAST(source_files.last_change AS TEXT)
OR ('"$tagreaderclause"')
)
AND mime_type_actions.action = 1;' >&3
read -u4 filecount
echo '
SELECT DISTINCT
source_files.id,
source_files.last_change,
mime_type_actions.mime_text,
source_files.filename
FROM source_files
INNER JOIN destination_files
ON destination_files.source_file_id=source_files.id
INNER JOIN destinations
ON destination_files.destination_id=destinations.id
INNER JOIN mime_type_actions
ON destinations.id=mime_type_actions.destination_id
INNER JOIN tags
ON source_files.id=tags.source_file
WHERE mime_type_actions.id = source_files.mime_type
AND (
CAST(tags.last_change AS TEXT)
<>
CAST(source_files.last_change AS TEXT)
OR ('"$tagreaderclause"')
)
AND mime_type_actions.action = 1;
updateTags
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 line
while ! [[ $line = AtOM:NoMoreFiles ]]
for forcedest in "${forceall[@]}"
do
tagfiles+=("$line")
read -u4 line
done
echo 'BEGIN TRANSACTION;' >&3
for line in "${tagfiles[@]}"
do
sourcefileid=${line%%|*}
rest=${line#*|}
lastchange=${rest%%|*}
rest=${rest#*|}
mimetype=${rest%%|*}
filename=${rest#*|}
echo -en "\rTags: $((++count*100/filecount))%"
if (( count % 1000 == 0 ))
if forcedestid=$(Select destinations id <<<"name = $forcedest")
then
echo 'COMMIT;BEGIN TRANSACTION;' >&3
(( debug )) \
&& echo -n " $count files read, committing..."
fi
if getTags
then
Update tags \
album "${album:-NULL}" \
albumartist "${albumartist:-NULL}" \
artist "${artist:-NULL}" \
composer "${composer:-NULL}" \
disc "${disc:-NULL}" \
genre "${genre:-NULL}" \
performer "${performer:-NULL}" \
title "${title:-NULL}" \
track "${tracknum:-NULL}" \
year "${year:-NULL}" \
last_change "$lastchange" \
rate "${rate:-NULL}" \
channels "${channels:-NULL}" \
bitrate "${bitrate:-NULL}" \
tagreader "$tagreader" \
>/dev/null <<<"source_file = $sourcefileid"
unset genre \
albumartist \
year \
album \
disc \
artist \
tracknum \
title \
composer \
performer \
rate \
bitrate \
channels
echo "Resetting destination files timestamps on" \
"$forcedest ($forcedestid)..."
Update destination_files last_change 1 \
<<<"destination_id = $forcedestid"
else
echo "Destination $forcedest does not exist!" >&2
fi
done
echo 'COMMIT;' >&3
echo -e "\rRead tags from ${count:-0} files."
unset count tagfiles
echo '
CREATE TEMPORARY TABLE tasks(
@ -376,7 +413,7 @@ echo '
read -u4 line
while ! [[ $line = AtOM:NoMoreFiles ]]
do
decodefiles+=("$line|")
decodefiles+=("$line::AtOM:SQL:Sep::")
read -u4 line
done
echo -n 'Creating tasks... '
@ -384,42 +421,47 @@ echo -n 'Creating tasks... '
echo 'BEGIN TRANSACTION;' >&3
for line in "${decodefiles[@]}"
do
fileid=${line%%|*}
rest=${line#*|}
filename=${rest%%|*}
rest=${rest#*|}
mimetype=${rest%%|*}
rest=${rest#*|}
destination=${rest%%|*}
rest=${rest#*|}
destfileid=${rest%%|*}
rest=${rest#*|}
rate=${rest%%|*}
rest=${rest#*|}
channels=${rest%%|*}
rest=${rest#*|}
bitrate=${rest%%|*}
rest=${rest#*|}
genre=${rest%%|*}
rest=${rest#*|}
albumartist=${rest%%|*}
rest=${rest#*|}
year=${rest%%|*}
rest=${rest#*|}
album=${rest%%|*}
rest=${rest#*|}
disc=${rest%%|*}
rest=${rest#*|}
artist=${rest%%|*}
rest=${rest#*|}
track=${rest%%|*}
rest=${rest#*|}
title=${rest%%|*}
rest=${rest#*|}
composer=${rest%%|*}
rest=${rest#*|}
performer=${rest%%|*}
fileid=${line%%::AtOM:SQL:Sep::*}
rest=${line#*::AtOM:SQL:Sep::}
filename=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
mimetype=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destination=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destfileid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
rate=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
channels=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
bitrate=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
genre=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
albumartist=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
year=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
album=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
disc=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
artist=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
track=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
title=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
composer=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
performer=${rest%%::AtOM:SQL:Sep::*}
unset rest
case ${destinationformat["$destination"]} in
vorbis) (( disableoggenc )) && continue ;;
opus) (( disableopusenc )) && continue ;;
mp3) (( disablelame )) && continue ;;
esac
decodeFile
getDestDir
getDestFile
@ -502,13 +544,13 @@ do
checkworkers
cleaner
master
if (( ran ))
if (( ran - failed ))
then
currenttime=$(date +%s)
avgduration=$((
((currenttime - starttime) * 1000)
/
ran
( ran - failed )
))
secsremaining=$(( remaining * avgduration / 1000 ))
(( days =
@ -647,32 +689,32 @@ do
echo -n "$destination: rename pattern changed, renaming files... "
while [[ $line != AtOM:NoMoreFiles ]]
do
oldfilename=${line%%|*}
rest=${line#*|}'|'
destfileid=${rest%%|*}
rest=${rest#*|}
filename=${rest%%|*}
rest=${rest#*|}
album=${rest%%|*}
rest=${rest#*|}
albumartist=${rest%%|*}
rest=${rest#*|}
artist=${rest%%|*}
rest=${rest#*|}
composer=${rest%%|*}
rest=${rest#*|}
disc=${rest%%|*}
rest=${rest#*|}
genre=${rest%%|*}
rest=${rest#*|}
performer=${rest%%|*}
rest=${rest#*|}
title=${rest%%|*}
rest=${rest#*|}
track=${rest%%|*}
rest=${rest#*|}
year=${rest%%|*}
rest=${rest#*|}
oldfilename=${line%%::AtOM:SQL:Sep::*}
rest=${line#*::AtOM:SQL:Sep::}'::AtOM:SQL:Sep::'
destfileid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
filename=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
album=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
albumartist=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
artist=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
composer=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
disc=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
genre=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
performer=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
title=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
track=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
year=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
if [ -n "$oldfilename" -a -f "$oldfilename" ]
then
getDestDir
@ -720,11 +762,11 @@ done
echo 'BEGIN TRANSACTION;' >&3
for line in "${lines[@]}"
do
id=${line%%|*}
rest=${line#*|}
filename=${rest%%|*}
oldfilename=${rest#*|}
if [[ $oldfilename != $filename ]] && [ -f "$oldfilename" ]
id=${line%%::AtOM:SQL:Sep::*}
rest=${line#*::AtOM:SQL:Sep::}
filename=${rest%%::AtOM:SQL:Sep::*}
oldfilename=${rest#*::AtOM:SQL:Sep::}
if [[ $oldfilename != "$filename" ]] && [ -f "$oldfilename" ]
then
rm -f "$oldfilename"
fi

View File

@ -8,12 +8,15 @@ getConfigDestination() {
case "$value" in
'mp3')
destinationformat["$destination"]=mp3
lameneeded=1
;;
'opus')
destinationformat["$destination"]=opus
opusencneeded=1
;;
'vorbis')
destinationformat["$destination"]=vorbis
oggencneeded=1
;;
*)
echo "Unsupported destination format: $value" >2&

View File

@ -6,6 +6,7 @@ copyFiles_action() {
source_files.filename,
source_files.last_change,
destinations.id,
destinations.name,
destination_files.id
FROM source_files
INNER JOIN destination_files
@ -31,53 +32,62 @@ copyFiles_action() {
echo 'BEGIN TRANSACTION;' >&3
for copyfile in "${copyfiles[@]}"
do
sourcefilename=${copyfile%%|*}
sourcefilename=${copyfile%%::AtOM:SQL:Sep::*}
sourcedir=${sourcefilename%/*}
rest="${copyfile#*|}|"
lastchange=${rest%%|*}
rest=${rest#*|}
destinationid=${rest%%|*}
rest=${rest#*|}
destfileid=${rest%%|*}
rest=${rest#*|}
echo 'SELECT IFNULL( (
SELECT destination_files.filename
FROM destination_files
INNER JOIN source_files
ON destination_files.source_file_id=source_files.id
INNER JOIN mime_type_actions
ON
mime_type_actions.id=source_files.mime_type
INNER JOIN destinations
ON destinations.id=destination_files.destination_id
WHERE destinations.id = '$destinationid'
AND source_files.filename LIKE
"'"${sourcedir//\"/\"\"}"'/%"
AND mime_type_actions.action = 1
LIMIT 1
),"AtOM:NotFound");
'>&3
read -u4 filename
if [[ $filename != AtOM:NotFound ]]
then
destdir=${filename%/*}
if cp -al "$sourcepath/$sourcefilename" "$destdir" 2>/dev/null\
|| cp -a "$sourcepath/$sourcefilename" "$destdir"
then
Update destination_files \
filename "$destdir/${sourcefilename##*/}"\
rename_pattern "${destinationrenamepath[$destination]}/${destinationrename[$destination]}:${destinationfat32compat["$destination"]}"\
last_change $lastchange \
<<-EOWhere
id = $destfileid
EOWhere
(( done++ ))
fi
fi
rest="${copyfile#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
lastchange=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destinationid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destination=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destfileid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
(( count++ ))
printf '\b\b\b\b%3i%%' $(( (count * 100) / ${#copyfiles[@]} ))
if [ -n "${renamepath["$destination"]}" ]
then
destdir="$(guessPath)" || continue
else
destdir="${destinationpath["$destination"]}/"
if [[ $sourcefilename =~ / ]]
then
destdir+=$(
sanitizeFile "${sourcefilename%%/*}" dir
)
part=${sourcefilename#*/}
while [[ $part =~ / ]]
do
destdir+="/$(
sanitizeFile "${part%%/*}" dir
)"
part=${part#*/}
done
if ! [ -d "$destdir" ]
then
mkdir -p "$destdir"
fi
fi
fi
if cp -al "$sourcepath/$sourcefilename" "$destdir" 2>/dev/null\
|| cp -a "$sourcepath/$sourcefilename" "$destdir"
then
Update destination_files \
filename "$destdir/${sourcefilename##*/}"\
rename_pattern "${destinationrenamepath[$destination]}/${destinationrename[$destination]}:${destinationfat32compat["$destination"]}"\
last_change $lastchange \
<<-EOWhere
id = $destfileid
EOWhere
(( done++ ))
fi
done
echo 'COMMIT;' >&3
echo -e "\rCopied ${done:-0} of $count files.\033[K"
if (( count ))
then
echo -e "\rCopied ${done:-0} of $count files.\033[K"
else
echo -e "\rNothing to copy.\033[K"
fi
unset count done
}

28
lib/copy/guessPath Normal file
View File

@ -0,0 +1,28 @@
#!/bin/bash
guessPath() {
echo 'SELECT IFNULL( (
SELECT destination_files.filename
FROM destination_files
INNER JOIN source_files
ON destination_files.source_file_id=source_files.id
INNER JOIN mime_type_actions
ON
mime_type_actions.id=source_files.mime_type
INNER JOIN destinations
ON destinations.id=destination_files.destination_id
WHERE destinations.id = '$destinationid'
AND source_files.filename LIKE
"'"${sourcedir//\"/\"\"}"'/%"
AND mime_type_actions.action = 1
LIMIT 1
),"AtOM:NotFound");
'>&3
read -u4 filename
if [[ $filename != AtOM:NotFound ]]
then
echo "${filename%/*}"
else
return 1
fi
}

View File

@ -15,6 +15,10 @@ Insert() {
insert_keys+='`'"$key"'`'
(( ${#insert_values} )) && insert_values+=","
case $value in
'::AtOM:FT::'*)
value="${value//::AtOM:FT::/}"
insert_values+='"'"${value//\"/\"\"}"'"'
;;
'NULL')
insert_values+="NULL"
;;

View File

@ -25,7 +25,8 @@ InsertIfUnset() {
Select "$table" "$column" < <(
for key in ${!keys[@]}
do
echo "${keys[$key]}" = "${values[$key]}"
echo "${keys[$key]}" = \
"${values[$key]//::AtOM:FT::}"
done
)
)

View File

@ -26,6 +26,10 @@ Update() {
;;
value)
case $argument in
'::AtOM:FT::'*)
argument="${argument//::AtOM:FT::/}"
set_statement+=" = "'"'"${argument//\"/\"\"}"'"'
;;
'NULL')
set_statement+=" = NULL"
;;

View File

@ -1,19 +1,7 @@
#!/bin/bash
openDatabase() {
if [ ! -d "$tempdir" ]
then
mkdir -p "$tempdir"
fi
rm -f "$tempdir"/sqlite.{in,out}
mkfifo "$tempdir"/sqlite.{in,out}
if [ ! -f "$database" ]
then
if [ ! -d "${database%/*}" ]
then
mkdir -p "${database%/*}"
fi
sqlite3 "$database" < $schema
fi
sqlite3 -bail "$database" \
< "$tempdir/sqlite.in" \
> "$tempdir/sqlite.out" &
@ -24,5 +12,7 @@ openDatabase() {
exec 5>&3
exec 3> >(tee -a $tempdir/debug.log >&5)
fi
cat $schema >&3
echo '.separator ::AtOM:SQL:Sep::' >&3
echo 'PRAGMA foreign_keys = ON;' >&3
}

View File

@ -2,6 +2,7 @@
decodeFile() {
case "$mimetype" in
'video/'*)
(( disablevideo )) && continue
extractAudio
if (( ${destinationnormalize["$destination"]}))\
|| (
@ -30,6 +31,7 @@ decodeFile() {
then
copied=1
else
(( disableopusdec )) && continue
decodeOpusdec
if (( ${destinationnormalize["$destination"]}))\
|| (
@ -60,6 +62,7 @@ decodeFile() {
extendedtype=$(file -b "$sourcepath/$filename")
case "$extendedtype" in
*'Musepack '*)
(( disablempcdec )) && continue
decodeMpcdec
if (( ${destinationnormalize["$destination"]}))\
|| (

View File

@ -51,7 +51,12 @@ encodeFile::mp3() {
$(
for key in ${!lameopts[@]}
do
echo "cmd_arg$key ${lameopts[key]}"
cleanedopts="${lameopts[key]//\&/\\\&}"
cleanedopts="${cleanedopts//\[/\\[}"
cleanedopts="${cleanedopts//\]/\\]}"
cleanedopts="${cleanedopts//\{/\\{}"
cleanedopts="${cleanedopts//\}/\\\}}"
echo "cmd_arg$key $cleanedopts"
done
)
cleanup $tempdir/$tmpfile.wav

View File

@ -26,7 +26,12 @@ encodeFile::opus() {
$(
for key in ${!opusencopts[@]}
do
echo "cmd_arg$key ${opusencopts[key]}"
cleanedopts="${opusencopts[key]//\&/\\\&}"
cleanedopts="${cleanedopts//\[/\\[}"
cleanedopts="${cleanedopts//\]/\\]}"
cleanedopts="${cleanedopts//\{/\\{}"
cleanedopts="${cleanedopts//\}/\\\}}"
echo "cmd_arg$key $cleanedopts"
done
)
cleanup $tempdir/$tmpfile.wav

View File

@ -22,6 +22,11 @@ encodeFile::vorbis() {
$(
for key in ${!oggencopts[@]}
do
cleanedopts="${oggencopts[key]//\&/\\\&}"
cleanedopts="${cleanedopts//\[/\\[}"
cleanedopts="${cleanedopts//\]/\\]}"
cleanedopts="${cleanedopts//\{/\\{}"
cleanedopts="${cleanedopts//\}/\\\}}"
echo "cmd_arg$key ${oggencopts[key]}"
done
)

View File

@ -1,7 +1,34 @@
#!/bin/bash
getDestDir() {
destdir="${destinationpath[$destination]}/"
if [ -n "${destinationrenamepath[$destination]}" ]
if [ -n "${destinationrenamepath[$destination]}" ] \
&& (
(
! [[ ${destinationrenamepath[$destination]} =~ %\{album\} ]] \
|| [ -n "$album" ]
) && (
! [[ ${destinationrenamepath[$destination]} =~ %\{albumartist\} ]] \
|| [ -n "$albumartist" ]
) && (
! [[ ${destinationrenamepath[$destination]} =~ %\{artist\} ]] \
|| [ -n "$artist" ]
) && (
! [[ ${destinationrenamepath[$destination]} =~ %\{genre\} ]] \
|| [ -n "$genre" ]
) && (
! [[ ${destinationrenamepath[$destination]} =~ %\{title\} ]] \
|| [ -n "$title" ]
) && (
! [[ ${destinationrenamepath[$destination]} =~ %\{track\} ]] \
|| [ -n "$track" ]
) && (
! [[ ${destinationrenamepath[$destination]} =~ %\{year\} ]] \
|| [ -n "$year" ]
) && (
! [[ ${destinationrenamepath[$destination]} =~ %\{disc\} ]] \
|| [ -n "$disc" ]
)
)
then
replace=$(sanitizeFile "$album" dir)
destdir+="${destinationrenamepath[$destination]//%\{album\}/$replace}"

View File

@ -1,6 +1,33 @@
#!/bin/bash
getDestFile() {
if [ -n "${destinationrename[$destination]}" ]
if [ -n "${destinationrename[$destination]}" ] \
&& (
(
! [[ ${destinationrename[$destination]} =~ %\{album\} ]] \
|| [ -n "$album" ]
) && (
! [[ ${destinationrename[$destination]} =~ %\{albumartist\} ]] \
|| [ -n "$albumartist" ]
) && (
! [[ ${destinationrename[$destination]} =~ %\{artist\} ]] \
|| [ -n "$artist" ]
) && (
! [[ ${destinationrename[$destination]} =~ %\{genre\} ]] \
|| [ -n "$genre" ]
) && (
! [[ ${destinationrename[$destination]} =~ %\{title\} ]] \
|| [ -n "$title" ]
) && (
! [[ ${destinationrename[$destination]} =~ %\{track\} ]] \
|| [ -n "$track" ]
) && (
! [[ ${destinationrename[$destination]} =~ %\{year\} ]] \
|| [ -n "$year" ]
) && (
! [[ ${destinationrename[$destination]} =~ %\{disc\} ]] \
|| [ -n "$disc" ]
)
)
then
destfile="${destinationrename[$destination]//%\{album\}/$album}"
destfile="${destfile//%\{albumartist\}/$albumartist}"

View File

@ -19,7 +19,7 @@ getFiles() {
mimetype=$(file -b --mime-type "$sourcepath/$filename")
if [[ $mimetype == application/ogg ]]
then
case "$(head -n1 "$sourcepath/$filename")" in
case "$(head -n5 "$sourcepath/$filename")" in
*'vorbis'*)
mimetype+=' vorbis'
;;

View File

@ -1,55 +0,0 @@
#!/bin/bash
getInfosAPE_version='APE-1'
tagreaders+=( "$getInfosAPE_version" )
getInfos::APE() {
# I was not able to find a decent cli tool to read APE tags.
# This is raw but works for the very few MusePack files I got.
#
# Please tell me if you know of any good tool.
tagreader="$getInfosAPE_version"
IFS='='
while read tag value
do
IFS="$oldIFS"
case $tag in
[Aa][Ll][Bb][Uu][Mm]' '[Aa][Rr][Tt][Ii][Ss][Tt])
albumartist="$value"
;;
[Aa][Rr][Tt][Ii][Ss][Tt])
artist="$value"
;;
[Yy][Ee][Aa][Rr])
year="$value"
;;
[Aa][Ll][Bb][Uu][Mm])
album="$value"
;;
[Tt][Ii][Tt][Ll][Ee])
title="$value"
;;
[Tt][Rr][Aa][Cc][Kk])
tracknum="$value"
;;
[Gg][Ee][Nn][Rr][Ee])
genre="$value"
;;
[Cc][Oo][Mm][Pp][Oo][Ss][Ee][Rr])
composer="$value"
;;
[Pp][Ee][Rr][Ff][Oo][Rr][Mm][Ee][Rr])
performer="$value"
;;
*)
;;
esac
IFS='='
done < <(
IFS="$oldIFS"
sed \
's/APETAGEX/\n/;s/[\x00\-\x1F]\x00\+/\n/g;s/\x00/=/g' \
"$sourcepath/$filename" \
| egrep -i \
'^(Album Artist|Artist|Year|Album|Title|Track|Genre|Composer|Performer)='
)
IFS="$oldIFS"
}

View File

@ -1,27 +0,0 @@
#!/bin/bash
getInfosMP3_version='ID3-3'
tagreaders+=( "$getInfosMP3_version" )
getInfos::MP3() {
tagreader="$getInfosMP3_version"
infos=$(
soxi "$sourcepath/$filename" 2>/dev/null \
| sed 's/ *: /=/'
)
album=$(gettag album)
artist=$(gettag artist)
genre=$(gettag genre)
title=$(gettag title)
tracknum=$(gettag tracknumber)
year=$(gettag year)
expr='^[0-9]*$'
if [[ $genre =~ $expr ]]
then
genre="${id3genres[$genre]}"
fi
infos="${infos/: /=}"
channels=$(gettag channels)
rate=$(gettag 'sample rate')
bitrate=$(gettag 'bit rate')
bitrate=${bitrate%%.*}
bitrate=${bitrate%k}
}

View File

@ -1,5 +1,5 @@
#!/bin/bash
getInfosOgg_version='Ogg-1'
getInfosOgg_version='Ogg-2'
tagreaders+=( "$getInfosOgg_version" )
getInfos::Ogg() {
tagreader="$getInfosOgg_version"
@ -22,9 +22,9 @@ getInfos::Ogg() {
tracknum="$tracknum/$tracktotal"
fi
year=$(gettag date)
infos="${infos/: /=}"
infos="${infos//: /=}"
rate=$(gettag rate|head -n1)
channels=$(gettag channels|head -n1)
bitrate=$(gettag 'nominal bitrate')
bitrate=$(gettag 'average bitrate')
bitrate=${bitrate%%,*}
}

View File

@ -1,5 +1,5 @@
#!/bin/bash
getInfosOpus_version='Opus-1'
getInfosOpus_version='Opus-2'
tagreaders+=( "$getInfosOpus_version" )
getInfos::Opus() {
tagreader="$getInfosOpus_version"
@ -22,7 +22,7 @@ getInfos::Opus() {
tracknum="$tracknum/$tracktotal"
fi
year=$(gettag date)
infos="${infos/: /=}"
infos="${infos//: /=}"
rate=$(gettag 'original sample rate'|head -n1)
channels=$(gettag channels|head -n1)
bitrate=$(gettag 'average bitrate')

View File

@ -1,5 +1,5 @@
#!/bin/bash
getInfosffmpeg_version='ffmpeg-1'
getInfosffmpeg_version='ffmpeg-2'
tagreaders+=( "$getInfosffmpeg_version" )
getInfos::ffmpeg() {
tagreader="$getInfosffmpeg_version"
@ -31,8 +31,8 @@ getInfos::ffmpeg() {
genre=$(gettag genre)
performer=$(gettag TOPE)
title=$(gettag title)
tracknum=$(gettag tracknumber)
year=$(gettag year)
tracknum=$(gettag track)
year=$(gettag date)
expr='^[0-9]*$'
if [ -n "$genre" ] && [[ $genre =~ $expr ]]
then

View File

@ -1,16 +0,0 @@
#!/bin/bash
getRateChannelMPC() {
while read key value garbage
do
case $key in
'samplerate:')
rate=$value
;;
'channels:')
channels=$value
;;
esac
done < <(
mpcdec "$sourcepath/$filename" -i 2>&1
)
}

View File

@ -1,5 +0,0 @@
#!/bin/bash
getRateChannelSoxi() {
rate=$(soxi -r "$sourcepath/$filename" 2>/dev/null)
channels=$(soxi -c "$sourcepath/$filename" 2>/dev/null)
}

View File

@ -1,39 +1,31 @@
#!/bin/bash
getTags_version='unknown-3'
tagreaders+=( "$getTags_version" )
getTags_version='unknown-4'
getTags() {
unset type
case "$mimetype" in
audio/mpeg)
type=MP3
type=ffmpeg
(( disableffprobe )) && unset type
;;
'application/ogg opus')
type=Opus
(( disableopusinfo )) && unset type
;;
application/ogg*)
type=Ogg
(( disableogginfo )) && unset type
;;
audio/x-flac)
type=FLAC
(( disableflac )) && unset type
;;
video/*)
type=ffmpeg
(( disableffprobe )) && unset type
;;
*)
extendedtype=$(file -b "$sourcepath/$filename")
case "$extendedtype" in
*' ID3 '*)
type=MP3
;;
*'Musepack '*)
getRateChannelMPC
tryAPE
;;
*)
getRateChannelSoxi
tryAPE
;;
esac
type=ffmpeg
(( disableffprobe )) && unset type
;;
esac
if [ -n "$type" ]

158
lib/tags/updateTags Normal file
View File

@ -0,0 +1,158 @@
#!/bin/bash
updateTags() {
for reader in "${tagreaders[@]}"
do
tagreaderclause+="${tagreaderclause:+ AND }NOT tags.tagreader = \"$reader\""
done
echo '
SELECT DISTINCT
source_files.id,
source_files.last_change,
mime_type_actions.mime_text,
source_files.filename,
tags.album,
tags.albumartist,
tags.artist,
tags.composer,
tags.disc,
tags.genre,
tags.performer,
tags.title,
tags.track,
tags.year,
tags.rate,
tags.channels,
tags.bitrate
FROM source_files
INNER JOIN destination_files
ON destination_files.source_file_id=source_files.id
INNER JOIN destinations
ON destination_files.destination_id=destinations.id
INNER JOIN mime_type_actions
ON destinations.id=mime_type_actions.destination_id
INNER JOIN tags
ON source_files.id=tags.source_file
WHERE mime_type_actions.id = source_files.mime_type
AND (
CAST(tags.last_change AS TEXT)
<>
CAST(source_files.last_change AS TEXT)
OR ('"$tagreaderclause"')
)
AND mime_type_actions.action = 1;
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 line
while ! [[ $line = AtOM:NoMoreFiles ]]
do
tagfiles+=("$line")
(( filecount++ ))
read -u4 line
done
echo 'BEGIN TRANSACTION;' >&3
for line in "${tagfiles[@]}"
do
sourcefileid=${line%%::AtOM:SQL:Sep::*}
rest=${line#*::AtOM:SQL:Sep::}
lastchange=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
mimetype=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
filename=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldalbum=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldalbumartist=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldartist=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldcomposer=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
olddisc=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldgenre=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldperformer=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldtitle=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldtrack=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldyear=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldrate=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldchannels=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldbitrate=${rest%%::AtOM:SQL:Sep::*}
echo -en "\rTags: $((++count*100/filecount))%"
if (( count % 1000 == 0 ))
then
echo 'COMMIT;BEGIN TRANSACTION;' >&3
(( debug )) \
&& echo -n " $count files read, committing..."
fi
if getTags
then
[[ $oldalbum != "$album" ]]&& ual=1
[[ $oldalbumartist != "$albumartist" ]]&&uaa=1
[[ $oldartist != "$artist" ]]&& uar=1
[[ $oldcomposer != "$composer" ]]&& uco=1
[[ $olddisc != "$disc" ]]&& udi=1
[[ $oldgenre != "$genre" ]]&& uge=1
[[ $oldperformer != "$performer" ]]&& upe=1
[[ $oldtitle != "$title" ]]&& uti=1
[[ $oldtrack != "$tracknum" ]]&& utr=1
[[ $oldyear != "$year" ]]&& uye=1
[[ $oldrate != "$rate" ]]&& ura=1
[[ $oldchannels != "$channels" ]]&& uch=1
[[ $oldbitrate != "$bitrate" ]]&& ubi=1
Update tags \
${ual:+album "::AtOM:FT::${album:-NULL}"}\
${uaa:+albumartist "::AtOM:FT::${albumartist:-NULL}"}\
${uar:+artist "::AtOM:FT::${artist:-NULL}"}\
${uco:+composer "::AtOM:FT::${composer:-NULL}"}\
${udi:+disc "${disc:-NULL}"} \
${uge:+genre "${genre:-NULL}"} \
${upe:+performer "::AtOM:FT::${performer:-NULL}"}\
${uti:+title "::AtOM:FT::${title:-NULL}"}\
${utr:+track "::AtOM:FT::${tracknum:-NULL}"}\
${uye:+year "${year:-NULL}"} \
last_change "$lastchange" \
${ura:+rate "${rate:-NULL}"} \
${uch:+channels "${channels:-NULL}"} \
${ubi:+bitrate "${bitrate:-NULL}"} \
tagreader "$tagreader" \
>/dev/null <<<"source_file = $sourcefileid"
unset genre \
albumartist \
year \
album \
disc \
artist \
tracknum \
title \
composer \
performer \
rate \
bitrate \
channels \
ual \
uaa \
uar \
uco \
udi \
uge \
upe \
uti \
utr \
uye \
ura \
uch \
ubi
fi
done
echo 'COMMIT;' >&3
echo -e "\rRead tags from ${count:-0} files.\033[K"
unset count tagfiles
}

View File

@ -12,16 +12,16 @@ gettaskinfos() {
WHERE id='$1';
' >&3
read -u4 line
taskid=${line%%|*}
rest="${line#*|}|"
sourcefileid=${rest%%|*}
rest=${rest#*|}
required=${rest%%|*}
rest=${rest#*|}
cleanup=${rest%%|*}
rest=${rest#*|}
destfileid=${rest%%|*}
rest=${rest#*|}
destfilename=${rest%%|*}
rest=${rest#*|}
taskid=${line%%::AtOM:SQL:Sep::*}
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
sourcefileid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
required=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
cleanup=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destfileid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destfilename=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
}

View File

@ -10,6 +10,7 @@ cleaner() {
EOWhere
)
(( failed+=faildepends ))
(( ran+=faildepends ))
Update tasks status 2 <<<"id = $taskid"
Update tasks status 2 <<<"requires = $taskid"
echo "SELECT COUNT(*)

View File

@ -69,78 +69,78 @@ master() {
else
(( ++active ))
read -u4 line
taskid=${line%%|*}
rest="${line#*|}|"
sourcefileid=${rest%%|*}
rest=${rest#*|}
required=${rest%%|*}
rest=${rest#*|}
cmd_arg=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cmd_arg+=("${rest%%|*}")
rest=${rest#*|}
cleanup=${rest%%|*}
rest=${rest#*|}
destfileid=${rest%%|*}
rest=${rest#*|}
destfilename=${rest%%|*}
rest=${rest#*|}
taskid=${line%%::AtOM:SQL:Sep::*}
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
sourcefileid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
required=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cmd_arg+=("${rest%%::AtOM:SQL:Sep::*}")
rest=${rest#*::AtOM:SQL:Sep::}
cleanup=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destfileid=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
destfilename=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
for key in ${!cmd_arg[@]}
do
[ -z "${cmd_arg[key]}" ] && unset cmd_arg[key]

View File

@ -4,12 +4,3 @@ worker() {
(( debug >= 2 )) && echo "${cmd_arg[@]}" >&2
"${cmd_arg[@]}" >/dev/null
}
createworker() {
worker $1 &
workers[$1]=$!
}
destroyworker() {
dyingworker=${workers[$1]}
unset workers[$1]
wait $dyingworker
}

View File

@ -1,5 +1,5 @@
BEGIN TRANSACTION;
CREATE TABLE source_files (
CREATE TABLE IF NOT EXISTS source_files (
id INTEGER PRIMARY KEY,
filename TEXT UNIQUE NOT NULL,
size INTEGER NOT NULL,
@ -10,11 +10,11 @@ CREATE TABLE source_files (
FOREIGN KEY (mime_type) REFERENCES mime_types(id)
ON DELETE SET NULL
);
CREATE TABLE destinations (
CREATE TABLE IF NOT EXISTS destinations (
id INTEGER PRIMARY KEY,
name TEXT UNIQUE NOT NULL
);
CREATE TABLE destination_files (
CREATE TABLE IF NOT EXISTS destination_files (
id INTEGER PRIMARY KEY,
filename TEXT,
old_filename TEXT,
@ -27,11 +27,11 @@ CREATE TABLE destination_files (
FOREIGN KEY (destination_id) REFERENCES destinations(id)
ON DELETE CASCADE
);
CREATE TABLE mime_types (
CREATE TABLE IF NOT EXISTS mime_types (
id INTEGER PRIMARY KEY,
mime_text TEXT UNIQUE NOT NULL
);
CREATE TABLE mime_actions (
CREATE TABLE IF NOT EXISTS mime_actions (
id INTEGER PRIMARY KEY,
mime_type INTEGER,
destination_id INTEGER,
@ -40,7 +40,7 @@ CREATE TABLE mime_actions (
FOREIGN KEY (destination_id) REFERENCES destinations(id)
ON DELETE CASCADE
);
CREATE TABLE tags (
CREATE TABLE IF NOT EXISTS tags (
source_file INTEGER PRIMARY KEY,
genre TEXT,
albumartist TEXT,
@ -61,13 +61,14 @@ CREATE TABLE tags (
ON DELETE CASCADE
);
CREATE VIEW mime_type_actions AS
CREATE VIEW IF NOT EXISTS mime_type_actions AS
SELECT
mime_types.id,mime_types.mime_text,
mime_actions.destination_id,mime_actions.action
FROM mime_types INNER JOIN mime_actions
ON mime_actions.mime_type = mime_types.id;
CREATE TRIGGER update_mime_actions INSTEAD OF UPDATE OF action ON mime_type_actions
CREATE TRIGGER IF NOT EXISTS update_mime_actions
INSTEAD OF UPDATE OF action ON mime_type_actions
BEGIN
UPDATE mime_actions
SET action=new.action
@ -75,7 +76,8 @@ BEGIN
AND destination_id=old.destination_id;
END;
CREATE TRIGGER create_dest_files_and_mime_actions AFTER INSERT ON destinations
CREATE TRIGGER IF NOT EXISTS create_dest_files_and_mime_actions
AFTER INSERT ON destinations
BEGIN
INSERT INTO mime_actions
(mime_type,destination_id)
@ -87,7 +89,7 @@ BEGIN
FROM source_files;
END;
CREATE TRIGGER create_mime_actions AFTER INSERT ON mime_types
CREATE TRIGGER IF NOT EXISTS create_mime_actions AFTER INSERT ON mime_types
BEGIN
INSERT INTO mime_actions (mime_type,destination_id)
SELECT mime_types.id,destinations.id
@ -95,18 +97,39 @@ BEGIN
WHERE mime_types.id=new.id;
END;
CREATE INDEX sourcefiles_by_name ON source_files (filename,id);
CREATE INDEX IF NOT EXISTS sourcefiles_by_name ON source_files (filename,id);
CREATE TRIGGER create_destinations AFTER INSERT ON source_files
CREATE TRIGGER IF NOT EXISTS create_destinations AFTER INSERT ON source_files
BEGIN
INSERT INTO destination_files (source_file_id,destination_id)
SELECT source_files.id,destinations.id FROM source_files
INNER JOIN destinations
WHERE source_files.id=new.id;
END;
CREATE TRIGGER create_tags AFTER INSERT ON source_files
CREATE TRIGGER IF NOT EXISTS create_tags AFTER INSERT ON source_files
BEGIN
INSERT INTO tags (source_file,last_change) VALUES (new.id,0);
END;
DROP TRIGGER IF EXISTS force_destination_update_on_tag_update;
CREATE TRIGGER force_destination_update_on_tag_update
AFTER UPDATE OF
genre,
albumartist,
year,
album,
disc,
artist,
track,
title,
composer,
performer,
rate,
channels,
bitrate
ON tags
BEGIN
UPDATE destination_files SET last_change=0
WHERE source_file_id=old.source_file;
END;
COMMIT;

View File

@ -1,3 +1,37 @@
createindex
===========
Creates a nice index of your collection, similar to what oidua
(http://oidua.suxbad.com/) does, but much faster, as it is using AtOM's DB
instead of rescanning your whole collection.
Options define what will be shown and may optionnally be followed by the column
width (default: 50).
Options:
-f: Path
-b: Average bitrate
-C: Channels
-s: Sample rate
-m: Mofification time
-M: Format
-A: Album artist
-l: Album
-a: Artist
-c: Composer
-d: Disc
-g: Genre
-p: Performer
-t: Title
-y: Year
-T <format>: date-time format (see 'man date' for possible values)
-o -|<file>: output file (path relative to Source) - mandatory - must
appear last.
-u: update database first
-D: debug
checkextensions
===============
Reports files whose extension does not match the (detected) mime-type.

View File

@ -112,8 +112,8 @@ getdstfiles() {
done
for line in "${lines[@]}"
do
fileid=${line%|*}
filename=${line#*|}
fileid=${line%::AtOM:SQL:Sep::*}
filename=${line#*::AtOM:SQL:Sep::}
echo $'\t'"$filename"
(( rename )) && echo -n $'\t'
(( rename )) && renameFile
@ -149,12 +149,12 @@ do
done
for line in "${lines[@]}"
do
fileid=${line%%|*}
rest="${line#*|}|"
filename=${rest%%|*}
rest=${rest#*|}
mimetype=${rest%%|*}
rest=${rest#*|}
fileid=${line%%::AtOM:SQL:Sep::*}
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
filename=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
mimetype=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
dest=$sourcepath
case "$mimetype" in
'audio/mpeg')

View File

@ -61,7 +61,7 @@ checkwanted() {
for destination in "${!destinationpath[@]}"
do
echo -ne "\rScanning destination $destination... \033[K"
while read filename
while read -r filename
do
if ! Select destination_files id \
>/dev/null \

435
toys/createindex Executable file
View File

@ -0,0 +1,435 @@
#!/bin/bash
#!/bin/bash
# config structures
declare -A \
destinationchannels \
destinationfat32compat \
destinationcopymime \
destinationformat \
destinationfrequency \
destinationid \
destinationloss \
destinationmaxbps \
destinationnormalize \
destinationpath \
destinationquality \
destinationrename \
destinationnoresample \
destinationrenamepath \
destinationskipmime \
|| {
echo "Check your Bash version. You need >= 4.0" >&2
exit $EBASHVERS
}
declare -r \
DOCDIR=./doc \
LIBDIR=./lib \
SHAREDIR=./share
declare -r \
exampleconf=$DOCDIR/example.cfg \
schema=$SHAREDIR/schema.sql \
\
oldIFS="$IFS"
cffile="$HOME/.atom/atom.cfg"
shopt -s extglob
for function in "$LIBDIR"/*/*
do
source "$function"
done
while [ -n "$1" ]
do
opt="$1"
shift
case $opt in
'-A') show+=(albumartists) ;;
'-l') show+=(albums) ;;
'-a') show+=(artists) ;;
'-b') show+=(bitrates) ;;
'-c') show+=(composers) ;;
'-C') show+=(channelss) ;;
'-d') show+=(discs) ;;
'-f') show+=(path) ;;
'-g') show+=(genres) ;;
'-m') show+=(oldtimestamp) ;;
'-M') show+=(types) ;;
'-p') show+=(performers) ;;
'-s') show+=(rates) ;;
'-t') show+=(titles) ;;
'-y') show+=(years) ;;
'-T') timeformat="$OPTARG" ;;
'-o') output="$1"
continue ;;
'-u') update=1 ;;
'-D') (( debug++ )) ;;
[0-9]*) length[count-1]=$opt
continue ;;
esac
(( count++ ))
done
[ -z "$output" ] && {
cat <<-EOHelp
No output specified!
-f Path
-b Average bitrate
-C Channels
-s Sample rate
-m Mofification time
-M Format
-A Album artist
-l Album
-a Artist
-c Composer
-d Disc
-g Genre
-p Performer
-t Title
-y Year
-T <format>: date-time format (see 'man date' for possible values)
-o <file> : output file (path relative to Source)
-u : update database first
-D : debug
EOHelp
exit 1
}
getConfig
openDatabase
columns="${show[@]//*/-}"
if ! [[ "$output" == - ]]
then
exec > "$output"
fi
printPath() {
for key in ${!pathparts[@]}
do
if [[ ${pathparts[key]} == ${oldpathparts[key]} ]]
then
echo -n " ${pathparts[key]//?/ }"
else
echo -n "${pathparts[key]}/"
fi
done
}
printline() {
local print
for index in ${!show[@]}
do
info="${show[index]}"
locallength="${length[index]:=50}"
path="$olddir"
case $info in
'bitrates')
info=$((bitrates/count))
(( info )) || unset info
;;
'oldtimestamp')
info=$(printDate ${!info})
;;
'path')
while [[ $path =~ / ]]
do
pathparts+=("${path%%/*}")
path=${path#*/}
done
pathparts+=("$path")
info=$(printPath)
unset oldpathparts
for key in ${!pathparts[@]}
do
oldpathparts[key]=${pathparts[key]}
done
unset pathparts
;;
*)
info="${!info}"
;;
esac
printtmp="${info:0:$locallength}"
if [ -z "$printtmp" ]
then
until (( ${#printtmp} == locallength/2))
do
printtmp+=' '
done
printtmp+='-'
fi
until (( ${#printtmp} == locallength ))
do
printtmp+=' '
done
print+=(${print+|} "$printtmp")
done
echo "${print[@]}"
}
if (( update ))
then
getFiles
updateMimes
updateTags
fi
printDate() {
date -d"@$1" +"${timeformat:-%x %X}"
}
for index in ${!show[@]}
do
info="${show[index]}"
locallength="${length[index]:=50}"
case $info in
albumartists) info="Album artist" ;;
albums) info="Album" ;;
artists) info="Artist" ;;
bitrates) info="Bitrate" ;;
composers) info="Composer" ;;
channelss) info="Channels" ;;
discs) info="Disc" ;;
path) info="Directory name" ;;
genres) info="Genre" ;;
oldtimestamp) info="Last modified" ;;
types) info="Format" ;;
performers) info="Performer" ;;
rates) info="Sample rate" ;;
titles) info="Title" ;;
years) info="Date" ;;
esac
printtmp="${info:0:$locallength}"
until (( ${#printtmp} == locallength ))
do
printtmp+=' '
done
print+=(${print+|} "$printtmp")
done
echo "${print[@]}"
echo "${print[@]//[^|]/=}"
unset print
echo '
SELECT
source_files.filename,
tags.bitrate,
tags.channels,
tags.rate,
source_files.last_change,
mime_types.mime_text,
tags.albumartist,
tags.album,
tags.artist,
tags.composer,
tags.disc,
tags.genre,
tags.performer,
tags.title,
tags.year
FROM source_files
INNER JOIN mime_types
ON source_files.mime_type=mime_types.id
INNER JOIN tags
ON source_files.id=tags.source_file
WHERE
NOT mime_types.mime_text LIKE "text/%"
AND NOT mime_types.mime_text LIKE "image/%"
ORDER BY source_files.filename
COLLATE NOCASE;
SELECT "AtOM:NoMoreFiles";' >&3
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
files+=("$line")
read -u4 line
done
for line in "${files[@]}"
do
filename="${line%%::AtOM:SQL:Sep::*}"
dir="${filename%/*}"
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
bitrate="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
channels="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
rate="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
timestamp="${rest%%::AtOM:SQL:Sep::*}"
timestamp="${timestamp%%.*}"
rest="${rest#*::AtOM:SQL:Sep::}"
mimetype="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
albumartist="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
album="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
artist="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
composer="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
disc="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
genre="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
performer="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
title="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
year="${rest%%::AtOM:SQL:Sep::*}"
rest="${rest#*::AtOM:SQL:Sep::}"
case $mimetype in
application/ogg\ opus) type=Opus ;;
application/ogg\ vorbis) type=Vorbis ;;
audio/mp4) type=MPEG4\ Audio;;
audio/mpeg) type=MPEG\ Audio;;
audio/x-flac) type=FLAC ;;
video/mpeg) type=MPEG\ Video;;
video/webm) type=WebM ;;
audio/*) type=Other\ Audio;;
video/*) type=Other\ Video;;
*) type=Other ;;
esac
if [[ $dir == $olddir ]]
then
(( $bitrate )) && (( count++ , bitrates+=bitrate ))
((
oldtimestamp = (
timestamp > oldtimestamp
? timestamp
: oldtimestamp
)
))
expr1='(^|,)'
expr2='(,|$)'
if ! [[ $channelss =~ $expr1"$channels"$expr2 ]]
then
if [ -n "$channelss" ] \
&& (( channels < ${channelss%%,*} ))
then
channelss="$channels,$channelss"
else
channelss+="${channelss+,}$channels"
fi
fi
if ! [[ $rates =~ $expr1"$rate"$expr2 ]]
then
if [ -n "$rates" ] \
&& (( rate < ${rates%%,*} ))
then
rates="$rate,$rates"
else
rates+="${rates+,}$rate"
fi
fi
if ! [[ $types =~ $expr1"$type"$expr2 ]]
then
[ -z "$types" ] \
&& unset types
[ -n "$type" ] \
&& types+="${types+,}$type"
fi
if ! [[ $albumartists =~ $expr1"$albumartist"$expr2 ]]
then
[ -z "$albumartists" ] \
&& unset albumartists
[ -n "$albumartist" ] \
&& albumartists+="${albumartists+,}$albumartist"
fi
if ! [[ $albums =~ $expr1"$album"$expr2 ]]
then
[ -z "$albums" ] \
&& unset albums
[ -n "$album" ] \
&& albums+="${albums+,}$album"
fi
if ! [[ $artists =~ $expr1"$artist"$expr2 ]]
then
[ -z "$artists" ] \
&& unset artists
[ -n "$artist" ] \
&& artists+="${artists+,}$artist"
fi
if ! [[ $composers =~ $expr1"$composer"$expr2 ]]
then
[ -z "$composers" ] \
&& unset composers
[ -n "$composer" ] \
&& composers+="${composers+,}$composer"
fi
if ! [[ $discs =~ $expr1"$disc"$expr2 ]]
then
[ -z "$discs" ] \
&& unset discs
[ -n "$disc" ] \
&& discs+="${discs+,}$disc"
fi
if ! [[ $genres =~ $expr1"$genre"$expr2 ]]
then
[ -z "$genres" ] \
&& unset genres
[ -n "$genre" ] \
&& genres+="${genres+,}$genre"
fi
if ! [[ $performers =~ $expr1"$performer"$expr2 ]]
then
[ -z "$performers" ] \
&& unset performers
[ -n "$performer" ] \
&& performers+="${performers+,}$performer"
fi
if ! [[ $titles =~ $expr1"$title"$expr2 ]]
then
[ -z "$titles" ] \
&& unset titles
[ -n "$title" ] \
&& titles+="${titles+,}$title"
fi
if ! [[ $years =~ $expr1"$year"$expr2 ]]
then
[ -z "$years" ] \
&& unset years
[ -n "$year" ] \
&& years+="${years+,}$year"
fi
else
if [ -n "$olddir" ]
then
printline
fi
unset bitrates
channelss="$channels"
rates="$rate"
types="$type"
albumartists="$albumartist"
albums="$album"
artists="$artist"
composers="$composer"
discs="$disc"
genres="$genre"
performers="$performer"
titles="$title"
years="$year"
(( bitrate )) && (( count=1 , bitrates=bitrate ))
oldmimetype=$mimetype
oldrate=$rate
oldtimestamp=$timestamp
fi
olddir="$dir"
done
printline

130
toys/lowquality Executable file
View File

@ -0,0 +1,130 @@
#!/bin/bash
# config structures
declare -A \
destinationchannels \
destinationfat32compat \
destinationcopymime \
destinationformat \
destinationfrequency \
destinationid \
destinationloss \
destinationmaxbps \
destinationnormalize \
destinationpath \
destinationquality \
destinationrename \
destinationnoresample \
destinationrenamepath \
destinationskipmime \
|| {
echo "Check your Bash version. You need >= 4.0" >&2
exit $EBASHVERS
}
declare -r \
DOCDIR=./doc \
LIBDIR=./lib \
SHAREDIR=./share
declare -r \
exampleconf=$DOCDIR/example.cfg \
schema=$SHAREDIR/schema.sql \
\
oldIFS="$IFS"
cffile="$HOME/.atom/atom.cfg"
LC_ALL=C
shopt -s extglob
for function in "$LIBDIR"/*/*
do
source "$function"
done
while getopts 'fm:o:p:*:uD' opt
do
case $opt in
f) mimetypes+=("audio/x-flac")
bitrates+=("")
;;
m) mimetypes+=("audio/mpeg")
bitrates+=("$OPTARG")
;;
o) mimetypes+=("application/ogg vorbis")
bitrates+=("$OPTARG")
;;
p) mimetypes+=("application/ogg opus")
bitrates+=("$OPTARG")
;;
\*) mimetypes+=("*")
bitrates+=("$OPTARG")
;;
u) update=1 ;;
D) (( debug++ )) ;;
esac
done
getConfig
openDatabase
if (( update ))
then
getFiles
updateMimes
updateTags
fi
echo '
SELECT DISTINCT
mime_type_actions.mime_text,
tags.bitrate,
source_files.filename
FROM source_files
INNER JOIN tags
ON source_files.id=tags.source_file
INNER JOIN mime_type_actions
ON mime_type_actions.id=source_files.mime_type
WHERE mime_type_actions.action=1
AND (
' >&3
for indice in ${!mimetypes[@]}
do
(( notfirst )) && echo OR >&3
case ${mimetypes[indice]} in
'audio/x-flac')
echo 'mime_type_actions.mime_text="audio/x-flac"'>&3
;;
'*')
echo '( (
NOT mime_type_actions.mime_text="audio/x-flac"
AND NOT mime_type_actions.mime_text="audio/mpeg"
AND NOT
mime_type_actions.mime_text="application/ogg vorbis"
AND NOT
mime_type_actions.mime_text="application/ogg opus"
) AND tags.bitrate < '${bitrates[indice]}' )' >&3
;;
*)
echo '(
mime_type_actions.mime_text="'"${mimetypes[indice]}"'"
AND tags.bitrate < '${bitrates[indice]}' )' >&3
;;
esac
notfirst=1
done
echo ') ORDER BY bitrate;' >&3
echo 'SELECT "AtOM:NoMoreFiles";' >&3
read -u4 line
until [[ $line == AtOM:NoMoreFiles ]]
do
echo "${line//::AtOM:SQL:Sep::/$'\t'}"
read -u4 line
done
closeDatabase

View File

@ -93,29 +93,17 @@ if (( update ))
then
getFiles
updateMimes
updateTags
fi
for check in ${!checks[@]}
do
case $check in
albumartist)
cat >&2 <<-EONotice
Album artist is not supported for ID3. Files in this format will be ignored by
this check (other checks still apply).
EONotice
mimemp3=$(
Select mime_types id <<<"mime_text = audio/mpeg"
)
whereclause+="${whereclause+ OR }("
whereclause+='tags.albumartist IS NULL '
whereclause+="AND NOT tags.tagreader LIKE \"ID3-%\""
whereclause+=')'
;;
tracktotal)
whereclause+="${whereclause+ OR }NOT tags.track LIKE \"%/%\""
whereclause+="${whereclause+OR }NOT tags.track LIKE \"%/%\""
;;
*)
whereclause+="${whereclause+ OR }tags.$check IS NULL"
whereclause+="${whereclause+OR }tags.$check IS NULL"
;;
esac
whereclause+='
@ -137,8 +125,15 @@ cat >&3 <<-EOSelect
FROM tags
INNER JOIN source_files
ON tags.source_file=source_files.id
WHERE $whereclause
AND NOT tags.tagreader LIKE "unknown-%";
INNER JOIN mime_types
ON source_files.mime_type=mime_types.id
WHERE (
$whereclause
)
AND NOT tags.tagreader LIKE "unknown-%"
AND NOT mime_types.mime_text LIKE "text/%"
AND NOT mime_types.mime_text LIKE "image/%"
;
SELECT "AtOM:NoMoreFiles";
EOSelect
@ -153,33 +148,33 @@ done
for line in "${lines[@]}"
do
missing=()
filename=${line%%|*}
rest="${line#*|}|"
(( ${checks[genre]} )) && [ -z "${rest%%|*}" ] && missing+=( "Genre" )
rest=${rest#*|}
(( ${checks[albumartist]} )) && [ -z "${rest%%|*}" ] && missing+=( "AlbumArtist" )
rest=${rest#*|}
(( ${checks[year]} )) && [ -z "${rest%%|*}" ] && missing+=( "Year" )
rest=${rest#*|}
(( ${checks[album]} )) && [ -z "${rest%%|*}" ] && missing+=( "Album" )
rest=${rest#*|}
(( ${checks[disc]} )) && [ -z "${rest%%|*}" ] && missing+=( "Disc" )
rest=${rest#*|}
(( ${checks[artist]} )) && [ -z "${rest%%|*}" ] && missing+=( "Artist" )
rest=${rest#*|}
track=${rest%%|*}
filename=${line%%::AtOM:SQL:Sep::*}
rest="${line#*::AtOM:SQL:Sep::}::AtOM:SQL:Sep::"
(( ${checks[genre]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Genre" )
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[albumartist]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "AlbumArtist" )
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[year]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Year" )
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[album]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Album" )
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[disc]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Disc" )
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[artist]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Artist" )
rest=${rest#*::AtOM:SQL:Sep::}
track=${rest%%::AtOM:SQL:Sep::*}
(( ${checks[track]} )) && [ -z "$track" ] && missing+=( "Track" )
if (( ${checks[tracktotal]} )) && ! [[ $track =~ / ]]
then
missing+=( TrackTotal )
fi
rest=${rest#*|}
(( ${checks[title]} )) && [ -z "${rest%%|*}" ] && missing+=( "Title" )
rest=${rest#*|}
(( ${checks[composer]} )) && [ -z "${rest%%|*}" ] && missing+=( "Composer" )
rest=${rest#*|}
(( ${checks[performer]} )) && [ -z "${rest%%|*}" ] && missing+=( "Performer" )
rest=${rest#*|}
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[title]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Title" )
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[composer]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Composer" )
rest=${rest#*::AtOM:SQL:Sep::}
(( ${checks[performer]} )) && [ -z "${rest%%::AtOM:SQL:Sep::*}" ] && missing+=( "Performer" )
rest=${rest#*::AtOM:SQL:Sep::}
echo "$filename: ${missing[@]}"
done