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.
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.
11 # Copyright for this work is to expire January 1, 2010, after which it
12 # shall be public domain.
18 echo "This is abcde v$VERSION."
19 echo "Usage: abcde [options] [tracks]"
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."
52 # Funtions to replace the need of seq, which is too distribution dependant.
56 while [ $i -ne `expr $2 + 1` ]
66 while [ $i -ne `expr $2 + 1` ]
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 "".
80 # Take the last line in the status file if there's multiple matches
82 BLURB
=$
(egrep $PATTERN "$ABCDETEMPDIR/status" |
tail -n 1)
84 if [ -z "$BLURB" ]; then
89 # See if there's a = in it
90 if [ "$(echo $BLURB | grep -c =)" != "0" ]; then
91 echo "$(echo $BLURB | cut -f2- -d=)"
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 "".
104 if [ ! -e "$ABCDETEMPDIR/errors" ]; then
107 # Take the last line in the status file if there's multiple matches
109 BLURB
="$(egrep $PATTERN $ABCDETEMPDIR/errors | tail -n 1)"
111 if [ -z "$BLURB" ]; then
112 # negative, we did not have a negative...
115 # affirmative, we had a negative...
120 # run_command [blurb] [command...]
121 # Runs a command, silently if necessary, and updates the status file
126 # See if this is supposed to be silent
127 if [ "$(checkstatus encode-output)" = "loud" ]; then
131 # Special case for SMP, since
132 # encoder output is never displayed, don't mute echos
133 if [ -z "$BLURB" -a "$MAXPROCS" != "1" ]; then
143 if [ "$RETURN" = "2" ]; then
144 # File was already normalized.
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
157 echo "${TWEAK}returned code $RETURN: $@" >> "$ABCDETEMPDIR/errors"
158 return $RETURN # Do not pass go, do not update the status file
160 if [ "$BLURB" ]; then
161 echo $BLURB >> "$ABCDETEMPDIR/status"
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
168 # Function to determine if a word contains a slash.
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
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 /
194 /*) ;; # No processing is needed for absolute paths
196 # Loop through common prefixes, ignoring them.
197 while slash
"$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
199 FR
="$(echo "$FR" | cut -d/ -f2-)"
200 TO
="$(echo "$TO" | cut -d/ -f2-)"
202 # Loop through directory portions left in FR, adding appropriate ../s.
205 FR
="$(echo "$FR" | cut -d/ -f2-)"
213 # This code splits the a Various Artist track name from one of the following
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)
224 # VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
227 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
228 case "$VARIOUSARTISTSTYLE" in
230 DTITLEARTIST
="$(echo $TRACKNAME | sed 's- / -~-g')"
231 TRACKARTIST
="$(echo $DTITLEARTIST | cut -f1 -d~)"
232 TRACKNAME
="$(echo $DTITLEARTIST | cut -f2 -d~)"
235 DTITLEARTIST
="$(echo $TRACKNAME | sed 's, - ,~,g')"
236 TRACKARTIST
="$(echo $DTITLEARTIST | cut -f1 -d~)"
237 TRACKNAME
="$(echo $DTITLEARTIST | cut -f2 -d~)"
240 DTITLEARTIST
="$(echo $TRACKNAME | sed 's- / -~-g')"
241 TRACKARTIST
="$(echo $DTITLEARTIST | cut -f2 -d~)"
242 TRACKNAME
="$(echo $DTITLEARTIST | cut -f1 -d~)"
245 DTITLEARTIST
="$(echo $TRACKNAME | sed 's, - ,~,g')"
246 TRACKARTIST
="$(echo $DTITLEARTIST | cut -f2 -d~)"
247 TRACKNAME
="$(echo $DTITLEARTIST | cut -f1 -d~)"
250 DTITLEARTIST
="$(echo $TRACKNAME | sed 's-: -~-g')"
251 TRACKARTIST
="$(echo $DTITLEARTIST | cut -f1 -d~)"
252 TRACKNAME
="$(echo $DTITLEARTIST | cut -f2 -d~)"
255 DTITLEARTIST
="$(echo $TRACKNAME | sed 's,^\(.*\) (\(.*\)),\1~\2,')"
256 TRACKARTIST
="$(echo $DTITLEARTIST | cut -f2 -d~)"
257 TRACKNAME
="$(echo $DTITLEARTIST | cut -f1 -d~)"
260 elif [ "$ONETRACK" = "y" ]; then
261 TRACKARTIST
="Various"
267 # do_tag [tracknumber]
268 # id3 tags a filename
270 # TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC,
271 # COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE (and temporarily) ID3TAGV
274 COMMENTOUTPUT
="$(eval echo ${COMMENT})"
275 run_command
'' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
276 for OUTPUT
in $
(echo $OUTPUTTYPE |
tr , \
)
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"
286 case "$OGGENCODERSYNTAX" in
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"
293 # These are from http://www.xiph.org/ogg/vorbis/doc/v-comment.html
294 echo ARTIST
="$TRACKARTIST"
296 echo TITLE
="$TRACKNAME"
297 if [ -n "$CDYEAR" ]; then
300 if [ -n "$CDGENRE" ]; then
301 echo GENRE
="$CDGENRE"
304 if [ "$(eval echo ${COMMENT})" != "" ]; then
305 case "$COMMENTOUTPUT" in
306 *=*) echo "$COMMENTOUTPUT";;
307 *) echo COMMENT
="$COMMENTOUTPUT";;
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"
316 mv "$ABCDETEMPDIR/track$1.uncommented.$OUTPUT" "$ABCDETEMPDIR/track$1.$OUTPUT"
323 echo ARTIST
="$TRACKARTIST"
325 echo TITLE
="$TRACKNAME"
326 if [ -n "$CDYEAR" ]; then
329 if [ -n "$CDGENRE" ]; then
330 echo GENRE
="$CDGENRE"
332 if [ "$(eval echo ${COMMENT})" != "" ]; then
333 case "$COMMENTOUTPUT" in
334 *=*) echo "$COMMENTOUTPUT";;
335 *) echo COMMENT
="$COMMENTOUTPUT";;
339 ) | run_command tagtrack-
$1 $METAFLAC --import-vc-from=- --no-utf8-convert "$ABCDETEMPDIR/track$1.$OUTPUT"
342 run_command tagtrack-
$1 true
350 # OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
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" )
358 case "$MP3ENCODERSYNTAX" in
363 for UTRACKNUM
in $TRACKQUEUE
365 TRACKFILES
="$TRACKFILES track$UTRACKNUM.wav"
367 nice
$ENCNICE $MP3ENCODER $MP3ENCODEROPTS --nogap $TRACKFILES
369 if [ "$RETURN" != "0" ]; then
370 echo "batch-encode: $ENCODER returned code $RETURN" >> errors
372 for UTRACKNUM
in $TRACKQUEUE
374 echo encodetrack-
$UTRACKNUM >> status
382 # Other encoders fall through to normal encoding as the tracks
383 # have not been entered in the status file.
386 # do_encode [tracknumber] [hostname]
387 # If no hostname is specified, encode locally
389 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
392 IN
="$ABCDETEMPDIR/track$1.wav"
393 # We need IN to proceed.
394 if [ -s "$IN" ] ; then
395 for OUTPUT
in $
(echo $OUTPUTTYPE |
tr , \
)
397 OUT
="$ABCDETEMPDIR/track$1.$OUTPUT"
398 run_command
'' echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
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 ;;
411 run_command encodetrack-
$OUTPUT-$1 nice
$DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev
/null
2>&1
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" ;;
424 run_command encodetrack-
$OUTPUT-$1 nice
$DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev
/null
2>&1
432 case "$FLACENCODERSYNTAX" in
433 flac
) run_command encodetrack-
$OUTPUT-$1 nice
$ENCNICE $FLACENCODER $FLACENCODEROPTS -o "$OUT" "$IN" ;;
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
445 if [ "$(eval echo ${COMMENT})" != "" ]; then
448 *) COMMENT
="COMMENT=$COMMENT" ;;
450 COMMENT
="--comment \"$COMMENT\""
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"
456 run_command encodetrack-
$OUTPUT-$1 nice
$ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
461 # Only remove .wav if the encoding succeeded
462 if checkerrors
"encodetrack-(.{3,4})-$1"; then
463 run_command encodetrack-
$1 false
465 run_command encodetrack-
$1 true
466 if [ ! "$KEEPWAVS" = "y" ] ; then
471 if [ "$(checkstatus encode-output)" = "loud" ]; then
472 echo "HEH! The file we were about to encode disappeared:"
475 run_command encodetrack-
$1 false
481 # NORMALIZER, NORMALIZEROPTS
482 do_batch_normalize
()
484 # The commands here don't go through run_command because they're never supposed to be silenced
485 echo "Batch normalizing tracks: $TRACKQUEUE"
490 for UTRACKNUM
in $TRACKQUEUE
492 TRACKFILES
="$TRACKFILES track$UTRACKNUM.wav"
494 # XXX: Hard-coded batch option!
495 $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
497 if [ "$RETURN" != "0" ]; then
498 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
500 for UTRACKNUM
in $TRACKQUEUE
502 echo normalizetrack-
$UTRACKNUM >> status
508 # do_normalize [tracknumber]
510 # TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
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"
518 if [ "$(checkstatus encode-output)" = "loud" ]; then
519 echo "HEH! The file we were about to normalize disappeared:"
522 run_command normalizetrack-
$1 false
"File $IN was not found"
526 # do_move [tracknumber]
527 # Deduces the outfile from environment variables
528 # Creates directory if necessary
530 # TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, OUTPUTDIR
533 for OUTPUT
in $
(echo $OUTPUTTYPE |
tr , \
)
535 # Create ALBUMFILE, ARTISTFILE, TRACKFILE
536 # Munge filenames as follows:
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)
550 OUTPUTFILE
=$
(eval echo $OUTPUTFORMAT)
553 TRACKNUM
=${UTRACKNUM}
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"
564 # Create the playlist if wanted
566 # PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
567 # VARIOUSARTISTS, OUTPUTDIR
570 for OUTPUT
in $
(echo $OUTPUTTYPE |
tr , \
)
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)
581 PLAYLISTFILE
=$
(eval echo $PLAYLISTFORMAT)
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
593 [ "$ERASEPLAYLIST" != "n" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE"
595 touch "$OUTPUTDIR/$PLAYLISTFILE"
596 for UTRACKNUM
in $TRACKQUEUE
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
:\
])
602 TRACKFILE
=$
(mungefilename
"$TRACKNAME")
603 ARTISTFILE
=$
(mungefilename
"$TRACKARTIST")
604 TRACKNUM
=${UTRACKNUM}
605 if [ "$VARIOUSARTISTS" = "y" ]; then
606 OUTPUTFILE
=$
(eval echo $VAOUTPUTFORMAT)
608 OUTPUTFILE
=$
(eval echo $OUTPUTFORMAT)
610 if [ "$VARIOUSARTISTS" = "y" ]; then
611 if [ "$VAPLAYLISTDATAPREFIX" ] ; then
612 echo ${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.
$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
614 relpath
"$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
617 if [ "$PLAYLISTDATAPREFIX" ]; then
618 echo ${PLAYLISTDATAPREFIX}$OUTPUTFILE.
$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
620 relpath
"$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
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"
630 echo "playlistcomplete" >> "$ABCDETEMPDIR/status"
635 # This essentially the start of things
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
648 TRACKINFO
=$
(cat "$WAVOUTPUTDIR/abcde.$DISCID/discid")
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
655 # get the number of digits to pad TRACKNUM with - we'll use this later
656 if [ "$PADTRACKS" = "y" ] ; then
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 ' ')
666 TRACKS
=$
(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
668 while [ "$X" -ne "$TRACKS" ]
670 X
=$
(printf "%0.${TRACKNUMPADDING}d" $
(expr $X + 1))
671 TRACKQUEUE
=$
(echo "$TRACKQUEUE" $X)
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 ' ')
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)
688 TRACKQUEUE
=$PADTRACKQUEUE
689 echo Grabbing tracks
: "$TRACKQUEUE"
692 # for LASTTRACK in $TRACKQUEUE; do :; done
694 QUEUEDTRACKS
=$
(echo $TRACKQUEUE |
wc -w |
tr -d ' ')
696 # We have the discid, create a temp directory after it to store all the temp
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
707 echo "abcde: file $ABCDETEMPDIR already exists and does not belong to abcde." >&2
708 echo "Please investigate, remove it, and rerun abcde." >&2
712 # It's a directory, let's see if it's owned by us
713 if [ ! -O "$ABCDETEMPDIR" ]; then
714 # Nope, complain and exit
716 echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
717 echo "Please investigate, remove it, and rerun abcde." >&2
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
732 if [ "$ANSWER" != "y" ]; then
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
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"
751 # Remove old error messages
752 if [ -f "$ABCDETEMPDIR/errors" ]; then
753 rm -f "$ABCDETEMPDIR/errors"
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
764 cat /dev
/null
> "$ABCDETEMPDIR/status"
767 # Create the discid file
768 echo "$TRACKINFO" > "$ABCDETEMPDIR/discid"
770 # Determine what actions are to be done from $ACTIONS and set the
771 # following environment variables for them:
783 for ACTION
in $
(echo $ACTIONS |
tr , \
)
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
;;
801 # Parses a CDDB file and outputs the title and the track names.
802 # Variables: CDDBFILE
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..."
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)
814 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
820 # Check for a local CDDB file, and report success
823 if checkstatus cddb-readcomplete
&& checkstatus cddb-choice
>/dev
/null
; then :; else
826 CDDBDISCID
=$
(echo $TRACKINFO | cut
-d' ' -f1)
827 CDDBLOCALFILE
="${CDDBLOCALDIR}/${CDDBDISCID}"
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
838 while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
839 echo -n 'Invalid selection. Please answer "y" or "n": '
842 [ x
"$USELOCALRESP" = "x" ] && USELOCALRESP
="y"
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"
855 #echo "Not using local copy of CDDB data"
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
872 echo 503 > "$ABCDETEMPDIR/cddbstat"
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 `.')
885 501|
*) # 501 Illegal CDDB protocol level: <n>.
886 CDDBPROTO
=`expr $CDDBPROTO - 1`
890 if test $rc -eq 1; then
894 echo cddb-statcomplete
>> "$ABCDETEMPDIR/status"
902 CDDBDISCID
=$
(echo $TRACKINFO | cut
-d' ' -f1)
903 CDDBLOCALFILE
="${CDDBLOCALDIR}/${CDDBDISCID}"
905 # Perform CDDB query if it hasn't already been done
906 if checkstatus cddb-querycomplete
; then :; else
907 if [ "$CDDBAVAIL" = "n" ]; then
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.
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"
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"
930 *) # strange and unknown error
931 echo ERRORCODE
=$ERRORCODE
932 echo "abcde: $CDDBTOOL returned unknown error code"
936 echo cddb-querycomplete
>> "$ABCDETEMPDIR/status"
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
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"
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)
967 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread
.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
969 echo >> "$ABCDETEMPDIR/cddbchoices"
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" ;;
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"
982 for TRACK
in $
(f_seq_row
1 $TRACKS)
984 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread
.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
986 echo >> "$ABCDETEMPDIR/cddbchoices"
987 echo cddb-read-1-complete
>> "$ABCDETEMPDIR/status"
988 echo cddb-choice
=1 >> "$ABCDETEMPDIR/status"
991 # Multiple exact, (possibly multiple) inexact matches
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"
999 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
1001 #echo -n "Retrieving multiple matches... "
1002 grep -v ^
[.
]$
"$ABCDETEMPDIR/cddbquery" |
( X
=0
1003 read DISCINFO
# eat top line
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"
1011 # List out disc title/author and contents
1012 echo \
#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
1013 for TRACK
in $
(f_seq_row
1 $TRACKS)
1015 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.
$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1017 echo >> "$ABCDETEMPDIR/cddbchoices"
1020 CDDBCHOICES
=$
(expr $
(cat "$ABCDETEMPDIR/cddbquery" |
wc -l) - 2)
1024 for TRACK
in $
(f_seq_row
1 $TRACKS)
1026 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread
.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1028 echo >> "$ABCDETEMPDIR/cddbchoices"
1029 echo cddb-read-1-complete
>> "$ABCDETEMPDIR/status"
1030 echo cddb-choice
=1 >> "$ABCDETEMPDIR/status"
1033 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
1040 if checkstatus cddb-edit
>/dev
/null
; then
1041 CDDBDATA
="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1042 VARIOUSARTISTS
="$(checkstatus variousartists)"
1043 VARIOUSARTISTSTYLE
="$(checkstatus variousartiststyle)"
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" ;;
1059 echo "Selected: #$CHOICE"
1060 do_cddbparse
"$ABCDETEMPDIR/cddbread.$CHOICE"
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"
1081 # No bananas, just cat the thing
1082 cat "$ABCDETEMPDIR/cddbchoices" >&2
1085 # It's all going to fit in one page, cat it
1086 cat "$ABCDETEMPDIR/cddbchoices" >&2
1089 # I'll take CDDB read #3 for $400, Alex
1090 echo -n "Which entry would you like abcde to use? [1-$CDDBCHOICES]: " >&2
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
1098 CDCHOICENUM
=$
(echo $CDDBCHOICE |
xargs printf %d
2>/dev
/null
)
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"
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" ;;
1118 echo "Selected: #$CHOICE"
1119 do_cddbparse
"$ABCDETEMPDIR/cddbread.$CHOICE"
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"
1138 if [ ! -z "$PREVIOUSCHOICE" ] ; then
1139 CDCHOICENUM
=$PREVIOUSCHOICE
1142 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1144 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= $ABCDETEMPDIR/cddbread.$CDCHOICENUM | cut -f2- -d= | tr -d \\r\\n))" >&2
1149 if checkstatus cddb-choice
>/dev
/null
; then :; else
1150 echo "abcde: internal error: cddb-choice not recorded." >&2
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
1159 [ "$EDITCDDB" != "n" ] && EDITCDDB
=y
1168 if [ "$EDITCDDB" = "y" ]; then
1169 CDDBDATAMD5SUM
=$
($MD5SUM "$CDDBDATA" | cut
-d " " -f 1);
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"
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"
1192 echo "No editor available. Check your EDITOR environment variable." >&2
1194 # delete editor backup file if it exists
1195 if [ -w "$CDDBDATA~" ]; then
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
1206 echo -n "Is the CD multi-artist? [y/n] (n): " >&2
1207 if [ "$INTERACTIVE" = "y" ]; then
1214 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
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
1222 elif [ "$(grep -c "^TTITLE.
*\
-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1223 # More than 1/2 contain a "-", so guess forward-dash
1225 elif [ "$(grep -c "^TTITLE.
*(.
*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
1226 # More than 1/2 contain something in parens, so guess trailing-paren
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
1241 echo $DEFAULTSTYLE >&2
1242 VARIOUSARTISTSTYLE
=$DEFAULTSTYLE
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
)
1252 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
1253 VARIOUSARTISTSTYLE
=$DEFAULTSTYLE
1255 echo "Selected: $VARIOUSARTISTSTYLE"
1256 case "$VARIOUSARTISTSTYLE" in
1258 VARIOUSARTISTSTYLE
=forward
1261 VARIOUSARTISTSTYLE
=forward-dash
1264 VARIOUSARTISTSTYLE
=reverse
1267 VARIOUSARTISTSTYLE
=reverse-dash
1270 VARIOUSARTISTSTYLE
=colon
1273 VARIOUSARTISTSTYLE
=trailing-paren
1281 echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
1282 echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
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
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): "
1299 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
1300 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
1302 echo -n 'Invalid selection. Please answer "y" or "n": '
1305 if [ "$YESNO" = "y" ] ||
[ "$YESNO" = "Y" ]; then
1306 echo -n "Sending..."
1307 $CDDBTOOL send
"$CDDBDATA" $CDDBSUBMIT
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)
1320 echo "cddb-edit" >> "$ABCDETEMPDIR/status"
1323 # do_cdread_one [lasttrack] [firsttrack]
1325 # Reads the CD in a single track. Live performances, concerts, mixes,... benefit from this.
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
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 ;;
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"
1345 if [ "$CDROMID" = "" ]; then
1346 CDDA2WAVCDROM
="$CDROM"
1348 CDDA2WAVCDROM
="$CDROMID"
1351 nice
$READNICE $CDROMREADER -D $CDDA2WAVCDROM -t 1+$LASTTRACKNUM "$WAVDATA" >&2
1353 dagrab
) nice
$READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
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
1365 debug
) nice
$READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
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"
1374 echo readtrack-
$FIRSTTRACKNUMBER >> "$ABCDETEMPDIR/status"
1378 # do_cdread [tracknumber]
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
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
1392 echo "Grabbing track $UTRACKNUM..." >&2
1394 case "$CDROMREADERSYNTAX" in
1395 cdparanoia
) nice
$READNICE $CDROMREADER -d $CDROM $UTRACKNUM "$WAVDATA" >&2 ;;
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"
1405 if [ "$CDROMID" = "" ]; then
1406 CDDA2WAVCDROM
="$CDROM"
1408 CDDA2WAVCDROM
="$CDROMID"
1411 nice
$READNICE $CDROMREADER -D $CDDA2WAVCDROM -t $UTRACKNUM "$WAVDATA" >&2
1413 dagrab
) nice
$READNICE $CDROMREADER -d $CDROM -f $WAVDATA -v $UTRACKNUM >&2 ;;
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
1425 debug
) nice
$READNICE $CDROMREADER -d $CDROM -w $UTRACKNUM-[:1] "$WAVDATA" >&2 ;;
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"
1434 echo readtrack-
$UTRACKNUM >> "$ABCDETEMPDIR/status"
1440 if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev
/null
; then
1441 vecho
"Setting CD speed to ${CDSPEEDVALUE}x"
1443 echo "abcde: unable to set the device speed" >&2
1449 # vecho outputs a message if EXTRAVERBOSE is selected
1452 if [ x
"$EXTRAVERBOSE" != "x" ]; then
1457 # Start of execution
1460 CDDBURL
="http://freedb.freedb.org/~cddb/cddb.cgi"
1461 CDDBSUBMIT
=freedb-submit@freedb.org
1463 HELLOINFO
="$(whoami)@$(hostname)"
1465 CDROMREADERSYNTAX
=cdparanoia
1467 ENCODERSYNTAX
=default
1469 MP3ENCODERSYNTAX
=default
1470 OGGENCODERSYNTAX
=default
1471 FLACENCODERSYNTAX
=default
1472 SPEEXENCODERSYNTAX
=default
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
=''
1491 VARIOUSARTISTSTYLE
=forward
1492 NORMALIZERSYNTAX
=default
1496 CDDBLOCALDIR
="$HOME/.cddb"
1499 # If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
1500 # i.e. CDROMID="1,0,0"
1503 # program paths - defaults to checking your $PATH
1509 XINGMP3ENC
=xingmp3enc
1521 CDPARANOIA
=cdparanoia
1530 VORBISCOMMENT
=vorbiscomment
1535 # Options for programs called from abcde
1564 # Default to one process if -j isn't specified
1567 # List of actions to perform - by default, run to completion
1568 ACTIONS
=cddb
,read,encode
,tag
,move
,clean
1570 # User-redefinable functions
1571 # Custom filename munging:
1574 echo "$@" |
sed s
,:,\
-,g |
tr \
/ __ |
tr -d \'\"\?\
[:cntrl
:\
]
1577 # Pre-read execution:
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
1589 elif [ X$
(uname
) = "XDarwin" ] ; then
1592 # We should have disktool in OSX, but let's be sure...
1594 elif [ X$
(uname
) = "XOpenBSD" ] ; then
1601 # If CDDBAVAIL is set to n, no CDDB read is done
1602 # If USEID3 is set to n, no ID3 tagging is done
1606 if [ -z "$OUTPUTDIR" ]; then
1610 if [ -z "$WAVOUTPUTDIR" ]; then
1611 WAVOUTPUTDIR
="$OUTPUTDIR"
1614 # Load system defaults
1615 if [ -r /etc
/abcde.conf
]; then
1618 # Load user preference defaults
1619 if [ -r $HOME/.abcde.conf
]; then
1623 # By this time, we need some HTTPGETOPTS already defined.
1624 # If the user has defined its own, we should not be empty.
1626 if [ "$HTTPGETOPTS" = "" ] ; then
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 ;;
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
1643 elif [ -e /dev
/cd0c
]; then
1645 elif [ -e /dev
/acd0c
]; then
1647 elif [ -e /dev
/disk1
]; then
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
1657 a
) ACTIONS
="$OPTARG" ;;
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" ;;
1664 f
) FORCECDDBUSELOCAL
=y
;;
1666 j
) MAXPROCS
="$OPTARG" ;;
1669 L
) CDDBUSELOCAL
="y" ;;
1671 N
) INTERACTIVE
="n" ;;
1673 o
) OUTPUTTYPE
="$OPTARG" ;;
1675 r
) REMOTEHOSTS
="$OPTARG" ;;
1676 s
) STARTTRACKNUMBER
="$OPTARG" ;;
1677 S
) CDSPEEDVALUE
="$OPTARG" ;;
1678 t
) PREPROCESSFORMATS
="$OPTARG"
1680 T
) POSTPROCESSFORMATS
="$OPTARG" ;;
1682 echo "This is abcde v$VERSION."
1683 echo "Usage: abcde [options] [tracks]"
1684 echo "abcde -h for extra help"
1687 V
) EXTRAVERBOSE
="y" ;;
1693 shift $
(($OPTIND - 1))
1695 if [ "$ONETRACK" = "y" ] ; then
1696 if [ $# -gt 0 ]; then
1697 vecho
"ONETRACK mode selected: grabbing all tracks..."
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
1707 NEWTRACKS
=$
(f_seq_line
$RSTART $REND)
1709 TRACKQUEUE
=$
(echo "$TRACKQUEUE" "$NEWTRACKS")
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"
1725 elif [ ! -e $CDROM ] ; then
1726 echo "abcde error: CDROM device cannot be found." >&2
1730 echo "abcde error: CDROM has not been defined or cannot be found" >&2
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"
1740 if [ "$BATCH" = "y" ]; then
1741 echo "abcde error: BATCH mode is not compatible with ONETRACK mode"
1745 # Decide which CDROM reader we're gonna use
1746 case "$CDROMREADERSYNTAX" in
1748 CDROMREADER
="$CDPARANOIA"
1749 CDROMREADEROPTS
="$CDPARANOIAOPTS"
1752 CDROMREADER
="$CDDA2WAV"
1753 CDROMREADEROPTS
="$CDDA2WAVOPTS"
1756 CDROMREADER
="$DAGRAB"
1757 CDROMREADEROPTS
="$DAGRABOPTS"
1760 CDROMREADER
="$CDDAFS"
1761 CDROMREADEROPTS
="$CDDAFSOPTS"
1765 # There's only one normalize...
1766 case "$NORMALIZERSYNTAX" in
1768 NORMALIZER
="$NORMALIZE"
1769 NORMALIZEROPTS
="$NORMALIZEOPTS"
1773 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac for flacs and speexenc for speex
1775 # Getting ready for multiple output changes
1776 for OUTPUT
in $
(echo $OUTPUTTYPE |
tr , \
)
1779 ogg
) [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX
=oggenc
1780 echo $ACTIONS |
grep tag
> /dev
/null
2>&1 && NEEDCOMMENTER
=y
1782 mp3
) [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX
=lame
1783 echo $ACTIONS |
grep tag
> /dev
/null
2>&1 && NEEDTAGGER
=y
1785 flac
) [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX
=flac
1786 echo $ACTIONS |
grep tag
> /dev
/null
2>&1 && NEEDMETAFLAC
=y
1788 spx
) [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX
=speexenc
;;
1789 *) echo "abcde error: Invalid OUTPUTTYPE defined" >&2
1795 # decide which encoder
1796 case "$MP3ENCODERSYNTAX" in
1798 MP3ENCODEROPTS
="$LAMEOPTS"
1802 MP3ENCODEROPTS
="$GOGOOPTS"
1806 MP3ENCODEROPTS
="$BLADEENCOPTS"
1807 MP3ENCODER
="$BLADEENC"
1810 MP3ENCODEROPTS
="$L3ENCOPTS"
1814 MP3ENCODEROPTS
="$XINGMP3ENCOPTS"
1815 MP3ENCODER
="$XINGMP3ENC"
1818 MP3ENCODEROPTS
="$MP3ENCOPTS"
1819 MP3ENCODER
="$MP3ENC"
1822 case "$OGGENCODERSYNTAX" in
1824 OGGENCODEROPTS
="$VORBIZEOPTS"
1825 OGGENCODER
="$VORBIZE"
1828 OGGENCODEROPTS
="$OGGENCOPTS"
1829 OGGENCODER
="$OGGENC"
1832 case "$FLACENCODERSYNTAX" in
1834 FLACENCODEROPTS
="$FLACOPTS"
1838 case "$SPEEXENCODERSYNTAX" in
1840 SPEEXENCODEROPTS
="$SPEEXENCOPTS"
1841 SPEEXENCODER
="$SPEEXENC"
1847 if [ "$ID3TAGV" = "1" ]; then
1849 TAGGEROPTS
="$ID3OPTS"
1852 TAGGEROPTS
="$ID3V2OPTS"
1855 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
1857 if [ "$ENCNICE" ]; then
1858 ENCNICE
="-n $ENCNICE"
1860 if [ "$READNICE" ]; then
1861 READNICE
="-n $READNICE"
1863 if [ "$DISTMP3NICE" ]; then
1864 DISTMP3NICE
="-n $DISTMP3NICE"
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
1873 if [ X
"$CDSPEEDVALUE" != "X" ]; then
1874 case "$CDROMREADERSYNTAX" in
1875 cdparanoia|debug
) CDROMREADEROPTS
="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
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}
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
1894 elif [ ! -x $
(which $X) ]; then
1895 echo "abcde error: $X is not executable." >&2
1900 CDROMREADER
="$CDROMREADER $CDROMREADEROPTS"
1901 CDDBTOOL
="$CDDBTOOL $CDDBTOOLOPTS"
1902 HTTPGET
="$HTTPGET $HTTPGETOPTS"
1904 # One thousand seven hundred lines in, we can start doing stuff with things
1906 # List of valid actions: cddb,playlist,read,normalize,encode,tag,move
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
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... "
1917 pre_read
# Execute the user-defined pre-read funtion. Close the CD with it.
1921 do_discid
# Get ABCDETEMPDIR created and status file initialized
1923 if [ "$DOCDDB" = "y" ]; then
1924 if [ $CDDBUSELOCAL = "y" ]; then
1927 if [ ! "$CDDBLOCALSUCCESS" = "y" ] ; then
1934 eval $
($CDDBTOOL parse
"$CDDBDATA")
1937 # Before reading tracks, we set the speed of the device
1939 if [ X
"$CDSPEEDVALUE" != "X" ]; then
1940 case "$CDROMREADERSYNTAX" in
1941 cdparanoia|debug
) : ;;
1946 # Create playlist if needed (backgroundable) and start reading in tracks
1949 if [ "$ONETRACK" = "y" ]; then :; else
1950 if [ "$DOPLAYLIST" = "y" ]; then
1951 echo Creating playlist...
>&2
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"
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
1970 for UTRACKNUM
in $TRACKQUEUE
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
1983 if [ "$BATCH" = "y" ]; then
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
1991 if checkerrors encodetrack-
$UTRACKNUM; then
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"
2008 # All tracks read, start encoding.
2009 if [ "$BATCH" = "y" ] ||
[ "$ONETRACK" = "y" ]; then
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
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
2033 $EJECT $EJECTOPTS $CDROM
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
2050 if [ "$DOENCODE" = "y" ]; then
2051 if checkstatus encodetrack-
$LASTTRACK; then :; else do_batch_encode
; fi
2052 if checkerrors batch-encode
; then exit; fi
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"
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")
2070 ENCODELOCATIONS
="$ENCODELOCATIONS %local$NUM%"
2074 ENCODELOCATIONS
=$
(echo $ENCODELOCATIONS)
2075 for UTRACKNUM
in $TRACKQUEUE
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
2089 for LOCATION
in $ENCODELOCATIONS
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
2098 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
2099 TEMPENCODELOCATIONS
="$TEMPENCODELOCATIONS $TEMPLOCATION"
2102 ENCODELOCATIONS
=$
(echo $TEMPENCODELOCATIONS)
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
2112 # all locations are working, wait and try again later
2113 if [ ! $PROCEED ]; then sleep 3; fi
2115 # Record the location we're about to encode the next track at
2116 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
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
2124 TRACKNUM
="$FIRSTTRACK"
2127 # TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${UTRACKNUM} + 0))
2129 CDDBTRACKNUM
=$
(expr $UTRACKNUM - 1)
2130 TRACKNAME
=$
(grep ^TTITLE
$CDDBTRACKNUM= "$CDDBDATA" |
head -n 1 | cut
-f2 -d= |
tr -d \
[:cntrl
:\
])
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
2138 if [ "$DONORMALIZE" = "y" ]; then
2139 if checkstatus readtrack-
$UTRACKNUM; then
2140 if checkstatus normalizetrack-
$UTRACKNUM; then :; else do_normalize
$UTRACKNUM; 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
2151 if checkstatus encodetrack-
$UTRACKNUM; then :; else do_encode
$UTRACKNUM $LOCATION $OUTPUT; fi
2155 if [ "$DOTAG" = "y" ]; then
2156 if checkstatus encodetrack-
$UTRACKNUM; then
2157 if checkstatus tagtrack-
$UTRACKNUM; then :; else do_tag
$UTRACKNUM; fi
2160 if [ "$DOMOVE" = "y" ]; then
2161 if checkstatus tagtrack-
$UTRACKNUM; then
2162 if checkstatus movetrack-
$UTRACKNUM; then :; else do_move
$UTRACKNUM; fi
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
2174 for LOCATION
in $ENCODELOCATIONS
2176 CHECKTRACK
="$(checkstatus encodetracklocation-$LOCATION)"
2177 # "How can he give us a status update, if he's DEAD?"
2178 if checkstatus encodetrack-
$CHECKTRACK; then
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
2187 if [ ! $PROCEED ]; then sleep 5; fi
2190 # If the above didn't catch the stragglers, this will
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"
2199 if [ "$KEEPWAVS" = "y" ];then
2203 if [ "$DOCLEAN" = "y" ]; then
2204 # Wipe all the evidence
2205 # Gimme gimme gimme some more time!
2207 rm -rf "$ABCDETEMPDIR"
2210 echo "Finished. Not cleaning $ABCDETEMPDIR."