72877606ac2af67a5b1ea5e8516ac084c28832bd
[clinton/abcde.git] / abcde
1 #!/bin/sh
2 # Copyright (c) 1998-2001 Robert Woodcock <rcw@debian.org>
3 # Copyright (c) 2003-2004 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 VERSION=2.1.20
15
16 usage ()
17 {
18 echo "This is abcde v$VERSION."
19 echo "Usage: abcde [options] [tracks]"
20 echo "Options:"
21 echo "-1 Encode the whole CD in a single file"
22 echo "-a Actions to perform (cddb,read,normalize,encode,tag,move,playlist,clean)"
23 echo "-b Batch mode: enable album normalization and nogap encoding"
24 echo "-c Specify a configuration file (overrides system and user config files)"
25 echo "-C Specify discid to resume from (only needed if you no longer have the cd)"
26 echo "-d Specify CDROM device to grab"
27 echo "-D Debugging mode (equivalent to sh -x abcde)"
28 #echo "-f Force the use of a local CDDB entry. Otherwise use an empty template"
29 echo "-h This help information"
30 #echo "-i Tag files while encoding, when possible (local only) -NWY-"
31 echo "-j Number of encoder processes to run at once"
32 echo "-k Keep the wav tracks for later use"
33 echo "-l Use low disk space algorithm"
34 echo "-L Use local CDDB storage directory"
35 echo "-n No lookup. Don't query CDDB, just create and use template"
36 echo "-N Noninteractive. Never prompt for anything"
37 echo "-m Modify playlist to include CRLF endings, to comply with some players"
38 echo "-o Output file type(s) (ogg,mp3,flac,spx). Defaults to ogg"
39 echo "-p Pad track numbers with 0's (if less than 10 tracks)"
40 echo "-r [host1,host2...] Also encode on these remote hosts"
41 #echo "-s Start the track numbering at a given number -NWY-"
42 echo "-S Set the CD speed (if possible)"
43 #echo "-t File types to preprocess (wav)"
44 #echo "-T Set postprocessing options"
45 echo "-v Show version number and exit"
46 echo "-V Be a bit more verbose about what is happening behind the scenes"
47 echo "-x Eject CD after all tracks are read"
48 echo "Tracks is a space-delimited list of tracks to grab."
49 echo "Ranges specified with hyphens are allowed."
50 }
51
52 # Funtions to replace the need of seq, which is too distribution dependant.
53 f_seq_row ()
54 {
55 i=$1
56 while [ $i -ne `expr $2 + 1` ]
57 do
58 echo $i
59 i=`expr $i + 1`
60 done
61 }
62
63 f_seq_line ()
64 {
65 i=$1
66 while [ $i -ne `expr $2 + 1` ]
67 do
68 printf $i" "
69 i=`expr $i + 1`
70 done
71 echo
72 }
73
74 # checkstatus [blurb]
75 # Returns "0" if the blurb was found, returns 1 if it wasn't
76 # Puts the blurb content, if available, on stdout.
77 # Otherwise, returns "".
78 checkstatus ()
79 {
80 # Take the last line in the status file if there's multiple matches
81 PATTERN="^$1(=.*)?$"
82 BLURB=$(egrep $PATTERN "$ABCDETEMPDIR/status" | tail -n 1)
83
84 if [ -z "$BLURB" ]; then
85 # No matches found
86 return 1
87 else
88 # Matches found
89 # See if there's a = in it
90 if [ "$(echo $BLURB | grep -c =)" != "0" ]; then
91 echo "$(echo $BLURB | cut -f2- -d=)"
92 fi
93 return 0
94 fi
95 }
96
97 # checkerrors [blurb]
98 # Returns "0" if the blurb was found (meaning there was an error),
99 # returns 1 if it wasn't (yes this is a little backwards).
100 # Does not print the blurb on stdout.
101 # Otherwise, returns "".
102 checkerrors ()
103 {
104 if [ ! -e "$ABCDETEMPDIR/errors" ]; then
105 return 1
106 fi
107 # Take the last line in the status file if there's multiple matches
108 PATTERN="^$1(:.*)?$"
109 BLURB="$(egrep $PATTERN $ABCDETEMPDIR/errors | tail -n 1)"
110
111 if [ -z "$BLURB" ]; then
112 # negative, we did not have a negative...
113 return 1
114 else
115 # affirmative, we had a negative...
116 return 0
117 fi
118 }
119
120 # run_command [blurb] [command...]
121 # Runs a command, silently if necessary, and updates the status file
122 run_command ()
123 {
124 BLURB="$1"
125 shift
126 # See if this is supposed to be silent
127 if [ "$(checkstatus encode-output)" = "loud" ]; then
128 "$@" >&2
129 RETURN=$?
130 else
131 # Special case for SMP, since
132 # encoder output is never displayed, don't mute echos
133 if [ -z "$BLURB" -a "$MAXPROCS" != "1" ]; then
134 "$@" >&2
135 RETURN=$?
136 else
137 "$@" >/dev/null 2>&1
138 RETURN=$?
139 fi
140 fi
141 case "$1" in
142 normalize)
143 if [ "$RETURN" = "2" ]; then
144 # File was already normalized.
145 RETURN=0
146 fi
147 ;;
148 esac
149 if [ "$RETURN" != "0" ]; then
150 # Put an error in the errors file. For various reasons we
151 # can't capture a copy of the program's output but we can
152 # log what we attempted to execute and the error code
153 # returned by the program.
154 if [ "$BLURB" ]; then
155 TWEAK="$BLURB: "
156 fi
157 echo "${TWEAK}returned code $RETURN: $@" >> "$ABCDETEMPDIR/errors"
158 return $RETURN # Do not pass go, do not update the status file
159 fi
160 if [ "$BLURB" ]; then
161 echo $BLURB >> "$ABCDETEMPDIR/status"
162 fi
163 }
164
165 # relpath() and slash() are Copyright (c) 1999 Stuart Ballard and
166 # distributed under the terms of the GNU GPL v2 or later, at your option
167
168 # Function to determine if a word contains a slash.
169 slash ()
170 {
171 case "$1" in
172 */*) return 0;;
173 *) return 1;;
174 esac
175 }
176
177 # Function to give the relative path from one file to another.
178 # Usage: relpath fromfile tofile
179 # eg relpath music/Artist/Album.m3u music/Artist/Album/Song.mp3
180 # (the result would be Album/Song.mp3)
181 # Output is relative path to $2 from $1 on stdout
182
183 # This code has the following restrictions:
184 # Multiple ////s are not collapsed into single /s, with strange effects.
185 # Absolute paths and ../s are handled wrong in FR (but they work in TO)
186 # If FR is a directory it must have a trailing /
187
188 relpath ()
189 {
190 FR="$1"
191 TO="$2"
192
193 case "$TO" in
194 /*) ;; # No processing is needed for absolute paths
195 *)
196 # Loop through common prefixes, ignoring them.
197 while slash "$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
198 do
199 FR="$(echo "$FR" | cut -d/ -f2-)"
200 TO="$(echo "$TO" | cut -d/ -f2-)"
201 done
202 # Loop through directory portions left in FR, adding appropriate ../s.
203 while slash "$FR"
204 do
205 FR="$(echo "$FR" | cut -d/ -f2-)"
206 TO="../$TO"
207 done
208 esac
209
210 echo $TO
211 }
212
213 # This code splits the a Various Artist track name from one of the following
214 # forms:
215 #
216 # forward: Artist / Track
217 # forward-dash: Artist - Track
218 # reverse: Track / Artist
219 # reverse-dash: Track - Artist
220 # colon: Artist: Track
221 # trailing-paren: Artist (Track)
222 #
223 # variables used:
224 # VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
225 splitvarious ()
226 {
227 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
228 case "$VARIOUSARTISTSTYLE" in
229 forward)
230 DTITLEARTIST="$(echo $TRACKNAME | sed 's- / -~-g')"
231 TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
232 TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
233 ;;
234 forward-dash)
235 DTITLEARTIST="$(echo $TRACKNAME | sed 's, - ,~,g')"
236 TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
237 TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
238 ;;
239 reverse)
240 DTITLEARTIST="$(echo $TRACKNAME | sed 's- / -~-g')"
241 TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
242 TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
243 ;;
244 reverse-dash)
245 DTITLEARTIST="$(echo $TRACKNAME | sed 's, - ,~,g')"
246 TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
247 TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
248 ;;
249 colon)
250 DTITLEARTIST="$(echo $TRACKNAME | sed 's-: -~-g')"
251 TRACKARTIST="$(echo $DTITLEARTIST | cut -f1 -d~)"
252 TRACKNAME="$(echo $DTITLEARTIST | cut -f2 -d~)"
253 ;;
254 trailing-paren)
255 DTITLEARTIST="$(echo $TRACKNAME | sed 's,^\(.*\) (\(.*\)),\1~\2,')"
256 TRACKARTIST="$(echo $DTITLEARTIST | cut -f2 -d~)"
257 TRACKNAME="$(echo $DTITLEARTIST | cut -f1 -d~)"
258 ;;
259 esac
260 elif [ "$ONETRACK" = "y" ]; then
261 TRACKARTIST="Various"
262 else
263 TRACKARTIST=$DARTIST
264 fi
265 }
266
267 # do_tag [tracknumber]
268 # id3 tags a filename
269 # variables used:
270 # TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC,
271 # COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE (and temporarily) ID3TAGV
272 do_tag ()
273 {
274 COMMENTOUTPUT="$(eval echo ${COMMENT})"
275 run_command '' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
276 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
277 do
278 case "$OUTPUT" in
279 mp3)
280 # id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
281 run_command tagtrack-$1 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
282 -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" \
283 -g "$CDGENRE" -T "$1/$TRACKS" "$ABCDETEMPDIR/track$1.$OUTPUT"
284 ;;
285 ogg)
286 case "$OGGENCODERSYNTAX" in
287 vorbize|oggenc)
288 # vorbiscomment can't do in-place modification, mv the file first
289 if [ -f "$ABCDETEMPDIR/track$1.$OUTPUT" -a ! -f "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" ]; then
290 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT"
291 fi
292 (
293 # These are from http://www.xiph.org/ogg/vorbis/doc/v-comment.html
294 echo ARTIST="$TRACKARTIST"
295 echo ALBUM="$DALBUM"
296 echo TITLE="$TRACKNAME"
297 if [ -n "$CDYEAR" ]; then
298 echo DATE="$CDYEAR"
299 fi
300 if [ -n "$CDGENRE" ]; then
301 echo GENRE="$CDGENRE"
302 fi
303 echo TRACKNUMBER=$1
304 if [ "$(eval echo ${COMMENT})" != "" ]; then
305 case "$COMMENTOUTPUT" in
306 *=*) echo "$COMMENTOUTPUT";;
307 *) echo COMMENT="$COMMENTOUTPUT";;
308 esac
309 fi
310 ) | run_command tagtrack-$1 $VORBISCOMMENT -w \
311 "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" "$ABCDETEMPDIR/track$1.$OUTPUT"
312 # Doublecheck that the commented file was created successfully before wiping the original
313 if [ -f "$ABCDETEMPDIR/track$1.$OUTPUT" ]; then
314 rm -f "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT"
315 else
316 mv "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" "$ABCDETEMPDIR/track$1.$OUTPUT"
317 fi
318 ;;
319 esac
320 ;;
321 flac)
322 (
323 echo ARTIST="$TRACKARTIST"
324 echo ALBUM="$DALBUM"
325 echo TITLE="$TRACKNAME"
326 if [ -n "$CDYEAR" ]; then
327 echo DATE="$CDYEAR"
328 fi
329 if [ -n "$CDGENRE" ]; then
330 echo GENRE="$CDGENRE"
331 fi
332 if [ "$(eval echo ${COMMENT})" != "" ]; then
333 case "$COMMENTOUTPUT" in
334 *=*) echo "$COMMENTOUTPUT";;
335 *) echo COMMENT="$COMMENTOUTPUT";;
336 esac
337 fi
338 echo TRACKNUMBER=$1
339 ) | run_command tagtrack-$1 $METAFLAC --import-vc-from=- --no-utf8-convert "$ABCDETEMPDIR/track$1.$OUTPUT"
340 ;;
341 spx)
342 run_command tagtrack-$1 true
343 ;;
344 esac
345 done
346 }
347
348 # do_batch_encode
349 # variables used:
350 # OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
351 do_batch_encode ()
352 {
353 # The commands here don't go through run_command because they're never supposed to be silenced
354 echo "Batch encoding tracks: $TRACKQUEUE"
355 OUTPUT=$(echo $OUTPUTTYPE | grep "mp3" )
356 case "$OUTPUT" in
357 mp3)
358 case "$MP3ENCODERSYNTAX" in
359 lame)
360 (
361 cd "$ABCDETEMPDIR"
362 TRACKFILES=
363 for UTRACKNUM in $TRACKQUEUE
364 do
365 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
366 done
367 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS --nogap $TRACKFILES
368 RETURN=$?
369 if [ "$RETURN" != "0" ]; then
370 echo "batch-encode: $ENCODER returned code $RETURN" >> errors
371 else
372 for UTRACKNUM in $TRACKQUEUE
373 do
374 echo encodetrack-$UTRACKNUM >> status
375 done
376 fi
377 )
378 ;;
379 esac
380 ;;
381 esac
382 # Other encoders fall through to normal encoding as the tracks
383 # have not been entered in the status file.
384 }
385
386 # do_encode [tracknumber] [hostname]
387 # If no hostname is specified, encode locally
388 # variables used:
389 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
390 do_encode ()
391 {
392 IN="$ABCDETEMPDIR/track$1.wav"
393 # We need IN to proceed.
394 if [ -s "$IN" ] ; then
395 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
396 do
397 OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
398 run_command '' echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
399 case "$OUTPUT" in
400 mp3)
401 case "$2" in
402 %local*%)
403 case "$MP3ENCODERSYNTAX" in
404 lame|gogo) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
405 bladeenc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" ;;
406 l3enc|xingmp3enc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
407 mp3enc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
408 esac
409 ;;
410 *)
411 run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
412 ;;
413 esac
414 ;;
415 ogg)
416 case "$2" in
417 %local*%)
418 case "$OGGENCODERSYNTAX" in
419 vorbize) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
420 oggenc) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
421 esac
422 ;;
423 *)
424 run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
425 ;;
426 esac
427 ;;
428 flac)
429
430 case "$2" in
431 %local*%)
432 case "$FLACENCODERSYNTAX" in
433 flac) run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $FLACENCODER $FLACENCODEROPTS -o "$OUT" "$IN" ;;
434 esac
435 ;;
436
437 *)
438 echo -n "DISTMP3:"
439 echo "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
440 run_command encodetrack-$OUTPUT-$1 nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
441 ;;
442 esac
443 ;;
444 spx)
445 if [ "$(eval echo ${COMMENT})" != "" ]; then
446 case "$COMMENT" in
447 *=*) ;;
448 *) COMMENT="COMMENT=$COMMENT" ;;
449 esac
450 COMMENT="--comment \"$COMMENT\""
451 fi
452 # Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
453 if [ ! "$DOTAG" = "y" ]; then
454 run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" "$COMMENT" "$IN" "$OUT"
455 else
456 run_command encodetrack-$OUTPUT-$1 nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
457 fi
458 ;;
459 esac
460 done
461 # Only remove .wav if the encoding succeeded
462 if checkerrors "encodetrack-(.{3,4})-$1"; then
463 run_command encodetrack-$1 false
464 else
465 run_command encodetrack-$1 true
466 if [ ! "$KEEPWAVS" = "y" ] ; then
467 rm -f "$IN"
468 fi
469 fi
470 else
471 if [ "$(checkstatus encode-output)" = "loud" ]; then
472 echo "HEH! The file we were about to encode disappeared:"
473 echo ">> $IN"
474 fi
475 run_command encodetrack-$1 false
476 fi
477 }
478
479 # do_batch_normalize
480 # variables used:
481 # NORMALIZER, NORMALIZEROPTS
482 do_batch_normalize ()
483 {
484 # The commands here don't go through run_command because they're never supposed to be silenced
485 echo "Batch normalizing tracks: $TRACKQUEUE"
486 (
487 cd "$ABCDETEMPDIR"
488 BLURB=
489 TRACKFILES=
490 for UTRACKNUM in $TRACKQUEUE
491 do
492 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
493 done
494 # XXX: Hard-coded batch option!
495 $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
496 RETURN=$?
497 if [ "$RETURN" != "0" ]; then
498 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
499 else
500 for UTRACKNUM in $TRACKQUEUE
501 do
502 echo normalizetrack-$UTRACKNUM >> status
503 done
504 fi
505 )
506 }
507
508 # do_normalize [tracknumber]
509 # variables used:
510 # TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
511 do_normalize ()
512 {
513 IN="$ABCDETEMPDIR/track$1.wav"
514 if [ -e "$IN" ] ; then
515 run_command '' echo "Normalizing track $1 of $TRACKS: $TRACKNAME..."
516 run_command normalizetrack-$1 $NORMALIZER $NORMALIZEROPTS "$IN"
517 else
518 if [ "$(checkstatus encode-output)" = "loud" ]; then
519 echo "HEH! The file we were about to normalize disappeared:"
520 echo ">> $IN"
521 fi
522 run_command normalizetrack-$1 false "File $IN was not found"
523 fi
524 }
525
526 # do_move [tracknumber]
527 # Deduces the outfile from environment variables
528 # Creates directory if necessary
529 # variables used:
530 # TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, OUTPUTDIR
531 do_move ()
532 {
533 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
534 do
535 # Create ALBUMFILE, ARTISTFILE, TRACKFILE
536 # Munge filenames as follows:
537 # ' ' -> '_'
538 # '/' -> '_'
539 # ''' -> ''
540 # '?' -> ''
541 # Eat control characters
542 ALBUMFILE=$(mungefilename "$DALBUM")
543 ARTISTFILE=$(mungefilename "$TRACKARTIST")
544 TRACKFILE=$(mungefilename "$TRACKNAME")
545 GENRE=$(echo $CDGENRE | tr "[:upper:]" "[:lower:]")
546 # Supported variables for OUTPUTFORMAT are GENRE, ALBUMFILE, ARTISTFILE, TRACKFILE, and TRACKNUM.
547 if [ "$VARIOUSARTISTS" = "y" ]; then
548 OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
549 else
550 OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
551 fi
552
553 TRACKNUM=${UTRACKNUM}
554
555 # Check that the directory for OUTPUTFILE exists, if it doesn't, create it
556 OUTPUTFILEDIR=$(dirname "$OUTPUTDIR/$OUTPUTFILE")
557 # mkdir -p shouldn't return an error if the directory already exists
558 mkdir -p "$OUTPUTFILEDIR"
559 run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
560 done
561 }
562
563 # do_playlist
564 # Create the playlist if wanted
565 # Variables used:
566 # PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
567 # VARIOUSARTISTS, OUTPUTDIR
568 do_playlist ()
569 {
570 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
571 do
572 # Create a playlist file for the playlist data to go into.
573 # We used to wipe it out if it existed. Now we request permision if interactive.
574 for LASTTRACK in $TRACKQUEUE; do :; done
575 ALBUMFILE=$(mungefilename "$DALBUM")
576 ARTISTFILE=$(mungefilename "$DARTIST")
577 GENRE=$(echo $CDGENRE | tr "[:upper:]" "[:lower:]")
578 if [ "$VARIOUSARTISTS" = "y" ] ; then
579 PLAYLISTFILE=$(eval echo $VAPLAYLISTFORMAT)
580 else
581 PLAYLISTFILE=$(eval echo $PLAYLISTFORMAT)
582 fi
583 FINALPLAYLISTDIR=$(dirname "$OUTPUTDIR/$PLAYLISTFILE")
584 mkdir -p "$FINALPLAYLISTDIR"
585 if [ -s "$OUTPUTDIR/$PLAYLISTFILE" ]; then
586 echo -n "Erase any existing playlist file? [y/n] (y): " >&2
587 if [ "$INTERACTIVE" = "y" ]; then
588 read ERASEPLAYLIST
589 else
590 echo y >&2
591 ERASEPLAYLIST=y
592 fi
593 [ "$ERASEPLAYLIST" != "n" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE"
594 fi
595 touch "$OUTPUTDIR/$PLAYLISTFILE"
596 for UTRACKNUM in $TRACKQUEUE
597 do
598 # Shares some code with do_move since the filenames have to match
599 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
600 TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
601 splitvarious
602 TRACKFILE=$(mungefilename "$TRACKNAME")
603 ARTISTFILE=$(mungefilename "$TRACKARTIST")
604 TRACKNUM=${UTRACKNUM}
605 if [ "$VARIOUSARTISTS" = "y" ]; then
606 OUTPUTFILE=$(eval echo $VAOUTPUTFORMAT)
607 else
608 OUTPUTFILE=$(eval echo $OUTPUTFORMAT)
609 fi
610 if [ "$VARIOUSARTISTS" = "y" ]; then
611 if [ "$VAPLAYLISTDATAPREFIX" ] ; then
612 echo ${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
613 else
614 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
615 fi
616 else
617 if [ "$PLAYLISTDATAPREFIX" ]; then
618 echo ${PLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
619 else
620 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
621 fi
622 fi
623 done
624 ## this will convert the playlist to have CRLF line-endings, if specified
625 ## (some hardware players insist on CRLF endings)
626 if [ "$DOSPLAYLIST" = "y" ]; then
627 awk '{substr("\r",""); printf "%s\r\n", $0}' "$OUTPUTDIR/$PLAYLISTFILE" > "$ABCDETEMPDIR/PLAYLISTFILE.tmp"
628 rm "$OUTPUTDIR/$PLAYLISTFILE" && mv "$ABCDETEMPDIR/PLAYLISTFILE.tmp" "$OUTPUTDIR/$PLAYLISTFILE"
629 fi
630 echo "playlistcomplete" >> "$ABCDETEMPDIR/status"
631 done
632 }
633
634 # do_discid
635 # This essentially the start of things
636 do_discid ()
637 {
638 # Query the CD to get the track info, unless the user specified -C
639 if [ -z "$DISCID" ]; then
640 echo -n "Getting CD track info... "
641 TRACKINFO=$($CDDISCID $CDROM)
642 # Make sure there's a CD in there by checking cd-discid's return code
643 if [ "$?" = "1" ]; then
644 echo "abcde error: CD could not be read. Perhaps there's no CD in the drive?" >&2
645 exit 1
646 fi
647 else
648 TRACKINFO=$(cat "$WAVOUTPUTDIR/abcde.$DISCID/discid")
649 fi
650
651 # Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.
652 # This needs to be done now because a section of the resuming code will need
653 # it later.
654
655 # get the number of digits to pad TRACKNUM with - we'll use this later
656 if [ "$PADTRACKS" = "y" ] ; then
657 TRACKNUMPADDING=2
658 fi
659
660 TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
661 if [ -z "$TRACKQUEUE" ]; then
662 echo -n "Grabbing entire CD - tracks: "
663 if [ ! "$PADTRACKS" = "y" ] ; then
664 TRACKNUMPADDING=$(echo -n $TRACKS | wc -c | tr -d ' ')
665 fi
666 TRACKS=$(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
667 X=0
668 while [ "$X" -ne "$TRACKS" ]
669 do
670 X=$(printf "%0.${TRACKNUMPADDING}d" $(expr $X + 1))
671 TRACKQUEUE=$(echo "$TRACKQUEUE" $X)
672 done
673 echo $TRACKQUEUE
674 else
675 # User-supplied track queue.
676 # Weed out non-numbers, whitespace, then sort and weed out duplicates
677 TRACKQUEUE=$(echo $TRACKQUEUE | sed 's-[^0-9 ]--g' | tr ' ' '\n' | grep -v ^$ | sort -n | uniq | tr '\n' ' ' | sed 's- $--g')
678 # Once cleaned, obtain the highest value in the trackqueue for number padding
679 for LASTTRACK in $TRACKQUEUE; do :; done
680 if [ ! "$PADTRACKS" = "y" ] ; then
681 TRACKNUMPADDING=$(echo -n $LASTTRACK | wc -c | tr -d ' ')
682 fi
683 # Now we normalize the trackqueue
684 for TRACK in $TRACKQUEUE ; do
685 TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${TRACK} + 0 ))
686 PADTRACKQUEUE=$(echo $PADTRACKQUEUE $TRACKNUM)
687 done
688 TRACKQUEUE=$PADTRACKQUEUE
689 echo Grabbing tracks: "$TRACKQUEUE"
690 fi
691
692 # for LASTTRACK in $TRACKQUEUE; do :; done
693
694 QUEUEDTRACKS=$(echo $TRACKQUEUE | wc -w | tr -d ' ')
695
696 # We have the discid, create a temp directory after it to store all the temp
697 # info
698
699 ABCDETEMPDIR="$WAVOUTPUTDIR/abcde.$(echo $TRACKINFO | cut -f1 -d' ')"
700 if [ -e "$ABCDETEMPDIR" ]; then
701 echo -n "abcde: attempting to resume from $ABCDETEMPDIR"
702 # It already exists, see if it's a directory
703 if [ ! -d "$ABCDETEMPDIR" ]; then
704 # This is a file/socket/fifo/device/etc, not a directory
705 # Complain and exit
706 echo >&2
707 echo "abcde: file $ABCDETEMPDIR already exists and does not belong to abcde." >&2
708 echo "Please investigate, remove it, and rerun abcde." >&2
709 exit 1
710 fi
711 echo -n .
712 # It's a directory, let's see if it's owned by us
713 if [ ! -O "$ABCDETEMPDIR" ]; then
714 # Nope, complain and exit
715 echo >&2
716 echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
717 echo "Please investigate, remove it, and rerun abcde." >&2
718 exit 1
719 fi
720 echo .
721 # See if it's populated
722 if [ ! -f "$ABCDETEMPDIR/discid" ]; then
723 # Wipe and start fresh
724 echo "abcde: $ABCDETEMPDIR/discid not found. Abcde must remove and recreate" >&2
725 echo -n "this directory to continue. Continue? [y/n] (n)" >&2
726 if [ "$INTERACTIVE" = "y" ]; then
727 read ANSWER
728 else
729 echo y >&2
730 ANSWER=y
731 fi
732 if [ "$ANSWER" != "y" ]; then
733 exit 1
734 fi
735 rm -rf "$ABCDETEMPDIR" || exit 1
736 mkdir "$ABCDETEMPDIR"
737 if [ "$?" -gt "0" ]; then
738 # Directory already exists or could not be created
739 echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
740 exit 1
741 fi
742 else
743 # Everything is fine. Check for ^encodetracklocation-
744 # and encode-output entries in the status file and
745 # remove them. These are not relevant across sessions.
746 if [ -f "$ABCDETEMPDIR/status" ]; then
747 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
748 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
749 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
750 fi
751 # Remove old error messages
752 if [ -f "$ABCDETEMPDIR/errors" ]; then
753 rm -f "$ABCDETEMPDIR/errors"
754 fi
755 fi
756 else
757 # We are starting from scratch
758 mkdir "$ABCDETEMPDIR"
759 if [ "$?" -gt "0" ]; then
760 # Directory already exists or could not be created
761 echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
762 exit 1
763 fi
764 cat /dev/null > "$ABCDETEMPDIR/status"
765 fi
766
767 # Create the discid file
768 echo "$TRACKINFO" > "$ABCDETEMPDIR/discid"
769
770 # Determine what actions are to be done from $ACTIONS and set the
771 # following environment variables for them:
772 DOCDDB=n
773 DOREAD=n
774 DONORMALIZE=n
775 DOPREPROCESS=n
776 DOENCODE=n
777 DOPOSTPROCESS=n
778 DOTAG=n
779 DOMOVE=n
780 DOPLAYLIST=n
781 DOCLEAN=n
782
783 for ACTION in $(echo $ACTIONS | tr , \ )
784 do
785 case $ACTION in
786 cddb) DOCDDB=y;;
787 read) DOREAD=y;;
788 normalize) DONORMALIZE=y; DOREAD=y;;
789 preprocess) DOPREPROCESS=y; DOREAD=y;;
790 encode) DOENCODE=y; DOREAD=y;;
791 postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
792 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
793 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
794 playlist) DOCDDB=y; DOPLAYLIST=y;;
795 clean) DOCLEAN=y;;
796 esac
797 done
798 }
799
800 # do_cddbparse
801 # Parses a CDDB file and outputs the title and the track names.
802 # Variables: CDDBFILE
803 do_cddbparse ()
804 {
805 CDDBPARSEFILE="$1"
806 # List out disc title/author and contents
807 if [ "$ONETRACK" = "y" ]; then
808 vecho "ONETRACK mode selected: displaying only the title of the CD..."
809 fi
810 echo "---- $(grep DTITLE "${CDDBPARSEFILE}" | cut '-d=' -f2- | tr -d \\r\\n ) ----"
811 if [ ! "$ONETRACK" = "y" ];then
812 for TRACK in $(f_seq_row 1 $TRACKS)
813 do
814 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
815 done
816 fi
817 }
818
819 # do_localcddb
820 # Check for a local CDDB file, and report success
821 do_localcddb ()
822 {
823 if checkstatus cddb-readcomplete && checkstatus cddb-choice >/dev/null; then :; else
824
825 CDDBLOCALSUCCESS="n"
826 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
827 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
828 USELOCALRESP="y"
829
830 # If the user has selected to check a local CDDB repo, we proceed with it
831 if [ "$CDDBUSELOCAL" = "y" ]; then
832 if [ -r "${CDDBLOCALFILE}" ]; then
833 # List out disc title/author and contents
834 do_cddbparse "${CDDBLOCALFILE}"
835 echo -n "Locally cached CDDB entry found, use it? [y/n] (y): "
836 if [ "$INTERACTIVE" = "y" ]; then
837 read USELOCALRESP
838 while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
839 echo -n 'Invalid selection. Please answer "y" or "n": '
840 read USELOCALRESP
841 done
842 [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
843 else
844 echo "y">&2
845 fi
846 if [ "$USELOCALRESP" = "y" ]; then
847 #echo "Using local copy of CDDB data"
848 cp "${CDDBLOCALFILE}" "$ABCDETEMPDIR/cddbread.1"
849 echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
850 echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
851 do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
852 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
853 CDDBLOCALSUCCESS="y"
854 else
855 #echo "Not using local copy of CDDB data"
856 CDDBLOCALSUCCESS="n"
857 fi
858 else
859 CDDBLOCALSUCCESS="n"
860 fi
861 fi
862 fi
863 }
864
865 # do_cddbstat
866 do_cddbstat ()
867 {
868 # Perform CDDB protocol version check if it hasn't already been done
869 if checkstatus cddb-statcomplete; then :; else
870 if [ "$CDDBAVAIL" = "n" ]; then
871 ERRORCODE=no_query
872 echo 503 > "$ABCDETEMPDIR/cddbstat"
873 else
874 rc=1
875 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
876 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
877 while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
878 vecho "Checking CDDB server status..."
879 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
880 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
881 case "$RESPONSECODE" in
882 210) # 210 OK, status information follows (until terminating `.')
883 rc=0;
884 ;;
885 501|*) # 501 Illegal CDDB protocol level: <n>.
886 CDDBPROTO=`expr $CDDBPROTO - 1`
887 ;;
888 esac
889 done
890 if test $rc -eq 1; then
891 CDDBAVAIL="n"
892 fi
893 fi
894 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
895 fi
896 }
897
898
899 # do_cddbquery
900 do_cddbquery ()
901 {
902 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
903 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
904
905 # Perform CDDB query if it hasn't already been done
906 if checkstatus cddb-querycomplete; then :; else
907 if [ "$CDDBAVAIL" = "n" ]; then
908 ERRORCODE=no_query
909 echo 503 > "$ABCDETEMPDIR/cddbquery"
910 # The default CDDBLOCALSUCCESS is "n"
911 # This part will be triggered if the user CDDB repo does not
912 # contain the entry, or if we are not trying to use the repo.
913 else
914 vecho "Querying the CDDB server..."
915 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
916 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
917 $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
918 ERRORCODE=$?
919 case $ERRORCODE in
920 0) # success
921 ;;
922 12|13|14)
923 # no match found in database,
924 # wget/fetch error, or user requested not to use CDDB
925 # Make up an error code (503) that abcde
926 # will recognize in do_cddbread
927 # and compensate by making a template
928 echo 503 > "$ABCDETEMPDIR/cddbquery"
929 ;;
930 *) # strange and unknown error
931 echo ERRORCODE=$ERRORCODE
932 echo "abcde: $CDDBTOOL returned unknown error code"
933 ;;
934 esac
935 fi
936 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
937 fi
938 }
939
940 # do_cddbread
941 do_cddbread ()
942 {
943 # If it's not to be used, generate a template.
944 # Then, display it (or them) and let the user choose/edit it
945 if checkstatus cddb-readcomplete; then :; else
946 vecho "Obtaining CDDB results..."
947 # If CDDB is to be used, interpret the query results and read all
948 # the available entries.
949 rm -f "$ABCDETEMPDIR/cddbchoices"
950 CDDBCHOICES=1 # Overridden by multiple matches
951 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
952 case "$RESPONSECODE" in
953 200)
954 # One exact match, retrieve it
955 # 200 [section] [discid] [artist] / [title]
956 if checkstatus cddb-read-1-complete; then :; else
957 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
958 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
959 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
960 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
961 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
962 fi
963 # List out disc title/author and contents
964 echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
965 for TRACK in $(f_seq_row 1 $TRACKS)
966 do
967 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
968 done
969 echo >> "$ABCDETEMPDIR/cddbchoices"
970 ;;
971 202|403|409|503)
972 # No match
973 case "$RESPONSECODE" in
974 202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
975 403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
976 503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
977 esac
978 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.1"
979 # List out disc title/author and contents of template
980 echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
981 UNKNOWNDISK=y
982 for TRACK in $(f_seq_row 1 $TRACKS)
983 do
984 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
985 done
986 echo >> "$ABCDETEMPDIR/cddbchoices"
987 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
988 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
989 ;;
990 210|211)
991 # Multiple exact, (possibly multiple) inexact matches
992 IN=
993 if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
994 if [ "$(wc -l < $ABCDETEMPDIR/cddbquery | tr -d ' ')" -eq 3 ]; then
995 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
996 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
997 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
998 else
999 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
1000 fi
1001 #echo -n "Retrieving multiple matches... "
1002 grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
1003 read DISCINFO # eat top line
1004 while read DISCINFO
1005 do
1006 X=$(expr $X + 1)
1007 if checkstatus cddb-read-$X-complete; then :; else
1008 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
1009 echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
1010 fi
1011 # List out disc title/author and contents
1012 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
1013 for TRACK in $(f_seq_row 1 $TRACKS)
1014 do
1015 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1016 done
1017 echo >> "$ABCDETEMPDIR/cddbchoices"
1018 done )
1019 #echo "done."
1020 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1021 ;;
1022 999)
1023 # Using local copy.
1024 for TRACK in $(f_seq_row 1 $TRACKS)
1025 do
1026 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1027 done
1028 echo >> "$ABCDETEMPDIR/cddbchoices"
1029 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1030 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1031 ;;
1032 esac
1033 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
1034 fi
1035 }
1036
1037 # do_cddbedit
1038 do_cddbedit ()
1039 {
1040 if checkstatus cddb-edit >/dev/null; then
1041 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1042 VARIOUSARTISTS="$(checkstatus variousartists)"
1043 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
1044 return 0
1045 fi
1046 if [ "$INTERACTIVE" = "y" ]; then
1047 # We should show the CDDB results both when we are not using the local CDDB repo
1048 # or when we are using it but we could not find a proper match
1049 if [ "$CDDBUSELOCAL" = "y" ] && [ ! "$CDDBLOCALSUCCESS" = "y" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1050 # Display the $ABCDETEMPDIR/cddbchoices file created above
1051 # Pick a pager so that if the tracks overflow the screen the user can still view everything
1052 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1053 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1054 CHOICE=$(checkstatus cddb-choice)
1055 if [ -n "$CHOICE" ] ; then
1056 case $CDDBCHOICES in
1057 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1058 *)
1059 echo "Selected: #$CHOICE"
1060 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1061 ;;
1062 esac
1063 else
1064 # The user has a choice to make, display the info in a pager if necessary
1065 if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
1066 # Use the debian sensible-pager wrapper to pick the pager
1067 # user has requested via their $PAGER environment variable
1068 if [ -x "/usr/bin/sensible-pager" ]; then
1069 /usr/bin/sensible-pager "$ABCDETEMPDIR/cddbchoices"
1070 elif [ -x "$PAGER" ]; then
1071 # That failed, try to load the preferred editor, starting
1072 # with their PAGER variable
1073 $PAGER "$ABCDETEMPDIR/cddbchoices"
1074 # If that fails, check for less
1075 elif [ -x /usr/bin/less ]; then
1076 /usr/bin/less -f "$ABCDETEMPDIR/cddbchoices"
1077 # more should be on all UNIX systems
1078 elif [ -x /bin/more ]; then
1079 /bin/more "$ABCDETEMPDIR/cddbchoices"
1080 else
1081 # No bananas, just cat the thing
1082 cat "$ABCDETEMPDIR/cddbchoices" >&2
1083 fi
1084 else
1085 # It's all going to fit in one page, cat it
1086 cat "$ABCDETEMPDIR/cddbchoices" >&2
1087 fi
1088
1089 # I'll take CDDB read #3 for $400, Alex
1090 echo -n "Which entry would you like abcde to use? [1-$CDDBCHOICES]: " >&2
1091 read CDDBCHOICE
1092 # Make sure we get a valid choice
1093 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
1094 while [ $CDCHOICENUM -lt 1 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
1095 echo "Invalid selection. Please choose a number between 1 and $CDDBCHOICES." >&2
1096 echo -n "Selection [1-$CDDBCHOICES]: " >&2
1097 read CDDBCHOICE
1098 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
1099 done
1100 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= $ABCDETEMPDIR/cddbread.$CDCHOICENUM | cut -f2- -d= | tr -d \\r\\n))" >&2
1101 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
1102 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1103 fi
1104 fi
1105 else
1106 # We need some code to show the selected option when local repository is selected and we have found a match
1107 echo "Using cached CDDB match..."
1108 # Display the $ABCDETEMPDIR/cddbchoices file created above
1109 # Pick a pager so that if the tracks overflow the screen the user can still view everything
1110 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1111 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1112 CHOICE=$(checkstatus cddb-choice)
1113 if [ "$USELOCALRESP" = "y" ]; then :; else
1114 if [ -n "$CHOICE" ] ; then
1115 case $CDDBCHOICES in
1116 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1117 *)
1118 echo "Selected: #$CHOICE"
1119 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1120 ;;
1121 esac
1122 fi
1123 fi
1124 fi
1125 fi
1126 else
1127 # We're noninteractive - pick the first choice.
1128 # But in case we run a previous instance and selected a choice, use it.
1129 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1130 # Show the choice if we are not using the locally stored one
1131 # or when the local search failed to find a match.
1132 PREVIOUSCHOICE=$(checkstatus cddb-choice)
1133 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSUCCESS" = "n" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1134 #if [ "$PREVIOUSCHOICE" ]; then
1135 cat "$ABCDETEMPDIR/cddbchoices"
1136 #fi
1137 fi
1138 if [ ! -z "$PREVIOUSCHOICE" ] ; then
1139 CDCHOICENUM=$PREVIOUSCHOICE
1140 else
1141 CDCHOICENUM=1
1142 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1143 fi
1144 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= $ABCDETEMPDIR/cddbread.$CDCHOICENUM | cut -f2- -d= | tr -d \\r\\n))" >&2
1145 fi
1146 fi
1147
1148 # sanity check
1149 if checkstatus cddb-choice >/dev/null; then :; else
1150 echo "abcde: internal error: cddb-choice not recorded." >&2
1151 exit 1
1152 fi
1153 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1154 echo -n "Edit selected CDDB data? [y/n] ("
1155 if [ "$INTERACTIVE" = "y" ]; then
1156 if [ "$UNKNOWNDISK" = "y" ]; then
1157 echo -n "y): " >&2
1158 read EDITCDDB
1159 [ "$EDITCDDB" != "n" ] && EDITCDDB=y
1160 else
1161 echo -n "n): " >&2
1162 read EDITCDDB
1163 fi
1164 else
1165 echo "n): n" >&2
1166 EDITCDDB=n
1167 fi
1168 if [ "$EDITCDDB" = "y" ]; then
1169 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
1170
1171 # Use the debian sensible-editor wrapper to pick the editor that the
1172 # user has requested via their $EDITOR environment variable
1173 if [ -x "/usr/bin/sensible-editor" ]; then
1174 /usr/bin/sensible-editor "$CDDBDATA"
1175 elif [ -n "$EDITOR" ]; then
1176 if [ -x $(which "${EDITOR%%\ *}") ]; then
1177 # That failed, try to load the preferred editor, starting
1178 # with their EDITOR variable
1179 eval $(echo "$EDITOR") "$CDDBDATA"
1180 fi
1181 # If that fails, check for a vi
1182 elif [ -x /usr/bin/vi ]; then
1183 /usr/bin/vi "$CDDBDATA"
1184 # nano should be on all (modern, i.e., sarge) debian systems
1185 elif [ -x /usr/bin/nano ]; then
1186 /usr/bin/nano "$CDDBDATA"
1187 # mg should be on all OpenBSD systems
1188 elif [ -x /usr/bin/mg ]; then
1189 /usr/bin/mg "$CDDBDATA"
1190 # bomb out
1191 else
1192 echo "No editor available. Check your EDITOR environment variable." >&2
1193 fi
1194 # delete editor backup file if it exists
1195 if [ -w "$CDDBDATA~" ]; then
1196 rm -f "$CDDBDATA~"
1197 fi
1198 fi
1199
1200 # Some heuristics first. Look at Disc Title, and if it starts with
1201 # "Various", then we'll assume Various Artists
1202 if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2 -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
1203 echo "Looks like a Multi-Artist CD" >&2
1204 VARIOUSARTISTS=y
1205 else
1206 echo -n "Is the CD multi-artist? [y/n] (n): " >&2
1207 if [ "$INTERACTIVE" = "y" ]; then
1208 read VARIOUSARTISTS
1209 else
1210 echo n >&2
1211 VARIOUSARTISTS=n
1212 fi
1213 fi
1214 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
1215 # Set a default
1216 DEFAULTSTYLE=1
1217 # Need NUMTRACKS before cddb-tool will return it:
1218 NUMTRACKS=$(grep -E '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
1219 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1220 # More than 1/2 tracks contain a "/", so guess forward
1221 DEFAULTSTYLE=1
1222 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1223 # More than 1/2 contain a "-", so guess forward-dash
1224 DEFAULTSTYLE=2
1225 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1226 # More than 1/2 contain something in parens, so guess trailing-paren
1227 DEFAULTSTYLE=6
1228 fi
1229
1230 echo "1) Artist / Title" >&2
1231 echo "2) Artist - Title" >&2
1232 echo "3) Title / Artist" >&2
1233 echo "4) Title - Artist" >&2
1234 echo "5) Artist: Title" >&2
1235 echo "6) Title (Artist)" >&2
1236 echo "7) This is a single-artist CD" >&2
1237 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
1238 if [ "$INTERACTIVE" = "y" ]; then
1239 read VARIOUSARTISTSTYLE
1240 else
1241 echo $DEFAULTSTYLE >&2
1242 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
1243 fi
1244 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
1245 # If they press Enter, then the default style (0) was chosen
1246 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
1247 echo "Invalid selection. Please choose a number between 1 and 7."
1248 echo -n "Selection [1-7]: "
1249 read VARIOUSARTISTSTYLE
1250 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
1251 done
1252 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
1253 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
1254 fi
1255 echo "Selected: $VARIOUSARTISTSTYLE"
1256 case "$VARIOUSARTISTSTYLE" in
1257 1) # Artist / Title
1258 VARIOUSARTISTSTYLE=forward
1259 ;;
1260 2) # Artist - Title
1261 VARIOUSARTISTSTYLE=forward-dash
1262 ;;
1263 3) # Title / Artist
1264 VARIOUSARTISTSTYLE=reverse
1265 ;;
1266 4) # Title - Artist
1267 VARIOUSARTISTSTYLE=reverse-dash
1268 ;;
1269 5) # Artist: Title
1270 VARIOUSARTISTSTYLE=colon
1271 ;;
1272 6) # Title (Artist)
1273 VARIOUSARTISTSTYLE=trailing-paren
1274 ;;
1275 7) # Single Artist
1276 VARIOUSARTISTS=n
1277 ;;
1278 esac
1279 fi
1280
1281 echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
1282 echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
1283
1284 if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
1285 if [ $CDDBDATAMD5SUM != "" ] && [ $CDDBDATAMD5SUM != $($MD5SUM "$CDDBDATA" | cut -d " " -f 1) ]; then
1286 # This works but does not have the necessary error checking
1287 # yet. If you are familiar with the CDDB spec
1288 # (see http://www.freedb.org/src/latest/DBFORMAT)
1289 # and can create an error-free entry on your own, then put
1290 # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
1291 # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
1292 # your abcde.conf to change the email address submissions are
1293 # sent to.
1294
1295 # submit the modified file, if they want
1296 if [ "$NOSUBMIT" != "y" ]; then
1297 echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
1298 read YESNO
1299 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
1300 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
1301 do
1302 echo -n 'Invalid selection. Please answer "y" or "n": '
1303 read YESNO
1304 done
1305 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
1306 echo -n "Sending..."
1307 $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
1308 echo "done."
1309 fi
1310 fi
1311 fi
1312 fi
1313 # Make sure the cache directory exists
1314 mkdir -p $CDDBLOCALDIR
1315 # Cache edited CDDB entry in the user's cddb dir
1316 if [ "$CDDBCOPYLOCAL" = "y" ] || [ "$COPYCDDBLOCAL" = "Y" ]; then
1317 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
1318 fi
1319
1320 echo "cddb-edit" >> "$ABCDETEMPDIR/status"
1321 }
1322
1323 # do_cdread_one [lasttrack] [firsttrack]
1324 #
1325 # Reads the CD in a single track. Live performances, concerts, mixes,... benefit from this.
1326 do_cdread_one ()
1327 {
1328 # The commands here don't go through run_command because they're never supposed to be silenced
1329 # return codes need to be doublechecked anyway, however
1330 LASTTRACKNUMBER=$1
1331 FIRSTTRACKNUMBER=$2
1332 WAVDATA="$ABCDETEMPDIR/track$FIRSTTRACKNUMBER.wav"
1333 echo "Grabbing the CD to a single track..." >&2
1334 case "$CDROMREADERSYNTAX" in
1335 cdparanoia) nice $READNICE $CDROMREADER -d $CDROM "1-" "$WAVDATA" >&2 ;;
1336 cdda2wav)
1337 if [ "$OSFLAVOUR" = "OSX" ] ; then
1338 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
1339 disktool -u ${CDROM#/dev/} 0
1340 # Also, in OSX the cdrom device for cdda2wav changes...
1341 CDDA2WAVCDROM="IODVDServices"
1342 elif [ "$OSFLAVOUR" = "FBSD" ] ; then
1343 CDDA2WAVCDROM="$CDROMID"
1344 else
1345 if [ "$CDROMID" = "" ]; then
1346 CDDA2WAVCDROM="$CDROM"
1347 else
1348 CDDA2WAVCDROM="$CDROMID"
1349 fi
1350 fi
1351 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t 1+$LASTTRACKNUM "$WAVDATA" >&2
1352 ;;
1353 dagrab) nice $READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
1354 cddafs)
1355 # Find the track's mounted path
1356 REALTRACKNUM=$(expr $UTRACKNUM + 0)
1357 FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \([^(]*\) (.*/\1/')
1358 FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
1359 # If the file exists, copy it
1360 if [ -e "$FILEPATH" ] ; then
1361 nice $READNICE $CDROMREADER "$FILEPATH" "$WAVDATA" >&2
1362 else
1363 false
1364 fi ;;
1365 debug) nice $READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
1366 esac
1367 RETURN=$?
1368 if [ "$RETURN" != "0" ]; then
1369 # Thank goodness errors is only machine-parseable up to the
1370 # first colon, otherwise this woulda sucked
1371 echo "readtrack-$FIRSTTRACKNUMBER: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
1372 return $RETURN
1373 else
1374 echo readtrack-$FIRSTTRACKNUMBER >> "$ABCDETEMPDIR/status"
1375 fi
1376 }
1377
1378 # do_cdread [tracknumber]
1379 #
1380 do_cdread ()
1381 {
1382 # The commands here don't go through run_command because they're never supposed to be silenced
1383 # return codes need to be doublechecked anyway, however
1384 UTRACKNUM=$1
1385 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
1386 WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
1387 OUTDATA="$ABCDETEMPDIR/track$UTRACKNUM.$OUTPUTTYPE"
1388 if [ -r "$CDDBDATA" ]; then
1389 TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
1390 echo "Grabbing track $UTRACKNUM: $TRACKNAME..." >&2
1391 else
1392 echo "Grabbing track $UTRACKNUM..." >&2
1393 fi
1394 case "$CDROMREADERSYNTAX" in
1395 cdparanoia) nice $READNICE $CDROMREADER -d $CDROM $UTRACKNUM "$WAVDATA" >&2 ;;
1396 cdda2wav)
1397 if [ "$OSFLAVOUR" = "OSX" ] ; then
1398 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
1399 disktool -u ${CDROM#/dev/} 0
1400 # Also, in OSX the cdrom device for cdda2wav changes...
1401 CDDA2WAVCDROM="IODVDServices"
1402 elif [ "$OSFLAVOUR" = "FBSD" ] ; then
1403 CDDA2WAVCDROM="$CDROMID"
1404 else
1405 if [ "$CDROMID" = "" ]; then
1406 CDDA2WAVCDROM="$CDROM"
1407 else
1408 CDDA2WAVCDROM="$CDROMID"
1409 fi
1410 fi
1411 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t $UTRACKNUM "$WAVDATA" >&2
1412 ;;
1413 dagrab) nice $READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
1414 cddafs)
1415 # Find the track's mounted path
1416 REALTRACKNUM=$(expr $UTRACKNUM + 0)
1417 FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \([^(]*\) (.*/\1/')
1418 FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
1419 # If the file exists, copy it
1420 if [ -e "$FILEPATH" ] ; then
1421 nice $READNICE $CDROMREADER "$FILEPATH" "$WAVDATA" >&2
1422 else
1423 false
1424 fi ;;
1425 debug) nice $READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
1426 esac
1427 RETURN=$?
1428 if [ "$RETURN" != "0" ]; then
1429 # Thank goodness errors is only machine-parseable up to the
1430 # first colon, otherwise this woulda sucked
1431 echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
1432 return $RETURN
1433 else
1434 echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
1435 fi
1436 }
1437
1438 do_cdspeed ()
1439 {
1440 if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
1441 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
1442 else
1443 echo "abcde: unable to set the device speed" >&2
1444 fi
1445 }
1446
1447 # vecho [message]
1448 #
1449 # vecho outputs a message if EXTRAVERBOSE is selected
1450 vecho ()
1451 {
1452 if [ x"$EXTRAVERBOSE" != "x" ]; then
1453 echo $@
1454 fi
1455 }
1456
1457 # Start of execution
1458
1459 # Builtin defaults
1460 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
1461 CDDBSUBMIT=freedb-submit@freedb.org
1462 CDDBPROTO=5
1463 HELLOINFO="$(whoami)@$(hostname)"
1464 INTERACTIVE=y
1465 CDROMREADERSYNTAX=cdparanoia
1466 OUTPUTTYPE=ogg
1467 ENCODERSYNTAX=default
1468
1469 MP3ENCODERSYNTAX=default
1470 OGGENCODERSYNTAX=default
1471 FLACENCODERSYNTAX=default
1472 SPEEXENCODERSYNTAX=default
1473
1474 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
1475 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
1476 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
1477 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
1478 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
1479 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
1480 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
1481 PLAYLISTDATAPREFIX=''
1482 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
1483 VAPLAYLISTDATAPREFIX=''
1484 DOSPLAYLIST=n
1485 COMMENT=''
1486 ID3TAGV=2
1487 ENCNICE=10
1488 READNICE=10
1489 DISTMP3NICE=10
1490 VARIOUSARTISTS=n
1491 VARIOUSARTISTSTYLE=forward
1492 NORMALIZERSYNTAX=default
1493 KEEPWAVS=n
1494 PADTRACKS=n
1495 CDDBCOPYLOCAL="n"
1496 CDDBLOCALDIR="$HOME/.cddb"
1497 CDDBUSELOCAL="n"
1498
1499 # If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
1500 # i.e. CDROMID="1,0,0"
1501 CDROMID=""
1502
1503 # program paths - defaults to checking your $PATH
1504 # mp3
1505 LAME=lame
1506 GOGO=gogo
1507 BLADEENC=bladeenc
1508 L3ENC=l3enc
1509 XINGMP3ENC=xingmp3enc
1510 MP3ENC=mp3enc
1511 # ogg
1512 VORBIZE=vorbize
1513 OGGENC=oggenc
1514 # flac
1515 FLAC=flac
1516 # speex
1517 SPEEXENC=speexenc
1518
1519 ID3=id3
1520 ID3V2=id3v2
1521 CDPARANOIA=cdparanoia
1522 CDDA2WAV=cdda2wav
1523 DAGRAB=dagrab
1524 CDDAFS=cp
1525 CDDISCID=cd-discid
1526 CDDBTOOL=cddb-tool
1527 EJECT=eject
1528 MD5SUM=md5sum
1529 DISTMP3=distmp3
1530 VORBISCOMMENT=vorbiscomment
1531 METAFLAC=metaflac
1532 NORMALIZE=normalize
1533 CDSPEED=eject
1534
1535 # Options for programs called from abcde
1536 # mp3
1537 LAMEOPTS=
1538 GOGOOPTS=
1539 BLADEENCOPTS=
1540 L3ENCOPTS=
1541 XINGMP3ENCOPTS=
1542 MP3ENCOPTS=
1543 # ogg
1544 VORBIZEOPTS=
1545 OGGENCOPTS=
1546 # flac
1547 FLACOPTS=
1548 # speex
1549 SPEEXENCOPTS=
1550
1551 ID3OPTS=
1552 ID3V2OPTS=
1553 CDPARANOIAOPTS=
1554 CDDA2WAVOPTS=
1555 DAGRABOPTS=
1556 CDDAFSOPTS="-f"
1557 CDDBTOOLOPTS=
1558 EJECTOPTS=
1559 DISTMP3OPTS=
1560 NORMALIZEOPTS=
1561 CDSPEEDOPTS="-x"
1562 CDSPEEDVALUE=
1563
1564 # Default to one process if -j isn't specified
1565 MAXPROCS=1
1566
1567 # List of actions to perform - by default, run to completion
1568 ACTIONS=cddb,read,encode,tag,move,clean
1569
1570 # User-redefinable functions
1571 # Custom filename munging:
1572 mungefilename ()
1573 {
1574 echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
1575 }
1576
1577 # Pre-read execution:
1578 pre_read ()
1579 {
1580 :
1581 }
1582
1583 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for Linux/OpenBSD/NetBSD.
1584 # Let's use these checkings to determine the OS flavour, which will be used later
1585 if [ X$(uname) = "XFreeBSD" ] ; then
1586 HTTPGET=fetch
1587 NEEDCDROMID=y
1588 OSFLAVOUR=FBSD
1589 elif [ X$(uname) = "XDarwin" ] ; then
1590 HTTPGET=curl
1591 OSFLAVOUR=OSX
1592 # We should have disktool in OSX, but let's be sure...
1593 NEEDDISKTOOL=y
1594 elif [ X$(uname) = "XOpenBSD" ] ; then
1595 HTTPGET=wget
1596 MD5SUM=md5
1597 else
1598 HTTPGET=wget
1599 fi
1600
1601 # If CDDBAVAIL is set to n, no CDDB read is done
1602 # If USEID3 is set to n, no ID3 tagging is done
1603 CDDBAVAIL=y
1604 USEID3=y
1605
1606 if [ -z "$OUTPUTDIR" ]; then
1607 OUTPUTDIR=$(pwd)
1608 fi
1609
1610 if [ -z "$WAVOUTPUTDIR" ]; then
1611 WAVOUTPUTDIR="$OUTPUTDIR"
1612 fi
1613
1614 # Load system defaults
1615 if [ -r /etc/abcde.conf ]; then
1616 . /etc/abcde.conf
1617 fi
1618 # Load user preference defaults
1619 if [ -r $HOME/.abcde.conf ]; then
1620 . $HOME/.abcde.conf
1621 fi
1622
1623 # By this time, we need some HTTPGETOPTS already defined.
1624 # If the user has defined its own, we should not be empty.
1625
1626 if [ "$HTTPGETOPTS" = "" ] ; then
1627 case $HTTPGET in
1628 wget) HTTPGETOPTS="-q -O -";;
1629 curl) HTTPGETOPTS="-f -s";;
1630 fetch)HTTPGETOPTS="-q -o -";;
1631 *) echo "abcde warning: HTTPGET in non-standard and HTTPGETOPTS are not defined." >&2 ;;
1632 esac
1633 fi
1634
1635 # If the CDROM has not been set yet, find a suitable one.
1636 # If this is a devfs system, default to /dev/cdroms/cdrom0
1637 # instead of /dev/cdrom
1638 if [ "$CDROM" = "" ] ; then
1639 if [ -e /dev/cdroms/cdrom0 ]; then
1640 CDROM=/dev/cdroms/cdrom0
1641 elif [ -e /dev/cdrom ]; then
1642 CDROM=/dev/cdrom
1643 elif [ -e /dev/cd0c ]; then
1644 CDROM=/dev/cd0c
1645 elif [ -e /dev/acd0c ]; then
1646 CDROM=/dev/acd0c
1647 elif [ -e /dev/disk1 ]; then
1648 CDROM=/dev/disk1
1649 fi
1650 fi
1651
1652 # Parse command line options
1653 #while getopts 1a:bc:C:d:Dhj:klLnNo:pr:S:t:T:vVx opt ; do
1654 while getopts 1a:bc:C:d:Dhj:klLnNo:pr:S:vVx opt ; do
1655 case "$opt" in
1656 1) ONETRACK=y ;;
1657 a) ACTIONS="$OPTARG" ;;
1658 b) BATCH=y ;;
1659 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else echo "abcde error: config file \"$OPTARG\" cannot be found." >&2 ; exit 1 ; fi ;;
1660 C) DISCID="${OPTARG#abcde.}" ;;
1661 d) CDROM="$OPTARG" ;;
1662 D) set -x ;;
1663 h) usage; exit ;;
1664 f) FORCECDDBUSELOCAL=y ;;
1665 i) INLINETAG=y ;;
1666 j) MAXPROCS="$OPTARG" ;;
1667 k) KEEPWAVS=y ;;
1668 l) LOWDISK=y ;;
1669 L) CDDBUSELOCAL="y" ;;
1670 n) CDDBAVAIL="n" ;;
1671 N) INTERACTIVE="n" ;;
1672 m) DOSPLAYLIST=y ;;
1673 o) OUTPUTTYPE="$OPTARG" ;;
1674 p) PADTRACKS="y" ;;
1675 r) REMOTEHOSTS="$OPTARG" ;;
1676 s) STARTTRACKNUMBER="$OPTARG" ;;
1677 S) CDSPEEDVALUE="$OPTARG" ;;
1678 t) PREPROCESSFORMATS="$OPTARG"
1679 PREPROCESS=y ;;
1680 T) POSTPROCESSFORMATS="$OPTARG" ;;
1681 v)
1682 echo "This is abcde v$VERSION."
1683 echo "Usage: abcde [options] [tracks]"
1684 echo "abcde -h for extra help"
1685 exit
1686 ;;
1687 V) EXTRAVERBOSE="y" ;;
1688 x) EJECTCD="y" ;;
1689 ?) usage; exit ;;
1690 esac
1691 done
1692
1693 shift $(($OPTIND - 1))
1694
1695 if [ "$ONETRACK" = "y" ] ; then
1696 if [ $# -gt 0 ]; then
1697 vecho "ONETRACK mode selected: grabbing all tracks..."
1698 fi
1699 else
1700 while [ $# -gt 0 ]; do
1701 # Range parsing code courtesy of Vincent Ho
1702 RSTART=$(echo $1 | cut -f1 -d-)
1703 REND=$(echo $1 | cut -f2 -d-)
1704 if [ "$RSTART" = "$REND" ]; then
1705 NEWTRACKS="$RSTART"
1706 else
1707 NEWTRACKS=$(f_seq_line $RSTART $REND)
1708 fi
1709 TRACKQUEUE=$(echo "$TRACKQUEUE" "$NEWTRACKS")
1710
1711 shift
1712 done
1713 fi
1714
1715 # At this point a CDROM has to be defined, so we check it exists.
1716 if [ "$CDROM" != "" ] ; then
1717 if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
1718 if [ "$OSFLAVOUR" = "FBSD" ]; then
1719 if ! echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then
1720 echo "abcde error: CDROMID not in the right format for $CDROMREADERSYNTAX"
1721 echo "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
1722 exit 1
1723 fi
1724 fi
1725 elif [ ! -e $CDROM ] ; then
1726 echo "abcde error: CDROM device cannot be found." >&2
1727 exit 1
1728 fi
1729 else
1730 echo "abcde error: CDROM has not been defined or cannot be found" >&2
1731 exit 1
1732 fi
1733
1734 # Decide if we can continue. TO_REMOVE as soon as we find out about dagrab
1735 if [ "$ONETRACK" = "y" ]; then
1736 case "$CDROMREADERSYNTAX" in
1737 dagrab|debug) echo "abcde error: ONETRACK reading is not suported with "$CDROMREADERSYNTAX" yet"
1738 exit 1 ;;
1739 esac
1740 if [ "$BATCH" = "y" ]; then
1741 echo "abcde error: BATCH mode is not compatible with ONETRACK mode"
1742 fi
1743 fi
1744
1745 # Decide which CDROM reader we're gonna use
1746 case "$CDROMREADERSYNTAX" in
1747 cdparanoia|debug)
1748 CDROMREADER="$CDPARANOIA"
1749 CDROMREADEROPTS="$CDPARANOIAOPTS"
1750 ;;
1751 cdda2wav)
1752 CDROMREADER="$CDDA2WAV"
1753 CDROMREADEROPTS="$CDDA2WAVOPTS"
1754 ;;
1755 dagrab)
1756 CDROMREADER="$DAGRAB"
1757 CDROMREADEROPTS="$DAGRABOPTS"
1758 ;;
1759 cddafs)
1760 CDROMREADER="$CDDAFS"
1761 CDROMREADEROPTS="$CDDAFSOPTS"
1762 ;;
1763 esac
1764
1765 # There's only one normalize...
1766 case "$NORMALIZERSYNTAX" in
1767 default|normalize)
1768 NORMALIZER="$NORMALIZE"
1769 NORMALIZEROPTS="$NORMALIZEOPTS"
1770 ;;
1771 esac
1772
1773 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac for flacs and speexenc for speex
1774
1775 # Getting ready for multiple output changes
1776 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1777 do
1778 case $OUTPUT in
1779 ogg) [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
1780 echo $ACTIONS | grep tag > /dev/null 2>&1 && NEEDCOMMENTER=y
1781 ;;
1782 mp3) [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
1783 echo $ACTIONS | grep tag > /dev/null 2>&1 && NEEDTAGGER=y
1784 ;;
1785 flac) [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
1786 echo $ACTIONS | grep tag > /dev/null 2>&1 && NEEDMETAFLAC=y
1787 ;;
1788 spx) [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc ;;
1789 *) echo "abcde error: Invalid OUTPUTTYPE defined" >&2
1790 exit 1
1791 ;;
1792 esac
1793 done
1794
1795 # decide which encoder
1796 case "$MP3ENCODERSYNTAX" in
1797 lame)
1798 MP3ENCODEROPTS="$LAMEOPTS"
1799 MP3ENCODER="$LAME"
1800 ;;
1801 gogo)
1802 MP3ENCODEROPTS="$GOGOOPTS"
1803 MP3ENCODER="$GOGO"
1804 ;;
1805 bladeenc)
1806 MP3ENCODEROPTS="$BLADEENCOPTS"
1807 MP3ENCODER="$BLADEENC"
1808 ;;
1809 l3enc)
1810 MP3ENCODEROPTS="$L3ENCOPTS"
1811 MP3ENCODER="$L3ENC"
1812 ;;
1813 xingmp3enc)
1814 MP3ENCODEROPTS="$XINGMP3ENCOPTS"
1815 MP3ENCODER="$XINGMP3ENC"
1816 ;;
1817 mp3enc)
1818 MP3ENCODEROPTS="$MP3ENCOPTS"
1819 MP3ENCODER="$MP3ENC"
1820 ;;
1821 esac
1822 case "$OGGENCODERSYNTAX" in
1823 vorbize)
1824 OGGENCODEROPTS="$VORBIZEOPTS"
1825 OGGENCODER="$VORBIZE"
1826 ;;
1827 oggenc)
1828 OGGENCODEROPTS="$OGGENCOPTS"
1829 OGGENCODER="$OGGENC"
1830 ;;
1831 esac
1832 case "$FLACENCODERSYNTAX" in
1833 flac)
1834 FLACENCODEROPTS="$FLACOPTS"
1835 FLACENCODER="$FLAC"
1836 ;;
1837 esac
1838 case "$SPEEXENCODERSYNTAX" in
1839 speexenc)
1840 SPEEXENCODEROPTS="$SPEEXENCOPTS"
1841 SPEEXENCODER="$SPEEXENC"
1842 ;;
1843 esac
1844
1845 # and which tagger
1846
1847 if [ "$ID3TAGV" = "1" ]; then
1848 TAGGER="$ID3"
1849 TAGGEROPTS="$ID3OPTS"
1850 else
1851 TAGGER="$ID3V2"
1852 TAGGEROPTS="$ID3V2OPTS"
1853 fi
1854
1855 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
1856
1857 if [ "$ENCNICE" ]; then
1858 ENCNICE="-n $ENCNICE"
1859 fi
1860 if [ "$READNICE" ]; then
1861 READNICE="-n $READNICE"
1862 fi
1863 if [ "$DISTMP3NICE" ]; then
1864 DISTMP3NICE="-n $DISTMP3NICE"
1865 fi
1866
1867 # Don't check for stuff if it's not needed
1868 if [ "$REMOTEHOSTS" ]; then NEEDDISTMP3=y; fi
1869 if echo $ACTIONS | grep normalize > /dev/null 2>&1 ; then NEEDNORMALIZER=y; fi
1870 if [ "$EJECTCD" = "y" ]; then NEEDEJECT=y; fi
1871 if echo $ACTIONS | grep cddb > /dev/null 2>&1 ; then NEEDHTTPGET=y ; fi
1872
1873 if [ X"$CDSPEEDVALUE" != "X" ]; then
1874 case "$CDROMREADERSYNTAX" in
1875 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
1876 *) NEEDCDSPEED=y ;;
1877 esac
1878 fi
1879
1880
1881 # Make sure a buncha things exist
1882 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
1883 $OGGENCODER $FLACENCODER $SPEEXENCODER ${NEEDHTTPGET+$HTTPGET} \
1884 ${NEEDDISTMP3+$DISTMP3} ${NEEDCOMMENTER+$VORBISCOMMENT} \
1885 ${NEEDMETAFLAC+$METAFLAC} ${NEEDNORMALIZER+$NORMALIZER} \
1886 ${NEEDEJECT+$EJECT} ${NEEDDISKTOOL+disktool} \
1887 ${NEEDCDSPEED+$CDSPEED}
1888 do
1889 # Cut off the command-line options we just added in
1890 X=$(echo $X | cut -d' ' -f2)
1891 if [ "$(which $X)" = "" ]; then
1892 echo "abcde error: $X is not in your path." >&2
1893 exit 1
1894 elif [ ! -x $(which $X) ]; then
1895 echo "abcde error: $X is not executable." >&2
1896 exit 1
1897 fi
1898 done
1899
1900 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
1901 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
1902 HTTPGET="$HTTPGET $HTTPGETOPTS"
1903
1904 # One thousand seven hundred lines in, we can start doing stuff with things
1905
1906 # List of valid actions: cddb,playlist,read,normalize,encode,tag,move
1907
1908 # Export needed things so they can be read in this subshell
1909 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
1910 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
1911
1912 # User-definable function to set some things. Use it for
1913 # - closing the CD tray with eject -t
1914 # - set the CD speed value with eject -x
1915 vecho -n "Executing customizable pre-read function... "
1916
1917 pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
1918
1919 vecho "done."
1920
1921 do_discid # Get ABCDETEMPDIR created and status file initialized
1922
1923 if [ "$DOCDDB" = "y" ]; then
1924 if [ $CDDBUSELOCAL = "y" ]; then
1925 do_localcddb
1926 fi
1927 if [ ! "$CDDBLOCALSUCCESS" = "y" ] ; then
1928 do_cddbstat
1929 do_cddbquery
1930 do_cddbread
1931 fi
1932 do_cddbedit
1933
1934 eval $($CDDBTOOL parse "$CDDBDATA")
1935 fi
1936
1937 # Before reading tracks, we set the speed of the device
1938
1939 if [ X"$CDSPEEDVALUE" != "X" ]; then
1940 case "$CDROMREADERSYNTAX" in
1941 cdparanoia|debug) : ;;
1942 *) do_cdspeed ;;
1943 esac
1944 fi
1945
1946 # Create playlist if needed (backgroundable) and start reading in tracks
1947
1948 (
1949 if [ "$ONETRACK" = "y" ]; then :; else
1950 if [ "$DOPLAYLIST" = "y" ]; then
1951 echo Creating playlist... >&2
1952 do_playlist
1953 fi
1954 fi
1955
1956 # For the lowdisk option, only one program is running at once so the encoder
1957 # can be unsilenced right away.
1958 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
1959 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
1960 fi
1961
1962 if [ "$ONETRACK" = "y" ]; then
1963 FIRSTTRACK=$( echo $TRACKQUEUE | awk '{print $1}' )
1964 TRACKS="$FIRSTTRACK"
1965 for UTRACKNUM in $TRACKQUEUE; do :;done
1966 if checkstatus readtrack-$FIRSTTRACK; then :; else
1967 do_cdread_one $UTRACKNUM $FIRSTTRACK
1968 fi
1969 else
1970 for UTRACKNUM in $TRACKQUEUE
1971 do
1972 if [ "$DOREAD" = "y" ]; then
1973 if checkstatus readtrack-$UTRACKNUM; then :; else
1974 do_cdread $UTRACKNUM
1975 if [ "$?" != "0" ]; then
1976 # CD read failed - don't give the goahead to
1977 # the encoder
1978 echo NO
1979 exit
1980 fi
1981 fi
1982 fi
1983 if [ "$BATCH" = "y" ]; then
1984 :
1985 else
1986 echo NEXTTRACK # Get the encoder machine churning again
1987 if [ "$DOREAD" = "y" ]; then
1988 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
1989 until checkstatus encodetrack-$UTRACKNUM
1990 do
1991 if checkerrors encodetrack-$UTRACKNUM; then
1992 break
1993 fi
1994 sleep 2
1995 done
1996 fi
1997 fi
1998 fi
1999 done
2000 fi
2001
2002 # Now that we're done the encoding can be loud again -
2003 # if we're not using SMP.
2004 if [ "$MAXPROCS" = "1" ]; then
2005 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
2006 fi
2007
2008 # All tracks read, start encoding.
2009 if [ "$BATCH" = "y" ] || [ "$ONETRACK" = "y" ]; then
2010 echo NEXTTRACK
2011 fi
2012
2013 # We are now finished with the cdrom - it can be safely ejected. Note that
2014 # abcde will not have completed yet.
2015 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
2016 # We check if the disk we are processing is actually the disk inside the
2017 # CD tray. If not, we do not eject the CD, since it might be so that the
2018 # user ejected it manually.
2019 #CURRENTTRACKINFO=$($CDDISCID $CDROM)
2020 #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
2021 # More FreeBSD bits.
2022 if [ X"$(uname)" = X"FreeBSD" ] ; then
2023 # FreeBSD eject uses the EJECT environment variable to name the CDROM
2024 # but in this script EJECT is in the envionment and names the program
2025 eject=$EJECT
2026 unset EJECT
2027 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
2028 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
2029 $eject $EJECTOPTS $cd
2030 elif [ X"$(uname)" = X"Darwin" ] ; then
2031 disktool -e ${CDROM#/dev/} 0
2032 else
2033 $EJECT $EJECTOPTS $CDROM
2034 fi
2035 #fi
2036 fi
2037
2038 ) | (
2039
2040 # In batch mode, we want all tracks to be read first.
2041 if [ "$BATCH" = "y" ]; then
2042 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
2043 if [ "$GOAHEAD" = "NO" ]; then break; fi
2044 for LASTTRACK in $TRACKQUEUE; do :; done
2045 if checkstatus readtrack-$LASTTRACK; then
2046 if [ "$DONORMALIZE" = "y" ]; then
2047 if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
2048 if checkerrors batch-normalize; then exit; fi
2049 fi
2050 if [ "$DOENCODE" = "y" ]; then
2051 if checkstatus encodetrack-$LASTTRACK; then :; else do_batch_encode; fi
2052 if checkerrors batch-encode; then exit; fi
2053 fi
2054 fi
2055 fi
2056
2057 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
2058 if [ "$ONETRACK" = "y" ] ; then
2059 FIRSTTRACK=$( echo $TRACKQUEUE | awk '{print $1}')
2060 TRACKQUEUE=$FIRSTTRACK
2061 TRACKS="$FIRSTTRACK"
2062 fi
2063
2064 # Do the encoding, including parallelization of remote encoding
2065 # Figure out where each track is going to be encoded
2066 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
2067 if [ "$MAXPROCS" != "0" ]; then
2068 for NUM in $(f_seq_row 1 "$MAXPROCS")
2069 do
2070 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
2071 done
2072 fi
2073 # Strip whitespace
2074 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
2075 for UTRACKNUM in $TRACKQUEUE
2076 do
2077 # Wait for our cue
2078 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
2079 if [ "$GOAHEAD" = "NO" ]; then break; fi
2080 # find out where this track is to be encoded
2081 if [ "$DOENCODE" = "y" ]; then
2082 # Make sure we have a place to encode this, if not, exit stage right
2083 if [ -z "$ENCODELOCATIONS" ]; then
2084 continue
2085 fi
2086 PROCEED=
2087 until [ $PROCEED ]
2088 do
2089 for LOCATION in $ENCODELOCATIONS
2090 do
2091 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
2092 # check first if a track has ever been assigned to this location
2093 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
2094 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
2095 if checkerrors encodetrack-$PREVIOUSTRACK; then
2096 for TEMPLOCATION in $ENCODELOCATIONS
2097 do
2098 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
2099 TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
2100 fi
2101 done
2102 ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
2103 ABORT=y
2104 PROCEED=y
2105 break
2106 fi
2107 # We're still here, this location must have been previously assigned,
2108 # and last completed without error - check if it's done with the
2109 # previous track yet
2110 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
2111 done
2112 # all locations are working, wait and try again later
2113 if [ ! $PROCEED ]; then sleep 3; fi
2114 done
2115 # Record the location we're about to encode the next track at
2116 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
2117 fi
2118 # Don't proceed with the rest of the loop if we can't encode
2119 if [ "$ABORT" ]; then continue; fi
2120 # Set TRACKNUM, TRACKNAME
2121 if [ -e "$CDDBDATA" ]; then
2122 if [ "$ONETRACK" = "y" ]; then
2123 TRACKNAME="$DALBUM"
2124 TRACKNUM="$FIRSTTRACK"
2125 splitvarious
2126 else
2127 # TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${UTRACKNUM} + 0))
2128 TRACKNUM=$UTRACKNUM
2129 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2130 TRACKNAME=$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2 -d= | tr -d \[:cntrl:\])
2131 splitvarious
2132 fi
2133 fi
2134 # You can't encode a file which needs to be normalized before finishing
2135 # You can't tag a file before it's finished encoding -
2136 # thus all of this is backgrounded together
2137 (
2138 if [ "$DONORMALIZE" = "y" ]; then
2139 if checkstatus readtrack-$UTRACKNUM; then
2140 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
2141 fi
2142 fi
2143 if [ "$DOENCODE" = "y" ]; then
2144 if checkstatus readtrack-$UTRACKNUM; then
2145 #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
2146 if [ "$DONORMALIZE" = "y" ]; then
2147 if checkstatus normalizetrack-$UTRACKNUM; then
2148 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
2149 fi
2150 else
2151 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
2152 fi
2153 fi
2154 fi
2155 if [ "$DOTAG" = "y" ]; then
2156 if checkstatus encodetrack-$UTRACKNUM; then
2157 if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
2158 fi
2159 fi
2160 if [ "$DOMOVE" = "y" ]; then
2161 if checkstatus tagtrack-$UTRACKNUM; then
2162 if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
2163 fi
2164 fi
2165 ) &
2166 done
2167 # Go through it again and make sure there's no distmp3 stragglers, otherwise
2168 # we'll delete the files they're working on
2169 if [ "$DOENCODE" = "y" ]; then
2170 PROCEED=
2171 until [ $PROCEED ]
2172 do
2173 PROCEED=y
2174 for LOCATION in $ENCODELOCATIONS
2175 do
2176 CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
2177 # "How can he give us a status update, if he's DEAD?"
2178 if checkstatus encodetrack-$CHECKTRACK; then
2179 continue
2180 fi
2181 # Nothing to see here please go quietly back to your homes
2182 if [ -z "$CHECKTRACK" ]; then continue; fi
2183 # You're still here? Maybe there is something...
2184 if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
2185 done
2186 # hold up
2187 if [ ! $PROCEED ]; then sleep 5; fi
2188 done
2189 fi
2190 # If the above didn't catch the stragglers, this will
2191 wait
2192 # Check to see if run_command logged any errors
2193 if [ -f "$ABCDETEMPDIR/errors" ]; then
2194 echo "The following commands failed to run:"
2195 cat "$ABCDETEMPDIR/errors"
2196 # Don't clean up
2197 DOCLEAN=n
2198 fi
2199 if [ "$KEEPWAVS" = "y" ];then
2200 # Don't clean up
2201 DOCLEAN=n
2202 fi
2203 if [ "$DOCLEAN" = "y" ]; then
2204 # Wipe all the evidence
2205 # Gimme gimme gimme some more time!
2206 sleep 5
2207 rm -rf "$ABCDETEMPDIR"
2208 echo "Finished."
2209 else
2210 echo "Finished. Not cleaning $ABCDETEMPDIR."
2211 fi
2212 )
2213 exit 0