Fix mp3 tagging fails for single author albums
[clinton/abcde.git] / abcde
diff --git a/abcde b/abcde
index 55d2831..536096c 100755 (executable)
--- a/abcde
+++ b/abcde
@@ -13,7 +13,7 @@
 #
 # $Id$
 
-VERSION='2.3.99-$Revision$'
+VERSION='2.4.0.1'
 
 usage ()
 {
@@ -47,16 +47,18 @@ echo "-n     No lookup. Don't query CDDB, just create and use template"
 echo "-N     Noninteractive. Never prompt for anything"
 echo "-m     Modify playlist to include CRLF endings, to comply with some players"
 echo "       WARNING: Deprecated. Use \"cue\" action"
-echo "-M     Create a CUE file"
+#echo "-M     Create a CUE file"
 echo "-o <type1[,type2]...>"
 echo "       Output file type(s) (vorbis,mp3,flac,spx,mpc,wav,m4a). Defaults to vorbis"
 echo "-p     Pad track numbers with 0's (if less than 10 tracks)"
 echo "-P     Use UNIX pipes to read+encode without wav files"
+echo "-q <level>"
+echo "       Set quality level (high,medium,low)"
 echo "-r <host1[,host2]...>"
 echo "       Also encode on these remote hosts"
 echo "-R     Use local CDDB in recursive mode"
 echo "-s <field>"
-echo "       Show dielfs from the CDDB info (year,genre)"
+echo "       Show fields from the CDDB info (year,genre)"
 echo "-S <#> Set the CD speed"
 echo "-t <#> Start the track numbering at a given number"
 echo "-T <#> Same as -t but modifies tag numbering"
@@ -66,7 +68,7 @@ echo "-V     Be a bit more verbose about what is happening behind the scenes"
 echo "-x     Eject CD after all tracks are read"
 echo "-w <comment>"
 echo "       Add a comment to the CD tracks"
-echo "-W <#> Contatenate CDs: -T #01 -w \"CD #\"" 
+echo "-W <#> Concatenate CDs: -T #01 -w \"CD #\"" 
 echo "-z     Use debug CDROMREADERSYNTAX option (needs cdparanoia)"
 echo ""
 echo "Tracks is a space-delimited list of tracks to grab."
@@ -354,10 +356,17 @@ checkexec ()
                # Cut off any command-line option we added in
                X=$(echo $@ | cut -d' ' -f2)
                # Test for built-in abcde.function
-               [ "$X" != "${X#abcde.}" ] && type $X >/dev/null 2&>1 && return
+               [ "$X" != "${X#abcde.}" ] && type $X >/dev/null 2>&1 && return
                if [ "$(which $X)" = "" ]; then
                        log error "$X is not in your path." >&2
                        log info  "Define the full path to the executable if it exists on your system." >&2
+                       if [ -e /etc/debian_release ] ; then
+                               case $X in
+                                       oggenc)         MISSING_PACKAGE=vorbis-tools ;;
+                                       lame|flac)      MISSING_PACKAGE=$X ;;
+                               esac
+                               log info "Hint: apt-get install $MISSING_PACKAGE" >&2
+                       fi
                        exit 1
                elif [ ! -x "$(which $X)" ]; then
                        log error "$X is not executable." >&2
@@ -381,7 +390,7 @@ diffentries ()
                if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBDIFFCHOICES ] || \
                   [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBDIFFCHOICES ] || \
                   [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then 
-                       echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBDIFFCHOICES" >&2
+                       echo "Invalid diff range. Please select two comma-separated numbers between 1 and $CDDBDIFFCHOICES" >&2
                else
                        # We parse the 2 choices to diff, store them in temporary files and diff them.
                        for PARSECHOICE in $(echo $CDDBDIFFCHOICE | tr , \ ); do
@@ -411,6 +420,9 @@ getcddbinfo()
        TRACKNAME)
                TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
                ;;
+       TRACK-INFO)
+               grep ^EXTT$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | perl -p -e 's/\\n/\n/;'
+               ;;
        esac
 }
 
@@ -484,7 +496,7 @@ makeids ()
 do_replaygain()
 {
        if checkstatus replaygain; then :; else
-               run_command "" echo "Adding replygain information..."
+               run_command "" echo "Adding replaygain information..."
                for TMPOUTPUT in $( echo $OUTPUTTYPE | tr , \ )
                do
                        case $TMPOUTPUT in
@@ -508,6 +520,8 @@ do_replaygain()
                                TRACKFILE="$(mungefilename "$TRACKNAME")"
                                ARTISTFILE="$(mungefilename "$TRACKARTIST")"
                                ALBUMFILE="$(mungefilename "$DALBUM")"
+                       GENRE="$(mungegenre "$GENRE")"
+                       YEAR=${CDYEAR:-$CDYEAR}
                                gettracknum
                                if [ "$ONETRACK" = "y" ]; then 
                                        if [ "$VARIOUSARTISTS" = "y" ]; then
@@ -527,13 +541,14 @@ do_replaygain()
                        done
                        case "$OUTPUT" in
                                flac)
-                                       run_command replaygain-flac nice $ENCNICE $METAFLAC --add-replay-gain "${OUTPUTFILES[@]}"
+                                       run_command replaygain-flac nice $ENCNICE $METAFLAC $FLACGAINOPTS "${OUTPUTFILES[@]}"
+                                       #run_command replaygain-flac true
                                        ;;
                                vorbis|ogg)
-                                       run_command replaygain-vorbis nice $ENCNICE $VORBISGAIN --album "${OUTPUTFILES[@]}"
+                                       run_command replaygain-vorbis nice $ENCNICE $VORBISGAIN $VORBISGAINOPTS "${OUTPUTFILES[@]}"
                                        ;;
                                mp3)
-                                       run_command replaygain-mp3 nice $ENCNICE $MP3GAIN -a "${OUTPUTFILES[@]}"
+                                       run_command replaygain-mp3 nice $ENCNICE $MP3GAIN $MP3GAINOPTS "${OUTPUTFILES[@]}"
                                        ;;
                                mpc)
                                        run_command replaygain-mpc nice $ENCNICE $MPPGAIN --auto "${OUTPUTFILES[@]}"
@@ -763,11 +778,14 @@ return 0
 # do_tag [tracknumber]
 # id3 tags a filename
 # variables used:
-# TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC, 
+# TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC, ATOMICPARSLEY 
 # COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE (and temporarily) ID3TAGV
 do_tag ()
 {
        COMMENTOUTPUT="$(eval echo ${COMMENT})"
+       if [ -z "$COMMENTOUTPUT" ]; then
+               COMMENTOUTPUT="$(getcddbinfo TRACK-INFO)"
+       fi
        CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
        run_command '' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
        # If we want to start the tracks with a given number, we need to modify the
@@ -781,6 +799,11 @@ do_tag ()
                mp3)
                        # id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
                        GENREID=$(do_getgenreid "${CDGENRE}")
+                       # Set TPE2 in case we have a Various Artists rip.
+                       TPE2=""
+                       if [ "$VARIOUSARTISTS" = "y" ]; then
+                               TPE2="Various"
+                       fi
        
                        case "$ID3SYNTAX" in
                                id3);;
@@ -790,23 +813,29 @@ do_tag ()
                                        run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS \
                                                --comment=::"$COMMENTOUTPUT" -A "$DALBUM" \
                                                -a "$TRACKARTIST" -t "$TRACKNAME" -Y "$CDYEAR" \
-                                               -G "$GENREID" -n "${TRACKNUM:-$1}" "${TRACKNUM:+-N $TRACKS}" \
+                                               -G "$GENREID" -n "${TRACKNUM:-$1}" \
+                                               "${TRACKNUM:+-N $TRACKS}" \
                                                "${ENCODING:+--set-encoding=$ENCODING}" \
+                                               "${TPE2:+--set-user-text-frame=TPE2:$TPE2}" \
                                                "$ABCDETEMPDIR/track$1.$OUTPUT"
                                        ;;
                                # FIXME # Still not activated...
                                id3ed)
-                                       run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
-                                               -a "$DALBUM" -n "$TRACKARTIST" -s "$TRACKNAME" -y "$CDYEAR" \
-                                               -g "$GENREID" -k "${TRACKNUM:-$1}" \
+                                       run_command tagtrack-$OUTPUT-$1 nice $ENCNICE \
+                                               $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
+                                               -a "$DALBUM" -n "$TRACKARTIST" -s "$TRACKNAME" \
+                                               -y "$CDYEAR" -g "$GENREID" -k "${TRACKNUM:-$1}" \
                                                "$ABCDETEMPDIR/track$1.$OUTPUT"
                                        ;;
                                *)
                                        # FIXME # track numbers in mp3 come with 1/10, so we cannot
                                        # happily substitute them with $TRACKNUM
-                                       run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
-                                               -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" \
-                                               -g "$GENREID" -T "${TRACKNUM:-$1/$TRACKS}" \
+                                       run_command tagtrack-$OUTPUT-$1 nice $ENCNICE \
+                                               $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
+                                               -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" \
+                                               -y "$CDYEAR" -g "$GENREID" \
+                                               -T "${TRACKNUM:-$1}/$TRACKS" \
+                                               ${TPE2:+--TPE2 "$TPE2"} \
                                                "$ABCDETEMPDIR/track$1.$OUTPUT"
                                        ;;
                        esac
@@ -819,7 +848,9 @@ do_tag ()
                                                mv "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
                                        fi
                                        (
-                                       # These are from http://www.xiph.org/ogg/vorbis/doc/v-comment.html
+                                       # These are from
+                                       # http://www.xiph.org/ogg/vorbis/doc/v-comment.html
+
                                        echo ARTIST="$TRACKARTIST"
                                        echo ALBUM="$DALBUM"
                                        echo TITLE="$TRACKNAME"
@@ -830,6 +861,9 @@ do_tag ()
                                                echo GENRE="$CDGENRE"
                                        fi      
                                        echo TRACKNUMBER=${TRACKNUM:-$1}
+                                       if [ -n "$DISCNUMBER" ]; then
+                                               echo DISCNUMBER="$DISCNUMBER"
+                                       fi
                                        echo CDDB=$CDDBDISCID
                                        if [ "$(eval echo ${COMMENT})" != "" ]; then
                                                case "$COMMENTOUTPUT" in
@@ -837,9 +871,11 @@ do_tag ()
                                                        *)   echo COMMENT="$COMMENTOUTPUT";;
                                                esac    
                                        fi
-                                       ) | run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $VORBISCOMMENT $VORBISCOMMENTOPTS -w \
+                                       ) | run_command tagtrack-$OUTPUT-$1 nice $ENCNICE \
+                                               $VORBISCOMMENT $VORBISCOMMENTOPTS -w \
                                                "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
-                                       # Doublecheck that the commented file was created successfully before wiping the original
+                                       # Doublecheck that the commented file was created
+                                       # successfully before wiping the original
                                        if [ -f "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" ]; then
                                                rm -f "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
                                        else
@@ -860,6 +896,9 @@ do_tag ()
                                echo GENRE="$CDGENRE"
                        fi      
                        echo TRACKNUMBER="${TRACKNUM:-$1}"
+                       if [ -n "$DISCNUMBER" ]; then
+                               echo DISCNUMBER="$DISCNUMBER"
+                       fi
                        echo CDDB="$CDDBDISCID"
                        if [ "$(eval echo ${COMMENT})" != "" ]; then
                                case "$COMMENTOUTPUT" in
@@ -876,7 +915,20 @@ do_tag ()
                        run_command tagtrack-$OUTPUT-$1 true
                        ;;
                m4a)
-                       run_command tagtrack-$OUTPUT-$1 true
+                       #  Use a temp-file of our choice. --overWrite seems to
+                       #  case core dumps with AtomicParsley 0.9.0
+                       ATOMICTEMPFILE="$ABCDETEMPDIR/track$1.m4a-atomic"
+
+                       VARIOUSBOOL="false"
+                       if [ "$VARIOUSARTISTS" = "y" ]; then
+                               VARIOUSBOOL="true"
+                       fi
+
+                       #It has to be command file opts for AtomicParsley
+                       run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $ATOMICPARSLEY $ABCDETEMPDIR/track$1.m4a --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --tracknum ${TRACKNUM:-$1} --year "$CDYEAR" --genre "$CDGENRE" --compilation $VARIOUSBOOL --comment "$COMMENTOUTPUT" --output $ATOMICTEMPFILE
+                       if [ -f $ATOMICTEMPFILE ]; then
+                               mv "$ATOMICTEMPFILE" "$ABCDETEMPDIR/track$1.m4a"
+                       fi
                        ;;
                wav)
                        run_command tagtrack-$OUTPUT-$1 true
@@ -894,7 +946,8 @@ do_tag ()
 # OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
 do_nogap_encode ()
 {
-       # The commands here don't go through run_command because they're never supposed to be silenced
+       # The commands here don't go through run_command because they're never
+       # supposed to be silenced
        echo "Encoding gapless MP3 tracks: $TRACKQUEUE"
        for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
        do
@@ -933,8 +986,8 @@ do_nogap_encode ()
                        fi
                fi
        fi
-       # Other encoders fall through to normal encoding as the tracks
-       # have not been entered in the status file.
+       # Other encoders fall through to normal encoding as the tracks have not
+       # been entered in the status file.
 }
 
 # do_encode [tracknumber] [hostname]
@@ -1072,7 +1125,7 @@ do_encode ()
                                fi
                                # Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
                                if [ ! "$DOTAG" = "y" ]; then
-                                       $RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" "$COMMENT" "$IN" "$OUT"
+                                       $RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" --comment "$COMMENT" "$IN" "$OUT"
                                else
                                        $RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
                                fi
@@ -1440,6 +1493,7 @@ do_playlist ()
                                        read ERASEPLAYLIST
                                        case $ERASEPLAYLIST in
                                                e|E|a|A|k|K) DONE=y ;;
+                                               "") ERASEPLAYLIST=e ; DONE=y ;;
                                                *) ;;
                                        esac
                                done
@@ -1520,8 +1574,12 @@ abcde.cue2discid () {
                IFS=":"
                set -- $1
                IFS="$OIFS"
+               local first second third
+               first=$(expr ${1} + 0 )
+               second=$(expr ${2} + 0 )
+               third=$(expr ${3} + 0 )
 
-               echo $(( ((($1 * 60) + $2) * 75) + $3 ))
+               echo $(( ((($first * 60) + $second) * 75) + $third ))
        }
 
        OFFSET=150
@@ -1621,12 +1679,10 @@ abcde.mkcue () {
     echo REM DISCID $DISCID
     echo FILE \"dummy.wav\" WAVE
 
-    if [ $1 -ne 150 ] ; then
-        if [ $MODE = PREGAP ] ; then
-            OFFSET=$1
-        else
-            OFFSET=150
-        fi
+    if [ $1 -ne 150 ] && [ $MODE = "PREGAP" ] ; then
+        OFFSET=$1
+    else
+        OFFSET=150
     fi
 
     i=1
@@ -1665,6 +1721,9 @@ do_discid ()
                        flac)
                                if $METAFLAC $METAFLACOPTS --export-cuesheet-to=- "$CDROM" > /dev/null 2>&1 ; then
                                        case "$CUE2DISCID" in
+                                               # FIXME # right now we have 2 cue2discid internal
+                                               # implementations: builtin and abcde.cue2discid. Test
+                                               # both of them and decide which one we want to use.
                                                builtin)
                                                        #vecho "Using builtin cue2discid implementation..."
                                                        CUESHEET="$(metaflac $METAFLACOPTS --export-cuesheet-to=- "$CDROM")"
@@ -1831,11 +1890,11 @@ do_discid ()
                        exit 1
                fi
                echo -n .
-               # It's a directory, let's see if it's owned by us
-               if [ ! -O "$ABCDETEMPDIR" ]; then
+               # It's a directory, let's see if it's writable by us
+               if [ ! -r "$ABCDETEMPDIR" ] || [ ! -w "$ABCDETEMPDIR" ] || [ ! -x "$ABCDETEMPDIR" ]; then
                        # Nope, complain and exit
                        echo >&2
-                       echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
+                       echo "abcde: directory $ABCDETEMPDIR already exists and is not writeable." >&2
                        echo "Please investigate, remove it, and rerun abcde." >&2
                        exit 1
                fi
@@ -2132,6 +2191,7 @@ do_musicbrainzstat ()
 
 do_musicbrainz ()
 {
+# Use MBE_TOCGetCDIndexId on a perl query
        :
 }
 
@@ -2153,11 +2213,21 @@ do_cddbstat ()
                                RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
                                case "$RESPONSECODE" in
                                210)    # 210 OK, status information follows (until terminating `.')
-                                       rc=0;
+                                       rc=0
                                        ;;
-                               501|*)  # 501 Illegal CDDB protocol level: <n>. 
+                               501)  # 501 Illegal CDDB protocol level: <n>. 
                                        CDDBPROTO=`expr $CDDBPROTO - 1`
                                        ;;
+                               *)      # Try a cddb query, since freedb2.org doesn't support the stat or ver commands
+                                       # FreeDB TESTCD disc-id is used for query
+                                       $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST 03015501 1 296 344 > "$ABCDETEMPDIR/cddbstat"
+                                       RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
+                                       case "$RESPONSECODE" in
+                                               2??)    # Server responded, everything seems OK
+                                                       rc=0
+                                                       ;;
+                                       esac
+                                       ;;
                                esac 
                        done
                        if test $rc -eq 1; then
@@ -2364,7 +2434,7 @@ do_cddbedit ()
                                                                if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
                                                                   [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
                                                                   [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then 
-                                                                       echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBCHOICES" >&2
+                                                                       echo "Invalid diff range. Please select two comma-separated numbers between 1 and $CDDBCHOICES" >&2
                                                                else
                                                                        # We parse the 2 choices to diff, store them in temporary files and diff them.
                                                                        for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
@@ -2645,7 +2715,7 @@ do_cdread ()
                # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
                # FIXME # Until then, we grab the whole CD in one track, no matter what
                # the user said
-               # We need the first and last track for cdda2wav
+               # We need the first and last track for cdda2wav/icedax
                FIRSTTRACK=$2
                LASTTRACK=$(expr $3 + 0)
                UTRACKNUM=$FIRSTTRACK
@@ -2655,7 +2725,7 @@ do_cdread ()
                                #XX FIXME XX
                                # Add a variable to check if tracks are provided in command line and if not, use "0-" to rip the tracks
                                READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
-                       cdda2wav) READTRACKNUMS="$FIRSTTRACK+$LASTTRACK" ;;
+                       cdda2wav | icedax) READTRACKNUMS="$FIRSTTRACK+$LASTTRACK" ;;
                        *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
                                exit 1 ;;
                esac
@@ -2666,7 +2736,7 @@ do_cdread ()
        if [ "$USEPIPES" = "y" ]; then
                TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
                FILEARG="$( eval echo "\$$TEMPARG" )"
-               REDIR=""
+               REDIR="y"
                PIPE_MESSAGE="and encoding "
        else
                WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
@@ -2682,7 +2752,7 @@ do_cdread ()
                                FILEARG="$WAVDATA"
                                ;;
                esac
-               REDIR=">&2"
+               REDIR="n"
        fi
        if [ "$1" = "onetrack" ]; then
                echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
@@ -2702,12 +2772,17 @@ do_cdread ()
                        STRIPTRACKNUM=$(expr $UTRACKNUM + 0)
                        nice $READNICE $FLAC -d -f --cue=${READTRACKNUMS:-$STRIPTRACKNUM.1-$(($STRIPTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;;
                cdparanoia) 
-                       nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;
-               cdda2wav)
+                   if [ "$REDIR" = "y" ]; then
+                           nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" >&2
+                       else
+                           nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG"
+                       fi;;
+
+               cdda2wav | icedax)
                        if [ "$OSFLAVOUR" = "OSX" ] ; then
-                               # Hei, we have to unmount the device before running anything like cdda2wav in OSX
+                               # Hei, we have to unmount the device before running anything like cdda2wav/icedax in OSX
                                disktool -u ${CDROM#/dev/} 0
-                               # Also, in OSX the cdrom device for cdda2wav changes...
+                               # Also, in OSX the cdrom device for cdda2wav/icedax changes...
                                CDDA2WAVCDROM="IODVDServices"
                        elif [ "$OSFLAVOUR" = "FBSD" ] ; then
                                CDDA2WAVCDROM="$CDROMID"
@@ -2718,12 +2793,19 @@ do_cdread ()
                                        CDDA2WAVCDROM="$CDROMID"
                                fi
                        fi
-                       nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR
-                       ;;
+                   if [ "$REDIR" = "y" ]; then
+                               nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" >&2
+                   else
+                               nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG"
+                       fi ;;
                ## FIXME ## We have an exception for dagrab, since it uses -f
                ## FIXME ## Shall we just use -f $FILEARG ??
-               dagrab) nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG" $REDIR
-                       ;;
+               dagrab) 
+                   if [ "$REDIR" = "y" ]; then
+                               nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG" >&2
+                       else
+                               nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG"
+                       fi ;;
                cddafs)
                        # Find the track's mounted path
                        REALTRACKNUM=$(expr $UTRACKNUM + 0)
@@ -2731,12 +2813,20 @@ do_cdread ()
                        FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
                        # If the file exists, copy it
                        if [ -e "$FILEPATH" ] ; then
-                               nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" $REDIR
+                       if [ "$REDIR" = "y" ]; then
+                                       nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" >&2
+                               else
+                                       nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG"
+                               fi
                        else
                                false
                        fi ;;
-               debug) nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG" $REDIR
-                       ;;
+               debug)
+                   if [ "$REDIR" = "y" ]; then
+                               nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG" >&2
+                       else
+                               nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG"
+                       fi ;;
        esac
        RETURN=$?
        # If we get some error or we get some missing wav 
@@ -2832,6 +2922,13 @@ post_read ()
 :
 }
 
+# post_encode
+# Empty post_encode function, to be defined in the configuration file.
+post_encode ()
+{
+:
+}
+
 ###############################################################################
 # End of functions
 #
@@ -2893,7 +2990,7 @@ NOGAP=n
 BATCHNORM=n
 NOCDDBQUERY=n
 
-# If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
+# If using scsi devices, cdda2wav/icedax needs a CDROMID, instead of a device node
 # i.e. CDROMID="1,0,0"
 CDROMID=""
 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
@@ -2924,8 +3021,12 @@ AACENC=faac
 ID3=id3
 ID3V2=id3v2
 EYED3=eyeD3
+VORBISCOMMENT=vorbiscomment
+METAFLAC=metaflac
+AACTAG=faac
+
 CDPARANOIA=cdparanoia
-CDDA2WAV=cdda2wav
+CDDA2WAV=icedax
 DAGRAB=dagrab
 CDDAFS=cp
 CDDISCID=cd-discid
@@ -2934,8 +3035,6 @@ MUSICBRAINZ=musicbrainz-get-tracks
 EJECT=eject
 MD5SUM=md5sum
 DISTMP3=distmp3
-VORBISCOMMENT=vorbiscomment
-METAFLAC=metaflac
 NORMALIZE=normalize-audio
 CDSPEED=eject
 VORBISGAIN=vorbisgain
@@ -2955,11 +3054,14 @@ BLADEENCOPTS=
 L3ENCOPTS=
 XINGMP3ENCOPTS=
 MP3ENCOPTS=
+MP3GAINOPTS="-a -k"
 # ogg
 VORBIZEOPTS=
 OGGENCOPTS=
+VORBISGAINOPTS="--album"
 # flac
 FLACOPTS=
+FLACGAINOPTS="--add-replay-gain"
 # speex
 SPEEXENCOPTS=
 # mpc
@@ -2996,7 +3098,13 @@ ACTIONS=cddb,read,encode,tag,move,clean
 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:toolame,mp3:lame,mp3:bladeenc,spx:speex,m4a:faac
 
 # List of prefered cdromreaders - by default, run whichever we have in the path
-DEFAULT_CDROMREADERS="cdparanoia cdda2wav"
+DEFAULT_CDROMREADERS="cdparanoia icedax cdda2wav"
+
+# List of quality levels associated with the encoders:
+DEFAULT_QUALITY_XLO="oggenc:-q -1,lame:-q 9,speex:--quality 1,m4a:"
+DEFAULT_QUALITY_LO="oggenc:-q 1,lame:-q 7,speex:--quality 5,m4a:"
+DEFAULT_QUALITY_HI="oggenc:-q 7,lame:--preset standard,speex:--quality 9,m4a:"
+DEFAULT_QUALITY_XHI="oggenc:-q 10,lame:--preset extreme,speex:--quality 10,m4a:"
 
 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for
 # Linux/OpenBSD. ftp is user for NetBSD.
@@ -3035,6 +3143,12 @@ CDDBAVAIL=y
 USEID3=y
 USEID3V2=y
 
+# There we go..
+# But before we get into business, let us chop off any GREP environmental
+# variables.
+GREP_OPTIONS=""
+GREP_COLOR=""
+
 if [ -z "$OUTPUTDIR" ]; then
        OUTPUTDIR=$(pwd)
 fi
@@ -3057,7 +3171,7 @@ fi
 
 if [ "$HTTPGETOPTS" = "" ] ; then
        case $HTTPGET in
-               wget) HTTPGETOPTS="-q -O -";;
+               wget) HTTPGETOPTS="-q -nv -e timestamping=off -O -";;
                curl) HTTPGETOPTS="-f -s";;
                fetch)HTTPGETOPTS="-q -o -";;
                ftp)  HTTPGETOPTS="-a -V -o - ";;
@@ -3083,7 +3197,7 @@ if [ "$CDROM" = "" ] ; then
 fi
 
 # Parse command line options
-#while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPr:Rs:S:t:T:vVxw:W: opt ; do
+#while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPq:r:Rs:S:t:T:vVxw:W: opt ; do
 while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPr:s:S:t:T:UvVxX:w:W:z opt ; do
        case "$opt" in
                1) ONETRACK=y ;;
@@ -3112,6 +3226,7 @@ while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPr:s:S:t:T:UvVxX:w:W:z opt ; do
                o) OUTPUTTYPE="$OPTARG" ;;
                p) PADTRACKS=y ;;
                P) USEPIPES=y ;;
+               q) QUALITYLEVEL="$OPTARG" ;;
                r) REMOTEHOSTS="$OPTARG" ;;
                R) CDDBLOCALRECURSIVE=y ;;
                s) SHOWCDDBFIELDS="$OPTARG" ;;
@@ -3130,7 +3245,10 @@ while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPr:s:S:t:T:UvVxX:w:W:z opt ; do
                X) CUE2DISCID="$OPTARG" ;;
                w) COMMENT="$OPTARG" ;;
                W) if echo $OPTARG | grep "[[:digit:]]" > /dev/null 2>&1 ; then 
-                    STARTTRACKNUMBER="${OPTARG}01" ; STARTTRACKNUMBERTAG="y" ; COMMENT="CD${OPTARG}"
+                    STARTTRACKNUMBER="${OPTARG}01"
+                        STARTTRACKNUMBERTAG="y"
+                        COMMENT="CD${OPTARG}"
+                        DISCNUMBER="${OPTARG}"
                   else
                     log error "argument of -W must be integer"
                         exit 1
@@ -3193,7 +3311,7 @@ if [ "$ONETRACK" = "y" ]; then
        case "$CDROMREADERSYNTAX" in
                flac) ;;
                cdparanoia) ;;
-               cdda2wav) ;;
+               cdda2wav | icedax) ;;
                *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
                   exit 1 ;;
        esac
@@ -3213,14 +3331,17 @@ if [ "$ONETRACK" = "y" ]; then
 else
        while [ $# -gt 0 ]; do
                # Range parsing code courtesy of Vincent Ho
-               RSTART=$(echo $1 | cut -f1 -d-)
-               REND=$(echo $1 | cut -f2 -d-)
-               if [ "$RSTART" = "$REND" ]; then
-                       NEWTRACKS="$RSTART"
-               else
-                       NEWTRACKS=$(f_seq_line $RSTART $REND)
-               fi
-               TRACKQUEUE=$(echo "$TRACKQUEUE" "$NEWTRACKS")
+               # Cleaned up to use shell built-ins by Charles Steinkuehler
+               if [ "${1#*[^0-9-]}" != "$1" ]; then
+                       log error "syntax error while processing track numbers"
+               else
+                       RSTART=${1%%-*}
+                       REND=${1##*-}
+                       while [ ${RSTART:=1} -le ${REND:=0} ] ; do
+                               TRACKQUEUE="$TRACKQUEUE $RSTART"
+                               RSTART=$(( $RSTART + 1 ))
+                       done
+               fi
                shift
        done
 fi
@@ -3241,7 +3362,8 @@ DOMOVE=n
 DOREPLAYGAIN=n
 DOPLAYLIST=n
 DOCLEAN=n
-DOCUE=n
+## FIXME ## Lets keep compatibility with -M
+[ "$DOCUE" != "y" ] && DOCUE=n
 
 for ACTION in $(echo $ACTIONS | tr , \ )
 do
@@ -3277,7 +3399,7 @@ done
 
 # At this point a CDROM has to be defined, so we check it exists.
 if [ X"$CDROM" != "X" ] ; then 
-       if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
+       if ( [ "$CDROMREADERSYNTAX" = "cdda2wav" ] || [ "$CDROMREADERSYNTAX" = "icedax" ] ) && [ "$NEEDCDROMID" = "y" ] ; then
                if [ "$OSFLAVOUR" = "FBSD" ]; then
                        if echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then :; else
                                log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
@@ -3351,7 +3473,7 @@ if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
        BATCHNORM=n
 fi
 
-# Check the encoding format from the ones available in the system, if nothing has been configured in the system.
+# Check the encoding format from the ones available in the system, if nothing has been configured.
 if [ X"$OUTPUTTYPE" = "X" ]; then
        for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
                DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
@@ -3375,7 +3497,7 @@ case "$CDROMREADERSYNTAX" in
                CDROMREADER="$CDPARANOIA"
                CDROMREADEROPTS="$CDPARANOIAOPTS"
                ;;
-       cdda2wav)
+       cdda2wav | icedax)
                CDROMREADER="$CDDA2WAV"
                CDROMREADEROPTS="$CDDA2WAVOPTS"
                ;;
@@ -3454,6 +3576,7 @@ do
                        ;;
                m4a)
                        [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
+                       [ "$DOTAG" = "y" ] && CHECKATOMICPARSLEY=y
                        ;;
                wav)
                        if [ "$KEEPWAVS" = "y" ]; then
@@ -3512,6 +3635,9 @@ case "$FLACENCODERSYNTAX" in
        flac)
                FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
                FLACENCODER="$FLAC"     
+               if [ "$DOREPLAYGAIN" = "y" ]; then
+                       FLACENCODEROPTS="${FLACENCODEROPTS} --replay-gain"
+               fi
                # FLAC streams can be encapsulated on a Ogg transport layer
                if echo "$FLACENCODEROPTS" | egrep -- "(^| )--ogg($| )" > /dev/null 2>&1 ;then
                        log error "FLAC on an Ogg container is not yet supported"
@@ -3551,9 +3677,9 @@ else
        TAGGEROPTS="$ID3V2OPTS"
 fi
 
-# Specific for NOGAP is the use of lame. Another encoder fails...
+# NOGAP is specific to lame. Other encoders fail ...
 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
-       log warning "the NOGAP option is specific of lame. Deactivating..."
+       log warning "the NOGAP option is specific to lame. Deactivating..."
        NOGAP=n
 fi
 
@@ -3676,6 +3802,7 @@ fi
 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
        $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
        $AACENCODER \
+       ${NEEDATOMICPARSLEY+$ATOMICPARSLEY} \
        ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
        ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
        ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
@@ -3687,6 +3814,15 @@ do
        checkexec "$X"
 done
 
+if [ "$CHECKATOMICPARSLEY" = "y" ]; then
+       if ! new_checkexec "$ATOMICPARSLEY"; then
+               echo "WARNING: $ATOMICPARSLEY Not Found Not Post-Tagging!"
+               DOTAG='n'
+       else
+               echo "Using $ATOMICPARSLEY To Tag AAC Tracks."
+       fi
+fi
+
 # And last but not least, check if we can diff between files. We do not abort,
 # since diffing is not critical...
 if [ -x $(which $DIFF) ]; then :; else
@@ -3710,7 +3846,7 @@ HTTPGET="$HTTPGET $HTTPGETOPTS"
 
 # Here it used to say:
 # One thousand lines in, we can start doing stuff with things
-# Well, right now we are at line 3306 ;)
+# Well, right now we are at line 3737 ;)
 
 # Export needed things so they can be read in this subshell
 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
@@ -4104,6 +4240,9 @@ if [ "$DOREPLAYGAIN" = "y" ]; then
        do_replaygain
 fi
 
+# Execute the user-defined post_encode function before cleaning up
+post_encode
+
 # Check to see if run_command logged any errors
 if [ -f "$ABCDETEMPDIR/errors" ]; then
        log error "The following commands failed to run:"