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