#!/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 -T Mofification time -A Album artist -l Album -a Artist -c Composer -d Disc -g Genre -p Performer -t Title -y Year -d : date-time format (see 'man date' for possible values) -o : 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