* When using Musicbrainz, checksum and only output unique matches for an
[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.3-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 "-m Modify playlist to include CRLF endings, to comply with some players"
47 #echo " WARNING: Deprecated. Use \"cue\" action"
48 #echo "-M Create a CUE file"
49 echo "-n No lookup. Don't query CDDB, just create and use template"
50 echo "-N Noninteractive. Never prompt for anything"
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 ($i)"
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 vvecho "$@"
250 BLURB="$1"
251 shift
252 # See if this is supposed to be silent
253 if [ "$(checkstatus encode-output)" = "loud" ]; then
254 "$@" >&2
255 RETURN=$?
256 else
257 # Special case for SMP, since
258 # encoder output is never displayed, don't mute echos
259 if [ -z "$BLURB" -a "$MAXPROCS" != "1" ]; then
260 "$@" >&2
261 RETURN=$?
262 else
263 "$@" >/dev/null 2>&1
264 RETURN=$?
265 fi
266 fi
267 case "$1" in
268 normalize|normalize-audio)
269 if [ "$RETURN" = "2" ]; then
270 # File was already normalized.
271 RETURN=0
272 fi
273 ;;
274 esac
275 if [ "$RETURN" != "0" ]; then
276 # Put an error in the errors file. For various reasons we
277 # can't capture a copy of the program's output but we can
278 # log what we attempted to execute and the error code
279 # returned by the program.
280 if [ "$BLURB" ]; then
281 TWEAK="$BLURB: "
282 fi
283 echo "${TWEAK}returned code $RETURN: $@" >> "$ABCDETEMPDIR/errors"
284 return $RETURN # Do not pass go, do not update the status file
285 fi
286 if [ "$BLURB" ]; then
287 echo $BLURB >> "$ABCDETEMPDIR/status"
288 fi
289 }
290
291 # relpath() and slash() are Copyright (c) 1999 Stuart Ballard and
292 # distributed under the terms of the GNU GPL v2 or later, at your option
293
294 # Function to determine if a word contains a slash.
295 slash ()
296 {
297 case "$1" in
298 */*) return 0;;
299 *) return 1;;
300 esac
301 }
302
303 # Function to give the relative path from one file to another.
304 # Usage: relpath fromfile tofile
305 # eg relpath music/Artist/Album.m3u music/Artist/Album/Song.mp3
306 # (the result would be Album/Song.mp3)
307 # Output is relative path to $2 from $1 on stdout
308
309 # This code has the following restrictions:
310 # Multiple ////s are not collapsed into single /s, with strange effects.
311 # Absolute paths and ../s are handled wrong in FR (but they work in TO)
312 # If FR is a directory it must have a trailing /
313
314 relpath ()
315 {
316 FR="$1"
317 TO="$2"
318
319 case "$TO" in
320 /*) ;; # No processing is needed for absolute paths
321 *)
322 # Loop through common prefixes, ignoring them.
323 while slash "$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
324 do
325 FR="$(echo "$FR" | cut -d/ -f2-)"
326 TO="$(echo "$TO" | cut -d/ -f2-)"
327 done
328 # Loop through directory portions left in FR, adding appropriate ../s.
329 while slash "$FR"
330 do
331 FR="$(echo "$FR" | cut -d/ -f2-)"
332 TO="../$TO"
333 done
334 ;;
335 esac
336
337 echo $TO
338 }
339
340 new_checkexec ()
341 {
342 if [ ! "$@" = "" ]; then
343 # Cut off any command-line option we added in
344 X=$(echo $@ | cut -d' ' -f2)
345 if [ "$(which $X)" = "" ]; then
346 return 1
347 elif [ ! -x $(which $X) ]; then
348 return 2
349 fi
350 fi
351 return 0
352 }
353
354 checkexec ()
355 {
356 if [ ! "$@" = "" ]; then
357 # Cut off any command-line option we added in
358 X=$(echo $@ | cut -d' ' -f2)
359 # Test for built-in abcde.function
360 [ "$X" != "${X#abcde.}" ] && type $X >/dev/null 2>&1 && return
361 if [ "$(which $X)" = "" ]; then
362 log error "$X is not in your path." >&2
363 log info "Define the full path to the executable if it exists on your system." >&2
364 if [ -e /etc/debian_release ] ; then
365 case $X in
366 oggenc) MISSING_PACKAGE=vorbis-tools ;;
367 lame|flac) MISSING_PACKAGE=$X ;;
368 esac
369 log info "Hint: apt-get install $MISSING_PACKAGE" >&2
370 fi
371 exit 1
372 elif [ ! -x "$(which $X)" ]; then
373 log error "$X is not executable." >&2
374 exit 1
375 fi
376 fi
377 }
378
379 # diffentries <filename> <max_value> <entry1>,<entry2>
380 # max_value: the range of entries goes from 1 to <max_value>
381 diffentries ()
382 {
383 FILENAME=$1
384 shift
385 local CDDBDIFFCHOICES=$1
386 shift
387 local CDDBDIFFCHOICE="$@"
388 if [ ! X"$DIFF" = "X" ]; then
389 PARSECHOICE1=$(echo $CDDBDIFFCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
390 PARSECHOICE2=$(echo $CDDBDIFFCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
391 if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBDIFFCHOICES ] || \
392 [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBDIFFCHOICES ] || \
393 [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then
394 echo "Invalid diff range. Please select two comma-separated numbers between 1 and $CDDBDIFFCHOICES" >&2
395 else
396 # We parse the 2 choices to diff, store them in temporary files and diff them.
397 for PARSECHOICE in $(echo $CDDBDIFFCHOICE | tr , \ ); do
398 do_cddbparse "$ABCDETEMPDIR/$FILENAME.$PARSECHOICE" > "$ABCDETEMPDIR/$FILENAME.parsechoice.$PARSECHOICE"
399 done
400 echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/$FILENAME.diff"
401 $DIFF $DIFFOPTS "$ABCDETEMPDIR/$FILENAME.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/$FILENAME.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/$FILENAME.diff"
402 if [ $(cat "$ABCDETEMPDIR/$FILENAME.diff" | wc -l) -ge 24 ]; then
403 page "$ABCDETEMPDIR/$FILENAME.diff"
404 else
405 cat "$ABCDETEMPDIR/$FILENAME.diff" >&2
406 fi
407 fi
408 else
409 echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBDIFFCHOICES." >&2
410 fi
411 }
412
413 # getcddbinfo
414 # Finds an specific field from cddbinfo
415 getcddbinfo()
416 {
417 case $1 in
418 TRACKNAME1)
419 TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
420 ;;
421 TRACKNAME)
422 TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
423 ;;
424 TRACK-INFO)
425 grep ^EXTT$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\\n/\n/g'
426 ;;
427 esac
428 }
429
430 # gettracknum
431 # Get the track number we are going to use for different actions
432 gettracknum()
433 {
434 if [ -n "$STARTTRACKNUMBER" ] ; then
435 # Get the trackpadding from the current track
436 CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
437 TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - $FIRSTTRACK ))
438 else
439 TRACKNUM=${UTRACKNUM}
440 fi
441 }
442
443 # makeids
444 #
445 # Calculate cddb disc ids without requiring specialized helper programs.
446 # largely copied from cd-discid and musicbrainz examples. some of the steps
447 # don't make sense, but they're necessary to match the ids generated by other
448 # programs.
449 #
450 ## FIXME ## Right now, we get 2 frames more than with cue2discid ??
451 # data@petit:~$ sh /tmp/cue2discid /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac
452 # 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
453 # 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2895
454 # data@petit:~$ metaflac --export-cuesheet-to=- /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac| python /home/data/sources/abcde/trunk/examples/cue2discid
455 # 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2893
456 #
457 # Variables: OFFSETS, TRACKS, LEADOUT, [LEADIN]
458 makeids ()
459 {
460 if [ X"$LEADOUT" = "X" ]; then
461 log warning "Error trying to calculate disc ids without lead-out information."
462 exit 1
463 fi
464
465 # default to a two second lead-in
466 IDMAGICNUM=150
467 LEADIN=${LEADIN:=150}
468
469 # number of cdframes per second
470 CDFRAMES=75
471
472 # reset cddb checksum for cddb disc-id calululation
473 CDDBCKSUM=0
474
475 COOKEDOFFSETS=""
476 for OFFSET in $(echo $OFFSETS)
477 do
478 COOKEDOFFSETS="${COOKEDOFFSETS} $(($OFFSET + $LEADIN))"
479
480 OFFSETTIME=$(( ($OFFSET + $LEADIN) / $CDFRAMES ))
481 while [ $OFFSETTIME -gt 0 ]; do
482 CDDBCKSUM=$(($CDDBCKSUM + $OFFSETTIME % 10))
483 OFFSETTIME=$(($OFFSETTIME / 10))
484 done
485
486 done
487
488 COOKEDOFFSETS="${COOKEDOFFSETS:1}" # eat the leading space
489
490 PREGAP=$(($(echo $OFFSETS | cut -f1 -d' ')))
491 TOTALTIME=$(( (($LEADOUT + $LEADIN + $PREGAP) / $CDFRAMES) - (($LEADIN + $PREGAP) / $CDFRAMES)))
492
493 case "$CDDBMETHOD" in
494 cddb)
495 printf -v DISCID "%08lx" $(( ($CDDBCKSUM % 0xff) << 24 | $TOTALTIME << 8 | $TRACKS))
496 ;;
497 musicbrainz)
498 # FIXME: don't assume the first track is 1
499 echo "dasd: 1 $TRACKS $LEADIN $LEADOUT $OFFSETS "
500 DISCID=$($MUSICBRAINZ --command calcid --discinfo 1 $TRACKS $LEADIN $LEADOUT $OFFSETS)
501 ;;
502 esac
503
504 TRACKINFO="${DISCID} $((TRACKS)) ${COOKEDOFFSETS} $((($LEADOUT + $LEADIN + $IDMAGICNUM) / $CDFRAMES))"
505 }
506
507 do_replaygain()
508 {
509 if checkstatus replaygain; then :; else
510 run_command "" echo "Adding replaygain information..."
511 for TMPOUTPUT in $( echo $OUTPUTTYPE | tr , \ )
512 do
513 case $TMPOUTPUT in
514 vorbis|ogg)
515 OUTPUT=$OGGOUTPUTCONTAINER
516 ;;
517 flac)
518 OUTPUT=$FLACOUTPUTCONTAINER
519 ;;
520 *)
521 OUTPUT=$TMPOUTPUT
522 ;;
523 esac
524 OUTPUTFILES=""
525 REPLAYINDEX=0
526 for UTRACKNUM in $TRACKQUEUE
527 do
528 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
529 getcddbinfo TRACKNAME
530 splitvarious
531 TRACKFILE="$(mungefilename "$TRACKNAME")"
532 ARTISTFILE="$(mungefilename "$TRACKARTIST")"
533 ALBUMFILE="$(mungefilename "$DALBUM")"
534 GENRE="$(mungegenre "$GENRE")"
535 YEAR=${CDYEAR:-$CDYEAR}
536 gettracknum
537 if [ "$ONETRACK" = "y" ]; then
538 if [ "$VARIOUSARTISTS" = "y" ]; then
539 OUTPUTFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\")"
540 else
541 OUTPUTFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\")"
542 fi
543 else
544 if [ "$VARIOUSARTISTS" = "y" ]; then
545 OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT"\")"
546 else
547 OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT"\")"
548 fi
549 fi
550 OUTPUTFILES[$REPLAYINDEX]="$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
551 (( REPLAYINDEX = $REPLAYINDEX + 1 ))
552 done
553 case "$OUTPUT" in
554 flac)
555 run_command replaygain-flac nice $ENCNICE $METAFLAC $FLACGAINOPTS "${OUTPUTFILES[@]}"
556 #run_command replaygain-flac true
557 ;;
558 vorbis|ogg)
559 run_command replaygain-vorbis nice $ENCNICE $VORBISGAIN $VORBISGAINOPTS "${OUTPUTFILES[@]}"
560 ;;
561 mp3)
562 run_command replaygain-mp3 nice $ENCNICE $MP3GAIN $MP3GAINOPTS "${OUTPUTFILES[@]}"
563 ;;
564 mpc)
565 run_command replaygain-mpc nice $ENCNICE $MPPGAIN --auto "${OUTPUTFILES[@]}"
566 ;;
567 *);;
568 esac
569 done
570 if checkerrors "replaygain-.{3,6}"; then :; else
571 run_command replaygain true
572 fi
573 fi
574 }
575
576 # This code splits the a Various Artist track name from one of the following
577 # forms:
578 #
579 # forward: Artist / Track
580 # forward-dash: Artist - Track
581 # reverse: Track / Artist
582 # reverse-dash: Track - Artist
583 # colon: Artist: Track
584 # trailing-paren: Artist (Track)
585 #
586 # variables used:
587 # VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
588 splitvarious ()
589 {
590 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
591 case "$VARIOUSARTISTSTYLE" in
592 forward)
593 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's- / -~-g')"
594 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
595 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
596 ;;
597 forward-dash)
598 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's, - ,~,g')"
599 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
600 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
601 ;;
602 reverse)
603 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's- / -~-g')"
604 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
605 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
606 ;;
607 reverse-dash)
608 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's, - ,~,g')"
609 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
610 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
611 ;;
612 colon)
613 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's-: -~-g')"
614 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
615 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
616 ;;
617 trailing-paren)
618 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's,^\(.*\) (\(.*\)),\1~\2,')"
619 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
620 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
621 ;;
622 esac
623 elif [ "$VARIOUSARTISTS" = "y" ] && [ "$ONETRACK" = "y" ]; then
624 TRACKARTIST="Various"
625 else
626 TRACKARTIST="$DARTIST"
627 fi
628 }
629
630 do_getgenreid () {
631 local genre=$(echo "${@}" | tr '[A-Z]' '[a-z]')
632 local id=""
633 case ${genre} in
634 "blues") id=0 ;;
635 "classic rock") id=1 ;;
636 "country") id=2 ;;
637 "dance") id=3 ;;
638 "disco") id=4 ;;
639 "funk") id=5 ;;
640 "grunge") id=6 ;;
641 "hip-hop") id=7 ;;
642 "jazz") id=8 ;;
643 "metal") id=9 ;;
644 "new age") id=10 ;;
645 "oldies") id=11 ;;
646 "other") id=12 ;;
647 "pop") id=13 ;;
648 "r&b") id=14 ;;
649 "rap") id=15 ;;
650 "reggae") id=16 ;;
651 "rock") id=17 ;;
652 "techno") id=18 ;;
653 "industrial") id=19 ;;
654 "alternative") id=20 ;;
655 "ska") id=21 ;;
656 "death metal") id=22 ;;
657 "pranks") id=23 ;;
658 "soundtrack") id=24 ;;
659 "euro-techno") id=25 ;;
660 "ambient") id=26 ;;
661 "trip-hop") id=27 ;;
662 "vocal") id=28 ;;
663 "jazz+funk") id=29 ;;
664 "fusion") id=30 ;;
665 "trance") id=31 ;;
666 "classical") id=32 ;;
667 "instrumental") id=33 ;;
668 "acid") id=34 ;;
669 "house") id=35 ;;
670 "game") id=36 ;;
671 "sound clip") id=37 ;;
672 "gospel") id=38 ;;
673 "noise") id=39 ;;
674 "alt. rock") id=40 ;;
675 "bass") id=41 ;;
676 "soul") id=42 ;;
677 "punk") id=43 ;;
678 "space") id=44 ;;
679 "meditative") id=45 ;;
680 "instrum. pop") id=46 ;;
681 "instrum. rock") id=47 ;;
682 "ethnic") id=48 ;;
683 "gothic") id=49 ;;
684 "darkwave") id=50 ;;
685 "techno-indust.") id=51 ;;
686 "electronic") id=52 ;;
687 "pop-folk") id=53 ;;
688 "eurodance") id=54 ;;
689 "dream") id=55 ;;
690 "southern rock") id=56 ;;
691 "comedy") id=57 ;;
692 "cult") id=58 ;;
693 "gangsta") id=59 ;;
694 "top 40") id=60 ;;
695 "christian rap") id=61 ;;
696 "pop/funk"|"pop / funk") id=62 ;;
697 "jungle") id=63 ;;
698 "native american") id=64 ;;
699 "cabaret") id=65 ;;
700 "new wave") id=66 ;;
701 "psychadelic") id=67 ;;
702 "rave") id=68 ;;
703 "showtunes") id=69 ;;
704 "trailer") id=70 ;;
705 "lo-fi") id=71 ;;
706 "tribal") id=72 ;;
707 "acid punk") id=73 ;;
708 "acid jazz") id=74 ;;
709 "polka") id=75 ;;
710 "retro") id=76 ;;
711 "musical") id=77 ;;
712 "rock & roll") id=78 ;;
713 "hard rock") id=79 ;;
714 "folk") id=80 ;;
715 "folk/rock") id=81 ;;
716 "national folk") id=82 ;;
717 "swing") id=83 ;;
718 "fusion") id=84 ;;
719 "bebob") id=85 ;;
720 "latin") id=86 ;;
721 "revival") id=87 ;;
722 "celtic") id=88 ;;
723 "bluegrass") id=89 ;;
724 "avantgarde") id=90 ;;
725 "gothic rock") id=91 ;;
726 "progress. rock") id=92 ;;
727 "psychadel. rock") id=93 ;;
728 "symphonic rock") id=94 ;;
729 "slow rock") id=95 ;;
730 "big band") id=96 ;;
731 "chorus") id=97 ;;
732 "easy listening") id=98 ;;
733 "acoustic") id=99 ;;
734 "humour") id=100 ;;
735 "speech") id=101 ;;
736 "chanson") id=102 ;;
737 "opera") id=103 ;;
738 "chamber music") id=104 ;;
739 "sonata") id=105 ;;
740 "symphony") id=106 ;;
741 "booty bass") id=107 ;;
742 "primus") id=108 ;;
743 "porn groove") id=109 ;;
744 "satire") id=110 ;;
745 "slow jam") id=111 ;;
746 "club") id=112 ;;
747 "tango") id=113 ;;
748 "samba") id=114 ;;
749 "folklore") id=115 ;;
750 "ballad") id=116 ;;
751 "power ballad") id=117 ;;
752 "rhythmic soul") id=118 ;;
753 "freestyle") id=119 ;;
754 "duet") id=120 ;;
755 "punk rock") id=121 ;;
756 "drum solo") id=122 ;;
757 "a capella") id=123 ;;
758 "euro-house") id=124 ;;
759 "dance hall") id=125 ;;
760 "goa") id=126 ;;
761 "drum & bass") id=127 ;;
762 "club-house") id=128 ;;
763 "hardcore") id=129 ;;
764 "terror") id=130 ;;
765 "indie") id=131 ;;
766 "britpop") id=132 ;;
767 "negerpunk") id=133 ;;
768 "polsk punk") id=134 ;;
769 "beat") id=135 ;;
770 "christian gangsta rap") id=136 ;;
771 "heavy metal") id=137 ;;
772 "black metal") id=138 ;;
773 "crossover") id=139 ;;
774 "contemporary christian")id=140 ;;
775 "christian rock") id=141 ;;
776 "merengue") id=142 ;;
777 "salsa") id=143 ;;
778 "thrash metal") id=144 ;;
779 "anime") id=145 ;;
780 "jpop") id=146 ;;
781 "synthpop") id=147 ;;
782 "rock/pop"|"rock / pop") id=148 ;;
783 *) return 1 ;;
784 esac
785 echo ${id}
786 return 0
787 }
788
789 # do_tag [tracknumber]
790 # id3 tags a filename
791 # variables used:
792 # TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC, ATOMICPARSLEY
793 # COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE
794 do_tag ()
795 {
796 COMMENTOUTPUT="$(eval echo ${COMMENT})"
797 if [ -z "$COMMENTOUTPUT" ]; then
798 COMMENTOUTPUT="$(getcddbinfo TRACK-INFO)"
799 fi
800 if [ "$CDDBMETHOD" = "cddb" ]; then
801 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
802 fi
803 run_command '' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
804 # If we want to start the tracks with a given number, we need to modify the
805 # TRACKNUM value before evaluation
806 if [ -n "$STARTTRACKNUMBERTAG" ] ; then
807 gettracknum
808 fi
809 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
810 do
811 case "$OUTPUT" in
812 mp3)
813 # id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
814 GENREID=$(do_getgenreid "${CDGENRE}")
815 # Set TPE2 in case we have a Various Artists rip.
816 TPE2=""
817 if [ "$VARIOUSARTISTS" = "y" ]; then
818 TPE2="Various"
819 fi
820
821 case "$ID3SYNTAX" in
822 id3);;
823 eyed3)
824 # FIXME # track numbers in mp3 come with 1/10, so we cannot
825 # happily substitute them with $TRACKNUM
826 run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS \
827 --comment=::"$COMMENTOUTPUT" -A "$DALBUM" \
828 -a "$TRACKARTIST" -t "$TRACKNAME" -Y "$CDYEAR" \
829 -G "$GENREID" -n "${TRACKNUM:-$1}" \
830 "${TRACKNUM:+-N $TRACKS}" \
831 "${ENCODING:+--set-encoding=$ENCODING}" \
832 "${TPE2:+--set-user-text-frame=TPE2:$TPE2}" \
833 "$ABCDETEMPDIR/track$1.$OUTPUT"
834 ;;
835 # FIXME # Still not activated...
836 id3ed)
837 run_command tagtrack-$OUTPUT-$1 nice $ENCNICE \
838 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
839 -a "$DALBUM" -n "$TRACKARTIST" -s "$TRACKNAME" \
840 -y "$CDYEAR" -g "$GENREID" -k "${TRACKNUM:-$1}" \
841 "$ABCDETEMPDIR/track$1.$OUTPUT"
842 ;;
843 *)
844 # FIXME # track numbers in mp3 come with 1/10, so we cannot
845 # happily substitute them with $TRACKNUM
846 run_command tagtrack-$OUTPUT-$1 nice $ENCNICE \
847 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
848 -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" \
849 -y "$CDYEAR" -g "$GENREID" \
850 -T "${TRACKNUM:-$1}/$TRACKS" \
851 ${TPE2:+--TPE2 "$TPE2"} \
852 "$ABCDETEMPDIR/track$1.$OUTPUT"
853 ;;
854 esac
855 ;;
856 vorbis|ogg)
857 case "$OGGENCODERSYNTAX" in
858 vorbize|oggenc)
859 # vorbiscomment can't do in-place modification, mv the file first
860 if [ -f "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" -a ! -f "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" ]; then
861 mv "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
862 fi
863 (
864 # These are from
865 # http://www.xiph.org/ogg/vorbis/doc/v-comment.html
866
867 echo ARTIST="$TRACKARTIST"
868 echo ALBUM="$DALBUM"
869 echo TITLE="$TRACKNAME"
870 if [ -n "$CDYEAR" ]; then
871 echo DATE="$CDYEAR"
872 fi
873 if [ -n "$CDGENRE" ]; then
874 echo GENRE="$CDGENRE"
875 fi
876 echo TRACKNUMBER=${TRACKNUM:-$1}
877 if [ -n "$DISCNUMBER" ]; then
878 echo DISCNUMBER="$DISCNUMBER"
879 fi
880 echo CDDB=$CDDBDISCID
881 if [ "$(eval echo ${COMMENT})" != "" ]; then
882 case "$COMMENTOUTPUT" in
883 *=*) echo "$COMMENTOUTPUT";;
884 *) echo COMMENT="$COMMENTOUTPUT";;
885 esac
886 fi
887 ) | run_command tagtrack-$OUTPUT-$1 nice $ENCNICE \
888 $VORBISCOMMENT $VORBISCOMMENTOPTS -w \
889 "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
890 # Doublecheck that the commented file was created
891 # successfully before wiping the original
892 if [ -f "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" ]; then
893 rm -f "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
894 else
895 mv "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
896 fi
897 ;;
898 esac
899 ;;
900 flac)
901 (
902 echo ARTIST="$TRACKARTIST"
903 echo ALBUM="$DALBUM"
904 echo TITLE="$TRACKNAME"
905 if [ -n "$CDYEAR" ]; then
906 echo DATE="$CDYEAR"
907 fi
908 if [ -n "$CDGENRE" ]; then
909 echo GENRE="$CDGENRE"
910 fi
911 echo TRACKNUMBER="${TRACKNUM:-$1}"
912 if [ -n "$DISCNUMBER" ]; then
913 echo DISCNUMBER="$DISCNUMBER"
914 fi
915 echo CDDB="$CDDBDISCID"
916 if [ "$(eval echo ${COMMENT})" != "" ]; then
917 case "$COMMENTOUTPUT" in
918 *=*) echo "$COMMENTOUTPUT";;
919 *) echo COMMENT="$COMMENTOUTPUT";;
920 esac
921 fi
922 ) | run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="$ABCDETEMPDIR/$CUEFILE"} --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
923 ;;
924 spx)
925 run_command tagtrack-$OUTPUT-$1 true
926 ;;
927 mpc)
928 run_command tagtrack-$OUTPUT-$1 true
929 ;;
930 m4a)
931 # Use a temp-file of our choice. --overWrite seems to
932 # case core dumps with AtomicParsley 0.9.0
933 ATOMICTEMPFILE="$ABCDETEMPDIR/track$1.m4a-atomic"
934
935 VARIOUSBOOL="false"
936 if [ "$VARIOUSARTISTS" = "y" ]; then
937 VARIOUSBOOL="true"
938 fi
939
940 #It has to be command file opts for AtomicParsley
941 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
942 if [ -f $ATOMICTEMPFILE ]; then
943 mv "$ATOMICTEMPFILE" "$ABCDETEMPDIR/track$1.m4a"
944 fi
945 ;;
946 wav)
947 run_command tagtrack-$OUTPUT-$1 true
948 ;;
949 esac
950 done
951 if checkerrors "tagtrack-(.{3,6})-$1"; then :; else
952 run_command tagtrack-$1 true
953 fi
954
955 }
956
957 # do_nogap_encode
958 # variables used:
959 # OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
960 do_nogap_encode ()
961 {
962 # The commands here don't go through run_command because they're never
963 # supposed to be silenced
964 echo "Encoding gapless MP3 tracks: $TRACKQUEUE"
965 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
966 do
967 case "$OUTPUT" in
968 mp3)
969 case "$MP3ENCODERSYNTAX" in
970 lame|toolame)
971 (
972 cd "$ABCDETEMPDIR"
973 TRACKFILES=
974 for UTRACKNUM in $TRACKQUEUE
975 do
976 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
977 done
978 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS --nogap $TRACKFILES
979 RETURN=$?
980 if [ "$RETURN" != "0" ]; then
981 echo "nogap-encode: $ENCODER returned code $RETURN" >> errors
982 else
983 for UTRACKNUM in $TRACKQUEUE
984 do
985 run_command encodetrack-$OUTPUT-$UTRACKNUM true
986 #run_command encodetrack-$UTRACKNUM true
987 done
988 fi
989 )
990 ;;
991 esac
992 ;;
993 esac
994 done
995 if checkerrors "nogap-encode"; then :; else
996 if [ ! "$KEEPWAVS" = "y" ] ; then
997 if [ ! "$KEEPWAVS" = "move" ] ; then
998 rm -f "$IN"
999 fi
1000 fi
1001 fi
1002 # Other encoders fall through to normal encoding as the tracks have not
1003 # been entered in the status file.
1004 }
1005
1006 # do_encode [tracknumber] [hostname]
1007 # If no hostname is specified, encode locally
1008 # variables used:
1009 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
1010 do_encode ()
1011 {
1012 if [ "$USEPIPES" = "y" ]; then
1013 case "$OUTPUT" in
1014 mp3)
1015 TEMPARG="PIPE_$MP3ENCODERSYNTAX"
1016 ;;
1017 vorbis|ogg)
1018 TEMPARG="PIPE_$OGGENCODERSYNTAX"
1019 ;;
1020 flac)
1021 TEMPARG="PIPE_$FLACENCODERSYNTAX"
1022 ;;
1023 spx)
1024 TEMPARG="PIPE_$SPEEXENCODER"
1025 ;;
1026 mpc)
1027 TEMPARG="PIPE_$MPPENCODER"
1028 ;;
1029 m4a)
1030 TEMPARG="PIPE_$AACENCODERSYNTAX"
1031 ;;
1032 esac
1033 IN="$( eval echo "\$$TEMPARG" )"
1034 else
1035 IN="$ABCDETEMPDIR/track$1.wav"
1036 case "$OUTPUT" in
1037 mp3)
1038 case "$MP3ENCODERSYNTAX" in
1039 # FIXME # check if mp3enc needs -if for pipes
1040 # FIXME # I have not been able to find a working mp3enc binary
1041 mp3enc)
1042 FILEARG="-if $IN"
1043 ;;
1044 *)
1045 FILEARG="$IN"
1046 ;;
1047 esac
1048 ;;
1049 *)
1050 FILEARG="$IN"
1051 ;;
1052 esac
1053 fi
1054 # We need IN to proceed, if we are not using pipes.
1055 if [ -s "$IN" -o X"$USEPIPES" = "Xy" ] ; then
1056 for TMPOUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1057 do
1058 case "$TMPOUTPUT" in
1059 vorbis|ogg)
1060 OUTPUT=$OGGOUTPUTCONTAINER
1061 ;;
1062 flac)
1063 OUTPUT=$FLACOUTPUTCONTAINER
1064 ;;
1065 *)
1066 OUTPUT=$TMPOUTPUT
1067 ;;
1068 esac
1069 OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
1070 if [ "$NOGAP" = "y" ] && checkstatus encodetrack-$OUTPUT-$1 ; then
1071 continue
1072 fi
1073 if [ X"$USEPIPES" = "Xy" ]; then
1074 RUN_COMMAND=""
1075 # We need a way to store the creation of the files when using PIPES
1076 RUN_COMMAND_PIPES="run_command encodetrack-$OUTPUT-$1 true"
1077 # When pipping it does not make sense to have a higher nice for
1078 # reading than for encoding, since it will be hold by the
1079 # encoding process. Setting an effective nice, to calm down a
1080 # bit the reading process.
1081 EFFECTIVE_NICE=$READNICE
1082 else
1083 run_command '' echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
1084 RUN_COMMAND="run_command encodetrack-$OUTPUT-$1"
1085 EFFECTIVE_NICE=$ENCNICE
1086 fi
1087 case "$OUTPUT" in
1088 mp3)
1089 case "$2" in
1090 %local*%)
1091 case "$MP3ENCODERSYNTAX" in
1092 lame|toolame|gogo) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
1093 bladeenc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" ;;
1094 l3enc|xingmp3enc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
1095 # FIXME # Relates to the previous FIXME since it might need the "-if" removed.
1096 mp3enc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
1097 esac
1098 ;;
1099 *)
1100 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
1101 ;;
1102 esac
1103 ;;
1104 vorbis|ogg)
1105 case "$2" in
1106 %local*%)
1107 case "$OGGENCODERSYNTAX" in
1108 vorbize) $RUN_COMMAND nice $EFFECTIVE_NICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
1109 oggenc) $RUN_COMMAND nice $EFFECTIVE_NICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
1110 esac
1111 ;;
1112 *)
1113 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
1114 ;;
1115 esac
1116 ;;
1117 flac)
1118 case "$2" in
1119 %local*%)
1120 case "$FLACENCODERSYNTAX" in
1121 flac) $RUN_COMMAND nice $EFFECTIVE_NICE $FLACENCODER -f $FLACENCODEROPTS -o "$OUT" "$IN" ;;
1122 esac
1123 ;;
1124 *)
1125 vecho -n "DISTMP3:"
1126 vecho "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
1127 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
1128 ;;
1129 esac
1130 ;;
1131 spx)
1132 if [ "$(eval echo ${COMMENT})" != "" ]; then
1133 case "$COMMENT" in
1134 *=*) ;;
1135 *) COMMENT="COMMENT=$COMMENT" ;;
1136 esac
1137 fi
1138 # Tag the file at encode time, as it can't be done after encoding.
1139 if [ "$DOTAG" = "y" ]; then
1140 $RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" ${COMMENT:+--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 # Tag the file at encode time, as it can't be done after encoding.
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 diskutil unmount ${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 diskutil mount ${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]? " >&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]? " >&2
2198 #else
2199 echo -n "Locally cached CDDB entry found, use it [Y/n]? " >&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_cdtext
2233 # Try to read CD-Text from the drive using icedax / cdda2wav
2234 do_cdtext ()
2235 {
2236 if new_checkexec icedax; then
2237 CDTEXT_READER=icedax
2238 elif new_checkexec cdda2wav; then
2239 CDTEXT_READER=cdda2wav
2240 else
2241 # Didn't find either, bail
2242 return 0
2243 fi
2244
2245 if [ "$CDROMID" = "" ]; then
2246 CDDA2WAVCDROM="$CDROM"
2247 else
2248 CDDA2WAVCDROM="$CDROMID"
2249 fi
2250
2251 # Do we have CD-Text on the disc (and can the drive read it?)
2252 ${CDTEXT_READER} -J -N -D ${CDDA2WAVCDROM} > $ABCDETEMPDIR/cd-text 2>&1
2253 grep -q '^CD-Text: detected' $ABCDETEMPDIR/cd-text
2254 ERRORCODE=$?
2255 if [ $ERRORCODE -ne 0 ]; then
2256 # No CD-Text found, bail
2257 return 0
2258 fi
2259
2260 rm -f "$ABCDETEMPDIR/cddbchoices"
2261 CDDBCHOICES=1
2262 # Make an empty template
2263 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.1"
2264 echo -n "Retrieved 1 CD-Text match..." >> "$ABCDETEMPDIR/cddbchoices"
2265 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
2266 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2267 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2268 ATITLE=$(grep -e '^Album title:' ${ABCDETEMPDIR}/cd-text | cut -c14- )
2269 echo "200 none ${ATITLE}" >> "$ABCDETEMPDIR/cddbquery"
2270 # List out disc title/author and contents
2271 echo ---- ${ATITLE} ---- >> "$ABCDETEMPDIR/cddbchoices"
2272 for TRACK in $(f_seq_row 1 $TRACKS)
2273 do
2274 TRACKM1=$(($TRACK - 1))
2275 TITLE="$(grep -E ^Track\ +$TRACK: "$ABCDETEMPDIR/cd-text" | tr -d \\r\\n | sed 's~^Track ..: .~~g;'"s~'$~~g")"
2276 echo "$TRACK: $TITLE" >> "$ABCDETEMPDIR/cddbchoices"
2277 sed -i "s~^TTITLE${TRACKM1}=.*~TTITLE${TRACKM1}=${TITLE}~" $ABCDETEMPDIR/cddbread.1
2278 done
2279 sed -i "s~^DTITLE=.*~DTITLE=${ATITLE}~" $ABCDETEMPDIR/cddbread.1
2280 echo >> "$ABCDETEMPDIR/cddbchoices"
2281 echo "cdtext-readcomplete" >> "$ABCDETEMPDIR/status"
2282 }
2283
2284 # do_musicbrainz
2285 # Work with the musicbrainz WS API, then transform the results here so
2286 # they look (very) like the results from CDDB. Maybe not the best way
2287 # to go, but it Works For Me (TM)
2288
2289 do_musicbrainz ()
2290 {
2291 if checkstatus musicbrainz-readcomplete; then :; else
2292 vecho "Obtaining Musicbrainz results..."
2293 # If MB is to be used, interpret the query results and read all
2294 # the available entries.
2295 rm -f "$ABCDETEMPDIR/cddbchoices"
2296 CDDBCHOICES=1 # Overridden by multiple matches
2297 MBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
2298 ${MUSICBRAINZ} --command data --discid "$MBDISCID" --workdir $ABCDETEMPDIR
2299
2300 # The helper script will write disc matches out to
2301 # cddbread.*. Count how many we have
2302 if [ ! -f ${ABCDETEMPDIR}/cddbread.1 ] ; then
2303 # No matches. Use the normal cddb template for the user to
2304 # fill in
2305 echo "No Musicbrainz match." >> "$ABCDETEMPDIR/cddbchoices"
2306 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2307 # List out disc title/author and contents of template
2308 echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
2309 UNKNOWNDISK=y
2310 for TRACK in $(f_seq_row 1 $TRACKS)
2311 do
2312 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2313 done
2314 echo >> "$ABCDETEMPDIR/cddbchoices"
2315 echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
2316 echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
2317 echo 503 > "$ABCDETEMPDIR/cddbquery"
2318 else
2319 # We have some matches
2320 NUM_RESPONSES=$(echo ${ABCDETEMPDIR}/cddbread.* | wc -w)
2321 if [ "$NUM_RESPONSES" -eq 1 ] ; then
2322 # One exact match
2323 echo -n "Retrieved 1 Musicbrainz match..." >> "$ABCDETEMPDIR/cddbchoices"
2324 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
2325 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2326 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2327 ATITLE=$(grep -e '^DTITLE=' ${ABCDETEMPDIR}/cddbread.1 | cut -c8- )
2328 echo "200 none ${ATITLE}" >> "$ABCDETEMPDIR/cddbquery"
2329 # List out disc title/author and contents
2330 echo ---- ${ATITLE} ---- >> "$ABCDETEMPDIR/cddbchoices"
2331 for TRACK in $(f_seq_row 1 $TRACKS)
2332 do
2333 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2334 done
2335 echo >> "$ABCDETEMPDIR/cddbchoices"
2336 else
2337 echo "210 Found exact matches, list follows (until terminating .)" > "$ABCDETEMPDIR/cddbquery"
2338 echo "Multiple Musicbrainz matches:" >> "$ABCDETEMPDIR/cddbchoices"
2339 for file in $ABCDETEMPDIR/cddbread.*
2340 do
2341 X=$(echo $file | sed 's/^.*cddbread\.//g')
2342 echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
2343 ATITLE=$(grep -e '^DTITLE=' ${ABCDETEMPDIR}/cddbread.$X | cut -c8- )
2344 echo "none ${ATITLE}" >> "$ABCDETEMPDIR/cddbquery"
2345 # List out disc title/author and contents
2346 echo "#$X: ---- ${ATITLE} ----" >> "$ABCDETEMPDIR/cddbchoices"
2347 for TRACK in $(f_seq_row 1 $TRACKS)
2348 do
2349 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2350 done
2351 echo >> "$ABCDETEMPDIR/cddbchoices"
2352 done
2353 echo "." >> "$ABCDETEMPDIR/cddbquery"
2354 fi
2355 fi
2356 echo "musicbrainz-readcomplete" >> "$ABCDETEMPDIR/status"
2357 fi
2358 }
2359
2360 # do_cddbstat
2361 do_cddbstat ()
2362 {
2363 # Perform CDDB protocol version check if it hasn't already been done
2364 if checkstatus cddb-statcomplete; then :; else
2365 if [ "$CDDBAVAIL" = "n" ]; then
2366 ERRORCODE=no_query
2367 echo 503 > "$ABCDETEMPDIR/cddbstat"
2368 else
2369 rc=1
2370 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
2371 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
2372 while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
2373 vecho "Checking CDDB server status..."
2374 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
2375 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
2376 case "$RESPONSECODE" in
2377 210) # 210 OK, status information follows (until terminating `.')
2378 rc=0
2379 ;;
2380 501) # 501 Illegal CDDB protocol level: <n>.
2381 CDDBPROTO=`expr $CDDBPROTO - 1`
2382 ;;
2383 *) # Try a cddb query, since freedb2.org doesn't support the stat or ver commands
2384 # FreeDB TESTCD disc-id is used for query
2385 $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST 03015501 1 296 344 > "$ABCDETEMPDIR/cddbstat"
2386 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
2387 case "$RESPONSECODE" in
2388 2??) # Server responded, everything seems OK
2389 rc=0
2390 ;;
2391 esac
2392 ;;
2393 esac
2394 done
2395 if test $rc -eq 1; then
2396 CDDBAVAIL="n"
2397 fi
2398 fi
2399 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
2400 fi
2401 }
2402
2403
2404 # do_cddbquery
2405 do_cddbquery ()
2406 {
2407 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
2408 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
2409
2410 # Perform CDDB query if it hasn't already been done
2411 if checkstatus cddb-querycomplete; then :; else
2412 if [ "$CDDBAVAIL" = "n" ]; then
2413 ERRORCODE=no_query
2414 echo 503 > "$ABCDETEMPDIR/cddbquery"
2415 # The default CDDBLOCALSTATUS is "notfound"
2416 # This part will be triggered if the user CDDB repo does not
2417 # contain the entry, or if we are not trying to use the repo.
2418 else
2419 vecho "Querying the CDDB server..."
2420 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
2421 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
2422 $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
2423 ERRORCODE=$?
2424 case $ERRORCODE in
2425 0) # success
2426 ;;
2427 12|13|14)
2428 # no match found in database,
2429 # wget/fetch error, or user requested not to use CDDB
2430 # Make up an error code (503) that abcde
2431 # will recognize in do_cddbread
2432 # and compensate by making a template
2433 echo 503 > "$ABCDETEMPDIR/cddbquery"
2434 ;;
2435 *) # strange and unknown error
2436 echo ERRORCODE=$ERRORCODE
2437 echo "abcde: $CDDBTOOL returned unknown error code"
2438 ;;
2439 esac
2440 fi
2441 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
2442 fi
2443 }
2444
2445 # do_cddbread
2446 do_cddbread ()
2447 {
2448 # If it's not to be used, generate a template.
2449 # Then, display it (or them) and let the user choose/edit it
2450 if checkstatus cddb-readcomplete; then :; else
2451 vecho "Obtaining CDDB results..."
2452 # If CDDB is to be used, interpret the query results and read all
2453 # the available entries.
2454 rm -f "$ABCDETEMPDIR/cddbchoices"
2455 CDDBCHOICES=1 # Overridden by multiple matches
2456 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
2457 case "$RESPONSECODE" in
2458 200)
2459 # One exact match, retrieve it
2460 # 200 [section] [discid] [artist] / [title]
2461 if checkstatus cddb-read-1-complete; then :; else
2462 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
2463 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
2464 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
2465 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2466 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2467 fi
2468 # List out disc title/author and contents
2469 echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
2470 for TRACK in $(f_seq_row 1 $TRACKS)
2471 do
2472 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2473 done
2474 echo >> "$ABCDETEMPDIR/cddbchoices"
2475 ;;
2476 202|403|409|503)
2477 # No match
2478 case "$RESPONSECODE" in
2479 202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
2480 403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
2481 503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
2482 esac
2483 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2484 # List out disc title/author and contents of template
2485 echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
2486 UNKNOWNDISK=y
2487 for TRACK in $(f_seq_row 1 $TRACKS)
2488 do
2489 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2490 done
2491 echo >> "$ABCDETEMPDIR/cddbchoices"
2492 echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
2493 echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
2494 ;;
2495 210|211)
2496 # Multiple exact, (possibly multiple) inexact matches
2497 IN=
2498 if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
2499 if [ "$(wc -l < "$ABCDETEMPDIR/cddbquery" | tr -d ' ')" -eq 3 ]; then
2500 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
2501 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
2502 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2503 else
2504 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
2505 fi
2506 vecho -n "Retrieving multiple matches... "
2507 grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
2508 read DISCINFO # eat top line
2509 while read DISCINFO
2510 do
2511 X=$(expr $X + 1)
2512 if checkstatus cddb-read-$X-complete; then :; else
2513 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
2514 echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
2515 fi
2516 # List out disc title/author and contents
2517 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
2518 for TRACK in $(f_seq_row 1 $TRACKS)
2519 do
2520 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2521 done
2522 echo >> "$ABCDETEMPDIR/cddbchoices"
2523 done )
2524 vecho "done."
2525 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2526 ;;
2527 999)
2528 # Using local copy.
2529 for TRACK in $(f_seq_row 1 $TRACKS)
2530 do
2531 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2532 done
2533 echo >> "$ABCDETEMPDIR/cddbchoices"
2534 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2535 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2536 ;;
2537 esac
2538 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
2539 fi
2540 }
2541
2542 # do_cddbedit
2543 do_cddbedit ()
2544 {
2545 if checkstatus cddb-edit >/dev/null; then
2546 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2547 VARIOUSARTISTS="$(checkstatus variousartists)"
2548 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
2549 return 0
2550 fi
2551 if [ "$INTERACTIVE" = "y" ]; then
2552 # We should show the CDDB results both when we are not using the local CDDB repo
2553 # or when we are using it but we could not find a proper match
2554 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2555 # Display the $ABCDETEMPDIR/cddbchoices file created above
2556 # Pick a pager so that if the tracks overflow the screen the user can still view everything
2557 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2558 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2559 CHOICE=$(checkstatus cddb-choice)
2560 if [ -n "$CHOICE" ] ; then
2561 case $CDDBCHOICES in
2562 -1) if head -1 "$ABCDETEMPDIR/cddbquery" | grep "^$" > /dev/null 2>&1 ; then
2563 log error "CDDB query failed!"
2564 exit 1
2565 else
2566 cat "$ABCDETEMPDIR/cddbchoices"
2567 fi
2568 ;;
2569 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
2570 *)
2571 echo "Selected: #$CHOICE"
2572 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
2573 ;;
2574 esac
2575 else
2576 # The user has a choice to make, display the info in a pager if necessary
2577 if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
2578 page "$ABCDETEMPDIR/cddbchoices"
2579 else
2580 # It's all going to fit in one page, cat it
2581 cat "$ABCDETEMPDIR/cddbchoices" >&2
2582 fi
2583
2584 CDDBCHOICENUM=""
2585 # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
2586 CDCHOICENUM=-1
2587 # I'll take CDDB read #3 for $400, Alex
2588 while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
2589 echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
2590 read CDDBCHOICE
2591 [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
2592 if echo $CDDBCHOICE | grep -E "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2593 if [ ! X"$DIFF" = "X" ]; then
2594 PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
2595 PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
2596 if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
2597 [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
2598 [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then
2599 echo "Invalid diff range. Please select two comma-separated numbers between 1 and $CDDBCHOICES" >&2
2600 else
2601 # We parse the 2 choices to diff, store them in temporary files and diff them.
2602 for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
2603 do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE"
2604 done
2605 echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/cddbread.diff"
2606 $DIFF $DIFFOPTS "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/cddbread.diff"
2607 if [ $(cat "$ABCDETEMPDIR/cddbread.diff" | wc -l) -ge 24 ]; then
2608 page "$ABCDETEMPDIR/cddbread.diff"
2609 else
2610 cat "$ABCDETEMPDIR/cddbread.diff" >&2
2611 fi
2612 fi
2613 else
2614 echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2
2615 fi
2616 elif echo $CDDBCHOICE | grep -E "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2617 # Make sure we get a valid choice
2618 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
2619 if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then
2620 echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2
2621 fi
2622 fi
2623 done
2624 if [ "$CDCHOICENUM" = "0" ]; then
2625 vecho "Creating empty CDDB template..."
2626 UNKNOWNDISK=y
2627 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2628 else
2629 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2630 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
2631 fi
2632 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2633 fi
2634 fi
2635 else
2636 # We need some code to show the selected option when local repository is selected and we have found a match
2637 vecho "Using cached CDDB match..." >&2
2638 # Display the $ABCDETEMPDIR/cddbchoices file created above
2639 # Pick a pager so that if the tracks overflow the screen the user can still view everything
2640 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2641 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2642 CHOICE=$(checkstatus cddb-choice)
2643 if [ "$USELOCALRESP" = "y" ]; then :; else
2644 if [ -n "$CHOICE" ] ; then
2645 case $CDDBCHOICES in
2646 0)
2647 UNKNOWNDISK=y
2648 echo "Selected template."
2649 ;;
2650 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
2651 *)
2652 echo "Selected: #$CHOICE"
2653 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
2654 ;;
2655 esac
2656 fi
2657 fi
2658 fi
2659 fi
2660 else
2661 # We're noninteractive - pick the first choice.
2662 # But in case we run a previous instance and selected a choice, use it.
2663 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2664 # Show the choice if we are not using the locally stored one
2665 # or when the local search failed to find a match.
2666 PREVIOUSCHOICE=$(checkstatus cddb-choice)
2667 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2668 #if [ "$PREVIOUSCHOICE" ]; then
2669 cat "$ABCDETEMPDIR/cddbchoices"
2670 #fi
2671 fi
2672 if [ ! -z "$PREVIOUSCHOICE" ] ; then
2673 CDCHOICENUM=$PREVIOUSCHOICE
2674 else
2675 CDCHOICENUM=1
2676 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2677 fi
2678 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2679 fi
2680 fi
2681
2682 # sanity check
2683 if checkstatus cddb-choice >/dev/null; then :; else
2684 echo "abcde: internal error: cddb-choice not recorded." >&2
2685 exit 1
2686 fi
2687 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2688 echo -n "Edit selected CDDB data? [y/n] (" >&2
2689 if [ "$INTERACTIVE" = "y" ]; then
2690 if [ "$UNKNOWNDISK" = "y" ]; then
2691 echo -n "y): " >&2
2692 read EDITCDDB
2693 [ "$EDITCDDB" != "n" ] && EDITCDDB=y
2694 else
2695 echo -n "n): " >&2
2696 read EDITCDDB
2697 fi
2698 else
2699 echo "n): n" >&2
2700 EDITCDDB=n
2701 fi
2702 if [ "$EDITCDDB" = "y" ]; then
2703 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
2704
2705 # Use the debian sensible-editor wrapper to pick the editor that the
2706 # user has requested via their $EDITOR environment variable
2707 if [ -x "/usr/bin/sensible-editor" ]; then
2708 /usr/bin/sensible-editor "$CDDBDATA"
2709 elif [ -n "$EDITOR" ]; then
2710 if [ -x $(which "${EDITOR%%\ *}") ]; then
2711 # That failed, try to load the preferred editor, starting
2712 # with their EDITOR variable
2713 eval $(echo "$EDITOR") \"$CDDBDATA\"
2714 fi
2715 # If that fails, check for a vi
2716 elif which vi >/dev/null 2>&1; then
2717 vi "$CDDBDATA"
2718 elif [ -x /usr/bin/vim ]; then
2719 /usr/bin/vim "$CDDBDATA"
2720 elif [ -x /usr/bin/vi ]; then
2721 /usr/bin/vi "$CDDBDATA"
2722 elif [ -x /bin/vi ]; then
2723 /bin/vi "$CDDBDATA"
2724 # nano should be on all (modern, i.e., sarge) debian systems
2725 elif which nano >/dev/null 2>&1 ; then
2726 nano "$CDDBDATA"
2727 elif [ -x /usr/bin/nano ]; then
2728 /usr/bin/nano "$CDDBDATA"
2729 # mg should be on all OpenBSD systems
2730 elif which mg >/dev/null 2>&1 ; then
2731 mg "$CDDBDATA"
2732 elif [ -x /usr/bin/mg ]; then
2733 /usr/bin/mg "$CDDBDATA"
2734 # bomb out
2735 else
2736 log warning "no editor available. Check your EDITOR environment variable."
2737 fi
2738 # delete editor backup file if it exists
2739 if [ -w "$CDDBDATA~" ]; then
2740 rm -f "$CDDBDATA~"
2741 fi
2742 fi
2743
2744 # Some heuristics first. Look at Disc Title, and if it starts with
2745 # "Various", then we'll assume Various Artists
2746 if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2- -d= | grep -Eci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
2747 echo "Looks like a Multi-Artist CD" >&2
2748 VARIOUSARTISTS=y
2749 else
2750 echo -n "Is the CD multi-artist [y/N]? " >&2
2751 if [ "$INTERACTIVE" = "y" ]; then
2752 read VARIOUSARTISTS
2753 else
2754 echo n >&2
2755 VARIOUSARTISTS=n
2756 fi
2757 fi
2758 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
2759 # Set a default
2760 DEFAULTSTYLE=1
2761 # Need NUMTRACKS before cddb-tool will return it:
2762 NUMTRACKS=$(grep -E '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
2763 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2764 # More than 1/2 tracks contain a "/", so guess forward
2765 DEFAULTSTYLE=1
2766 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2767 # More than 1/2 contain a "-", so guess forward-dash
2768 DEFAULTSTYLE=2
2769 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2770 # More than 1/2 contain something in parens, so guess trailing-paren
2771 DEFAULTSTYLE=6
2772 fi
2773
2774 echo "1) Artist / Title" >&2
2775 echo "2) Artist - Title" >&2
2776 echo "3) Title / Artist" >&2
2777 echo "4) Title - Artist" >&2
2778 echo "5) Artist: Title" >&2
2779 echo "6) Title (Artist)" >&2
2780 echo "7) This is a single-artist CD" >&2
2781 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
2782 if [ "$INTERACTIVE" = "y" ]; then
2783 read VARIOUSARTISTSTYLE
2784 else
2785 echo $DEFAULTSTYLE >&2
2786 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2787 fi
2788 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2789 # If they press Enter, then the default style (0) was chosen
2790 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
2791 echo "Invalid selection. Please choose a number between 1 and 7."
2792 echo -n "Selection [1-7]: "
2793 read VARIOUSARTISTSTYLE
2794 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2795 done
2796 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
2797 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2798 fi
2799 vecho "Selected: $VARIOUSARTISTSTYLE"
2800 case "$VARIOUSARTISTSTYLE" in
2801 1) # Artist / Title
2802 VARIOUSARTISTSTYLE=forward
2803 ;;
2804 2) # Artist - Title
2805 VARIOUSARTISTSTYLE=forward-dash
2806 ;;
2807 3) # Title / Artist
2808 VARIOUSARTISTSTYLE=reverse
2809 ;;
2810 4) # Title - Artist
2811 VARIOUSARTISTSTYLE=reverse-dash
2812 ;;
2813 5) # Artist: Title
2814 VARIOUSARTISTSTYLE=colon
2815 ;;
2816 6) # Title (Artist)
2817 VARIOUSARTISTSTYLE=trailing-paren
2818 ;;
2819 7) # Single Artist
2820 VARIOUSARTISTS=n
2821 ;;
2822 esac
2823 fi
2824
2825 echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
2826 echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
2827
2828 if [ "$EDITCDDB" = "y" ] && [ "$CDDBMETHOD" = "cddb" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
2829 if [ "$CDDBDATAMD5SUM" != "" ] && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
2830 # This works but does not have the necessary error checking
2831 # yet. If you are familiar with the CDDB spec
2832 # (see http://www.freedb.org/src/latest/DBFORMAT)
2833 # and can create an error-free entry on your own, then put
2834 # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
2835 # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
2836 # your abcde.conf to change the email address submissions are
2837 # sent to.
2838
2839 # submit the modified file, if they want
2840 if [ "$NOSUBMIT" != "y" ]; then
2841 echo -n "Do you want to submit this entry to $CDDBSUBMIT [y/N]? "
2842 read YESNO
2843 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
2844 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
2845 do
2846 echo -n 'Invalid selection. Please answer "y" or "n": '
2847 read YESNO
2848 done
2849 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
2850 echo -n "Sending..."
2851 $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
2852 echo "done."
2853 fi
2854 fi
2855 fi
2856 fi
2857 ### FIXME ###
2858 # User CDDBLOCALPOLICY to find out if we store the file or not...
2859 # Cache edited CDDB entry in the user's cddb dir
2860 if [ "$CDDBCOPYLOCAL" = "y" ]; then
2861 # Make sure the cache directory exists
2862 mkdir -p $CDDBLOCALDIR
2863 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
2864 fi
2865
2866 echo "cddb-edit" >> "$ABCDETEMPDIR/status"
2867 }
2868
2869 # do_cdread [tracknumber]
2870 # do_cdread onetrack [firsttrack] [lasttrack]
2871 #
2872 do_cdread ()
2873 {
2874 # The commands here don't go through run_command because they're never supposed to be silenced
2875 # return codes need to be doublechecked anyway, however
2876 if [ "$1" = "onetrack" ]; then
2877 # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
2878 # FIXME # Until then, we grab the whole CD in one track, no matter what
2879 # the user said
2880 # We need the first and last track for cdda2wav/icedax
2881 FIRSTTRACK=$2
2882 LASTTRACK=$(expr $3 + 0)
2883 UTRACKNUM=$FIRSTTRACK
2884 case "$CDROMREADERSYNTAX" in
2885 flac) READTRACKNUMS="$FIRSTTRACK.1-$(($LASTTRACK + 1)).0" ;;
2886 cdparanoia)
2887 #XX FIXME XX
2888 # Add a variable to check if tracks are provided in command line and if not, use "0-" to rip the tracks
2889 READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
2890 cdda2wav | icedax) READTRACKNUMS="$FIRSTTRACK+$LASTTRACK" ;;
2891 *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
2892 exit 1 ;;
2893 esac
2894 else
2895 UTRACKNUM=$1
2896 fi
2897 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2898 if [ "$USEPIPES" = "y" ]; then
2899 TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
2900 FILEARG="$( eval echo "\$$TEMPARG" )"
2901 REDIR="y"
2902 PIPE_MESSAGE="and encoding "
2903 else
2904 WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
2905 case "$CDROMREADERSYNTAX" in
2906 ## FIXME ## Find the cases for dagrab and flac, to avoid exceptions
2907 flac)
2908 FILEARG="--output-name=$WAVDATA"
2909 ;;
2910 dagrab)
2911 FILEARG="-f $WAVDATA"
2912 ;;
2913 *)
2914 FILEARG="$WAVDATA"
2915 ;;
2916 esac
2917 REDIR="n"
2918 fi
2919 if [ "$1" = "onetrack" ]; then
2920 echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
2921 else
2922 if [ -r "$CDDBDATA" ]; then
2923 getcddbinfo TRACKNAME
2924 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
2925 else
2926 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
2927 fi
2928 fi
2929 case "$CDROMREADERSYNTAX" in
2930 ### FIXME ### use an exception for flac, since it uses -o
2931 ### FIXME ### Shall we just use -o $FILEARG ??
2932 flac)
2933 # Avoid problems wit math expressions by unpadding the given UTRACKNUM
2934 STRIPTRACKNUM=$(expr $UTRACKNUM + 0)
2935 nice $READNICE $FLAC -d -f --cue=${READTRACKNUMS:-$STRIPTRACKNUM.1-$(($STRIPTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;;
2936 cdparanoia)
2937 if [ "$REDIR" = "y" ]; then
2938 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" >&2
2939 else
2940 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG"
2941 fi;;
2942
2943 cdda2wav | icedax)
2944 if [ "$OSFLAVOUR" = "OSX" ] ; then
2945 # Hei, we have to unmount the device before running anything like cdda2wav/icedax in OSX
2946 diskutil unmount ${CDROM#/dev/} 0
2947 # Also, in OSX the cdrom device for cdda2wav/icedax changes...
2948 CDDA2WAVCDROM="IODVDServices"
2949 elif [ "$OSFLAVOUR" = "FBSD" ] ; then
2950 CDDA2WAVCDROM="$CDROMID"
2951 else
2952 if [ "$CDROMID" = "" ]; then
2953 CDDA2WAVCDROM="$CDROM"
2954 else
2955 CDDA2WAVCDROM="$CDROMID"
2956 fi
2957 fi
2958 if [ "$REDIR" = "y" ]; then
2959 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" >&2
2960 else
2961 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG"
2962 fi ;;
2963 ## FIXME ## We have an exception for dagrab, since it uses -f
2964 ## FIXME ## Shall we just use -f $FILEARG ??
2965 dagrab)
2966 if [ "$REDIR" = "y" ]; then
2967 nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG" >&2
2968 else
2969 nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG"
2970 fi ;;
2971 cddafs)
2972 # Find the track's mounted path
2973 REALTRACKNUM=$(expr $UTRACKNUM + 0)
2974 FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
2975 FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
2976 # If the file exists, copy it
2977 if [ -e "$FILEPATH" ] ; then
2978 if [ "$REDIR" = "y" ]; then
2979 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" >&2
2980 else
2981 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG"
2982 fi
2983 else
2984 false
2985 fi ;;
2986 debug)
2987 if [ "$REDIR" = "y" ]; then
2988 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG" >&2
2989 else
2990 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG"
2991 fi ;;
2992 esac
2993 RETURN=$?
2994 # If we get some error or we get some missing wav
2995 # (as long as we dont use pipes)
2996 if [ "$RETURN" != "0" -o \( ! -s "$WAVDATA" -a X"$USEPIPES" != "Xy" \) ]; then
2997 # Thank goodness errors is only machine-parseable up to the
2998 # first colon, otherwise this woulda sucked
2999 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
3000 RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
3001 fi
3002 if [ "$USEPIPES" = "y" ]; then
3003 echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
3004 else
3005 echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
3006 fi
3007 return $RETURN
3008 else
3009 if [ "$USEPIPES" = "y" ]; then
3010 echo readencodetrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
3011 else
3012 echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
3013 fi
3014 if [ "$1" = "onetrack" ]; then
3015 echo onetrack >> "$ABCDETEMPDIR/status"
3016 fi
3017 fi
3018 }
3019
3020 # do_cdspeed
3021 # No values accepted, only uses env variables
3022 do_cdspeed ()
3023 {
3024 if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
3025 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
3026 else
3027 echo "abcde: unable to set the device speed" >&2
3028 fi
3029 }
3030
3031 # vecho [message]
3032 #
3033 # vecho outputs a message if EXTRAVERBOSE is 1 or more
3034 vecho ()
3035 {
3036 if [ x"$EXTRAVERBOSE" != "x" ] && [ $EXTRAVERBOSE -gt 0 ] ; then
3037 case $1 in
3038 warning) shift ; log warning "$@" ;;
3039 *) echo "$@" ;;
3040 esac
3041 fi
3042 }
3043
3044 # vvecho [message]
3045 #
3046 # vvecho outputs a message if EXTRAVERBOSE is 2 or more
3047 vvecho ()
3048 {
3049 if [ x"$EXTRAVERBOSE" != "x" ] && [ $EXTRAVERBOSE -gt 1 ] ; then
3050 case $1 in
3051 warning) shift ; log warning "$@" ;;
3052 *) echo "$@" ;;
3053 esac
3054 fi
3055 }
3056
3057 # decho [message]
3058 #
3059 # decho outputs a debug message if DEBUG is selected
3060 decho ()
3061 {
3062 if [ x"$DEBUG" != "x" ]; then
3063 if echo $1 | grep "^\[" > /dev/null 2>&1 ; then
3064 DEBUGECHO=$(echo "$@" | tr -d '[]')
3065 echo "[DEBUG] $DEBUGECHO: `eval echo \\$${DEBUGECHO}`"
3066 else
3067 echo "[DEBUG] $1"
3068 fi
3069 fi
3070 }
3071
3072 # User-redefinable functions
3073 # Custom filename munging:
3074 mungefilename ()
3075 {
3076 #echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
3077 echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
3078 }
3079
3080 # Custom genre munging:
3081 mungegenre ()
3082 {
3083 echo $CDGENRE | tr "[:upper:]" "[:lower:]"
3084 }
3085
3086 # pre_read
3087 # Empty pre_read function, to be defined in the configuration file.
3088 pre_read ()
3089 {
3090 :
3091 }
3092
3093 # post_read
3094 # Empty post_read function, to be defined in the configuration file.
3095 post_read ()
3096 {
3097 :
3098 }
3099
3100 # post_encode
3101 # Empty post_encode function, to be defined in the configuration file.
3102 post_encode ()
3103 {
3104 :
3105 }
3106
3107 ###############################################################################
3108 # End of functions
3109 #
3110 # Start of execution
3111 ###############################################################################
3112
3113 # Builtin defaults
3114
3115 # CDDB
3116 # Defaults to FreeDB, but musicbrainz can be used too, via the abcde-musicbrainz-tool script
3117 CDDBMETHOD=cddb
3118 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
3119 CDDBSUBMIT=freedb-submit@freedb.org
3120 CDDBPROTO=6
3121 HELLOINFO="$(whoami)@$(hostname)"
3122 CDDBCOPYLOCAL="n"
3123 CDDBLOCALPOLICY="always"
3124 CDDBLOCALRECURSIVE="y"
3125 CDDBLOCALDIR="$HOME/.cddb"
3126 CDDBUSELOCAL="n"
3127
3128 # List of fields we parse and show during the CDDB parsing...
3129 SHOWCDDBFIELDS="year,genre"
3130
3131 INTERACTIVE=y
3132 #CDROMREADERSYNTAX=cdparanoia
3133 ENCODERSYNTAX=default
3134
3135 MP3ENCODERSYNTAX=default
3136 OGGENCODERSYNTAX=default
3137 FLACENCODERSYNTAX=default
3138 SPEEXENCODERSYNTAX=default
3139 MPPENCODERSYNTAX=default
3140 AACENCODERSYNTAX=default
3141 NORMALIZERSYNTAX=default
3142 CUEREADERSYNTAX=default
3143
3144 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
3145 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
3146 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
3147 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
3148 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
3149 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
3150 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
3151 PLAYLISTDATAPREFIX=''
3152 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
3153 VAPLAYLISTDATAPREFIX=''
3154 DOSPLAYLIST=n
3155 COMMENT=''
3156 ID3TAGV=2
3157 ENCNICE=10
3158 READNICE=10
3159 DISTMP3NICE=10
3160 VARIOUSARTISTS=n
3161 VARIOUSARTISTSTYLE=forward
3162 KEEPWAVS=n
3163 PADTRACKS=n
3164 NOGAP=n
3165 BATCHNORM=n
3166 NOCDDBQUERY=n
3167
3168 # If using scsi devices, cdda2wav/icedax needs a CDROMID, instead of a device node
3169 # i.e. CDROMID="1,0,0"
3170 CDROMID=""
3171 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
3172 # If we are using the ide-scsi emulation layer, we need to define a "g"
3173 CDPARANOIACDROMBUS="d"
3174
3175 # program paths - defaults to checking your $PATH
3176 # mp3
3177 LAME=lame
3178 TOOLAME=toolame
3179 GOGO=gogo
3180 BLADEENC=bladeenc
3181 L3ENC=l3enc
3182 XINGMP3ENC=xingmp3enc
3183 MP3ENC=mp3enc
3184 # ogg
3185 VORBIZE=vorbize
3186 OGGENC=oggenc
3187 # flac
3188 FLAC=flac
3189 # speex
3190 SPEEXENC=speexenc
3191 # mpp (Musepack)
3192 MPPENC=mppenc
3193 # m4a
3194 AACENC=faac
3195
3196 ID3=id3
3197 ID3V2=id3v2
3198 EYED3=eyeD3
3199 VORBISCOMMENT=vorbiscomment
3200 METAFLAC=metaflac
3201 AACTAG=faac
3202 ATOMICPARSLEY=AtomicParsley
3203
3204 CDPARANOIA=cdparanoia
3205 CDDA2WAV=icedax
3206 DAGRAB=dagrab
3207 CDDAFS=cp
3208 CDDISCID=cd-discid
3209 CDDBTOOL=cddb-tool
3210 MUSICBRAINZ=abcde-musicbrainz-tool
3211 EJECT=eject
3212 MD5SUM=md5sum
3213 DISTMP3=distmp3
3214 NORMALIZE=normalize-audio
3215 CDSPEED=eject
3216 VORBISGAIN=vorbisgain
3217 MP3GAIN=mp3gain
3218 MPPGAIN=replaygain
3219 MKCUE=mkcue
3220 MKTOC=cdrdao
3221 DIFF=diff
3222 CUE2DISCID=builtin
3223
3224 # Options for programs called from abcde
3225 # mp3
3226 LAMEOPTS=
3227 TOOLAMEOPTS=
3228 GOGOOPTS=
3229 BLADEENCOPTS=
3230 L3ENCOPTS=
3231 XINGMP3ENCOPTS=
3232 MP3ENCOPTS=
3233 MP3GAINOPTS="-a -k"
3234 # ogg
3235 VORBIZEOPTS=
3236 OGGENCOPTS=
3237 VORBISGAINOPTS="--album"
3238 # flac
3239 FLACOPTS=
3240 FLACGAINOPTS="--add-replay-gain"
3241 # speex
3242 SPEEXENCOPTS=
3243 # mpc
3244 MPPENCOPTS=
3245 # m4a
3246 AACENCOPTS=
3247
3248 ID3OPTS=
3249 ID3V2OPTS=
3250 CDPARANOIAOPTS=
3251 CDDA2WAVOPTS=
3252 DAGRABOPTS=
3253 CDDAFSOPTS="-f"
3254 CDDBTOOLOPTS=
3255 EJECTOPTS=
3256 DISTMP3OPTS=
3257 NORMALIZEOPTS=
3258 CDSPEEDOPTS="-x"
3259 CDSPEEDVALUE=
3260 MKCUEOPTS=
3261 MKTOCOPTS=""
3262 VORBISCOMMENTOPTS="-R"
3263 METAFLACOPTS="--no-utf8-convert"
3264 DIFFOPTS=
3265
3266 # Default to one process if -j isn't specified
3267 MAXPROCS=1
3268
3269 # List of actions to perform - by default, run to completion
3270 ACTIONS=cddb,read,encode,tag,move,clean
3271
3272 # This option is basicaly for Debian package dependencies:
3273 # List of prefered outputs - by default, run with whatever we have in the path
3274 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:toolame,mp3:lame,mp3:bladeenc,spx:speex,m4a:faac
3275
3276 # List of prefered cdromreaders - by default, run whichever we have in the path
3277 DEFAULT_CDROMREADERS="cdparanoia icedax cdda2wav"
3278
3279 # List of quality levels associated with the encoders:
3280 DEFAULT_QUALITY_XLO="oggenc:-q -1,lame:-q 9,speex:--quality 1,m4a:"
3281 DEFAULT_QUALITY_LO="oggenc:-q 1,lame:-q 7,speex:--quality 5,m4a:"
3282 DEFAULT_QUALITY_HI="oggenc:-q 7,lame:--preset standard,speex:--quality 9,m4a:"
3283 DEFAULT_QUALITY_XHI="oggenc:-q 10,lame:--preset extreme,speex:--quality 10,m4a:"
3284
3285 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for
3286 # Linux/OpenBSD. ftp is user for NetBSD.
3287 # Let's use these checkings to determine the OS flavour, which will be used
3288 # later
3289 if [ X$(uname) = "XFreeBSD" ] ; then
3290 HTTPGET=fetch
3291 MD5SUM=md5
3292 NEEDCDROMID=y
3293 OSFLAVOUR=FBSD
3294 elif [ X$(uname) = "XDarwin" ] ; then
3295 HTTPGET=curl
3296 OSFLAVOUR=OSX
3297 # We should have diskutil in OSX, but let's be sure...
3298 NEEDDISKUTIL=y
3299 CDROMREADERSYNTAX=cddafs
3300 elif [ X$(uname) = "XOpenBSD" ] ; then
3301 HTTPGET=wget
3302 MD5SUM=md5
3303 OSFLAVOUR=OBSD
3304 elif [ X$(uname) = "XNetBSD" ] ; then
3305 HTTPGET=ftp
3306 MD5SUM=md5
3307 OSFLAVOUR=NBSD
3308 elif [ X$(uname) = "SunOS" ] ; then
3309 HTTPGET=""
3310 MD5SUM=md5
3311 OSFLAVOUR=SunOS
3312 else
3313 HTTPGET=wget
3314 fi
3315
3316 # If CDDBAVAIL is set to n, no CDDB read is done
3317 # If USEID3 is set to n, no ID3 tagging is done
3318 CDDBAVAIL=y
3319 USEID3=y
3320 USEID3V2=y
3321
3322 # There we go..
3323 # But before we get into business, let us chop off any GREP environmental
3324 # variables.
3325 GREP_OPTIONS=""
3326 GREP_COLOR=""
3327
3328 if [ -z "$OUTPUTDIR" ]; then
3329 OUTPUTDIR=$(pwd)
3330 fi
3331
3332 if [ -z "$WAVOUTPUTDIR" ]; then
3333 WAVOUTPUTDIR="$OUTPUTDIR"
3334 fi
3335
3336 # Load system defaults
3337 if [ -r /etc/abcde.conf ]; then
3338 . /etc/abcde.conf
3339 fi
3340 # Load user preference defaults
3341 if [ -r $HOME/.abcde.conf ]; then
3342 . $HOME/.abcde.conf
3343 fi
3344
3345 # By this time, we need some HTTPGETOPTS already defined.
3346 # If the user has defined a non-default HTTPGET method, we should not be empty.
3347
3348 if [ "$HTTPGETOPTS" = "" ] ; then
3349 case $HTTPGET in
3350 wget) HTTPGETOPTS="-q -nv -e timestamping=off -O -";;
3351 curl) HTTPGETOPTS="-f -s";;
3352 fetch)HTTPGETOPTS="-q -o -";;
3353 ftp) HTTPGETOPTS="-a -V -o - ";;
3354 *) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
3355 esac
3356 fi
3357
3358 # If the CDROM has not been set yet, find a suitable one.
3359 # If this is a devfs system, default to /dev/cdroms/cdrom0
3360 # instead of /dev/cdrom
3361 if [ "$CDROM" = "" ] ; then
3362 if [ -e /dev/cdroms/cdrom0 ]; then
3363 CDROM=/dev/cdroms/cdrom0
3364 elif [ -e /dev/cdrom ]; then
3365 CDROM=/dev/cdrom
3366 elif [ -e /dev/sr0 ]; then
3367 CDROM=/dev/sr0
3368 elif [ -e /dev/cd0c ]; then
3369 CDROM=/dev/cd0c
3370 elif [ -e /dev/acd0c ]; then
3371 CDROM=/dev/acd0c
3372 elif [ -e /dev/disk1 ]; then
3373 CDROM=/dev/disk1
3374 elif [ "$OSFLAVOUR" = "OSX" ] && [[ $(diskutil list) =~ CD_part.*(disk.)$'\n' ]]; then
3375 CDROM=/dev/${BASH_REMATCH[1]}
3376 fi
3377 fi
3378
3379 # We used to use EXTRAVERBOSE=y to turn on more debug output. Now
3380 # that's changed to a number to allow for more control. If
3381 # EXTRAVERBOSE=y, set it to 1 for backwards compatibility.
3382 if [ "$EXTRAVERBOSE" = "y" ]; then
3383 EXTRAVERBOSE=1
3384 fi
3385 if [ "$EXTRAVERBOSE" = "n" ]; then
3386 EXTRAVERBOSE=0
3387 fi
3388
3389 # Parse command line options
3390 #while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPq:r:Rs:S:t:T:vVxw:W: opt ; do
3391 while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPq:r:s:S:t:T:UvVxX:w:W:z opt ; do
3392 case "$opt" in
3393 1) ONETRACK=y ;;
3394 a) ACTIONS="$OPTARG" ;;
3395 A) EXPACTIONS="$OPTARG" ;;
3396 b) BATCHNORM=y ;;
3397 B) NOBATCHREPLAYGAIN=y ;;
3398 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
3399 C) DISCID="$( echo ${OPTARG#abcde.} | tr -d /)" ;;
3400 d) CDROM="$OPTARG" ;;
3401 D) set -x ;;
3402 h) usage; exit ;;
3403 e) ERASEENCODEDSTATUS=y ;;
3404 E) ENCODING="$OPTARG" ;;
3405 f) FORCE=y ;;
3406 g) NOGAP=y ;;
3407 i) INLINETAG=y ;;
3408 j) MAXPROCS="$OPTARG" ;;
3409 k) KEEPWAVS=y ;;
3410 l) LOWDISK=y ;;
3411 L) CDDBUSELOCAL=y ;;
3412 n) CDDBAVAIL=n ;;
3413 N) INTERACTIVE=n ;;
3414 m) DOSPLAYLIST=y ;;
3415 M) DOCUE=y ;;
3416 o) OUTPUTTYPE="$OPTARG" ;;
3417 p) PADTRACKS=y ;;
3418 P) USEPIPES=y ;;
3419 q) QUALITYLEVEL="$OPTARG" ;;
3420 r) REMOTEHOSTS="$OPTARG" ;;
3421 R) CDDBLOCALRECURSIVE=y ;;
3422 s) SHOWCDDBFIELDS="$OPTARG" ;;
3423 S) CDSPEEDVALUE="$OPTARG" ;;
3424 t) STARTTRACKNUMBER="$OPTARG" ;;
3425 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
3426 U) CDDBPROTO=5 ;;
3427 v)
3428 echo "This is abcde v$VERSION."
3429 echo "Usage: abcde [options] [tracks]"
3430 echo "abcde -h for extra help"
3431 exit
3432 ;;
3433 V) EXTRAVERBOSE=$(($EXTRAVERBOSE + 1)) ;;
3434 x) EJECTCD="y" ;;
3435 X) CUE2DISCID="$OPTARG" ;;
3436 w) COMMENT="$OPTARG" ;;
3437 W) if echo $OPTARG | grep "[[:digit:]]" > /dev/null 2>&1 ; then
3438 STARTTRACKNUMBER="${OPTARG}01"
3439 STARTTRACKNUMBERTAG="y"
3440 COMMENT="CD${OPTARG}"
3441 DISCNUMBER="${OPTARG}"
3442 else
3443 log error "argument of -W must be integer"
3444 exit 1
3445 fi
3446 ;;
3447 z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
3448 ?) usage; exit ;;
3449 esac
3450 done
3451
3452 shift $(($OPTIND - 1))
3453
3454 # Here it comes the worse part of the whole thing. From here until we start
3455 # ripping, we have a mixture of sanity checks, verifications, default settigs
3456 # and other crazy stuff that interdepends, but hey, someone has to do it.
3457
3458 # If NOCDDBQUERY is set, don't query the CDDB server.
3459 if [ "$NOCDDBQUERY" = "y" ]; then
3460 CDDBAVAIL="n"
3461 fi
3462
3463 # If the user specified a flac file, then switch to special flac mode
3464 if echo "$CDROM" | grep -i '.flac$' > /dev/null 2>&1 ; then
3465 if [ ! -f "$CDROM" ]; then
3466 log error "the defined file for FLAC ripping cannot be found" >&2
3467 exit 1
3468 fi
3469 vecho warning "switching to flac CDROMREADERSYNTAX..."
3470 CDROMREADERSYNTAX=flac
3471 # We have a builtin version of cue2discid...
3472 case "$CUE2DISCID" in
3473 builtin);;
3474 *) NEEDCUE2DISCID=y;;
3475 esac
3476 NEEDMETAFLAC=y
3477 EJECTCD=n
3478 fi
3479
3480 # If the user provided a DISCID, disable eject
3481 if [ -n "$DISCID" ] || [ "$CDROMREADERSYNTAX" = "flac" ]; then EJECTCD=n ; fi
3482
3483 # Check the available cd rippers in the system, from the ones we know.
3484 if [ "$CDROMREADERSYNTAX" = "" ]; then
3485 for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
3486 if new_checkexec $DEFAULT_CDROMREADER; then
3487 CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
3488 break
3489 fi
3490 done
3491 if [ "$CDROMREADERSYNTAX" = "" ]; then
3492 log error "no cdreader found in your PATH"
3493 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3494 exit 1
3495 fi
3496 fi
3497
3498 # Decide if we can continue.
3499 if [ "$ONETRACK" = "y" ]; then
3500 # FIXME # remove check as soon as we find out about the other readers
3501 case "$CDROMREADERSYNTAX" in
3502 flac) ;;
3503 cdparanoia) ;;
3504 cdda2wav | icedax) ;;
3505 *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
3506 exit 1 ;;
3507 esac
3508 if [ "$BATCHNORM" = "y" ]; then
3509 log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
3510 BATCHNORM=n
3511 fi
3512 if [ "$NOGAP" = "y" ]; then
3513 log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
3514 NOGAP=n
3515 fi
3516 # It does not matter how many tracks we want. In ONETRACK mode we grab them all
3517 # FIXME # allow ranges of tracks to be selected for onetrack ripping
3518 if [ $# -gt 0 ]; then
3519 log warning "ONETRACK mode selected, grabbing all tracks..."
3520 fi
3521 else
3522 while [ $# -gt 0 ]; do
3523 # Range parsing code courtesy of Vincent Ho
3524 # Cleaned up to use shell built-ins by Charles Steinkuehler
3525 if [ "${1#*[^0-9-]}" != "$1" ]; then
3526 log error "syntax error while processing track numbers ($1)"
3527 exit 1
3528 else
3529 RSTART=${1%%-*}
3530 REND=${1##*-}
3531 while [ ${RSTART:=1} -le ${REND:=0} ] ; do
3532 TRACKQUEUE="$TRACKQUEUE $RSTART"
3533 RSTART=$(( $RSTART + 1 ))
3534 done
3535 fi
3536 shift
3537 done
3538 fi
3539
3540 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
3541 # List of experimental actions: retag,transcode
3542
3543 # Determine what actions are to be done from $ACTIONS and set the
3544 # following environment variables for them:
3545 DOCDDB=n
3546 DOREAD=n
3547 DONORMALIZE=n
3548 DOPREPROCESS=n
3549 DOENCODE=n
3550 DOPOSTPROCESS=n
3551 DOTAG=n
3552 DOMOVE=n
3553 DOREPLAYGAIN=n
3554 DOPLAYLIST=n
3555 DOCLEAN=n
3556 ## FIXME ## Lets keep compatibility with -M
3557 [ "$DOCUE" != "y" ] && DOCUE=n
3558
3559 for ACTION in $(echo $ACTIONS | tr , \ )
3560 do
3561 case $ACTION in
3562 default) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOCLEAN=y;;
3563 cue) DOCUE=y ; MAKECUEFILE=y ;;
3564 cddb) DOCDDB=y;;
3565 read) DOREAD=y;;
3566 normalize) DONORMALIZE=y; DOREAD=y;;
3567 # preprocess) DOPREPROCESS=y; DOREAD=y;;
3568 encode) DOENCODE=y; DOREAD=y;;
3569 # postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
3570 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3571 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3572 replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
3573 playlist) DOCDDB=y; DOPLAYLIST=y;;
3574 clean) DOCLEAN=y;;
3575 esac
3576 done
3577
3578 if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
3579 # FIXME # should we abort on error or just inform the user?
3580 log warning "selected both normalize and replaygain actions"
3581 fi
3582
3583 for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
3584 case $SHOWCDDBFIELD in
3585 y*|Y*) SHOWCDDBYEAR="y";;
3586 g*|G*) SHOWCDDBGENRE="y";;
3587 *) ;;
3588 esac
3589 done
3590
3591 # At this point a CDROM has to be defined, so we check it exists.
3592 if [ X"$CDROM" != "X" ] ; then
3593 if ( [ "$CDROMREADERSYNTAX" = "cdda2wav" ] || [ "$CDROMREADERSYNTAX" = "icedax" ] ) && [ "$NEEDCDROMID" = "y" ] ; then
3594 if [ "$OSFLAVOUR" = "FBSD" ]; then
3595 if echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then :; else
3596 log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
3597 log error "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
3598 exit 1
3599 fi
3600 fi
3601 elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
3602 log error "CDROM device cannot be found."
3603 exit 1
3604 fi
3605 # avoid processing if we are not going to hit the CDROM.
3606 elif [ X"$DOREAD" = "Xy" ]; then
3607 log error "CDROM has not been defined or cannot be found"
3608 exit 1
3609 fi
3610
3611 # USEPIPES pre-tests, before we get into more serious stuff
3612 # Not compatible with:
3613 # - multiple outputs
3614 # - normalize
3615 # - lowdisk algorithm
3616 # - anything else?
3617 if [ X"$USEPIPES" = "Xy" ]; then
3618 if [ $(echo "$OUTPUTTYPE" | tr , \ | wc -w ) -gt 1 ]; then
3619 log error "Unix pipes not compatible with multiple outputs"
3620 exit 1
3621 fi
3622 if [ X"$DONORMALIZE" = "Xy" ]; then
3623 log error "Unix pipes not compatible with normalizer"
3624 # FIXME # Do we need to exit or shall we just disable the mode?
3625 exit 1
3626 fi
3627 if [ X"$BATCHNORM" = "Xy" ]; then
3628 log error "Unix pipes not compatible with BATCHNORM encoding"
3629 exit 1
3630 fi
3631 if [ X"$NOGAP" = "Xy" ]; then
3632 log error "Unix pipes not compatible with NOGAP encoding"
3633 exit 1
3634 fi
3635 if [ X"$DOENCODE" = "Xn" ]; then
3636 vecho warning "Disabling Unix pipes since we are not encoding!"
3637 USEPIPES=n
3638 fi
3639 if [ X"$LOWDISK" = "Xy" ]; then
3640 log error "Unix pipes not compatible with lowdisk algorithm"
3641 exit 1
3642 fi
3643 fi
3644
3645 # LOWDISK pre-tests, before we get into more problematic stuff
3646 # Not compatible with anything that needs all the files in the hard disc:
3647 # - BATCHNORM
3648 # - NOGAP lame mode
3649 if [ X"$LOWDISK" = "Xy" ]; then
3650 if [ X"$BATCHNORM" = "Xy" ]; then
3651 log error "Unix pipes not compatible with BATCHNORM encoding"
3652 exit 1
3653 fi
3654 if [ X"$NOGAP" = "Xy" ]; then
3655 log error "Unix pipes not compatible with NOGAP encoding"
3656 exit 1
3657 fi
3658 fi
3659
3660 # BATCHNORM pre-tests, before we get into serious problems
3661 # Not compatible with
3662 if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
3663 vecho warning "Disabling BATCHNORM since we are not normalizing!"
3664 BATCHNORM=n
3665 fi
3666
3667 # Check the encoding format from the ones available in the system, if nothing has been configured.
3668 if [ X"$OUTPUTTYPE" = "X" ]; then
3669 for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
3670 DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
3671 DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
3672 if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
3673 OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
3674 vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
3675 break
3676 fi
3677 done
3678 if [ X"$OUTPUTTYPE" = "X" ]; then
3679 log error "no encoder found in the PATH"
3680 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3681 exit 1
3682 fi
3683 fi
3684
3685 # Decide which CDROM reader we're gonna use
3686 case "$CDROMREADERSYNTAX" in
3687 cdparanoia|debug)
3688 CDROMREADER="$CDPARANOIA"
3689 CDROMREADEROPTS="$CDPARANOIAOPTS"
3690 ;;
3691 cdda2wav | icedax)
3692 CDROMREADER="$CDDA2WAV"
3693 CDROMREADEROPTS="$CDDA2WAVOPTS"
3694 ;;
3695 dagrab)
3696 CDROMREADER="$DAGRAB"
3697 CDROMREADEROPTS="$DAGRABOPTS"
3698 ;;
3699 cddafs)
3700 CDROMREADER="$CDDAFS"
3701 CDROMREADEROPTS="$CDDAFSOPTS"
3702 ;;
3703 flac)
3704 CDROMREADER="$FLAC"
3705 CDROMREADEROPTS="$FLACOPTS"
3706 ;;
3707 esac
3708
3709 # There's only one normalize...
3710 case "$NORMALIZERSYNTAX" in
3711 default|normalize)
3712 NORMALIZER="$NORMALIZE"
3713 NORMALIZEROPTS="$NORMALIZEOPTS"
3714 ;;
3715 esac
3716
3717 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
3718 if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
3719 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr \ \|| tr , \ | tr \| \ )"; do
3720 case "$OUTPUT" in
3721 vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3722 mp3:*) MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3723 flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3724 spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3725 mpc:*) MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3726 m4a:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3727 esac
3728 done
3729 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
3730 TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
3731 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
3732 done
3733 OUTPUTTYPE="$TEMPOUTPUTTYPE"
3734 fi
3735
3736 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
3737 # for flacs and speexenc for speex and mppenc for mpps and faac for m4as
3738
3739 # Getting ready for multiple output changes
3740 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
3741 do
3742 case $OUTPUT in
3743 vorbis|ogg)
3744 [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
3745 [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
3746 [ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
3747 OGGOUTPUTCONTAINER=ogg
3748 ;;
3749 mp3)
3750 [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
3751 [ "$DOTAG" = "y" ] && NEEDTAGGER=y
3752 [ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
3753 ;;
3754 flac)
3755 [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
3756 [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
3757 [ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
3758 [ "$ONETRACK" = "y" ] && [ "$DOCUE" = "y" ] && NEEDMETAFLAC=y
3759 ;;
3760 spx)
3761 [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
3762 # [ "$DOREPLAYGAIN" = "y" ] &&
3763 ;;
3764 mpc)
3765 [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc
3766 [ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y
3767 ;;
3768 m4a)
3769 [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
3770 [ "$DOTAG" = "y" ] && CHECKATOMICPARSLEY=y
3771 ;;
3772 wav)
3773 if [ "$KEEPWAVS" = "y" ]; then
3774 vecho "Setting the KEEPWAVS option, since the resulting wav files were requested..."
3775 fi
3776 KEEPWAVS=move
3777 ;;
3778 *) log error "Invalid OUTPUTTYPE defined"
3779 exit 1
3780 ;;
3781 esac
3782 done
3783
3784 # decide which encoder
3785 case "$MP3ENCODERSYNTAX" in
3786 lame)
3787 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
3788 MP3ENCODER="$LAME"
3789 ;;
3790 toolame)
3791 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$TOOLAMEOPTS}"
3792 MP3ENCODER="$TOOLAME"
3793 ;;
3794 gogo)
3795 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
3796 MP3ENCODER="$GOGO"
3797 ;;
3798 bladeenc)
3799 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
3800 MP3ENCODER="$BLADEENC"
3801 ;;
3802 l3enc)
3803 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
3804 MP3ENCODER="$L3ENC"
3805 ;;
3806 xingmp3enc)
3807 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
3808 MP3ENCODER="$XINGMP3ENC"
3809 ;;
3810 mp3enc)
3811 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
3812 MP3ENCODER="$MP3ENC"
3813 ;;
3814 esac
3815 case "$OGGENCODERSYNTAX" in
3816 vorbize)
3817 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
3818 OGGENCODER="$VORBIZE"
3819 ;;
3820 oggenc)
3821 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
3822 OGGENCODER="$OGGENC"
3823 ;;
3824 esac
3825 case "$FLACENCODERSYNTAX" in
3826 flac)
3827 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
3828 FLACENCODER="$FLAC"
3829 if [ "$DOREPLAYGAIN" = "y" ]; then
3830 FLACENCODEROPTS="${FLACENCODEROPTS} --replay-gain"
3831 fi
3832 # FLAC streams can be encapsulated on a Ogg transport layer
3833 if echo "$FLACENCODEROPTS" | grep -E -- "(^| )--ogg($| )" > /dev/null 2>&1 ;then
3834 log error "FLAC on an Ogg container is not yet supported"
3835 log error "due to problem with adding comments to such files"
3836 exit 1
3837 FLACOUTPUTCONTAINER=ogg
3838 else
3839 FLACOUTPUTCONTAINER=flac
3840 fi
3841 ;;
3842 esac
3843 case "$SPEEXENCODERSYNTAX" in
3844 speexenc)
3845 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
3846 SPEEXENCODER="$SPEEXENC"
3847 ;;
3848 esac
3849 case "$MPPENCODERSYNTAX" in
3850 mppenc)
3851 MPPENCODEROPTS="${MPPENCODEROPTSCLI:-$MPPENCOPTS}"
3852 MPPENCODER="$MPPENC"
3853 ;;
3854 esac
3855 case "$AACENCODERSYNTAX" in
3856 faac)
3857 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
3858 AACENCODER="$AACENC"
3859 ;;
3860 esac
3861
3862 # and which tagger
3863 if [ "$ID3TAGV" = "1" ]; then
3864 TAGGER="$ID3"
3865 TAGGEROPTS="$ID3OPTS"
3866 else
3867 TAGGER="$ID3V2"
3868 TAGGEROPTS="$ID3V2OPTS"
3869 fi
3870
3871 # NOGAP is specific to lame. Other encoders fail ...
3872 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
3873 log warning "the NOGAP option is specific to lame. Deactivating..."
3874 NOGAP=n
3875 fi
3876
3877 # Options for mkcue
3878 case "$CUEREADERSYNTAX" in
3879 default|mkcue)
3880 CUEREADEROPTS="${CDROM}"
3881 CUEREADER="$MKCUE"
3882 ;;
3883 esac
3884
3885 # which information retrieval tool are we using?
3886 case "$CDDBTOOL" in
3887 cddb) ;;
3888 musicbrainz) ;;
3889 esac
3890
3891 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
3892 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
3893 log error "FLAC on an Ogg container is not yet supported"
3894 log error "due to problem with adding comments to such files"
3895 exit 1
3896 OGGOUTPUTCONTAINER=ogg.ogg
3897 FLACOUTPUTCONTAINER=flac.ogg
3898 vecho warning "modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
3899 fi
3900
3901 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
3902
3903 if [ "$ENCNICE" ]; then
3904 ENCNICE="-n $ENCNICE"
3905 fi
3906 if [ "$READNICE" ]; then
3907 READNICE="-n $READNICE"
3908 fi
3909 if [ "$DISTMP3NICE" ]; then
3910 DISTMP3NICE="-n $DISTMP3NICE"
3911 fi
3912
3913 # Don't check for stuff if it's not needed
3914 if [ "$REMOTEHOSTS" ]; then
3915 NEEDDISTMP3=y
3916 fi
3917 if [ "$DONORMALIZE" = "y" ]; then
3918 NEEDNORMALIZER=y
3919 fi
3920 if [ "$EJECTCD" = "y" ]; then
3921 NEEDEJECT=y
3922 fi
3923 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
3924 if [ "$CDDBMETHOD" = "cddb" ]; then
3925 NEEDHTTPGET=y
3926 elif [ "$CDDBMETHOD" = "musicbrainz" ]; then
3927 :
3928 fi
3929 fi
3930 if [ "$DOCUE" = "y" ]; then
3931 NEEDCUEREADER=y
3932 fi
3933
3934 if [ X"$CDSPEEDVALUE" != "X" ] && [ "$DOREAD" = "y" ]; then
3935 case "$CDROMREADERSYNTAX" in
3936 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
3937 ### FIXME ### translate "cue2discid" from python to bash
3938 flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ; CDSPEEDVALUE="" ;;
3939 *) NEEDCDSPEED=y ;;
3940 esac
3941 fi
3942
3943 ###USEPIPESSUPPORT###
3944
3945 # Rippers with USEPIPE support
3946 # FIXME # Include here all the rippers we can figure out support pipes
3947 PIPERIPPER_cdparanoia="-"
3948 PIPERIPPER_debug="-"
3949 PIPERIPPER_flac="-c "
3950
3951 # Encoders with USEPIPE support
3952 # FIXME # Include here all the encoders we can figure out support pipes
3953 PIPE_lame="-"
3954 PIPE_bladeenc="-"
3955 PIPE_oggenc="-"
3956 PIPE_flac="-"
3957
3958 # Figure out if we can use pipes with the ripper/encoder combination
3959 # exit otherwise
3960 if [ "$USEPIPES" = "y" ]; then
3961 PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
3962 case "$OUTPUT" in
3963 mp3)
3964 PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
3965 vorbis|ogg)
3966 PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
3967 flac)
3968 PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
3969 spx)
3970 PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
3971 mpc)
3972 PIPEENCODERSVARCHECK="PIPE_$MPPENCODER" ;;
3973 esac
3974 decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
3975 if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
3976 [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
3977 log error "no support for pipes with given ripper"
3978 log error "read the USEPIPES file from the source tarball to get help."
3979 log error "On a Debian system, it is under /usr/share/doc/abcde/USEPIPES.gz"
3980 exit 1;
3981 fi
3982 decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
3983 if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
3984 [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
3985 log error "no support for pipes with given encoder"
3986 log error "read the USEPIPES file from the source tarball to help"
3987 log error "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz"
3988 exit 1;
3989 fi
3990 fi
3991
3992 # Make sure a buncha things exist
3993 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
3994 $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
3995 $AACENCODER $CDDBTOOL \
3996 ${NEEDATOMICPARSLEY+$ATOMICPARSLEY} \
3997 ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
3998 ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
3999 ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
4000 ${NEEDDISKUTIL+diskutil} ${NEEDCDSPEED+$CDSPEED} \
4001 ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
4002 ${NEEDMPPGAIN+$MPPGAIN} ${NEEDCUEREADER+$CUEREADER} \
4003 ${NEEDCUE2DISCID+$CUE2DISCID}
4004 do
4005 checkexec "$X"
4006 done
4007
4008 if [ "$CHECKATOMICPARSLEY" = "y" ]; then
4009 if ! new_checkexec "$ATOMICPARSLEY"; then
4010 echo "WARNING: $ATOMICPARSLEY Not Found Not Post-Tagging!"
4011 DOTAG='n'
4012 else
4013 echo "Using $ATOMICPARSLEY To Tag AAC Tracks."
4014 fi
4015 fi
4016
4017 # And last but not least, check if we can diff between files. We do not abort,
4018 # since diffing is not critical...
4019 if [ -x $(which $DIFF) ]; then :; else
4020 vecho warning "Disabling diff since we cannot find it in the \$PATH..."
4021 DIFF=""
4022 fi
4023
4024 ## Now that we have metaflac, check if we need cue2discid
4025 #case $CDROMREADERSYNTAX in
4026 # flac)
4027 # TRACKINFO=$($METAFLAC --show-tag=CDDB $CDROM | cut -d"=" -f2 | grep -E "[a-f0-9]{8}")
4028 # if [ "$TRACKINFO" = "" ]; then
4029 # checkexec ${NEEDCUE2DISCID+$CUE2DISCID}
4030 # fi
4031 # ;;
4032 #esac
4033
4034 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
4035 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
4036 HTTPGET="$HTTPGET $HTTPGETOPTS"
4037
4038 # Here it used to say:
4039 # One thousand lines in, we can start doing stuff with things
4040 # Well, right now we are at line 3737 ;)
4041
4042 # Export needed things so they can be read in this subshell
4043 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
4044 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
4045
4046 if [ "$DOREAD" = "y" ]; then
4047 # User-definable function to set some things. Use it for
4048 # - closing the CD tray with eject -t
4049 # - set the CD speed value with eject -x
4050 vecho -n "Executing customizable pre-read function... "
4051
4052 pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
4053
4054 vecho "done."
4055 fi
4056
4057 # Get ABCDETEMPDIR created and status file initialized
4058 do_discid
4059
4060 if [ "$DOCDDB" = "y" ]; then
4061 # start with a sane default:
4062 CDDBLOCALSTATUS=notfound
4063 if [ $CDDBUSELOCAL = "y" ]; then
4064 do_localcddb
4065 fi
4066 if checkstatus cddb-choice > /dev/null; then
4067 :
4068 else
4069 if [ "$CDDBLOCALSTATUS" = "notfound" ] ; then
4070 case "$CDDBMETHOD" in
4071 cddb)
4072 do_cddbstat
4073 do_cddbquery
4074 do_cddbread
4075 ;;
4076 musicbrainz)
4077 do_musicbrainz
4078 ;;
4079 esac
4080 fi
4081 CHOICE=$(checkstatus cddb-choice)
4082 if [ $CHOICE = 0 ] ; then
4083 # We don't have any information at all; try to fall back
4084 # to CD-Text for basic information
4085 vecho "No CDDB information found, trying cdtext from the CD"
4086 do_cdtext
4087 fi
4088 fi
4089 do_cddbedit
4090
4091 eval "$($CDDBTOOL parse "$CDDBDATA")"
4092 fi
4093
4094 # Before reading tracks, we set the speed of the device
4095
4096 if [ X"$CDSPEEDVALUE" != "X" ]; then
4097 case "$CDROMREADERSYNTAX" in
4098 cdparanoia|debug) ;;
4099 flac) ;;
4100 *) do_cdspeed ;;
4101 esac
4102 fi
4103
4104 # Define the first and last track, since we might need them later in several places
4105 FIRSTTRACK=$( get_first $TRACKQUEUE )
4106 LASTTRACK=$( get_last $TRACKQUEUE )
4107
4108 if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
4109 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
4110 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
4111 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
4112 fi
4113
4114 if checkstatus onetrack ; then ONETRACK=y ; fi
4115
4116 if [ "$ONETRACK" = "y" ]; then
4117 # Reuse the CUEFILE in case we created it (now or in a previous run)
4118 if CUEFILE=$(checkstatus cuefile); then
4119 IMPORTCUESHEET=y
4120 fi
4121 fi
4122
4123 # Create playlist if needed (backgroundable) and start reading in tracks
4124
4125 (
4126
4127 if [ ! "$ONETRACK" = "y" ]; then
4128 if [ "$DOPLAYLIST" = "y" ]; then
4129 echo Creating playlist... >&2
4130 do_playlist
4131 fi
4132 fi
4133
4134 # For the lowdisk option, only one program is running at once so the encoder
4135 # can be unsilenced right away.
4136 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
4137 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4138 fi
4139
4140 if [ "$ONETRACK" = "y" ]; then
4141 TRACKS="$FIRSTTRACK"
4142 if [ "$USEPIPES" = "y" ]; then
4143 if checkstatus readencodetrack-$FIRSTTRACK; then :; else
4144 do_cdread onetrack $FIRSTTRACK $LASTTRACK | do_encode $FIRSTTRACK %local0% > /dev/null 2>&1
4145 fi
4146 else
4147 if checkstatus readtrack-$FIRSTTRACK; then :; else
4148 do_cdread onetrack $FIRSTTRACK $LASTTRACK
4149 fi
4150 fi
4151 else
4152 for UTRACKNUM in $TRACKQUEUE
4153 do
4154 if [ "$DOREAD" = "y" ]; then
4155 if [ "$USEPIPES" = "y" ]; then
4156 if checkstatus readencodetrack-$UTRACKNUM; then :; else
4157 # Read, pipe, shut up!
4158 do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
4159 fi
4160 else
4161 if checkstatus readtrack-$UTRACKNUM; then :; else
4162 do_cdread $UTRACKNUM
4163 fi
4164 if [ "$?" != "0" ]; then
4165 # CD read failed - don't give the goahead to
4166 # the encoder
4167 echo NO
4168 exit
4169 fi
4170 fi
4171 fi
4172 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ]; then
4173 :
4174 else
4175 # If we are not reading, set the encode output to loud already, so
4176 # that we can see the output of the first track.
4177 if [ "$MAXPROCS" = "1" ] && [ ! "$DOREAD" = "y" ]; then
4178 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4179 fi
4180 echo NEXTTRACK # Get the encoder machine churning again
4181 if [ "$DOREAD" = "y" ]; then
4182 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
4183 until checkstatus encodetrack-$UTRACKNUM
4184 do
4185 if checkerrors encodetrack-$UTRACKNUM; then
4186 break
4187 fi
4188 sleep 2
4189 done
4190 fi
4191 fi
4192 fi
4193 done
4194 fi
4195
4196 # Now that we're done the encoding can be loud again -
4197 # if we're not using SMP.
4198 if [ "$MAXPROCS" = "1" ]; then
4199 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4200 fi
4201
4202 # All tracks read, start encoding.
4203 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ] || [ "$ONETRACK" = "y" ]; then
4204 echo NEXTTRACK
4205 fi
4206
4207 # Execute the user-defined post_read funtion before ejecting CD
4208 post_read
4209
4210 # We are now finished with the cdrom - it can be safely ejected. Note that
4211 # abcde will not have completed yet.
4212 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
4213 # We check if the disk we are processing is actually the disk inside the
4214 # CD tray. If not, we do not eject the CD, since it might be so that the
4215 # user ejected it manually.
4216 #CURRENTTRACKINFO=$($CDDISCID $CDROM)
4217 #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
4218 # More FreeBSD bits.
4219 if [ X"$(uname)" = X"FreeBSD" ] ; then
4220 # FreeBSD eject uses the EJECT environment variable to name the CDROM
4221 # but in this script EJECT is in the envionment and names the program
4222 eject=$EJECT
4223 unset EJECT
4224 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
4225 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
4226 $eject $EJECTOPTS $cd
4227 elif [ X"$(uname)" = X"Darwin" ] ; then
4228 diskutil eject ${CDROM#/dev/} 0
4229 else
4230 $EJECT $EJECTOPTS "$CDROM"
4231 fi
4232 #fi
4233 fi
4234
4235 ) | (
4236
4237 ## Do we need to pre-process
4238 #if [ x"$PREPROCESS" = "x" ] ; then
4239 # cat
4240 #else
4241 # for PRETRACKNUM in $TRACKQUEUE
4242 # do
4243 # read GOAHEAD
4244 # if [ "$GOAHEAD" = "NO" ]; then break; fi
4245 # PREPROCEED=
4246 # until [ $PREPROCEED ]
4247 # do
4248 # if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
4249 # # all locations are working, wait and try again later
4250 # if [ ! $PREPROCEED ]; then sleep 3; fi
4251 # done
4252 # ( do_preprocess $PRETRACKNUM
4253 # echo "NEXTTRACK"
4254 # ) &
4255 # done
4256 #fi
4257 #
4258 #) | (
4259
4260 # In BATCHNORM and/or NOGAP modes, we want all tracks to be read first.
4261 #BACK
4262 if [ "$BATCHNORM" = "y" ] || [ "$NOGAP" = "y" ]; then
4263 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
4264 if [ "$GOAHEAD" = "NO" ]; then break; fi
4265 for LASTTRACK in $TRACKQUEUE; do :; done
4266 if checkstatus readtrack-$LASTTRACK; then
4267 if [ "$DONORMALIZE" = "y" ] && [ "$BATCHNORM" = "y" ]; then
4268 if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
4269 if checkerrors batch-normalize; then exit 1; fi
4270 fi
4271 if [ "$DOENCODE" = "y" ] && [ "$NOGAP" = "y" ]; then
4272 if [ "$DONORMALIZE" = "y" ]; then
4273 for UTRACKNUM in $TRACKQUEUE
4274 do
4275 if checkstatus readtrack-$UTRACKNUM; then
4276 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
4277 fi
4278 done
4279 fi
4280 if checkstatus encodetrack-$LASTTRACK; then :; else do_nogap_encode; fi
4281 if checkerrors nogap-encode; then exit 1; fi
4282 fi
4283 fi
4284 fi
4285
4286 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
4287 if [ "$ONETRACK" = "y" ] ; then
4288 TRACKQUEUE="$FIRSTTRACK"
4289 TRACKS="$FIRSTTRACK"
4290 fi
4291
4292 # Do the encoding, including parallelization of remote encoding
4293 # Figure out where each track is going to be encoded
4294 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
4295 if [ "$MAXPROCS" != "0" ]; then
4296 for NUM in $(f_seq_row 1 "$MAXPROCS")
4297 do
4298 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
4299 done
4300 fi
4301 # Strip whitespace
4302 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
4303 for UTRACKNUM in $TRACKQUEUE
4304 do
4305 # Wait for our cue
4306 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
4307 if [ "$GOAHEAD" = "NO" ]; then break; fi
4308 # find out where this track is to be encoded
4309 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
4310 # Make sure we have a place to encode this, if not, exit stage right
4311 if [ -z "$ENCODELOCATIONS" ]; then
4312 continue
4313 fi
4314 PROCEED=
4315 until [ $PROCEED ]
4316 do
4317 for LOCATION in $ENCODELOCATIONS
4318 do
4319 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
4320 # check first if a track has ever been assigned to this location
4321 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
4322 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
4323 if checkerrors encodetrack-$PREVIOUSTRACK; then
4324 for TEMPLOCATION in $ENCODELOCATIONS
4325 do
4326 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
4327 TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
4328 fi
4329 done
4330 ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
4331 ABORT=y
4332 PROCEED=y
4333 break
4334 fi
4335 # We're still here, this location must have been previously assigned,
4336 # and last completed without error - check if it's done with the
4337 # previous track yet
4338 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
4339 done
4340 # all locations are working, wait and try again later
4341 if [ ! $PROCEED ]; then sleep 3; fi
4342 done
4343 # Record the location we're about to encode the next track at
4344 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
4345 fi
4346 # Don't proceed with the rest of the loop if we can't encode
4347 if [ "$ABORT" ]; then continue; fi
4348 ## FIXME ## Add here
4349 ## run_command tagtrack-$OUTPUT-$1 $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="$ABCDETEMPDIR/$CUEFILE"} --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
4350 # Set TRACKNUM, TRACKNAME
4351 if [ -e "$CDDBDATA" ]; then
4352 if [ "$ONETRACK" = "y" ]; then
4353 TRACKNAME="$DALBUM"
4354 TRACKNUM="$FIRSTTRACK"
4355 splitvarious
4356 else
4357 TRACKNUM=$UTRACKNUM
4358 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
4359 getcddbinfo TRACKNAME
4360 splitvarious
4361 fi
4362 fi
4363 # You can't encode a file which needs to be normalized before finishing
4364 # You can't tag a file before it's finished encoding -
4365 # thus all of this is backgrounded together
4366 (
4367 if [ "$DONORMALIZE" = "y" ]; then
4368 if checkstatus readtrack-$UTRACKNUM; then
4369 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
4370 fi
4371 fi
4372 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
4373 if checkstatus readtrack-$UTRACKNUM; then
4374 #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
4375 if [ "$DONORMALIZE" = "y" ]; then
4376 if checkstatus normalizetrack-$UTRACKNUM; then
4377 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4378 fi
4379 else
4380 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4381 fi
4382 fi
4383 fi
4384 if [ "$DOTAG" = "y" ]; then
4385 if checkstatus encodetrack-$UTRACKNUM; then
4386 if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
4387 fi
4388 # Lets tag the cue file
4389 if checkstatus cleancuefile >/dev/null; then :; else
4390 if checkstatus cuefile >/dev/null ; then
4391 do_cleancue
4392 fi
4393 fi
4394 fi
4395 if [ "$DOMOVE" = "y" ]; then
4396 if checkstatus tagtrack-$UTRACKNUM; then
4397 if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
4398 fi
4399 fi
4400 ) &
4401 done
4402
4403
4404 # Go through it again and make sure there's no distmp3 stragglers, otherwise
4405 # we'll delete the files they're working on
4406 # Do NOT play ball if there is no ball to play (so ABORT if needed)
4407 ## FIXME ## Check also for files which are encoded using PIPEs.
4408 if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ] && [ ! "$ABORT" ]; then
4409 PROCEED=
4410 until [ $PROCEED ]
4411 do
4412 PROCEED=y
4413 for LOCATION in $ENCODELOCATIONS
4414 do
4415 CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
4416 # "How can he give us a status update, if he's DEAD?"
4417 if checkstatus encodetrack-$CHECKTRACK; then
4418 continue
4419 fi
4420 # Nothing to see here please go quietly back to your homes
4421 if [ -z "$CHECKTRACK" ]; then continue; fi
4422 # You're still here? Maybe there is something...
4423 if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
4424 done
4425 # hold up
4426 if [ ! $PROCEED ]; then sleep 5; fi
4427 done
4428 fi
4429 # If the above didn't catch the stragglers, this will
4430 wait
4431 if [ "$DOREPLAYGAIN" = "y" ]; then
4432 do_replaygain
4433 fi
4434
4435 # Execute the user-defined post_encode function before cleaning up
4436 post_encode
4437
4438 # Check to see if run_command logged any errors
4439 if [ -f "$ABCDETEMPDIR/errors" ]; then
4440 log error "The following commands failed to run:"
4441 cat "$ABCDETEMPDIR/errors"
4442 # Don't clean up
4443 DOCLEAN=n
4444 fi
4445 if [ "$KEEPWAVS" = "y" ];then
4446 # Don't clean up
4447 DOCLEAN=n
4448 fi
4449 # Check if we have moved all the formats we had previously encoded, if we are not using the FORCE.
4450 if [ "$DOCLEAN" = "y" ] && [ ! "$FORCE" = "y" ]; then
4451 ENCODED_FORMATS=$(grep -E "^encodetrack-(.{3,6})-(.{1,2})$" "$ABCDETEMPDIR/status" | cut -d"-" -f2 | sort -u | tr '\n' '|')
4452 MOVED_FORMATS=$(grep -E "^movetrack-output-(.{3,6})$" "$ABCDETEMPDIR/status" | cut -d"-" -f3 | sort -u | tr '\n' '|')
4453 if [ "$ENCODED_FORMATS" != "$MOVED_FORMATS" ]; then
4454 log warning "The encoded formats does not match with the moved ones"
4455 log warning "Formats encoded: $( echo $ENCODED_FORMATS | tr "|" " " )"
4456 log warning "Formats moved: $( echo $MOVED_FORMATS | tr "|" " " )"
4457 log warning "Use \"abcde -a clean -f -C $DISCID\" to force the removal of the remaining data."
4458 DOCLEAN=n
4459 fi
4460 fi
4461 if [ "$DOCLEAN" = "y" ]; then
4462 # Wipe all the evidence
4463 # Gimme gimme gimme some more time!
4464 sleep 5
4465 rm -rf "$ABCDETEMPDIR"
4466 echo "Finished."
4467 else
4468 echo "Finished. Not cleaning $ABCDETEMPDIR."
4469 fi
4470 )
4471 exit 0
4472
4473 # b:is_bash
4474 # vim:tabstop=4