+#!/bin/sh
+# Copyright (c) 1998-2001 Robert Woodcock <rcw@debian.org>
+# Copyright (c) 2003-2004 Jesus Climent <jesus.climent@hispalinux.es>
+# This code is hereby licensed for public consumption under either the
+# GNU GPL v2 or greater, or Larry Wall's Artistic license - your choice.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# Copyright for this work is to expire January 1, 2010, after which it
+# shall be public domain.
+
+VERSION=2.1.20
+
+usage ()
+{
+echo "This is abcde v$VERSION."
+echo "Usage: abcde [options] [tracks]"
+echo "Options:"
+echo "-1 Encode the whole CD in a single file"
+echo "-a Actions to perform (cddb,read,normalize,encode,tag,move,playlist,clean)"
+echo "-b Batch mode: enable album normalization and nogap encoding"
+echo "-c Specify a configuration file (overrides system and user config files)"
+echo "-C Specify discid to resume from (only needed if you no longer have the cd)"
+echo "-d Specify CDROM device to grab"
+echo "-D Debugging mode (equivalent to sh -x abcde)"
+#echo "-f Force the use of a local CDDB entry. Otherwise use an empty template"
+echo "-h This help information"
+#echo "-i Tag files while encoding, when possible (local only) -NWY-"
+echo "-j Number of encoder processes to run at once"
+echo "-k Keep the wav tracks for later use"
+echo "-l Use low disk space algorithm"
+echo "-L Use local CDDB storage directory"
+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 "-o Output file type(s) (ogg,mp3,flac,spx). Defaults to ogg"
+echo "-p Pad track numbers with 0's (if less than 10 tracks)"
+echo "-r [host1,host2...] Also encode on these remote hosts"
+#echo "-s Start the track numbering at a given number -NWY-"
+echo "-S Set the CD speed (if possible)"
+#echo "-t File types to preprocess (wav)"
+#echo "-T Set postprocessing options"
+echo "-v Show version number and exit"
+echo "-V Be a bit more verbose about what is happening behind the scenes"
+echo "-x Eject CD after all tracks are read"
+echo "Tracks is a space-delimited list of tracks to grab."
+echo "Ranges specified with hyphens are allowed."
+}
+
+# Funtions to replace the need of seq, which is too distribution dependant.
+f_seq_row ()
+{
+ i=$1
+ while [ $i -ne `expr $2 + 1` ]
+ do
+ echo $i
+ i=`expr $i + 1`
+ done
+}
+
+f_seq_line ()
+{
+ i=$1
+ while [ $i -ne `expr $2 + 1` ]
+ do
+ printf $i" "
+ i=`expr $i + 1`
+ done
+ echo
+}
+
+# checkstatus [blurb]
+# Returns "0" if the blurb was found, returns 1 if it wasn't
+# Puts the blurb content, if available, on stdout.
+# Otherwise, returns "".
+checkstatus ()
+{
+ # Take the last line in the status file if there's multiple matches
+ PATTERN="^$1(=.*)?$"
+ BLURB=$(egrep $PATTERN "$ABCDETEMPDIR/status" | tail -n 1)
+
+ if [ -z "$BLURB" ]; then
+ # No matches found
+ return 1
+ else
+ # Matches found
+ # See if there's a = in it
+ if [ "$(echo $BLURB | grep -c =)" != "0" ]; then
+ echo "$(echo $BLURB | cut -f2- -d=)"
+ fi
+ return 0
+ fi
+}
+
+# checkerrors [blurb]
+# Returns "0" if the blurb was found (meaning there was an error),
+# returns 1 if it wasn't (yes this is a little backwards).
+# Does not print the blurb on stdout.
+# Otherwise, returns "".
+checkerrors ()
+{
+ if [ ! -e "$ABCDETEMPDIR/errors" ]; then
+ return 1
+ fi
+ # Take the last line in the status file if there's multiple matches
+ PATTERN="^$1(:.*)?$"
+ BLURB="$(egrep $PATTERN $ABCDETEMPDIR/errors | tail -n 1)"
+
+ if [ -z "$BLURB" ]; then
+ # negative, we did not have a negative...
+ return 1
+ else
+ # affirmative, we had a negative...
+ return 0
+ fi
+}
+
+# run_command [blurb] [command...]
+# Runs a command, silently if necessary, and updates the status file
+run_command ()
+{
+ BLURB="$1"
+ shift
+ # See if this is supposed to be silent
+ if [ "$(checkstatus encode-output)" = "loud" ]; then
+ "$@" >&2
+ RETURN=$?
+ else
+ # Special case for SMP, since
+ # encoder output is never displayed, don't mute echos
+ if [ -z "$BLURB" -a "$MAXPROCS" != "1" ]; then
+ "$@" >&2
+ RETURN=$?
+ else
+ "$@" >/dev/null 2>&1
+ RETURN=$?
+ fi
+ fi
+ case "$1" in
+ normalize)
+ if [ "$RETURN" = "2" ]; then
+ # File was already normalized.
+ RETURN=0
+ fi
+ ;;
+ esac
+ if [ "$RETURN" != "0" ]; then
+ # Put an error in the errors file. For various reasons we
+ # can't capture a copy of the program's output but we can
+ # log what we attempted to execute and the error code
+ # returned by the program.
+ if [ "$BLURB" ]; then
+ TWEAK="$BLURB: "
+ fi
+ echo "${TWEAK}returned code $RETURN: $@" >> "$ABCDETEMPDIR/errors"
+ return $RETURN # Do not pass go, do not update the status file
+ fi
+ if [ "$BLURB" ]; then
+ echo $BLURB >> "$ABCDETEMPDIR/status"
+ fi
+}
+
+# relpath() and slash() are Copyright (c) 1999 Stuart Ballard and
+# distributed under the terms of the GNU GPL v2 or later, at your option
+
+# Function to determine if a word contains a slash.
+slash ()
+{
+ case "$1" in
+ */*) return 0;;
+ *) return 1;;
+ esac
+}
+
+# Function to give the relative path from one file to another.
+# Usage: relpath fromfile tofile
+# eg relpath music/Artist/Album.m3u music/Artist/Album/Song.mp3
+# (the result would be Album/Song.mp3)
+# Output is relative path to $2 from $1 on stdout
+
+# This code has the following restrictions:
+# Multiple ////s are not collapsed into single /s, with strange effects.
+# Absolute paths and ../s are handled wrong in FR (but they work in TO)
+# If FR is a directory it must have a trailing /
+
+relpath ()
+{
+ FR="$1"
+ TO="$2"
+
+ case "$TO" in
+ /*) ;; # No processing is needed for absolute paths
+ *)
+ # Loop through common prefixes, ignoring them.
+ while slash "$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
+ do
+ FR="$(echo "$FR" | cut -d/ -f2-)"
+ TO="$(echo "$TO" | cut -d/ -f2-)"
+ done
+ # Loop through directory portions left in FR, adding appropriate ../s.
+ while slash "$FR"
+ do
+ FR="$(echo "$FR" | cut -d/ -f2-)"
+ TO="../$TO"
+ done
+ esac
+
+ echo $TO
+}
+
+# This code splits the a Various Artist track name from one of the following
+# forms:
+#
+# forward: Artist / Track
+# forward-dash: Artist - Track
+# reverse: Track / Artist
+# reverse-dash: Track - Artist
+# colon: Artist: Track
+# trailing-paren: Artist (Track)
+#
+# variables used:
+# VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
+splitvarious ()
+{
+ if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
+ case "$VARIOUSARTISTSTYLE" in
+ forward)
+ DTITLEARTIST="$(echo $TRACKNAME | sed 's- / -~-g')"
+ TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
+ TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
+ ;;
+ forward-dash)
+ DTITLEARTIST="$(echo $TRACKNAME | sed 's, - ,~,g')"
+ TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
+ TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
+ ;;
+ reverse)
+ DTITLEARTIST="$(echo $TRACKNAME | sed 's- / -~-g')"
+ TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
+ TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
+ ;;
+ reverse-dash)
+ DTITLEARTIST="$(echo $TRACKNAME | sed 's, - ,~,g')"
+ TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
+ TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
+ ;;
+ colon)
+ DTITLEARTIST="$(echo $TRACKNAME | sed 's-: -~-g')"
+ TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
+ TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
+ ;;
+ trailing-paren)
+ DTITLEARTIST="$(echo $TRACKNAME | sed 's,^\(.*\) (\(.*\)),\1~\2,')"
+ TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
+ TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
+ ;;
+ esac
+ elif [ "$ONETRACK" = "y" ]; then
+ TRACKARTIST="Various"
+ else
+ TRACKARTIST=$DARTIST
+ fi
+}
+
+# do_tag [tracknumber]
+# id3 tags a filename
+# variables used:
+# TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC,
+# COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE (and temporarily) ID3TAGV
+do_tag ()
+{
+ COMMENTOUTPUT="$(eval echo ${COMMENT})"
+ run_command '' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
+ for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
+ do
+ case "$OUTPUT" in
+ mp3)
+ # id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
+ run_command tagtrack-$1 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
+ -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" \
+ -g "$CDGENRE" -T "$1/$TRACKS" "$ABCDETEMPDIR/track$1.$OUTPUT"
+ ;;
+ ogg)
+ case "$OGGENCODERSYNTAX" in
+ vorbize|oggenc)
+ # vorbiscomment can't do in-place modification, mv the file first
+ if [ -f "$ABCDETEMPDIR/track$1.$OUTPUT" -a ! -f "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" ]; then
+ mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT"
+ fi
+ (
+ # These are from http://www.xiph.org/ogg/vorbis/doc/v-comment.html
+ echo ARTIST="$TRACKARTIST"
+ echo ALBUM="$DALBUM"
+ echo TITLE="$TRACKNAME"
+ if [ -n "$CDYEAR" ]; then
+ echo DATE="$CDYEAR"
+ fi
+ if [ -n "$CDGENRE" ]; then
+ echo GENRE="$CDGENRE"
+ fi
+ echo TRACKNUMBER=$1
+ if [ "$(eval echo ${COMMENT})" != "" ]; then
+ case "$COMMENTOUTPUT" in
+ *=*) echo "$COMMENTOUTPUT";;
+ *) echo COMMENT="$COMMENTOUTPUT";;
+ esac
+ fi
+ ) | run_command tagtrack-$1 $VORBISCOMMENT -w \
+ "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" "$ABCDETEMPDIR/track$1.$OUTPUT"
+ # Doublecheck that the commented file was created successfully before wiping the original
+ if [ -f "$ABCDETEMPDIR/track$1.$OUTPUT" ]; then
+ rm -f "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT"
+ else
+ mv "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" "$ABCDETEMPDIR/track$1.$OUTPUT"
+ fi
+ ;;
+ esac
+ ;;
+ flac)
+ (
+ echo ARTIST="$TRACKARTIST"
+ echo ALBUM="$DALBUM"
+ echo TITLE="$TRACKNAME"
+ if [ -n "$CDYEAR" ]; then
+ echo DATE="$CDYEAR"
+ fi
+ if [ -n "$CDGENRE" ]; then
+ echo GENRE="$CDGENRE"
+ fi
+ if [ "$(eval echo ${COMMENT})" != "" ]; then
+ case "$COMMENTOUTPUT" in
+ *=*) echo "$COMMENTOUTPUT";;
+ *) echo COMMENT="$COMMENTOUTPUT";;
+ esac
+ fi
+ echo TRACKNUMBER=$1
+ ) | run_command tagtrack-$1 $METAFLAC --import-vc-from=- --no-utf8-convert "$ABCDETEMPDIR/track$1.$OUTPUT"
+ ;;
+ spx)
+ run_command tagtrack-$1 true
+ ;;
+ esac
+ done
+}
+
+# do_batch_encode
+# variables used:
+# OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
+do_batch_encode ()
+{
+ # The commands here don't go through run_command because they're never supposed to be silenced
+ echo "Batch encoding tracks: $TRACKQUEUE"
+ OUTPUT=$(echo $OUTPUTTYPE | grep "mp3" )
+ case "$OUTPUT" in
+ mp3)
+ case "$MP3ENCODERSYNTAX" in
+ lame)
+ (
+ cd "$ABCDETEMPDIR"
+ TRACKFILES=
+ for UTRACKNUM in $TRACKQUEUE
+ do
+ TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
+ done
+ nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS --nogap $TRACKFILES
+ RETURN=$?
+ if [ "$RETURN" != "0" ]; then
+ echo "batch-encode: $ENCODER returned code $RETURN" >> errors
+ else
+ for UTRACKNUM in $TRACKQUEUE
+ do
+ echo encodetrack-$UTRACKNUM >> status
+ done
+ fi
+ )
+ ;;
+ esac
+ ;;
+ esac
+ # Other encoders fall through to normal encoding as the tracks
+ # have not been entered in the status file.
+}
+
+# do_encode [tracknumber] [hostname]
+# If no hostname is specified, encode locally
+# variables used:
+# TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
+do_encode ()
+{
+ IN="$ABCDETEMPDIR/track$1.wav"
+ # We need IN to proceed.
+ if [ -s "$IN" ] ; then
+ for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
+ do
+ OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
+ run_command '' echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
+ case "$OUTPUT" in
+ mp3)
+ case "$2" in
+ %local*%)
+ case "$MP3ENCODERSYNTAX" in
+ lame|gogo) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
+ bladeenc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" ;;
+ l3enc|xingmp3enc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
+ mp3enc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
+ esac
+ ;;
+ *)
+ run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
+ ;;
+ esac
+ ;;
+ ogg)
+ case "$2" in
+ %local*%)
+ case "$OGGENCODERSYNTAX" in
+ vorbize) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
+ oggenc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
+ esac
+ ;;
+ *)
+ run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
+ ;;
+ esac
+ ;;
+ flac)
+
+ case "$2" in
+ %local*%)
+ case "$FLACENCODERSYNTAX" in
+ flac) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $FLACENCODER $FLACENCODEROPTS -o "$OUT" "$IN" ;;
+ esac
+ ;;
+
+ *)
+ echo -n "DISTMP3:"
+ echo "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
+ run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
+ ;;
+ esac
+ ;;
+ spx)
+ if [ "$(eval echo ${COMMENT})" != "" ]; then
+ case "$COMMENT" in
+ *=*) ;;
+ *) COMMENT="COMMENT=$COMMENT" ;;
+ esac
+ COMMENT="--comment \"$COMMENT\""
+ 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 encodetrack-$OUTPUT-$1 nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" "$COMMENT" "$IN" "$OUT"
+ else
+ run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
+ fi
+ ;;
+ esac
+ done
+ # Only remove .wav if the encoding succeeded
+ if checkerrors "encodetrack-(.{3,4})-$1"; then
+ run_command encodetrack-$1 false
+ else
+ run_command encodetrack-$1 true
+ if [ ! "$KEEPWAVS" = "y" ] ; then
+ rm -f "$IN"
+ fi
+ fi
+ else
+ if [ "$(checkstatus encode-output)" = "loud" ]; then
+ echo "HEH! The file we were about to encode disappeared:"
+ echo ">> $IN"
+ fi
+ run_command encodetrack-$1 false
+ fi
+}
+
+# do_batch_normalize
+# variables used:
+# NORMALIZER, NORMALIZEROPTS
+do_batch_normalize ()
+{
+ # The commands here don't go through run_command because they're never supposed to be silenced
+ echo "Batch normalizing tracks: $TRACKQUEUE"
+ (
+ cd "$ABCDETEMPDIR"
+ BLURB=
+ TRACKFILES=
+ for UTRACKNUM in $TRACKQUEUE
+ do
+ TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
+ done
+ # XXX: Hard-coded batch option!
+ $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
+ RETURN=$?
+ if [ "$RETURN" != "0" ]; then
+ echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
+ else
+ for UTRACKNUM in $TRACKQUEUE
+ do
+ echo normalizetrack-$UTRACKNUM >> status
+ done
+ fi
+ )
+}
+
+# do_normalize [tracknumber]
+# variables used:
+# TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
+do_normalize ()
+{
+ IN="$ABCDETEMPDIR/track$1.wav"
+ if [ -e "$IN" ] ; then
+ run_command '' echo "Normalizing track $1 of $TRACKS: $TRACKNAME..."
+ run_command normalizetrack-$1 $NORMALIZER $NORMALIZEROPTS "$IN"
+ else
+ if [ "$(checkstatus encode-output)" = "loud" ]; then
+ echo "HEH! The file we were about to normalize disappeared:"
+ echo ">> $IN"
+ fi
+ run_command normalizetrack-$1 false "File $IN was not found"
+ fi
+}
+
+# do_move [tracknumber]
+# Deduces the outfile from environment variables
+# Creates directory if necessary
+# variables used:
+# TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, OUTPUTDIR
+do_move ()
+{
+ for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
+ do
+ # Create ALBUMFILE, ARTISTFILE, TRACKFILE
+ # Munge filenames as follows:
+ # ' ' -> '_'
+ # '/' -> '_'
+ # ''' -> ''
+ # '?' -> ''
+ # Eat control characters
+ ALBUMFILE=$(mungefilename "$DALBUM")
+ ARTISTFILE=$(mungefilename "$TRACKARTIST")
+ TRACKFILE=$(mungefilename "$TRACKNAME")
+ GENRE=$(echo $CDGENRE | tr "[:upper:]" "[:lower:]")
+ # Supported variables for OUTPUTFORMAT are GENRE, ALBUMFILE, ARTISTFILE, TRACKFILE, and TRACKNUM.
+ if [ "$VARIOUSARTISTS" = "y" ]; then
+ OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
+ else
+ OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
+ fi
+
+ TRACKNUM=${UTRACKNUM}
+
+ # Check that the directory for OUTPUTFILE exists, if it doesn't, create it
+ OUTPUTFILEDIR=$(dirname "$OUTPUTDIR/$OUTPUTFILE")
+ # mkdir -p shouldn't return an error if the directory already exists
+ mkdir -p "$OUTPUTFILEDIR"
+ run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
+ done
+}
+
+# do_playlist
+# Create the playlist if wanted
+# Variables used:
+# PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
+# VARIOUSARTISTS, OUTPUTDIR
+do_playlist ()
+{
+ for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
+ do
+ # Create a playlist file for the playlist data to go into.
+ # We used to wipe it out if it existed. Now we request permision if interactive.
+ for LASTTRACK in $TRACKQUEUE; do :; done
+ ALBUMFILE=$(mungefilename "$DALBUM")
+ ARTISTFILE=$(mungefilename "$DARTIST")
+ GENRE=$(echo $CDGENRE | tr "[:upper:]" "[:lower:]")
+ if [ "$VARIOUSARTISTS" = "y" ] ; then
+ PLAYLISTFILE=$(eval echo $VAPLAYLISTFORMAT)
+ else
+ PLAYLISTFILE=$(eval echo $PLAYLISTFORMAT)
+ fi
+ FINALPLAYLISTDIR=$(dirname "$OUTPUTDIR/$PLAYLISTFILE")
+ mkdir -p "$FINALPLAYLISTDIR"
+ if [ -s "$OUTPUTDIR/$PLAYLISTFILE" ]; then
+ echo -n "Erase any existing playlist file? [y/n] (y): " >&2
+ if [ "$INTERACTIVE" = "y" ]; then
+ read ERASEPLAYLIST
+ else
+ echo y >&2
+ ERASEPLAYLIST=y
+ fi
+ [ "$ERASEPLAYLIST" != "n" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE"
+ fi
+ touch "$OUTPUTDIR/$PLAYLISTFILE"
+ for UTRACKNUM in $TRACKQUEUE
+ do
+ # Shares some code with do_move since the filenames have to match
+ CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
+ TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
+ splitvarious
+ TRACKFILE=$(mungefilename "$TRACKNAME")
+ ARTISTFILE=$(mungefilename "$TRACKARTIST")
+ TRACKNUM=${UTRACKNUM}
+ if [ "$VARIOUSARTISTS" = "y" ]; then
+ OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
+ else
+ OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
+ fi
+ if [ "$VARIOUSARTISTS" = "y" ]; then
+ if [ "$VAPLAYLISTDATAPREFIX" ] ; then
+ echo ${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
+ else
+ relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
+ fi
+ else
+ if [ "$PLAYLISTDATAPREFIX" ]; then
+ echo ${PLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
+ else
+ relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
+ fi
+ fi
+ done
+ ## this will convert the playlist to have CRLF line-endings, if specified
+ ## (some hardware players insist on CRLF endings)
+ if [ "$DOSPLAYLIST" = "y" ]; then
+ awk '{substr("\r",""); printf "%s\r\n", $0}' "$OUTPUTDIR/$PLAYLISTFILE" > "$ABCDETEMPDIR/PLAYLISTFILE.tmp"
+ rm "$OUTPUTDIR/$PLAYLISTFILE" && mv "$ABCDETEMPDIR/PLAYLISTFILE.tmp" "$OUTPUTDIR/$PLAYLISTFILE"
+ fi
+ echo "playlistcomplete" >> "$ABCDETEMPDIR/status"
+ done
+}
+
+# do_discid
+# This essentially the start of things
+do_discid ()
+{
+ # Query the CD to get the track info, unless the user specified -C
+ if [ -z "$DISCID" ]; then
+ echo -n "Getting CD track info... "
+ TRACKINFO=$($CDDISCID $CDROM)
+ # Make sure there's a CD in there by checking cd-discid's return code
+ if [ "$?" = "1" ]; then
+ echo "abcde error: CD could not be read. Perhaps there's no CD in the drive?" >&2
+ exit 1
+ fi
+ else
+ TRACKINFO=$(cat "$WAVOUTPUTDIR/abcde.$DISCID/discid")
+ fi
+
+ # Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.
+ # This needs to be done now because a section of the resuming code will need
+ # it later.
+
+ # get the number of digits to pad TRACKNUM with - we'll use this later
+ if [ "$PADTRACKS" = "y" ] ; then
+ TRACKNUMPADDING=2
+ fi
+
+ TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
+ if [ -z "$TRACKQUEUE" ]; then
+ echo -n "Grabbing entire CD - tracks: "
+ if [ ! "$PADTRACKS" = "y" ] ; then
+ TRACKNUMPADDING=$(echo -n $TRACKS | wc -c | tr -d ' ')
+ fi
+ TRACKS=$(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
+ X=0
+ while [ "$X" -ne "$TRACKS" ]
+ do
+ X=$(printf "%0.${TRACKNUMPADDING}d" $(expr $X + 1))
+ TRACKQUEUE=$(echo "$TRACKQUEUE" $X)
+ done
+ echo $TRACKQUEUE
+ else
+ # User-supplied track queue.
+ # Weed out non-numbers, whitespace, then sort and weed out duplicates
+ TRACKQUEUE=$(echo $TRACKQUEUE | sed 's-[^0-9 ]--g' | tr ' ' '\n' | grep -v ^$ | sort -n | uniq | tr '\n' ' ' | sed 's- $--g')
+ # Once cleaned, obtain the highest value in the trackqueue for number padding
+ for LASTTRACK in $TRACKQUEUE; do :; done
+ if [ ! "$PADTRACKS" = "y" ] ; then
+ TRACKNUMPADDING=$(echo -n $LASTTRACK | wc -c | tr -d ' ')
+ fi
+ # Now we normalize the trackqueue
+ for TRACK in $TRACKQUEUE ; do
+ TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${TRACK} + 0 ))
+ PADTRACKQUEUE=$(echo $PADTRACKQUEUE $TRACKNUM)
+ done
+ TRACKQUEUE=$PADTRACKQUEUE
+ echo Grabbing tracks: "$TRACKQUEUE"
+ fi
+
+# for LASTTRACK in $TRACKQUEUE; do :; done
+
+ QUEUEDTRACKS=$(echo $TRACKQUEUE | wc -w | tr -d ' ')
+
+ # We have the discid, create a temp directory after it to store all the temp
+ # info
+
+ ABCDETEMPDIR="$WAVOUTPUTDIR/abcde.$(echo $TRACKINFO | cut -f1 -d' ')"
+ if [ -e "$ABCDETEMPDIR" ]; then
+ echo -n "abcde: attempting to resume from $ABCDETEMPDIR"
+ # It already exists, see if it's a directory
+ if [ ! -d "$ABCDETEMPDIR" ]; then
+ # This is a file/socket/fifo/device/etc, not a directory
+ # Complain and exit
+ echo >&2
+ echo "abcde: file $ABCDETEMPDIR already exists and does not belong to abcde." >&2
+ echo "Please investigate, remove it, and rerun abcde." >&2
+ exit 1
+ fi
+ echo -n .
+ # It's a directory, let's see if it's owned by us
+ if [ ! -O "$ABCDETEMPDIR" ]; then
+ # Nope, complain and exit
+ echo >&2
+ echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
+ echo "Please investigate, remove it, and rerun abcde." >&2
+ exit 1
+ fi
+ echo .
+ # See if it's populated
+ if [ ! -f "$ABCDETEMPDIR/discid" ]; then
+ # Wipe and start fresh
+ echo "abcde: $ABCDETEMPDIR/discid not found. Abcde must remove and recreate" >&2
+ echo -n "this directory to continue. Continue? [y/n] (n)" >&2
+ if [ "$INTERACTIVE" = "y" ]; then
+ read ANSWER
+ else
+ echo y >&2
+ ANSWER=y
+ fi
+ if [ "$ANSWER" != "y" ]; then
+ exit 1
+ fi
+ rm -rf "$ABCDETEMPDIR" || exit 1
+ mkdir "$ABCDETEMPDIR"
+ if [ "$?" -gt "0" ]; then
+ # Directory already exists or could not be created
+ echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
+ exit 1
+ fi
+ else
+ # Everything is fine. Check for ^encodetracklocation-
+ # and encode-output entries in the status file and
+ # remove them. These are not relevant across sessions.
+ if [ -f "$ABCDETEMPDIR/status" ]; then
+ mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
+ grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
+ | grep -v ^encode-output > "$ABCDETEMPDIR/status"
+ fi
+ # Remove old error messages
+ if [ -f "$ABCDETEMPDIR/errors" ]; then
+ rm -f "$ABCDETEMPDIR/errors"
+ fi
+ fi
+ else
+ # We are starting from scratch
+ mkdir "$ABCDETEMPDIR"
+ if [ "$?" -gt "0" ]; then
+ # Directory already exists or could not be created
+ echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
+ exit 1
+ fi
+ cat /dev/null > "$ABCDETEMPDIR/status"
+ fi
+
+ # Create the discid file
+ echo "$TRACKINFO" > "$ABCDETEMPDIR/discid"
+
+ # Determine what actions are to be done from $ACTIONS and set the
+ # following environment variables for them:
+ DOCDDB=n
+ DOREAD=n
+ DONORMALIZE=n
+ DOPREPROCESS=n
+ DOENCODE=n
+ DOPOSTPROCESS=n
+ DOTAG=n
+ DOMOVE=n
+ DOPLAYLIST=n
+ DOCLEAN=n
+
+ for ACTION in $(echo $ACTIONS | tr , \ )
+ do
+ case $ACTION in
+ cddb) DOCDDB=y;;
+ read) DOREAD=y;;
+ normalize) DONORMALIZE=y; DOREAD=y;;
+ preprocess) DOPREPROCESS=y; DOREAD=y;;
+ encode) DOENCODE=y; DOREAD=y;;
+ postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
+ tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
+ move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
+ playlist) DOCDDB=y; DOPLAYLIST=y;;
+ clean) DOCLEAN=y;;
+ esac
+ done
+}
+
+# do_cddbparse
+# Parses a CDDB file and outputs the title and the track names.
+# Variables: CDDBFILE
+do_cddbparse ()
+{
+ CDDBPARSEFILE="$1"
+ # List out disc title/author and contents
+ if [ "$ONETRACK" = "y" ]; then
+ vecho "ONETRACK mode selected: displaying only the title of the CD..."
+ fi
+ echo "---- $(grep DTITLE "${CDDBPARSEFILE}" | cut '-d=' -f2- | tr -d \\r\\n ) ----"
+ if [ ! "$ONETRACK" = "y" ];then
+ for TRACK in $(f_seq_row 1 $TRACKS)
+ do
+ echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
+ done
+ fi
+}
+
+# do_localcddb
+# Check for a local CDDB file, and report success
+do_localcddb ()
+{
+ if checkstatus cddb-readcomplete && checkstatus cddb-choice >/dev/null; then :; else
+
+ CDDBLOCALSUCCESS="n"
+ CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
+ CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
+ USELOCALRESP="y"
+
+ # If the user has selected to check a local CDDB repo, we proceed with it
+ if [ "$CDDBUSELOCAL" = "y" ]; then
+ if [ -r "${CDDBLOCALFILE}" ]; then
+ # List out disc title/author and contents
+ do_cddbparse "${CDDBLOCALFILE}"
+ echo -n "Locally cached CDDB entry found, use it? [y/n] (y): "
+ if [ "$INTERACTIVE" = "y" ]; then
+ read USELOCALRESP
+ while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
+ echo -n 'Invalid selection. Please answer "y" or "n": '
+ read USELOCALRESP
+ done
+ [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
+ else
+ echo "y">&2
+ fi
+ if [ "$USELOCALRESP" = "y" ]; then
+ #echo "Using local copy of CDDB data"
+ cp "${CDDBLOCALFILE}" "$ABCDETEMPDIR/cddbread.1"
+ echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
+ echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
+ do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
+ echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
+ CDDBLOCALSUCCESS="y"
+ else
+ #echo "Not using local copy of CDDB data"
+ CDDBLOCALSUCCESS="n"
+ fi
+ else
+ CDDBLOCALSUCCESS="n"
+ fi
+ fi
+ fi
+}
+
+# do_cddbstat
+do_cddbstat ()
+{
+ # Perform CDDB protocol version check if it hasn't already been done
+ if checkstatus cddb-statcomplete; then :; else
+ if [ "$CDDBAVAIL" = "n" ]; then
+ ERRORCODE=no_query
+ echo 503 > "$ABCDETEMPDIR/cddbstat"
+ else
+ rc=1
+ CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
+ CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
+ while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
+ vecho "Checking CDDB server status..."
+ $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
+ RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
+ case "$RESPONSECODE" in
+ 210) # 210 OK, status information follows (until terminating `.')
+ rc=0;
+ ;;
+ 501|*) # 501 Illegal CDDB protocol level: <n>.
+ CDDBPROTO=`expr $CDDBPROTO - 1`
+ ;;
+ esac
+ done
+ if test $rc -eq 1; then
+ CDDBAVAIL="n"
+ fi
+ fi
+ echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
+ fi
+}
+
+
+# do_cddbquery
+do_cddbquery ()
+{
+ CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
+ CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
+
+ # Perform CDDB query if it hasn't already been done
+ if checkstatus cddb-querycomplete; then :; else
+ if [ "$CDDBAVAIL" = "n" ]; then
+ ERRORCODE=no_query
+ echo 503 > "$ABCDETEMPDIR/cddbquery"
+ # The default CDDBLOCALSUCCESS is "n"
+ # This part will be triggered if the user CDDB repo does not
+ # contain the entry, or if we are not trying to use the repo.
+ else
+ vecho "Querying the CDDB server..."
+ CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
+ CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
+ $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
+ ERRORCODE=$?
+ case $ERRORCODE in
+ 0) # success
+ ;;
+ 12|13|14)
+ # no match found in database,
+ # wget/fetch error, or user requested not to use CDDB
+ # Make up an error code (503) that abcde
+ # will recognize in do_cddbread
+ # and compensate by making a template
+ echo 503 > "$ABCDETEMPDIR/cddbquery"
+ ;;
+ *) # strange and unknown error
+ echo ERRORCODE=$ERRORCODE
+ echo "abcde: $CDDBTOOL returned unknown error code"
+ ;;
+ esac
+ fi
+ echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
+ fi
+}
+
+# do_cddbread
+do_cddbread ()
+{
+ # If it's not to be used, generate a template.
+ # Then, display it (or them) and let the user choose/edit it
+ if checkstatus cddb-readcomplete; then :; else
+ vecho "Obtaining CDDB results..."
+ # If CDDB is to be used, interpret the query results and read all
+ # the available entries.
+ rm -f "$ABCDETEMPDIR/cddbchoices"
+ CDDBCHOICES=1 # Overridden by multiple matches
+ RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
+ case "$RESPONSECODE" in
+ 200)
+ # One exact match, retrieve it
+ # 200 [section] [discid] [artist] / [title]
+ if checkstatus cddb-read-1-complete; then :; else
+ echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
+ $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
+ echo "done." >> "$ABCDETEMPDIR/cddbchoices"
+ echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
+ echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
+ fi
+ # List out disc title/author and contents
+ echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
+ for TRACK in $(f_seq_row 1 $TRACKS)
+ do
+ echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
+ done
+ echo >> "$ABCDETEMPDIR/cddbchoices"
+ ;;
+ 202|403|409|503)
+ # No match
+ case "$RESPONSECODE" in
+ 202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
+ 403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
+ 503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
+ esac
+ $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.1"
+ # List out disc title/author and contents of template
+ echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
+ UNKNOWNDISK=y
+ for TRACK in $(f_seq_row 1 $TRACKS)
+ do
+ echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
+ done
+ echo >> "$ABCDETEMPDIR/cddbchoices"
+ echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
+ echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
+ ;;
+ 210|211)
+ # Multiple exact, (possibly multiple) inexact matches
+ IN=
+ if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
+ if [ "$(wc -l < $ABCDETEMPDIR/cddbquery | tr -d ' ')" -eq 3 ]; then
+ echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
+ tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
+ echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
+ else
+ echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
+ fi
+ #echo -n "Retrieving multiple matches... "
+ grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
+ read DISCINFO # eat top line
+ while read DISCINFO
+ do
+ X=$(expr $X + 1)
+ if checkstatus cddb-read-$X-complete; then :; else
+ $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
+ echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
+ fi
+ # List out disc title/author and contents
+ echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
+ for TRACK in $(f_seq_row 1 $TRACKS)
+ do
+ echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
+ done
+ echo >> "$ABCDETEMPDIR/cddbchoices"
+ done )
+ #echo "done."
+ CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
+ ;;
+ 999)
+ # Using local copy.
+ for TRACK in $(f_seq_row 1 $TRACKS)
+ do
+ echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
+ done
+ echo >> "$ABCDETEMPDIR/cddbchoices"
+ echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
+ echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
+ ;;
+ esac
+ echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
+ fi
+}
+
+# do_cddbedit
+do_cddbedit ()
+{
+ if checkstatus cddb-edit >/dev/null; then
+ CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
+ VARIOUSARTISTS="$(checkstatus variousartists)"
+ VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
+ return 0
+ fi
+ if [ "$INTERACTIVE" = "y" ]; then
+ # We should show the CDDB results both when we are not using the local CDDB repo
+ # or when we are using it but we could not find a proper match
+ if [ "$CDDBUSELOCAL" = "y" ] && [ ! "$CDDBLOCALSUCCESS" = "y" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
+ # Display the $ABCDETEMPDIR/cddbchoices file created above
+ # Pick a pager so that if the tracks overflow the screen the user can still view everything
+ if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
+ CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
+ CHOICE=$(checkstatus cddb-choice)
+ if [ -n "$CHOICE" ] ; then
+ case $CDDBCHOICES in
+ 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
+ *)
+ echo "Selected: #$CHOICE"
+ do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
+ ;;
+ esac
+ else
+ # The user has a choice to make, display the info in a pager if necessary
+ if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
+ # Use the debian sensible-pager wrapper to pick the pager
+ # user has requested via their $PAGER environment variable
+ if [ -x "/usr/bin/sensible-pager" ]; then
+ /usr/bin/sensible-pager "$ABCDETEMPDIR/cddbchoices"
+ elif [ -x "$PAGER" ]; then
+ # That failed, try to load the preferred editor, starting
+ # with their PAGER variable
+ $PAGER "$ABCDETEMPDIR/cddbchoices"
+ # If that fails, check for less
+ elif [ -x /usr/bin/less ]; then
+ /usr/bin/less -f "$ABCDETEMPDIR/cddbchoices"
+ # more should be on all UNIX systems
+ elif [ -x /bin/more ]; then
+ /bin/more "$ABCDETEMPDIR/cddbchoices"
+ else
+ # No bananas, just cat the thing
+ cat "$ABCDETEMPDIR/cddbchoices" >&2
+ fi
+ else
+ # It's all going to fit in one page, cat it
+ cat "$ABCDETEMPDIR/cddbchoices" >&2
+ fi
+
+ # I'll take CDDB read #3 for $400, Alex
+ echo -n "Which entry would you like abcde to use? [1-$CDDBCHOICES]: " >&2
+ read CDDBCHOICE
+ # Make sure we get a valid choice
+ CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
+ while [ $CDCHOICENUM -lt 1 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
+ echo "Invalid selection. Please choose a number between 1 and $CDDBCHOICES." >&2
+ echo -n "Selection [1-$CDDBCHOICES]: " >&2
+ read CDDBCHOICE
+ CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
+ done
+ echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= $ABCDETEMPDIR/cddbread.$CDCHOICENUM | cut -f2- -d= | tr -d \\r\\n))" >&2
+ do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
+ echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
+ fi
+ fi
+ else
+ # We need some code to show the selected option when local repository is selected and we have found a match
+ echo "Using cached CDDB match..."
+ # Display the $ABCDETEMPDIR/cddbchoices file created above
+ # Pick a pager so that if the tracks overflow the screen the user can still view everything
+ if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
+ CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
+ CHOICE=$(checkstatus cddb-choice)
+ if [ "$USELOCALRESP" = "y" ]; then :; else
+ if [ -n "$CHOICE" ] ; then
+ case $CDDBCHOICES in
+ 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
+ *)
+ echo "Selected: #$CHOICE"
+ do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
+ ;;
+ esac
+ fi
+ fi
+ fi
+ fi
+ else
+ # We're noninteractive - pick the first choice.
+ # But in case we run a previous instance and selected a choice, use it.
+ if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
+ # Show the choice if we are not using the locally stored one
+ # or when the local search failed to find a match.
+ PREVIOUSCHOICE=$(checkstatus cddb-choice)
+ if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSUCCESS" = "n" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
+ #if [ "$PREVIOUSCHOICE" ]; then
+ cat "$ABCDETEMPDIR/cddbchoices"
+ #fi
+ fi
+ if [ ! -z "$PREVIOUSCHOICE" ] ; then
+ CDCHOICENUM=$PREVIOUSCHOICE
+ else
+ CDCHOICENUM=1
+ echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
+ fi
+ echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= $ABCDETEMPDIR/cddbread.$CDCHOICENUM | cut -f2- -d= | tr -d \\r\\n))" >&2
+ fi
+ fi
+
+ # sanity check
+ if checkstatus cddb-choice >/dev/null; then :; else
+ echo "abcde: internal error: cddb-choice not recorded." >&2
+ exit 1
+ fi
+ CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
+ echo -n "Edit selected CDDB data? [y/n] ("
+ if [ "$INTERACTIVE" = "y" ]; then
+ if [ "$UNKNOWNDISK" = "y" ]; then
+ echo -n "y): " >&2
+ read EDITCDDB
+ [ "$EDITCDDB" != "n" ] && EDITCDDB=y
+ else
+ echo -n "n): " >&2
+ read EDITCDDB
+ fi
+ else
+ echo "n): n" >&2
+ EDITCDDB=n
+ fi
+ if [ "$EDITCDDB" = "y" ]; then
+ CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
+
+ # Use the debian sensible-editor wrapper to pick the editor that the
+ # user has requested via their $EDITOR environment variable
+ if [ -x "/usr/bin/sensible-editor" ]; then
+ /usr/bin/sensible-editor "$CDDBDATA"
+ elif [ -n "$EDITOR" ]; then
+ if [ -x $(which "${EDITOR%%\ *}") ]; then
+ # That failed, try to load the preferred editor, starting
+ # with their EDITOR variable
+ eval $(echo "$EDITOR") "$CDDBDATA"
+ fi
+ # If that fails, check for a vi
+ elif [ -x /usr/bin/vi ]; then
+ /usr/bin/vi "$CDDBDATA"
+ # nano should be on all (modern, i.e., sarge) debian systems
+ elif [ -x /usr/bin/nano ]; then
+ /usr/bin/nano "$CDDBDATA"
+ # mg should be on all OpenBSD systems
+ elif [ -x /usr/bin/mg ]; then
+ /usr/bin/mg "$CDDBDATA"
+ # bomb out
+ else
+ echo "No editor available. Check your EDITOR environment variable." >&2
+ fi
+ # delete editor backup file if it exists
+ if [ -w "$CDDBDATA~" ]; then
+ rm -f "$CDDBDATA~"
+ fi
+ fi
+
+ # Some heuristics first. Look at Disc Title, and if it starts with
+ # "Various", then we'll assume Various Artists
+ if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2 -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
+ echo "Looks like a Multi-Artist CD" >&2
+ VARIOUSARTISTS=y
+ else
+ echo -n "Is the CD multi-artist? [y/n] (n): " >&2
+ if [ "$INTERACTIVE" = "y" ]; then
+ read VARIOUSARTISTS
+ else
+ echo n >&2
+ VARIOUSARTISTS=n
+ fi
+ fi
+ if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
+ # Set a default
+ DEFAULTSTYLE=1
+ # Need NUMTRACKS before cddb-tool will return it:
+ NUMTRACKS=$(grep -E '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
+ if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
+ # More than 1/2 tracks contain a "/", so guess forward
+ DEFAULTSTYLE=1
+ elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
+ # More than 1/2 contain a "-", so guess forward-dash
+ DEFAULTSTYLE=2
+ elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
+ # More than 1/2 contain something in parens, so guess trailing-paren
+ DEFAULTSTYLE=6
+ fi
+
+ echo "1) Artist / Title" >&2
+ echo "2) Artist - Title" >&2
+ echo "3) Title / Artist" >&2
+ echo "4) Title - Artist" >&2
+ echo "5) Artist: Title" >&2
+ echo "6) Title (Artist)" >&2
+ echo "7) This is a single-artist CD" >&2
+ echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
+ if [ "$INTERACTIVE" = "y" ]; then
+ read VARIOUSARTISTSTYLE
+ else
+ echo $DEFAULTSTYLE >&2
+ VARIOUSARTISTSTYLE=$DEFAULTSTYLE
+ fi
+ VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
+ # If they press Enter, then the default style (0) was chosen
+ while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
+ echo "Invalid selection. Please choose a number between 1 and 7."
+ echo -n "Selection [1-7]: "
+ read VARIOUSARTISTSTYLE
+ VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
+ done
+ if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
+ VARIOUSARTISTSTYLE=$DEFAULTSTYLE
+ fi
+ echo "Selected: $VARIOUSARTISTSTYLE"
+ case "$VARIOUSARTISTSTYLE" in
+ 1) # Artist / Title
+ VARIOUSARTISTSTYLE=forward
+ ;;
+ 2) # Artist - Title
+ VARIOUSARTISTSTYLE=forward-dash
+ ;;
+ 3) # Title / Artist
+ VARIOUSARTISTSTYLE=reverse
+ ;;
+ 4) # Title - Artist
+ VARIOUSARTISTSTYLE=reverse-dash
+ ;;
+ 5) # Artist: Title
+ VARIOUSARTISTSTYLE=colon
+ ;;
+ 6) # Title (Artist)
+ VARIOUSARTISTSTYLE=trailing-paren
+ ;;
+ 7) # Single Artist
+ VARIOUSARTISTS=n
+ ;;
+ esac
+ fi
+
+ echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
+ echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
+
+ if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
+ if [ $CDDBDATAMD5SUM != "" ] && [ $CDDBDATAMD5SUM != $($MD5SUM "$CDDBDATA" | cut -d " " -f 1) ]; then
+ # This works but does not have the necessary error checking
+ # yet. If you are familiar with the CDDB spec
+ # (see http://www.freedb.org/src/latest/DBFORMAT)
+ # and can create an error-free entry on your own, then put
+ # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
+ # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
+ # your abcde.conf to change the email address submissions are
+ # sent to.
+
+ # submit the modified file, if they want
+ if [ "$NOSUBMIT" != "y" ]; then
+ echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
+ read YESNO
+ while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
+ [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
+ do
+ echo -n 'Invalid selection. Please answer "y" or "n": '
+ read YESNO
+ done
+ if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
+ echo -n "Sending..."
+ $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
+ echo "done."
+ fi
+ fi
+ fi
+ fi
+ # Make sure the cache directory exists
+ mkdir -p $CDDBLOCALDIR
+ # Cache edited CDDB entry in the user's cddb dir
+ if [ "$CDDBCOPYLOCAL" = "y" ] || [ "$COPYCDDBLOCAL" = "Y" ]; then
+ cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
+ fi
+
+ echo "cddb-edit" >> "$ABCDETEMPDIR/status"
+}
+
+# do_cdread_one [lasttrack] [firsttrack]
+#
+# Reads the CD in a single track. Live performances, concerts, mixes,... benefit from this.
+do_cdread_one ()
+{
+ # The commands here don't go through run_command because they're never supposed to be silenced
+ # return codes need to be doublechecked anyway, however
+ LASTTRACKNUMBER=$1
+ FIRSTTRACKNUMBER=$2
+ WAVDATA="$ABCDETEMPDIR/track$FIRSTTRACKNUMBER.wav"
+ echo "Grabbing the CD to a single track..." >&2
+ case "$CDROMREADERSYNTAX" in
+ cdparanoia) nice $READNICE $CDROMREADER -d $CDROM "1-" "$WAVDATA" >&2 ;;
+ cdda2wav)
+ if [ "$OSFLAVOUR" = "OSX" ] ; then
+ # Hei, we have to unmount the device before running anything like cdda2wav in OSX
+ disktool -u ${CDROM#/dev/} 0
+ # Also, in OSX the cdrom device for cdda2wav changes...
+ CDDA2WAVCDROM="IODVDServices"
+ elif [ "$OSFLAVOUR" = "FBSD" ] ; then
+ CDDA2WAVCDROM="$CDROMID"
+ else
+ if [ "$CDROMID" = "" ]; then
+ CDDA2WAVCDROM="$CDROM"
+ else
+ CDDA2WAVCDROM="$CDROMID"
+ fi
+ fi
+ nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t 1+$LASTTRACKNUM "$WAVDATA" >&2
+ ;;
+ dagrab) nice $READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
+ cddafs)
+ # Find the track's mounted path
+ REALTRACKNUM=$(expr $UTRACKNUM + 0)
+ FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \([^(]*\) (.*/\1/')
+ FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
+ # If the file exists, copy it
+ if [ -e "$FILEPATH" ] ; then
+ nice $READNICE $CDROMREADER "$FILEPATH" "$WAVDATA" >&2
+ else
+ false
+ fi ;;
+ debug) nice $READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
+ esac
+ RETURN=$?
+ if [ "$RETURN" != "0" ]; then
+ # Thank goodness errors is only machine-parseable up to the
+ # first colon, otherwise this woulda sucked
+ echo "readtrack-$FIRSTTRACKNUMBER: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
+ return $RETURN
+ else
+ echo readtrack-$FIRSTTRACKNUMBER >> "$ABCDETEMPDIR/status"
+ fi
+}
+
+# do_cdread [tracknumber]
+#
+do_cdread ()
+{
+ # The commands here don't go through run_command because they're never supposed to be silenced
+ # return codes need to be doublechecked anyway, however
+ UTRACKNUM=$1
+ CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
+ WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
+ OUTDATA="$ABCDETEMPDIR/track$UTRACKNUM.$OUTPUTTYPE"
+ if [ -r "$CDDBDATA" ]; then
+ TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
+ echo "Grabbing track $UTRACKNUM: $TRACKNAME..." >&2
+ else
+ echo "Grabbing track $UTRACKNUM..." >&2
+ fi
+ case "$CDROMREADERSYNTAX" in
+ cdparanoia) nice $READNICE $CDROMREADER -d $CDROM $UTRACKNUM "$WAVDATA" >&2 ;;
+ cdda2wav)
+ if [ "$OSFLAVOUR" = "OSX" ] ; then
+ # Hei, we have to unmount the device before running anything like cdda2wav in OSX
+ disktool -u ${CDROM#/dev/} 0
+ # Also, in OSX the cdrom device for cdda2wav changes...
+ CDDA2WAVCDROM="IODVDServices"
+ elif [ "$OSFLAVOUR" = "FBSD" ] ; then
+ CDDA2WAVCDROM="$CDROMID"
+ else
+ if [ "$CDROMID" = "" ]; then
+ CDDA2WAVCDROM="$CDROM"
+ else
+ CDDA2WAVCDROM="$CDROMID"
+ fi
+ fi
+ nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t $UTRACKNUM "$WAVDATA" >&2
+ ;;
+ dagrab) nice $READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
+ cddafs)
+ # Find the track's mounted path
+ REALTRACKNUM=$(expr $UTRACKNUM + 0)
+ FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \([^(]*\) (.*/\1/')
+ FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
+ # If the file exists, copy it
+ if [ -e "$FILEPATH" ] ; then
+ nice $READNICE $CDROMREADER "$FILEPATH" "$WAVDATA" >&2
+ else
+ false
+ fi ;;
+ debug) nice $READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
+ esac
+ RETURN=$?
+ if [ "$RETURN" != "0" ]; then
+ # Thank goodness errors is only machine-parseable up to the
+ # first colon, otherwise this woulda sucked
+ echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
+ return $RETURN
+ else
+ echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
+ fi
+}
+
+do_cdspeed ()
+{
+ if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
+ vecho "Setting CD speed to ${CDSPEEDVALUE}x"
+ else
+ echo "abcde: unable to set the device speed" >&2
+ fi
+}
+
+# vecho [message]
+#
+# vecho outputs a message if EXTRAVERBOSE is selected
+vecho ()
+{
+if [ x"$EXTRAVERBOSE" != "x" ]; then
+ echo $@
+fi
+}
+
+# Start of execution
+
+# Builtin defaults
+CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
+CDDBSUBMIT=freedb-submit@freedb.org
+CDDBPROTO=5
+HELLOINFO="$(whoami)@$(hostname)"
+INTERACTIVE=y
+CDROMREADERSYNTAX=cdparanoia
+OUTPUTTYPE=ogg
+ENCODERSYNTAX=default
+
+MP3ENCODERSYNTAX=default
+OGGENCODERSYNTAX=default
+FLACENCODERSYNTAX=default
+SPEEXENCODERSYNTAX=default
+
+OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
+# Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
+#VAOUTPUTFORMAT=${OUTPUTFORMAT}
+VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
+ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
+VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
+PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
+PLAYLISTDATAPREFIX=''
+VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
+VAPLAYLISTDATAPREFIX=''
+DOSPLAYLIST=n
+COMMENT=''
+ID3TAGV=2
+ENCNICE=10
+READNICE=10
+DISTMP3NICE=10
+VARIOUSARTISTS=n
+VARIOUSARTISTSTYLE=forward
+NORMALIZERSYNTAX=default
+KEEPWAVS=n
+PADTRACKS=n
+CDDBCOPYLOCAL="n"
+CDDBLOCALDIR="$HOME/.cddb"
+CDDBUSELOCAL="n"
+
+# If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
+# i.e. CDROMID="1,0,0"
+CDROMID=""
+
+# program paths - defaults to checking your $PATH
+# mp3
+LAME=lame
+GOGO=gogo
+BLADEENC=bladeenc
+L3ENC=l3enc
+XINGMP3ENC=xingmp3enc
+MP3ENC=mp3enc
+# ogg
+VORBIZE=vorbize
+OGGENC=oggenc
+# flac
+FLAC=flac
+# speex
+SPEEXENC=speexenc
+
+ID3=id3
+ID3V2=id3v2
+CDPARANOIA=cdparanoia
+CDDA2WAV=cdda2wav
+DAGRAB=dagrab
+CDDAFS=cp
+CDDISCID=cd-discid
+CDDBTOOL=cddb-tool
+EJECT=eject
+MD5SUM=md5sum
+DISTMP3=distmp3
+VORBISCOMMENT=vorbiscomment
+METAFLAC=metaflac
+NORMALIZE=normalize
+CDSPEED=eject
+
+# Options for programs called from abcde
+# mp3
+LAMEOPTS=
+GOGOOPTS=
+BLADEENCOPTS=
+L3ENCOPTS=
+XINGMP3ENCOPTS=
+MP3ENCOPTS=
+# ogg
+VORBIZEOPTS=
+OGGENCOPTS=
+# flac
+FLACOPTS=
+# speex
+SPEEXENCOPTS=
+
+ID3OPTS=
+ID3V2OPTS=
+CDPARANOIAOPTS=
+CDDA2WAVOPTS=
+DAGRABOPTS=
+CDDAFSOPTS="-f"
+CDDBTOOLOPTS=
+EJECTOPTS=
+DISTMP3OPTS=
+NORMALIZEOPTS=
+CDSPEEDOPTS="-x"
+CDSPEEDVALUE=
+
+# Default to one process if -j isn't specified
+MAXPROCS=1
+
+# List of actions to perform - by default, run to completion
+ACTIONS=cddb,read,encode,tag,move,clean
+
+# User-redefinable functions
+# Custom filename munging:
+mungefilename ()
+{
+ echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
+}
+
+# Pre-read execution:
+pre_read ()
+{
+:
+}
+
+# Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for Linux/OpenBSD/NetBSD.
+# Let's use these checkings to determine the OS flavour, which will be used later
+if [ X$(uname) = "XFreeBSD" ] ; then
+ HTTPGET=fetch
+ NEEDCDROMID=y
+ OSFLAVOUR=FBSD
+elif [ X$(uname) = "XDarwin" ] ; then
+ HTTPGET=curl
+ OSFLAVOUR=OSX
+ # We should have disktool in OSX, but let's be sure...
+ NEEDDISKTOOL=y
+elif [ X$(uname) = "XOpenBSD" ] ; then
+ HTTPGET=wget
+ MD5SUM=md5
+else
+ HTTPGET=wget
+fi
+
+# If CDDBAVAIL is set to n, no CDDB read is done
+# If USEID3 is set to n, no ID3 tagging is done
+CDDBAVAIL=y
+USEID3=y
+
+if [ -z "$OUTPUTDIR" ]; then
+ OUTPUTDIR=$(pwd)
+fi
+
+if [ -z "$WAVOUTPUTDIR" ]; then
+ WAVOUTPUTDIR="$OUTPUTDIR"
+fi
+
+# Load system defaults
+if [ -r /etc/abcde.conf ]; then
+ . /etc/abcde.conf
+fi
+# Load user preference defaults
+if [ -r $HOME/.abcde.conf ]; then
+ . $HOME/.abcde.conf
+fi
+
+# By this time, we need some HTTPGETOPTS already defined.
+# If the user has defined its own, we should not be empty.
+
+if [ "$HTTPGETOPTS" = "" ] ; then
+ case $HTTPGET in
+ wget) HTTPGETOPTS="-q -O -";;
+ curl) HTTPGETOPTS="-f -s";;
+ fetch)HTTPGETOPTS="-q -o -";;
+ *) echo "abcde warning: HTTPGET in non-standard and HTTPGETOPTS are not defined." >&2 ;;
+ esac
+fi
+
+# If the CDROM has not been set yet, find a suitable one.
+# If this is a devfs system, default to /dev/cdroms/cdrom0
+# instead of /dev/cdrom
+if [ "$CDROM" = "" ] ; then
+ if [ -e /dev/cdroms/cdrom0 ]; then
+ CDROM=/dev/cdroms/cdrom0
+ elif [ -e /dev/cdrom ]; then
+ CDROM=/dev/cdrom
+ elif [ -e /dev/cd0c ]; then
+ CDROM=/dev/cd0c
+ elif [ -e /dev/acd0c ]; then
+ CDROM=/dev/acd0c
+ elif [ -e /dev/disk1 ]; then
+ CDROM=/dev/disk1
+ fi
+fi
+
+# Parse command line options
+#while getopts 1a:bc:C:d:Dhj:klLnNo:pr:S:t:T:vVx opt ; do
+while getopts 1a:bc:C:d:Dhj:klLnNo:pr:S:vVx opt ; do
+ case "$opt" in
+ 1) ONETRACK=y ;;
+ a) ACTIONS="$OPTARG" ;;
+ b) BATCH=y ;;
+ c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else echo "abcde error: config file \"$OPTARG\" cannot be found." >&2 ; exit 1 ; fi ;;
+ C) DISCID="${OPTARG#abcde.}" ;;
+ d) CDROM="$OPTARG" ;;
+ D) set -x ;;
+ h) usage; exit ;;
+ f) FORCECDDBUSELOCAL=y ;;
+ i) INLINETAG=y ;;
+ j) MAXPROCS="$OPTARG" ;;
+ k) KEEPWAVS=y ;;
+ l) LOWDISK=y ;;
+ L) CDDBUSELOCAL="y" ;;
+ n) CDDBAVAIL="n" ;;
+ N) INTERACTIVE="n" ;;
+ m) DOSPLAYLIST=y ;;
+ o) OUTPUTTYPE="$OPTARG" ;;
+ p) PADTRACKS="y" ;;
+ r) REMOTEHOSTS="$OPTARG" ;;
+ s) STARTTRACKNUMBER="$OPTARG" ;;
+ S) CDSPEEDVALUE="$OPTARG" ;;
+ t) PREPROCESSFORMATS="$OPTARG"
+ PREPROCESS=y ;;
+ T) POSTPROCESSFORMATS="$OPTARG" ;;
+ v)
+ echo "This is abcde v$VERSION."
+ echo "Usage: abcde [options] [tracks]"
+ echo "abcde -h for extra help"
+ exit
+ ;;
+ V) EXTRAVERBOSE="y" ;;
+ x) EJECTCD="y" ;;
+ ?) usage; exit ;;
+ esac
+done
+
+shift $(($OPTIND - 1))
+
+if [ "$ONETRACK" = "y" ] ; then
+ if [ $# -gt 0 ]; then
+ vecho "ONETRACK mode selected: grabbing all tracks..."
+ fi
+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")
+
+ shift
+ done
+fi
+
+# At this point a CDROM has to be defined, so we check it exists.
+if [ "$CDROM" != "" ] ; then
+ if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
+ if [ "$OSFLAVOUR" = "FBSD" ]; then
+ if ! echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then
+ echo "abcde error: CDROMID not in the right format for $CDROMREADERSYNTAX"
+ echo "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
+ exit 1
+ fi
+ fi
+ elif [ ! -e $CDROM ] ; then
+ echo "abcde error: CDROM device cannot be found." >&2
+ exit 1
+ fi
+else
+ echo "abcde error: CDROM has not been defined or cannot be found" >&2
+ exit 1
+fi
+
+# Decide if we can continue. TO_REMOVE as soon as we find out about dagrab
+if [ "$ONETRACK" = "y" ]; then
+ case "$CDROMREADERSYNTAX" in
+ dagrab|debug) echo "abcde error: ONETRACK reading is not suported with "$CDROMREADERSYNTAX" yet"
+ exit 1 ;;
+ esac
+ if [ "$BATCH" = "y" ]; then
+ echo "abcde error: BATCH mode is not compatible with ONETRACK mode"
+ fi
+fi
+
+# Decide which CDROM reader we're gonna use
+case "$CDROMREADERSYNTAX" in
+ cdparanoia|debug)
+ CDROMREADER="$CDPARANOIA"
+ CDROMREADEROPTS="$CDPARANOIAOPTS"
+ ;;
+ cdda2wav)
+ CDROMREADER="$CDDA2WAV"
+ CDROMREADEROPTS="$CDDA2WAVOPTS"
+ ;;
+ dagrab)
+ CDROMREADER="$DAGRAB"
+ CDROMREADEROPTS="$DAGRABOPTS"
+ ;;
+ cddafs)
+ CDROMREADER="$CDDAFS"
+ CDROMREADEROPTS="$CDDAFSOPTS"
+ ;;
+esac
+
+# There's only one normalize...
+case "$NORMALIZERSYNTAX" in
+ default|normalize)
+ NORMALIZER="$NORMALIZE"
+ NORMALIZEROPTS="$NORMALIZEOPTS"
+ ;;
+esac
+
+# If nothing has been specified, use oggenc for oggs and lame for mp3s and flac for flacs and speexenc for speex
+
+# Getting ready for multiple output changes
+for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
+do
+ case $OUTPUT in
+ ogg) [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
+ echo $ACTIONS | grep tag > /dev/null 2>&1 && NEEDCOMMENTER=y
+ ;;
+ mp3) [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
+ echo $ACTIONS | grep tag > /dev/null 2>&1 && NEEDTAGGER=y
+ ;;
+ flac) [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
+ echo $ACTIONS | grep tag > /dev/null 2>&1 && NEEDMETAFLAC=y
+ ;;
+ spx) [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc ;;
+ *) echo "abcde error: Invalid OUTPUTTYPE defined" >&2
+ exit 1
+ ;;
+ esac
+done
+
+# decide which encoder
+case "$MP3ENCODERSYNTAX" in
+ lame)
+ MP3ENCODEROPTS="$LAMEOPTS"
+ MP3ENCODER="$LAME"
+ ;;
+ gogo)
+ MP3ENCODEROPTS="$GOGOOPTS"
+ MP3ENCODER="$GOGO"
+ ;;
+ bladeenc)
+ MP3ENCODEROPTS="$BLADEENCOPTS"
+ MP3ENCODER="$BLADEENC"
+ ;;
+ l3enc)
+ MP3ENCODEROPTS="$L3ENCOPTS"
+ MP3ENCODER="$L3ENC"
+ ;;
+ xingmp3enc)
+ MP3ENCODEROPTS="$XINGMP3ENCOPTS"
+ MP3ENCODER="$XINGMP3ENC"
+ ;;
+ mp3enc)
+ MP3ENCODEROPTS="$MP3ENCOPTS"
+ MP3ENCODER="$MP3ENC"
+ ;;
+esac
+case "$OGGENCODERSYNTAX" in
+ vorbize)
+ OGGENCODEROPTS="$VORBIZEOPTS"
+ OGGENCODER="$VORBIZE"
+ ;;
+ oggenc)
+ OGGENCODEROPTS="$OGGENCOPTS"
+ OGGENCODER="$OGGENC"
+ ;;
+esac
+case "$FLACENCODERSYNTAX" in
+ flac)
+ FLACENCODEROPTS="$FLACOPTS"
+ FLACENCODER="$FLAC"
+ ;;
+esac
+case "$SPEEXENCODERSYNTAX" in
+ speexenc)
+ SPEEXENCODEROPTS="$SPEEXENCOPTS"
+ SPEEXENCODER="$SPEEXENC"
+ ;;
+esac
+
+# and which tagger
+
+if [ "$ID3TAGV" = "1" ]; then
+ TAGGER="$ID3"
+ TAGGEROPTS="$ID3OPTS"
+else
+ TAGGER="$ID3V2"
+ TAGGEROPTS="$ID3V2OPTS"
+fi
+
+# Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
+
+if [ "$ENCNICE" ]; then
+ ENCNICE="-n $ENCNICE"
+fi
+if [ "$READNICE" ]; then
+ READNICE="-n $READNICE"
+fi
+if [ "$DISTMP3NICE" ]; then
+ DISTMP3NICE="-n $DISTMP3NICE"
+fi
+
+# Don't check for stuff if it's not needed
+if [ "$REMOTEHOSTS" ]; then NEEDDISTMP3=y; fi
+if echo $ACTIONS | grep normalize > /dev/null 2>&1 ; then NEEDNORMALIZER=y; fi
+if [ "$EJECTCD" = "y" ]; then NEEDEJECT=y; fi
+if echo $ACTIONS | grep cddb > /dev/null 2>&1 ; then NEEDHTTPGET=y ; fi
+
+if [ X"$CDSPEEDVALUE" != "X" ]; then
+ case "$CDROMREADERSYNTAX" in
+ cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
+ *) NEEDCDSPEED=y ;;
+ esac
+fi
+
+
+# Make sure a buncha things exist
+for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
+ $OGGENCODER $FLACENCODER $SPEEXENCODER ${NEEDHTTPGET+$HTTPGET} \
+ ${NEEDDISTMP3+$DISTMP3} ${NEEDCOMMENTER+$VORBISCOMMENT} \
+ ${NEEDMETAFLAC+$METAFLAC} ${NEEDNORMALIZER+$NORMALIZER} \
+ ${NEEDEJECT+$EJECT} ${NEEDDISKTOOL+disktool} \
+ ${NEEDCDSPEED+$CDSPEED}
+do
+ # Cut off the command-line options we just added in
+ X=$(echo $X | cut -d' ' -f2)
+ if [ "$(which $X)" = "" ]; then
+ echo "abcde error: $X is not in your path." >&2
+ exit 1
+ elif [ ! -x $(which $X) ]; then
+ echo "abcde error: $X is not executable." >&2
+ exit 1
+ fi
+done
+
+CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
+CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
+HTTPGET="$HTTPGET $HTTPGETOPTS"
+
+# One thousand seven hundred lines in, we can start doing stuff with things
+
+# List of valid actions: cddb,playlist,read,normalize,encode,tag,move
+
+# Export needed things so they can be read in this subshell
+export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
+export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
+
+# User-definable function to set some things. Use it for
+# - closing the CD tray with eject -t
+# - set the CD speed value with eject -x
+vecho -n "Executing customizable pre-read function... "
+
+pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
+
+vecho "done."
+
+do_discid # Get ABCDETEMPDIR created and status file initialized
+
+if [ "$DOCDDB" = "y" ]; then
+ if [ $CDDBUSELOCAL = "y" ]; then
+ do_localcddb
+ fi
+ if [ ! "$CDDBLOCALSUCCESS" = "y" ] ; then
+ do_cddbstat
+ do_cddbquery
+ do_cddbread
+ fi
+ do_cddbedit
+
+ eval $($CDDBTOOL parse "$CDDBDATA")
+fi
+
+# Before reading tracks, we set the speed of the device
+
+if [ X"$CDSPEEDVALUE" != "X" ]; then
+ case "$CDROMREADERSYNTAX" in
+ cdparanoia|debug) : ;;
+ *) do_cdspeed ;;
+ esac
+fi
+
+# Create playlist if needed (backgroundable) and start reading in tracks
+
+(
+if [ "$ONETRACK" = "y" ]; then :; else
+ if [ "$DOPLAYLIST" = "y" ]; then
+ echo Creating playlist... >&2
+ do_playlist
+ fi
+fi
+
+# For the lowdisk option, only one program is running at once so the encoder
+# can be unsilenced right away.
+if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
+ echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
+fi
+
+if [ "$ONETRACK" = "y" ]; then
+ FIRSTTRACK=$( echo $TRACKQUEUE | awk '{print $1}' )
+ TRACKS="$FIRSTTRACK"
+ for UTRACKNUM in $TRACKQUEUE; do :;done
+ if checkstatus readtrack-$FIRSTTRACK; then :; else
+ do_cdread_one $UTRACKNUM $FIRSTTRACK
+ fi
+else
+ for UTRACKNUM in $TRACKQUEUE
+ do
+ if [ "$DOREAD" = "y" ]; then
+ if checkstatus readtrack-$UTRACKNUM; then :; else
+ do_cdread $UTRACKNUM
+ if [ "$?" != "0" ]; then
+ # CD read failed - don't give the goahead to
+ # the encoder
+ echo NO
+ exit
+ fi
+ fi
+ fi
+ if [ "$BATCH" = "y" ]; then
+ :
+ else
+ echo NEXTTRACK # Get the encoder machine churning again
+ if [ "$DOREAD" = "y" ]; then
+ if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
+ until checkstatus encodetrack-$UTRACKNUM
+ do
+ if checkerrors encodetrack-$UTRACKNUM; then
+ break
+ fi
+ sleep 2
+ done
+ fi
+ fi
+ fi
+ done
+fi
+
+# Now that we're done the encoding can be loud again -
+# if we're not using SMP.
+if [ "$MAXPROCS" = "1" ]; then
+ echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
+fi
+
+# All tracks read, start encoding.
+if [ "$BATCH" = "y" ] || [ "$ONETRACK" = "y" ]; then
+ echo NEXTTRACK
+fi
+
+# We are now finished with the cdrom - it can be safely ejected. Note that
+# abcde will not have completed yet.
+if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
+ # We check if the disk we are processing is actually the disk inside the
+ # CD tray. If not, we do not eject the CD, since it might be so that the
+ # user ejected it manually.
+ #CURRENTTRACKINFO=$($CDDISCID $CDROM)
+ #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
+ # More FreeBSD bits.
+ if [ X"$(uname)" = X"FreeBSD" ] ; then
+ # FreeBSD eject uses the EJECT environment variable to name the CDROM
+ # but in this script EJECT is in the envionment and names the program
+ eject=$EJECT
+ unset EJECT
+ # The FreeBSD eject needs "adc0" not "/dev/adc0c"
+ cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
+ $eject $EJECTOPTS $cd
+ elif [ X"$(uname)" = X"Darwin" ] ; then
+ disktool -e ${CDROM#/dev/} 0
+ else
+ $EJECT $EJECTOPTS $CDROM
+ fi
+ #fi
+fi
+
+) | (
+
+# In batch mode, we want all tracks to be read first.
+if [ "$BATCH" = "y" ]; then
+ read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
+ if [ "$GOAHEAD" = "NO" ]; then break; fi
+ for LASTTRACK in $TRACKQUEUE; do :; done
+ if checkstatus readtrack-$LASTTRACK; then
+ if [ "$DONORMALIZE" = "y" ]; then
+ if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
+ if checkerrors batch-normalize; then exit; fi
+ fi
+ if [ "$DOENCODE" = "y" ]; then
+ if checkstatus encodetrack-$LASTTRACK; then :; else do_batch_encode; fi
+ if checkerrors batch-encode; then exit; fi
+ fi
+ fi
+fi
+
+# If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
+if [ "$ONETRACK" = "y" ] ; then
+ FIRSTTRACK=$( echo $TRACKQUEUE | awk '{print $1}')
+ TRACKQUEUE=$FIRSTTRACK
+ TRACKS="$FIRSTTRACK"
+fi
+
+# Do the encoding, including parallelization of remote encoding
+# Figure out where each track is going to be encoded
+ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
+if [ "$MAXPROCS" != "0" ]; then
+ for NUM in $(f_seq_row 1 "$MAXPROCS")
+ do
+ ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
+ done
+fi
+# Strip whitespace
+ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
+for UTRACKNUM in $TRACKQUEUE
+do
+ # Wait for our cue
+ read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
+ if [ "$GOAHEAD" = "NO" ]; then break; fi
+ # find out where this track is to be encoded
+ if [ "$DOENCODE" = "y" ]; then
+ # Make sure we have a place to encode this, if not, exit stage right
+ if [ -z "$ENCODELOCATIONS" ]; then
+ continue
+ fi
+ PROCEED=
+ until [ $PROCEED ]
+ do
+ for LOCATION in $ENCODELOCATIONS
+ do
+ PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
+ # check first if a track has ever been assigned to this location
+ if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
+ # If it errored out, rebuild $ENCODELOCATIONS without this location in it
+ if checkerrors encodetrack-$PREVIOUSTRACK; then
+ for TEMPLOCATION in $ENCODELOCATIONS
+ do
+ if [ "$TEMPLOCATION" != "$LOCATION" ]; then
+ TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
+ fi
+ done
+ ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
+ ABORT=y
+ PROCEED=y
+ break
+ fi
+ # We're still here, this location must have been previously assigned,
+ # and last completed without error - check if it's done with the
+ # previous track yet
+ if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
+ done
+ # all locations are working, wait and try again later
+ if [ ! $PROCEED ]; then sleep 3; fi
+ done
+ # Record the location we're about to encode the next track at
+ echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
+ fi
+ # Don't proceed with the rest of the loop if we can't encode
+ if [ "$ABORT" ]; then continue; fi
+ # Set TRACKNUM, TRACKNAME
+ if [ -e "$CDDBDATA" ]; then
+ if [ "$ONETRACK" = "y" ]; then
+ TRACKNAME="$DALBUM"
+ TRACKNUM="$FIRSTTRACK"
+ splitvarious
+ else
+# TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${UTRACKNUM} + 0))
+ TRACKNUM=$UTRACKNUM
+ CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
+ TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
+ splitvarious
+ fi
+ fi
+ # You can't encode a file which needs to be normalized before finishing
+ # You can't tag a file before it's finished encoding -
+ # thus all of this is backgrounded together
+ (
+ if [ "$DONORMALIZE" = "y" ]; then
+ if checkstatus readtrack-$UTRACKNUM; then
+ if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
+ fi
+ fi
+ if [ "$DOENCODE" = "y" ]; then
+ if checkstatus readtrack-$UTRACKNUM; then
+ #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
+ if [ "$DONORMALIZE" = "y" ]; then
+ if checkstatus normalizetrack-$UTRACKNUM; then
+ if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
+ fi
+ else
+ if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
+ fi
+ fi
+ fi
+ if [ "$DOTAG" = "y" ]; then
+ if checkstatus encodetrack-$UTRACKNUM; then
+ if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
+ fi
+ fi
+ if [ "$DOMOVE" = "y" ]; then
+ if checkstatus tagtrack-$UTRACKNUM; then
+ if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
+ fi
+ fi
+ ) &
+done
+# Go through it again and make sure there's no distmp3 stragglers, otherwise
+# we'll delete the files they're working on
+if [ "$DOENCODE" = "y" ]; then
+ PROCEED=
+ until [ $PROCEED ]
+ do
+ PROCEED=y
+ for LOCATION in $ENCODELOCATIONS
+ do
+ CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
+ # "How can he give us a status update, if he's DEAD?"
+ if checkstatus encodetrack-$CHECKTRACK; then
+ continue
+ fi
+ # Nothing to see here please go quietly back to your homes
+ if [ -z "$CHECKTRACK" ]; then continue; fi
+ # You're still here? Maybe there is something...
+ if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
+ done
+ # hold up
+ if [ ! $PROCEED ]; then sleep 5; fi
+ done
+fi
+# If the above didn't catch the stragglers, this will
+wait
+# Check to see if run_command logged any errors
+if [ -f "$ABCDETEMPDIR/errors" ]; then
+ echo "The following commands failed to run:"
+ cat "$ABCDETEMPDIR/errors"
+ # Don't clean up
+ DOCLEAN=n
+fi
+if [ "$KEEPWAVS" = "y" ];then
+ # Don't clean up
+ DOCLEAN=n
+fi
+if [ "$DOCLEAN" = "y" ]; then
+ # Wipe all the evidence
+ # Gimme gimme gimme some more time!
+ sleep 5
+ rm -rf "$ABCDETEMPDIR"
+ echo "Finished."
+else
+ echo "Finished. Not cleaning $ABCDETEMPDIR."
+fi
+)
+exit 0