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