Rework the move code to not move a set of files if the tagging failed.
[abcde.git] / abcde
1 #!/bin/sh
2 # Copyright (c) 1998-2001 Robert Woodcock <rcw@debian.org>
3 # Copyright (c) 2003-2005 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.3.99-$Id$"
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 <action1[,action2]...>"
23 echo "       Actions to perform (cddb,read,normalize,encode,tag,move,playlist,clean)"
24 #echo "-A     Experimental actions (retag, transcode)"
25 echo "-b     Batch mode: enable album normalization and nogap encoding"
26 echo "-c <file>"
27 echo "       Specify a configuration file (overrides system and user config files)"
28 echo "-C <discid#>"
29 echo "       Specify discid to resume from (only needed if you no longer have the cd)"
30 echo "-d <device>"
31 echo "       Specify CDROM device to grab"
32 echo "-D     Debugging mode (equivalent to sh -x abcde)"
33 echo "-e     Erase encoded track information from status file"
34 #echo "-E     Set the encoding information for the tags"
35 echo "-h     This help information"
36 #echo "-i    Tag files while encoding, when possible (local only) -NWY-"
37 echo "-j <#> Number of encoder processes to run at once (localhost)"
38 echo "-k     Keep the wav tracks for later use"
39 echo "-l     Use low disk space algorithm"
40 echo "-L     Use local CDDB storage directory"
41 echo "-n     No lookup. Don't query CDDB, just create and use template"
42 echo "-N     Noninteractive. Never prompt for anything"
43 echo "-m     Modify playlist to include CRLF endings, to comply with some players"
44 echo "-M     Create a CUE file"
45 echo "-o <type1[,type2]...>"
46 echo "       Output file type(s) (vorbis,mp3,flac,spx,mpc). Defaults to vorbis"
47 echo "-p     Pad track numbers with 0's (if less than 10 tracks)"
48 echo "-P     Use UNIX pipes to read+encode without wav files"
49 echo "-r <host1[,host2]...>"
50 echo "       Also encode on these remote hosts"
51 echo "-R     Add replaygain values to the tag info (only for vorbis,flac)"
52 echo "-s <field>"
53 echo "       Show dielfs from the CDDB info (year,genre)"
54 echo "-S <#> Set the CD speed"
55 #echo "-t    File types to preprocess (wav)"
56 #echo "-T    Set postprocessing options"
57 echo "-t <#> Start the track numbering at a given number"
58 echo "-T <#> Same as -t but modifies tag numbering"
59 echo "-v     Show version number and exit"
60 echo "-V     Be a bit more verbose about what is happening behind the scenes"
61 echo "-x     Eject CD after all tracks are read"
62 echo "-w <comment>"
63 echo "       Add a comment to the CD tracks"
64 echo "-W <#> Contatenate CDs: -T #01 -w \"CD #\"" 
65 echo ""
66 echo "Tracks is a space-delimited list of tracks to grab."
67 echo "Ranges specified with hyphens are allowed (i.e., 1-5)."
68 echo ""
69 #echo "Double hyphens are used to concatenate tracks"
70 }
71
72 # Funtions to replace the need of seq, which is too distribution dependant.
73 f_seq_row ()
74 {
75         i=$1
76         while [ $i -ne `expr $2 + 1` ]
77         do
78                 echo $i
79                 i=`expr $i + 1`
80         done
81 }
82
83 f_seq_line ()
84 {
85         i=$1
86         while [ $i -ne `expr $2 + 1` ]
87         do
88                 printf $i" "
89                 i=`expr $i + 1`
90         done
91         echo
92 }
93
94 # Functions to replace the need of awk {print $1} and {print $NF}
95 get_first()
96 {
97 if [ X"$1" = "X" ]; then
98         for first in `cat`; do
99                 break
100         done
101 else
102         first=$1
103 fi
104 echo $first
105 }
106
107 get_last()
108 {
109 if [ X"$1" = "X" ]; then
110         for stdin in `cat`; do
111                 last=$stdin
112         done
113 else
114         for last in $@ ; do :; done
115 fi
116 echo $last
117 }
118
119 # checkstatus [blurb]
120 # Returns "0" if the blurb was found, returns 1 if it wasn't
121 # Puts the blurb content, if available, on stdout.
122 # Otherwise, returns "".
123 checkstatus ()
124 {
125         # Take the last line in the status file if there's multiple matches
126         PATTERN="^$1(=.*)?$"
127         BLURB=$(egrep $PATTERN "$ABCDETEMPDIR/status" | tail -n 1)
128
129         if [ -z "$BLURB" ]; then
130                 # No matches found
131                 return 1
132         else
133                 # Matches found
134                 # See if there's a = in it
135                 if [ "$(echo $BLURB | grep -c =)" != "0" ]; then
136                         echo "$(echo $BLURB | cut -f2- -d=)"
137                 fi
138                 return 0
139         fi
140 }
141
142 # checkerrors [blurb]
143 # Returns "0" if the blurb was found (meaning there was an error),
144 # returns 1 if it wasn't (yes this is a little backwards).
145 # Does not print the blurb on stdout.
146 # Otherwise, returns "".
147 checkerrors ()
148 {
149         if [ -e "$ABCDETEMPDIR/errors" ]; then :; else
150                 return 1
151         fi
152         # Take the last line in the status file if there's multiple matches
153         PATTERN="^$1(:.*)?$"
154         BLURB="$(egrep $PATTERN "$ABCDETEMPDIR/errors" | tail -n 1)"
155
156         if [ -z "$BLURB" ]; then
157                 # negative, we did not have a negative...
158                 return 1
159         else
160                 # affirmative, we had a negative...
161                 return 0
162         fi
163 }
164
165 # page [file]
166 # Finds the right pager in the system to display a file
167 page ()
168 {
169         PAGEFILE="$1"
170         # Use the debian sensible-pager wrapper to pick the pager
171         # user has requested via their $PAGER environment variable
172         if [ -x "/usr/bin/sensible-pager" ]; then
173                 /usr/bin/sensible-pager "$PAGEFILE"
174         elif [ -x "$PAGER" ]; then
175                 # That failed, try to load the preferred editor, starting
176                 # with their PAGER variable
177                 $PAGER "$PAGEFILE"
178                 # If that fails, check for less
179         elif [ -x /usr/bin/less ]; then
180                 /usr/bin/less -f "$PAGEFILE"
181                 # more should be on all UNIX systems
182         elif [ -x /bin/more ]; then
183                 /bin/more "$PAGEFILE"
184         else
185                 # No bananas, just cat the thing
186                 cat "$PAGEFILE" >&2
187         fi
188 }
189
190 # run_command [blurb] [command...]
191 # Runs a command, silently if necessary, and updates the status file
192 run_command ()
193 {
194         BLURB="$1"
195         shift
196         # See if this is supposed to be silent
197         if [ "$(checkstatus encode-output)" = "loud" ]; then
198                 "$@" >&2
199                 RETURN=$?
200         else
201                 # Special case for SMP, since
202                 # encoder output is never displayed, don't mute echos
203                 if [ -z "$BLURB" -a "$MAXPROCS" != "1" ]; then
204                         "$@" >&2
205                         RETURN=$?
206                 else
207                         "$@" >/dev/null 2>&1
208                         RETURN=$?
209                 fi
210         fi
211         case "$1" in
212         normalize|normalize-audio)
213                 if [ "$RETURN" = "2" ]; then
214                         # File was already normalized.
215                         RETURN=0
216                 fi
217                 ;;
218         esac
219         if [ "$RETURN" != "0" ]; then
220                 # Put an error in the errors file. For various reasons we
221                 # can't capture a copy of the program's output but we can
222                 # log what we attempted to execute and the error code
223                 # returned by the program.
224                 if [ "$BLURB" ]; then
225                         TWEAK="$BLURB: "
226                 fi
227                 echo "${TWEAK}returned code $RETURN: $@" >> "$ABCDETEMPDIR/errors"
228                 return $RETURN # Do not pass go, do not update the status file
229         fi
230         if [ "$BLURB" ]; then
231                 echo $BLURB >> "$ABCDETEMPDIR/status"
232         fi
233 }
234
235 # relpath() and slash() are Copyright (c) 1999 Stuart Ballard and
236 # distributed under the terms of the GNU GPL v2 or later, at your option
237
238 # Function to determine if a word contains a slash.
239 slash ()
240 {
241         case "$1" in
242         */*) return 0;;
243         *) return 1;;
244         esac
245 }
246
247 # Function to give the relative path from one file to another.
248 # Usage: relpath fromfile tofile
249 # eg relpath music/Artist/Album.m3u music/Artist/Album/Song.mp3
250 # (the result would be Album/Song.mp3)
251 # Output is relative path to $2 from $1 on stdout
252
253 # This code has the following restrictions:
254 # Multiple ////s are not collapsed into single /s, with strange effects.
255 # Absolute paths and ../s are handled wrong in FR (but they work in TO)
256 # If FR is a directory it must have a trailing /
257
258 relpath ()
259 {
260         FR="$1"
261         TO="$2"
262
263         case "$TO" in
264         /*) ;; # No processing is needed for absolute paths
265         *)
266                 # Loop through common prefixes, ignoring them.
267                 while slash "$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
268                 do
269                         FR="$(echo "$FR" | cut -d/ -f2-)"
270                         TO="$(echo "$TO" | cut -d/ -f2-)"
271                 done
272                 # Loop through directory portions left in FR, adding appropriate ../s.
273                 while slash "$FR"
274                 do
275                         FR="$(echo "$FR" | cut -d/ -f2-)"
276                         TO="../$TO"
277                 done
278                 ;;
279         esac
280
281         echo $TO
282 }
283
284 # do_getcddbinfo
285 # Finds an specific field from cddbinfo
286
287 #       TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2 -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')
288 #       TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
289 #       TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
290
291 do_getcddbinfo()
292 {
293         case $1 in
294         TRACKNAME1)
295                 TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
296                 ;;
297         TRACKNAME)
298                 TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
299                 ;;
300         esac
301 }
302
303 # do_gettracknum
304 # Get the track number we are going to use for different actions
305 do_gettracknum()
306 {
307         if [ -n "$STARTTRACKNUMBER" ] ; then
308                 # Get the trackpadding from the current track
309                 CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
310                 TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - $FIRSTTRACK ))
311         else
312                 TRACKNUM=${UTRACKNUM}
313         fi
314 }
315
316 do_replaygain()
317 {
318         run_command "" echo "Adding reply-gain information..."
319         for OUTPUT in $( echo $OUTPUTTYPE | tr , \ )
320         do
321                 OUTPUTFILES=""
322                 for UTRACKNUM in $TRACKQUEUE
323                 do
324                         CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
325                         do_getcddbinfo TRACKNAME
326                         splitvarious
327                         TRACKFILE=$(mungefilename "$TRACKNAME")
328                         ARTISTFILE=$(mungefilename "$TRACKARTIST")
329                         ALBUMFILE=$(mungefilename "$DALBUM")
330                         do_gettrucknum
331                         if [ "$VARIOUSARTISTS" = "y" ]; then
332                                 OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
333                         else
334                                 OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
335                         fi
336                         OUTPUTFILES="$OUTPUTDIR/$OUTPUTFILE.$OUTPUT $OUTPUTFILES"
337                 done
338                 case "$OUTPUT" in
339                         flac);;
340                         ogg);;
341                         *);;
342                 esac
343                 echo vorbisgain-$OUTPUT >> "$ABCDETEMPDIR/status"
344         done
345         echo vorbisgain >> "$ABCDETEMPDIR/status"
346 }
347
348 # This code splits the a Various Artist track name from one of the following
349 # forms:
350 #
351 #  forward:        Artist / Track
352 #  forward-dash:   Artist - Track
353 #  reverse:        Track / Artist
354 #  reverse-dash:   Track - Artist
355 #  colon:          Artist: Track
356 #  trailing-paren: Artist (Track)
357 #
358 # variables used:
359 # VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
360 splitvarious ()
361 {
362         if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
363                 case "$VARIOUSARTISTSTYLE" in
364                 forward)
365                         DTITLEARTIST=$(echo "$TRACKNAME" | sed 's- / -~-g')
366                         TRACKARTIST=$(echo "$DTITLEARTIST" | cut -f1 -d~)
367                         TRACKNAME=$(echo "$DTITLEARTIST" | cut -f2 -d~)
368                         ;;
369                 forward-dash)
370                         DTITLEARTIST=$(echo "$TRACKNAME" | sed 's, - ,~,g')
371                         TRACKARTIST=$(echo "$DTITLEARTIST" | cut -f1 -d~)
372                         TRACKNAME=$(echo "$DTITLEARTIST" | cut -f2 -d~)
373                         ;;
374                 reverse)
375                         DTITLEARTIST=$(echo "$TRACKNAME" | sed 's- / -~-g')
376                         TRACKARTIST=$(echo "$DTITLEARTIST" | cut -f2 -d~)
377                         TRACKNAME=$(echo "$DTITLEARTIST" | cut -f1 -d~)
378                         ;;
379                 reverse-dash)
380                         DTITLEARTIST=$(echo "$TRACKNAME" | sed 's, - ,~,g')
381                         TRACKARTIST=$(echo "$DTITLEARTIST" | cut -f2 -d~)
382                         TRACKNAME=$(echo "$DTITLEARTIST" | cut -f1 -d~)
383                         ;;
384                 colon)
385                         DTITLEARTIST=$(echo "$TRACKNAME" | sed 's-: -~-g')
386                         TRACKARTIST=$(echo "$DTITLEARTIST" | cut -f1 -d~)
387                         TRACKNAME=$(echo "$DTITLEARTIST" | cut -f2 -d~)
388                         ;;
389                 trailing-paren)
390                         DTITLEARTIST=$(echo "$TRACKNAME" | sed 's,^\(.*\) (\(.*\)),\1~\2,')
391                         TRACKARTIST=$(echo "$DTITLEARTIST" | cut -f2 -d~)
392                         TRACKNAME=$(echo "$DTITLEARTIST" | cut -f1 -d~)
393                         ;;
394                 esac
395         elif [ "$VARIOUSARTISTS" = "y" ] && [ "$ONETRACK" = "y" ]; then
396                 TRACKARTIST="Various"
397         else
398                 TRACKARTIST="$DARTIST"
399         fi
400 }
401
402 do_getgenreid () {
403 local genre=$(echo "${@}" | tr '[A-Z]' '[a-z]')
404 local id=""
405         case ${genre} in
406                 "blues")                 id=0 ;;
407                 "classic rock")          id=1 ;;
408                 "country")               id=2 ;;
409                 "dance")                 id=3 ;;
410                 "disco")                 id=4 ;;
411                 "funk")                  id=5 ;;
412                 "grunge")                id=6 ;;
413                 "hip-hop")               id=7 ;;
414                 "jazz")                  id=8 ;;
415                 "metal")                 id=9 ;;
416                 "new age")               id=10 ;;
417                 "oldies")                id=11 ;;
418                 "other")                 id=12 ;;
419                 "pop")                   id=13 ;;
420                 "r&b")                   id=14 ;;
421                 "rap")                   id=15 ;;
422                 "reggae")                id=16 ;;
423                 "rock")                  id=17 ;;
424                 "techno")                id=18 ;;
425                 "industrial")            id=19 ;;
426                 "alternative")           id=20 ;;
427                 "ska")                   id=21 ;;
428                 "death metal")           id=22 ;;
429                 "pranks")                id=23 ;;
430                 "soundtrack")            id=24 ;;
431                 "euro-techno")           id=25 ;;
432                 "ambient")               id=26 ;;
433                 "trip-hop")              id=27 ;;
434                 "vocal")                 id=28 ;;
435                 "jazz+funk")             id=29 ;;
436                 "fusion")                id=30 ;;
437                 "trance")                id=31 ;;
438                 "classical")             id=32 ;;
439                 "instrumental")          id=33 ;;
440                 "acid")                  id=34 ;;
441                 "house")                 id=35 ;;
442                 "game")                  id=36 ;;
443                 "sound clip")            id=37 ;;
444                 "gospel")                id=38 ;;
445                 "noise")                 id=39 ;;
446                 "alt. rock")             id=40 ;;
447                 "bass")                  id=41 ;;
448                 "soul")                  id=42 ;;
449                 "punk")                  id=43 ;;
450                 "space")                 id=44 ;;
451                 "meditative")            id=45 ;;
452                 "instrum. pop")          id=46 ;;
453                 "instrum. rock")         id=47 ;;
454                 "ethnic")                id=48 ;;
455                 "gothic")                id=49 ;;
456                 "darkwave")              id=50 ;;
457                 "techno-indust.")        id=51 ;;
458                 "electronic")            id=52 ;;
459                 "pop-folk")              id=53 ;;
460                 "eurodance")             id=54 ;;
461                 "dream")                 id=55 ;;
462                 "southern rock")         id=56 ;;
463                 "comedy")                id=57 ;;
464                 "cult")                  id=58 ;;
465                 "gangsta")               id=59 ;;
466                 "top 40")                id=60 ;;
467                 "christian rap")         id=61 ;;
468                 "pop/funk"|"pop / funk") id=62 ;;
469                 "jungle")                id=63 ;;
470                 "native american")       id=64 ;;
471                 "cabaret")               id=65 ;;
472                 "new wave")              id=66 ;;
473                 "psychadelic")           id=67 ;;
474                 "rave")                  id=68 ;;
475                 "showtunes")             id=69 ;;
476                 "trailer")               id=70 ;;
477                 "lo-fi")                 id=71 ;;
478                 "tribal")                id=72 ;;
479                 "acid punk")             id=73 ;;
480                 "acid jazz")             id=74 ;;
481                 "polka")                 id=75 ;;
482                 "retro")                 id=76 ;;
483                 "musical")               id=77 ;;
484                 "rock & roll")           id=78 ;;
485                 "hard rock")             id=79 ;;
486                 "folk")                  id=80 ;;
487                 "folk/rock")             id=81 ;;
488                 "national folk")         id=82 ;;
489                 "swing")                 id=83 ;;
490                 "fusion")                id=84 ;;
491                 "bebob")                 id=85 ;;
492                 "latin")                 id=86 ;;
493                 "revival")               id=87 ;;
494                 "celtic")                id=88 ;;
495                 "bluegrass")             id=89 ;;
496                 "avantgarde")            id=90 ;;
497                 "gothic rock")           id=91 ;;
498                 "progress. rock")        id=92 ;;
499                 "psychadel. rock")       id=93 ;;
500                 "symphonic rock")        id=94 ;;
501                 "slow rock")             id=95 ;;
502                 "big band")              id=96 ;;
503                 "chorus")                id=97 ;;
504                 "easy listening")        id=98 ;;
505                 "acoustic")              id=99 ;;
506                 "humour")                id=100 ;;
507                 "speech")                id=101 ;;
508                 "chanson")               id=102 ;;
509                 "opera")                 id=103 ;;
510                 "chamber music")         id=104 ;;
511                 "sonata")                id=105 ;;
512                 "symphony")              id=106 ;;
513                 "booty bass")            id=107 ;;
514                 "primus")                id=108 ;;
515                 "porn groove")           id=109 ;;
516                 "satire")                id=110 ;;
517                 "slow jam")              id=111 ;;
518                 "club")                  id=112 ;;
519                 "tango")                 id=113 ;;
520                 "samba")                 id=114 ;;
521                 "folklore")              id=115 ;;
522                 "ballad")                id=116 ;;
523                 "power ballad")          id=117 ;;
524                 "rhythmic soul")         id=118 ;;
525                 "freestyle")             id=119 ;;
526                 "duet")                  id=120 ;;
527                 "punk rock")             id=121 ;;
528                 "drum solo")             id=122 ;;
529                 "a capella")             id=123 ;;
530                 "euro-house")            id=124 ;;
531                 "dance hall")            id=125 ;;
532                 "goa")                   id=126 ;;
533                 "drum & bass")           id=127 ;;
534                 "club-house")            id=128 ;;
535                 "hardcore")              id=129 ;;
536                 "terror")                id=130 ;;
537                 "indie")                 id=131 ;;
538                 "britpop")               id=132 ;;
539                 "negerpunk")             id=133 ;;
540                 "polsk punk")            id=134 ;;
541                 "beat")                  id=135 ;;
542                 "christian gangsta rap") id=136 ;;
543                 "heavy metal")           id=137 ;;
544                 "black metal")           id=138 ;;
545                 "crossover")             id=139 ;;
546                 "contemporary christian")id=140 ;;
547                 "christian rock")        id=141 ;;
548                 "merengue")              id=142 ;;
549                 "salsa")                 id=143 ;;
550                 "thrash metal")          id=144 ;;
551                 "anime")                 id=145 ;;
552                 "jpop")                  id=146 ;;
553                 "synthpop")              id=147 ;;
554                 "rock/pop"|"rock / pop") id=148 ;;
555                 *)                       return 1 ;;
556         esac
557 echo ${id}
558 return 0
559 }
560
561 # do_tag [tracknumber]
562 # id3 tags a filename
563 # variables used:
564 # TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC, 
565 # COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE (and temporarily) ID3TAGV
566 do_tag ()
567 {
568         COMMENTOUTPUT="$(eval echo ${COMMENT})"
569         run_command '' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
570         # If we want to start the tracks with a given number, we need to modify the
571         # TRACKNUM value before evaluation
572 #       if [ -n "$STARTTRACKNUMBER" -a -n "$STARTTRACKNUMBERTAG" ] ; then
573 #               # Get the trackpadding from the current track
574 #               CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
575 #               TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - $FIRSTTRACK ))
576 #       fi
577         if [ -n "$STARTTRACKNUMBERTAG" ] ; then
578                 do_gettracknum
579         fi
580         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
581         do
582                 case "$OUTPUT" in
583                 mp3)
584                         # id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
585                         GENREID=$(do_getgenreid "${CDGENRE}")
586         
587                         case "$ID3SYNTAX" in
588                                 id3);;
589                                 eyed3)
590                                         # FIXME # track numbers in mp3 come with 1/10, so we cannot happily substitute them with $TRACKNUM
591                                         run_command tagtrack-$OUTPUT-$1 $TAGGER $TAGGEROPTS --commen=::"$COMMENTOUTPUT" \
592                                                 -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -Y "$CDYEAR" \
593                                                 -G "$GENREID" -n "${TRACKNUM:-$1}" "${TRACKNUM:+-N $TRACKS}" \
594                                                 "${ENCODING:+--set-encoding=$ENCODING}"
595                                                 "$ABCDETEMPDIR/track$1.$OUTPUT"
596                                         ;;
597                                 *)
598                                         # FIXME # track numbers in mp3 come with 1/10, so we cannot happily substitute them with $TRACKNUM
599                                         run_command tagtrack-$OUTPUT-$1 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
600                                                 -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" \
601                                                 -g "$GENREID" -T "${TRACKNUM:-$1/$TRACKS}" \
602                                                 "$ABCDETEMPDIR/track$1.$OUTPUT"
603                                         ;;
604                         esac
605                         ;;
606                 vorbis|ogg)
607                         case "$OGGENCODERSYNTAX" in
608                                 vorbize|oggenc)
609                                         # vorbiscomment can't do in-place modification, mv the file first
610                                         if [ -f "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" -a ! -f "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" ]; then
611                                                 mv "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
612                                         fi
613                                         (
614                                         # These are from http://www.xiph.org/ogg/vorbis/doc/v-comment.html
615                                         echo ARTIST="$TRACKARTIST"
616                                         echo ALBUM="$DALBUM"
617                                         echo TITLE="$TRACKNAME"
618                                         if [ -n "$CDYEAR" ]; then
619                                                 echo DATE="$CDYEAR"
620                                         fi
621                                         if [ -n "$CDGENRE" ]; then
622                                                 echo GENRE="$CDGENRE"
623                                         fi      
624                                         echo TRACKNUMBER=${TRACKNUM:-$1}
625                                         echo CDDB=$CDDBDISCID
626                                         if [ "$(eval echo ${COMMENT})" != "" ]; then
627                                                 case "$COMMENTOUTPUT" in
628                                                         *=*) echo "$COMMENTOUTPUT";;
629                                                         *)   echo COMMENT="$COMMENTOUTPUT";;
630                                                 esac    
631                                         fi
632                                         ) | run_command tagtrack-$OUTPUT-$1 $VORBISCOMMENT $VORBISCOMMENTOPTS -w \
633                                                 "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
634                                         # Doublecheck that the commented file was created successfully before wiping the original
635                                         if [ -f "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" ]; then
636                                                 rm -f "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
637                                         else
638                                                 mv "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
639                                         fi
640                                         ;;
641                         esac
642                         ;;
643                 flac)
644                         (
645                         echo ARTIST="$TRACKARTIST"
646                         echo ALBUM="$DALBUM"
647                         echo TITLE="$TRACKNAME"
648                         if [ -n "$CDYEAR" ]; then
649                                 echo DATE="$CDYEAR"
650                         fi
651                         if [ -n "$CDGENRE" ]; then
652                                 echo GENRE="$CDGENRE"
653                         fi      
654                         echo TRACKNUMBER="${TRACKNUM:-$1}"
655                         echo CDDB="$CDDBDISCID"
656                         if [ "$(eval echo ${COMMENT})" != "" ]; then
657                                 case "$COMMENTOUTPUT" in
658                                         *=*) echo "$COMMENTOUTPUT";;
659                                         *)   echo COMMENT="$COMMENTOUTPUT";;
660                                 esac    
661                         fi
662                         ) | run_command tagtrack-$OUTPUT-$1 $METAFLAC $METAFLACOPTS --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
663                         ;;
664                 spx)
665                         run_command tagtrack-$OUTPUT-$1 true
666                         ;;
667                 mpc)
668                         run_command tagtrack-$OUTPUT-$1 true
669                         ;;
670                 esac
671         done
672         if checkerrors "tagtrack-(.{3,4})-$1"; then
673                 run_command tagtrack-$1 false
674         else
675                 run_command tagtrack-$1 true
676         fi
677
678 }
679
680 # do_batch_encode
681 # variables used:
682 # OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
683 do_batch_encode ()
684 {
685         # The commands here don't go through run_command because they're never supposed to be silenced
686         echo "Batch encoding tracks: $TRACKQUEUE"
687         OUTPUT=$(echo $OUTPUTTYPE | grep "mp3" )
688         case "$OUTPUT" in
689         mp3)
690                 case "$MP3ENCODERSYNTAX" in
691                 lame)
692                         (
693                         cd "$ABCDETEMPDIR"
694                         TRACKFILES=
695                         for UTRACKNUM in $TRACKQUEUE
696                         do
697                                 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
698                         done
699                         nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS `[ "$MP3ENCODER" = "lame" ] && echo "--nogap"` $TRACKFILES
700                         RETURN=$?
701                         if [ "$RETURN" != "0" ]; then
702                                 echo "batch-encode: $ENCODER returned code $RETURN" >> errors
703                         else
704                                 for UTRACKNUM in $TRACKQUEUE
705                                 do
706                                         echo encodetrack-$UTRACKNUM >> status
707                                 done
708                         fi
709                         )
710                         ;;
711                 esac
712                 ;;
713         esac
714         # Other encoders fall through to normal encoding as the tracks
715         # have not been entered in the status file.
716 }
717
718 # do_encode [tracknumber] [hostname]
719 # If no hostname is specified, encode locally
720 # variables used:
721 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
722 do_encode ()
723 {
724         if [ "$USEPIPES" = "y" ]; then
725                 case "$OUTPUT" in
726                         mp3)
727                                 TEMPARG="PIPE_$MP3ENCODERSYNTAX"
728                                 ;;
729                         vorbis|ogg)
730                                 TEMPARG="PIPE_$OGGENCODERSYNTAX"
731                                 ;;
732                         flac)
733                                 TEMPARG="PIPE_$FLACENCODERSYNTAX"
734                                 ;;
735                         spx)
736                                 TEMPARG="PIPE_$SPEEXENCODER"
737                                 ;;
738                         mpc)
739                                 TEMPARG="PIPE_$MPPENCODER"
740                                 ;;
741                 esac
742                 IN="$( eval echo "\$$TEMPARG" )"
743         else
744                 IN="$ABCDETEMPDIR/track$1.wav"
745                 case "$OUTPUT" in
746                         mp3)
747                                 case "$MP3ENCODERSYNTAX" in
748                                         # FIXME # check if mp3enc needs -if for pipes
749                                         mp3enc)
750                                                 FILEARG="-if $IN"
751                                                 ;;
752                                         *)
753                                                 FILEARG="$IN"
754                                                 ;;
755                                 esac
756                                 ;;
757                         *)
758                                 FILEARG="$IN"
759                                 ;;
760                 esac
761         fi
762         # We need IN to proceed, if we are not using pipes.
763         if [ -s "$IN" -o X"$USEPIPES" = "Xy" ] ; then
764                 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
765                 do
766                         case "$OUTPUT" in
767                                 vorbis|ogg)
768                                         OUT="$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
769                                         ;;
770                                 flac)
771                                         OUT="$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
772                                         ;;
773                                 *)
774                                         OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
775                                         ;;
776                         esac
777                         if [ X"$USEPIPES" = "Xy" ]; then
778                                 RUN_COMMAND=""
779                         else
780                                 run_command '' echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
781                                 RUN_COMMAND="run_command encodetrack-$OUTPUT-$1"
782                         fi
783                         case "$OUTPUT" in
784                         mp3)
785                                 case "$2" in
786                                 %local*%)
787                                         case "$MP3ENCODERSYNTAX" in
788                                         lame|gogo) $RUN_COMMAND nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
789                                         bladeenc) $RUN_COMMAND nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" ;;
790                                         l3enc|xingmp3enc) $RUN_COMMAND nice $ENCNICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
791                                         # FIXME # Relates to the previous FIXME since it might need the "-if" removed.
792                                         mp3enc) $RUN_COMMAND nice $ENCNICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
793                                         esac
794                                         ;;
795                                 *)
796                                         $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
797                                         ;;
798                                 esac
799                                 ;;
800                         vorbis|ogg)
801                                 case "$2" in
802                                 %local*%)
803                                         case "$OGGENCODERSYNTAX" in
804                                         vorbize) $RUN_COMMAND nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
805                                         oggenc) $RUN_COMMAND nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
806                                         esac
807                                         ;;
808                                 *)
809                                         $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
810                                         ;;
811                                 esac
812                                 ;;
813                         flac)
814                                 case "$2" in
815                                 %local*%)
816                                         case "$FLACENCODERSYNTAX" in
817                                         flac) $RUN_COMMAND nice $ENCNICE $FLACENCODER $FLACENCODEROPTS -o "$OUT" "$IN" ;; 
818                                         esac
819                                         ;;
820         
821                                 *)
822                                         echo -n "DISTMP3:"
823                                         echo "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
824                                         $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
825                                         ;;
826                                 esac
827                                 ;;
828                         spx)
829                                 if [ "$(eval echo ${COMMENT})" != "" ]; then
830                                         case "$COMMENT" in
831                                                 *=*) ;;
832                                                 *)   COMMENT="COMMENT=$COMMENT" ;;
833                                         esac    
834                                         COMMENT="--comment \"$COMMENT\""
835                                 fi
836                                 # Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
837                                 if [ ! "$DOTAG" = "y" ]; then
838                                         $RUN_COMMAND nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" "$COMMENT" "$IN" "$OUT"
839                                 else
840                                         $RUN_COMMAND nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
841                                 fi
842                                 ;;
843                         mpc)    
844                                 # MPP/MP+(Musepack) format (.mpc) is done locally, with inline
845                                 # tagging.
846                                 # I tried compiling the mppenc from corecodecs.org and got some
847                                 # errors, so I have not tried it myself.
848                                 ## FIXME ## Needs some cleanup to determine if an empty tag sent
849                                 ## FIXME ## to the encoder ends up empty.
850                                 $RUN_COMMAND nice $ENCNICE $MPPENCODER $MPPENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" "$IN" "$OUT"
851                                 ;;
852                         esac
853                 done
854                 # Only remove .wav if the encoding succeeded
855                 if checkerrors "encodetrack-(.{3,4})-$1"; then 
856                         run_command encodetrack-$1 false
857                 else
858                         run_command encodetrack-$1 true
859                         if [ ! "$KEEPWAVS" = "y" ] ; then
860                                 rm -f "$IN"
861                         fi
862                 fi
863         else
864                 run_command "" echo "HEH! The file we were about to encode disappeared:"
865                 run_command "" echo ">> $IN"
866                 run_command encodetrack-$1 false
867         fi
868 }
869
870 # do_preprocess [tracknumber]
871 # variables used:
872 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
873 #do_preprocess ()
874 #{
875 #       IN="$ABCDETEMPDIR/track$1.wav"
876 #       # We need IN to proceed.
877 #       if [ -s "$IN" ] ; then
878 #               for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
879 #               do
880 #                       #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
881 #                       run_command '' echo "Pre-processing track $1 of $TRACKS..."
882 #                       case "$POSTPROCESSFORMAT" in
883 #                       all|wav*)
884 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $WAV_PRE $IF $OF ;;
885 #                       mp3)
886 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $MP3_PRE $IF $OF ;;
887 #                       ogg)
888 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $OGG_PRE $IF $OF ;;
889 #                       flac)
890 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $FLAC_PRE $IF $OF ;;
891 #                       spx)
892 #                               run_command preprocess-$OUTPUT-$1 nice $PRENICE $SPX_PRE $IF $OF ;;
893 #                       esac
894 #               done
895 #               # Only remove .wav if the encoding succeeded
896 #               if checkerrors "preprocess-(.{3,4})-$1"; then 
897 #                       run_command preprocess-$1 false
898 #               else
899 #                       run_command preprocess-$1 true
900 #               fi
901 #       else
902 #               if [ "$(checkstatus encode-output)" = "loud" ]; then
903 #                       echo "HEH! The file we were about to pre-process disappeared:"
904 #                       echo ">> $IN"
905 #               fi
906 #               run_command preprocess-$1 false
907 #       fi
908 #}
909
910
911 # do_postprocess [tracknumber]
912 # variables used:
913 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
914 #do_postprocess ()
915 #{
916 #       for POSTPROCESSFORMAT in $(echo $POSTPROCESSFORMATS | tr , \ )
917 #       do
918 #               IN="$ABCDETEMPDIR/track$1.$POSTPROCESSFORMAT"
919 #               # We need IN to proceed.
920 #               if [ -s "$IN" ] ; then
921 #                       #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
922 #                       run_command '' echo "Post-processing track $1 of $TRACKS..."
923 #                       case "$POSTPROCESSFORMAT" in
924 #                               mp3)
925 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $MP3_POST $IF $OF ;;
926 #                               ogg)
927 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $OGG_POST $IF $OF ;;
928 #                               flac)
929 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $FLAC_POST $IF $OF ;;
930 #                               spx)
931 #                                       run_command postprocess-$OUTPUT-$1 nice $POSTNICE $SPX_POST $IF $OF ;;
932 #                       esac
933 #                       # Only remove .wav if the encoding succeeded
934 #                       if checkerrors "postprocess-(.{3,4})-$1"; then 
935 #                               run_command postprocess-$1 false
936 #                       else
937 #                               run_command postprocess-$1 true
938 #                       fi
939 #               else
940 #                       if [ "$(checkstatus encode-output)" = "loud" ]; then
941 #                               echo "HEH! The file we were about to post-process disappeared:"
942 #                               echo ">> $IN"
943 #                       fi
944 #                       run_command postprocess-$1 false
945 #               fi
946 #       done
947 #}
948
949 # do_single_gain
950 # variables used:
951 # FIXME #
952 do_single_gain ()
953 {
954 :
955 }
956
957 # do_batch_gain
958 # variables used:
959 # MP3GAIN, MP3GAINOPTS, VORBISGAIN, VORBISGAINOPTS
960 # FIXME #
961 do_batch_gain ()
962 {
963         # The commands here don't go through run_command because they're never supposed to be silenced
964         echo "Batch analizing gain in tracks: $TRACKQUEUE"
965         (
966         cd "$ABCDETEMPDIR"
967         BLURB=
968         TRACKFILES=
969         for UTRACKNUM in $TRACKQUEUE
970         do
971                 MP3FILES="$TRACKFILES track$UTRACKNUM.mp3"
972         done
973         # XXX: Hard-coded batch option!
974         $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
975         RETURN=$?
976         if [ "$RETURN" != "0" ]; then
977                 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
978         else
979                 for UTRACKNUM in $TRACKQUEUE
980                 do
981                         echo normalizetrack-$UTRACKNUM >> status
982                 done
983         fi
984         )
985 }
986
987 # do_batch_normalize
988 # variables used:
989 # NORMALIZER, NORMALIZEROPTS
990 do_batch_normalize ()
991 {
992         # The commands here don't go through run_command because they're never supposed to be silenced
993         echo "Batch normalizing tracks: $TRACKQUEUE"
994         (
995         cd "$ABCDETEMPDIR"
996         BLURB=
997         TRACKFILES=
998         for UTRACKNUM in $TRACKQUEUE
999         do
1000                 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
1001         done
1002         # XXX: Hard-coded batch option!
1003         $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
1004         RETURN=$?
1005         if [ "$RETURN" != "0" ]; then
1006                 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
1007         else
1008                 for UTRACKNUM in $TRACKQUEUE
1009                 do
1010                         echo normalizetrack-$UTRACKNUM >> status
1011                 done
1012         fi
1013         )
1014 }
1015
1016 # do_normalize [tracknumber]
1017 # variables used:
1018 # TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
1019 do_normalize ()
1020 {
1021         IN="$ABCDETEMPDIR/track$1.wav"
1022         if [ -e "$IN" ] ; then
1023                 run_command '' echo "Normalizing track $1 of $TRACKS: $TRACKNAME..."
1024                 run_command normalizetrack-$1 $NORMALIZER $NORMALIZEROPTS "$IN"
1025         else
1026                 if [ "$(checkstatus encode-output)" = "loud" ]; then
1027                         echo "HEH! The file we were about to normalize disappeared:"
1028                         echo ">> $IN"
1029                 fi
1030                 run_command normalizetrack-$1 false "File $IN was not found"
1031         fi
1032 }
1033
1034 # do_move [tracknumber]
1035 # Deduces the outfile from environment variables
1036 # Creates directory if necessary
1037 # variables used:
1038 # TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, CDYEAR
1039 do_move ()
1040 {
1041         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1042         do
1043                 # Create ALBUMFILE, ARTISTFILE, TRACKFILE
1044                 # Munge filenames as follows:
1045                 # ' ' -> '_'
1046                 # '/' -> '_'
1047                 # ''' -> ''
1048                 # '?' -> ''
1049                 # Eat control characters
1050                 ALBUMFILE=$(mungefilename "$DALBUM")
1051                 ARTISTFILE=$(mungefilename "$TRACKARTIST")
1052                 TRACKFILE=$(mungefilename "$TRACKNAME")
1053                 GENRE=$(mungegenre "$GENRE")
1054                 YEAR=$(echo $CDYEAR)
1055                 # If we want to start the tracks with a given number, we need to modify the
1056                 # TRACKNUM value before evaluation
1057         #       if [ -n "$STARTTRACKNUMBER" ] ; then
1058         #               # Get the trackpadding from the current track
1059         #               CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
1060         #               TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - $FIRSTTRACK ))
1061         #       else
1062         #               TRACKNUM=${UTRACKNUM}
1063         #       fi
1064                 do_gettracknum
1065                 # Supported variables for OUTPUTFORMAT are GENRE, ALBUMFILE, ARTISTFILE,
1066                 # TRACKFILE, and TRACKNUM.
1067                 if [ "$VARIOUSARTISTS" = "y" ]; then
1068                         OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
1069                         else
1070                         OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
1071                 fi
1072                 if checkerrors "tagtrack-$OUTPUT-$1"; then :; else
1073                         # Once we know the specific output was successful, we can change the OUTPUT to the value containing the container
1074                         case $OUTPUT in
1075                                 vorbis|ogg)
1076                                         OUTPUT=$OGGOUTPUTCONTAINER
1077                                         ;;
1078                                 flac)
1079                                         OUTPUT=$FLACOUTPUTCONTAINER
1080                                         ;;
1081                         esac
1082                         # Check that the directory for OUTPUTFILE exists, if it doesn't, create it
1083                         OUTPUTFILEDIR=$(dirname "$OUTPUTDIR/$OUTPUTFILE")
1084                         # mkdir -p shouldn't return an error if the directory already exists
1085                         mkdir -p "$OUTPUTFILEDIR"
1086                         run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
1087                         # Lets move the cue file
1088                         if CUEFILE=$(checkstatus cuefile) >/dev/null ; then 
1089                                 if [ -r "$ABCDETEMPDIR/$CUEFILE" ]; then
1090                                         if checkstatus movecue-$OUTPUT; then :; else
1091                                                 # Silence the Copying output since it overlaps with encoding processes...
1092                                                 #run_command '' vecho "Copying cue file to its destination directory..."
1093                                                 if checkstatus onetrack >/dev/null ; then
1094                                                         case $OUTPUT in
1095                                                                 # NOTE: Creating a cue file with the 3-char-extension files is to comply with
1096                                                                 # http://brianvictor.tripod.com/mp3cue.htm#details
1097                                                                 [a-z0-9][a-z0-9][a-z0-9])
1098                                                                         run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.cue"
1099                                                                         ;;
1100                                                                 *)
1101                                                                         run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT.cue"
1102                                                                         ;;
1103                                                         esac
1104                                                 else
1105                                                         run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTFILEDIR/$CUEFILE"
1106                                                 fi
1107                                                 echo movecue-$OUTPUT >> "$ABCDETEMPDIR/status"
1108                                         fi
1109                                 fi
1110                         fi
1111                 fi
1112         done
1113 }
1114
1115 # do_playlist
1116 # Create the playlist if wanted
1117 # Variables used:
1118 # PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
1119 # VARIOUSARTISTS, OUTPUTDIR
1120 do_playlist ()
1121 {
1122         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1123         do
1124                 # Create a playlist file for the playlist data to go into.
1125                 # We used to wipe it out if it existed. Now we request permision if interactive.
1126                 for LASTTRACK in $TRACKQUEUE; do :; done
1127                 ALBUMFILE=$(mungefilename "$DALBUM")
1128                 ARTISTFILE=$(mungefilename "$DARTIST")
1129                 GENRE=$(mungegenre "$GENRE")
1130                 YEAR=${CDYEAR:-$CDYEAR}
1131                 if [ "$VARIOUSARTISTS" = "y" ] ; then
1132                         PLAYLISTFILE=$(eval echo $VAPLAYLISTFORMAT)
1133                 else
1134                         PLAYLISTFILE=$(eval echo $PLAYLISTFORMAT)
1135                 fi
1136                 FINALPLAYLISTDIR=$(dirname "$OUTPUTDIR/$PLAYLISTFILE")
1137                 mkdir -p "$FINALPLAYLISTDIR"
1138                 if [ -s "$OUTPUTDIR/$PLAYLISTFILE" ]; then
1139                         echo -n "Erase, Append to, or Keep the existing playlist file? [e/a/k] (e): " >&2
1140                         if [ "$INTERACTIVE" = "y" ]; then
1141                                 while [ "$DONE" != "y" ]; do
1142                                         read ERASEPLAYLIST
1143                                         case $ERASEPLAYLIST in
1144                                                 e|E|a|A|k|K) DONE=y ;;
1145                                                 *) ;;
1146                                         esac
1147                                 done
1148                         else
1149                                 echo e >&2
1150                                 ERASEPLAYLIST=e
1151                         fi
1152                         # Once we erase the playlist, we use append to create the new one.
1153                         [ "$ERASEPLAYLIST" = "e" -o "$ERASEPLAYLIST" = "E" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE" && ERASEPLAYLIST=a
1154                 else
1155                         # The playlist does not exist, so we can safelly use append to create the new list
1156                         ERASEPLAYLIST=a
1157                 fi
1158                 if [ "$ERASEPLAYLIST" = "a" -o "$ERASEPLAYLIST" = "A" ]; then
1159                         touch "$OUTPUTDIR/$PLAYLISTFILE"
1160                         for UTRACKNUM in $TRACKQUEUE
1161                         do
1162                                 # Shares some code with do_move since the filenames have to match
1163                                 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
1164                                 #TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2 -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')
1165                                 do_getcddbinfo TRACKNAME
1166                                 splitvarious
1167                                 TRACKFILE=$(mungefilename "$TRACKNAME")
1168                                 ARTISTFILE=$(mungefilename "$TRACKARTIST")
1169                                 ALBUMFILE=$(mungefilename "$DALBUM")
1170                                 # If we want to start the tracks with a given number, we need to modify the
1171                                 # TRACKNUM value before evaluation
1172                         #       if [ -n "$STARTTRACKNUMBER" ] ; then
1173                         #               # Get the trackpadding from the current track
1174                         #               CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
1175                         #               TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - $FIRSTTRACK ))
1176                         #       else
1177                         #               TRACKNUM=${UTRACKNUM}
1178                         #       fi
1179                                 do_gettrucknum
1180                                 if [ "$VARIOUSARTISTS" = "y" ]; then
1181                                         OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
1182                                 else
1183                                         OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
1184                                 fi
1185                                 if [ "$VARIOUSARTISTS" = "y" ]; then
1186                                         if [ "$VAPLAYLISTDATAPREFIX" ] ; then
1187                                                 echo ${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
1188                                         else
1189                                                 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1190                                         fi
1191                                 else
1192                                         if [ "$PLAYLISTDATAPREFIX" ]; then
1193                                                 echo ${PLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
1194                                         else
1195                                                 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1196                                         fi
1197                                 fi
1198                         done
1199                 fi
1200                 ## this will convert the playlist to have CRLF line-endings, if specified
1201                 ## (some hardware players insist on CRLF endings)
1202                 if [ "$DOSPLAYLIST" = "y" ]; then
1203                         awk '{substr("\r",""); printf "%s\r\n", $0}' "$OUTPUTDIR/$PLAYLISTFILE" > "$ABCDETEMPDIR/PLAYLISTFILE.tmp"
1204 #                       mv -f "$ABCDETEMPDIR/PLAYLISTFILE.tmp" "$OUTPUTDIR/$PLAYLISTFILE"
1205                         cat "$ABCDETEMPDIR/PLAYLISTFILE.tmp" | sed 's/\//\\/' > "$OUTPUTDIR/$PLAYLISTFILE"
1206                 fi
1207                 echo "playlistcomplete" >> "$ABCDETEMPDIR/status"
1208         done
1209 }
1210
1211 # do_discid
1212 # This essentially the start of things
1213 do_discid ()
1214 {
1215         # Query the CD to get the track info, unless the user specified -C
1216         # or we are using some actions which do not need the CDDB data at all
1217         #if [ ! X"$EXPACTIONS" = "X" ]; then
1218         #       :
1219         #elif [ -z "$DISCID" ]; then
1220         if [ -z "$DISCID" ]; then
1221                 vecho -n "Getting CD track info... "
1222                 # In OSX, unmount the disc before a query
1223                 if [ "$OSFLAVOUR" = "OSX" ]; then
1224                         disktool -u ${CDROM#/dev/}
1225                 fi
1226                 TRACKINFO=$($CDDISCID $CDROM)
1227                 # Make sure there's a CD in there by checking cd-discid's return code
1228                 if [ "$?" = "1" ]; then
1229                         echo "abcde error: CD could not be read. Perhaps there's no CD in the drive?" >&2
1230                         exit 1
1231                 fi
1232                 # In OSX, remount the disc again
1233                 if [ "$OSFLAVOUR" = "OSX" ]; then
1234                         disktool -m ${CDROM#/dev/}
1235                 fi
1236                 WEHAVEACD=y
1237         else
1238                 TRACKINFO=$(cat "$WAVOUTPUTDIR/abcde.$DISCID/discid")
1239         fi
1240
1241         # Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.
1242         # This needs to be done now because a section of the resuming code will need
1243         # it later.
1244
1245         # get the number of digits to pad TRACKNUM with - we'll use this later
1246         # a CD can only hold 99 tracks, but since we support a feature for starting
1247         # numbering the tracks from a given number, we might need to set it as a
1248         # variable for the user to define... or obtain it somehow.
1249         if [ "$PADTRACKS" = "y" ] ; then
1250                 TRACKNUMPADDING=2
1251         fi
1252
1253         ABCDETEMPDIR="$WAVOUTPUTDIR/abcde.$(echo $TRACKINFO | cut -f1 -d' ')"
1254         if [ -z "$TRACKQUEUE" ]; then
1255                 if [ ! "$STRIPDATATRACKS" = "y" ]; then
1256                         case "$CDROMREADERSYNTAX" in
1257                                 cdparanoia|debug)
1258                                         if [ "$WEHAVEACD" = "y" ]; then
1259                                                 vecho "Querying the CD for audio tracks..."
1260                                                 CDPARANOIAOUTPUT="$( $CDROMREADER -$CDPARANOIACDROMBUS $CDROM -Q --verbose 2>&1 )"
1261                                                 RET=$?
1262                                                 if [ ! "$RET" = "0" ];then
1263                                                         echo "Warning: Something went wrong while querying the CD... Maybe a DATA CD?"
1264                                                 fi
1265                                                 TRACKS="$( echo "$CDPARANOIAOUTPUT" | egrep '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ' )"
1266                                                 CDPARANOIAAUDIOTRACKS="$TRACKS"
1267                                         else
1268                                                 if [ -f "$ABCDETEMPDIR/status" ] && checkstatus cdparanoia-audio-tracks ; then
1269                                                         TRACKS=$( cat "$ABCDETEMPDIR/cdparanoia-audio-tracks" )
1270                                                 else
1271                                                         TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
1272                                                 fi
1273                                         fi
1274                                         ;;
1275                                 *)      TRACKS=$(echo $TRACKINFO | cut -f2 -d' ') ;;
1276                         esac
1277                 else
1278                         TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
1279                 fi
1280                 if echo "$TRACKS" | grep "[[:digit:]]" > /dev/null 2>&1 ;then :;else
1281                         echo "The disc does not contain any tracks. Giving up..."
1282                         exit 0
1283                 fi
1284                 echo -n "Grabbing entire CD - tracks: "
1285                 if [ ! "$PADTRACKS" = "y" ] ; then
1286                         TRACKNUMPADDING=$(echo -n $TRACKS | wc -c | tr -d ' ')
1287                 fi
1288                 TRACKS=$(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
1289                 X=0
1290                 while [ "$X" -ne "$TRACKS" ]
1291                 do
1292                         X=$(printf "%0.${TRACKNUMPADDING}d" $(expr $X + 1))
1293                         TRACKQUEUE=$(echo "$TRACKQUEUE" $X)
1294                 done
1295                 echo $TRACKQUEUE
1296         else
1297                 TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
1298                 # User-supplied track queue.
1299                 # Weed out non-numbers, whitespace, then sort and weed out duplicates
1300                 TRACKQUEUE=$(echo $TRACKQUEUE | sed 's-[^0-9 ]--g' | tr ' ' '\n' | grep -v ^$ | sort -n | uniq | tr '\n' ' ' | sed 's- $--g')
1301                 # Once cleaned, obtain the highest value in the trackqueue for number padding
1302                 for LASTTRACK in $TRACKQUEUE; do :; done
1303                 if [ ! "$PADTRACKS" = "y" ] ; then
1304                         TRACKNUMPADDING=$(echo -n $LASTTRACK | wc -c | tr -d ' ')
1305                 fi
1306                 # Now we normalize the trackqueue
1307                 for TRACK in $TRACKQUEUE ; do
1308                         TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${TRACK} + 0 ))
1309                         PADTRACKQUEUE=$(echo $PADTRACKQUEUE $TRACKNUM)
1310                 done
1311                 TRACKQUEUE=$PADTRACKQUEUE
1312                 echo Grabbing tracks: "$TRACKQUEUE"
1313         fi
1314
1315         QUEUEDTRACKS=$(echo $TRACKQUEUE | wc -w | tr -d ' ')
1316
1317         # We have the discid, create a temp directory after it to store all the temp
1318         # info
1319
1320         if [ -e "$ABCDETEMPDIR" ]; then
1321                 echo -n "abcde: attempting to resume from $ABCDETEMPDIR"
1322                 # It already exists, see if it's a directory
1323                 if [ ! -d "$ABCDETEMPDIR" ]; then
1324                         # This is a file/socket/fifo/device/etc, not a directory
1325                         # Complain and exit
1326                         echo >&2
1327                         echo "abcde: file $ABCDETEMPDIR already exists and does not belong to abcde." >&2
1328                         echo "Please investigate, remove it, and rerun abcde." >&2
1329                         exit 1
1330                 fi
1331                 echo -n .
1332                 # It's a directory, let's see if it's owned by us
1333                 if [ ! -O "$ABCDETEMPDIR" ]; then
1334                         # Nope, complain and exit
1335                         echo >&2
1336                         echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
1337                         echo "Please investigate, remove it, and rerun abcde." >&2
1338                         exit 1
1339                 fi
1340                 echo .
1341                 # See if it's populated
1342                 if [ ! -f "$ABCDETEMPDIR/discid" ]; then
1343                         # Wipe and start fresh
1344                         echo "abcde: $ABCDETEMPDIR/discid not found. Abcde must remove and recreate" >&2
1345                         echo -n "this directory to continue. Continue? [y/n] (n)" >&2
1346                         if [ "$INTERACTIVE" = "y" ]; then
1347                                 read ANSWER
1348                         else
1349                                 echo y >&2
1350                                 ANSWER=y
1351                         fi
1352                         if [ "$ANSWER" != "y" ]; then
1353                                 exit 1
1354                         fi
1355                         rm -rf "$ABCDETEMPDIR" || exit 1
1356                         mkdir "$ABCDETEMPDIR"
1357                         if [ "$?" -gt "0" ]; then
1358                                 # Directory already exists or could not be created
1359                                 echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
1360                                 exit 1
1361                         fi
1362                 else
1363                         # Everything is fine. Check for ^encodetracklocation-
1364                         # and encode-output entries in the status file and
1365                         # remove them. These are not relevant across sessions.
1366                         if [ -f "$ABCDETEMPDIR/status" ]; then
1367                                 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
1368                                 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
1369                                         | grep -v ^encode-output > "$ABCDETEMPDIR/status"
1370                         fi
1371                         # Remove old error messages
1372                         if [ -f "$ABCDETEMPDIR/errors" ]; then
1373                                 rm -f "$ABCDETEMPDIR/errors"
1374                         fi
1375                 fi
1376         else
1377                 # We are starting from scratch
1378                 mkdir "$ABCDETEMPDIR"
1379                 if [ "$?" -gt "0" ]; then
1380                         # Directory already exists or could not be created
1381                         echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
1382                         exit 1
1383                 fi
1384                 cat /dev/null > "$ABCDETEMPDIR/status"
1385         fi
1386         if [ X"$MAKECUEFILE" = "Xy" -a X"$WEHAVEACD" = "Xy" ]; then
1387                 if checkstatus cuefile > /dev/null 2>&1 ; then :; else
1388                         CUEFILE=cue-$(echo "$TRACKINFO" | cut -f1 -d' ').txt
1389                         vecho "Creating cue file..."
1390                         if $CUEREADER $CUEREADEROPTS > "$ABCDETEMPDIR/$CUEFILE"; then
1391                                 echo cuefile=$CUEFILE >> "$ABCDETEMPDIR/status"
1392                         else
1393                                 echo "abcde: reading the CUE sheet with mkcue is still considered experimental"
1394                                 echo "abcde: and there was a problem with the CD reading. abcde will continue,"
1395                                 echo "abcde: but consider reporting the problem to the abcde author"
1396                         fi
1397                 fi
1398         fi
1399         # If we got the CDPARANOIA status and it is not recorded, save it now
1400         if [ -n "$CDPARANOIAAUDIOTRACKS" ]; then
1401                 if checkstatus cdparanoia-audio-tracks; then :; else
1402                         if echo "$CDPARANOIAAUDIOTRACKS" >> "$ABCDETEMPDIR/cdparanoia-audio-tracks"; then
1403                                 echo "cdparanoia-audio-tracks" >> "$ABCDETEMPDIR/status"
1404                         fi
1405                 fi
1406         fi
1407         
1408         # Create the discid file
1409         echo "$TRACKINFO" > "$ABCDETEMPDIR/discid"
1410 }
1411
1412 # do_cleancue
1413 # Create a proper CUE file based on the CUE file we created before.
1414 do_cleancue()
1415 {
1416         # FIXME # we can get the name of the cuefile from the status file
1417         if CUEFILE_IN="$ABCDETEMPDIR"/$(checkstatus cuefile); then
1418                 CUEFILE_OUT=$CUEFILE_IN.out
1419                 ### FIXME ### checkstatus cddb
1420                 if [ -e "$CDDBDATA" ]; then
1421                         vecho "Adding metadata to the cue file..."
1422                         # FIXME It doesn't preserve spaces! Why?
1423                         # FIXME parse $track into PERFORMER and TITLE - abcde already has code for this?
1424                         n=1
1425                         echo "PERFORMER \"$DARTIST\"" >> "$CUEFILE_OUT"
1426                         echo "TITLE \"$DALBUM\"" >> "$CUEFILE_OUT"
1427                         cat "$CUEFILE_IN" | while read line
1428                         do
1429                                 if echo "$line" | grep -q "INDEX"
1430                                 then
1431                                         eval track="\$TRACK$n"
1432                                         n=$(expr $n + 1)
1433                                         echo "TITLE \"$track\"" >> "$CUEFILE_OUT"
1434                                 fi
1435                                 echo "$line" >> "$CUEFILE_OUT"
1436                         done
1437                         mv "$CUEFILE_OUT" "$CUEFILE_IN"
1438                         echo "cleancuefile" >> "$ABCDETEMPDIR/status"
1439                 fi
1440         fi
1441 }
1442
1443 # do_cddbparse
1444 # Parses a CDDB file and outputs the title and the track names.
1445 # Variables: CDDBFILE
1446 do_cddbparse ()
1447 {
1448         CDDBPARSEFILE="$1"
1449         # List out disc title/author and contents
1450         if [ "$ONETRACK" = "y" ]; then
1451                 vecho "ONETRACK mode selected: displaying only the title of the CD..."
1452         fi
1453         echo "---- $(grep DTITLE "${CDDBPARSEFILE}" | cut '-d=' -f2- | tr -d \\r\\n ) ----"
1454         if [ X"$SHOWCDDBYEAR" = "Xy" ]; then
1455                 PARSEDYEAR=$(grep DYEAR "${CDDBPARSEFILE}" | cut '-d=' -f2-)
1456                 if [ ! X"$PARSEDYEAR" = "X" ]; then
1457                         echo "Year: $PARSEDYEAR"
1458                 fi
1459         fi
1460         if [ X"$SHOWCDDBGENRE" = "Xy" ]; then
1461                 PARSEDGENRE=$(grep DGENRE "${CDDBPARSEFILE}" | cut '-d=' -f2-)
1462                 if [ ! X"$PARSEDGENRE" = "X" ]; then
1463                         echo "Genre: $PARSEDGENRE"
1464                 fi
1465         fi
1466         if [ ! "$ONETRACK" = "y" ]; then
1467                 for TRACK in $(f_seq_row 1 $TRACKS)
1468                 do
1469                         echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
1470                 done
1471         fi
1472 }
1473
1474 # do_localcddb
1475 # Check for a local CDDB file, and report success
1476 do_localcddb ()
1477 {
1478         if checkstatus cddb-readcomplete && checkstatus cddb-choice >/dev/null; then :; else
1479         
1480                 CDDBLOCALSUCCESS="n"
1481                 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
1482                 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
1483                 USELOCALRESP="y"
1484                 
1485                 # If the user has selected to check a local CDDB repo, we proceed with it
1486                 if [ -r "${CDDBLOCALFILE}" ]; then
1487                         # List out disc title/author and contents
1488                         do_cddbparse "${CDDBLOCALFILE}"
1489                         echo -n "Locally cached CDDB entry found, use it? [y/n] (y): "
1490                         if [ "$INTERACTIVE" = "y" ]; then
1491                                 read USELOCALRESP
1492                                 while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
1493                                         echo -n 'Invalid selection. Please answer "y" or "n": '
1494                                         read USELOCALRESP
1495                                 done
1496                                 [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
1497                         else
1498                                 echo "y" >&2
1499                         fi
1500                         if [ "$USELOCALRESP" = "y" ]; then
1501                                 #echo "Using local copy of CDDB data"
1502                                 cp "${CDDBLOCALFILE}" "$ABCDETEMPDIR/cddbread.1"
1503                                 echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
1504                                 echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
1505                                 do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
1506                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1507                                 CDDBLOCALSUCCESS="y"
1508                         else
1509                                 #echo "Not using local copy of CDDB data"
1510                                 CDDBLOCALSUCCESS="n"
1511                         fi
1512                 else
1513                         CDDBLOCALSUCCESS="n"
1514                 fi
1515         fi
1516 }
1517
1518 # do_cddbstat
1519 do_cddbstat ()
1520 {
1521         # Perform CDDB protocol version check if it hasn't already been done
1522         if checkstatus cddb-statcomplete; then :; else
1523                 if [ "$CDDBAVAIL" = "n" ]; then
1524                         ERRORCODE=no_query
1525                         echo 503 > "$ABCDETEMPDIR/cddbstat"
1526                 else
1527                         rc=1
1528                         CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1529                         CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1530                         while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
1531                                 vecho "Checking CDDB server status..."
1532                                 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
1533                                 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
1534                                 case "$RESPONSECODE" in
1535                                 210)    # 210 OK, status information follows (until terminating `.')
1536                                         rc=0;
1537                                         ;;
1538                                 501|*)  # 501 Illegal CDDB protocol level: <n>. 
1539                                         CDDBPROTO=`expr $CDDBPROTO - 1`
1540                                         ;;
1541                                 esac 
1542                         done
1543                         if test $rc -eq 1; then
1544                                 CDDBAVAIL="n" 
1545                         fi
1546                 fi
1547                 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
1548         fi
1549 }
1550
1551
1552 # do_cddbquery
1553 do_cddbquery ()
1554 {
1555         CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
1556         CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
1557         
1558         # Perform CDDB query if it hasn't already been done
1559         if checkstatus cddb-querycomplete; then :; else
1560                 if [ "$CDDBAVAIL" = "n" ]; then
1561                         ERRORCODE=no_query
1562                         echo 503 > "$ABCDETEMPDIR/cddbquery"
1563                 # The default CDDBLOCALSUCCESS is "n"
1564                 # This part will be triggered if the user CDDB repo does not 
1565                 # contain the entry, or if we are not trying to use the repo.
1566                 else
1567                         vecho "Querying the CDDB server..."
1568                         CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1569                         CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1570                         $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
1571                         ERRORCODE=$?
1572                         case $ERRORCODE in
1573                                 0)  # success
1574                                 ;;
1575                                 12|13|14)
1576                                         # no match found in database,
1577                                         # wget/fetch error, or user requested not to use CDDB
1578                                         # Make up an error code (503) that abcde
1579                                         # will recognize in do_cddbread
1580                                         # and compensate by making a template
1581                                         echo 503 > "$ABCDETEMPDIR/cddbquery"
1582                                 ;;
1583                                 *) # strange and unknown error
1584                                         echo ERRORCODE=$ERRORCODE
1585                                         echo "abcde: $CDDBTOOL returned unknown error code"
1586                                 ;;
1587                         esac
1588                 fi
1589                 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
1590         fi
1591 }
1592
1593 # do_cddbread
1594 do_cddbread ()
1595 {
1596         # If it's not to be used, generate a template.
1597         # Then, display it (or them) and let the user choose/edit it
1598         if checkstatus cddb-readcomplete; then :; else
1599                 vecho "Obtaining CDDB results..."
1600                 # If CDDB is to be used, interpret the query results and read all
1601                 # the available entries.
1602                 rm -f "$ABCDETEMPDIR/cddbchoices"
1603                 CDDBCHOICES=1 # Overridden by multiple matches
1604                 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
1605                 case "$RESPONSECODE" in
1606                 200)
1607                         # One exact match, retrieve it
1608                         # 200 [section] [discid] [artist] / [title]
1609                         if checkstatus cddb-read-1-complete; then :; else
1610                                 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
1611                                 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
1612                                 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
1613                                 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1614                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1615                         fi
1616                         # List out disc title/author and contents
1617                         echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
1618                         for TRACK in $(f_seq_row 1 $TRACKS)
1619                         do
1620                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1621                         done
1622                         echo >> "$ABCDETEMPDIR/cddbchoices"
1623                         ;;
1624                 202|403|409|503)
1625                         # No match
1626                         case "$RESPONSECODE" in
1627                         202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
1628                         403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
1629                         503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
1630                         esac
1631                         $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
1632                         # List out disc title/author and contents of template
1633                         echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
1634                         UNKNOWNDISK=y
1635                         for TRACK in $(f_seq_row 1 $TRACKS)
1636                         do
1637                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1638                         done
1639                         echo >> "$ABCDETEMPDIR/cddbchoices"
1640                         echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
1641                         echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
1642                         ;;
1643                 210|211)
1644                         # Multiple exact, (possibly multiple) inexact matches
1645                         IN=
1646                         if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
1647                         if [ "$(wc -l < "$ABCDETEMPDIR/cddbquery" | tr -d ' ')" -eq 3 ]; then
1648                                 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
1649                                 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
1650                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1651                         else
1652                                 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
1653                         fi
1654                         vecho -n "Retrieving multiple matches... "
1655                         grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
1656                         read DISCINFO # eat top line
1657                         while read DISCINFO
1658                         do
1659                                 X=$(expr $X + 1)
1660                                 if checkstatus cddb-read-$X-complete; then :; else
1661                                         $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
1662                                         echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
1663                                 fi
1664                                 # List out disc title/author and contents
1665                                 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
1666                                 for TRACK in $(f_seq_row 1 $TRACKS)
1667                                 do
1668                                         echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1669                                 done
1670                                 echo >> "$ABCDETEMPDIR/cddbchoices"
1671                         done )
1672                         vecho "done."
1673                         CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1674                         ;;
1675                 999)
1676                         # Using local copy.
1677                         for TRACK in $(f_seq_row 1 $TRACKS)
1678                         do
1679                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1680                         done
1681                         echo >> "$ABCDETEMPDIR/cddbchoices"
1682                         echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1683                         echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1684                         ;;
1685                 esac    
1686                 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
1687         fi
1688 }
1689
1690 # do_cddbedit
1691 do_cddbedit ()
1692 {
1693         if checkstatus cddb-edit >/dev/null; then
1694                 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1695                 VARIOUSARTISTS="$(checkstatus variousartists)"
1696                 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
1697                 return 0
1698         fi
1699         if [ "$INTERACTIVE" = "y" ]; then
1700                 # We should show the CDDB results both when we are not using the local CDDB repo
1701                 # or when we are using it but we could not find a proper match
1702                 if [ "$CDDBUSELOCAL" = "y" ] && [ ! "$CDDBLOCALSUCCESS" = "y" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1703                         # Display the $ABCDETEMPDIR/cddbchoices file created above
1704                         # Pick a pager so that if the tracks overflow the screen the user can still view everything
1705                         if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1706                                 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1707                                 CHOICE=$(checkstatus cddb-choice)
1708                                 if [ -n "$CHOICE" ] ; then
1709                                         case $CDDBCHOICES in
1710                                                 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1711                                                 *)
1712                                                 echo "Selected: #$CHOICE"
1713                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1714                                                 ;;
1715                                         esac
1716                                 else
1717                                         # The user has a choice to make, display the info in a pager if necessary
1718                                         if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
1719                                                 page "$ABCDETEMPDIR/cddbchoices"
1720                                         else
1721                                                 # It's all going to fit in one page, cat it
1722                                                 cat "$ABCDETEMPDIR/cddbchoices" >&2
1723                                         fi
1724                                         
1725                                         CDDBCHOICENUM=""
1726                                         # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
1727                                         CDCHOICENUM=-1
1728                                         # I'll take CDDB read #3 for $400, Alex
1729                                         while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
1730                                                 echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
1731                                                 read CDDBCHOICE
1732                                                 [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
1733                                                 if echo $CDDBCHOICE | egrep -q "[[:digit:]]+,[[:digit:]]+" ; then
1734                                                         if [ ! X"$DIFF" = "X" ]; then
1735                                                                 PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1)
1736                                                                 PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2)
1737                                                                 if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
1738                                                                    [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
1739                                                                    [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then 
1740                                                                         echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBCHOICES" >&2
1741                                                                 else
1742
1743                                                                         # We parse the 2 choices to diff, store them in temporary files and diff them.
1744                                                                         for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
1745                                                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE"
1746                                                                         done
1747                                                                         echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/cddbread.diff"
1748                                                                         $DIFF $DIFFOPTS "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/cddbread.diff"
1749                                                                         if [ $(cat "$ABCDETEMPDIR/cddbread.diff" | wc -l) -ge 24 ]; then
1750                                                                                 page "$ABCDETEMPDIR/cddbread.diff"
1751                                                                         else
1752                                                                                 cat "$ABCDETEMPDIR/cddbread.diff" >&2
1753                                                                         fi
1754                                                                 fi
1755                                                         else
1756                                                                 echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2
1757                                                         fi
1758                                                 else
1759                                                         if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then
1760                                                                 # Make sure we get a valid choice
1761                                                                 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
1762                                                                 echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2
1763                                                         fi
1764                                                 fi
1765                                         done
1766                                         if [ "$CDCHOICENUM" = "0" ]; then
1767                                                 vecho "Creating empty CDDB template..."
1768                                                 UNKNOWNDISK=y
1769                                                 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
1770                                         else
1771                                                 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
1772                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
1773                                         fi
1774                                         echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1775                                 fi
1776                         fi
1777                 else
1778                         # We need some code to show the selected option when local repository is selected and we have found a match
1779                         vecho "Using cached CDDB match..." >&2
1780                         # Display the $ABCDETEMPDIR/cddbchoices file created above
1781                         # Pick a pager so that if the tracks overflow the screen the user can still view everything
1782                         if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1783                                 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1784                                 CHOICE=$(checkstatus cddb-choice)
1785                                 if [ "$USELOCALRESP" = "y" ]; then :; else
1786                                         if [ -n "$CHOICE" ] ; then
1787                                                 case $CDDBCHOICES in
1788                                                         0) 
1789                                                         UNKNOWNDISK=y
1790                                                         echo "Selected template."
1791                                                         ;;
1792                                                         1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1793                                                         *)
1794                                                         echo "Selected: #$CHOICE"
1795                                                         do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1796                                                         ;;
1797                                                 esac
1798                                         fi
1799                                 fi
1800                         fi
1801                 fi
1802         else
1803                 # We're noninteractive - pick the first choice.
1804                 # But in case we run a previous instance and selected a choice, use it.
1805                 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1806                         # Show the choice if we are not using the locally stored one
1807                         # or when the local search failed to find a match.
1808                         PREVIOUSCHOICE=$(checkstatus cddb-choice)
1809                         if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSUCCESS" = "n" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1810                                 #if [ "$PREVIOUSCHOICE" ]; then
1811                                         cat "$ABCDETEMPDIR/cddbchoices"
1812                                 #fi
1813                         fi
1814                         if [ ! -z "$PREVIOUSCHOICE" ] ; then
1815                                 CDCHOICENUM=$PREVIOUSCHOICE
1816                         else
1817                                 CDCHOICENUM=1
1818                                 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1819                         fi
1820                         echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
1821                 fi
1822         fi
1823
1824         # sanity check
1825         if checkstatus cddb-choice >/dev/null; then :; else
1826                 echo "abcde: internal error: cddb-choice not recorded." >&2
1827                 exit 1
1828         fi
1829         CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1830         echo -n "Edit selected CDDB data? [y/n] (" >&2
1831         if [ "$INTERACTIVE" = "y" ]; then
1832                 if [ "$UNKNOWNDISK" = "y" ]; then
1833                         echo -n "y): " >&2
1834                         read EDITCDDB
1835                         [ "$EDITCDDB" != "n" ] && EDITCDDB=y
1836                 else
1837                         echo -n "n): " >&2
1838                         read EDITCDDB
1839                 fi
1840         else
1841                 echo "n): n" >&2
1842                 EDITCDDB=n
1843         fi
1844         if [ "$EDITCDDB" = "y" ]; then
1845                 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
1846                 
1847                 # Use the debian sensible-editor wrapper to pick the editor that the
1848                 # user has requested via their $EDITOR environment variable
1849                 if [ -x "/usr/bin/sensible-editor" ]; then
1850                         /usr/bin/sensible-editor "$CDDBDATA"
1851                 elif [ -n "$EDITOR" ]; then
1852                         if [ -x $(which "${EDITOR%%\ *}") ]; then
1853                                 # That failed, try to load the preferred editor, starting
1854                                 # with their EDITOR variable
1855                                 eval $(echo "$EDITOR") \"$CDDBDATA\"
1856                         fi
1857                 # If that fails, check for a vi
1858                 elif which vi >/dev/null 2>&1; then
1859                         vi "$CDDBDATA"
1860                 elif [ -x /usr/bin/vim ]; then
1861                         /usr/bin/vim "$CDDBDATA"
1862                 elif [ -x /usr/bin/vi ]; then
1863                         /usr/bin/vi "$CDDBDATA"
1864                 elif [ -x /bin/vi ]; then
1865                         /bin/vi "$CDDBDATA"
1866                 # nano should be on all (modern, i.e., sarge) debian systems
1867                 elif which nano >/dev/null 2>&1 ; then
1868                         nano "$CDDBDATA"
1869                 elif [ -x /usr/bin/nano ]; then
1870                         /usr/bin/nano "$CDDBDATA"
1871                 # mg should be on all OpenBSD systems
1872                 elif which mg >/dev/null 2>&1 ; then
1873                         mg "$CDDBDATA"
1874                 elif [ -x /usr/bin/mg ]; then
1875                         /usr/bin/mg "$CDDBDATA"
1876                 # bomb out
1877                 else
1878                         echo "No editor available. Check your EDITOR environment variable." >&2
1879                 fi
1880                 # delete editor backup file if it exists
1881                 if [ -w "$CDDBDATA~" ]; then
1882                         rm -f "$CDDBDATA~"
1883                 fi
1884         fi
1885
1886         # Some heuristics first. Look at Disc Title, and if it starts with
1887         # "Various", then we'll assume Various Artists
1888         if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2- -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
1889                 echo "Looks like a Multi-Artist CD" >&2
1890                 VARIOUSARTISTS=y
1891         else
1892                 echo -n "Is the CD multi-artist? [y/n] (n): " >&2
1893                 if [ "$INTERACTIVE" = "y" ]; then
1894                         read VARIOUSARTISTS
1895                 else
1896                         echo n >&2
1897                         VARIOUSARTISTS=n
1898                 fi
1899         fi
1900         if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
1901                 # Set a default
1902                 DEFAULTSTYLE=1
1903                 # Need NUMTRACKS before cddb-tool will return it:
1904                 NUMTRACKS=$(egrep '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
1905                 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1906                         # More than 1/2 tracks contain a "/", so guess forward
1907                         DEFAULTSTYLE=1
1908                 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1909                         # More than 1/2 contain a "-", so guess forward-dash
1910                         DEFAULTSTYLE=2
1911                 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1912                         # More than 1/2 contain something in parens, so guess trailing-paren
1913                         DEFAULTSTYLE=6
1914                 fi
1915
1916                 echo "1) Artist / Title" >&2
1917                 echo "2) Artist - Title" >&2
1918                 echo "3) Title / Artist" >&2
1919                 echo "4) Title - Artist" >&2
1920                 echo "5) Artist: Title" >&2
1921                 echo "6) Title (Artist)" >&2
1922                 echo "7) This is a single-artist CD" >&2
1923                 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
1924                 if [ "$INTERACTIVE" = "y" ]; then
1925                         read VARIOUSARTISTSTYLE
1926                 else
1927                         echo $DEFAULTSTYLE >&2
1928                         VARIOUSARTISTSTYLE=$DEFAULTSTYLE
1929                 fi
1930                 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
1931                 # If they press Enter, then the default style (0) was chosen
1932                 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
1933                         echo "Invalid selection. Please choose a number between 1 and 7."
1934                         echo -n "Selection [1-7]: "
1935                         read VARIOUSARTISTSTYLE
1936                         VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
1937                 done
1938                 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
1939                         VARIOUSARTISTSTYLE=$DEFAULTSTYLE
1940                 fi
1941                 vecho "Selected: $VARIOUSARTISTSTYLE"
1942                 case "$VARIOUSARTISTSTYLE" in
1943                 1) # Artist / Title
1944                         VARIOUSARTISTSTYLE=forward
1945                         ;;
1946                 2) # Artist - Title
1947                         VARIOUSARTISTSTYLE=forward-dash
1948                         ;;
1949                 3) # Title / Artist
1950                         VARIOUSARTISTSTYLE=reverse
1951                         ;;
1952                 4) # Title - Artist
1953                         VARIOUSARTISTSTYLE=reverse-dash
1954                         ;;
1955                 5) # Artist: Title
1956                         VARIOUSARTISTSTYLE=colon
1957                         ;;
1958                 6) # Title (Artist)
1959                         VARIOUSARTISTSTYLE=trailing-paren
1960                         ;;
1961                 7) # Single Artist
1962                         VARIOUSARTISTS=n
1963                         ;;
1964                 esac
1965         fi
1966
1967         echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
1968         echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
1969
1970         if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
1971                 if [ "$CDDBDATAMD5SUM" != "" ]  && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
1972                         # This works but does not have the necessary error checking
1973                         # yet. If you are familiar with the CDDB spec
1974                         # (see http://www.freedb.org/src/latest/DBFORMAT) 
1975                         # and can create an error-free entry on your own, then put
1976                         # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
1977                         # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
1978                         # your abcde.conf to change the email address submissions are
1979                         # sent to.
1980
1981                         # submit the modified file, if they want
1982                         if [ "$NOSUBMIT" != "y" ]; then
1983                                 echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
1984                                 read YESNO
1985                                 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
1986                                         [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
1987                                 do
1988                                         echo -n 'Invalid selection. Please answer "y" or "n": '
1989                                         read YESNO
1990                                 done
1991                                 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
1992                                         echo -n "Sending..."
1993                                         $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
1994                                         echo "done."
1995                                 fi
1996                         fi
1997                 fi
1998         fi
1999         # Make sure the cache directory exists
2000         mkdir -p $CDDBLOCALDIR
2001         # Cache edited CDDB entry in the user's cddb dir
2002         if [ "$CDDBCOPYLOCAL" = "y" ] || [ "$COPYCDDBLOCAL" = "Y" ]; then
2003                 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
2004         fi
2005
2006         echo "cddb-edit" >> "$ABCDETEMPDIR/status"
2007 }
2008
2009 # do_cdread [tracknumber]
2010 # do_cdread onetrack [firsttrack] [lasttrack]
2011
2012 do_cdread ()
2013 {
2014         # The commands here don't go through run_command because they're never supposed to be silenced
2015         # return codes need to be doublechecked anyway, however
2016         if [ "$1" = "onetrack" ]; then
2017                 # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
2018                 # FIXME # Until then, we grab the whole CD in one track, no matter what
2019                 # the user said
2020                 # We need the first and last track for cdda2wav
2021                 FIRSTTRACK=$2
2022                 LASTTRACK=$3
2023                 UTRACKNUM=$FIRSTTRACK
2024                 case "$CDROMREADERSYNTAX" in
2025                         cdparanoia) READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
2026                         cdda2wav) READTRACKNUMS="$FIRSTTRACK+$LASTRACK" ;;
2027                         *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
2028                            exit 1 ;;
2029                 esac
2030         else
2031                 UTRACKNUM=$1
2032         fi
2033         CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2034         if [ "$USEPIPES" = "y" ]; then
2035                 TEMPARG="PIPE_$CDROMREADERSYNTAX"
2036                 FILEARG="$( eval echo "\$$TEMPARG" )"
2037                 REDIR=""
2038                 PIPE_MESSAGE="and encoding "
2039         else
2040                 WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
2041                 case "$CDROMREADERSYNTAX" in
2042                 ## FIXME ## Find the case for dagrab, to avoid exceptions
2043                         dagrab)
2044                                 FILEARG="-f $WAVDATA"
2045                                 ;;
2046                         *)
2047                                 FILEARG="$WAVDATA"
2048                                 ;;
2049                 esac
2050                 REDIR=">&2"
2051         fi
2052         if [ "$1" = "onetrack" ]; then
2053                 echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
2054         else
2055                 if [ -r "$CDDBDATA" ]; then
2056                         #TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
2057                         do_getcddbinfo TRACKNAME
2058                         echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
2059                 else
2060                         echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
2061                 fi
2062         fi
2063         case "$CDROMREADERSYNTAX" in
2064                 cdparanoia) 
2065                         nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;
2066                 cdda2wav)
2067                         if [ "$OSFLAVOUR" = "OSX" ] ; then
2068                                 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
2069                                 disktool -u ${CDROM#/dev/} 0
2070                                 # Also, in OSX the cdrom device for cdda2wav changes...
2071                                 CDDA2WAVCDROM="IODVDServices"
2072                         elif [ "$OSFLAVOUR" = "FBSD" ] ; then
2073                                 CDDA2WAVCDROM="$CDROMID"
2074                         else
2075                                 if [ "$CDROMID" = "" ]; then
2076                                         CDDA2WAVCDROM="$CDROM"
2077                                 else
2078                                         CDDA2WAVCDROM="$CDROMID"
2079                                 fi
2080                         fi
2081                         nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR
2082                         ;;
2083                 ## FIXME ## We have an exception for dagrab, since it uses -f
2084                 ## FIXME ## Shall we just use -f $FILEARG ??
2085                 dagrab) nice $READNICE $CDROMREADER -d $CDROM -v $UTRACKNUM "$FILEARG" $REDIR
2086                         ;;
2087                 cddafs)
2088                         # Find the track's mounted path
2089                         REALTRACKNUM=$(expr $UTRACKNUM + 0)
2090                         FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
2091                         FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
2092                         # If the file exists, copy it
2093                         if [ -e "$FILEPATH" ] ; then
2094                                 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" $REDIR
2095                         else
2096                                 false
2097                         fi ;;
2098                 debug) nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM -w $UTRACKNUM-[:1] "$FILEARG" $REDIR
2099                         ;;
2100         esac
2101         RETURN=$?
2102         # If we get some error or we get some missing wav 
2103         # (as long as we dont use pipes)
2104         if [ "$RETURN" != "0" -o \( ! -s "$WAVDATA" -a X"$USEPIPES" != "Xy" \) ]; then
2105                 # Thank goodness errors is only machine-parseable up to the
2106                 # first colon, otherwise this woulda sucked
2107                 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
2108                         RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
2109                 fi
2110                 if [ "$USEPIPES" = "y" ]; then
2111                         echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2112                 else
2113                         echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2114                 fi
2115                 return $RETURN
2116         else
2117                 if [ "$USEPIPES" = "y" ]; then
2118                         echo readencodetrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2119                 else
2120                         echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2121                         if [ "$1" = "onetrack" ]; then
2122                                 echo onetrack >> "$ABCDETEMPDIR/status"
2123                         fi
2124                 fi
2125         fi
2126 }
2127
2128 # do_cdspeed
2129 # No values accepted, only uses env variables
2130 do_cdspeed () 
2131 {
2132         if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
2133                 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
2134         else
2135                 echo "abcde: unable to set the device speed" >&2
2136         fi
2137 }
2138
2139 # vecho [message]
2140 #
2141 # vecho outputs a message if EXTRAVERBOSE is selected
2142 vecho ()
2143 {
2144 if [ x"$EXTRAVERBOSE" != "x" ]; then
2145         echo $@
2146 fi
2147 }
2148
2149 # User-redefinable functions
2150 # Custom filename munging:
2151 mungefilename ()
2152 {
2153         #echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
2154         echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
2155 }
2156
2157 # Custom genre munging:
2158 mungegenre ()
2159 {
2160         echo $CDGENRE | tr "[:upper:]" "[:lower:]"
2161 }
2162
2163 # pre_read
2164 # Empty pre_read function, to be defined in the configuration file.
2165 pre_read ()
2166 {
2167 :
2168 }
2169
2170 # post_read
2171 # Empty post_read function, to be defined in the configuration file.
2172 post_read ()
2173 {
2174 :
2175 }
2176
2177 ###############################################################################
2178 # End of functions
2179 #
2180 # Start of execution
2181 ###############################################################################
2182
2183 # Builtin defaults
2184 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
2185 CDDBSUBMIT=freedb-submit@freedb.org
2186 CDDBPROTO=5
2187 HELLOINFO="$(whoami)@$(hostname)"
2188 CDDBCOPYLOCAL="n"
2189 CDDBLOCALDIR="$HOME/.cddb"
2190 CDDBUSELOCAL="n"
2191
2192 # List of fields we parse and show during the CDDB parsing...
2193 SHOWCDDBFIELDS="year,genre"
2194
2195 INTERACTIVE=y
2196 CDROMREADERSYNTAX=cdparanoia
2197 ENCODERSYNTAX=default
2198
2199 MP3ENCODERSYNTAX=default
2200 OGGENCODERSYNTAX=default
2201 FLACENCODERSYNTAX=default
2202 SPEEXENCODERSYNTAX=default
2203 MPPENCODERSYNTAX=default
2204 NORMALIZERSYNTAX=default
2205 CUEREADERSYNTAX=default
2206
2207 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
2208 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
2209 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
2210 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
2211 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
2212 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
2213 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2214 PLAYLISTDATAPREFIX=''
2215 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2216 VAPLAYLISTDATAPREFIX=''
2217 DOSPLAYLIST=n
2218 COMMENT=''
2219 ID3TAGV=2
2220 ENCNICE=10
2221 READNICE=10
2222 DISTMP3NICE=10
2223 VARIOUSARTISTS=n
2224 VARIOUSARTISTSTYLE=forward
2225 KEEPWAVS=n
2226 PADTRACKS=n
2227
2228 # If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
2229 # i.e. CDROMID="1,0,0"
2230 CDROMID=""
2231 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
2232 # If we are using the ide-scsi emulation layer, we need to define a "g"
2233 CDPARANOIACDROMBUS="d"
2234
2235 # program paths - defaults to checking your $PATH
2236 # mp3
2237 LAME=lame
2238 GOGO=gogo
2239 BLADEENC=bladeenc
2240 L3ENC=l3enc
2241 XINGMP3ENC=xingmp3enc
2242 MP3ENC=mp3enc
2243 # ogg
2244 VORBIZE=vorbize
2245 OGGENC=oggenc
2246 # flac
2247 FLAC=flac
2248 # speex
2249 SPEEXENC=speexenc
2250 # mpp (Musepack)
2251 MPPENC=mppenc
2252
2253 ID3=id3
2254 ID3V2=id3v2
2255 EYED3=eyeD3
2256 CDPARANOIA=cdparanoia
2257 CDDA2WAV=cdda2wav
2258 DAGRAB=dagrab
2259 CDDAFS=cp
2260 CDDISCID=cd-discid
2261 CDDBTOOL=cddb-tool
2262 EJECT=eject
2263 MD5SUM=md5sum
2264 DISTMP3=distmp3
2265 VORBISCOMMENT=vorbiscomment
2266 METAFLAC=metaflac
2267 NORMALIZE=normalize-audio
2268 CDSPEED=eject
2269 VORBISGAIN=vorbisgain
2270 MKCUE=mkcue
2271 MKTOC=cdrdao
2272 DIFF=diff
2273
2274 # Options for programs called from abcde
2275 # mp3
2276 LAMEOPTS=
2277 GOGOOPTS=
2278 BLADEENCOPTS=
2279 L3ENCOPTS=
2280 XINGMP3ENCOPTS=
2281 MP3ENCOPTS=
2282 # ogg
2283 VORBIZEOPTS=
2284 OGGENCOPTS=
2285 # flac
2286 FLACOPTS="-f"
2287 # speex
2288 SPEEXENCOPTS=
2289 # mpc
2290 MPPENCOPTS=
2291
2292 ID3OPTS=
2293 ID3V2OPTS=
2294 CDPARANOIAOPTS=
2295 CDDA2WAVOPTS=
2296 DAGRABOPTS=
2297 CDDAFSOPTS="-f"
2298 CDDBTOOLOPTS=
2299 EJECTOPTS=
2300 DISTMP3OPTS=
2301 NORMALIZEOPTS=
2302 CDSPEEDOPTS="-x"
2303 CDSPEEDVALUE=
2304 MKCUEOPTS=
2305 MKTOCOPTS=""
2306 VORBISCOMMENTOPTS="-R"
2307 METAFLACOPTS="--no-utf8-convert"
2308
2309 # Default to one process if -j isn't specified
2310 MAXPROCS=1
2311
2312 # List of actions to perform - by default, run to completion
2313 ACTIONS=cddb,read,encode,tag,move,clean
2314
2315 # List of prefered outputs - by default, run with whatever we have in the path
2316 # This option is basicaly for Debian package dependencies
2317 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:lame,mp3:bladeenc,spx:speex
2318
2319 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for Linux/OpenBSD/NetBSD.
2320 # Let's use these checkings to determine the OS flavour, which will be used later
2321 if [ X$(uname) = "XFreeBSD" ] ; then
2322         HTTPGET=fetch
2323         MD5SUM=md5
2324         NEEDCDROMID=y
2325         OSFLAVOUR=FBSD
2326 elif [ X$(uname) = "XDarwin" ] ; then
2327         HTTPGET=curl
2328         OSFLAVOUR=OSX
2329         # We should have disktool in OSX, but let's be sure...
2330         NEEDDISKTOOL=y
2331         CDROMREADERSYNTAX=cddafs
2332 elif [ X$(uname) = "XOpenBSD" ] ; then
2333         HTTPGET=wget
2334         MD5SUM=md5
2335 elif [ X$(uname) = "XNetBSD" ] ; then
2336         HTTPGET=ftp
2337         MD5SUM=md5
2338 else
2339         HTTPGET=wget
2340 fi
2341
2342 # If CDDBAVAIL is set to n, no CDDB read is done
2343 # If USEID3 is set to n, no ID3 tagging is done
2344 CDDBAVAIL=y
2345 USEID3=y
2346 USEID3V2=y
2347
2348 if [ -z "$OUTPUTDIR" ]; then
2349         OUTPUTDIR=$(pwd)
2350 fi
2351
2352 if [ -z "$WAVOUTPUTDIR" ]; then
2353         WAVOUTPUTDIR="$OUTPUTDIR"
2354 fi
2355
2356 # Load system defaults
2357 if [ -r /etc/abcde.conf ]; then
2358         . /etc/abcde.conf
2359 fi
2360 # Load user preference defaults
2361 if [ -r $HOME/.abcde.conf ]; then
2362         . $HOME/.abcde.conf
2363 fi
2364
2365 # By this time, we need some HTTPGETOPTS already defined.
2366 # If the user has defined a non-default HTTPGET method, we should not be empty.
2367
2368 if [ "$HTTPGETOPTS" = "" ] ; then
2369         case $HTTPGET in
2370                 wget) HTTPGETOPTS="-q -O -";;
2371                 curl) HTTPGETOPTS="-f -s";;
2372                 fetch)HTTPGETOPTS="-q -o -";;
2373                 ftp)  HTTPGETOPTS="-q -o -";;
2374                 *) echo "abcde warning: HTTPGET in non-standard and HTTPGETOPTS are not defined." >&2 ;;
2375         esac
2376 fi
2377
2378 # If the CDROM has not been set yet, find a suitable one.
2379 # If this is a devfs system, default to /dev/cdroms/cdrom0
2380 # instead of /dev/cdrom
2381 if [ "$CDROM" = "" ] ; then
2382         if [ -e /dev/cdroms/cdrom0 ]; then
2383                 CDROM=/dev/cdroms/cdrom0
2384         elif [ -e /dev/cdrom ]; then
2385                 CDROM=/dev/cdrom
2386         elif [ -e /dev/cd0c ]; then
2387                 CDROM=/dev/cd0c
2388         elif [ -e /dev/acd0c ]; then
2389                 CDROM=/dev/acd0c
2390         elif [ -e /dev/disk1 ]; then
2391                 CDROM=/dev/disk1
2392         fi
2393 fi
2394
2395 # Parse command line options
2396 #while getopts 1a:A:bc:C:d:Dehj:klLmMnNo:pPr:Rs:S:t:T:vVxw:W: opt ; do
2397 while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPr:Rs:S:t:T:vVxw:W: opt ; do
2398         case "$opt" in
2399                 1) ONETRACK=y ;;
2400                 a) ACTIONS="$OPTARG" ;;
2401                 A) EXPACTIONS="$OPTARG" ;;
2402                 b) BATCH=y ;;
2403                 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else echo "abcde error: config file \"$OPTARG\" cannot be found." >&2 ; exit 1 ; fi ;;
2404                 C) DISCID="${OPTARG#abcde.}" ;;
2405                 d) CDROM="$OPTARG" ;;
2406                 D) set -x ;;
2407                 e) ERASEENCODEDSTATUS=y ;;
2408                 h) usage; exit ;;
2409                 e) ERASEENCODEDSTATUS=y ;;
2410                 E) ENCODING="$OPTARG" ;;
2411 #               f) FORCECDDBUSELOCAL=y ;;
2412                 i) INLINETAG=y ;;
2413                 j) MAXPROCS="$OPTARG" ;;
2414                 k) KEEPWAVS=y ;;
2415                 l) LOWDISK=y ;;
2416                 L) CDDBUSELOCAL=y ;;
2417                 n) CDDBAVAIL=n ;;
2418                 N) INTERACTIVE=n ;;
2419                 m) DOSPLAYLIST=y ;;
2420                 M) MAKECUEFILE=y ;;
2421                 o) OUTPUTTYPE="$OPTARG" ;;
2422                 p) PADTRACKS=y ;;
2423                 P) USEPIPES=y ;;
2424                 r) REMOTEHOSTS="$OPTARG" ;;
2425                 R) REPLAYGAIN=y ;;
2426                 s) SHOWCDDBFIELDS="$OPTARG" ;;
2427                 S) CDSPEEDVALUE="$OPTARG" ;;
2428 #               t) PREPROCESSFORMATS="$OPTARG"
2429 #                  PREPROCESS=y ;;
2430 #               T) POSTPROCESSFORMATS="$OPTARG" ;;
2431                 t) STARTTRACKNUMBER="$OPTARG" ;;
2432                 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
2433                 v) 
2434                    echo "This is abcde v$VERSION."
2435                    echo "Usage: abcde [options] [tracks]"
2436                    echo "abcde -h for extra help"
2437                    exit
2438                    ;;
2439                 V) EXTRAVERBOSE="y" ;;
2440                 x) EJECTCD="y" ;;
2441                 w) COMMENT="$OPTARG" ;;
2442                 W) if echo $OPTARG | grep -q "[[:digit:]]" ; then 
2443                      STARTTRACKNUMBER="${OPTARG}01" ; STARTTRACKNUMBERTAG="y" ; COMMENT="CD${OPTARG}"
2444                    else
2445                      echo "abcde error: argument of -W must be integer"
2446                          exit 1
2447                    fi
2448                    ;;
2449                 ?) usage; exit ;;
2450         esac
2451 done
2452
2453 shift $(($OPTIND - 1))
2454
2455 # Decide if we can continue.
2456 if [ "$ONETRACK" = "y" ]; then 
2457         # FIXME # remove check as soon as we find out about the other readers
2458         case "$CDROMREADERSYNTAX" in
2459                 cdparanoia) ;;
2460                 cdda2wav) ;;
2461                 *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
2462                    exit 1 ;;
2463         esac
2464         if [ "$BATCH" = "y" ]; then
2465                 echo "abcde error: BATCH mode is not compatible with ONETRACK mode"
2466                 BATCH=n
2467         fi
2468         # It does not matter how many tracks we want. In ONETRACK mode we grab them all
2469         # FIXME # allow ranges of tracks to be selected for onetrack ripping
2470         if [ $# -gt 0 ]; then
2471                 vecho "abcde warning: ONETRACK mode selected, grabbing all tracks..."
2472         fi
2473 else
2474         while [ $# -gt 0 ]; do
2475                 # Range parsing code courtesy of Vincent Ho
2476                 RSTART=$(echo $1 | cut -f1 -d-)
2477                 REND=$(echo $1 | cut -f2 -d-)
2478                 if [ "$RSTART" = "$REND" ]; then
2479                         NEWTRACKS="$RSTART"
2480                 else
2481                         NEWTRACKS=$(f_seq_line $RSTART $REND)
2482                 fi
2483                 TRACKQUEUE=$(echo "$TRACKQUEUE" "$NEWTRACKS")
2484                 shift
2485         done
2486 fi
2487
2488 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
2489 # List of experimental actions: retag,transcode
2490
2491 # Determine what actions are to be done from $ACTIONS and set the
2492 # following environment variables for them:
2493 DOCDDB=n
2494 DOREAD=n
2495 DONORMALIZE=n
2496 DOPREPROCESS=n
2497 DOENCODE=n
2498 DOPOSTPROCESS=n
2499 DOTAG=n
2500 DOMOVE=n
2501 DOPLAYLIST=n
2502 DOCLEAN=n
2503
2504 for ACTION in $(echo $ACTIONS | tr , \ )
2505 do
2506         case $ACTION in
2507                 cddb) DOCDDB=y;;
2508                 read) DOREAD=y;;
2509                 normalize) DONORMALIZE=y; DOREAD=y;;
2510 #               preprocess) DOPREPROCESS=y; DOREAD=y;;
2511                 encode) DOENCODE=y; DOREAD=y;;
2512 #               postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
2513                 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
2514                 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
2515                 playlist) DOCDDB=y; DOPLAYLIST=y;;
2516                 clean) DOCLEAN=y;;
2517         esac
2518 done
2519
2520 for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
2521         case $SHOWCDDBFIELD in
2522                 y*|Y*) SHOWCDDBYEAR="y";;
2523                 g*|G*) SHOWCDDBGENRE="y";;
2524                 *) ;;
2525         esac
2526 done
2527
2528 # Sanity checks:
2529
2530 # At this point a CDROM has to be defined, so we check it exists.
2531 if [ X"$CDROM" != "X" ] ; then 
2532         if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
2533                 if [ "$OSFLAVOUR" = "FBSD" ]; then
2534                         if ! echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then
2535                                 echo "abcde error: CDROMID not in the right format for $CDROMREADERSYNTAX"
2536                                 echo "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
2537                                 exit 1
2538                         fi
2539                 fi
2540         elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
2541                 echo "abcde error: CDROM device cannot be found." >&2
2542                 exit 1
2543         fi
2544 # avoid processing if we are not going to hit the CDROM.
2545 elif [ X"$DOREAD" = "Xy" ]; then
2546         echo "abcde error: CDROM has not been defined or cannot be found" >&2
2547         exit 1
2548 fi
2549
2550 # USEPIPES pre-tests, before we get into more serious stuff
2551 # Not compatible with:
2552 # - multiple outputs
2553 # - normalize
2554 # - lowdisk algorithm
2555 # - anything else?
2556 if [ X"$USEPIPES" = "Xy" ]; then
2557         if [ $(echo "$OUTPUTTYPE" | tr , \  | wc -w ) -gt 1 ]; then
2558                 echo "abcde error: Unix pipes not compatible with multiple outputs" >&2
2559                 exit 1
2560         fi
2561         if [ X"$DONORMALIZE" = "Xy" ]; then
2562                 echo "abcde error: Unix pipes not compatible with normalizer"
2563                 # FIXME # Do we need to exit or shall we just disable the mode?
2564                 exit 1
2565         fi
2566         if [ X"$DOENCODE" = "Xn" ]; then
2567                 vecho "Disabling Unix pipes since we are not encoding!"
2568                 USEPIPES=n
2569         fi
2570         if [ X"$LOWDISK" = "Xy" ]; then
2571                 vecho "abcde error: Unix pipes not compatible with lowdisk algorithm"
2572                 exit 1
2573         fi
2574 fi
2575
2576 # Check the encoding format from the ones available in the system, if nothing has been configured in the system.
2577 if [ X"$OUTPUTTYPE" = "X" ]; then
2578         for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
2579                 DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
2580                 DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
2581                 if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
2582                         OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
2583                         vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
2584                         break
2585                 fi
2586         done
2587         if [ X"$OUTPUTTYPE" = "X" ]; then
2588                 echo "abcde error: no encoder found in the PATH" >&2
2589                 echo "hits: are all dependencies installed? has the \$PATH been modified?" >&2
2590                 exit 1
2591         fi
2592 fi
2593
2594 # Decide which CDROM reader we're gonna use
2595 case "$CDROMREADERSYNTAX" in
2596         cdparanoia|debug)
2597                 CDROMREADER="$CDPARANOIA"
2598                 CDROMREADEROPTS="$CDPARANOIAOPTS"
2599                 ;;
2600         cdda2wav)
2601                 CDROMREADER="$CDDA2WAV"
2602                 CDROMREADEROPTS="$CDDA2WAVOPTS"
2603                 ;;
2604         dagrab)
2605                 CDROMREADER="$DAGRAB"
2606                 CDROMREADEROPTS="$DAGRABOPTS"
2607                 ;;
2608         cddafs)
2609                 CDROMREADER="$CDDAFS"
2610                 CDROMREADEROPTS="$CDDAFSOPTS"
2611                 ;;
2612 esac
2613
2614 # There's only one normalize...
2615 case "$NORMALIZERSYNTAX" in
2616         default|normalize)
2617                 NORMALIZER="$NORMALIZE"
2618                 NORMALIZEROPTS="$NORMALIZEOPTS"
2619                 ;;
2620 esac
2621
2622 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
2623 if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
2624         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ ); do
2625                 case "$OUTPUT" in
2626                         vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2627                         mp3:*)  MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2628                         flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2629                         spx:*)  SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2630                         mpc:*)  MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2631                 esac
2632         done
2633         for OUTPUT in $(echo $OUTPUTTYPE | tr , \ ); do
2634                 TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
2635                 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
2636         done
2637         OUTPUTTYPE="$TEMPOUTPUTTYPE"
2638 fi
2639
2640 # 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
2641
2642 # Getting ready for multiple output changes
2643 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
2644 do
2645         case $OUTPUT in
2646                 vorbis|ogg)
2647                         [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
2648                         [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
2649                         [ "$REPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
2650                         OGGOUTPUTCONTAINER=ogg
2651                         ;;
2652                 mp3)
2653                         [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
2654                         [ "$DOTAG" = "y" ] && NEEDTAGGER=y
2655                         ;;
2656                 flac)
2657                         [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
2658                         [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
2659                         ;;
2660                 spx)
2661                         [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
2662                         ;;
2663                 mpc)
2664                         [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc
2665                         ;;
2666                 *)      echo "abcde error: Invalid OUTPUTTYPE defined" >&2
2667                         exit 1
2668                         ;;
2669         esac
2670 done
2671
2672 # decide which encoder
2673 case "$MP3ENCODERSYNTAX" in
2674         lame)
2675                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
2676                 MP3ENCODER="$LAME"
2677                 ;;
2678         gogo)
2679                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
2680                 MP3ENCODER="$GOGO"
2681                 ;;
2682         bladeenc)
2683                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
2684                 MP3ENCODER="$BLADEENC"
2685                 ;;
2686         l3enc)
2687                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
2688                 MP3ENCODER="$L3ENC"
2689                 ;;
2690         xingmp3enc)
2691                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
2692                 MP3ENCODER="$XINGMP3ENC"
2693                 ;;
2694         mp3enc)
2695                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
2696                 MP3ENCODER="$MP3ENC"
2697                 ;;
2698 esac
2699 case "$OGGENCODERSYNTAX" in
2700         vorbize)
2701                 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
2702                 OGGENCODER="$VORBIZE"
2703                 ;;
2704         oggenc)
2705                 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
2706                 OGGENCODER="$OGGENC"
2707                 ;;
2708 esac
2709 case "$FLACENCODERSYNTAX" in
2710         flac)
2711                 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
2712                 FLACENCODER="$FLAC"     
2713                 # FLAC streams can be encapsulated on a Ogg transport layer
2714                 if echo "$FLACENCODEROPTS" | egrep -q -- "(^| )--ogg($| )" ;then
2715                         echo "abcde error: FLAC on an Ogg container is not yet supported" >&2
2716                         echo "             due to problem with adding comments to such files" >&2
2717                         exit 1
2718                         FLACOUTPUTCONTAINER=ogg
2719                 else
2720                         FLACOUTPUTCONTAINER=flac
2721                 fi
2722                 ;;
2723 esac
2724 case "$SPEEXENCODERSYNTAX" in
2725         speexenc)
2726                 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
2727                 SPEEXENCODER="$SPEEXENC"
2728                 ;;
2729 esac
2730 case "$MPPENCODERSYNTAX" in
2731         mppenc)
2732                 MPPENCODEROPTS="${MPPENCODEROPTSCLI:-$MPPENCOPTS}"
2733                 MPPENCODER="$MPPENC"
2734                 ;;
2735 esac
2736                 
2737 # and which tagger
2738
2739 if [ "$ID3TAGV" = "1" ]; then
2740         TAGGER="$ID3"
2741         TAGGEROPTS="$ID3OPTS"
2742 else
2743         TAGGER="$ID3V2"
2744         TAGGEROPTS="$ID3V2OPTS"
2745 fi
2746
2747 # Options for mkcue
2748 case "$CUEREADERSYNTAX" in
2749         default|mkcue)
2750                 CUEREADEROPTS="${CDROM}"
2751                 CUEREADER="$MKCUE"
2752                 ;;
2753 esac
2754
2755 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
2756 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
2757         echo "abcde error: FLAC on an Ogg container is not yet supported" >&2
2758         echo "             due to problem with adding comments to such files" >&2
2759         exit 1
2760         OGGOUTPUTCONTAINER=ogg.ogg
2761         FLACOUTPUTCONTAINER=flac.ogg
2762         vecho "abcde warning: modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
2763 fi
2764
2765 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
2766
2767 if [ "$ENCNICE" ]; then
2768         ENCNICE="-n $ENCNICE"
2769 fi
2770 if [ "$READNICE" ]; then
2771         READNICE="-n $READNICE"
2772 fi
2773 if [ "$DISTMP3NICE" ]; then
2774         DISTMP3NICE="-n $DISTMP3NICE"
2775 fi
2776
2777 # Don't check for stuff if it's not needed
2778 if [ "$REMOTEHOSTS" ]; then 
2779         NEEDDISTMP3=y
2780 fi
2781 if [ "$DONORMALIZE" = "y" ]; then
2782         NEEDNORMALIZER=y
2783 fi
2784 if [ "$EJECTCD" = "y" ]; then
2785         NEEDEJECT=y
2786 fi
2787 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
2788         NEEDHTTPGET=y
2789 fi
2790 if [ "$MAKECUEFILE" = "y" ]; then
2791         NEEDCUEREADER=y
2792 fi
2793
2794 if [ X"$CDSPEEDVALUE" != "X" ]; then
2795         case "$CDROMREADERSYNTAX" in
2796                 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
2797                 *) NEEDCDSPEED=y ;;
2798         esac
2799 fi
2800
2801 # Rippers with USEPIPE support
2802 # FIXME # Include here all the rippers we can figure out support pipes
2803 PIPE_cdparanoia="-"
2804
2805 # Encoders with USEPIPE support
2806 # FIXME # Include here all the encoders we can figure out support pipes
2807 PIPE_lame="-"
2808 PIPE_bladeenc="-"
2809 PIPE_oggenc="-"
2810
2811 # Figure out if we can use pipes with the ripper/encoder combination
2812 # exit otherwise
2813 if [ "$USEPIPES" = "y" ]; then
2814         PIPERIPPERSVARCHECK="PIPE_${CDROMREADER}"
2815         case "$OUTPUT" in
2816                 mp3)
2817                         PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
2818                 vorbis|ogg)
2819                         PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
2820                 flac)
2821                         PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
2822                 spx)
2823                         PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
2824                 mpc)
2825                         PIPEENCODERSVARCHECK="PIPE_$MPPENCODER" ;;
2826         esac
2827         if [ ! -n "$( eval echo "\$$PIPERIPPERSVARCHECK" )" ] ; then
2828                 echo "abcde error: no support for pipes with given ripper" >&2
2829                 echo "read the USEPIPES file from the source tarball to help" >&2
2830                 echo "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz" >&2
2831                 exit 1;
2832         fi
2833         if [ ! -n "$( eval echo "\$$PIPEENCODERSVARCHECK" )" ] ; then
2834                 echo "abcde error: no support for pipes with given encoder" >&2
2835                 echo "read the USEPIPES file from the source tarball to help" >&2
2836                 echo "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz" >&2
2837                 exit 1;
2838         fi
2839 fi
2840
2841 # Make sure a buncha things exist
2842 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
2843         $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
2844         ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
2845         ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
2846         ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
2847         ${NEEDDISKTOOL+disktool} ${NEEDCDSPEED+$CDSPEED} \
2848         ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDCUEREADER+$CUEREADER}
2849 do
2850         # Cut off the command-line options we just added in
2851         X=$(echo $X | cut -d' ' -f2)
2852         if [ "$(which $X)" = "" ]; then
2853                 echo "abcde error: $X is not in your path." >&2
2854                 exit 1
2855         elif [ ! -x $(which $X) ]; then
2856                 echo "abcde error: $X is not executable." >&2
2857                 exit 1
2858         fi
2859 done
2860
2861 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
2862 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
2863 HTTPGET="$HTTPGET $HTTPGETOPTS"
2864
2865 # And last but not least, check if we can diff between files
2866 if [ -x $(which $DIFF) ]; then :; else
2867         vecho "[WAR] Disabling diff since we cannot find it in the \$PATH..."
2868         DIFF=""
2869 fi
2870
2871 # Here it used to say:
2872 # One thousand lines in, we can start doing stuff with things
2873 # Well, right now we are at line 2736 ;)
2874
2875 # Export needed things so they can be read in this subshell
2876 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
2877 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
2878
2879 # User-definable function to set some things. Use it for
2880 #  - closing the CD tray with eject -t
2881 #  - set the CD speed value with eject -x
2882 vecho -n "Executing customizable pre-read function... "
2883
2884 pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
2885
2886 vecho "done."
2887
2888 do_discid # Get ABCDETEMPDIR created and status file initialized
2889
2890 if [ "$DOCDDB" = "y" ]; then
2891         if [ $CDDBUSELOCAL = "y" ]; then
2892                 do_localcddb
2893         fi
2894         if checkstatus cddb-choice > /dev/null; then
2895                 :
2896         else 
2897                 if [ ! "$CDDBLOCALSUCCESS" = "y" ] ; then
2898                         do_cddbstat
2899                         do_cddbquery
2900                         do_cddbread
2901                 fi
2902         fi
2903         do_cddbedit
2904
2905         eval $($CDDBTOOL parse "$CDDBDATA")
2906 fi
2907
2908 # Before reading tracks, we set the speed of the device
2909
2910 if [ X"$CDSPEEDVALUE" != "X" ]; then
2911         case "$CDROMREADERSYNTAX" in
2912                 cdparanoia|debug) : ;;
2913                 *) do_cdspeed ;;
2914         esac
2915 fi
2916
2917 # Define the first and last track, since we might need them later in several places
2918 FIRSTTRACK=$( get_first $TRACKQUEUE )
2919 LASTTRACK=$( get_last $TRACKQUEUE )
2920
2921 if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
2922         mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
2923         grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
2924                 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
2925 fi
2926
2927 # Create playlist if needed (backgroundable) and start reading in tracks
2928
2929 (
2930
2931 if [ ! "$ONETRACK" = "y" ]; then
2932         if [ "$DOPLAYLIST" = "y" ]; then
2933                 echo Creating playlist... >&2
2934                 do_playlist
2935         fi
2936 fi
2937
2938 # For the lowdisk option, only one program is running at once so the encoder
2939 # can be unsilenced right away.
2940 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
2941         echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
2942 fi
2943
2944 if [ "$ONETRACK" = "y" ]; then 
2945         TRACKS="$FIRSTTRACK"
2946         if checkstatus readtrack-$FIRSTTRACK; then :; else
2947                 do_cdread onetrack $FIRSTTRACK $LASTTRACK
2948         fi
2949 else
2950         for UTRACKNUM in $TRACKQUEUE
2951         do
2952                 if [ "$DOREAD" = "y" ]; then
2953                         if [ "$USEPIPES" = "y" ]; then
2954                                 if checkstatus readencodetrack-$UTRACKNUM; then :; else
2955                                         # Read, pipe, shut up!
2956                                         do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
2957                                 fi
2958                         else
2959                                 if checkstatus readtrack-$UTRACKNUM; then :; else
2960                                         do_cdread $UTRACKNUM
2961                                 fi
2962                                 if [ "$?" != "0" ]; then
2963                                         # CD read failed - don't give the goahead to
2964                                         # the encoder
2965                                         echo NO
2966                                         exit
2967                                 fi
2968                         fi
2969                 fi
2970                 if [ "$BATCH" = "y" ]; then
2971                     :
2972                 else
2973                         echo NEXTTRACK # Get the encoder machine churning again
2974                         if [ "$DOREAD" = "y" ]; then
2975                                 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
2976                                         until checkstatus encodetrack-$UTRACKNUM
2977                                         do
2978                                                 if checkerrors encodetrack-$UTRACKNUM; then
2979                                                         break
2980                                                 fi
2981                                                 sleep 2
2982                                         done
2983                                 fi
2984                         fi
2985                 fi
2986         done
2987 fi
2988
2989 # Now that we're done the encoding can be loud again -
2990 # if we're not using SMP.
2991 if [ "$MAXPROCS" = "1" ]; then
2992         echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
2993 fi
2994
2995 # All tracks read, start encoding.
2996 if [ "$BATCH" = "y" ] || [ "$ONETRACK" = "y" ]; then
2997         echo NEXTTRACK
2998 fi
2999
3000 # Execute the user-defined post_read funtion before ejecting CD
3001 post_read
3002
3003 # We are now finished with the cdrom - it can be safely ejected. Note that
3004 # abcde will not have completed yet.
3005 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
3006         # We check if the disk we are processing is actually the disk inside the 
3007         # CD tray. If not, we do not eject the CD, since it might be so that the
3008         # user ejected it manually.
3009         #CURRENTTRACKINFO=$($CDDISCID $CDROM)
3010         #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then 
3011         # More FreeBSD bits.
3012         if [ X"$(uname)" = X"FreeBSD" ] ; then
3013                 # FreeBSD eject uses the EJECT environment variable to name the CDROM
3014                 # but in this script EJECT is in the envionment and names the program
3015                 eject=$EJECT
3016                 unset EJECT
3017                 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
3018                 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
3019                 $eject $EJECTOPTS $cd
3020         elif [ X"$(uname)" = X"Darwin" ] ; then
3021                 disktool -e ${CDROM#/dev/} 0
3022         else
3023                 $EJECT $EJECTOPTS $CDROM
3024         fi
3025         #fi
3026 fi
3027
3028 ) | (
3029
3030 ## Do we need to pre-process 
3031 #if [ x"$PREPROCESS" = "x" ] ; then
3032 #       cat
3033 #else
3034 #       for PRETRACKNUM in $TRACKQUEUE
3035 #       do
3036 #               read GOAHEAD
3037 #               if [ "$GOAHEAD" = "NO" ]; then break; fi
3038 #               PREPROCEED=
3039 #               until [ $PREPROCEED ]
3040 #               do
3041 #                       if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
3042 #                       # all locations are working, wait and try again later
3043 #                       if [ ! $PREPROCEED ]; then sleep 3; fi
3044 #               done
3045 #               ( do_preprocess $PRETRACKNUM 
3046 #               echo "NEXTTRACK"
3047 #               ) &
3048 #       done
3049 #fi
3050 #
3051 #) | (
3052
3053 # In batch mode, we want all tracks to be read first.
3054 if [ "$BATCH" = "y" ]; then
3055         read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
3056         if [ "$GOAHEAD" = "NO" ]; then break; fi
3057         for LASTTRACK in $TRACKQUEUE; do :; done
3058         if checkstatus readtrack-$LASTTRACK; then
3059                 if [ "$DONORMALIZE" = "y" ]; then
3060                         if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
3061                         if checkerrors batch-normalize; then exit; fi
3062                 fi
3063                 if [ "$DOENCODE" = "y" ]; then
3064                         if checkstatus encodetrack-$LASTTRACK; then :; else do_batch_encode; fi
3065                         if checkerrors batch-encode; then exit; fi
3066                 fi
3067         fi
3068 fi
3069
3070 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
3071 if [ "$ONETRACK" = "y" ] ; then
3072         TRACKQUEUE="$FIRSTTRACK"
3073         TRACKS="$FIRSTTRACK"
3074 fi
3075
3076 # Do the encoding, including parallelization of remote encoding
3077 # Figure out where each track is going to be encoded
3078 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
3079 if [ "$MAXPROCS" != "0" ]; then
3080         for NUM in $(f_seq_row 1 "$MAXPROCS")
3081         do
3082                 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
3083         done
3084 fi
3085 # Strip whitespace
3086 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
3087 for UTRACKNUM in $TRACKQUEUE
3088 do
3089         # Wait for our cue
3090         read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
3091         if [ "$GOAHEAD" = "NO" ]; then break; fi
3092         # find out where this track is to be encoded
3093         if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
3094                 # Make sure we have a place to encode this, if not, exit stage right
3095                 if [ -z "$ENCODELOCATIONS" ]; then
3096                         continue
3097                 fi
3098                 PROCEED=
3099                 until [ $PROCEED ]
3100                 do
3101                         for LOCATION in $ENCODELOCATIONS
3102                         do
3103                                 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
3104                                 # check first if a track has ever been assigned to this location
3105                                 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
3106                                 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
3107                                 if checkerrors encodetrack-$PREVIOUSTRACK; then
3108                                         for TEMPLOCATION in $ENCODELOCATIONS
3109                                         do
3110                                                 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
3111                                                         TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
3112                                                 fi
3113                                         done
3114                                         ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
3115                                         ABORT=y
3116                                         PROCEED=y
3117                                         break
3118                                 fi
3119                                 # We're still here, this location must have been previously assigned,
3120                                 # and last completed without error - check if it's done with the
3121                                 # previous track yet
3122                                 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
3123                         done
3124                         # all locations are working, wait and try again later
3125                         if [ ! $PROCEED ]; then sleep 3; fi
3126                 done
3127                 # Record the location we're about to encode the next track at
3128                 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
3129         fi
3130         # Don't proceed with the rest of the loop if we can't encode
3131         if [ "$ABORT" ]; then continue; fi
3132         # Set TRACKNUM, TRACKNAME
3133         if [ -e "$CDDBDATA" ]; then
3134                 if [ "$ONETRACK" = "y" ]; then 
3135                         TRACKNAME="$DALBUM"
3136                         TRACKNUM="$FIRSTTRACK"
3137                         splitvarious
3138                 else
3139 #                       TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${UTRACKNUM} + 0))
3140                         TRACKNUM=$UTRACKNUM
3141                         CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
3142                         #TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
3143                         do_getcddbinfo TRACKNAME
3144                         splitvarious
3145                 fi
3146         fi
3147         # You can't encode a file which needs to be normalized before finishing
3148         # You can't tag a file before it's finished encoding -
3149         # thus all of this is backgrounded together
3150         (
3151         if [ "$DONORMALIZE" = "y" ]; then
3152                 if checkstatus readtrack-$UTRACKNUM; then
3153                         if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
3154                 fi
3155         fi
3156         if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
3157                 if checkstatus readtrack-$UTRACKNUM; then
3158                         #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
3159                         if [ "$DONORMALIZE" = "y" ]; then
3160                                 if checkstatus normalizetrack-$UTRACKNUM; then
3161                                         if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
3162                                 fi
3163                         else
3164                                 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
3165                         fi
3166                 fi
3167         fi
3168         if [ "$DOTAG" = "y" ]; then
3169                 if checkstatus encodetrack-$UTRACKNUM; then
3170                         if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
3171                 fi
3172                 # Lets tag the cue file
3173                 if checkstatus cleancuefile >/dev/null; then :; else
3174                         if checkstatus cuefile >/dev/null ; then 
3175                                 do_cleancue
3176                         fi
3177                 fi
3178         fi
3179         if [ "$DOMOVE" = "y" ]; then
3180                 if checkstatus tagtrack-$UTRACKNUM; then
3181                         if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
3182                 fi
3183         fi
3184         ) &
3185 done
3186
3187
3188 # Go through it again and make sure there's no distmp3 stragglers, otherwise
3189 # we'll delete the files they're working on
3190 ## FIXME ## Check also for files which are encoded using PIPEs.
3191 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
3192         PROCEED=
3193         until [ $PROCEED ]
3194         do
3195                 PROCEED=y
3196                 for LOCATION in $ENCODELOCATIONS
3197                 do
3198                         CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
3199                         # "How can he give us a status update, if he's DEAD?"
3200                         if checkstatus encodetrack-$CHECKTRACK; then
3201                                 continue
3202                         fi
3203                         # Nothing to see here please go quietly back to your homes
3204                         if [ -z "$CHECKTRACK" ]; then continue; fi
3205                         # You're still here? Maybe there is something...
3206                         if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
3207                 done
3208                 # hold up
3209                 if [ ! $PROCEED ]; then sleep 5; fi
3210         done
3211 fi
3212 # If the above didn't catch the stragglers, this will
3213 wait
3214 if checkstatus replaygain; then :; else
3215         do_replaygain
3216 fi
3217 # Check to see if run_command logged any errors
3218 if [ -f "$ABCDETEMPDIR/errors" ]; then
3219         echo "The following commands failed to run:"
3220         cat "$ABCDETEMPDIR/errors"
3221         # Don't clean up
3222         DOCLEAN=n
3223 fi
3224 if [ "$KEEPWAVS" = "y" ];then
3225         # Don't clean up
3226         DOCLEAN=n
3227 fi
3228 if [ "$DOCLEAN" = "y" ]; then
3229         # Wipe all the evidence
3230         # Gimme gimme gimme some more time!
3231         sleep 5
3232         rm -rf "$ABCDETEMPDIR"
3233         echo "Finished."
3234 else
3235         echo "Finished. Not cleaning $ABCDETEMPDIR."
3236 fi
3237 )
3238 exit 0
3239
3240 # b:is_bash
3241 # vim:tabstop=4