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