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