abcde.conf
[abcde.git] / abcde
1 #!/bin/sh
2 # Copyright (c) 1998-2001 Robert Woodcock <rcw@debian.org>
3 # Copyright (c) 2003-2004 Jesus Climent <jesus.climent@hispalinux.es>
4 # This code is hereby licensed for public consumption under either the
5 # GNU GPL v2 or greater, or Larry Wall's Artistic license - your choice.
6 #
7 # You should have received a copy of the GNU General Public License
8 # along with this program; if not, write to the Free Software
9 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
10 #
11 # Copyright for this work is to expire January 1, 2010, after which it
12 # shall be public domain.
13
14 VERSION="2.1pre2.2.0"
15
16 usage ()
17 {
18 echo "This is abcde v$VERSION."
19 echo "Usage: abcde [options] [tracks]"
20 echo "Options:"
21 echo "-1    Encode the whole CD in a single file"
22 echo "-a    Actions to perform (cddb,read,normalize,encode,tag,move,playlist,clean)"
23 echo "-A    Experimental actions (retag, transcode)"
24 echo "-b    Batch mode: enable album normalization and nogap encoding"
25 echo "-c    Specify a configuration file (overrides system and user config files)"
26 echo "-C    Specify discid to resume from (only needed if you no longer have the cd)"
27 echo "-d    Specify CDROM device to grab"
28 echo "-D    Debugging mode (equivalent to sh -x abcde)"
29 echo "-h    This help information"
30 #echo "-i    Tag files while encoding, when possible (local only) -NWY-"
31 echo "-j    Number of encoder processes to run at once"
32 echo "-k    Keep the wav tracks for later use"
33 echo "-l    Use low disk space algorithm"
34 echo "-L    Use local CDDB storage directory"
35 echo "-n    No lookup. Don't query CDDB, just create and use template"
36 echo "-N    Noninteractive. Never prompt for anything"
37 echo "-m    Modify playlist to include CRLF endings, to comply with some players"
38 echo "-o    Output file type(s) (ogg,mp3,flac,spx,mpc). Defaults to ogg"
39 echo "-p    Pad track numbers with 0's (if less than 10 tracks)"
40 #echo "-P    Use UNIX pipes to read+encode without wav files"
41 echo "-r    [host1,host2...] Also encode on these remote hosts"
42 echo "-R    Add replaygain values to the tag info (only for ogg,flac)"
43 echo "-s    Start the track numbering at a given number [DEPRECATED: use -t]"
44 echo "-S    Set the CD speed"
45 #echo "-t    File types to preprocess (wav)"
46 #echo "-T    Set postprocessing options"
47 echo "-t    Start the track numbering at a given number"
48 echo "-T    Start the track numbering at a given number, modifying tag numbering"
49 echo "-v    Show version number and exit"
50 echo "-V    Be a bit more verbose about what is happening behind the scenes"
51 echo "-x    Eject CD after all tracks are read"
52 echo "-w    [comment] Add a comment to the CD tracks"
53 echo "Tracks is a space-delimited list of tracks to grab."
54 echo "Ranges specified with hyphens are allowed."
55 }
56
57 # Funtions to replace the need of seq, which is too distribution dependant.
58 f_seq_row ()
59 {
60         i=$1
61         while [ $i -ne `expr $2 + 1` ]
62         do
63                 echo $i
64                 i=`expr $i + 1`
65         done
66 }
67
68 f_seq_line ()
69 {
70         i=$1
71         while [ $i -ne `expr $2 + 1` ]
72         do
73                 printf $i" "
74                 i=`expr $i + 1`
75         done
76         echo
77 }
78
79 # checkstatus [blurb]
80 # Returns "0" if the blurb was found, returns 1 if it wasn't
81 # Puts the blurb content, if available, on stdout.
82 # Otherwise, returns "".
83 checkstatus ()
84 {
85         # Take the last line in the status file if there's multiple matches
86         PATTERN="^$1(=.*)?$"
87         BLURB=$(egrep $PATTERN "$ABCDETEMPDIR/status" | tail -n 1)
88
89         if [ -z "$BLURB" ]; then
90                 # No matches found
91                 return 1
92         else
93                 # Matches found
94                 # See if there's a = in it
95                 if [ "$(echo $BLURB | grep -c =)" != "0" ]; then
96                         echo "$(echo $BLURB | cut -f2- -d=)"
97                 fi
98                 return 0
99         fi
100 }
101
102 # checkerrors [blurb]
103 # Returns "0" if the blurb was found (meaning there was an error),
104 # returns 1 if it wasn't (yes this is a little backwards).
105 # Does not print the blurb on stdout.
106 # Otherwise, returns "".
107 checkerrors ()
108 {
109         if [ -e "$ABCDETEMPDIR/errors" ]; then :; else
110                 return 1
111         fi
112         # Take the last line in the status file if there's multiple matches
113         PATTERN="^$1(:.*)?$"
114         BLURB="$(egrep $PATTERN $ABCDETEMPDIR/errors | tail -n 1)"
115
116         if [ -z "$BLURB" ]; then
117                 # negative, we did not have a negative...
118                 return 1
119         else
120                 # affirmative, we had a negative...
121                 return 0
122         fi
123 }
124
125 # run_command [blurb] [command...]
126 # Runs a command, silently if necessary, and updates the status file
127 run_command ()
128 {
129         BLURB="$1"
130         shift
131         # See if this is supposed to be silent
132         if [ "$(checkstatus encode-output)" = "loud" ]; then
133                 "$@" >&2
134                 RETURN=$?
135         else
136                 # Special case for SMP, since
137                 # encoder output is never displayed, don't mute echos
138                 if [ -z "$BLURB" -a "$MAXPROCS" != "1" ]; then
139                         "$@" >&2
140                         RETURN=$?
141                 else
142                         "$@" >/dev/null 2>&1
143                         RETURN=$?
144                 fi
145         fi
146         case "$1" in
147         normalize)
148                 if [ "$RETURN" = "2" ]; then
149                         # File was already normalized.
150                         RETURN=0
151                 fi
152                 ;;
153         esac
154         if [ "$RETURN" != "0" ]; then
155                 # Put an error in the errors file. For various reasons we
156                 # can't capture a copy of the program's output but we can
157                 # log what we attempted to execute and the error code
158                 # returned by the program.
159                 if [ "$BLURB" ]; then
160                         TWEAK="$BLURB: "
161                 fi
162                 echo "${TWEAK}returned code $RETURN: $@" >> "$ABCDETEMPDIR/errors"
163                 return $RETURN # Do not pass go, do not update the status file
164         fi
165         if [ "$BLURB" ]; then
166                 echo $BLURB >> "$ABCDETEMPDIR/status"
167         fi
168 }
169
170 # relpath() and slash() are Copyright (c) 1999 Stuart Ballard and
171 # distributed under the terms of the GNU GPL v2 or later, at your option
172
173 # Function to determine if a word contains a slash.
174 slash ()
175 {
176         case "$1" in
177         */*) return 0;;
178         *) return 1;;
179         esac
180 }
181
182 # Function to give the relative path from one file to another.
183 # Usage: relpath fromfile tofile
184 # eg relpath music/Artist/Album.m3u music/Artist/Album/Song.mp3
185 # (the result would be Album/Song.mp3)
186 # Output is relative path to $2 from $1 on stdout
187
188 # This code has the following restrictions:
189 # Multiple ////s are not collapsed into single /s, with strange effects.
190 # Absolute paths and ../s are handled wrong in FR (but they work in TO)
191 # If FR is a directory it must have a trailing /
192
193 relpath ()
194 {
195         FR="$1"
196         TO="$2"
197
198         case "$TO" in
199         /*) ;; # No processing is needed for absolute paths
200         *)
201                 # Loop through common prefixes, ignoring them.
202                 while slash "$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
203                 do
204                         FR="$(echo "$FR" | cut -d/ -f2-)"
205                         TO="$(echo "$TO" | cut -d/ -f2-)"
206                 done
207                 # Loop through directory portions left in FR, adding appropriate ../s.
208                 while slash "$FR"
209                 do
210                         FR="$(echo "$FR" | cut -d/ -f2-)"
211                         TO="../$TO"
212                 done
213         esac
214
215         echo $TO
216 }
217
218 # This code splits the a Various Artist track name from one of the following
219 # forms:
220 #
221 #  forward:        Artist / Track
222 #  forward-dash:   Artist - Track
223 #  reverse:        Track / Artist
224 #  reverse-dash:   Track - Artist
225 #  colon:          Artist: Track
226 #  trailing-paren: Artist (Track)
227 #
228 # variables used:
229 # VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
230 splitvarious ()
231 {
232         if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
233                 case "$VARIOUSARTISTSTYLE" in
234                 forward)
235                         DTITLEARTIST="$(echo $TRACKNAME | sed 's- / -~-g')"
236                         TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
237                         TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
238                         ;;
239                 forward-dash)
240                         DTITLEARTIST="$(echo $TRACKNAME | sed 's, - ,~,g')"
241                         TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
242                         TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
243                         ;;
244                 reverse)
245                         DTITLEARTIST="$(echo $TRACKNAME | sed 's- / -~-g')"
246                         TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
247                         TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
248                         ;;
249                 reverse-dash)
250                         DTITLEARTIST="$(echo $TRACKNAME | sed 's, - ,~,g')"
251                         TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
252                         TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
253                         ;;
254                 colon)
255                         DTITLEARTIST="$(echo $TRACKNAME | sed 's-: -~-g')"
256                         TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
257                         TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
258                         ;;
259                 trailing-paren)
260                         DTITLEARTIST="$(echo $TRACKNAME | sed 's,^\(.*\) (\(.*\)),\1~\2,')"
261                         TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
262                         TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
263                         ;;
264                 esac
265         elif [ "$ONETRACK" = "y" ]; then
266                 TRACKARTIST="Various"
267         else
268                 TRACKARTIST=$DARTIST
269         fi
270 }
271
272 # do_tag [tracknumber]
273 # id3 tags a filename
274 # variables used:
275 # TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC, 
276 # COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE (and temporarily) ID3TAGV
277 do_tag ()
278 {
279         COMMENTOUTPUT="$(eval echo ${COMMENT})"
280         run_command '' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
281         # If we want to start the tracks with a given number, we need to modify the
282         # TRACKNUM value before evaluation
283         if [ -n "$STARTTRACKNUMBER" -a -n "$STARTTRACKNUMBERTAG" ] ; then
284                 # Get the trackpadding from the current track
285                 CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
286                 TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - 1 ))
287         fi
288         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
289         do
290         case "$OUTPUT" in
291         mp3)
292                 # id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
293                 run_command tagtrack-$1 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
294                         -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" \
295                         -g "$CDGENRE" -T "$1/$TRACKS" "$ABCDETEMPDIR/track$1.$OUTPUT"
296                 ;;
297         ogg)
298                 case "$OGGENCODERSYNTAX" in
299                         vorbize|oggenc)
300                                 # vorbiscomment can't do in-place modification, mv the file first
301                                 if [ -f "$ABCDETEMPDIR/track$1.$OUTPUT" -a ! -f "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" ]; then
302                                         mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT"
303                                 fi
304                                 (
305                                 # These are from http://www.xiph.org/ogg/vorbis/doc/v-comment.html
306                                 echo ARTIST=$TRACKARTIST
307                                 echo ALBUM="$DALBUM"
308                                 echo TITLE=$TRACKNAME
309                                 if [ -n "$CDYEAR" ]; then
310                                         echo DATE="$CDYEAR"
311                                 fi
312                                 if [ -n "$CDGENRE" ]; then
313                                         echo GENRE="$CDGENRE"
314                                 fi      
315                                 echo TRACKNUMBER=$1
316                                 echo CDDB=$CDDBDISCID
317                                 if [ "$(eval echo ${COMMENT})" != "" ]; then
318                                         case "$COMMENTOUTPUT" in
319                                                 *=*) echo "$COMMENTOUTPUT";;
320                                                 *)   echo COMMENT="$COMMENTOUTPUT";;
321                                         esac    
322                                 fi
323                                 ) | run_command tagtrack-$1 $VORBISCOMMENT -w \
324                                         "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" "$ABCDETEMPDIR/track$1.$OUTPUT"
325                                 # Doublecheck that the commented file was created successfully before wiping the original
326                                 if [ -f "$ABCDETEMPDIR/track$1.$OUTPUT" ]; then
327                                         rm -f "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT"
328                                 else
329                                         mv "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" "$ABCDETEMPDIR/track$1.$OUTPUT"
330                                 fi
331                                 ;;
332                 esac
333                 ;;
334         flac)
335                 (
336                 echo ARTIST="$TRACKARTIST"
337                 echo ALBUM="$DALBUM"
338                 echo TITLE="$TRACKNAME"
339                 if [ -n "$CDYEAR" ]; then
340                         echo DATE="$CDYEAR"
341                 fi
342                 if [ -n "$CDGENRE" ]; then
343                         echo GENRE="$CDGENRE"
344                 fi      
345                 echo TRACKNUMBER=${TRACKNUM:-$1}
346                 echo CDDB=$CDDBDISCID
347                 if [ "$(eval echo ${COMMENT})" != "" ]; then
348                         case "$COMMENTOUTPUT" in
349                                 *=*) echo "$COMMENTOUTPUT";;
350                                 *)   echo COMMENT="$COMMENTOUTPUT";;
351                         esac    
352                 fi
353                 ) | run_command tagtrack-$1 $METAFLAC --import-vc-from=- --no-utf8-convert "$ABCDETEMPDIR/track$1.$OUTPUT"
354                 ;;
355         spx)
356                 run_command tagtrack-$1 true
357                 ;;
358         mpc)
359                 run_command tagtrack-$1 true
360                 ;;
361         esac
362         done
363 }
364
365 # do_batch_encode
366 # variables used:
367 # OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
368 do_batch_encode ()
369 {
370         # The commands here don't go through run_command because they're never supposed to be silenced
371         echo "Batch encoding tracks: $TRACKQUEUE"
372         OUTPUT=$(echo $OUTPUTTYPE | grep "mp3" )
373         case "$OUTPUT" in
374         mp3)
375                 case "$MP3ENCODERSYNTAX" in
376                 lame)
377                         (
378                         cd "$ABCDETEMPDIR"
379                         TRACKFILES=
380                         for UTRACKNUM in $TRACKQUEUE
381                         do
382                                 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
383                         done
384                         nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS --nogap $TRACKFILES
385                         RETURN=$?
386                         if [ "$RETURN" != "0" ]; then
387                                 echo "batch-encode: $ENCODER returned code $RETURN" >> errors
388                         else
389                                 for UTRACKNUM in $TRACKQUEUE
390                                 do
391                                         echo encodetrack-$UTRACKNUM >> status
392                                 done
393                         fi
394                         )
395                         ;;
396                 esac
397                 ;;
398         esac
399         # Other encoders fall through to normal encoding as the tracks
400         # have not been entered in the status file.
401 }
402
403 # do_encode [tracknumber] [hostname]
404 # If no hostname is specified, encode locally
405 # variables used:
406 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
407 do_encode ()
408 {
409         IN="$ABCDETEMPDIR/track$1.wav"
410         # We need IN to proceed.
411         if [ -s "$IN" ] ; then
412                 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
413                 do
414                         OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
415                         echo "Encoding track $1 of $TRACKS: $TRACKNAME..." >&2
416                         case "$OUTPUT" in
417                         mp3)
418                                 case "$2" in
419                                 %local*%)
420                                         case "$MP3ENCODERSYNTAX" in
421                                         lame|gogo) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
422                                         bladeenc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" ;;
423                                         l3enc|xingmp3enc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
424                                         mp3enc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
425                                         esac
426                                         ;;
427                                 *)
428                                         run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
429                                         ;;
430                                 esac
431                                 ;;
432                         ogg)
433                                 case "$2" in
434                                 %local*%)
435                                         case "$OGGENCODERSYNTAX" in
436                                         vorbize) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
437                                         oggenc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
438                                         esac
439                                         ;;
440                                 *)
441                                         run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
442                                         ;;
443                                 esac
444                                 ;;
445                         flac)
446                                 case "$2" in
447                                 %local*%)
448                                         case "$FLACENCODERSYNTAX" in
449                                         flac) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $FLACENCODER  $FLACENCODEROPTS -o "$OUT" "$IN" ;; 
450                                         esac
451                                         ;;
452         
453                                 *)
454                                         echo -n "DISTMP3:"
455                                         echo "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
456                                         run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
457                                         ;;
458                                 esac
459                                 ;;
460                         spx)
461                                 if [ "$(eval echo ${COMMENT})" != "" ]; then
462                                         case "$COMMENT" in
463                                                 *=*) ;;
464                                                 *)   COMMENT="COMMENT=$COMMENT" ;;
465                                         esac    
466                                         COMMENT="--comment \"$COMMENT\""
467                                 fi
468                                 # Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
469                                 if [ ! "$DOTAG" = "y" ]; then
470                                         run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" "$COMMENT" "$IN" "$OUT"
471                                 else
472                                         run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
473                                 fi
474                                 ;;
475                         mpc)    
476                                 # MPP/MP+(Musepack) format (.mpc) is done locally, with inline
477                                 # tagging.
478                                 # I tried compiling the mppenc from corecodecs.org and got some
479                                 # errors, so I have not tried it myself.
480                                 ## FIXME ## Needs some cleanup to determine if an empty tag sent
481                                 ## FIXME ## to the encoder ends up empty.
482                                 run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MPPENCODER $MPPENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" "$IN" "$OUT"
483                                 ;;
484                         esac
485                 done
486                 # Only remove .wav if the encoding succeeded
487                 if checkerrors "encodetrack-(.{3,4})-$1"; then 
488                         run_command encodetrack-$1 false
489                 else
490                         run_command encodetrack-$1 true
491                         if [ ! "$KEEPWAVS" = "y" ] ; then
492                                 rm -f "$IN"
493                         fi
494                 fi
495         else
496                 if [ "$(checkstatus encode-output)" = "loud" ]; then
497                         echo "HEH! The file we were about to encode disappeared:"
498                         echo ">> $IN"
499                 fi
500                 run_command encodetrack-$1 false
501         fi
502 }
503
504 # do_preprocess [tracknumber]
505 # variables used:
506 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
507 #do_preprocess ()
508 #{
509 #       IN="$ABCDETEMPDIR/track$1.wav"
510 #       # We need IN to proceed.
511 #       if [ -s "$IN" ] ; then
512 #               for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
513 #               do
514 #                       #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
515 #                       run_command '' echo "Pre-processing track $1 of $TRACKS..."
516 #                       case "$POSTPROCESSFORMAT" in
517 #                       all|wav*)
518 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $WAV_PRE $IF $OF ;;
519 #                       mp3)
520 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $MP3_PRE $IF $OF ;;
521 #                       ogg)
522 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $OGG_PRE $IF $OF ;;
523 #                       flac)
524 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $FLAC_PRE $IF $OF ;;
525 #                       spx)
526 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $SPX_PRE $IF $OF ;;
527 #                       esac
528 #               done
529 #               # Only remove .wav if the encoding succeeded
530 #               if checkerrors "preprocess-(.{3,4})-$1"; then 
531 #                       run_command preprocess-$1 false
532 #               else
533 #                       run_command preprocess-$1 true
534 #               fi
535 #       else
536 #               if [ "$(checkstatus encode-output)" = "loud" ]; then
537 #                       echo "HEH! The file we were about to pre-process disappeared:"
538 #                       echo ">> $IN"
539 #               fi
540 #               run_command preprocess-$1 false
541 #       fi
542 #}
543
544
545 # do_postprocess [tracknumber]
546 # variables used:
547 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
548 #do_postprocess ()
549 #{
550 #       for POSTPROCESSFORMAT in $(echo $POSTPROCESSFORMATS | tr , \ )
551 #       do
552 #               IN="$ABCDETEMPDIR/track$1.$POSTPROCESSFORMAT"
553 #               # We need IN to proceed.
554 #               if [ -s "$IN" ] ; then
555 #                       #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
556 #                       run_command '' echo "Post-processing track $1 of $TRACKS..."
557 #                       case "$POSTPROCESSFORMAT" in
558 #                               mp3)
559 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $MP3_POST $IF $OF ;;
560 #                               ogg)
561 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $OGG_POST $IF $OF ;;
562 #                               flac)
563 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $FLAC_POST $IF $OF ;;
564 #                               spx)
565 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $SPX_POST $IF $OF ;;
566 #                       esac
567 #                       # Only remove .wav if the encoding succeeded
568 #                       if checkerrors "postprocess-(.{3,4})-$1"; then 
569 #                               run_command postprocess-$1 false
570 #                       else
571 #                               run_command postprocess-$1 true
572 #                       fi
573 #               else
574 #                       if [ "$(checkstatus encode-output)" = "loud" ]; then
575 #                               echo "HEH! The file we were about to post-process disappeared:"
576 #                               echo ">> $IN"
577 #                       fi
578 #                       run_command postprocess-$1 false
579 #               fi
580 #       done
581 #}
582
583 # do_batch_gain
584 # variables used:
585 # MP3GAIN, MP3GAINOPTS, VORBISGAIN, VORBISGAINOPTS
586 do_batch_gain ()
587 {
588         # The commands here don't go through run_command because they're never supposed to be silenced
589         echo "Batch analizing gain in tracks: $TRACKQUEUE"
590         (
591         cd "$ABCDETEMPDIR"
592         BLURB=
593         TRACKFILES=
594         for UTRACKNUM in $TRACKQUEUE
595         do
596                 MP3FILES="$TRACKFILES track$UTRACKNUM.mp3"
597         done
598         # XXX: Hard-coded batch option!
599         $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
600         RETURN=$?
601         if [ "$RETURN" != "0" ]; then
602                 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
603         else
604                 for UTRACKNUM in $TRACKQUEUE
605                 do
606                         echo normalizetrack-$UTRACKNUM >> status
607                 done
608         fi
609         )
610 }
611
612 # do_batch_normalize
613 # variables used:
614 # NORMALIZER, NORMALIZEROPTS
615 do_batch_normalize ()
616 {
617         # The commands here don't go through run_command because they're never supposed to be silenced
618         echo "Batch normalizing tracks: $TRACKQUEUE"
619         (
620         cd "$ABCDETEMPDIR"
621         BLURB=
622         TRACKFILES=
623         for UTRACKNUM in $TRACKQUEUE
624         do
625                 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
626         done
627         # XXX: Hard-coded batch option!
628         $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
629         RETURN=$?
630         if [ "$RETURN" != "0" ]; then
631                 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
632         else
633                 for UTRACKNUM in $TRACKQUEUE
634                 do
635                         echo normalizetrack-$UTRACKNUM >> status
636                 done
637         fi
638         )
639 }
640
641 # do_normalize [tracknumber]
642 # variables used:
643 # TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
644 do_normalize ()
645 {
646         IN="$ABCDETEMPDIR/track$1.wav"
647         if [ -e "$IN" ] ; then
648                 run_command '' echo "Normalizing track $1 of $TRACKS: $TRACKNAME..."
649                 run_command normalizetrack-$1 $NORMALIZER $NORMALIZEROPTS "$IN"
650         else
651                 if [ "$(checkstatus encode-output)" = "loud" ]; then
652                         echo "HEH! The file we were about to normalize disappeared:"
653                         echo ">> $IN"
654                 fi
655                 run_command normalizetrack-$1 false "File $IN was not found"
656         fi
657 }
658
659 # do_move [tracknumber]
660 # Deduces the outfile from environment variables
661 # Creates directory if necessary
662 # variables used:
663 # TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, CDYEAR
664 do_move ()
665 {
666         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
667         do
668                 # Create ALBUMFILE, ARTISTFILE, TRACKFILE
669                 # Munge filenames as follows:
670                 # ' ' -> '_'
671                 # '/' -> '_'
672                 # ''' -> ''
673                 # '?' -> ''
674                 # Eat control characters
675                 ALBUMFILE=$(mungefilename "$DALBUM")
676                 ARTISTFILE=$(mungefilename "$TRACKARTIST")
677                 TRACKFILE=$(mungefilename "$TRACKNAME")
678                 GENRE=$(mungegenre "$GENRE")
679                 YEAR=$(echo $CDYEAR)
680                 # If we want to start the tracks with a given number, we need to modify the
681                 # TRACKNUM value before evaluation
682                 if [ -n "$STARTTRACKNUMBER" ] ; then
683                         # Get the trackpadding from the current track
684                         CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
685                         TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - 1 ))
686                 else
687                         TRACKNUM=${UTRACKNUM}
688                 fi
689                 # Supported variables for OUTPUTFORMAT are GENRE, ALBUMFILE, ARTISTFILE,
690                 # TRACKFILE, and TRACKNUM.
691                 if [ "$VARIOUSARTISTS" = "y" ]; then
692                         OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
693                         else
694                         OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
695                 fi
696                 # Check that the directory for OUTPUTFILE exists, if it doesn't, create it
697                 OUTPUTFILEDIR=$(dirname "$OUTPUTDIR/$OUTPUTFILE")
698                 # mkdir -p shouldn't return an error if the directory already exists
699                 mkdir -p "$OUTPUTFILEDIR"
700                 run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
701         done
702 }
703
704 # do_playlist
705 # Create the playlist if wanted
706 # Variables used:
707 # PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
708 # VARIOUSARTISTS, OUTPUTDIR
709 do_playlist ()
710 {
711         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
712         do
713                 # Create a playlist file for the playlist data to go into.
714                 # We used to wipe it out if it existed. Now we request permision if interactive.
715                 for LASTTRACK in $TRACKQUEUE; do :; done
716                 ALBUMFILE=$(mungefilename "$DALBUM")
717                 ARTISTFILE=$(mungefilename "$DARTIST")
718                 GENRE=$(mungegenre "$GENRE")
719                 if [ "$VARIOUSARTISTS" = "y" ] ; then
720                         PLAYLISTFILE=$(eval echo $VAPLAYLISTFORMAT)
721                 else
722                         PLAYLISTFILE=$(eval echo $PLAYLISTFORMAT)
723                 fi
724                 FINALPLAYLISTDIR=$(dirname "$OUTPUTDIR/$PLAYLISTFILE")
725                 mkdir -p "$FINALPLAYLISTDIR"
726                 if [ -s "$OUTPUTDIR/$PLAYLISTFILE" ]; then
727                         #echo -n "Erase any existing playlist file? [y/n] (y): " >&2
728                         echo -n "Erase, Append to, or Keep the existing playlist file? [e/a/k] (e): " >&2
729                         if [ "$INTERACTIVE" = "y" ]; then
730                                 while [ "$DONE" != "y" ]; do
731                                         read ERASEPLAYLIST
732                                         case $ERASEPLAYLIST in
733                                                 e|E|a|A|k|K) DONE=y ;;
734                                                 *) ;;
735                                         esac
736                                 done
737                         else
738                                 echo e >&2
739                                 ERASEPLAYLIST=e
740                         fi
741                         # Once we erase the playlist, we use append to create the new one.
742                         [ "$ERASEPLAYLIST" = "e" -o "$ERASEPLAYLIST" = "E" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE" && ERASEPLAYLIST=a
743                 else
744                         # The playlist does not exist, so we can safelly use append to create the new list
745                         ERASEPLAYLIST=a
746                 fi
747                 if [ "$ERASEPLAYLIST" = "a" -o "$ERASEPLAYLIST" = "A" ]; then
748                         touch "$OUTPUTDIR/$PLAYLISTFILE"
749                         for UTRACKNUM in $TRACKQUEUE
750                         do
751                                 # Shares some code with do_move since the filenames have to match
752                                 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
753                                 TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
754                                 splitvarious
755                                 TRACKFILE=$(mungefilename "$TRACKNAME")
756                                 ARTISTFILE=$(mungefilename "$TRACKARTIST")
757                                 # If we want to start the tracks with a given number, we need to modify the
758                                 # TRACKNUM value before evaluation
759                                 if [ -n $STARTTRACKNUMBER ] ; then
760                                         # Get the trackpadding from the current track
761                                         CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
762                                         TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - 1 ))
763                                 else
764                                         TRACKNUM=${UTRACKNUM}
765                                 fi
766                                 if [ "$VARIOUSARTISTS" = "y" ]; then
767                                         OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
768                                 else
769                                         OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
770                                 fi
771                                 if [ "$VARIOUSARTISTS" = "y" ]; then
772                                         if [ "$VAPLAYLISTDATAPREFIX" ] ; then
773                                                 echo ${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
774                                         else
775                                                 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
776                                         fi
777                                 else
778                                         if [ "$PLAYLISTDATAPREFIX" ]; then
779                                                 echo ${PLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
780                                         else
781                                                 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
782                                         fi
783                                 fi
784                         done
785                 fi
786                 ## this will convert the playlist to have CRLF line-endings, if specified
787                 ## (some hardware players insist on CRLF endings)
788                 if [ "$DOSPLAYLIST" = "y" ]; then
789                         awk '{substr("\r",""); printf "%s\r\n", $0}' "$OUTPUTDIR/$PLAYLISTFILE" > "$ABCDETEMPDIR/PLAYLISTFILE.tmp"
790 #                       mv -f "$ABCDETEMPDIR/PLAYLISTFILE.tmp" "$OUTPUTDIR/$PLAYLISTFILE"
791                         cat "$ABCDETEMPDIR/PLAYLISTFILE.tmp" | sed 's/\//\\/' > "$OUTPUTDIR/$PLAYLISTFILE"
792                 fi
793                 echo "playlistcomplete" >> "$ABCDETEMPDIR/status"
794         done
795 }
796
797 # do_discid
798 # This essentially the start of things
799 do_discid ()
800 {
801         # Query the CD to get the track info, unless the user specified -C
802         # or we are using some actions which do not need the CDDB data at all
803         #if [ ! X"$EXPACTIONS" = "X" ]; then
804         #       :
805         #elif [ -z "$DISCID" ]; then
806         if [ -z "$DISCID" ]; then
807                 vecho -n "Getting CD track info... "
808                 TRACKINFO=$($CDDISCID $CDROM)
809                 # Make sure there's a CD in there by checking cd-discid's return code
810                 if [ "$?" = "1" ]; then
811                         echo "abcde error: CD could not be read. Perhaps there's no CD in the drive?" >&2
812                         exit 1
813                 fi
814                 WEHAVEACD=y
815         else
816                 TRACKINFO=$(cat "$WAVOUTPUTDIR/abcde.$DISCID/discid")
817         fi
818
819         # Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.
820         # This needs to be done now because a section of the resuming code will need
821         # it later.
822
823         # get the number of digits to pad TRACKNUM with - we'll use this later
824         # a CD can only hold 99 tracks, but since we support a feature for starting
825         # numbering the tracks from a given number, we might need to set it as a
826         # variable for the user to define... or obtain it somehow.
827         if [ "$PADTRACKS" = "y" ] ; then
828                 TRACKNUMPADDING=2
829         fi
830
831         ABCDETEMPDIR="$WAVOUTPUTDIR/abcde.$(echo $TRACKINFO | cut -f1 -d' ')"
832         if [ -z "$TRACKQUEUE" ]; then
833                 if [ ! "$STRIPDATATRACKS" = "y" ]; then
834                         case "$CDROMREADERSYNTAX" in
835                                 cdparanoia|debug)
836                                         if [ "$WEHAVEACD" = "y" ]; then
837                                                 vecho "Querying the CD for audio tracks..."
838                                                 TRACKS=$( $CDROMREADER -Q 2>&1 | egrep '^[[:space:]]+[[:digit:]]' | tail -n 1 |  awk '{print $1}' | tr -d "." | tr '\n' ' ' )
839                                                 CDPARANOIAAUDIOTRACKS="$TRACKS"
840                                         else
841                                                 if [ -f "$ABCDETEMPDIR/status" ] && checkstatus cdparanoia-audio-tracks ; then
842                                                         TRACKS=$( cat $ABCDETEMPDIR/cdparanoia-audio-tracks )
843                                                 else
844                                                         TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
845                                                 fi
846                                         fi
847                                         ;;
848                                 *)      TRACKS=$(echo $TRACKINFO | cut -f2 -d' ') ;;
849                         esac
850                 else
851                         TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
852                 fi
853                 echo -n "Grabbing entire CD - tracks: "
854                 if [ ! "$PADTRACKS" = "y" ] ; then
855                         TRACKNUMPADDING=$(echo -n $TRACKS | wc -c | tr -d ' ')
856                 fi
857                 TRACKS=$(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
858                 X=0
859                 while [ "$X" -ne "$TRACKS" ]
860                 do
861                         X=$(printf "%0.${TRACKNUMPADDING}d" $(expr $X + 1))
862                         TRACKQUEUE=$(echo "$TRACKQUEUE" $X)
863                 done
864                 echo $TRACKQUEUE
865         else
866                 TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
867                 # User-supplied track queue.
868                 # Weed out non-numbers, whitespace, then sort and weed out duplicates
869                 TRACKQUEUE=$(echo $TRACKQUEUE | sed 's-[^0-9 ]--g' | tr ' ' '\n' | grep -v ^$ | sort -n | uniq | tr '\n' ' ' | sed 's- $--g')
870                 # Once cleaned, obtain the highest value in the trackqueue for number padding
871                 for LASTTRACK in $TRACKQUEUE; do :; done
872                 if [ ! "$PADTRACKS" = "y" ] ; then
873                         TRACKNUMPADDING=$(echo -n $LASTTRACK | wc -c | tr -d ' ')
874                 fi
875                 # Now we normalize the trackqueue
876                 for TRACK in $TRACKQUEUE ; do
877                         TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${TRACK} + 0 ))
878                         PADTRACKQUEUE=$(echo $PADTRACKQUEUE $TRACKNUM)
879                 done
880                 TRACKQUEUE=$PADTRACKQUEUE
881                 echo Grabbing tracks: "$TRACKQUEUE"
882         fi
883
884 #       for LASTTRACK in $TRACKQUEUE; do :; done
885
886         QUEUEDTRACKS=$(echo $TRACKQUEUE | wc -w | tr -d ' ')
887
888         # We have the discid, create a temp directory after it to store all the temp
889         # info
890
891         if [ -e "$ABCDETEMPDIR" ]; then
892                 echo -n "abcde: attempting to resume from $ABCDETEMPDIR"
893                 # It already exists, see if it's a directory
894                 if [ ! -d "$ABCDETEMPDIR" ]; then
895                         # This is a file/socket/fifo/device/etc, not a directory
896                         # Complain and exit
897                         echo >&2
898                         echo "abcde: file $ABCDETEMPDIR already exists and does not belong to abcde." >&2
899                         echo "Please investigate, remove it, and rerun abcde." >&2
900                         exit 1
901                 fi
902                 echo -n .
903                 # It's a directory, let's see if it's owned by us
904                 if [ ! -O "$ABCDETEMPDIR" ]; then
905                         # Nope, complain and exit
906                         echo >&2
907                         echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
908                         echo "Please investigate, remove it, and rerun abcde." >&2
909                         exit 1
910                 fi
911                 echo .
912                 # See if it's populated
913                 if [ ! -f "$ABCDETEMPDIR/discid" ]; then
914                         # Wipe and start fresh
915                         echo "abcde: $ABCDETEMPDIR/discid not found. Abcde must remove and recreate" >&2
916                         echo -n "this directory to continue. Continue? [y/n] (n)" >&2
917                         if [ "$INTERACTIVE" = "y" ]; then
918                                 read ANSWER
919                         else
920                                 echo y >&2
921                                 ANSWER=y
922                         fi
923                         if [ "$ANSWER" != "y" ]; then
924                                 exit 1
925                         fi
926                         rm -rf "$ABCDETEMPDIR" || exit 1
927                         mkdir "$ABCDETEMPDIR"
928                         if [ "$?" -gt "0" ]; then
929                                 # Directory already exists or could not be created
930                                 echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
931                                 exit 1
932                         fi
933                 else
934                         # Everything is fine. Check for ^encodetracklocation-
935                         # and encode-output entries in the status file and
936                         # remove them. These are not relevant across sessions.
937                         if [ -f "$ABCDETEMPDIR/status" ]; then
938                                 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
939                                 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
940                                         | grep -v ^encode-output > "$ABCDETEMPDIR/status"
941                         fi
942                         # Remove old error messages
943                         if [ -f "$ABCDETEMPDIR/errors" ]; then
944                                 rm -f "$ABCDETEMPDIR/errors"
945                         fi
946                 fi
947         else
948                 # We are starting from scratch
949                 mkdir "$ABCDETEMPDIR"
950                 if [ "$?" -gt "0" ]; then
951                         # Directory already exists or could not be created
952                         echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
953                         exit 1
954                 fi
955                 cat /dev/null > "$ABCDETEMPDIR/status"
956         fi
957         
958         # If we got the CDPARANOIA status and it is not recorded, save it now
959         ## FIXME ## ! is non-portable
960         if [ -n "$CDPARANOIAAUDIOTRACKS" ] && ! checkstatus cdparanoia-audio-tracks; then
961                 if echo "$CDPARANOIAAUDIOTRACKS" >> "$ABCDETEMPDIR/cdparanoia-audio-tracks"; then
962                         echo "cdparanoia-audio-tracks" >> "$ABCDETEMPDIR/status"
963                 fi
964         fi
965         
966         # Create the discid file
967         echo "$TRACKINFO" > "$ABCDETEMPDIR/discid"
968 }
969
970 # do_cddbparse
971 # Parses a CDDB file and outputs the title and the track names.
972 # Variables: CDDBFILE
973 do_cddbparse ()
974 {
975         CDDBPARSEFILE="$1"
976         # List out disc title/author and contents
977         if [ "$ONETRACK" = "y" ]; then
978                 vecho "ONETRACK mode selected: displaying only the title of the CD..."
979         fi
980         echo "---- $(grep DTITLE "${CDDBPARSEFILE}" | cut '-d=' -f2- | tr -d \\r\\n ) ----"
981         if [ ! "$ONETRACK" = "y" ]; then
982                 for TRACK in $(f_seq_row 1 $TRACKS)
983                 do
984                         echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
985                 done
986         fi
987 }
988
989 # do_localcddb
990 # Check for a local CDDB file, and report success
991 do_localcddb ()
992 {
993         if checkstatus cddb-readcomplete && checkstatus cddb-choice >/dev/null; then :; else
994         
995                 CDDBLOCALSUCCESS="n"
996                 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
997                 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
998                 USELOCALRESP="y"
999                 
1000                 # If the user has selected to check a local CDDB repo, we proceed with it
1001                 if [ -r "${CDDBLOCALFILE}" ]; then
1002                         # List out disc title/author and contents
1003                         do_cddbparse "${CDDBLOCALFILE}"
1004                         echo -n "Locally cached CDDB entry found, use it? [y/n] (y): "
1005                         if [ "$INTERACTIVE" = "y" ]; then
1006                                 read USELOCALRESP
1007                                 while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
1008                                         echo -n 'Invalid selection. Please answer "y" or "n": '
1009                                         read USELOCALRESP
1010                                 done
1011                                 [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
1012                         else
1013                                 echo "y" >&2
1014                         fi
1015                         if [ "$USELOCALRESP" = "y" ]; then
1016                         #echo "Using local copy of CDDB data"
1017                                 cp "${CDDBLOCALFILE}" "$ABCDETEMPDIR/cddbread.1"
1018                                 echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
1019                                 echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
1020                                 do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
1021                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1022                                 CDDBLOCALSUCCESS="y"
1023                         else
1024                                 #echo "Not using local copy of CDDB data"
1025                                 CDDBLOCALSUCCESS="n"
1026                         fi
1027                         CDDBLOCALSUCCESS="y"
1028                 else
1029                         CDDBLOCALSUCCESS="n"
1030                 fi
1031         fi
1032 }
1033
1034 # do_cddbstat
1035 do_cddbstat ()
1036 {
1037         # Perform CDDB protocol version check if it hasn't already been done
1038         if checkstatus cddb-statcomplete; then :; else
1039                 if [ "$CDDBAVAIL" = "n" ]; then
1040                         ERRORCODE=no_query
1041                         echo 503 > "$ABCDETEMPDIR/cddbstat"
1042                 else
1043                         rc=1
1044                         CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1045                         CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1046                         while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
1047                                 vecho "Checking CDDB server status..."
1048                                 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
1049                                 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
1050                                 case "$RESPONSECODE" in
1051                                 210)    # 210 OK, status information follows (until terminating `.')
1052                                         rc=0;
1053                                         ;;
1054                                 501|*)  # 501 Illegal CDDB protocol level: <n>. 
1055                                         CDDBPROTO=`expr $CDDBPROTO - 1`
1056                                         ;;
1057                                 esac 
1058                         done
1059                         if test $rc -eq 1; then
1060                                 CDDBAVAIL="n" 
1061                         fi
1062                 fi
1063                 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
1064         fi
1065 }
1066
1067
1068 # do_cddbquery
1069 do_cddbquery ()
1070 {
1071         CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
1072         CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
1073         
1074         # Perform CDDB query if it hasn't already been done
1075         if checkstatus cddb-querycomplete; then :; else
1076                 if [ "$CDDBAVAIL" = "n" ]; then
1077                         ERRORCODE=no_query
1078                         echo 503 > "$ABCDETEMPDIR/cddbquery"
1079                 # The default CDDBLOCALSUCCESS is "n"
1080                 # This part will be triggered if the user CDDB repo does not 
1081                 # contain the entry, or if we are not trying to use the repo.
1082                 else
1083                         vecho "Querying the CDDB server..."
1084                         CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1085                         CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1086                         $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
1087                         ERRORCODE=$?
1088                         case $ERRORCODE in
1089                                 0)  # success
1090                                 ;;
1091                                 12|13|14)
1092                                         # no match found in database,
1093                                         # wget/fetch error, or user requested not to use CDDB
1094                                         # Make up an error code (503) that abcde
1095                                         # will recognize in do_cddbread
1096                                         # and compensate by making a template
1097                                         echo 503 > "$ABCDETEMPDIR/cddbquery"
1098                                 ;;
1099                                 *) # strange and unknown error
1100                                         echo ERRORCODE=$ERRORCODE
1101                                         echo "abcde: $CDDBTOOL returned unknown error code"
1102                                 ;;
1103                         esac
1104                 fi
1105                 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
1106         fi
1107 }
1108
1109 # do_cddbread
1110 do_cddbread ()
1111 {
1112         # If it's not to be used, generate a template.
1113         # Then, display it (or them) and let the user choose/edit it
1114         if checkstatus cddb-readcomplete; then :; else
1115                 vecho "Obtaining CDDB results..."
1116                 # If CDDB is to be used, interpret the query results and read all
1117                 # the available entries.
1118                 rm -f "$ABCDETEMPDIR/cddbchoices"
1119                 CDDBCHOICES=1 # Overridden by multiple matches
1120                 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
1121                 case "$RESPONSECODE" in
1122                 200)
1123                         # One exact match, retrieve it
1124                         # 200 [section] [discid] [artist] / [title]
1125                         if checkstatus cddb-read-1-complete; then :; else
1126                                 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
1127                                 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
1128                                 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
1129                                 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1130                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1131                         fi
1132                         # List out disc title/author and contents
1133                         echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
1134                         for TRACK in $(f_seq_row 1 $TRACKS)
1135                         do
1136                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1137                         done
1138                         echo >> "$ABCDETEMPDIR/cddbchoices"
1139                         ;;
1140                 202|403|409|503)
1141                         # No match
1142                         case "$RESPONSECODE" in
1143                         202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
1144                         403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
1145                         503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
1146                         esac
1147                         $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
1148                         # List out disc title/author and contents of template
1149                         echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
1150                         UNKNOWNDISK=y
1151                         for TRACK in $(f_seq_row 1 $TRACKS)
1152                         do
1153                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1154                         done
1155                         echo >> "$ABCDETEMPDIR/cddbchoices"
1156                         echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
1157                         echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
1158                         ;;
1159                 210|211)
1160                         # Multiple exact, (possibly multiple) inexact matches
1161                         IN=
1162                         if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
1163                         if [ "$(wc -l < $ABCDETEMPDIR/cddbquery | tr -d ' ')" -eq 3 ]; then
1164                                 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
1165                                 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
1166                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1167                         else
1168                                 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
1169                         fi
1170                         vecho -n "Retrieving multiple matches... "
1171                         grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
1172                         read DISCINFO # eat top line
1173                         while read DISCINFO
1174                         do
1175                                 X=$(expr $X + 1)
1176                                 if checkstatus cddb-read-$X-complete; then :; else
1177                                         $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
1178                                         echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
1179                                 fi
1180                                 # List out disc title/author and contents
1181                                 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
1182                                 for TRACK in $(f_seq_row 1 $TRACKS)
1183                                 do
1184                                         echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1185                                 done
1186                                 echo >> "$ABCDETEMPDIR/cddbchoices"
1187                         done )
1188                         vecho "done."
1189                         CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1190                         ;;
1191                 999)
1192                         # Using local copy.
1193                         for TRACK in $(f_seq_row 1 $TRACKS)
1194                         do
1195                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1196                         done
1197                         echo >> "$ABCDETEMPDIR/cddbchoices"
1198                         echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1199                         echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1200                         ;;
1201                 esac    
1202                 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
1203         fi
1204 }
1205
1206 # do_cddbedit
1207 do_cddbedit ()
1208 {
1209         if checkstatus cddb-edit >/dev/null; then
1210                 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1211                 VARIOUSARTISTS="$(checkstatus variousartists)"
1212                 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
1213                 return 0
1214         fi
1215         if [ "$INTERACTIVE" = "y" ]; then
1216                 # We should show the CDDB results both when we are not using the local CDDB repo
1217                 # or when we are using it but we could not find a proper match
1218                 if [ "$CDDBUSELOCAL" = "y" ] && [ ! "$CDDBLOCALSUCCESS" = "y" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1219                         # Display the $ABCDETEMPDIR/cddbchoices file created above
1220                         # Pick a pager so that if the tracks overflow the screen the user can still view everything
1221                         if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1222                                 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1223                                 CHOICE=$(checkstatus cddb-choice)
1224                                 if [ -n "$CHOICE" ] ; then
1225                                         case $CDDBCHOICES in
1226                                                 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1227                                                 *)
1228                                                 echo "Selected: #$CHOICE"
1229                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1230                                                 ;;
1231                                         esac
1232                                 else
1233                                         # The user has a choice to make, display the info in a pager if necessary
1234                                         if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
1235                                                 # Use the debian sensible-pager wrapper to pick the pager
1236                                                 # user has requested via their $PAGER environment variable
1237                                                 if [ -x "/usr/bin/sensible-pager" ]; then
1238                                                         /usr/bin/sensible-pager "$ABCDETEMPDIR/cddbchoices"
1239                                                 elif [ -x "$PAGER" ]; then
1240                                                         # That failed, try to load the preferred editor, starting
1241                                                         # with their PAGER variable
1242                                                         $PAGER "$ABCDETEMPDIR/cddbchoices"
1243                                                         # If that fails, check for less
1244                                                 elif [ -x /usr/bin/less ]; then
1245                                                         /usr/bin/less -f "$ABCDETEMPDIR/cddbchoices"
1246                                                         # more should be on all UNIX systems
1247                                                 elif [ -x /bin/more ]; then
1248                                                         /bin/more "$ABCDETEMPDIR/cddbchoices"
1249                                                 else
1250                                                         # No bananas, just cat the thing
1251                                                         cat "$ABCDETEMPDIR/cddbchoices" >&2
1252                                                 fi
1253                                         else
1254                                                 # It's all going to fit in one page, cat it
1255                                                 cat "$ABCDETEMPDIR/cddbchoices" >&2
1256                                         fi
1257                                         
1258                                         # I'll take CDDB read #3 for $400, Alex
1259                                         echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
1260                                         read CDDBCHOICE
1261                                         # Make sure we get a valid choice
1262                                         CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
1263                                         while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
1264                                                 echo "Invalid selection. Please choose a number between 1 and $CDDBCHOICES." >&2
1265                                                 echo -n "Selection [0-$CDDBCHOICES]: " >&2
1266                                                 read CDDBCHOICE
1267                                                 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
1268                                         done
1269                                         if [ "$CDCHOICENUM" = "0" ]; then
1270                                                 vecho "Creating empty CDDB template..."
1271                                                 UNKNOWNDISK=y
1272                                                 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > $ABCDETEMPDIR/cddbread.0
1273                                         else
1274                                                 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= $ABCDETEMPDIR/cddbread.$CDCHOICENUM | cut -f2- -d= | tr -d \\r\\n))" >&2
1275                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
1276                                         fi
1277                                         echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1278                                 fi
1279                         fi
1280                 else
1281                         # We need some code to show the selected option when local repository is selected and we have found a match
1282                         vecho "Using cached CDDB match..." >&2
1283                         # Display the $ABCDETEMPDIR/cddbchoices file created above
1284                         # Pick a pager so that if the tracks overflow the screen the user can still view everything
1285                         if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1286                                 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1287                                 CHOICE=$(checkstatus cddb-choice)
1288                                 if [ "$USELOCALRESP" = "y" ]; then :; else
1289                                         if [ -n "$CHOICE" ] ; then
1290                                                 case $CDDBCHOICES in
1291                                                         0) 
1292                                                         UNKNOWNDISK=y
1293                                                         echo "Selected template."
1294                                                         ;;
1295                                                         1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1296                                                         *)
1297                                                         echo "Selected: #$CHOICE"
1298                                                         do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1299                                                         ;;
1300                                                 esac
1301                                         fi
1302                                 fi
1303                         fi
1304                 fi
1305         else
1306                 # We're noninteractive - pick the first choice.
1307                 # But in case we run a previous instance and selected a choice, use it.
1308                 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1309                         # Show the choice if we are not using the locally stored one
1310                         # or when the local search failed to find a match.
1311                         PREVIOUSCHOICE=$(checkstatus cddb-choice)
1312                         if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSUCCESS" = "n" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1313                                 #if [ "$PREVIOUSCHOICE" ]; then
1314                                         cat "$ABCDETEMPDIR/cddbchoices"
1315                                 #fi
1316                         fi
1317                         if [ ! -z "$PREVIOUSCHOICE" ] ; then
1318                                 CDCHOICENUM=$PREVIOUSCHOICE
1319                         else
1320                                 CDCHOICENUM=1
1321                                 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1322                         fi
1323                         echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= $ABCDETEMPDIR/cddbread.$CDCHOICENUM | cut -f2- -d= | tr -d \\r\\n))" >&2
1324                 fi
1325         fi
1326
1327         # sanity check
1328         if checkstatus cddb-choice >/dev/null; then :; else
1329                 echo "abcde: internal error: cddb-choice not recorded." >&2
1330                 exit 1
1331         fi
1332         CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1333         echo -n "Edit selected CDDB data? [y/n] (" >&2
1334         if [ "$INTERACTIVE" = "y" ]; then
1335                 if [ "$UNKNOWNDISK" = "y" ]; then
1336                         echo -n "y): " >&2
1337                         read EDITCDDB
1338                         [ "$EDITCDDB" != "n" ] && EDITCDDB=y
1339                 else
1340                         echo -n "n): " >&2
1341                         read EDITCDDB
1342                 fi
1343         else
1344                 echo "n): n" >&2
1345                 EDITCDDB=n
1346         fi
1347         if [ "$EDITCDDB" = "y" ]; then
1348                 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
1349                 
1350                 # Use the debian sensible-editor wrapper to pick the editor that the
1351                 # user has requested via their $EDITOR environment variable
1352                 if [ -x "/usr/bin/sensible-editor" ]; then
1353                         /usr/bin/sensible-editor "$CDDBDATA"
1354                 elif [ -n "$EDITOR" ]; then
1355                         if [ -x $(which "${EDITOR%%\ *}") ]; then
1356                                 # That failed, try to load the preferred editor, starting
1357                                 # with their EDITOR variable
1358                                 eval $(echo "$EDITOR") "$CDDBDATA"
1359                         fi
1360                 # If that fails, check for a vi
1361                 elif [ -x /usr/bin/vi ]; then
1362                         /usr/bin/vi "$CDDBDATA"
1363                 # nano should be on all (modern, i.e., sarge) debian systems
1364                 elif [ -x /usr/bin/nano ]; then
1365                         /usr/bin/nano "$CDDBDATA"
1366                 # mg should be on all OpenBSD systems
1367                 elif [ -x /usr/bin/mg ]; then
1368                         /usr/bin/mg "$CDDBDATA"
1369                 # bomb out
1370                 else
1371                         echo "No editor available. Check your EDITOR environment variable." >&2
1372                 fi
1373                 # delete editor backup file if it exists
1374                 if [ -w "$CDDBDATA~" ]; then
1375                         rm -f "$CDDBDATA~"
1376                 fi
1377         fi
1378
1379         # Some heuristics first. Look at Disc Title, and if it starts with
1380         # "Various", then we'll assume Various Artists
1381         if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2 -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
1382                 echo "Looks like a Multi-Artist CD" >&2
1383                 VARIOUSARTISTS=y
1384         else
1385                 echo -n "Is the CD multi-artist? [y/n] (n): " >&2
1386                 if [ "$INTERACTIVE" = "y" ]; then
1387                         read VARIOUSARTISTS
1388                 else
1389                         echo n >&2
1390                         VARIOUSARTISTS=n
1391                 fi
1392         fi
1393         if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
1394                 # Set a default
1395                 DEFAULTSTYLE=1
1396                 # Need NUMTRACKS before cddb-tool will return it:
1397                 NUMTRACKS=$(egrep '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
1398                 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1399                         # More than 1/2 tracks contain a "/", so guess forward
1400                         DEFAULTSTYLE=1
1401                 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1402                         # More than 1/2 contain a "-", so guess forward-dash
1403                         DEFAULTSTYLE=2
1404                 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1405                         # More than 1/2 contain something in parens, so guess trailing-paren
1406                         DEFAULTSTYLE=6
1407                 fi
1408
1409                 echo "1) Artist / Title" >&2
1410                 echo "2) Artist - Title" >&2
1411                 echo "3) Title / Artist" >&2
1412                 echo "4) Title - Artist" >&2
1413                 echo "5) Artist: Title" >&2
1414                 echo "6) Title (Artist)" >&2
1415                 echo "7) This is a single-artist CD" >&2
1416                 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
1417                 if [ "$INTERACTIVE" = "y" ]; then
1418                         read VARIOUSARTISTSTYLE
1419                 else
1420                         echo $DEFAULTSTYLE >&2
1421                         VARIOUSARTISTSTYLE=$DEFAULTSTYLE
1422                 fi
1423                 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
1424                 # If they press Enter, then the default style (0) was chosen
1425                 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
1426                         echo "Invalid selection. Please choose a number between 1 and 7."
1427                         echo -n "Selection [1-7]: "
1428                         read VARIOUSARTISTSTYLE
1429                         VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
1430                 done
1431                 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
1432                         VARIOUSARTISTSTYLE=$DEFAULTSTYLE
1433                 fi
1434                 vecho "Selected: $VARIOUSARTISTSTYLE"
1435                 case "$VARIOUSARTISTSTYLE" in
1436                 1) # Artist / Title
1437                         VARIOUSARTISTSTYLE=forward
1438                         ;;
1439                 2) # Artist - Title
1440                         VARIOUSARTISTSTYLE=forward-dash
1441                         ;;
1442                 3) # Title / Artist
1443                         VARIOUSARTISTSTYLE=reverse
1444                         ;;
1445                 4) # Title - Artist
1446                         VARIOUSARTISTSTYLE=reverse-dash
1447                         ;;
1448                 5) # Artist: Title
1449                         VARIOUSARTISTSTYLE=colon
1450                         ;;
1451                 6) # Title (Artist)
1452                         VARIOUSARTISTSTYLE=trailing-paren
1453                         ;;
1454                 7) # Single Artist
1455                         VARIOUSARTISTS=n
1456                         ;;
1457                 esac
1458         fi
1459
1460         echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
1461         echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
1462
1463         if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
1464                 if [ $CDDBDATAMD5SUM != "" ]  && [ $CDDBDATAMD5SUM != $($MD5SUM "$CDDBDATA" | cut -d " " -f 1) ]; then
1465                         # This works but does not have the necessary error checking
1466                         # yet. If you are familiar with the CDDB spec
1467                         # (see http://www.freedb.org/src/latest/DBFORMAT) 
1468                         # and can create an error-free entry on your own, then put
1469                         # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
1470                         # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
1471                         # your abcde.conf to change the email address submissions are
1472                         # sent to.
1473
1474                         # submit the modified file, if they want
1475                         if [ "$NOSUBMIT" != "y" ]; then
1476                                 echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
1477                                 read YESNO
1478                                 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
1479                                         [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
1480                                 do
1481                                         echo -n 'Invalid selection. Please answer "y" or "n": '
1482                                         read YESNO
1483                                 done
1484                                 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
1485                                         echo -n "Sending..."
1486                                         $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
1487                                         echo "done."
1488                                 fi
1489                         fi
1490                 fi
1491         fi
1492         # Make sure the cache directory exists
1493         mkdir -p $CDDBLOCALDIR
1494         # Cache edited CDDB entry in the user's cddb dir
1495         if [ "$CDDBCOPYLOCAL" = "y" ] || [ "$COPYCDDBLOCAL" = "Y" ]; then
1496                 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
1497         fi
1498
1499         echo "cddb-edit" >> "$ABCDETEMPDIR/status"
1500 }
1501
1502 # do_cdread_one [lasttrack] [firsttrack]
1503
1504 # Reads the CD in a single track. Live performances, concerts, mixes,... benefit from this.
1505 do_cdread_one ()
1506 {
1507         # The commands here don't go through run_command because they're never supposed to be silenced
1508         # return codes need to be doublechecked anyway, however
1509         LASTTRACKNUMBER=$1
1510         FIRSTTRACKNUMBER=$2
1511         WAVDATA="$ABCDETEMPDIR/track$FIRSTTRACKNUMBER.wav"
1512         echo "Grabbing the CD to a single track..." >&2
1513         case "$CDROMREADERSYNTAX" in
1514                 cdparanoia) nice $READNICE $CDROMREADER -d $CDROM "1-" "$WAVDATA" >&2 ;;
1515                 cdda2wav)
1516                         if [ "$OSFLAVOUR" = "OSX" ] ; then
1517                                 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
1518                                 disktool -u ${CDROM#/dev/} 0
1519                                 # Also, in OSX the cdrom device for cdda2wav changes...
1520                                 CDDA2WAVCDROM="IODVDServices"
1521                         elif [ "$OSFLAVOUR" = "FBSD" ] ; then
1522                                 CDDA2WAVCDROM="$CDROMID"
1523                         else
1524                                 if [ "$CDROMID" = "" ]; then
1525                                         CDDA2WAVCDROM="$CDROM"
1526                                 else
1527                                         CDDA2WAVCDROM="$CDROMID"
1528                                 fi
1529                         fi
1530                         nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t 1+$LASTTRACKNUM "$WAVDATA" >&2 
1531                         ;;
1532                 dagrab) nice $READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
1533                 cddafs)
1534                         # Find the track's mounted path
1535                         REALTRACKNUM=$(expr $UTRACKNUM + 0)
1536                         FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
1537                         FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
1538                         # If the file exists, copy it
1539                         if [ -e "$FILEPATH" ] ; then
1540                                 nice $READNICE $CDROMREADER "$FILEPATH" "$WAVDATA" >&2
1541                         else
1542                                 false
1543                         fi ;;
1544                 debug) nice $READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
1545         esac
1546         RETURN=$?
1547         if [ "$RETURN" != "0" -o ! -s "$WAVDATA" ]; then
1548                 # Thank goodness errors is only machine-parseable up to the
1549                 # first colon, otherwise this woulda sucked
1550                 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
1551                         RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
1552                 fi
1553                 echo "readtrack-$FIRSTTRACKNUMBER: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
1554                 return $RETURN
1555         else
1556                 echo readtrack-$FIRSTTRACKNUMBER >> "$ABCDETEMPDIR/status"
1557         fi
1558 }
1559
1560 # do_cdread [tracknumber]
1561
1562 do_cdread ()
1563 {
1564         # The commands here don't go through run_command because they're never supposed to be silenced
1565         # return codes need to be doublechecked anyway, however
1566         UTRACKNUM=$1
1567         CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
1568         WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
1569         OUTDATA="$ABCDETEMPDIR/track$UTRACKNUM.$OUTPUTTYPE"
1570         if [ -r "$CDDBDATA" ]; then
1571                 TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
1572                 echo "Grabbing track $UTRACKNUM: $TRACKNAME..." >&2
1573         else
1574                 echo "Grabbing track $UTRACKNUM..." >&2
1575         fi
1576         case "$CDROMREADERSYNTAX" in
1577                 cdparanoia) nice $READNICE $CDROMREADER -d $CDROM $UTRACKNUM "$WAVDATA" >&2 ;;
1578                 cdda2wav)
1579                         if [ "$OSFLAVOUR" = "OSX" ] ; then
1580                                 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
1581                                 disktool -u ${CDROM#/dev/} 0
1582                                 # Also, in OSX the cdrom device for cdda2wav changes...
1583                                 CDDA2WAVCDROM="IODVDServices"
1584                         elif [ "$OSFLAVOUR" = "FBSD" ] ; then
1585                                 CDDA2WAVCDROM="$CDROMID"
1586                         else
1587                                 if [ "$CDROMID" = "" ]; then
1588                                         CDDA2WAVCDROM="$CDROM"
1589                                 else
1590                                         CDDA2WAVCDROM="$CDROMID"
1591                                 fi
1592                         fi
1593                         nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t $UTRACKNUM "$WAVDATA" >&2 
1594                         ;;
1595                 dagrab) nice $READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
1596                 cddafs)
1597                         # Find the track's mounted path
1598                         REALTRACKNUM=$(expr $UTRACKNUM + 0)
1599                         FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
1600                         FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
1601                         # If the file exists, copy it
1602                         if [ -e "$FILEPATH" ] ; then
1603                                 nice $READNICE $CDROMREADER "$FILEPATH" "$WAVDATA" >&2
1604                         else
1605                                 false
1606                         fi ;;
1607                 debug) nice $READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
1608         esac
1609         RETURN=$?
1610         if [ "$RETURN" != "0" -o ! -s "$WAVDATA" ]; then
1611                 # Thank goodness errors is only machine-parseable up to the
1612                 # first colon, otherwise this woulda sucked
1613                 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
1614                         RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
1615                 fi
1616                 echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
1617                 return $RETURN
1618         else
1619                 echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
1620         fi
1621 }
1622
1623 # do_cdspeed
1624 # No values accepted, only uses env variables
1625 do_cdspeed () 
1626 {
1627         if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
1628                 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
1629         else
1630                 echo "abcde: unable to set the device speed" >&2
1631         fi
1632 }
1633
1634 # vecho [message]
1635 #
1636 # vecho outputs a message if EXTRAVERBOSE is selected
1637 vecho ()
1638 {
1639 if [ x"$EXTRAVERBOSE" != "x" ]; then
1640         echo $@
1641 fi
1642 }
1643
1644 # User-redefinable functions
1645 # Custom filename munging:
1646 mungefilename ()
1647 {
1648         echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
1649 }
1650
1651 # Custom genre munging:
1652 mungegenre ()
1653 {
1654         echo $CDGENRE | tr "[:upper:]" "[:lower:]"
1655 }
1656
1657 # pre_read
1658 # Empty pre_read function, to be defined in the configuration file.
1659 pre_read ()
1660 {
1661 :
1662 }
1663
1664 # End of functions
1665 #
1666 # Start of execution
1667
1668 # Builtin defaults
1669 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
1670 CDDBSUBMIT=freedb-submit@freedb.org
1671 CDDBPROTO=5
1672 HELLOINFO="$(whoami)@$(hostname)"
1673 INTERACTIVE=y
1674 CDROMREADERSYNTAX=cdparanoia
1675 OUTPUTTYPE=ogg
1676 ENCODERSYNTAX=default
1677
1678 MP3ENCODERSYNTAX=default
1679 OGGENCODERSYNTAX=default
1680 FLACENCODERSYNTAX=default
1681 SPEEXENCODERSYNTAX=default
1682 MPPENCODERSYNTAX=default
1683 NORMALIZERSYNTAX=default
1684
1685 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
1686 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
1687 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
1688 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
1689 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
1690 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
1691 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
1692 PLAYLISTDATAPREFIX=''
1693 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
1694 VAPLAYLISTDATAPREFIX=''
1695 DOSPLAYLIST=n
1696 COMMENT=''
1697 ID3TAGV=2
1698 ENCNICE=10
1699 READNICE=10
1700 DISTMP3NICE=10
1701 VARIOUSARTISTS=n
1702 VARIOUSARTISTSTYLE=forward
1703 KEEPWAVS=n
1704 PADTRACKS=n
1705 CDDBCOPYLOCAL="n"
1706 CDDBLOCALDIR="$HOME/.cddb"
1707 CDDBUSELOCAL="n"
1708
1709 # If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
1710 # i.e. CDROMID="1,0,0"
1711 CDROMID=""
1712
1713 # program paths - defaults to checking your $PATH
1714 # mp3
1715 LAME=lame
1716 GOGO=gogo
1717 BLADEENC=bladeenc
1718 L3ENC=l3enc
1719 XINGMP3ENC=xingmp3enc
1720 MP3ENC=mp3enc
1721 # ogg
1722 VORBIZE=vorbize
1723 OGGENC=oggenc
1724 # flac
1725 FLAC=flac
1726 # speex
1727 SPEEXENC=speexenc
1728 # mpp (Musepack)
1729 MPPENC=mppenc
1730
1731 ID3=id3
1732 ID3V2=id3v2
1733 CDPARANOIA=cdparanoia
1734 CDDA2WAV=cdda2wav
1735 DAGRAB=dagrab
1736 CDDAFS=cp
1737 CDDISCID=cd-discid
1738 CDDBTOOL=cddb-tool
1739 EJECT=eject
1740 MD5SUM=md5sum
1741 DISTMP3=distmp3
1742 VORBISCOMMENT=vorbiscomment
1743 METAFLAC=metaflac
1744 NORMALIZE=normalize-audio
1745 CDSPEED=eject
1746 VORBISGAIN=vorbisgain
1747
1748 # Options for programs called from abcde
1749 # mp3
1750 LAMEOPTS=
1751 GOGOOPTS=
1752 BLADEENCOPTS=
1753 L3ENCOPTS=
1754 XINGMP3ENCOPTS=
1755 MP3ENCOPTS=
1756 # ogg
1757 VORBIZEOPTS=
1758 OGGENCOPTS=
1759 # flac
1760 FLACOPTS=
1761 # speex
1762 SPEEXENCOPTS=
1763 # mpc
1764 MPPENCOPTS=
1765
1766 ID3OPTS=
1767 ID3V2OPTS=
1768 CDPARANOIAOPTS=
1769 CDDA2WAVOPTS=
1770 DAGRABOPTS=
1771 CDDAFSOPTS="-f"
1772 CDDBTOOLOPTS=
1773 EJECTOPTS=
1774 DISTMP3OPTS=
1775 NORMALIZEOPTS=
1776 CDSPEEDOPTS="-x"
1777 CDSPEEDVALUE=
1778
1779 # Default to one process if -j isn't specified
1780 MAXPROCS=1
1781
1782 # List of actions to perform - by default, run to completion
1783 ACTIONS=cddb,read,encode,tag,move,clean
1784
1785 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for Linux/OpenBSD/NetBSD.
1786 # Let's use these checkings to determine the OS flavour, which will be used later
1787 if [ X$(uname) = "XFreeBSD" ] ; then
1788         HTTPGET=fetch
1789         NEEDCDROMID=y
1790         OSFLAVOUR=FBSD
1791 elif [ X$(uname) = "XDarwin" ] ; then
1792         HTTPGET=curl
1793         OSFLAVOUR=OSX
1794         # We should have disktool in OSX, but let's be sure...
1795         NEEDDISKTOOL=y
1796 elif [ X$(uname) = "XOpenBSD" ] ; then
1797         HTTPGET=wget
1798         MD5SUM=md5
1799 else
1800         HTTPGET=wget
1801 fi
1802
1803 # If CDDBAVAIL is set to n, no CDDB read is done
1804 # If USEID3 is set to n, no ID3 tagging is done
1805 CDDBAVAIL=y
1806 USEID3=y
1807
1808 if [ -z "$OUTPUTDIR" ]; then
1809         OUTPUTDIR=$(pwd)
1810 fi
1811
1812 if [ -z "$WAVOUTPUTDIR" ]; then
1813         WAVOUTPUTDIR="$OUTPUTDIR"
1814 fi
1815
1816 # Load system defaults
1817 if [ -r /etc/abcde.conf ]; then
1818         . /etc/abcde.conf
1819 fi
1820 # Load user preference defaults
1821 if [ -r $HOME/.abcde.conf ]; then
1822         . $HOME/.abcde.conf
1823 fi
1824
1825 # By this time, we need some HTTPGETOPTS already defined.
1826 # If the user has defined a non-default HTTPGET method, we should not be empty.
1827
1828 if [ "$HTTPGETOPTS" = "" ] ; then
1829         case $HTTPGET in
1830                 wget) HTTPGETOPTS="-q -O -";;
1831                 curl) HTTPGETOPTS="-f -s";;
1832                 fetch)HTTPGETOPTS="-q -o -";;
1833                 *) echo "abcde warning: HTTPGET in non-standard and HTTPGETOPTS are not defined." >&2 ;;
1834         esac
1835 fi
1836
1837 # If the CDROM has not been set yet, find a suitable one.
1838 # If this is a devfs system, default to /dev/cdroms/cdrom0
1839 # instead of /dev/cdrom
1840 if [ "$CDROM" = "" ] ; then
1841         if [ -e /dev/cdroms/cdrom0 ]; then
1842                 CDROM=/dev/cdroms/cdrom0
1843         elif [ -e /dev/cdrom ]; then
1844                 CDROM=/dev/cdrom
1845         elif [ -e /dev/cd0c ]; then
1846                 CDROM=/dev/cd0c
1847         elif [ -e /dev/acd0c ]; then
1848                 CDROM=/dev/acd0c
1849         elif [ -e /dev/disk1 ]; then
1850                 CDROM=/dev/disk1
1851         fi
1852 fi
1853
1854 # Parse command line options
1855 #while getopts 1a:bc:C:d:Dhj:klLnNo:pr:S:t:T:vVx opt ; do
1856 while getopts 1a:A:bc:C:d:Dhj:klLnNo:pr:Rs:S:t:T:vVxw: opt ; do
1857         case "$opt" in
1858                 1) ONETRACK=y ;;
1859                 a) ACTIONS="$OPTARG" ;;
1860                 A) EXPACTIONS="$OPTARG";;
1861                 b) BATCH=y ;;
1862                 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else echo "abcde error: config file \"$OPTARG\" cannot be found." >&2 ; exit 1 ; fi ;;
1863                 C) DISCID="${OPTARG#abcde.}" ;;
1864                 d) CDROM="$OPTARG" ;;
1865                 D) set -x ;;
1866                 h) usage; exit ;;
1867 #               f) FORCECDDBUSELOCAL=y ;;
1868                 i) INLINETAG=y ;;
1869                 j) MAXPROCS="$OPTARG" ;;
1870                 k) KEEPWAVS=y ;;
1871                 l) LOWDISK=y ;;
1872                 L) CDDBUSELOCAL=y ;;
1873                 n) CDDBAVAIL=n ;;
1874                 N) INTERACTIVE=n ;;
1875                 m) DOSPLAYLIST=y ;;
1876                 o) OUTPUTTYPE="$OPTARG" ;;
1877                 p) PADTRACKS=y ;;
1878                 P) USEPIPES=y ;;
1879                 r) REMOTEHOSTS="$OPTARG" ;;
1880                 R) REPLAYGAIN=y ;;
1881                 s) STARTTRACKNUMBER="$OPTARG" ;;
1882                 S) CDSPEEDVALUE="$OPTARG" ;;
1883 #               t) PREPROCESSFORMATS="$OPTARG"
1884 #                  PREPROCESS=y ;;
1885 #               T) POSTPROCESSFORMATS="$OPTARG" ;;
1886                 t) STARTTRACKNUMBER="$OPTARG" ;;
1887                 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
1888                 v) 
1889                    echo "This is abcde v$VERSION."
1890                    echo "Usage: abcde [options] [tracks]"
1891                    echo "abcde -h for extra help"
1892                    exit
1893                    ;;
1894                 V) EXTRAVERBOSE="y" ;;
1895                 x) EJECTCD="y" ;;
1896                 w) COMMENT="$OPTARG" ;;
1897                 ?) usage; exit ;;
1898         esac
1899 done
1900
1901 shift $(($OPTIND - 1))
1902
1903 # Decide if we can continue. TO_REMOVE as soon as we find out about dagrab
1904 if [ "$ONETRACK" = "y" ] ; then 
1905         case "$CDROMREADERSYNTAX" in
1906                 dagrab|debug) echo "abcde error: ONETRACK reading is not suported with "$CDROMREADERSYNTAX" yet"
1907                               exit 1 ;;
1908         esac
1909         if [ "$BATCH" = "y" ]; then
1910                 echo "abcde error: BATCH mode is not compatible with ONETRACK mode"
1911         fi
1912         # It does not matter how many tracks we want. In ONETRACK mode we grab them all
1913         if [ $# -gt 0 ]; then
1914                 vecho "ONETRACK mode selected: grabbing all tracks..."
1915         fi
1916 else
1917         while [ $# -gt 0 ]; do
1918                 # Range parsing code courtesy of Vincent Ho
1919                 RSTART=$(echo $1 | cut -f1 -d-)
1920                 REND=$(echo $1 | cut -f2 -d-)
1921                 if [ "$RSTART" = "$REND" ]; then
1922                         NEWTRACKS="$RSTART"
1923                 else
1924                         NEWTRACKS=$(f_seq_line $RSTART $REND)
1925                 fi
1926                 TRACKQUEUE=$(echo "$TRACKQUEUE" "$NEWTRACKS")
1927                 shift
1928         done
1929 fi
1930
1931 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
1932 # List of experimental actions: retag,transcode
1933
1934 # Determine what actions are to be done from $ACTIONS and set the
1935 # following environment variables for them:
1936 DOCDDB=n
1937 DOREAD=n
1938 DONORMALIZE=n
1939 DOPREPROCESS=n
1940 DOENCODE=n
1941 DOPOSTPROCESS=n
1942 DOTAG=n
1943 DOMOVE=n
1944 DOPLAYLIST=n
1945 DOCLEAN=n
1946
1947 for ACTION in $(echo $ACTIONS | tr , \ )
1948 do
1949         case $ACTION in
1950         cddb) DOCDDB=y;;
1951         read) DOREAD=y;;
1952         normalize) DONORMALIZE=y; DOREAD=y;;
1953 #       preprocess) DOPREPROCESS=y; DOREAD=y;;
1954         encode) DOENCODE=y; DOREAD=y;;
1955 #       postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
1956         tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
1957         move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
1958         playlist) DOCDDB=y; DOPLAYLIST=y;;
1959         clean) DOCLEAN=y;;
1960         esac
1961 done
1962
1963 # Sanity checks:
1964
1965 # At this point a CDROM has to be defined, so we check it exists.
1966 if [ "$CDROM" != "" ] ; then 
1967         if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
1968                 if [ "$OSFLAVOUR" = "FBSD" ]; then
1969                         if ! echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then
1970                                 echo "abcde error: CDROMID not in the right format for $CDROMREADERSYNTAX"
1971                                 echo "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
1972                                 exit 1
1973                         fi
1974                 fi
1975         elif [ ! -e $CDROM ] ; then
1976                 echo "abcde error: CDROM device cannot be found." >&2
1977                 exit 1
1978         fi
1979 else
1980         echo "abcde error: CDROM has not been defined or cannot be found" >&2
1981         exit 1
1982 fi
1983
1984 # Decide which CDROM reader we're gonna use
1985 case "$CDROMREADERSYNTAX" in
1986         cdparanoia|debug)
1987                 CDROMREADER="$CDPARANOIA"
1988                 CDROMREADEROPTS="$CDPARANOIAOPTS"
1989                 ;;
1990         cdda2wav)
1991                 CDROMREADER="$CDDA2WAV"
1992                 CDROMREADEROPTS="$CDDA2WAVOPTS"
1993                 ;;
1994         dagrab)
1995                 CDROMREADER="$DAGRAB"
1996                 CDROMREADEROPTS="$DAGRABOPTS"
1997                 ;;
1998         cddafs)
1999                 CDROMREADER="$CDDAFS"
2000                 CDROMREADEROPTS="$CDDAFSOPTS"
2001                 ;;
2002 esac
2003
2004 # There's only one normalize...
2005 case "$NORMALIZERSYNTAX" in
2006         default|normalize)
2007                 NORMALIZER="$NORMALIZE"
2008                 NORMALIZEROPTS="$NORMALIZEOPTS"
2009                 ;;
2010 esac
2011
2012 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac for flacs and speexenc for speex and mppenc for mpps
2013
2014 # Getting ready for multiple output changes
2015 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
2016 do
2017         case $OUTPUT in
2018                 ogg)  [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
2019                       [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
2020                       [ "$REPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
2021                         ;;
2022                 mp3)  [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
2023                       [ "$DOTAG" = "y" ] && NEEDTAGGER=y
2024                         ;;
2025                 flac) [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
2026                       [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
2027                         ;;
2028                 spx) [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc ;;
2029                 mpc) [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc ;;
2030                 *) echo "abcde error: Invalid OUTPUTTYPE defined" >&2
2031                    exit 1
2032                    ;;
2033         esac
2034 done
2035
2036 # decide which encoder
2037 case "$MP3ENCODERSYNTAX" in
2038         lame)
2039                 MP3ENCODEROPTS="$LAMEOPTS"
2040                 MP3ENCODER="$LAME"
2041                 ;;
2042         gogo)
2043                 MP3ENCODEROPTS="$GOGOOPTS"
2044                 MP3ENCODER="$GOGO"
2045                 ;;
2046         bladeenc)
2047                 MP3ENCODEROPTS="$BLADEENCOPTS"
2048                 MP3ENCODER="$BLADEENC"
2049                 ;;
2050         l3enc)
2051                 MP3ENCODEROPTS="$L3ENCOPTS"
2052                 MP3ENCODER="$L3ENC"
2053                 ;;
2054         xingmp3enc)
2055                 MP3ENCODEROPTS="$XINGMP3ENCOPTS"
2056                 MP3ENCODER="$XINGMP3ENC"
2057                 ;;
2058         mp3enc)
2059                 MP3ENCODEROPTS="$MP3ENCOPTS"
2060                 MP3ENCODER="$MP3ENC"
2061                 ;;
2062 esac
2063 case "$OGGENCODERSYNTAX" in
2064         vorbize)
2065                 OGGENCODEROPTS="$VORBIZEOPTS"
2066                 OGGENCODER="$VORBIZE"
2067                 ;;
2068         oggenc)
2069                 OGGENCODEROPTS="$OGGENCOPTS"
2070                 OGGENCODER="$OGGENC"
2071                 ;;
2072 esac
2073 case "$FLACENCODERSYNTAX" in
2074         flac)
2075                 FLACENCODEROPTS="$FLACOPTS"
2076                 FLACENCODER="$FLAC"
2077                 ;;
2078 esac
2079 case "$SPEEXENCODERSYNTAX" in
2080         speexenc)
2081                 SPEEXENCODEROPTS="$SPEEXENCOPTS"
2082                 SPEEXENCODER="$SPEEXENC"
2083                 ;;
2084 esac
2085 case "$MPPENCODERSYNTAX" in
2086         mppenc)
2087                 MPPENCODEROPTS="$MPPENCOPTS"
2088                 MPPENCODER="$MPPENC"
2089                 ;;
2090 esac
2091
2092 # and which tagger
2093
2094 if [ "$ID3TAGV" = "1" ]; then
2095         TAGGER="$ID3"
2096         TAGGEROPTS="$ID3OPTS"
2097 else
2098         TAGGER="$ID3V2"
2099         TAGGEROPTS="$ID3V2OPTS"
2100 fi
2101
2102 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
2103
2104 if [ "$ENCNICE" ]; then
2105         ENCNICE="-n $ENCNICE"
2106 fi
2107 if [ "$READNICE" ]; then
2108         READNICE="-n $READNICE"
2109 fi
2110 if [ "$DISTMP3NICE" ]; then
2111         DISTMP3NICE="-n $DISTMP3NICE"
2112 fi
2113
2114 # Don't check for stuff if it's not needed
2115 if [ "$REMOTEHOSTS" ]; then NEEDDISTMP3=y; fi
2116 [ "$DONORMALIZE" = "y" ] && NEEDNORMALIZER=y
2117 [ "$EJECTCD" = "y" ] && NEEDEJECT=y
2118 [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ] && NEEDHTTPGET=y
2119
2120 if [ X"$CDSPEEDVALUE" != "X" ]; then
2121         case "$CDROMREADERSYNTAX" in
2122                 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
2123                 *) NEEDCDSPEED=y ;;
2124         esac
2125 fi
2126
2127
2128 # Make sure a buncha things exist
2129 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
2130         $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
2131         ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
2132         ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
2133         ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
2134         ${NEEDDISKTOOL+disktool} ${NEEDCDSPEED+$CDSPEED} \
2135         ${NEEDVORBISGAIN+$VORBISGAIN}
2136 do
2137         # Cut off the command-line options we just added in
2138         X=$(echo $X | cut -d' ' -f2)
2139         if [ "$(which $X)" = "" ]; then
2140                 echo "abcde error: $X is not in your path." >&2
2141                 exit 1
2142         elif [ ! -x $(which $X) ]; then
2143                 echo "abcde error: $X is not executable." >&2
2144                 exit 1
2145         fi
2146 done
2147
2148 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
2149 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
2150 HTTPGET="$HTTPGET $HTTPGETOPTS"
2151
2152 # Here it used to say:
2153 # One thousand lines in, we can start doing stuff with things
2154 # Well, right now we are at line 2157 ;)
2155
2156 # Export needed things so they can be read in this subshell
2157 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
2158 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
2159
2160 # User-definable function to set some things. Use it for
2161 #  - closing the CD tray with eject -t
2162 #  - set the CD speed value with eject -x
2163 vecho -n "Executing customizable pre-read function... "
2164
2165 pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
2166
2167 vecho "done."
2168
2169 do_discid # Get ABCDETEMPDIR created and status file initialized
2170
2171 if [ "$DOCDDB" = "y" ]; then
2172         if [ $CDDBUSELOCAL = "y" ]; then
2173                 do_localcddb
2174         fi
2175         if checkstatus cddb-choice > /dev/null; then
2176                 :
2177         else 
2178                 if [ ! "$CDDBLOCALSUCCESS" = "y" ] ; then
2179                         do_cddbstat
2180                         do_cddbquery
2181                         do_cddbread
2182                 fi
2183         fi
2184         do_cddbedit
2185
2186         eval $($CDDBTOOL parse "$CDDBDATA")
2187 fi
2188
2189 # Before reading tracks, we set the speed of the device
2190
2191 if [ X"$CDSPEEDVALUE" != "X" ]; then
2192         case "$CDROMREADERSYNTAX" in
2193                 cdparanoia|debug) : ;;
2194                 *) do_cdspeed ;;
2195         esac
2196 fi
2197
2198 if [ "$STRIPDATATRACKS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
2199         case "$CDROMREADERSYNTAX" in
2200                 cdparanoia|debug) 
2201                         # cdparanoia can query the CD, so let's process the TRACKQUEUE list with the results.
2202                         if checkstatus cdparanoia-audio-tracks; then
2203                                 CDTRACKQUEUE=$( cat $ABCDETEMPDIR/cdparanoia-audio-tracks )
2204                         else
2205                                 ## FIXME ##
2206                                 vecho "Querying the CD to obtain a list of valid audio tracks..."
2207                                 $CDROMREADER -Q > $ABCDETEMPDIR/cdparanoia-query 2>&1
2208                                 # Obtain a list of valid audio tracks from the results of the query
2209                                 CDTRACKQUEUE=$( cat $ABCDETEMPDIR/cdparanoia-query | egrep '^[[:space:]]+[[:digit:]]' | awk '{print $1}' | tr -d "." | tr '\n' ' ' )
2210                         fi
2211                         # Obtain the track padding value from the before-processing list and pad the CD list
2212                         TRACKNUMPADDING=$( echo $TRACKQUEUE | awk '{print $1}' | tr -d " \n" | wc -c )
2213                         for TRACK in $CDTRACKQUEUE ; do
2214                                 TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${TRACK} + 0 ))
2215                                 PADNEWTRACKQUEUE=$(echo $PADNEWTRACKQUEUE $TRACKNUM)
2216                         done
2217                         CDTRACKQUEUE=$PADNEWTRACKQUEUE
2218                         # Now, compare if the values in the list are valid tracks in the CD
2219                         for TRACK in $TRACKQUEUE; do
2220                                 if echo $CDTRACKQUEUE | grep $TRACK >/dev/null ; then
2221                                         NEWTRACKQUEUE="$NEWTRACKQUEUE $TRACK"
2222                                 fi
2223                         done
2224                         TRACKQUEUE="$NEWTRACKQUEUE"
2225                 ;;
2226         esac
2227 fi
2228
2229 # Create playlist if needed (backgroundable) and start reading in tracks
2230
2231 (
2232
2233 if [ "$ONETRACK" = "y" ]; then :; else
2234         if [ "$DOPLAYLIST" = "y" ]; then
2235                 echo Creating playlist... >&2
2236                 do_playlist
2237         fi
2238 fi
2239
2240 # For the lowdisk option, only one program is running at once so the encoder
2241 # can be unsilenced right away.
2242 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
2243         echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
2244 fi
2245
2246 if [ "$ONETRACK" = "y" ]; then 
2247         FIRSTTRACK=$( echo $TRACKQUEUE | awk '{print $1}' )
2248         TRACKS="$FIRSTTRACK"
2249         for UTRACKNUM in $TRACKQUEUE; do :;done
2250         if checkstatus readtrack-$FIRSTTRACK; then :; else
2251                 do_cdread_one $UTRACKNUM $FIRSTTRACK
2252         fi
2253 else
2254         for UTRACKNUM in $TRACKQUEUE
2255         do
2256                 if [ "$DOREAD" = "y" ]; then
2257                         if checkstatus readtrack-$UTRACKNUM; then :; else
2258                                 do_cdread $UTRACKNUM
2259                                 if [ "$?" != "0" ]; then
2260                                         # CD read failed - don't give the goahead to
2261                                         # the encoder
2262                                         echo NO
2263                                         exit
2264                                 fi
2265                         fi
2266                 fi
2267                 if [ "$BATCH" = "y" ]; then
2268                     :
2269                 else
2270                         echo NEXTTRACK # Get the encoder machine churning again
2271                         if [ "$DOREAD" = "y" ]; then
2272                                 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
2273                                         until checkstatus encodetrack-$UTRACKNUM
2274                                         do
2275                                                 if checkerrors encodetrack-$UTRACKNUM; then
2276                                                         break
2277                                                 fi
2278                                                 sleep 2
2279                                         done
2280                                 fi
2281                         fi
2282                 fi
2283         done
2284 fi
2285
2286 # Now that we're done the encoding can be loud again -
2287 # if we're not using SMP.
2288 if [ "$MAXPROCS" = "1" ]; then
2289         echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
2290 fi
2291
2292 # All tracks read, start encoding.
2293 if [ "$BATCH" = "y" ] || [ "$ONETRACK" = "y" ]; then
2294         echo NEXTTRACK
2295 fi
2296
2297 # We are now finished with the cdrom - it can be safely ejected. Note that
2298 # abcde will not have completed yet.
2299 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
2300         # We check if the disk we are processing is actually the disk inside the 
2301         # CD tray. If not, we do not eject the CD, since it might be so that the
2302         # user ejected it manually.
2303         #CURRENTTRACKINFO=$($CDDISCID $CDROM)
2304         #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then 
2305         # More FreeBSD bits.
2306         if [ X"$(uname)" = X"FreeBSD" ] ; then
2307                 # FreeBSD eject uses the EJECT environment variable to name the CDROM
2308                 # but in this script EJECT is in the envionment and names the program
2309                 eject=$EJECT
2310                 unset EJECT
2311                 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
2312                 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
2313                 $eject $EJECTOPTS $cd
2314         elif [ X"$(uname)" = X"Darwin" ] ; then
2315                 disktool -e ${CDROM#/dev/} 0
2316         else
2317                 $EJECT $EJECTOPTS $CDROM
2318         fi
2319         #fi
2320 fi
2321
2322 ) | (
2323
2324 ## Do we need to pre-process 
2325 #if [ x"$PREPROCESS" = "x" ] ; then
2326 #       cat
2327 #else
2328 #       for PRETRACKNUM in $TRACKQUEUE
2329 #       do
2330 #               read GOAHEAD
2331 #               if [ "$GOAHEAD" = "NO" ]; then break; fi
2332 #               PREPROCEED=
2333 #               until [ $PREPROCEED ]
2334 #               do
2335 #                       if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
2336 #                       # all locations are working, wait and try again later
2337 #                       if [ ! $PREPROCEED ]; then sleep 3; fi
2338 #               done
2339 #               ( do_preprocess $PRETRACKNUM 
2340 #               echo "NEXTTRACK"
2341 #               ) &
2342 #       done
2343 #fi
2344 #
2345 #) | (
2346
2347 # In batch mode, we want all tracks to be read first.
2348 if [ "$BATCH" = "y" ]; then
2349         read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
2350         if [ "$GOAHEAD" = "NO" ]; then break; fi
2351         for LASTTRACK in $TRACKQUEUE; do :; done
2352         if checkstatus readtrack-$LASTTRACK; then
2353                 if [ "$DONORMALIZE" = "y" ]; then
2354                         if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
2355                         if checkerrors batch-normalize; then exit; fi
2356                 fi
2357                 if [ "$DOENCODE" = "y" ]; then
2358                         if checkstatus encodetrack-$LASTTRACK; then :; else do_batch_encode; fi
2359                         if checkerrors batch-encode; then exit; fi
2360                 fi
2361         fi
2362 fi
2363
2364 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
2365 if [ "$ONETRACK" = "y" ] ; then
2366         FIRSTTRACK=$( echo $TRACKQUEUE | awk '{print $1}')
2367         TRACKQUEUE=$FIRSTTRACK
2368         TRACKS="$FIRSTTRACK"
2369 fi
2370
2371 # Do the encoding, including parallelization of remote encoding
2372 # Figure out where each track is going to be encoded
2373 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
2374 if [ "$MAXPROCS" != "0" ]; then
2375         for NUM in $(f_seq_row 1 "$MAXPROCS")
2376         do
2377                 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
2378         done
2379 fi
2380 # Strip whitespace
2381 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
2382 for UTRACKNUM in $TRACKQUEUE
2383 do
2384         # Wait for our cue
2385         read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
2386         if [ "$GOAHEAD" = "NO" ]; then break; fi
2387         # find out where this track is to be encoded
2388         if [ "$DOENCODE" = "y" ]; then
2389                 # Make sure we have a place to encode this, if not, exit stage right
2390                 if [ -z "$ENCODELOCATIONS" ]; then
2391                         continue
2392                 fi
2393                 PROCEED=
2394                 until [ $PROCEED ]
2395                 do
2396                         for LOCATION in $ENCODELOCATIONS
2397                         do
2398                                 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
2399                                 # check first if a track has ever been assigned to this location
2400                                 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
2401                                 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
2402                                 if checkerrors encodetrack-$PREVIOUSTRACK; then
2403                                         for TEMPLOCATION in $ENCODELOCATIONS
2404                                         do
2405                                                 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
2406                                                         TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
2407                                                 fi
2408                                         done
2409                                         ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
2410                                         ABORT=y
2411                                         PROCEED=y
2412                                         break
2413                                 fi
2414                                 # We're still here, this location must have been previously assigned,
2415                                 # and last completed without error - check if it's done with the
2416                                 # previous track yet
2417                                 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
2418                         done
2419                         # all locations are working, wait and try again later
2420                         if [ ! $PROCEED ]; then sleep 3; fi
2421                 done
2422                 # Record the location we're about to encode the next track at
2423                 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
2424         fi
2425         # Don't proceed with the rest of the loop if we can't encode
2426         if [ "$ABORT" ]; then continue; fi
2427         # Set TRACKNUM, TRACKNAME
2428         if [ -e "$CDDBDATA" ]; then
2429                 if [ "$ONETRACK" = "y" ]; then 
2430                         TRACKNAME="$DALBUM"
2431                         TRACKNUM="$FIRSTTRACK"
2432                         splitvarious
2433                 else
2434 #                       TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${UTRACKNUM} + 0))
2435                         TRACKNUM=$UTRACKNUM
2436                         CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2437                         TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
2438                         splitvarious
2439                 fi
2440         fi
2441         # You can't encode a file which needs to be normalized before finishing
2442         # You can't tag a file before it's finished encoding -
2443         # thus all of this is backgrounded together
2444         (
2445         if [ "$DONORMALIZE" = "y" ]; then
2446                 if checkstatus readtrack-$UTRACKNUM; then
2447                         if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
2448                 fi
2449         fi
2450         if [ "$DOENCODE" = "y" ]; then
2451                 if checkstatus readtrack-$UTRACKNUM; then
2452                         #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
2453                         if [ "$DONORMALIZE" = "y" ]; then
2454                                 if checkstatus normalizetrack-$UTRACKNUM; then
2455                                         if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
2456                                 fi
2457                         else
2458                                 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
2459                         fi
2460                 fi
2461         fi
2462         if [ "$DOTAG" = "y" ]; then
2463                 if checkstatus encodetrack-$UTRACKNUM; then
2464                         if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
2465                 fi
2466         fi
2467         if [ "$DOMOVE" = "y" ]; then
2468                 if checkstatus tagtrack-$UTRACKNUM; then
2469                         if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
2470                 fi
2471         fi
2472         ) &
2473 done
2474 # Go through it again and make sure there's no distmp3 stragglers, otherwise
2475 # we'll delete the files they're working on
2476 if [ "$DOENCODE" = "y" ]; then
2477         PROCEED=
2478         until [ $PROCEED ]
2479         do
2480                 PROCEED=y
2481                 for LOCATION in $ENCODELOCATIONS
2482                 do
2483                         CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
2484                         # "How can he give us a status update, if he's DEAD?"
2485                         if checkstatus encodetrack-$CHECKTRACK; then
2486                                 continue
2487                         fi
2488                         # Nothing to see here please go quietly back to your homes
2489                         if [ -z "$CHECKTRACK" ]; then continue; fi
2490                         # You're still here? Maybe there is something...
2491                         if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
2492                 done
2493                 # hold up
2494                 if [ ! $PROCEED ]; then sleep 5; fi
2495         done
2496 fi
2497 # If the above didn't catch the stragglers, this will
2498 wait
2499 # Check to see if run_command logged any errors
2500 if [ -f "$ABCDETEMPDIR/errors" ]; then
2501         echo "The following commands failed to run:"
2502         cat "$ABCDETEMPDIR/errors"
2503         # Don't clean up
2504         DOCLEAN=n
2505 fi
2506 if [ "$KEEPWAVS" = "y" ];then
2507         # Don't clean up
2508         DOCLEAN=n
2509 fi
2510 if [ "$DOCLEAN" = "y" ]; then
2511         # Wipe all the evidence
2512         # Gimme gimme gimme some more time!
2513         sleep 5
2514         rm -rf "$ABCDETEMPDIR"
2515         echo "Finished."
2516 else
2517         echo "Finished. Not cleaning $ABCDETEMPDIR."
2518 fi
2519 )
2520 exit 0