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