Compare commits

..

12 Commits

Author SHA1 Message Date
Vincent Riquer
ec99e0ffce releasecountry: renamepattern 2025-02-10 01:47:54 +01:00
Vincent Riquer
537c205577 quickfix: Opus: remove " kbit/s*" from bitrate 2025-02-10 01:35:02 +01:00
Vincent Riquer
dfa4ad092a quickfix: Opus: remove " Hz" from rate 2025-02-10 01:14:23 +01:00
Vincent Riquer
142215af0a quickfix: MPEG reported rates are truncated 2025-02-10 01:07:46 +01:00
Vincent Riquer
555b8f24e4 quickfix: opus tag reader 2025-02-10 00:57:13 +01:00
Vincent Riquer
387c88b9da releasecountry: attempt to write to destination
Limited support for MP3, ID3v2 is quite limited
2025-02-10 00:53:54 +01:00
Vincent Riquer
9deb614687 releasecountry: MP3: fallback on "MusicBrainz Album Release Country" 2025-02-10 00:46:06 +01:00
Vincent Riquer
b49f099565 quickfix: tag reader for ogg vorbis 2025-02-10 00:16:32 +01:00
Vincent Riquer
3ecf4b627d releasecountry: toys/createindex 2025-02-10 00:13:10 +01:00
Vincent Riquer
50ca3a3748 releasecountry: read and store releasecountry tag 2025-02-09 21:08:38 +01:00
Vincent Riquer
03bfa34c43 remove unused tagreading function 2025-02-09 21:08:10 +01:00
Vincent Riquer
78c8c2b996 releasecountry support: update DB schema 2025-02-09 21:07:07 +01:00
39 changed files with 626 additions and 1013 deletions

View File

@ -1,34 +0,0 @@
# 1.0.3
## `BREAKING CHANGES`
* Implementing replaygain copy meant bumping versions of every tag parser. All file tags will be read again. Running in batches (`-B <batchsize>`) is recommended.
### Bugs
* Fix a number of issues with `releasecountry` tag
### Enhancements
* Spawn tasks faster when slots are available.
* Copy replaygain tags.
* Add `copy_extension` to setup
# 1.0.2
### Bugs
* Tag reading hangs on vorbis files with embedded images.
* Recreate destination files on releasecountry tag change (bump database schema to 5).
# 1.0.1
## `BREAKING CHANGES`
* Implementing releasecountry meant bumping versions of every tag parser. All file tags will be read again. Running in batches (`-B <batchsize>`) is recommended.
### Enhancements
* Copy releasecountry tag ("MusicBrainz Album Release Country" for MP3).
### Bugs
* Opus tags were not actually parsed due to an issue with the tag reader selector.
### Enhancements
* Fetch releasecountry tag from files
* Add `%{releasecountry}` placeholder in `rename`
* Add `-r` (show release country) to toys/createindex
# 1.0.0
Initial public release

View File

@ -20,17 +20,17 @@ in the same format, it will want a constant sample-rate and bitrate. You can
have AtOM do that!
Here's what I have for my tests:
| Directory | Format | Sample rate | Bitrate | Channels | FAT32 compat. | ASCII | Size |
| --------- | ------ | ----------- | ------- | -------- | ------------- | ----- | ---- |
| 0-Full | Mixed | Mixed | Mixed | Mixed | No | No | 508G |
| 1-High | Opus | Same | 128 | Same | Yes | No | 101G |
| 2-Medium | Opus | Same | 64 | Same | Yes | No | 59G |
| 3-Small | Opus | Same | 32 | Same | Yes | No | 30G |
| 4-MP3 | MP3 | 44100 | 128 | 2 | Yes | Yes | 114G |
| Directory | Format | Frequency | Bitrate | Channels | FAT32 compat. | ASCII | Size |
| --------- | ------ | --------- | ------- | -------- | ------------- | ----- | ---- |
| 0-Full | Mixed | Mixed | Mixed | Mixed | No | No | 508G |
| 1-High | Opus | Same | 128 | Same | Yes | No | 101G |
| 2-Medium | Opus | Same | 64 | Same | Yes | No | 59G |
| 3-Small | Opus | Same | 32 | Same | Yes | No | 30G |
| 4-MP3 | MP3 | 44100 | 128 | 2 | Yes | Yes | 114G |
* URL: https://framagit.org/atom/AtOM/
* URL: https://framagit.org/ScriptFanix/AtOM/
* Author: Vincent Riquer <vincent+prog.atom@riquer.fr>
* Copyright/left: 2012-2013,2015,2025 Vincent Riquer - GPLv3

5
TODO Normal file
View File

@ -0,0 +1,5 @@
Tag Guessing
------------
From a user-defined pattern, guess tags for unsupported formats/untagged files
from the file path and file name.

256
atom
View File

@ -72,7 +72,7 @@ help() {
-c <file> Load configuration file <file>
-C Dump configuration and exit
-l <load> Override max-load
-f <workers> Use exactly <workers> child processes
-f <workers> Use exactly <workers> child processes
-T <seconds> override load-interval
-F <destination> Force re-generation of all files in
<destination>
@ -183,7 +183,163 @@ set +H
(( cfgdump )) && exit
# check sanity
sanityCheck
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
WebM metadata disabled" >&2
disableogginfo=1
(( sanitywarn++ ))
fi
if ! which soxi >/dev/null
then
echo "[WARNING] Tool soxi (from sox) is not" \
"installed or not in PATH
Vorbis metadata disabled" >&2
disablesoxi=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 mkvextract >/dev/null
then
echo "[WARNING] Tool mkvextract (from MKVToolNix) is not" \
"installed or not in PATH
WebM metadata disabled
WebM support disabled" >&2
disablemkvextract=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 (( textunidecodeneeded )) && ! perl -MText::Unidecode -e 'exit;' 2>/dev/null
then
echo "[WARNING] Perl module Text::Unidecode is not available
Renaming to ASCII-only disabled" >&2
unset destinationascii
destinationascii=0
textunidecodeneeded=0
(( 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
if ! (( cron ))
then
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
fi
openDatabase
for destination in "${destinations[@]}"
@ -398,23 +554,20 @@ echo '
mime_type_actions.mime_text,
destinations.name,
destination_files.id,
tags.album,
tags.albumartist,
tags.artist,
tags.bitrate,
tags.channels,
tags.composer,
tags.depth,
tags.disc,
tags.genre,
tags.performer,
tags.rate,
tags.releasecountry,
tags.replaygain_alb,
tags.replaygain_trk,
tags.title,
tags.channels,
tags.bitrate,
tags.genre,
tags.albumartist,
tags.year,
tags.album,
tags.disc,
tags.artist,
tags.track,
tags.year
tags.title,
tags.composer,
tags.performer
FROM source_files
INNER JOIN destination_files
ON source_files.id
@ -457,39 +610,33 @@ do
rest=${rest#*::AtOM:SQL:Sep::}
destfileid=${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::}
bitrate=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
channels=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
composer=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
depth=${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::*}
bitdepth=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
rate=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
releasecountry=${rest%%::AtOM:SQL:Sep::*}
channels=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
replaygain_alb=${rest%%::AtOM:SQL:Sep::*}
bitrate=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
replaygain_trk=${rest%%::AtOM:SQL:Sep::*}
genre=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
title=${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::}
year=${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 ;;
@ -501,7 +648,7 @@ do
getDestFile
for copy_ext in "${destinationcopyext[@]}"
do
if [[ $filename =~ '.*\.'"$copy_ext"'$' ]]
if [[ $filename =~ '.*'"$copy_ext" ]]
then
copied=1
break
@ -517,13 +664,13 @@ do
album \
albumartist \
artist \
bitdepth \
bitrate \
channels \
commandline \
composer \
copied \
decodetaskid \
depth \
destfileid \
destination \
disc \
@ -532,9 +679,6 @@ do
mimetype \
performer \
rate \
releasecountry \
replaygain_alb \
replaygain_trk \
rest \
sox_needed \
soxoptions_in \
@ -555,20 +699,19 @@ echo "Created ${count:-0} tasks for $filecount files ${togo:+($togo left) }(${co
concurrency=$(( maxload / 2 ))
(( concurrency )) || concurrency=1
active=0
concurrencychange=$EPOCHSECONDS
concurrencychange=$(date +%s)
starttime=$concurrencychange
taskcount=$count
remaining=$taskcount
failed=0
echo 'BEGIN TRANSACTION;' >&3
committime=$EPOCHSECONDS
committime=$(date +%s)
while (( (remaining || ${#workers[@]}) && ! quit ))
do
timestamp=$EPOCHSECONDS
if (( $timestamp - committime >= 60 ))
if (( $(date +%s) - committime >= 60 ))
then
echo $'COMMIT;\nBEGIN TRANSACTION;' >&3
committime=$timestamp
committime=$(date +%s)
fi
read humanload garbage < /proc/loadavg
load=${humanload%.*}
@ -578,16 +721,16 @@ do
else
if [ -z "$quit" ] \
&& (( ! pause )) \
&& (( timestamp - concurrencychange >= loadinterval ))
&& (( $(date +%s)-concurrencychange >= loadinterval ))
then
if (( concurrency > 1 )) \
&& (( load > maxload ))
then
concurrencychange=$timestamp
concurrencychange=$(date +%s)
(( --concurrency ))
elif (( load < maxload )) && (( active > concurrency - 1 ))
then
concurrencychange=$timestamp
concurrencychange=$(date +%s)
(( ++concurrency ))
fi
fi
@ -597,7 +740,7 @@ do
(( pause )) || master
if (( ran - failed ))
then
currenttime=$timestamp
currenttime=$(date +%s)
if (( pause ))
then
(( runtime = pausestart - starttime - pausedtime ))
@ -673,7 +816,7 @@ done
echo 'COMMIT;' >&3
unset count
endtime=$EPOCHSECONDS
endtime=$(date +%s)
(( elapsedseconds = endtime - starttime - pausedtime ))
(( days =
@ -809,7 +952,6 @@ do
tags.disc,
tags.genre,
tags.performer,
tags.releasecountry,
tags.title,
tags.track,
tags.year
@ -878,8 +1020,6 @@ do
rest=${rest#*::AtOM:SQL:Sep::}
performer=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
releasecountry=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
title=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
track=${rest%%::AtOM:SQL:Sep::*}

View File

@ -1,186 +1,55 @@
[general]
# This section contains parameters of the program itself.
# * max-load <load>: Integer. Defines how parallel processing will behave. AtOM
# will try to keep the 1 minute load average between <load> and <load>+1 by
# adjusting concurrency.
# Initial concurrency will be set to half of that value.
max-load 16
# * load-interval <seconds>: Integer. How often should we check the load average
# and adjust concurrency. Set this too low, and concurrency may be increased
# too quickly. Set this too high, and AtOM will not adapt quickly enough to
# load increase. In both cases, your hard drive will suffer. In my
# experience, 30 seconds is a good value.
load-interval 10
# * ionice <class> [niceness]: IO-hungry processes will be run with ionice class
# <class> and niceness [niceness] (if applicable). See man ionice for details.
ionice 3
# * temporary-directory <directory>: String. Name speaks for itself: this is
# where FIFOs (for communicating with sqlite) and temporary WAVE files will
# be created. Note that debug logs (if enabled) will go there too.
temporary-directory /tmp/AtOM-user/
# * database <file>: String. Where the SQLite database should be stored.
database /home/user/.local/share/AtOM/atom.db
# * debug <level>: Integer.
# 0: No debug output, encoding and decoding errors logged to
# <temporary-directory>/workerN.log
# 1: Print some debug to stdout, log decoding and encoding commands to
# <temporary-directory>/workerN.log
# 3: log SQL queries to <temporary-directory>/debug.log
#debug 1
ionice 3
max-load 6
load-interval 30
temporary-directory %HOME%/.atom/tmp
database %HOME%/.atom/atom.db
debug 0
[source]
# This section defines where are the files you want transcoded.
path /var/lib/mpd/music
skip /last
skip /lastfm
skip /zzz-atrier
# * path <directory>: String. The root of your collection.
# Default: /var/lib/mpd/music
path /mnt/Musique
# * skip <directory>: String. Files in <directory> will be ignored. Note that
# <directory> can be any expression accepted by find.
skip /lost+found
skip /last
skip /lastfm
skip /zzz-atrier
[Vorbis]
# Each section not named 'general' or 'source' will define a new destination.
# Common parameters:
# Mandatory parameters:
# * enabled: Whether or not to treat this destination (1=true/0=false)
enabled 1
# * path: Where files will be written
path /mnt/Musique-OggQ2
# * format: copy, ogg, opus or mp3. Other formats may appear in the future -
# feel free to implement your preferred format.
format vorbis
# Ogg parameters:
# * quality <quality>: The quality parameter of oggenc. See man oggenc for
# more info. This is the only mode supported and planned. Still, if you want
# to be able to use bitrate settings, feel free to fork and file a pull
# request.
quality 1
# Optional parameters:
# * normalize <yes>/<no>: Normalize output files.
normalize yes
# * rename <string>: Destination files will be named according to <string>,
# after expansion of special strings:
# %{album},
# %{albumartist},
# %{artist},
# %{disc},
# %{genre},
# %{releasecountry},
# %{title},
# %{track},
# %{year}.
# Untagged files or files in unrecognized formats will not be changed.
rename %{genre}/%{albumartist}/%{year}-%{album}-%{releasecountry}/%{disc}%{track}--%{artist}-%{title}
# * fat32compat <yes>/<no>: Rename files for compatibility with FAT32
# filesystems.
fat32compat yes
# * ascii-only <yes>/<no>: Rename files for compatibility with ASCII-only
# systems.
ascii-only no
[Ogg]
path /mnt/Musique-OggQ2
format vorbis
quality 1
normalize yes
channels 2
frequency 44100
# you should not skip or copy application/octet-stream, they could be something
# similar to "Audio file with ID3 version 2.4.0, unsynchronized frames"
# * skip_mime-type <mime-type>: Files with mime-type <mime-type> will not
# be included in that destination. For more than one mime-type, use multiple
# times, as needed. The '*' character is a wildcard.
skip_mime-type inode/x-empty
skip_mime-type audio/midi
skip_mime-type image/*
skip_mime-type text/*
skip_mime-type application/pdf
skip_mime-type application/javascript*
skip_mime-type very short file (no magic)
# * copy_mime-type <mime-type>: Same as skip_mime-type, except that files
# matching will be copied as-is to the destination. E.g. image/* will copy
# covers and other images to the destination. In fact, AtOM will try to use
# hard links instead of copies.
copy_mime-type image/*
# * copy_extension <extension>: Copy files whose name and with ".<extension>"
copy_extension txt
# * channels <number>: Files with more than <number> channels will be
# downmixed. Useful if you create files for telephony music-on-hold.
channels 2
# * frequency <hertz>: Files will be resampled as needed to <hertz>Hz
# sampling-rate. Shoutcast/Icecast streams require a constant sampling-rate.
# Telephony systems often require a sample rate of 8000Hz.
frequency 44100
# * higher-than <bitrate>: Integer. Only reencode files with bitrates higher
# then <bitrate>kbps. This only applies if sample-rate, channel count and of
# course format are equal. If unset, only files with bitrates equal to that
# of the target will be copied (actually, hardlinking will be attempted
# first). As Ogg Vorbis target quality is not defined by its bitrate, Ogg
# Vorbis files will always be reencoded if unset.
higher-than 200
copy_mime-type image/*
copy_mime-type text/*
[Opus]
enabled 1
path /mnt/Musique-opus
format opus
# Opus parameters:
# * bitrate <bitrate>: Set (VBR) bitrate to <bitrate>. Note that while Opus
# allows for decimal values, AtOM does not. The reason for this is simple:
# we do numeric comparisons, and Bash only manipulates integers.
bitrate 96
normalize yes
frequency 48000
copy_mime-type image/*
copy_mime-type text/*
[MP3]
enabled 1
path /mnt/Musique-mp3
path /mnt/Musique-mp3.test
format mp3
# MP3 parameters:
# * bitrate <bitrate>: Set ABR to <bitrate>. Again, if you want CBR or any
# other mode supported by lame, please fork and file a pull request.
bitrate 96
# * noresample <yes>/<no>: LAME may decide to encode your file to a lower
# sampling-rate if you use a low bitrate. Setting this to yes will
# append --resample <original file's rate>, preventing any resampling from
# happening.
noresample yes
normalize yes
higher-than 128
# rename file, path unchanged
rename %{track}--%{artist}-%{title}
# change the whole filepath
#rename %{genre}/%{albumartist}/%{year}-%{album}-%{releasecountry}/%{track}--%{artist}-%{title}
#rename %{genre}/%{albumartist}/%{year}-%{album}/%{track}--%{artist}-%{title}
skip_mime-type image/*
skip_mime-type text/*
[asterisk]
enabled 1
path /mnt/Musique-asterisk
format vorbis
quality 0

View File

@ -186,7 +186,7 @@ getConfigDestination() {
destinationcopymime[$destination]="${destinationcopymime[$destination]:+${destinationcopymime[$destination]}|}$value"
;;
'copy_extension')
destinationcopyext[$destination]="${destinationcopyext[$destination]:+${destinationcopyext[$destination]}|}$value"
destinationcopyext[$destination]="${destinationcopyext[$destination]:+${destinationcopyext[$destination]}|}\.$value$"
;;
'higher-than')
expr='^[0-9]*$'

View File

@ -49,13 +49,13 @@ printConfig() {
EOF
[ -n "${destinationskipmime["$destination"]}" ] \
&& echo " |Skipped mime-types|${destinationskipmime["$destination"]//\|/
| |}"
| | |}"
[ -n "${destinationcopymime["$destination"]}" ] \
&& echo " |Copied mime-types|${destinationcopymime["$destination"]//\|/
| |}"
| | |}"
[ -n "${destinationcopyext["$destination"]}" ] \
&& echo " |Copied extensions|${destinationcopyext["$destination"]//\|/
| |}"
| | |}"
done
}|column -t -s'|'
}

View File

@ -60,7 +60,7 @@ path $sourcepath
# Common parameters:
# Mandatory parameters:
# * enabled: Whether or not to treat this destination (1=true/0=false)
# * enabled: Whether or not to treat this destination (1=tue/0=false)
enabled 1
# * path: Where files will be written
@ -144,7 +144,6 @@ bitrate ${destinationquality["$destination"]}
# %{artist},
# %{disc},
# %{genre},
# %{releasecountry},
# %{title},
# %{track},
# %{year}.
@ -208,7 +207,8 @@ bitrate ${destinationquality["$destination"]}
done
cat <<-EOCfg
# * copy_extension <extension>: Copy files whose name and with ".<extension>"
# * copy_extension <extension>: Same as skip_extension, except that files
# matching will be copied as-is to the destination.
EOCfg
destinationcopyext["$destination"]="${destinationcopyext["$destination"]}|"
while [[ ${destinationcopyext["$destination"]} =~ \| ]]

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
currentdbversion=6
#!/bin/bash
currentdbversion=4
checkDatabaseVersion() {
local dbversion
if dbversion=$(Select atom version <<<"\"1\" = 1")

View File

@ -1,6 +1,5 @@
#!/usr/bin/env bash
#!/bin/bash
openDatabase() {
[[ -f "$database" ]] || populate_db=1
rm -f "$tempdir"/sqlite.{in,out}
mkfifo "$tempdir"/sqlite.{in,out}
sqlite3 -bail "$database" \
@ -14,7 +13,7 @@ openDatabase() {
exec 5>&3
exec 3> >(tee -a "$tempdir/debug.log" >&5)
fi
(( populate_db )) && cat $schema >&3
cat $schema >&3
echo '.separator ::AtOM:SQL:Sep::' >&3
echo 'PRAGMA foreign_keys = ON;' >&3
echo 'PRAGMA recursive_triggers = ON;' >&3

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
upgradedatabase_1_2() {
local data \

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
upgradedatabase_2_3() {
local data \
@ -11,4 +11,4 @@ upgradedatabase_2_3() {
Update destinations enabled 1 <<< "1 = 1"
Update atom version 3 <<<"1 = 1"
}
}

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
upgradedatabase_3_4() {
echo "Upgrading database to version 4... (backup is $database.bak_v3)"
@ -6,4 +6,4 @@ upgradedatabase_3_4() {
echo 'ALTER TABLE tags ADD COLUMN releasecountry TEXT;' >&3
Update atom version 4 <<<"1 = 1"
}
}

View File

@ -1,33 +0,0 @@
#!/usr/bin/env bash
upgradedatabase_4_5() {
echo "Upgrading database to version 5... (backup is $database.bak_v4)"
cp "$database" "$database.bak_v4"
echo 'DROP TRIGGER force_destination_update_on_tag_update;' >&3
echo '
CREATE TRIGGER IF NOT EXISTS force_destination_update_on_tag_update
AFTER UPDATE OF
genre,
albumartist,
year,
album,
disc,
artist,
track,
title,
composer,
performer,
releasecountry,
rate,
channels,
bitrate,
depth
ON tags
BEGIN
UPDATE destination_files SET last_change=0
WHERE source_file_id=old.source_file;
END;
' >&3
Update atom version 5 <<<"1 = 1"
}

View File

@ -1,37 +0,0 @@
#!/usr/bin/env bash
upgradedatabase_5_6() {
echo "Upgrading database to version 6... (backup is $database.bak_v5)"
cp "$database" "$database.bak_v5"
echo '
ALTER TABLE tags ADD COLUMN replaygain_alb TEXT;
ALTER TABLE tags ADD COLUMN replaygain_trk TEXT;
DROP TRIGGER force_destination_update_on_tag_update;
CREATE TRIGGER IF NOT EXISTS force_destination_update_on_tag_update
AFTER UPDATE OF
genre,
albumartist,
year,
album,
disc,
artist,
track,
title,
composer,
performer,
releasecountry,
replaygain_alb,
replaygain_trk,
rate,
channels,
bitrate,
depth
ON tags
BEGIN
UPDATE destination_files SET last_change=0
WHERE source_file_id=old.source_file;
END;
' >&3
Update atom version 6 <<<"1 = 1"
}

View File

@ -26,7 +26,7 @@ decodeSox() {
commandline+=(-c ${destinationchannels["$destination"]})
soxoptions_out+=" -c ${destinationchannels["$destination"]}"
fi
if (( ${depth:-0} > 16 ))
if (( ${bitdepth:-0} > 16 ))
then
commandline+=(-b 16)
soxoptions_out+=" -b 16"

View File

@ -1,6 +1,6 @@
#!/usr/bin/env bash
#!/bin/bash
encodeFile::mp3() {
lameopts=(${ionice}lame --quiet --noreplaygain)
lameopts=(${ionice}lame --quiet)
lameopts+=(-v --abr ${destinationquality[$destination]})
[ -n "$album" ] && lameopts+=(--tl "$album" )
[ -n "$artist" ] && lameopts+=(--ta "$artist")
@ -13,10 +13,6 @@ encodeFile::mp3() {
[ -n "$performer" ] && lameopts+=(--tv TOPE="$performer")
[ -n "$releasecountry" ] \
&& lameopts+=(--tv TXXX="MusicBrainz Album Release Country=$releasecountry")
[ -n "$replaygain_alb" ] \
&& lameopts+=(--tv "TXXX=REPLAYGAIN_ALBUM_GAIN=$replaygain_alb")
[ -n "$replaygain_trk" ] \
&& lameopts+=(--tv "TXXX=REPLAYGAIN_TRACK_GAIN=$replaygain_trk")
[ -n "$disc" ] && lameopts+=(--tv TPOS="$disc")
if (( ${destinationnoresample[$destination]:-0} == 1 ))
then

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
encodeFile::opus() {
opusencopts=(${ionice}opusenc --quiet)
opusencopts+=(--bitrate ${destinationquality[$destination]})
@ -13,12 +13,6 @@ encodeFile::opus() {
[ -n "$performer" ] && opusencopts+=(--comment "PERFORMER=$performer")
[ -n "$releasecountry" ] \
&& opusencopts+=(--comment "RELEASECOUNTRY=$releasecountry")
[ -n "$replaygain_alb" ] \
&& opusencopts+=(--comment) \
&& opusencopts+=("REPLAYGAIN_ALBUM_GAIN=$replaygain_alb")
[ -n "$replaygain_trk" ] \
&& opusencopts+=(--comment) \
&& opusencopts+=("REPLAYGAIN_TRACK_GAIN=$replaygain_trk")
[ -n "$title" ] && opusencopts+=(--title "$title")
[ -n "$track" ] && opusencopts+=(--comment "TRACKNUMBER=${track%/*}")
[ -n "${track#*/}" ] && opusencopts+=(--comment "TRACKTOTAL=${track#*/}")

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
encodeFile::vorbis() {
oggencopts=(${ionice}oggenc -Q -q ${destinationquality[$destination]})
[ -n "$albumartist" ] && oggencopts+=(-c "ALBUMARTIST=$albumartist")
@ -9,11 +9,7 @@ encodeFile::vorbis() {
[ -n "$genre" ] && oggencopts+=(-G "$genre")
[ -n "$performer" ] && oggencopts+=(-c "PERFORMER=$performer")
[ -n "$releasecountry" ] \
&& oggencopts+=(-c "RELEASECOUNTRY=$releasecountry")
[ -n "$replaygain_alb" ] \
&& oggencopts+=(-c "REPLAYGAIN_ALBUM_GAIN=$replaygain_alb")
[ -n "$replaygain_trk" ] \
&& oggencopts+=(-c "REPLAYGAIN_TRACK_GAIN=$replaygain_trk")
&& oggencopts+=(--comment "RELEASECOUNTRY=$releasecountry")
[ -n "$title" ] && oggencopts+=(-t "$title")
[ -n "$track" ] && oggencopts+=(-N "$track")
[ -n "$year" ] && oggencopts+=(-d "$year")

View File

@ -1,6 +1,6 @@
#!/bin/bash
getFiles() {
scantime=$EPOCHSECONDS
scantime=$(date +%s)
for prune_expression in "${skippeddirectories[@]}"
do
prunes+=( -path "$sourcepath$prune_expression" -prune -o )

View File

@ -251,7 +251,6 @@ setupDestination() {
%{artist},
%{disc},
%{genre},
%{releasecountry},
%{title},
%{track},
%{year}.
@ -388,16 +387,16 @@ setupDestination() {
copiedmimes+=("${destinationcopymime["$destination"]%%|*}")
destinationcopymime["$destination"]="${destinationcopymime["$destination"]#*|}"
done
[ -n "${destinationcopymime["$destination"]}" ] \
[ -n "${destinationcopymime["$destination"]}" ] \
&& copiedmimes+=("${destinationcopymime["$destination"]}")
count=${#copiedmimes[@]}
unset destinationcopymime["$destination"]
for (( i=0 ; 1 ; i++ ))
do
read \
-e \
read \
-e \
${copiedmimes[i]+-i"${copiedmimes[i]}"} \
-p 'Copy mime-type: ' \
-p 'Copy mime-type: ' \
value
if [ -n "$value" ]
then
@ -410,44 +409,6 @@ setupDestination() {
fi
done
unset copiedmimes
cat <<-EODesc
Copy extensions (extension, string):
Files with extension <extension> will be copied as-is to the
destination. E.g. .jpg will copy covers and other images to the
destination.
This prompt will loop until an empty string is encountered.
EODesc
while [[ ${destinationcopyext["$destination"]} =~ \| ]]
do
copiedexts+=("${destinationcopyext["$destination"]%%|*}")
destinationcopyext["$destination"]="${destinationcopyext["$destination"]#*|}"
done
[ -n "${destinationcopyext["$destination"]}" ] \
&& copiedexts+=("${destinationcopyext["$destination"]}")
count=${#copiedexts[@]}
unset destinationcopyext["$destination"]
for (( i=0 ; 1 ; i++ ))
do
read \
-e \
${copiedexts[i]+-i"${copiedexts[i]}"} \
-p 'Copy extension: ' \
value
if [ -n "$value" ]
then
destinationcopyext[$destination]="${destinationcopyext[$destination]:+${destinationcopyext[$destination]}|}$value"
elif (( i < count ))
then
continue
else
break
fi
done
unset copiedexts
cat <<-EODesc
Channels (integer):

View File

@ -24,7 +24,6 @@ Completion is available for prompts asking for a paths or filenames.
destinationchannels \
destinationfat32compat \
destinationcopymime \
destinationcopyext \
destinationformat \
destinationfrequency \
destinationid \
@ -41,7 +40,6 @@ Completion is available for prompts asking for a paths or filenames.
destinationchannels \
destinationfat32compat \
destinationcopymime \
destinationcopyext \
destinationformat \
destinationfrequency \
destinationid \
@ -76,7 +74,7 @@ Completion is available for prompts asking for a paths or filenames.
esac
;;
esac
read -p'Run index and conversion now? [Y/n] ' do_run
read -p'Run now? [Y/n] ' do_run
case $do_run in
n) exit ;;
*) ;;

65
lib/tags/ffmpeg Normal file
View File

@ -0,0 +1,65 @@
#!/bin/bash
getInfosffmpeg_version='ffmpeg-7'
tagreaders+=( "$getInfosffmpeg_version" )
getInfos::ffmpeg() {
tagreader="$getInfosffmpeg_version"
local allinfos=$(
ffprobe -show_streams \
-i "$sourcepath/$filename" 2>&1 \
|sed '
/^Input/,/.* Audio: /{s/ *: */=/}
s/^[[:space:]]*//
s/\0//g'
)
local metadata=$(
echo -e "$allinfos" \
|sed -n '/Metadata=/,/\[STREAM\]/p'
)
local fmt_infos=$(
echo -e "$allinfos" \
|sed -n \
'/codec_type=audio/,/\[STREAM\]/{
/^\(sample_fmt\|sample_rate\|bit_rate\|channels\)=/{
p
}
}'
)
local infos="$metadata"
albumartist=$(gettag album_artist)
album=$(gettag album)
artist=$(gettag artist)
composer=$(gettag composer)
disc=$(gettag disc)
genre=$(gettag genre)
performer=$(gettag TOPE)
releasecountry=$(gettag releasecountry)
[[ -z "$releasecountry" ]] && releasecountry=$(gettag "MusicBrainz Album Release Country")
title=$(gettag title)
tracknum=$(gettag track)
year=$(gettag date)
expr='^[0-9]*$'
if [ -n "$genre" ] && [[ $genre =~ $expr ]]
then
genre="${id3genres[$genre]}"
fi
infos="$fmt_infos"
channels=$(gettag channels)
rate=$(gettag 'sample_rate')
case $rate in
96) rate=96000;;
48) rate=48000;;
441) rate=44100;;
32) rate=32000;;
24) rate=24000;;
225) rate=22500;;
esac
bitrate=$(gettag 'bit_rate')
bitdepth=$(gettag 'sample_fmt')
bitdepth=${bitdepth//[A-z]/}
if [[ $bitrate == N/A ]]
then
unset bitrate
else
bitrate=$((bitrate / 1000))
fi
}

50
lib/tags/flac Normal file
View File

@ -0,0 +1,50 @@
#!/bin/bash
getInfosFLAC_version='FLAC-4'
tagreaders+=( "$getInfosFLAC_version" )
getInfos::FLAC() {
tagreader="$getInfosFLAC_version"
infos=$(
metaflac \
--show-tag=ALBUM \
--show-tag=ALBUMARTIST \
--show-tag=ARTIST \
--show-tag=COMPOSER \
--show-tag=DATE \
--show-tag=DISCNUMBER \
--show-tag=GENRE \
--show-tag=PERFORMER \
--show-tag=RELEASECOUNTRY \
--show-tag=TITLE \
--show-tag=TRACKNUMBER \
--show-tag=TRACKTOTAL \
"$sourcepath/$filename"
)
albumartist=$(gettag albumartist)
album=$(gettag album)
artist=$(gettag artist)
composer=$(gettag composer)
disc=$(gettag discnumber)
genre=$(gettag genre)
performer=$(gettag performer)
releasecountry=$(gettag releasecountry)
title=$(gettag title)
tracknum=$(gettag tracknumber)
tracktotal=$(gettag tracktotal)
year=$(gettag date)
if [ -n "$tracknum" -a -n "$tracktotal" ]
then
tracknum="$tracknum/$tracktotal"
fi
year=$(gettag DATE)
{
read rate
read channels
read bitdepth
} < <(
metaflac \
--show-sample-rate \
--show-channels \
--show-bps \
"$sourcepath/$filename"
)
}

View File

@ -1,54 +0,0 @@
#!/usr/bin/env bash
getInfosFLAC_version='FLAC-5'
tagreaders+=( "$getInfosFLAC_version" )
getInfos::FLAC() {
local \
infos \
tagreader="$getInfosFLAC_version"
infos=$(
metaflac \
--show-sample-rate \
--show-channels \
--show-bps \
--show-tag=ALBUM \
--show-tag=ALBUMARTIST \
--show-tag=ARTIST \
--show-tag=COMPOSER \
--show-tag=DATE \
--show-tag=DISCNUMBER \
--show-tag=GENRE \
--show-tag=PERFORMER \
--show-tag=RELEASECOUNTRY \
--show-tag=REPLAYGAIN_ALBUM_GAIN \
--show-tag=REPLAYGAIN_TRACK_GAIN \
--show-tag=TITLE \
--show-tag=TRACKNUMBER \
--show-tag=TRACKTOTAL \
"$sourcepath/$filename"
)
albumartist=$(gettag albumartist)
album=$(gettag album)
artist=$(gettag artist)
composer=$(gettag composer)
disc=$(gettag discnumber)
genre=$(gettag genre)
performer=$(gettag performer)
releasecountry=$(gettag releasecountry)
replaygain_alb=$(gettag replaygain_album_gain)
replaygain_trk=$(gettag replaygain_track_gain)
title=$(gettag title)
tracknum=$(gettag tracknumber)
tracktotal=$(gettag tracktotal)
year=$(gettag date)
if [ -n "$tracknum" -a -n "$tracktotal" ]
then
tracknum="$tracknum/$tracktotal"
fi
year=$(gettag DATE)
{
read rate
read channels
read depth
} <<<"$infos"
}

View File

@ -1,75 +0,0 @@
#!/usr/bin/env bash
getInfosffmpeg_version='ffmpeg-9'
tagreaders+=( "$getInfosffmpeg_version" )
getInfos::ffmpeg() {
tagreader="$getInfosffmpeg_version"
local \
infos \
infos=$(
ffprobe -v error \
-show_entries " \
format_tags= \
album_artist, \
album, \
artist, \
composer, \
disc, \
genre, \
TOPE, \
releasecountry, \
'MusicBrainz Album Release Country',\
title, \
track, \
date, \
replaygain_track_gain, \
replaygain_album_gain \
:stream= \
bit_rate, \
channels, \
sample_rate, \
" \
-of default=noprint_wrappers=1 \
-i "$sourcepath/$filename" \
| egrep -v '=N/A$'
)
albumartist=$(gettag TAG:album_artist)
album=$(gettag TAG:album)
artist=$(gettag TAG:artist)
composer=$(gettag TAG:composer)
disc=$(gettag TAG:disc)
genre=$(gettag TAG:genre)
performer=$(gettag TAG:TOPE)
releasecountry=$(gettag TAG:releasecountry)
[[ -z "$releasecountry" ]] \
&& releasecountry=$(gettag "TAG:MusicBrainz Album Release Country")
replaygain_alb=$(gettag TAG:replaygain_album_gain)
replaygain_trk=$(gettag TAG:replaygain_track_gain)
title=$(gettag TAG:title)
tracknum=$(gettag TAG:track)
year=$(gettag TAG:date)
expr='^[0-9]*$'
if [ -n "$genre" ] && [[ $genre =~ $expr ]]
then
genre="${id3genres[$genre]}"
fi
channels=$(gettag channels)
rate=$(gettag 'sample_rate')
case $rate in
96) rate=96000;;
48) rate=48000;;
441) rate=44100;;
32) rate=32000;;
24) rate=24000;;
225) rate=22500;;
esac
bitrate=$(gettag 'bit_rate')
depth=$(gettag 'sample_fmt')
depth=${depth//[A-z]/}
if [[ $bitrate == N/A ]]
then
unset bitrate
else
bitrate=$((bitrate / 1000))
fi
}

View File

@ -1,11 +1,8 @@
#!/usr/bin/env bash
getInfosOpus_version='Opus-4'
#!/bin/bash
getInfosOpus_version='Opus-3'
tagreaders+=( "$getInfosOpus_version" )
getInfos::Opus() {
tagreader="$getInfosOpus_version"
local \
infos \
infos=$(
opusinfo "$sourcepath/$filename" \
| sed 's/\t//'
@ -18,8 +15,6 @@ getInfos::Opus() {
genre=$(gettag genre)
performer=$(gettag performer)
releasecountry=$(gettag releasecountry)
replaygain_alb=$(gettag replaygain_album_gain)
replaygain_trk=$(gettag replaygain_track_gain)
title=$(gettag title)
tracknum=$(gettag tracknumber)
tracktotal=$(gettag tracktotal)

View File

@ -1,14 +1,10 @@
#!/usr/bin/env bash
getInfosSoxi_version='soxi-3'
#!/bin/bash
getInfosSoxi_version='soxi-2'
tagreaders+=( "$getInfosSoxi_version" )
getInfos::soxi() {
tagreader="$getInfosSoxi_version"
local \
infos \
infos=$(
soxi "$sourcepath/$filename" \
| grep -v METADATA_BLOCK_PICTURE
soxi "$sourcepath/$filename"
)
albumartist=$(gettag albumartist)
album=$(gettag album)
@ -18,8 +14,6 @@ getInfos::soxi() {
genre=$(gettag genre)
performer=$(gettag performer)
releasecountry=$(gettag releasecountry)
replaygain_alb=$(gettag replaygain_album_gain)
replaygain_trk=$(gettag replaygain_track_gain)
title=$(gettag title)
tracknum=$(gettag tracknumber)
tracktotal=$(gettag tracktotal)
@ -34,6 +28,6 @@ getInfos::soxi() {
bitrate=$(gettag 'bit rate')
bitrate=${bitrate%k}
bitrate=${bitrate%%.*}
depth=$(gettag precision)
depth=${depth%-bit}
bitdepth=$(gettag precision)
bitdepth=${bitdepth%-bit}
}

View File

@ -1,7 +1,5 @@
#!/usr/bin/env bash
#!/bin/bash
updateTags() {
local reader \
for reader in "${tagreaders[@]}"
do
tagreaderclause+="${tagreaderclause:+ AND }NOT tags.tagreader = \"$reader\""
@ -21,8 +19,6 @@ updateTags() {
tags.genre,
tags.performer,
tags.releasecountry,
tags.replaygain_alb,
tags.replaygain_trk,
tags.title,
tags.track,
tags.year,
@ -88,10 +84,6 @@ echo '
rest=${rest#*::AtOM:SQL:Sep::}
oldreleasecountry=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldreplaygain_alb=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldreplaygain_trk=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldtitle=${rest%%::AtOM:SQL:Sep::*}
rest=${rest#*::AtOM:SQL:Sep::}
oldtrack=${rest%%::AtOM:SQL:Sep::*}
@ -105,7 +97,7 @@ echo '
oldbitrate=${rest%%::AtOM:SQL:Sep::*}
((++count))
(( cron )) || echo -en "\rTags: $((count*100/filecount))%"
if (( count % 100 == 0 ))
if (( count % 1000 == 0 ))
then
echo 'COMMIT;BEGIN TRANSACTION;' >&3
(( debug )) \
@ -117,13 +109,11 @@ echo '
[[ $oldalbumartist != "$albumartist" ]]&&uaa=1
[[ $oldartist != "$artist" ]]&& uar=1
[[ $oldcomposer != "$composer" ]]&& uco=1
[[ $olddepth != "$depth" ]]&& ude=1
[[ $olddepth != "$bitdepth" ]]&& ude=1
[[ $olddisc != "$disc" ]]&& udi=1
[[ $oldgenre != "$genre" ]]&& uge=1
[[ $oldperformer != "$performer" ]]&& upe=1
[[ $oldreleasecountry != "$releasecountry" ]]&& urc=1
[[ $oldreplaygain_alb != "$replaygain_alb" ]]&& urpa=1
[[ $oldreplaygain_trk != "$replaygain_trk" ]]&& urpt=1
[[ $oldtitle != "$title" ]]&& uti=1
[[ $oldtrack != "$tracknum" ]]&& utr=1
[[ $oldyear != "$year" ]]&& uye=1
@ -135,13 +125,11 @@ echo '
${uaa:+albumartist "${albumartist:+::AtOM:FT::}${albumartist:-NULL}"}\
${uar:+artist "${artist:+::AtOM:FT::}${artist:-NULL}"}\
${uco:+composer "${composer:+::AtOM:FT::}${composer:-NULL}"}\
${ude:+depth "${depth:-NULL}"} \
${ude:+depth "${bitdepth:-NULL}"} \
${udi:+disc "${disc:-NULL}"} \
${uge:+genre "${genre:-NULL}"} \
${upe:+performer "${performer:+::AtOM:FT::}${performer:-NULL}"}\
${urc:+releasecountry "${releasecountry:+::AtOM:FT::}${releasecountry:-NULL}"}\
${urpa:+replaygain_alb "${replaygain_alb:-NULL}"}\
${urpt:+replaygain_trk "${replaygain_trk:-NULL}"}\
${uti:+title "${title:+::AtOM:FT::}${title:-NULL}"}\
${utr:+track "${track:+::AtOM:FT::}${tracknum:-NULL}"}\
${uye:+year "${year:-NULL}"} \
@ -150,58 +138,37 @@ echo '
${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 \
releasecountry \
replaygain_alb \
replaygain_trk \
rate \
depth \
bitrate \
channels \
oldgenre \
oldalbumartist \
oldyear \
oldalbum \
olddisc \
oldartist \
oldtracknum \
oldtitle \
oldcomposer \
oldperformer \
oldreleasecountry \
oldreplaygain_alb \
oldreplaygain_trk \
oldrate \
olddepth \
oldbitrate \
oldchannels \
ual \
uaa \
uar \
uco \
ude \
udi \
uge \
upe \
urc \
urpa \
urpt \
uti \
utr \
uye \
ura \
uch \
ubi
>/dev/null <<<"source_file = $sourcefileid"
unset genre \
albumartist \
year \
album \
disc \
artist \
tracknum \
title \
composer \
performer \
releasecountry \
rate \
bitdepth \
bitrate \
channels \
ual \
uaa \
uar \
uco \
ude \
udi \
uge \
upe \
urc \
uti \
utr \
uye \
ura \
uch \
ubi
fi
done
echo 'COMMIT;' >&3

View File

@ -1,166 +0,0 @@
#!/usr/bin/env bash
sanityCheck() {
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
WebM metadata disabled" >&2
disableogginfo=1
(( sanitywarn++ ))
fi
if ! which soxi >/dev/null
then
echo "[WARNING] Tool soxi (from sox) is not" \
"installed or not in PATH
Vorbis metadata disabled" >&2
disablesoxi=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 mkvextract >/dev/null
then
echo "[WARNING] Tool mkvextract (from MKVToolNix) is not"\
"installed or not in PATH
WebM metadata disabled
WebM support disabled" >&2
disablemkvextract=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 (( textunidecodeneeded )) && ! perl -MText::Unidecode -e 'exit;' 2>/dev/null
then
echo "[WARNING] Perl module Text::Unidecode is not available
Renaming to ASCII-only disabled" >&2
unset destinationascii
destinationascii=0
textunidecodeneeded=0
(( 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
if ! (( cron ))
then
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
fi
}
# vim:set ts=8 sw=8:

View File

@ -17,224 +17,213 @@ master() {
return 0
fi
until (( active == concurrency || remaining == 0 ))
do
echo '
SELECT COUNT(*)
FROM tasks
WHERE status = 0
AND requires IN (
SELECT id
FROM tasks
WHERE status = 4
);
echo '
SELECT COUNT(*)
FROM tasks
WHERE status = 0
AND requires IN (
SELECT id
FROM tasks
WHERE status = 4
);
SELECT
id,
source_file,
cmd_arg0,
cmd_arg1,
cmd_arg2,
cmd_arg3,
cmd_arg4,
cmd_arg5,
cmd_arg6,
cmd_arg7,
cmd_arg8,
cmd_arg9,
cmd_arg10,
cmd_arg11,
cmd_arg12,
cmd_arg13,
cmd_arg14,
cmd_arg15,
cmd_arg16,
cmd_arg17,
cmd_arg18,
cmd_arg19,
cmd_arg20,
cmd_arg21,
cmd_arg22,
cmd_arg23,
cmd_arg24,
cmd_arg25,
cmd_arg26,
cmd_arg27,
cmd_arg28,
cmd_arg29,
cmd_arg30,
cmd_arg31,
cmd_arg32,
cmd_arg33,
cmd_arg34,
cmd_arg35,
cmd_arg36,
cmd_arg37,
cmd_arg38,
cmd_arg39,
cmd_arg40,
cmd_arg41,
cmd_arg42,
cmd_arg43,
cmd_arg44,
cmd_arg45,
cmd_arg46,
cmd_arg47,
cmd_arg48,
cmd_arg49,
cmd_arg50,
cmd_arg51,
cmd_arg52,
cmd_arg53,
cmd_arg54,
cmd_arg55,
cmd_arg56,
cmd_arg57,
cmd_arg58,
cmd_arg59,
cleanup,
fileid,
filename
FROM tasks
WHERE status = 0
AND requires IN (
SELECT id
FROM tasks
WHERE status = 4
ORDER BY source_file
/* LIMIT 1 */
)
ORDER BY source_file
LIMIT 1;
'>&3
SELECT
id,
source_file,
cmd_arg0,
cmd_arg1,
cmd_arg2,
cmd_arg3,
cmd_arg4,
cmd_arg5,
cmd_arg6,
cmd_arg7,
cmd_arg8,
cmd_arg9,
cmd_arg10,
cmd_arg11,
cmd_arg12,
cmd_arg13,
cmd_arg14,
cmd_arg15,
cmd_arg16,
cmd_arg17,
cmd_arg18,
cmd_arg19,
cmd_arg20,
cmd_arg21,
cmd_arg22,
cmd_arg23,
cmd_arg24,
cmd_arg25,
cmd_arg26,
cmd_arg27,
cmd_arg28,
cmd_arg29,
cmd_arg30,
cmd_arg31,
cmd_arg32,
cmd_arg33,
cmd_arg34,
cmd_arg35,
cmd_arg36,
cmd_arg37,
cmd_arg38,
cmd_arg39,
cmd_arg40,
cmd_arg41,
cmd_arg42,
cmd_arg43,
cmd_arg44,
cmd_arg45,
cmd_arg46,
cmd_arg47,
cmd_arg48,
cmd_arg49,
cmd_arg50,
cmd_arg51,
cmd_arg52,
cmd_arg53,
cmd_arg54,
cmd_arg55,
cmd_arg56,
cmd_arg57,
cmd_arg58,
cmd_arg59,
cleanup,
fileid,
filename
FROM tasks
WHERE status = 0
AND requires IN (
SELECT id
FROM tasks
WHERE status = 4
ORDER BY source_file
/* LIMIT 1 */
)
ORDER BY source_file
LIMIT 1;
'>&3
read -u4 ready
if (( ready > 0 ))
then
createworker
continue
fi
read -u4 ready
if (( ready > 0 ))
then
createworker
return 0
fi
echo '
SELECT COUNT(*)
FROM tasks
WHERE status = 0
AND requires is NULL;
echo '
SELECT COUNT(*)
FROM tasks
WHERE status = 0
AND requires is NULL;
SELECT
id,
source_file,
cmd_arg0,
cmd_arg1,
cmd_arg2,
cmd_arg3,
cmd_arg4,
cmd_arg5,
cmd_arg6,
cmd_arg7,
cmd_arg8,
cmd_arg9,
cmd_arg10,
cmd_arg11,
cmd_arg12,
cmd_arg13,
cmd_arg14,
cmd_arg15,
cmd_arg16,
cmd_arg17,
cmd_arg18,
cmd_arg19,
cmd_arg20,
cmd_arg21,
cmd_arg22,
cmd_arg23,
cmd_arg24,
cmd_arg25,
cmd_arg26,
cmd_arg27,
cmd_arg28,
cmd_arg29,
cmd_arg30,
cmd_arg31,
cmd_arg32,
cmd_arg33,
cmd_arg34,
cmd_arg35,
cmd_arg36,
cmd_arg37,
cmd_arg38,
cmd_arg39,
cmd_arg40,
cmd_arg41,
cmd_arg42,
cmd_arg43,
cmd_arg44,
cmd_arg45,
cmd_arg46,
cmd_arg47,
cmd_arg48,
cmd_arg49,
cmd_arg50,
cmd_arg51,
cmd_arg52,
cmd_arg53,
cmd_arg54,
cmd_arg55,
cmd_arg56,
cmd_arg57,
cmd_arg58,
cmd_arg59,
cleanup,
fileid,
filename
FROM tasks
WHERE status = 0
AND requires is NULL
ORDER BY source_file
LIMIT 1;
' >&3
SELECT
id,
source_file,
cmd_arg0,
cmd_arg1,
cmd_arg2,
cmd_arg3,
cmd_arg4,
cmd_arg5,
cmd_arg6,
cmd_arg7,
cmd_arg8,
cmd_arg9,
cmd_arg10,
cmd_arg11,
cmd_arg12,
cmd_arg13,
cmd_arg14,
cmd_arg15,
cmd_arg16,
cmd_arg17,
cmd_arg18,
cmd_arg19,
cmd_arg20,
cmd_arg21,
cmd_arg22,
cmd_arg23,
cmd_arg24,
cmd_arg25,
cmd_arg26,
cmd_arg27,
cmd_arg28,
cmd_arg29,
cmd_arg30,
cmd_arg31,
cmd_arg32,
cmd_arg33,
cmd_arg34,
cmd_arg35,
cmd_arg36,
cmd_arg37,
cmd_arg38,
cmd_arg39,
cmd_arg40,
cmd_arg41,
cmd_arg42,
cmd_arg43,
cmd_arg44,
cmd_arg45,
cmd_arg46,
cmd_arg47,
cmd_arg48,
cmd_arg49,
cmd_arg50,
cmd_arg51,
cmd_arg52,
cmd_arg53,
cmd_arg54,
cmd_arg55,
cmd_arg56,
cmd_arg57,
cmd_arg58,
cmd_arg59,
cleanup,
fileid,
filename
FROM tasks
WHERE status = 0
AND requires is NULL
ORDER BY source_file
LIMIT 1;
' >&3
read -u4 ready
read -u4 ready
if (( active == 0 && ready == 0 ))
then
dumpfile="$tempdir/tasks-$(date -Iseconds).csv"
cat <<-EOF
if (( active == 0 && ready == 0 ))
then
dumpfile="$tempdir/tasks-$(date -Iseconds).csv"
cat <<-EOF
$remaining TASKS LEFT, NONE READY!
$remaining TASKS LEFT, NONE READY!
Something went wrong, dumping tasks table to $dumpfile
EOF
cat >&3 <<-EOSQL
.mode csv
.headers on
.output $dumpfile
SELECT * from tasks;
.mode list
.headers off
.output stdout
COMMIT;
EOSQL
closeDatabase
echo "Waiting for children to come back home..."
wait
echo $'\nGood luck!'
exit 1
elif (( ready == 0 ))
then
sleep 0.1
break
else
createworker
fi
echo '
SELECT COUNT(*)
FROM tasks
WHERE status = 0;
'>&3
read -u4 remaining
done
Something went wrong, dumping tasks table to $dumpfile
EOF
cat >&3 <<-EOSQL
.mode csv
.headers on
.output $dumpfile
SELECT * from tasks;
.mode list
.headers off
.output stdout
COMMIT;
EOSQL
closeDatabase
echo "Waiting for children to come back home..."
wait
echo $'\nGood luck!'
exit 1
elif (( ready == 0 ))
then
sleep 0.1
else
createworker
fi
fi
}

View File

@ -59,8 +59,6 @@ CREATE TABLE IF NOT EXISTS tags (
composer TEXT,
performer TEXT,
releasecountry TEXT,
replaygain_alb TEXT,
replaygain_trk TEXT,
depth INTEGER,
rate INTEGER,
channels INTEGER,
@ -132,13 +130,10 @@ CREATE TRIGGER IF NOT EXISTS force_destination_update_on_tag_update
title,
composer,
performer,
releasecountry,
replaygain_alb,
replaygain_trk,
rate,
channels,
bitrate,
depth
bitdepth
ON tags
BEGIN
UPDATE destination_files SET last_change=0

View File

@ -62,7 +62,6 @@ done
getConfig
sanityCheck
openDatabase
(( update )) && getFiles

View File

@ -58,7 +58,7 @@ do
done
getConfig
sanityCheck
openDatabase
sourcepath=''

View File

@ -59,7 +59,7 @@ do
done
getConfig
sanityCheck
openDatabase
echo 'SELECT id,filename FROM destination_files WHERE filename IS NOT NULL;' >&3

View File

@ -59,7 +59,7 @@ do
done
getConfig
sanityCheck
openDatabase
checkwanted() {

View File

@ -38,7 +38,7 @@ LC_ALL=C
shopt -s extglob
source "$SHAREDIR"/id3genres
source ./share/id3genres
for function in "$LIBDIR"/*/*
do
@ -139,7 +139,7 @@ done
}
getConfig
sanityCheck
openDatabase
columns="${show[@]//*/-}"
@ -287,12 +287,12 @@ cat <<-EOBrag
#
# $0 $args
#
# Last database update: $(printf "%(%x %X)T" "$lastupdate")
# Last database update: $(date -d @$lastupdate +'%x %X')
EOBrag
printDate() {
printf "%("${timeformat:-%x %X}")T" "$1"
date -d"@$1" +"${timeformat:-%x %X}"
}
for index in ${!show[@]}

View File

@ -75,7 +75,7 @@ do
done
getConfig
sanityCheck
openDatabase
if (( update ))

View File

@ -94,7 +94,7 @@ done
}
getConfig
sanityCheck
openDatabase
if (( update ))