More work on musicbrainz support
[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                 CDDBLOCALSUCCESS="n"
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 [ "$(echo "${CDDBLOCALRESULTS}" | wc -l)" = "1" ]; then
1632                                 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBLOCALRESULTS}"
1633                                 CDDBLOCALMATCH=single
1634                         elif (( $(echo "${CDDBLOCALRESULTS}" | wc -l) > 1 )); then
1635                                 CDDBLOCALMATCH=multiple
1636                         else
1637                                 CDDBLOCALMATCH=none
1638                         fi
1639                 elif [ -r "${CDDBLOCALDIR}/${CDDBDISCID}" ]; then
1640                         CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
1641                         CDDBLOCALMATCH=single
1642                 else
1643                         CDDBLOCALMATCH=none
1644                 fi
1645                 
1646                 # If the user has selected to check a local CDDB repo, we proceed with it
1647                 case $CDDBLOCALMATCH in
1648                         single)
1649                                 # List out disc title/author and contents
1650                                 do_cddbparse "${CDDBLOCALFILE}"
1651                                 echo -n "Locally cached CDDB entry found, use it? [y/n] (y): "
1652                                 if [ "$INTERACTIVE" = "y" ]; then
1653                                         read USELOCALRESP
1654                                         while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
1655                                                 echo -n 'Invalid selection. Please answer "y" or "n": '
1656                                                 read USELOCALRESP
1657                                         done
1658                                         [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
1659                                 else
1660                                         echo "y" >&2
1661                                 fi
1662                                 if [ "$USELOCALRESP" = "y" ]; then
1663                                         #echo "Using local copy of CDDB data"
1664                                         echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1"
1665                                         cat "${CDDBLOCALFILE}" >> "$ABCDETEMPDIR/cddbread.1"
1666                                         echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
1667                                         echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
1668                                         do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
1669                                         echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1670                                         CDDBLOCALSUCCESS="y"
1671                                 else
1672                                         #echo "Not using local copy of CDDB data"
1673                                         CDDBLOCALSUCCESS="n"
1674                                 fi
1675                                 ;;
1676                         none)
1677                                 CDDBLOCALSUCCESS="n"
1678                                 ;;
1679                 esac
1680         fi
1681 }
1682
1683 do_musicbrainzstat ()
1684 {
1685         :
1686 }
1687
1688 do_musizbrainz ()
1689 {
1690         :
1691 }
1692
1693 # do_cddbstat
1694 do_cddbstat ()
1695 {
1696         # Perform CDDB protocol version check if it hasn't already been done
1697         if checkstatus cddb-statcomplete; then :; else
1698                 if [ "$CDDBAVAIL" = "n" ]; then
1699                         ERRORCODE=no_query
1700                         echo 503 > "$ABCDETEMPDIR/cddbstat"
1701                 else
1702                         rc=1
1703                         CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1704                         CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1705                         while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
1706                                 vecho "Checking CDDB server status..."
1707                                 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
1708                                 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
1709                                 case "$RESPONSECODE" in
1710                                 210)    # 210 OK, status information follows (until terminating `.')
1711                                         rc=0;
1712                                         ;;
1713                                 501|*)  # 501 Illegal CDDB protocol level: <n>. 
1714                                         CDDBPROTO=`expr $CDDBPROTO - 1`
1715                                         ;;
1716                                 esac 
1717                         done
1718                         if test $rc -eq 1; then
1719                                 CDDBAVAIL="n" 
1720                         fi
1721                 fi
1722                 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
1723         fi
1724 }
1725
1726
1727 # do_cddbquery
1728 do_cddbquery ()
1729 {
1730         CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
1731         CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
1732         
1733         # Perform CDDB query if it hasn't already been done
1734         if checkstatus cddb-querycomplete; then :; else
1735                 if [ "$CDDBAVAIL" = "n" ]; then
1736                         ERRORCODE=no_query
1737                         echo 503 > "$ABCDETEMPDIR/cddbquery"
1738                 # The default CDDBLOCALSUCCESS is "n"
1739                 # This part will be triggered if the user CDDB repo does not 
1740                 # contain the entry, or if we are not trying to use the repo.
1741                 else
1742                         vecho "Querying the CDDB server..."
1743                         CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1744                         CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1745                         $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
1746                         ERRORCODE=$?
1747                         case $ERRORCODE in
1748                                 0)  # success
1749                                 ;;
1750                                 12|13|14)
1751                                         # no match found in database,
1752                                         # wget/fetch error, or user requested not to use CDDB
1753                                         # Make up an error code (503) that abcde
1754                                         # will recognize in do_cddbread
1755                                         # and compensate by making a template
1756                                         echo 503 > "$ABCDETEMPDIR/cddbquery"
1757                                 ;;
1758                                 *) # strange and unknown error
1759                                         echo ERRORCODE=$ERRORCODE
1760                                         echo "abcde: $CDDBTOOL returned unknown error code"
1761                                 ;;
1762                         esac
1763                 fi
1764                 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
1765         fi
1766 }
1767
1768 # do_cddbread
1769 do_cddbread ()
1770 {
1771         # If it's not to be used, generate a template.
1772         # Then, display it (or them) and let the user choose/edit it
1773         if checkstatus cddb-readcomplete; then :; else
1774                 vecho "Obtaining CDDB results..."
1775                 # If CDDB is to be used, interpret the query results and read all
1776                 # the available entries.
1777                 rm -f "$ABCDETEMPDIR/cddbchoices"
1778                 CDDBCHOICES=1 # Overridden by multiple matches
1779                 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
1780                 case "$RESPONSECODE" in
1781                 200)
1782                         # One exact match, retrieve it
1783                         # 200 [section] [discid] [artist] / [title]
1784                         if checkstatus cddb-read-1-complete; then :; else
1785                                 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
1786                                 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
1787                                 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
1788                                 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1789                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1790                         fi
1791                         # List out disc title/author and contents
1792                         echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
1793                         for TRACK in $(f_seq_row 1 $TRACKS)
1794                         do
1795                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1796                         done
1797                         echo >> "$ABCDETEMPDIR/cddbchoices"
1798                         ;;
1799                 202|403|409|503)
1800                         # No match
1801                         case "$RESPONSECODE" in
1802                         202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
1803                         403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
1804                         503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
1805                         esac
1806                         $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
1807                         # List out disc title/author and contents of template
1808                         echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
1809                         UNKNOWNDISK=y
1810                         for TRACK in $(f_seq_row 1 $TRACKS)
1811                         do
1812                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1813                         done
1814                         echo >> "$ABCDETEMPDIR/cddbchoices"
1815                         echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
1816                         echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
1817                         ;;
1818                 210|211)
1819                         # Multiple exact, (possibly multiple) inexact matches
1820                         IN=
1821                         if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
1822                         if [ "$(wc -l < "$ABCDETEMPDIR/cddbquery" | tr -d ' ')" -eq 3 ]; then
1823                                 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
1824                                 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
1825                                 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1826                         else
1827                                 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
1828                         fi
1829                         vecho -n "Retrieving multiple matches... "
1830                         grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
1831                         read DISCINFO # eat top line
1832                         while read DISCINFO
1833                         do
1834                                 X=$(expr $X + 1)
1835                                 if checkstatus cddb-read-$X-complete; then :; else
1836                                         $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
1837                                         echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
1838                                 fi
1839                                 # List out disc title/author and contents
1840                                 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
1841                                 for TRACK in $(f_seq_row 1 $TRACKS)
1842                                 do
1843                                         echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1844                                 done
1845                                 echo >> "$ABCDETEMPDIR/cddbchoices"
1846                         done )
1847                         vecho "done."
1848                         CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1849                         ;;
1850                 999)
1851                         # Using local copy.
1852                         for TRACK in $(f_seq_row 1 $TRACKS)
1853                         do
1854                                 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1855                         done
1856                         echo >> "$ABCDETEMPDIR/cddbchoices"
1857                         echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1858                         echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1859                         ;;
1860                 esac    
1861                 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
1862         fi
1863 }
1864
1865 # do_cddbedit
1866 do_cddbedit ()
1867 {
1868         if checkstatus cddb-edit >/dev/null; then
1869                 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1870                 VARIOUSARTISTS="$(checkstatus variousartists)"
1871                 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
1872                 return 0
1873         fi
1874         if [ "$INTERACTIVE" = "y" ]; then
1875                 # We should show the CDDB results both when we are not using the local CDDB repo
1876                 # or when we are using it but we could not find a proper match
1877                 if [ "$CDDBUSELOCAL" = "y" ] && [ ! "$CDDBLOCALSUCCESS" = "y" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1878                         # Display the $ABCDETEMPDIR/cddbchoices file created above
1879                         # Pick a pager so that if the tracks overflow the screen the user can still view everything
1880                         if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1881                                 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1882                                 CHOICE=$(checkstatus cddb-choice)
1883                                 if [ -n "$CHOICE" ] ; then
1884                                         case $CDDBCHOICES in
1885                                                 -1) if head -1 "$ABCDETEMPDIR/cddbquery" | grep -q "^$" ; then
1886                                                                 log error "CDDB query failed!" 
1887                                                                 exit 1
1888                                                         else
1889                                                                 cat "$ABCDETEMPDIR/cddbchoices"
1890                                                         fi
1891                                                         ;;
1892                                                 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1893                                                 *)
1894                                                 echo "Selected: #$CHOICE"
1895                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1896                                                 ;;
1897                                         esac
1898                                 else
1899                                         # The user has a choice to make, display the info in a pager if necessary
1900                                         if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
1901                                                 page "$ABCDETEMPDIR/cddbchoices"
1902                                         else
1903                                                 # It's all going to fit in one page, cat it
1904                                                 cat "$ABCDETEMPDIR/cddbchoices" >&2
1905                                         fi
1906                                         
1907                                         CDDBCHOICENUM=""
1908                                         # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
1909                                         CDCHOICENUM=-1
1910                                         # I'll take CDDB read #3 for $400, Alex
1911                                         while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
1912                                                 echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
1913                                                 read CDDBCHOICE
1914                                                 [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
1915                                                 if echo $CDDBCHOICE | egrep -q "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" ; then
1916                                                         if [ ! X"$DIFF" = "X" ]; then
1917                                                                 PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
1918                                                                 PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
1919                                                                 if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
1920                                                                    [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
1921                                                                    [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then 
1922                                                                         echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBCHOICES" >&2
1923                                                                 else
1924                                                                         # We parse the 2 choices to diff, store them in temporary files and diff them.
1925                                                                         for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
1926                                                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE"
1927                                                                         done
1928                                                                         echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/cddbread.diff"
1929                                                                         $DIFF $DIFFOPTS "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/cddbread.diff"
1930                                                                         if [ $(cat "$ABCDETEMPDIR/cddbread.diff" | wc -l) -ge 24 ]; then
1931                                                                                 page "$ABCDETEMPDIR/cddbread.diff"
1932                                                                         else
1933                                                                                 cat "$ABCDETEMPDIR/cddbread.diff" >&2
1934                                                                         fi
1935                                                                 fi
1936                                                         else
1937                                                                 echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2
1938                                                         fi
1939                                                 elif echo $CDDBCHOICE | egrep -q "[[:space:]]*[[:digit:]]+[[:space:]]*" ; then
1940                                                         # Make sure we get a valid choice
1941                                                         CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
1942                                                         if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then
1943                                                                 echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2
1944                                                         fi
1945                                                 fi
1946                                         done
1947                                         if [ "$CDCHOICENUM" = "0" ]; then
1948                                                 vecho "Creating empty CDDB template..."
1949                                                 UNKNOWNDISK=y
1950                                                 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
1951                                         else
1952                                                 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
1953                                                 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
1954                                         fi
1955                                         echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1956                                 fi
1957                         fi
1958                 else
1959                         # We need some code to show the selected option when local repository is selected and we have found a match
1960                         vecho "Using cached CDDB match..." >&2
1961                         # Display the $ABCDETEMPDIR/cddbchoices file created above
1962                         # Pick a pager so that if the tracks overflow the screen the user can still view everything
1963                         if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1964                                 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1965                                 CHOICE=$(checkstatus cddb-choice)
1966                                 if [ "$USELOCALRESP" = "y" ]; then :; else
1967                                         if [ -n "$CHOICE" ] ; then
1968                                                 case $CDDBCHOICES in
1969                                                         0) 
1970                                                         UNKNOWNDISK=y
1971                                                         echo "Selected template."
1972                                                         ;;
1973                                                         1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1974                                                         *)
1975                                                         echo "Selected: #$CHOICE"
1976                                                         do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1977                                                         ;;
1978                                                 esac
1979                                         fi
1980                                 fi
1981                         fi
1982                 fi
1983         else
1984                 # We're noninteractive - pick the first choice.
1985                 # But in case we run a previous instance and selected a choice, use it.
1986                 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1987                         # Show the choice if we are not using the locally stored one
1988                         # or when the local search failed to find a match.
1989                         PREVIOUSCHOICE=$(checkstatus cddb-choice)
1990                         if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSUCCESS" = "n" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1991                                 #if [ "$PREVIOUSCHOICE" ]; then
1992                                         cat "$ABCDETEMPDIR/cddbchoices"
1993                                 #fi
1994                         fi
1995                         if [ ! -z "$PREVIOUSCHOICE" ] ; then
1996                                 CDCHOICENUM=$PREVIOUSCHOICE
1997                         else
1998                                 CDCHOICENUM=1
1999                                 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2000                         fi
2001                         echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2002                 fi
2003         fi
2004
2005         # sanity check
2006         if checkstatus cddb-choice >/dev/null; then :; else
2007                 echo "abcde: internal error: cddb-choice not recorded." >&2
2008                 exit 1
2009         fi
2010         CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2011         echo -n "Edit selected CDDB data? [y/n] (" >&2
2012         if [ "$INTERACTIVE" = "y" ]; then
2013                 if [ "$UNKNOWNDISK" = "y" ]; then
2014                         echo -n "y): " >&2
2015                         read EDITCDDB
2016                         [ "$EDITCDDB" != "n" ] && EDITCDDB=y
2017                 else
2018                         echo -n "n): " >&2
2019                         read EDITCDDB
2020                 fi
2021         else
2022                 echo "n): n" >&2
2023                 EDITCDDB=n
2024         fi
2025         if [ "$EDITCDDB" = "y" ]; then
2026                 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
2027                 
2028                 # Use the debian sensible-editor wrapper to pick the editor that the
2029                 # user has requested via their $EDITOR environment variable
2030                 if [ -x "/usr/bin/sensible-editor" ]; then
2031                         /usr/bin/sensible-editor "$CDDBDATA"
2032                 elif [ -n "$EDITOR" ]; then
2033                         if [ -x $(which "${EDITOR%%\ *}") ]; then
2034                                 # That failed, try to load the preferred editor, starting
2035                                 # with their EDITOR variable
2036                                 eval $(echo "$EDITOR") \"$CDDBDATA\"
2037                         fi
2038                 # If that fails, check for a vi
2039                 elif which vi >/dev/null 2>&1; then
2040                         vi "$CDDBDATA"
2041                 elif [ -x /usr/bin/vim ]; then
2042                         /usr/bin/vim "$CDDBDATA"
2043                 elif [ -x /usr/bin/vi ]; then
2044                         /usr/bin/vi "$CDDBDATA"
2045                 elif [ -x /bin/vi ]; then
2046                         /bin/vi "$CDDBDATA"
2047                 # nano should be on all (modern, i.e., sarge) debian systems
2048                 elif which nano >/dev/null 2>&1 ; then
2049                         nano "$CDDBDATA"
2050                 elif [ -x /usr/bin/nano ]; then
2051                         /usr/bin/nano "$CDDBDATA"
2052                 # mg should be on all OpenBSD systems
2053                 elif which mg >/dev/null 2>&1 ; then
2054                         mg "$CDDBDATA"
2055                 elif [ -x /usr/bin/mg ]; then
2056                         /usr/bin/mg "$CDDBDATA"
2057                 # bomb out
2058                 else
2059                         log warning "no editor available. Check your EDITOR environment variable."
2060                 fi
2061                 # delete editor backup file if it exists
2062                 if [ -w "$CDDBDATA~" ]; then
2063                         rm -f "$CDDBDATA~"
2064                 fi
2065         fi
2066
2067         # Some heuristics first. Look at Disc Title, and if it starts with
2068         # "Various", then we'll assume Various Artists
2069         if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2- -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
2070                 echo "Looks like a Multi-Artist CD" >&2
2071                 VARIOUSARTISTS=y
2072         else
2073                 echo -n "Is the CD multi-artist? [y/n] (n): " >&2
2074                 if [ "$INTERACTIVE" = "y" ]; then
2075                         read VARIOUSARTISTS
2076                 else
2077                         echo n >&2
2078                         VARIOUSARTISTS=n
2079                 fi
2080         fi
2081         if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
2082                 # Set a default
2083                 DEFAULTSTYLE=1
2084                 # Need NUMTRACKS before cddb-tool will return it:
2085                 NUMTRACKS=$(egrep '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
2086                 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2087                         # More than 1/2 tracks contain a "/", so guess forward
2088                         DEFAULTSTYLE=1
2089                 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2090                         # More than 1/2 contain a "-", so guess forward-dash
2091                         DEFAULTSTYLE=2
2092                 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2093                         # More than 1/2 contain something in parens, so guess trailing-paren
2094                         DEFAULTSTYLE=6
2095                 fi
2096
2097                 echo "1) Artist / Title" >&2
2098                 echo "2) Artist - Title" >&2
2099                 echo "3) Title / Artist" >&2
2100                 echo "4) Title - Artist" >&2
2101                 echo "5) Artist: Title" >&2
2102                 echo "6) Title (Artist)" >&2
2103                 echo "7) This is a single-artist CD" >&2
2104                 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
2105                 if [ "$INTERACTIVE" = "y" ]; then
2106                         read VARIOUSARTISTSTYLE
2107                 else
2108                         echo $DEFAULTSTYLE >&2
2109                         VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2110                 fi
2111                 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2112                 # If they press Enter, then the default style (0) was chosen
2113                 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
2114                         echo "Invalid selection. Please choose a number between 1 and 7."
2115                         echo -n "Selection [1-7]: "
2116                         read VARIOUSARTISTSTYLE
2117                         VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2118                 done
2119                 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
2120                         VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2121                 fi
2122                 vecho "Selected: $VARIOUSARTISTSTYLE"
2123                 case "$VARIOUSARTISTSTYLE" in
2124                 1) # Artist / Title
2125                         VARIOUSARTISTSTYLE=forward
2126                         ;;
2127                 2) # Artist - Title
2128                         VARIOUSARTISTSTYLE=forward-dash
2129                         ;;
2130                 3) # Title / Artist
2131                         VARIOUSARTISTSTYLE=reverse
2132                         ;;
2133                 4) # Title - Artist
2134                         VARIOUSARTISTSTYLE=reverse-dash
2135                         ;;
2136                 5) # Artist: Title
2137                         VARIOUSARTISTSTYLE=colon
2138                         ;;
2139                 6) # Title (Artist)
2140                         VARIOUSARTISTSTYLE=trailing-paren
2141                         ;;
2142                 7) # Single Artist
2143                         VARIOUSARTISTS=n
2144                         ;;
2145                 esac
2146         fi
2147
2148         echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
2149         echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
2150
2151         if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
2152                 if [ "$CDDBDATAMD5SUM" != "" ]  && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
2153                         # This works but does not have the necessary error checking
2154                         # yet. If you are familiar with the CDDB spec
2155                         # (see http://www.freedb.org/src/latest/DBFORMAT) 
2156                         # and can create an error-free entry on your own, then put
2157                         # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
2158                         # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
2159                         # your abcde.conf to change the email address submissions are
2160                         # sent to.
2161
2162                         # submit the modified file, if they want
2163                         if [ "$NOSUBMIT" != "y" ]; then
2164                                 echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
2165                                 read YESNO
2166                                 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
2167                                         [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
2168                                 do
2169                                         echo -n 'Invalid selection. Please answer "y" or "n": '
2170                                         read YESNO
2171                                 done
2172                                 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
2173                                         echo -n "Sending..."
2174                                         $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
2175                                         echo "done."
2176                                 fi
2177                         fi
2178                 fi
2179         fi
2180         # Make sure the cache directory exists
2181         mkdir -p $CDDBLOCALDIR
2182         # Cache edited CDDB entry in the user's cddb dir
2183         if [ "$CDDBCOPYLOCAL" = "y" ] || [ "$COPYCDDBLOCAL" = "Y" ]; then
2184                 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
2185         fi
2186
2187         echo "cddb-edit" >> "$ABCDETEMPDIR/status"
2188 }
2189
2190 # do_cdread [tracknumber]
2191 # do_cdread onetrack [firsttrack] [lasttrack]
2192
2193 do_cdread ()
2194 {
2195         # The commands here don't go through run_command because they're never supposed to be silenced
2196         # return codes need to be doublechecked anyway, however
2197         if [ "$1" = "onetrack" ]; then
2198                 # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
2199                 # FIXME # Until then, we grab the whole CD in one track, no matter what
2200                 # the user said
2201                 # We need the first and last track for cdda2wav
2202                 FIRSTTRACK=$2
2203                 LASTTRACK=$3
2204                 UTRACKNUM=$FIRSTTRACK
2205                 case "$CDROMREADERSYNTAX" in
2206                         flac) READTRACKNUMS="$FIRSTTRACK.1-$(($LASTTRACK + 1)).0" ;;
2207                         cdparanoia) READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
2208                         cdda2wav) READTRACKNUMS="$FIRSTTRACK+$LASTRACK" ;;
2209                         *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
2210                                 exit 1 ;;
2211                 esac
2212         else
2213                 UTRACKNUM=$1
2214         fi
2215         CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2216         if [ "$USEPIPES" = "y" ]; then
2217                 TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
2218                 FILEARG="$( eval echo "\$$TEMPARG" )"
2219                 REDIR=""
2220                 PIPE_MESSAGE="and encoding "
2221         else
2222                 WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
2223                 case "$CDROMREADERSYNTAX" in
2224                 ## FIXME ## Find the cases for dagrab and flac, to avoid exceptions
2225                         flac)
2226                                 FILEARG="--output-name=$WAVDATA"
2227                                 ;;
2228                         dagrab)
2229                                 FILEARG="-f $WAVDATA"
2230                                 ;;
2231                         *)
2232                                 FILEARG="$WAVDATA"
2233                                 ;;
2234                 esac
2235                 REDIR=">&2"
2236         fi
2237         if [ "$1" = "onetrack" ]; then
2238                 echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
2239         else
2240                 if [ -r "$CDDBDATA" ]; then
2241                         do_getcddbinfo TRACKNAME
2242                         echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
2243                 else
2244                         echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
2245                 fi
2246         fi
2247         case "$CDROMREADERSYNTAX" in
2248                 ### FIXME ### use an exception for flac, since it uses -o
2249                 ### FIXME ### Shall we just use -o $FILEARG ??
2250                 flac)
2251                         nice $READNICE $FLAC -d --cue=${READTRACKNUMS:-$UTRACKNUM.1-$(($UTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;;
2252                 cdparanoia) 
2253                         echo "nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;" > /tmp/log
2254                         nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;
2255                 cdda2wav)
2256                         if [ "$OSFLAVOUR" = "OSX" ] ; then
2257                                 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
2258                                 disktool -u ${CDROM#/dev/} 0
2259                                 # Also, in OSX the cdrom device for cdda2wav changes...
2260                                 CDDA2WAVCDROM="IODVDServices"
2261                         elif [ "$OSFLAVOUR" = "FBSD" ] ; then
2262                                 CDDA2WAVCDROM="$CDROMID"
2263                         else
2264                                 if [ "$CDROMID" = "" ]; then
2265                                         CDDA2WAVCDROM="$CDROM"
2266                                 else
2267                                         CDDA2WAVCDROM="$CDROMID"
2268                                 fi
2269                         fi
2270                         nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR
2271                         ;;
2272                 ## FIXME ## We have an exception for dagrab, since it uses -f
2273                 ## FIXME ## Shall we just use -f $FILEARG ??
2274                 dagrab) nice $READNICE $CDROMREADER -d $CDROM -v $UTRACKNUM "$FILEARG" $REDIR
2275                         ;;
2276                 cddafs)
2277                         # Find the track's mounted path
2278                         REALTRACKNUM=$(expr $UTRACKNUM + 0)
2279                         FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
2280                         FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
2281                         # If the file exists, copy it
2282                         if [ -e "$FILEPATH" ] ; then
2283                                 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" $REDIR
2284                         else
2285                                 false
2286                         fi ;;
2287                 debug) nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM -w $UTRACKNUM-[:1] "$FILEARG" $REDIR
2288                         ;;
2289         esac
2290         RETURN=$?
2291         # If we get some error or we get some missing wav 
2292         # (as long as we dont use pipes)
2293         if [ "$RETURN" != "0" -o \( ! -s "$WAVDATA" -a X"$USEPIPES" != "Xy" \) ]; then
2294                 # Thank goodness errors is only machine-parseable up to the
2295                 # first colon, otherwise this woulda sucked
2296                 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
2297                         RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
2298                 fi
2299                 if [ "$USEPIPES" = "y" ]; then
2300                         echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2301                 else
2302                         echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2303                 fi
2304                 return $RETURN
2305         else
2306                 if [ "$USEPIPES" = "y" ]; then
2307                         echo readencodetrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2308                 else
2309                         echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2310                         if [ "$1" = "onetrack" ]; then
2311                                 echo onetrack >> "$ABCDETEMPDIR/status"
2312                         fi
2313                 fi
2314         fi
2315 }
2316
2317 # do_cdspeed
2318 # No values accepted, only uses env variables
2319 do_cdspeed () 
2320 {
2321         if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
2322                 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
2323         else
2324                 echo "abcde: unable to set the device speed" >&2
2325         fi
2326 }
2327
2328 # vecho [message]
2329 #
2330 # vecho outputs a message if EXTRAVERBOSE is selected
2331 vecho ()
2332 {
2333 if [ x"$EXTRAVERBOSE" != "x" ]; then
2334         case $1 in
2335                 warning) log warning "$@" ;;
2336                 *) echo "$@" ;;
2337         esac
2338 fi
2339 }
2340
2341 # decho [message]
2342 #
2343 # decho outputs a debug message if DEBUG is selected
2344 decho ()
2345 {
2346 if [ x"$DEBUG" != "x" ]; then
2347         if echo $1 | grep -q "^\[" ; then
2348                 DEBUGECHO=$(echo "$@" | tr -d '[]')
2349                 echo "[DEBUG] $DEBUGECHO: `eval echo \\$${DEBUGECHO}`"
2350         else
2351                 echo "[DEBUG] $1"
2352         fi
2353 fi
2354 }
2355
2356 # User-redefinable functions
2357 # Custom filename munging:
2358 mungefilename ()
2359 {
2360         #echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
2361         echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
2362 }
2363
2364 # Custom genre munging:
2365 mungegenre ()
2366 {
2367         echo $CDGENRE | tr "[:upper:]" "[:lower:]"
2368 }
2369
2370 # pre_read
2371 # Empty pre_read function, to be defined in the configuration file.
2372 pre_read ()
2373 {
2374 :
2375 }
2376
2377 # post_read
2378 # Empty post_read function, to be defined in the configuration file.
2379 post_read ()
2380 {
2381 :
2382 }
2383
2384 ###############################################################################
2385 # End of functions
2386 #
2387 # Start of execution
2388 ###############################################################################
2389
2390 # Builtin defaults
2391
2392 # CDDB
2393 # Defaults to FreeDB, but a python musicbrainz can be used
2394 CDDBMETHOD=cddb
2395 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
2396 CDDBSUBMIT=freedb-submit@freedb.org
2397 CDDBPROTO=5
2398 HELLOINFO="$(whoami)@$(hostname)"
2399 CDDBCOPYLOCAL="n"
2400 CDDBLOCALDIR="$HOME/.cddb"
2401 CDDBUSELOCAL="n"
2402
2403 # List of fields we parse and show during the CDDB parsing...
2404 SHOWCDDBFIELDS="year,genre"
2405
2406 INTERACTIVE=y
2407 #CDROMREADERSYNTAX=cdparanoia
2408 ENCODERSYNTAX=default
2409
2410 MP3ENCODERSYNTAX=default
2411 OGGENCODERSYNTAX=default
2412 FLACENCODERSYNTAX=default
2413 SPEEXENCODERSYNTAX=default
2414 MPPENCODERSYNTAX=default
2415 AACENCODERSYNTAX=default
2416 NORMALIZERSYNTAX=default
2417 CUEREADERSYNTAX=default
2418
2419 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
2420 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
2421 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
2422 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
2423 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
2424 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
2425 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2426 PLAYLISTDATAPREFIX=''
2427 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2428 VAPLAYLISTDATAPREFIX=''
2429 DOSPLAYLIST=n
2430 COMMENT=''
2431 ID3TAGV=2
2432 ENCNICE=10
2433 READNICE=10
2434 DISTMP3NICE=10
2435 VARIOUSARTISTS=n
2436 VARIOUSARTISTSTYLE=forward
2437 KEEPWAVS=n
2438 PADTRACKS=n
2439 NOGAP=n
2440 BATCHNORM=n
2441
2442 # If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
2443 # i.e. CDROMID="1,0,0"
2444 CDROMID=""
2445 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
2446 # If we are using the ide-scsi emulation layer, we need to define a "g"
2447 CDPARANOIACDROMBUS="d"
2448
2449 # program paths - defaults to checking your $PATH
2450 # mp3
2451 LAME=lame
2452 TOOLAME=toolame
2453 GOGO=gogo
2454 BLADEENC=bladeenc
2455 L3ENC=l3enc
2456 XINGMP3ENC=xingmp3enc
2457 MP3ENC=mp3enc
2458 # ogg
2459 VORBIZE=vorbize
2460 OGGENC=oggenc
2461 # flac
2462 FLAC=flac
2463 # speex
2464 SPEEXENC=speexenc
2465 # mpp (Musepack)
2466 MPPENC=mppenc
2467 # m4a
2468 AACENC=faac
2469
2470 ID3=id3
2471 ID3V2=id3v2
2472 EYED3=eyeD3
2473 CDPARANOIA=cdparanoia
2474 CDDA2WAV=cdda2wav
2475 DAGRAB=dagrab
2476 CDDAFS=cp
2477 CDDISCID=cd-discid
2478 CDDBTOOL=cddb-tool
2479 MUSICBRAINZ=musicbrainz-get-tracks
2480 EJECT=eject
2481 MD5SUM=md5sum
2482 DISTMP3=distmp3
2483 VORBISCOMMENT=vorbiscomment
2484 METAFLAC=metaflac
2485 NORMALIZE=normalize-audio
2486 CDSPEED=eject
2487 VORBISGAIN=vorbisgain
2488 MP3GAIN=mp3gain
2489 MPPGAIN=replaygain
2490 MKCUE=mkcue
2491 MKTOC=cdrdao
2492 DIFF=diff
2493 CUE2DISCID=cue2discid
2494
2495 # Options for programs called from abcde
2496 # mp3
2497 LAMEOPTS=
2498 TOOLAMEOPTS=
2499 GOGOOPTS=
2500 BLADEENCOPTS=
2501 L3ENCOPTS=
2502 XINGMP3ENCOPTS=
2503 MP3ENCOPTS=
2504 # ogg
2505 VORBIZEOPTS=
2506 OGGENCOPTS=
2507 # flac
2508 FLACOPTS=
2509 # speex
2510 SPEEXENCOPTS=
2511 # mpc
2512 MPPENCOPTS=
2513 # m4a
2514 AACENCOPTS=
2515
2516 ID3OPTS=
2517 ID3V2OPTS=
2518 CDPARANOIAOPTS=
2519 CDDA2WAVOPTS=
2520 DAGRABOPTS=
2521 CDDAFSOPTS="-f"
2522 CDDBTOOLOPTS=
2523 EJECTOPTS=
2524 DISTMP3OPTS=
2525 NORMALIZEOPTS=
2526 CDSPEEDOPTS="-x"
2527 CDSPEEDVALUE=
2528 MKCUEOPTS=
2529 MKTOCOPTS=""
2530 VORBISCOMMENTOPTS="-R"
2531 METAFLACOPTS="--no-utf8-convert"
2532 DIFFOPTS=
2533
2534 # Default to one process if -j isn't specified
2535 MAXPROCS=1
2536
2537 # List of actions to perform - by default, run to completion
2538 ACTIONS=cddb,read,encode,tag,move,clean
2539
2540 # This option is basicaly for Debian package dependencies: 
2541 # List of prefered outputs - by default, run with whatever we have in the path
2542 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:lame,mp3:bladeenc,spx:speex
2543
2544 # List of prefered cdromreaders - by default, run whichever we have in the path
2545 DEFAULT_CDROMREADERS="cdparanoia cdda2wav"
2546
2547 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for Linux/OpenBSD/NetBSD.
2548 # Let's use these checkings to determine the OS flavour, which will be used later
2549 if [ X$(uname) = "XFreeBSD" ] ; then
2550         HTTPGET=fetch
2551         MD5SUM=md5
2552         NEEDCDROMID=y
2553         OSFLAVOUR=FBSD
2554 elif [ X$(uname) = "XDarwin" ] ; then
2555         HTTPGET=curl
2556         OSFLAVOUR=OSX
2557         # We should have disktool in OSX, but let's be sure...
2558         NEEDDISKTOOL=y
2559         CDROMREADERSYNTAX=cddafs
2560 elif [ X$(uname) = "XOpenBSD" ] ; then
2561         HTTPGET=wget
2562         MD5SUM=md5
2563 elif [ X$(uname) = "XNetBSD" ] ; then
2564         HTTPGET=ftp
2565         MD5SUM=md5
2566 else
2567         HTTPGET=wget
2568 fi
2569
2570 # If CDDBAVAIL is set to n, no CDDB read is done
2571 # If USEID3 is set to n, no ID3 tagging is done
2572 CDDBAVAIL=y
2573 USEID3=y
2574 USEID3V2=y
2575
2576 if [ -z "$OUTPUTDIR" ]; then
2577         OUTPUTDIR=$(pwd)
2578 fi
2579
2580 if [ -z "$WAVOUTPUTDIR" ]; then
2581         WAVOUTPUTDIR="$OUTPUTDIR"
2582 fi
2583
2584 # Load system defaults
2585 if [ -r /etc/abcde.conf ]; then
2586         . /etc/abcde.conf
2587 fi
2588 # Load user preference defaults
2589 if [ -r $HOME/.abcde.conf ]; then
2590         . $HOME/.abcde.conf
2591 fi
2592
2593 # By this time, we need some HTTPGETOPTS already defined.
2594 # If the user has defined a non-default HTTPGET method, we should not be empty.
2595
2596 if [ "$HTTPGETOPTS" = "" ] ; then
2597         case $HTTPGET in
2598                 wget) HTTPGETOPTS="-q -O -";;
2599                 curl) HTTPGETOPTS="-f -s";;
2600                 fetch)HTTPGETOPTS="-q -o -";;
2601                 ftp)  HTTPGETOPTS="-q -o -";;
2602                 *) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
2603         esac
2604 fi
2605
2606 # If the CDROM has not been set yet, find a suitable one.
2607 # If this is a devfs system, default to /dev/cdroms/cdrom0
2608 # instead of /dev/cdrom
2609 if [ "$CDROM" = "" ] ; then
2610         if [ -e /dev/cdroms/cdrom0 ]; then
2611                 CDROM=/dev/cdroms/cdrom0
2612         elif [ -e /dev/cdrom ]; then
2613                 CDROM=/dev/cdrom
2614         elif [ -e /dev/cd0c ]; then
2615                 CDROM=/dev/cd0c
2616         elif [ -e /dev/acd0c ]; then
2617                 CDROM=/dev/acd0c
2618         elif [ -e /dev/disk1 ]; then
2619                 CDROM=/dev/disk1
2620         fi
2621 fi
2622
2623 # Parse command line options
2624 #while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPr:Rs:S:t:T:vVxw:W: opt ; do
2625 while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPr:s:S:t:T:uvVxw:W:z opt ; do
2626         case "$opt" in
2627                 1) ONETRACK=y ;;
2628                 a) ACTIONS="$OPTARG" ;;
2629                 A) EXPACTIONS="$OPTARG" ;;
2630                 b) BATCHNORM=y ;;
2631                 B) NOBATCHREPLAYGAIN=y ;;
2632                 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
2633                 C) DISCID="$( echo ${OPTARG#abcde.} | tr -d /)" ;;
2634                 d) CDROM="$OPTARG" ;;
2635                 D) set -x ;;
2636                 e) ERASEENCODEDSTATUS=y ;;
2637                 h) usage; exit ;;
2638                 e) ERASEENCODEDSTATUS=y ;;
2639                 E) ENCODING="$OPTARG" ;;
2640                 f) FORCE=y ;;
2641                 g) NOGAP=y ;;
2642                 i) INLINETAG=y ;;
2643                 j) MAXPROCS="$OPTARG" ;;
2644                 k) KEEPWAVS=y ;;
2645                 l) LOWDISK=y ;;
2646                 L) CDDBUSELOCAL=y ;;
2647                 n) CDDBAVAIL=n ;;
2648                 N) INTERACTIVE=n ;;
2649                 m) DOSPLAYLIST=y ;;
2650                 M) MAKECUEFILE=y ;;
2651                 o) OUTPUTTYPE="$OPTARG" ;;
2652                 p) PADTRACKS=y ;;
2653                 P) USEPIPES=y ;;
2654                 r) REMOTEHOSTS="$OPTARG" ;;
2655                 R) DOREPLAYGAIN=y ;;
2656                 s) SHOWCDDBFIELDS="$OPTARG" ;;
2657                 S) CDSPEEDVALUE="$OPTARG" ;;
2658                 t) STARTTRACKNUMBER="$OPTARG" ;;
2659                 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
2660                 u) CDDBPROTO=6 ;;
2661                 v) 
2662                    echo "This is abcde v$VERSION."
2663                    echo "Usage: abcde [options] [tracks]"
2664                    echo "abcde -h for extra help"
2665                    exit
2666                    ;;
2667                 V) EXTRAVERBOSE="y" ;;
2668                 x) EJECTCD="y" ;;
2669                 w) COMMENT="$OPTARG" ;;
2670                 W) if echo $OPTARG | grep -q "[[:digit:]]" ; then 
2671                      STARTTRACKNUMBER="${OPTARG}01" ; STARTTRACKNUMBERTAG="y" ; COMMENT="CD${OPTARG}"
2672                    else
2673                      log error "argument of -W must be integer"
2674                          exit 1
2675                    fi
2676                    ;;
2677                 z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
2678                 ?) usage; exit ;;
2679         esac
2680 done
2681
2682 shift $(($OPTIND - 1))
2683
2684 # If the user specified a flac file, then switch to special flac mode
2685 if echo $CDROM | grep -i -q '.flac$'; then
2686         vecho "abcde: switching to flac CDROMREADERSYNTAX..."
2687         CDROMREADERSYNTAX=flac
2688         if [ "$EJECTCD" = "y" ];then
2689                 vecho "abcde: CDROM flac mode, deactivating EJECTCD..."
2690                 EJECTCD=n
2691         fi
2692 fi
2693
2694 # If the user provided a DISCID, disable eject
2695 if [ -n "$DISCID" ]; then EJECTCD=n ; fi
2696
2697 # Check the available cd rippers in the system, from the ones we know.
2698 if [ "$CDROMREADERSYNTAX" = "" ]; then
2699         for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
2700                 if [ -x $( which $DEFAULT_CDROMREADER ) ]; then
2701                         CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
2702                         break
2703                 fi
2704         done
2705         if [ "$CDROMREADERSYNTAX" = "" ]; then
2706                 log error "no cdreader found in your PATH"
2707                 log error "hints: are all dependencies installed? has the \$PATH been modified?"
2708                 exit 1
2709         fi
2710 fi
2711
2712 # Decide if we can continue.
2713 if [ "$ONETRACK" = "y" ]; then 
2714         # FIXME # remove check as soon as we find out about the other readers
2715         case "$CDROMREADERSYNTAX" in
2716                 flac) ;;
2717                 cdparanoia) ;;
2718                 cdda2wav) ;;
2719                 *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
2720                    exit 1 ;;
2721         esac
2722         if [ "$BATCHNORM" = "y" ]; then
2723                 log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
2724                 BATCHNORM=n
2725         fi
2726         if [ "$NOGAP" = "y" ]; then
2727                 log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
2728                 NOGAP=n
2729         fi
2730         # It does not matter how many tracks we want. In ONETRACK mode we grab them all
2731         # FIXME # allow ranges of tracks to be selected for onetrack ripping
2732         if [ $# -gt 0 ]; then
2733                 log warning "ONETRACK mode selected, grabbing all tracks..."
2734         fi
2735 else
2736         while [ $# -gt 0 ]; do
2737                 # Range parsing code courtesy of Vincent Ho
2738                 RSTART=$(echo $1 | cut -f1 -d-)
2739                 REND=$(echo $1 | cut -f2 -d-)
2740                 if [ "$RSTART" = "$REND" ]; then
2741                         NEWTRACKS="$RSTART"
2742                 else
2743                         NEWTRACKS=$(f_seq_line $RSTART $REND)
2744                 fi
2745                 TRACKQUEUE=$(echo "$TRACKQUEUE" "$NEWTRACKS")
2746                 shift
2747         done
2748 fi
2749
2750 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
2751 # List of experimental actions: retag,transcode
2752
2753 # Determine what actions are to be done from $ACTIONS and set the
2754 # following environment variables for them:
2755 DOCDDB=n
2756 DOREAD=n
2757 DONORMALIZE=n
2758 DOPREPROCESS=n
2759 DOENCODE=n
2760 DOPOSTPROCESS=n
2761 DOTAG=n
2762 DOMOVE=n
2763 DOREPLAYGAIN=n
2764 DOPLAYLIST=n
2765 DOCLEAN=n
2766
2767 for ACTION in $(echo $ACTIONS | tr , \ )
2768 do
2769         case $ACTION in
2770                 cddb) DOCDDB=y;;
2771                 read) DOREAD=y;;
2772                 normalize) DONORMALIZE=y; DOREAD=y;;
2773 #               preprocess) DOPREPROCESS=y; DOREAD=y;;
2774                 encode) DOENCODE=y; DOREAD=y;;
2775 #               postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
2776                 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
2777                 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
2778                 replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
2779                 playlist) DOCDDB=y; DOPLAYLIST=y;;
2780                 clean) DOCLEAN=y;;
2781         esac
2782 done
2783
2784 if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
2785         # FIXME # should we abort on error or just inform the user?
2786         log warning "selected both normalize and replaygain actions"
2787 fi
2788
2789 for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
2790         case $SHOWCDDBFIELD in
2791                 y*|Y*) SHOWCDDBYEAR="y";;
2792                 g*|G*) SHOWCDDBGENRE="y";;
2793                 *) ;;
2794         esac
2795 done
2796
2797 # Sanity checks:
2798
2799 # At this point a CDROM has to be defined, so we check it exists.
2800 if [ X"$CDROM" != "X" ] ; then 
2801         if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
2802                 if [ "$OSFLAVOUR" = "FBSD" ]; then
2803                         if ! echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then
2804                                 log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
2805                                 log error "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
2806                                 exit 1
2807                         fi
2808                 fi
2809         elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
2810                 log error "CDROM device cannot be found."
2811                 exit 1
2812         fi
2813 # avoid processing if we are not going to hit the CDROM.
2814 elif [ X"$DOREAD" = "Xy" ]; then
2815         log error "CDROM has not been defined or cannot be found"
2816         exit 1
2817 fi
2818
2819 # USEPIPES pre-tests, before we get into more serious stuff
2820 # Not compatible with:
2821 # - multiple outputs
2822 # - normalize
2823 # - lowdisk algorithm
2824 # - anything else?
2825 if [ X"$USEPIPES" = "Xy" ]; then
2826         if [ $(echo "$OUTPUTTYPE" | tr , \  | wc -w ) -gt 1 ]; then
2827                 log error "Unix pipes not compatible with multiple outputs"
2828                 exit 1
2829         fi
2830         if [ X"$DONORMALIZE" = "Xy" ]; then
2831                 log error "Unix pipes not compatible with normalizer"
2832                 # FIXME # Do we need to exit or shall we just disable the mode?
2833                 exit 1
2834         fi
2835         if [ X"$BATCHNORM" = "Xy" ]; then
2836                 log error "Unix pipes not compatible with BATCHNORM encoding"
2837                 exit 1
2838         fi
2839         if [ X"$NOGAP" = "Xy" ]; then
2840                 log error "Unix pipes not compatible with NOGAP encoding"
2841                 exit 1
2842         fi
2843         if [ X"$DOENCODE" = "Xn" ]; then
2844                 vecho warning "Disabling Unix pipes since we are not encoding!"
2845                 USEPIPES=n
2846         fi
2847         if [ X"$LOWDISK" = "Xy" ]; then
2848                 log error "Unix pipes not compatible with lowdisk algorithm"
2849                 exit 1
2850         fi
2851 fi
2852
2853 # LOWDISK pre-tests, before we get into more problematic stuff
2854 # Not compatible with anything that needs all the files in the hard disc:
2855 # - BATCHNORM
2856 # - NOGAP lame mode
2857 if [ X"$LOWDISK" = "Xy" ]; then
2858         if [ X"$BATCHNORM" = "Xy" ]; then
2859                 log error "Unix pipes not compatible with BATCHNORM encoding"
2860                 exit 1
2861         fi
2862         if [ X"$NOGAP" = "Xy" ]; then
2863                 log error "Unix pipes not compatible with NOGAP encoding"
2864                 exit 1
2865         fi
2866 fi
2867
2868 # BATCHNORM pre-tests, before we get into serious problems
2869 # Not compatible with 
2870 if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
2871         vecho warning "Disabling BATCHNORM since we are not normalizing!"
2872         BATCHNORM=n
2873 fi
2874
2875 # Check the encoding format from the ones available in the system, if nothing has been configured in the system.
2876 if [ X"$OUTPUTTYPE" = "X" ]; then
2877         for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
2878                 DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
2879                 DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
2880                 if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
2881                         OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
2882                         vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
2883                         break
2884                 fi
2885         done
2886         if [ X"$OUTPUTTYPE" = "X" ]; then
2887                 log error "no encoder found in the PATH"
2888                 log error "hints: are all dependencies installed? has the \$PATH been modified?"
2889                 exit 1
2890         fi
2891 fi
2892
2893 # Decide which CDROM reader we're gonna use
2894 case "$CDROMREADERSYNTAX" in
2895         cdparanoia|debug)
2896                 CDROMREADER="$CDPARANOIA"
2897                 CDROMREADEROPTS="$CDPARANOIAOPTS"
2898                 ;;
2899         cdda2wav)
2900                 CDROMREADER="$CDDA2WAV"
2901                 CDROMREADEROPTS="$CDDA2WAVOPTS"
2902                 ;;
2903         dagrab)
2904                 CDROMREADER="$DAGRAB"
2905                 CDROMREADEROPTS="$DAGRABOPTS"
2906                 ;;
2907         cddafs)
2908                 CDROMREADER="$CDDAFS"
2909                 CDROMREADEROPTS="$CDDAFSOPTS"
2910                 ;;
2911         flac)
2912                 CDROMREADER="$FLAC"
2913                 CDROMREADEROPTS="$FLACOPTS"
2914                 ;;
2915 esac
2916
2917 # There's only one normalize...
2918 case "$NORMALIZERSYNTAX" in
2919         default|normalize)
2920                 NORMALIZER="$NORMALIZE"
2921                 NORMALIZEROPTS="$NORMALIZEOPTS"
2922                 ;;
2923 esac
2924
2925 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
2926 if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
2927         for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
2928                 case "$OUTPUT" in
2929                         vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2930                         mp3:*)  MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2931                         flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2932                         spx:*)  SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2933                         mpc:*)  MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2934                         m4a:*)  AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2935                 esac
2936         done
2937         for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
2938                 TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
2939                 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
2940         done
2941         OUTPUTTYPE="$TEMPOUTPUTTYPE"
2942 fi
2943
2944 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
2945 # for flacs and speexenc for speex and mppenc for mpps and faac for m4as
2946
2947 # Getting ready for multiple output changes
2948 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
2949 do
2950         case $OUTPUT in
2951                 vorbis|ogg)
2952                         [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
2953                         [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
2954                         [ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
2955                         OGGOUTPUTCONTAINER=ogg
2956                         ;;
2957                 mp3)
2958                         [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
2959                         [ "$DOTAG" = "y" ] && NEEDTAGGER=y
2960                         [ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
2961                         ;;
2962                 flac)
2963                         [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
2964                         [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
2965                         [ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
2966                         ;;
2967                 spx)
2968                         [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
2969 #                       [ "$DOREPLAYGAIN" = "y" ] &&
2970                         ;;
2971                 mpc)
2972                         [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc
2973                         [ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y
2974                         ;;
2975                 m4a)
2976                         [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
2977                         ;;
2978                 wav)
2979                         if [ "$KEEPWAVS" = "y" ]; then
2980                                 vecho "Unsetting the KEEPWAVS option, since the resulting wav files were requested..."
2981                         fi
2982                         KEEPWAVS=move
2983                         ;;
2984                 *)      log error "Invalid OUTPUTTYPE defined"
2985                         exit 1
2986                         ;;
2987         esac
2988 done
2989
2990 # decide which encoder
2991 case "$MP3ENCODERSYNTAX" in
2992         lame)
2993                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
2994                 MP3ENCODER="$LAME"
2995                 ;;
2996         toolame)
2997                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$TOOLAMEOPTS}"
2998                 MP3ENCODER="$TOOLAME"
2999                 ;;
3000         gogo)
3001                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
3002                 MP3ENCODER="$GOGO"
3003                 ;;
3004         bladeenc)
3005                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
3006                 MP3ENCODER="$BLADEENC"
3007                 ;;
3008         l3enc)
3009                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
3010                 MP3ENCODER="$L3ENC"
3011                 ;;
3012         xingmp3enc)
3013                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
3014                 MP3ENCODER="$XINGMP3ENC"
3015                 ;;
3016         mp3enc)
3017                 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
3018                 MP3ENCODER="$MP3ENC"
3019                 ;;
3020 esac
3021 case "$OGGENCODERSYNTAX" in
3022         vorbize)
3023                 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
3024                 OGGENCODER="$VORBIZE"
3025                 ;;
3026         oggenc)
3027                 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
3028                 OGGENCODER="$OGGENC"
3029                 ;;
3030 esac
3031 case "$FLACENCODERSYNTAX" in
3032         flac)
3033                 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
3034                 FLACENCODER="$FLAC"     
3035                 # FLAC streams can be encapsulated on a Ogg transport layer
3036                 if echo "$FLACENCODEROPTS" | egrep -q -- "(^| )--ogg($| )" ;then
3037                         log error "FLAC on an Ogg container is not yet supported"
3038                         log error "due to problem with adding comments to such files"
3039                         exit 1
3040                         FLACOUTPUTCONTAINER=ogg
3041                 else
3042                         FLACOUTPUTCONTAINER=flac
3043                 fi
3044                 ;;
3045 esac
3046 case "$SPEEXENCODERSYNTAX" in
3047         speexenc)
3048                 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
3049                 SPEEXENCODER="$SPEEXENC"
3050                 ;;
3051 esac
3052 case "$MPPENCODERSYNTAX" in
3053         mppenc)
3054                 MPPENCODEROPTS="${MPPENCODEROPTSCLI:-$MPPENCOPTS}"
3055                 MPPENCODER="$MPPENC"
3056                 ;;
3057 esac
3058 case "$AACENCODERSYNTAX" in
3059         faac)
3060                 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
3061                 AACENCODER="$AACENC"
3062                 ;;
3063 esac
3064 # and which tagger
3065
3066 if [ "$ID3TAGV" = "1" ]; then
3067         TAGGER="$ID3"
3068         TAGGEROPTS="$ID3OPTS"
3069 else
3070         TAGGER="$ID3V2"
3071         TAGGEROPTS="$ID3V2OPTS"
3072 fi
3073
3074 # Specific for NOGAP is the use of lame. Another encoder fails...
3075 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
3076         log warning "the NOGAP option is specific of lame. Deactivating..."
3077         NOGAP=n
3078 fi
3079
3080 # Options for mkcue
3081 case "$CUEREADERSYNTAX" in
3082         default|mkcue)
3083                 CUEREADEROPTS="${CDROM}"
3084                 CUEREADER="$MKCUE"
3085                 ;;
3086 esac
3087
3088 # which information retrieval tool are we using?
3089 case "$CDDBTOOL" in
3090         cddb) ;;
3091         musicbrainz) ;;
3092 esac
3093
3094 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
3095 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
3096         log error "FLAC on an Ogg container is not yet supported"
3097         log error "due to problem with adding comments to such files"
3098         exit 1
3099         OGGOUTPUTCONTAINER=ogg.ogg
3100         FLACOUTPUTCONTAINER=flac.ogg
3101         vecho warning "modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
3102 fi
3103
3104 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
3105
3106 if [ "$ENCNICE" ]; then
3107         ENCNICE="-n $ENCNICE"
3108 fi
3109 if [ "$READNICE" ]; then
3110         READNICE="-n $READNICE"
3111 fi
3112 if [ "$DISTMP3NICE" ]; then
3113         DISTMP3NICE="-n $DISTMP3NICE"
3114 fi
3115
3116 # Don't check for stuff if it's not needed
3117 if [ "$REMOTEHOSTS" ]; then 
3118         NEEDDISTMP3=y
3119 fi
3120 if [ "$DONORMALIZE" = "y" ]; then
3121         NEEDNORMALIZER=y
3122 fi
3123 if [ "$EJECTCD" = "y" ]; then
3124         NEEDEJECT=y
3125 fi
3126 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
3127         if [ "$CDDBMETHOD" = "cddb" ]; then
3128                 NEEDHTTPGET=y
3129         elif [ "$CDDBMETHOD" = "musicbrainz" ]; then
3130                 :
3131         fi
3132 fi
3133 if [ "$MAKECUEFILE" = "y" ]; then
3134         NEEDCUEREADER=y
3135 fi
3136
3137 if [ X"$CDSPEEDVALUE" != "X" ]; then
3138         case "$CDROMREADERSYNTAX" in
3139                 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
3140                 ### FIXME ### translate "cue2discid" from python to bash
3141                 flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ;;
3142                 *) NEEDCDSPEED=y ;;
3143         esac
3144 fi
3145
3146 ###USEPIPESSUPPORT###
3147
3148 # Rippers with USEPIPE support
3149 # FIXME # Include here all the rippers we can figure out support pipes
3150 PIPERIPPER_cdparanoia="-"
3151 PIPERIPPER_debug="-"
3152 PIPERIPPER_flac="-c "
3153
3154 # Encoders with USEPIPE support
3155 # FIXME # Include here all the encoders we can figure out support pipes
3156 PIPE_lame="-"
3157 PIPE_bladeenc="-"
3158 PIPE_oggenc="-"
3159 PIPE_flac="-"
3160
3161 # Figure out if we can use pipes with the ripper/encoder combination
3162 # exit otherwise
3163 if [ "$USEPIPES" = "y" ]; then
3164         PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
3165         case "$OUTPUT" in
3166                 mp3)
3167                         PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
3168                 vorbis|ogg)
3169                         PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
3170                 flac)
3171                         PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
3172                 spx)
3173                         PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
3174                 mpc)
3175                         PIPEENCODERSVARCHECK="PIPE_$MPPENCODER" ;;
3176         esac
3177         decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
3178         if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
3179            [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
3180                 log error "no support for pipes with given ripper"
3181                 log error "read the USEPIPES file from the source tarball to get help."
3182                 log error "On a Debian system, it is under /usr/share/doc/abcde/USEPIPES.gz"
3183                 exit 1;
3184         fi
3185         decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
3186         if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
3187            [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
3188                 log error "no support for pipes with given encoder"
3189                 log error "read the USEPIPES file from the source tarball to help"
3190                 log error "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz"
3191                 exit 1;
3192         fi
3193 fi
3194
3195 # Make sure a buncha things exist
3196 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
3197         $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
3198         ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
3199         ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
3200         ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
3201         ${NEEDDISKTOOL+disktool} ${NEEDCDSPEED+$CDSPEED} \
3202         ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
3203         ${NEEDMPPGAIN+$MPPGAIN} \
3204         ${NEEDCUEREADER+$CUEREADER} ${NEEDCUE2DISCID+$CUE2DISCID}
3205 do
3206         # Cut off the command-line options we just added in
3207         X=$(echo $X | cut -d' ' -f2)
3208         if [ "$(which $X)" = "" ]; then
3209                 log error "$X is not in your path." >&2
3210                 exit 1
3211         elif [ ! -x $(which $X) ]; then
3212                 log error "$X is not executable." >&2
3213                 exit 1
3214         fi
3215 done
3216
3217 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
3218 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
3219 HTTPGET="$HTTPGET $HTTPGETOPTS"
3220
3221 # And last but not least, check if we can diff between files
3222 if [ -x $(which $DIFF) ]; then :; else
3223         vecho warning "Disabling diff since we cannot find it in the \$PATH..."
3224         DIFF=""
3225 fi
3226
3227 # Here it used to say:
3228 # One thousand lines in, we can start doing stuff with things
3229 # Well, right now we are at line 2736 ;)
3230
3231 # Export needed things so they can be read in this subshell
3232 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
3233 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
3234
3235 if [ "$DOREAD" = "y" ]; then
3236         # User-definable function to set some things. Use it for
3237         #  - closing the CD tray with eject -t
3238         #  - set the CD speed value with eject -x
3239         vecho -n "Executing customizable pre-read function... "
3240
3241         pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
3242
3243         vecho "done."
3244 fi
3245
3246 case "$CDDBMETHOD" in
3247         cddb)
3248                 do_discid # Get ABCDETEMPDIR created and status file initialized
3249                 ;;
3250         musicbrainz)
3251                 do_musicbrainz
3252                 ;;
3253 esac
3254
3255 if [ "$DOCDDB" = "y" ]; then
3256         if [ $CDDBUSELOCAL = "y" ]; then
3257                 do_localcddb
3258         fi
3259         if checkstatus cddb-choice > /dev/null; then
3260                 :
3261         else 
3262                 if [ ! "$CDDBLOCALSUCCESS" = "y" ] ; then
3263                         case "$CDDBMETHOD" in
3264                                 cddb)
3265                                         do_cddbstat
3266                                         do_cddbquery
3267                                         do_cddbread
3268                                         ;;
3269                                 musicbrainz)
3270                                         do_musicbrainz
3271                                         ;;
3272                         esac
3273                 fi
3274         fi
3275         do_cddbedit
3276
3277         eval "$($CDDBTOOL parse "$CDDBDATA")"
3278 fi
3279
3280 # Before reading tracks, we set the speed of the device
3281
3282 if [ X"$CDSPEEDVALUE" != "X" ]; then
3283         case "$CDROMREADERSYNTAX" in
3284                 cdparanoia|debug) ;;
3285                 flac) ;;
3286                 *) do_cdspeed ;;
3287         esac
3288 fi
3289
3290 # Define the first and last track, since we might need them later in several places
3291 FIRSTTRACK=$( get_first $TRACKQUEUE )
3292 LASTTRACK=$( get_last $TRACKQUEUE )
3293
3294 if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
3295         mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
3296         grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
3297                 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
3298 fi
3299
3300 # Create playlist if needed (backgroundable) and start reading in tracks
3301
3302 (
3303
3304 if [ ! "$ONETRACK" = "y" ]; then
3305         if [ "$DOPLAYLIST" = "y" ]; then
3306        &n