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