start 2.5.3 development
[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 "-n No lookup. Don't query CDDB, just create and use template"
47 echo "-N Noninteractive. Never prompt for anything"
48 echo "-m Modify playlist to include CRLF endings, to comply with some players"
49 #echo " WARNING: Deprecated. Use \"cue\" action"
50 #echo "-M Create a CUE file"
51 echo "-o <type1[,type2]...>"
52 echo " Output file type(s) (vorbis,mp3,flac,spx,mpc,wav,m4a). Defaults to vorbis"
53 echo "-p Pad track numbers with 0's (if less than 10 tracks)"
54 echo "-P Use UNIX pipes to read+encode without wav files"
55 echo "-q <level>"
56 echo " Set quality level (high,medium,low)"
57 echo "-r <host1[,host2]...>"
58 echo " Also encode on these remote hosts"
59 echo "-R Use local CDDB in recursive mode"
60 echo "-s <field>"
61 echo " Show fields from the CDDB info (year,genre)"
62 echo "-S <#> Set the CD speed"
63 echo "-t <#> Start the track numbering at a given number"
64 echo "-T <#> Same as -t but modifies tag numbering"
65 echo "-U Do NOT use UNICODE (UTF8) tags and comments"
66 echo "-v Show version number and exit"
67 echo "-V Be a bit more verbose about what is happening behind the scenes"
68 echo "-x Eject CD after all tracks are read"
69 echo "-w <comment>"
70 echo " Add a comment to the CD tracks"
71 echo "-W <#> Concatenate CDs: -T #01 -w \"CD #\""
72 echo "-z Use debug CDROMREADERSYNTAX option (needs cdparanoia)"
73 echo ""
74 echo "Tracks is a space-delimited list of tracks to grab."
75 echo "Ranges specified with hyphens are allowed (i.e., 1-5)."
76 echo ""
77 #echo "Double hyphens are used to concatenate tracks"
78 }
79
80 addstatus ()
81 {
82 echo "$@" >> "$ABCDETEMPDIR/status"
83 }
84
85 # log [level] [message]
86 #
87 # log outputs the right message in a common format
88 log ()
89 {
90 BLURB="$1"
91 shift
92 case $BLURB in
93 error) echo "[ERROR] abcde: $@" >&2 ;;
94 warning) echo "[WARNING] $@" >&2 ;;
95 info) echo "[INFO] $@" ;;
96 esac
97 }
98
99 # Funtions to replace the need of seq, which is too distribution dependant.
100 f_seq_row ()
101 {
102 i=$1
103 while [ $i -ne `expr $2 + 1` ]
104 do
105 echo $i
106 i=`expr $i + 1`
107 done
108 }
109
110 f_seq_line ()
111 {
112 i=$1
113 if echo $i | grep "[[:digit:]]" > /dev/null 2>&1 ; then
114 while [ $i -ne `expr $2 + 1` ]
115 do
116 printf $i" "
117 i=`expr $i + 1`
118 done
119 echo
120 else
121 log error "syntax error while processing track numbers ($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_$MPPENCODER"
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 NUM_RESPONSES=$(echo ${ABCDETEMPDIR}/cddbread.* | wc -w)
2303 if [ "$NUM_RESPONSES" -eq 1 ] ; then
2304 # One exact match
2305 echo -n "Retrieved 1 Musicbrainz match..." >> "$ABCDETEMPDIR/cddbchoices"
2306 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
2307 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2308 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2309 ATITLE=$(grep -e '^DTITLE=' ${ABCDETEMPDIR}/cddbread.1 | cut -c8- )
2310 echo "200 none ${ATITLE}" >> "$ABCDETEMPDIR/cddbquery"
2311 # List out disc title/author and contents
2312 echo ---- ${ATITLE} ---- >> "$ABCDETEMPDIR/cddbchoices"
2313 for TRACK in $(f_seq_row 1 $TRACKS)
2314 do
2315 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2316 done
2317 echo >> "$ABCDETEMPDIR/cddbchoices"
2318 elif [ "$NUM_RESPONSES" -eq 0 ] ; then
2319 # No matches. Use the normal cddb template for the user to
2320 # fill in
2321 echo "No Musicbrainz match." >> "$ABCDETEMPDIR/cddbchoices"
2322 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2323 # List out disc title/author and contents of template
2324 echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
2325 UNKNOWNDISK=y
2326 for TRACK in $(f_seq_row 1 $TRACKS)
2327 do
2328 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2329 done
2330 echo >> "$ABCDETEMPDIR/cddbchoices"
2331 echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
2332 echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
2333 echo 503 > "$ABCDETEMPDIR/cddbquery"
2334 else
2335 echo "210 Found exact matches, list follows (until terminating .)" > "$ABCDETEMPDIR/cddbquery"
2336 echo "Multiple Musicbrainz matches:" >> "$ABCDETEMPDIR/cddbchoices"
2337 for file in $ABCDETEMPDIR/cddbread.*
2338 do
2339 X=$(echo $file | sed 's/^.*cddbread\.//g')
2340 echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
2341 ATITLE=$(grep -e '^DTITLE=' ${ABCDETEMPDIR}/cddbread.$X | cut -c8- )
2342 echo "none ${ATITLE}" >> "$ABCDETEMPDIR/cddbquery"
2343 # List out disc title/author and contents
2344 echo "#$X: ---- ${ATITLE} ----" >> "$ABCDETEMPDIR/cddbchoices"
2345 for TRACK in $(f_seq_row 1 $TRACKS)
2346 do
2347 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2348 done
2349 echo >> "$ABCDETEMPDIR/cddbchoices"
2350 done
2351 echo "." >> "$ABCDETEMPDIR/cddbquery"
2352 fi
2353 echo "musicbrainz-readcomplete" >> "$ABCDETEMPDIR/status"
2354 fi
2355 }
2356
2357 # do_cddbstat
2358 do_cddbstat ()
2359 {
2360 # Perform CDDB protocol version check if it hasn't already been done
2361 if checkstatus cddb-statcomplete; then :; else
2362 if [ "$CDDBAVAIL" = "n" ]; then
2363 ERRORCODE=no_query
2364 echo 503 > "$ABCDETEMPDIR/cddbstat"
2365 else
2366 rc=1
2367 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
2368 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
2369 while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
2370 vecho "Checking CDDB server status..."
2371 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
2372 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
2373 case "$RESPONSECODE" in
2374 210) # 210 OK, status information follows (until terminating `.')
2375 rc=0
2376 ;;
2377 501) # 501 Illegal CDDB protocol level: <n>.
2378 CDDBPROTO=`expr $CDDBPROTO - 1`
2379 ;;
2380 *) # Try a cddb query, since freedb2.org doesn't support the stat or ver commands
2381 # FreeDB TESTCD disc-id is used for query
2382 $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST 03015501 1 296 344 > "$ABCDETEMPDIR/cddbstat"
2383 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
2384 case "$RESPONSECODE" in
2385 2??) # Server responded, everything seems OK
2386 rc=0
2387 ;;
2388 esac
2389 ;;
2390 esac
2391 done
2392 if test $rc -eq 1; then
2393 CDDBAVAIL="n"
2394 fi
2395 fi
2396 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
2397 fi
2398 }
2399
2400
2401 # do_cddbquery
2402 do_cddbquery ()
2403 {
2404 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
2405 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
2406
2407 # Perform CDDB query if it hasn't already been done
2408 if checkstatus cddb-querycomplete; then :; else
2409 if [ "$CDDBAVAIL" = "n" ]; then
2410 ERRORCODE=no_query
2411 echo 503 > "$ABCDETEMPDIR/cddbquery"
2412 # The default CDDBLOCALSTATUS is "notfound"
2413 # This part will be triggered if the user CDDB repo does not
2414 # contain the entry, or if we are not trying to use the repo.
2415 else
2416 vecho "Querying the CDDB server..."
2417 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
2418 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
2419 $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
2420 ERRORCODE=$?
2421 case $ERRORCODE in
2422 0) # success
2423 ;;
2424 12|13|14)
2425 # no match found in database,
2426 # wget/fetch error, or user requested not to use CDDB
2427 # Make up an error code (503) that abcde
2428 # will recognize in do_cddbread
2429 # and compensate by making a template
2430 echo 503 > "$ABCDETEMPDIR/cddbquery"
2431 ;;
2432 *) # strange and unknown error
2433 echo ERRORCODE=$ERRORCODE
2434 echo "abcde: $CDDBTOOL returned unknown error code"
2435 ;;
2436 esac
2437 fi
2438 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
2439 fi
2440 }
2441
2442 # do_cddbread
2443 do_cddbread ()
2444 {
2445 # If it's not to be used, generate a template.
2446 # Then, display it (or them) and let the user choose/edit it
2447 if checkstatus cddb-readcomplete; then :; else
2448 vecho "Obtaining CDDB results..."
2449 # If CDDB is to be used, interpret the query results and read all
2450 # the available entries.
2451 rm -f "$ABCDETEMPDIR/cddbchoices"
2452 CDDBCHOICES=1 # Overridden by multiple matches
2453 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
2454 case "$RESPONSECODE" in
2455 200)
2456 # One exact match, retrieve it
2457 # 200 [section] [discid] [artist] / [title]
2458 if checkstatus cddb-read-1-complete; then :; else
2459 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
2460 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
2461 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
2462 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2463 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2464 fi
2465 # List out disc title/author and contents
2466 echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
2467 for TRACK in $(f_seq_row 1 $TRACKS)
2468 do
2469 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2470 done
2471 echo >> "$ABCDETEMPDIR/cddbchoices"
2472 ;;
2473 202|403|409|503)
2474 # No match
2475 case "$RESPONSECODE" in
2476 202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
2477 403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
2478 503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
2479 esac
2480 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2481 # List out disc title/author and contents of template
2482 echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
2483 UNKNOWNDISK=y
2484 for TRACK in $(f_seq_row 1 $TRACKS)
2485 do
2486 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2487 done
2488 echo >> "$ABCDETEMPDIR/cddbchoices"
2489 echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
2490 echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
2491 ;;
2492 210|211)
2493 # Multiple exact, (possibly multiple) inexact matches
2494 IN=
2495 if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
2496 if [ "$(wc -l < "$ABCDETEMPDIR/cddbquery" | tr -d ' ')" -eq 3 ]; then
2497 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
2498 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
2499 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2500 else
2501 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
2502 fi
2503 vecho -n "Retrieving multiple matches... "
2504 grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
2505 read DISCINFO # eat top line
2506 while read DISCINFO
2507 do
2508 X=$(expr $X + 1)
2509 if checkstatus cddb-read-$X-complete; then :; else
2510 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
2511 echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
2512 fi
2513 # List out disc title/author and contents
2514 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
2515 for TRACK in $(f_seq_row 1 $TRACKS)
2516 do
2517 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2518 done
2519 echo >> "$ABCDETEMPDIR/cddbchoices"
2520 done )
2521 vecho "done."
2522 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2523 ;;
2524 999)
2525 # Using local copy.
2526 for TRACK in $(f_seq_row 1 $TRACKS)
2527 do
2528 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2529 done
2530 echo >> "$ABCDETEMPDIR/cddbchoices"
2531 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2532 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2533 ;;
2534 esac
2535 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
2536 fi
2537 }
2538
2539 # do_cddbedit
2540 do_cddbedit ()
2541 {
2542 if checkstatus cddb-edit >/dev/null; then
2543 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2544 VARIOUSARTISTS="$(checkstatus variousartists)"
2545 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
2546 return 0
2547 fi
2548 if [ "$INTERACTIVE" = "y" ]; then
2549 # We should show the CDDB results both when we are not using the local CDDB repo
2550 # or when we are using it but we could not find a proper match
2551 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2552 # Display the $ABCDETEMPDIR/cddbchoices file created above
2553 # Pick a pager so that if the tracks overflow the screen the user can still view everything
2554 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2555 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2556 CHOICE=$(checkstatus cddb-choice)
2557 if [ -n "$CHOICE" ] ; then
2558 case $CDDBCHOICES in
2559 -1) if head -1 "$ABCDETEMPDIR/cddbquery" | grep "^$" > /dev/null 2>&1 ; then
2560 log error "CDDB query failed!"
2561 exit 1
2562 else
2563 cat "$ABCDETEMPDIR/cddbchoices"
2564 fi
2565 ;;
2566 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
2567 *)
2568 echo "Selected: #$CHOICE"
2569 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
2570 ;;
2571 esac
2572 else
2573 # The user has a choice to make, display the info in a pager if necessary
2574 if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
2575 page "$ABCDETEMPDIR/cddbchoices"
2576 else
2577 # It's all going to fit in one page, cat it
2578 cat "$ABCDETEMPDIR/cddbchoices" >&2
2579 fi
2580
2581 CDDBCHOICENUM=""
2582 # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
2583 CDCHOICENUM=-1
2584 # I'll take CDDB read #3 for $400, Alex
2585 while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
2586 echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
2587 read CDDBCHOICE
2588 [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
2589 if echo $CDDBCHOICE | grep -E "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2590 if [ ! X"$DIFF" = "X" ]; then
2591 PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
2592 PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
2593 if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
2594 [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
2595 [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then
2596 echo "Invalid diff range. Please select two comma-separated numbers between 1 and $CDDBCHOICES" >&2
2597 else
2598 # We parse the 2 choices to diff, store them in temporary files and diff them.
2599 for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
2600 do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE"
2601 done
2602 echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/cddbread.diff"
2603 $DIFF $DIFFOPTS "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/cddbread.diff"
2604 if [ $(cat "$ABCDETEMPDIR/cddbread.diff" | wc -l) -ge 24 ]; then
2605 page "$ABCDETEMPDIR/cddbread.diff"
2606 else
2607 cat "$ABCDETEMPDIR/cddbread.diff" >&2
2608 fi
2609 fi
2610 else
2611 echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2
2612 fi
2613 elif echo $CDDBCHOICE | grep -E "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2614 # Make sure we get a valid choice
2615 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
2616 if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then
2617 echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2
2618 fi
2619 fi
2620 done
2621 if [ "$CDCHOICENUM" = "0" ]; then
2622 vecho "Creating empty CDDB template..."
2623 UNKNOWNDISK=y
2624 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2625 else
2626 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2627 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
2628 fi
2629 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2630 fi
2631 fi
2632 else
2633 # We need some code to show the selected option when local repository is selected and we have found a match
2634 vecho "Using cached CDDB match..." >&2
2635 # Display the $ABCDETEMPDIR/cddbchoices file created above
2636 # Pick a pager so that if the tracks overflow the screen the user can still view everything
2637 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2638 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2639 CHOICE=$(checkstatus cddb-choice)
2640 if [ "$USELOCALRESP" = "y" ]; then :; else
2641 if [ -n "$CHOICE" ] ; then
2642 case $CDDBCHOICES in
2643 0)
2644 UNKNOWNDISK=y
2645 echo "Selected template."
2646 ;;
2647 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
2648 *)
2649 echo "Selected: #$CHOICE"
2650 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
2651 ;;
2652 esac
2653 fi
2654 fi
2655 fi
2656 fi
2657 else
2658 # We're noninteractive - pick the first choice.
2659 # But in case we run a previous instance and selected a choice, use it.
2660 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2661 # Show the choice if we are not using the locally stored one
2662 # or when the local search failed to find a match.
2663 PREVIOUSCHOICE=$(checkstatus cddb-choice)
2664 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2665 #if [ "$PREVIOUSCHOICE" ]; then
2666 cat "$ABCDETEMPDIR/cddbchoices"
2667 #fi
2668 fi
2669 if [ ! -z "$PREVIOUSCHOICE" ] ; then
2670 CDCHOICENUM=$PREVIOUSCHOICE
2671 else
2672 CDCHOICENUM=1
2673 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2674 fi
2675 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2676 fi
2677 fi
2678
2679 # sanity check
2680 if checkstatus cddb-choice >/dev/null; then :; else
2681 echo "abcde: internal error: cddb-choice not recorded." >&2
2682 exit 1
2683 fi
2684 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2685 echo -n "Edit selected CDDB data? [y/n] (" >&2
2686 if [ "$INTERACTIVE" = "y" ]; then
2687 if [ "$UNKNOWNDISK" = "y" ]; then
2688 echo -n "y): " >&2
2689 read EDITCDDB
2690 [ "$EDITCDDB" != "n" ] && EDITCDDB=y
2691 else
2692 echo -n "n): " >&2
2693 read EDITCDDB
2694 fi
2695 else
2696 echo "n): n" >&2
2697 EDITCDDB=n
2698 fi
2699 if [ "$EDITCDDB" = "y" ]; then
2700 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
2701
2702 # Use the debian sensible-editor wrapper to pick the editor that the
2703 # user has requested via their $EDITOR environment variable
2704 if [ -x "/usr/bin/sensible-editor" ]; then
2705 /usr/bin/sensible-editor "$CDDBDATA"
2706 elif [ -n "$EDITOR" ]; then
2707 if [ -x $(which "${EDITOR%%\ *}") ]; then
2708 # That failed, try to load the preferred editor, starting
2709 # with their EDITOR variable
2710 eval $(echo "$EDITOR") \"$CDDBDATA\"
2711 fi
2712 # If that fails, check for a vi
2713 elif which vi >/dev/null 2>&1; then
2714 vi "$CDDBDATA"
2715 elif [ -x /usr/bin/vim ]; then
2716 /usr/bin/vim "$CDDBDATA"
2717 elif [ -x /usr/bin/vi ]; then
2718 /usr/bin/vi "$CDDBDATA"
2719 elif [ -x /bin/vi ]; then
2720 /bin/vi "$CDDBDATA"
2721 # nano should be on all (modern, i.e., sarge) debian systems
2722 elif which nano >/dev/null 2>&1 ; then
2723 nano "$CDDBDATA"
2724 elif [ -x /usr/bin/nano ]; then
2725 /usr/bin/nano "$CDDBDATA"
2726 # mg should be on all OpenBSD systems
2727 elif which mg >/dev/null 2>&1 ; then
2728 mg "$CDDBDATA"
2729 elif [ -x /usr/bin/mg ]; then
2730 /usr/bin/mg "$CDDBDATA"
2731 # bomb out
2732 else
2733 log warning "no editor available. Check your EDITOR environment variable."
2734 fi
2735 # delete editor backup file if it exists
2736 if [ -w "$CDDBDATA~" ]; then
2737 rm -f "$CDDBDATA~"
2738 fi
2739 fi
2740
2741 # Some heuristics first. Look at Disc Title, and if it starts with
2742 # "Various", then we'll assume Various Artists
2743 if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2- -d= | grep -Eci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
2744 echo "Looks like a Multi-Artist CD" >&2
2745 VARIOUSARTISTS=y
2746 else
2747 echo -n "Is the CD multi-artist [y/N]? " >&2
2748 if [ "$INTERACTIVE" = "y" ]; then
2749 read VARIOUSARTISTS
2750 else
2751 echo n >&2
2752 VARIOUSARTISTS=n
2753 fi
2754 fi
2755 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
2756 # Set a default
2757 DEFAULTSTYLE=1
2758 # Need NUMTRACKS before cddb-tool will return it:
2759 NUMTRACKS=$(grep -E '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
2760 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2761 # More than 1/2 tracks contain a "/", so guess forward
2762 DEFAULTSTYLE=1
2763 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2764 # More than 1/2 contain a "-", so guess forward-dash
2765 DEFAULTSTYLE=2
2766 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2767 # More than 1/2 contain something in parens, so guess trailing-paren
2768 DEFAULTSTYLE=6
2769 fi
2770
2771 echo "1) Artist / Title" >&2
2772 echo "2) Artist - Title" >&2
2773 echo "3) Title / Artist" >&2
2774 echo "4) Title - Artist" >&2
2775 echo "5) Artist: Title" >&2
2776 echo "6) Title (Artist)" >&2
2777 echo "7) This is a single-artist CD" >&2
2778 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
2779 if [ "$INTERACTIVE" = "y" ]; then
2780 read VARIOUSARTISTSTYLE
2781 else
2782 echo $DEFAULTSTYLE >&2
2783 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2784 fi
2785 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2786 # If they press Enter, then the default style (0) was chosen
2787 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
2788 echo "Invalid selection. Please choose a number between 1 and 7."
2789 echo -n "Selection [1-7]: "
2790 read VARIOUSARTISTSTYLE
2791 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2792 done
2793 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
2794 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2795 fi
2796 vecho "Selected: $VARIOUSARTISTSTYLE"
2797 case "$VARIOUSARTISTSTYLE" in
2798 1) # Artist / Title
2799 VARIOUSARTISTSTYLE=forward
2800 ;;
2801 2) # Artist - Title
2802 VARIOUSARTISTSTYLE=forward-dash
2803 ;;
2804 3) # Title / Artist
2805 VARIOUSARTISTSTYLE=reverse
2806 ;;
2807 4) # Title - Artist
2808 VARIOUSARTISTSTYLE=reverse-dash
2809 ;;
2810 5) # Artist: Title
2811 VARIOUSARTISTSTYLE=colon
2812 ;;
2813 6) # Title (Artist)
2814 VARIOUSARTISTSTYLE=trailing-paren
2815 ;;
2816 7) # Single Artist
2817 VARIOUSARTISTS=n
2818 ;;
2819 esac
2820 fi
2821
2822 echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
2823 echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
2824
2825 if [ "$EDITCDDB" = "y" ] && [ "$CDDBMETHOD" = "cddb" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
2826 if [ "$CDDBDATAMD5SUM" != "" ] && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
2827 # This works but does not have the necessary error checking
2828 # yet. If you are familiar with the CDDB spec
2829 # (see http://www.freedb.org/src/latest/DBFORMAT)
2830 # and can create an error-free entry on your own, then put
2831 # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
2832 # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
2833 # your abcde.conf to change the email address submissions are
2834 # sent to.
2835
2836 # submit the modified file, if they want
2837 if [ "$NOSUBMIT" != "y" ]; then
2838 echo -n "Do you want to submit this entry to $CDDBSUBMIT [y/N]? "
2839 read YESNO
2840 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
2841 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
2842 do
2843 echo -n 'Invalid selection. Please answer "y" or "n": '
2844 read YESNO
2845 done
2846 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
2847 echo -n "Sending..."
2848 $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
2849 echo "done."
2850 fi
2851 fi
2852 fi
2853 fi
2854 ### FIXME ###
2855 # User CDDBLOCALPOLICY to find out if we store the file or not...
2856 # Cache edited CDDB entry in the user's cddb dir
2857 if [ "$CDDBCOPYLOCAL" = "y" ]; then
2858 # Make sure the cache directory exists
2859 mkdir -p $CDDBLOCALDIR
2860 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
2861 fi
2862
2863 echo "cddb-edit" >> "$ABCDETEMPDIR/status"
2864 }
2865
2866 # do_cdread [tracknumber]
2867 # do_cdread onetrack [firsttrack] [lasttrack]
2868 #
2869 do_cdread ()
2870 {
2871 # The commands here don't go through run_command because they're never supposed to be silenced
2872 # return codes need to be doublechecked anyway, however
2873 if [ "$1" = "onetrack" ]; then
2874 # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
2875 # FIXME # Until then, we grab the whole CD in one track, no matter what
2876 # the user said
2877 # We need the first and last track for cdda2wav/icedax
2878 FIRSTTRACK=$2
2879 LASTTRACK=$(expr $3 + 0)
2880 UTRACKNUM=$FIRSTTRACK
2881 case "$CDROMREADERSYNTAX" in
2882 flac) READTRACKNUMS="$FIRSTTRACK.1-$(($LASTTRACK + 1)).0" ;;
2883 cdparanoia)
2884 #XX FIXME XX
2885 # Add a variable to check if tracks are provided in command line and if not, use "0-" to rip the tracks
2886 READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
2887 cdda2wav | icedax) READTRACKNUMS="$FIRSTTRACK+$LASTTRACK" ;;
2888 *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
2889 exit 1 ;;
2890 esac
2891 else
2892 UTRACKNUM=$1
2893 fi
2894 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2895 if [ "$USEPIPES" = "y" ]; then
2896 TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
2897 FILEARG="$( eval echo "\$$TEMPARG" )"
2898 REDIR="y"
2899 PIPE_MESSAGE="and encoding "
2900 else
2901 WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
2902 case "$CDROMREADERSYNTAX" in
2903 ## FIXME ## Find the cases for dagrab and flac, to avoid exceptions
2904 flac)
2905 FILEARG="--output-name=$WAVDATA"
2906 ;;
2907 dagrab)
2908 FILEARG="-f $WAVDATA"
2909 ;;
2910 *)
2911 FILEARG="$WAVDATA"
2912 ;;
2913 esac
2914 REDIR="n"
2915 fi
2916 if [ "$1" = "onetrack" ]; then
2917 echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
2918 else
2919 if [ -r "$CDDBDATA" ]; then
2920 getcddbinfo TRACKNAME
2921 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
2922 else
2923 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
2924 fi
2925 fi
2926 case "$CDROMREADERSYNTAX" in
2927 ### FIXME ### use an exception for flac, since it uses -o
2928 ### FIXME ### Shall we just use -o $FILEARG ??
2929 flac)
2930 # Avoid problems wit math expressions by unpadding the given UTRACKNUM
2931 STRIPTRACKNUM=$(expr $UTRACKNUM + 0)
2932 nice $READNICE $FLAC -d -f --cue=${READTRACKNUMS:-$STRIPTRACKNUM.1-$(($STRIPTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;;
2933 cdparanoia)
2934 if [ "$REDIR" = "y" ]; then
2935 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" >&2
2936 else
2937 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG"
2938 fi;;
2939
2940 cdda2wav | icedax)
2941 if [ "$OSFLAVOUR" = "OSX" ] ; then
2942 # Hei, we have to unmount the device before running anything like cdda2wav/icedax in OSX
2943 diskutil unmount ${CDROM#/dev/} 0
2944 # Also, in OSX the cdrom device for cdda2wav/icedax changes...
2945 CDDA2WAVCDROM="IODVDServices"
2946 elif [ "$OSFLAVOUR" = "FBSD" ] ; then
2947 CDDA2WAVCDROM="$CDROMID"
2948 else
2949 if [ "$CDROMID" = "" ]; then
2950 CDDA2WAVCDROM="$CDROM"
2951 else
2952 CDDA2WAVCDROM="$CDROMID"
2953 fi
2954 fi
2955 if [ "$REDIR" = "y" ]; then
2956 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" >&2
2957 else
2958 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG"
2959 fi ;;
2960 ## FIXME ## We have an exception for dagrab, since it uses -f
2961 ## FIXME ## Shall we just use -f $FILEARG ??
2962 dagrab)
2963 if [ "$REDIR" = "y" ]; then
2964 nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG" >&2
2965 else
2966 nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG"
2967 fi ;;
2968 cddafs)
2969 # Find the track's mounted path
2970 REALTRACKNUM=$(expr $UTRACKNUM + 0)
2971 FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
2972 FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
2973 # If the file exists, copy it
2974 if [ -e "$FILEPATH" ] ; then
2975 if [ "$REDIR" = "y" ]; then
2976 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" >&2
2977 else
2978 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG"
2979 fi
2980 else
2981 false
2982 fi ;;
2983 debug)
2984 if [ "$REDIR" = "y" ]; then
2985 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG" >&2
2986 else
2987 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG"
2988 fi ;;
2989 esac
2990 RETURN=$?
2991 # If we get some error or we get some missing wav
2992 # (as long as we dont use pipes)
2993 if [ "$RETURN" != "0" -o \( ! -s "$WAVDATA" -a X"$USEPIPES" != "Xy" \) ]; then
2994 # Thank goodness errors is only machine-parseable up to the
2995 # first colon, otherwise this woulda sucked
2996 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
2997 RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
2998 fi
2999 if [ "$USEPIPES" = "y" ]; then
3000 echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
3001 else
3002 echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
3003 fi
3004 return $RETURN
3005 else
3006 if [ "$USEPIPES" = "y" ]; then
3007 echo readencodetrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
3008 else
3009 echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
3010 fi
3011 if [ "$1" = "onetrack" ]; then
3012 echo onetrack >> "$ABCDETEMPDIR/status"
3013 fi
3014 fi
3015 }
3016
3017 # do_cdspeed
3018 # No values accepted, only uses env variables
3019 do_cdspeed ()
3020 {
3021 if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
3022 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
3023 else
3024 echo "abcde: unable to set the device speed" >&2
3025 fi
3026 }
3027
3028 # vecho [message]
3029 #
3030 # vecho outputs a message if EXTRAVERBOSE is 1 or more
3031 vecho ()
3032 {
3033 if [ x"$EXTRAVERBOSE" != "x" ] && [ $EXTRAVERBOSE -gt 0 ] ; then
3034 case $1 in
3035 warning) shift ; log warning "$@" ;;
3036 *) echo "$@" ;;
3037 esac
3038 fi
3039 }
3040
3041 # vvecho [message]
3042 #
3043 # vvecho outputs a message if EXTRAVERBOSE is 2 or more
3044 vvecho ()
3045 {
3046 if [ x"$EXTRAVERBOSE" != "x" ] && [ $EXTRAVERBOSE -gt 1 ] ; then
3047 case $1 in
3048 warning) shift ; log warning "$@" ;;
3049 *) echo "$@" ;;
3050 esac
3051 fi
3052 }
3053
3054 # decho [message]
3055 #
3056 # decho outputs a debug message if DEBUG is selected
3057 decho ()
3058 {
3059 if [ x"$DEBUG" != "x" ]; then
3060 if echo $1 | grep "^\[" > /dev/null 2>&1 ; then
3061 DEBUGECHO=$(echo "$@" | tr -d '[]')
3062 echo "[DEBUG] $DEBUGECHO: `eval echo \\$${DEBUGECHO}`"
3063 else
3064 echo "[DEBUG] $1"
3065 fi
3066 fi
3067 }
3068
3069 # User-redefinable functions
3070 # Custom filename munging:
3071 mungefilename ()
3072 {
3073 #echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
3074 echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
3075 }
3076
3077 # Custom genre munging:
3078 mungegenre ()
3079 {
3080 echo $CDGENRE | tr "[:upper:]" "[:lower:]"
3081 }
3082
3083 # pre_read
3084 # Empty pre_read function, to be defined in the configuration file.
3085 pre_read ()
3086 {
3087 :
3088 }
3089
3090 # post_read
3091 # Empty post_read function, to be defined in the configuration file.
3092 post_read ()
3093 {
3094 :
3095 }
3096
3097 # post_encode
3098 # Empty post_encode function, to be defined in the configuration file.
3099 post_encode ()
3100 {
3101 :
3102 }
3103
3104 ###############################################################################
3105 # End of functions
3106 #
3107 # Start of execution
3108 ###############################################################################
3109
3110 # Builtin defaults
3111
3112 # CDDB
3113 # Defaults to FreeDB, but musicbrainz can be used too, via the abcde-musicbrainz-tool script
3114 CDDBMETHOD=cddb
3115 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
3116 CDDBSUBMIT=freedb-submit@freedb.org
3117 CDDBPROTO=6
3118 HELLOINFO="$(whoami)@$(hostname)"
3119 CDDBCOPYLOCAL="n"
3120 CDDBLOCALPOLICY="always"
3121 CDDBLOCALRECURSIVE="y"
3122 CDDBLOCALDIR="$HOME/.cddb"
3123 CDDBUSELOCAL="n"
3124
3125 # List of fields we parse and show during the CDDB parsing...
3126 SHOWCDDBFIELDS="year,genre"
3127
3128 INTERACTIVE=y
3129 #CDROMREADERSYNTAX=cdparanoia
3130 ENCODERSYNTAX=default
3131
3132 MP3ENCODERSYNTAX=default
3133 OGGENCODERSYNTAX=default
3134 FLACENCODERSYNTAX=default
3135 SPEEXENCODERSYNTAX=default
3136 MPPENCODERSYNTAX=default
3137 AACENCODERSYNTAX=default
3138 NORMALIZERSYNTAX=default
3139 CUEREADERSYNTAX=default
3140
3141 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
3142 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
3143 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
3144 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
3145 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
3146 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
3147 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
3148 PLAYLISTDATAPREFIX=''
3149 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
3150 VAPLAYLISTDATAPREFIX=''
3151 DOSPLAYLIST=n
3152 COMMENT=''
3153 ID3TAGV=2
3154 ENCNICE=10
3155 READNICE=10
3156 DISTMP3NICE=10
3157 VARIOUSARTISTS=n
3158 VARIOUSARTISTSTYLE=forward
3159 KEEPWAVS=n
3160 PADTRACKS=n
3161 NOGAP=n
3162 BATCHNORM=n
3163 NOCDDBQUERY=n
3164
3165 # If using scsi devices, cdda2wav/icedax needs a CDROMID, instead of a device node
3166 # i.e. CDROMID="1,0,0"
3167 CDROMID=""
3168 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
3169 # If we are using the ide-scsi emulation layer, we need to define a "g"
3170 CDPARANOIACDROMBUS="d"
3171
3172 # program paths - defaults to checking your $PATH
3173 # mp3
3174 LAME=lame
3175 TOOLAME=toolame
3176 GOGO=gogo
3177 BLADEENC=bladeenc
3178 L3ENC=l3enc
3179 XINGMP3ENC=xingmp3enc
3180 MP3ENC=mp3enc
3181 # ogg
3182 VORBIZE=vorbize
3183 OGGENC=oggenc
3184 # flac
3185 FLAC=flac
3186 # speex
3187 SPEEXENC=speexenc
3188 # mpp (Musepack)
3189 MPPENC=mppenc
3190 # m4a
3191 AACENC=faac
3192
3193 ID3=id3
3194 ID3V2=id3v2
3195 EYED3=eyeD3
3196 VORBISCOMMENT=vorbiscomment
3197 METAFLAC=metaflac
3198 AACTAG=faac
3199 ATOMICPARSLEY=AtomicParsley
3200
3201 CDPARANOIA=cdparanoia
3202 CDDA2WAV=icedax
3203 DAGRAB=dagrab
3204 CDDAFS=cp
3205 CDDISCID=cd-discid
3206 CDDBTOOL=cddb-tool
3207 MUSICBRAINZ=abcde-musicbrainz-tool
3208 EJECT=eject
3209 MD5SUM=md5sum
3210 DISTMP3=distmp3
3211 NORMALIZE=normalize-audio
3212 CDSPEED=eject
3213 VORBISGAIN=vorbisgain
3214 MP3GAIN=mp3gain
3215 MPPGAIN=replaygain
3216 MKCUE=mkcue
3217 MKTOC=cdrdao
3218 DIFF=diff
3219 CUE2DISCID=builtin
3220
3221 # Options for programs called from abcde
3222 # mp3
3223 LAMEOPTS=
3224 TOOLAMEOPTS=
3225 GOGOOPTS=
3226 BLADEENCOPTS=
3227 L3ENCOPTS=
3228 XINGMP3ENCOPTS=
3229 MP3ENCOPTS=
3230 MP3GAINOPTS="-a -k"
3231 # ogg
3232 VORBIZEOPTS=
3233 OGGENCOPTS=
3234 VORBISGAINOPTS="--album"
3235 # flac
3236 FLACOPTS=
3237 FLACGAINOPTS="--add-replay-gain"
3238 # speex
3239 SPEEXENCOPTS=
3240 # mpc
3241 MPPENCOPTS=
3242 # m4a
3243 AACENCOPTS=
3244
3245 ID3OPTS=
3246 ID3V2OPTS=
3247 CDPARANOIAOPTS=
3248 CDDA2WAVOPTS=
3249 DAGRABOPTS=
3250 CDDAFSOPTS="-f"
3251 CDDBTOOLOPTS=
3252 EJECTOPTS=
3253 DISTMP3OPTS=
3254 NORMALIZEOPTS=
3255 CDSPEEDOPTS="-x"
3256 CDSPEEDVALUE=
3257 MKCUEOPTS=
3258 MKTOCOPTS=""
3259 VORBISCOMMENTOPTS="-R"
3260 METAFLACOPTS="--no-utf8-convert"
3261 DIFFOPTS=
3262
3263 # Default to one process if -j isn't specified
3264 MAXPROCS=1
3265
3266 # List of actions to perform - by default, run to completion
3267 ACTIONS=cddb,read,encode,tag,move,clean
3268
3269 # This option is basicaly for Debian package dependencies:
3270 # List of prefered outputs - by default, run with whatever we have in the path
3271 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:toolame,mp3:lame,mp3:bladeenc,spx:speex,m4a:faac
3272
3273 # List of prefered cdromreaders - by default, run whichever we have in the path
3274 DEFAULT_CDROMREADERS="cdparanoia icedax cdda2wav"
3275
3276 # List of quality levels associated with the encoders:
3277 DEFAULT_QUALITY_XLO="oggenc:-q -1,lame:-q 9,speex:--quality 1,m4a:"
3278 DEFAULT_QUALITY_LO="oggenc:-q 1,lame:-q 7,speex:--quality 5,m4a:"
3279 DEFAULT_QUALITY_HI="oggenc:-q 7,lame:--preset standard,speex:--quality 9,m4a:"
3280 DEFAULT_QUALITY_XHI="oggenc:-q 10,lame:--preset extreme,speex:--quality 10,m4a:"
3281
3282 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for
3283 # Linux/OpenBSD. ftp is user for NetBSD.
3284 # Let's use these checkings to determine the OS flavour, which will be used
3285 # later
3286 if [ X$(uname) = "XFreeBSD" ] ; then
3287 HTTPGET=fetch
3288 MD5SUM=md5
3289 NEEDCDROMID=y
3290 OSFLAVOUR=FBSD
3291 elif [ X$(uname) = "XDarwin" ] ; then
3292 HTTPGET=curl
3293 OSFLAVOUR=OSX
3294 # We should have diskutil in OSX, but let's be sure...
3295 NEEDDISKUTIL=y
3296 CDROMREADERSYNTAX=cddafs
3297 elif [ X$(uname) = "XOpenBSD" ] ; then
3298 HTTPGET=wget
3299 MD5SUM=md5
3300 OSFLAVOUR=OBSD
3301 elif [ X$(uname) = "XNetBSD" ] ; then
3302 HTTPGET=ftp
3303 MD5SUM=md5
3304 OSFLAVOUR=NBSD
3305 elif [ X$(uname) = "SunOS" ] ; then
3306 HTTPGET=""
3307 MD5SUM=md5
3308 OSFLAVOUR=SunOS
3309 else
3310 HTTPGET=wget
3311 fi
3312
3313 # If CDDBAVAIL is set to n, no CDDB read is done
3314 # If USEID3 is set to n, no ID3 tagging is done
3315 CDDBAVAIL=y
3316 USEID3=y
3317 USEID3V2=y
3318
3319 # There we go..
3320 # But before we get into business, let us chop off any GREP environmental
3321 # variables.
3322 GREP_OPTIONS=""
3323 GREP_COLOR=""
3324
3325 if [ -z "$OUTPUTDIR" ]; then
3326 OUTPUTDIR=$(pwd)
3327 fi
3328
3329 if [ -z "$WAVOUTPUTDIR" ]; then
3330 WAVOUTPUTDIR="$OUTPUTDIR"
3331 fi
3332
3333 # Load system defaults
3334 if [ -r /etc/abcde.conf ]; then
3335 . /etc/abcde.conf
3336 fi
3337 # Load user preference defaults
3338 if [ -r $HOME/.abcde.conf ]; then
3339 . $HOME/.abcde.conf
3340 fi
3341
3342 # By this time, we need some HTTPGETOPTS already defined.
3343 # If the user has defined a non-default HTTPGET method, we should not be empty.
3344
3345 if [ "$HTTPGETOPTS" = "" ] ; then
3346 case $HTTPGET in
3347 wget) HTTPGETOPTS="-q -nv -e timestamping=off -O -";;
3348 curl) HTTPGETOPTS="-f -s";;
3349 fetch)HTTPGETOPTS="-q -o -";;
3350 ftp) HTTPGETOPTS="-a -V -o - ";;
3351 *) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
3352 esac
3353 fi
3354
3355 # If the CDROM has not been set yet, find a suitable one.
3356 # If this is a devfs system, default to /dev/cdroms/cdrom0
3357 # instead of /dev/cdrom
3358 if [ "$CDROM" = "" ] ; then
3359 if [ -e /dev/cdroms/cdrom0 ]; then
3360 CDROM=/dev/cdroms/cdrom0
3361 elif [ -e /dev/cdrom ]; then
3362 CDROM=/dev/cdrom
3363 elif [ -e /dev/sr0 ]; then
3364 CDROM=/dev/sr0
3365 elif [ -e /dev/cd0c ]; then
3366 CDROM=/dev/cd0c
3367 elif [ -e /dev/acd0c ]; then
3368 CDROM=/dev/acd0c
3369 elif [ -e /dev/disk1 ]; then
3370 CDROM=/dev/disk1
3371 elif [ "$OSFLAVOUR" = "OSX" ] && [[ $(diskutil list) =~ CD_part.*(disk.)$'\n' ]]; then
3372 CDROM=/dev/${BASH_REMATCH[1]}
3373 fi
3374 fi
3375
3376 # We used to use EXTRAVERBOSE=y to turn on more debug output. Now
3377 # that's changed to a number to allow for more control. If
3378 # EXTRAVERBOSE=y, set it to 1 for backwards compatibility.
3379 if [ "$EXTRAVERBOSE" = "y" ]; then
3380 EXTRAVERBOSE=1
3381 fi
3382 if [ "$EXTRAVERBOSE" = "n" ]; then
3383 EXTRAVERBOSE=0
3384 fi
3385
3386 # Parse command line options
3387 #while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPq:r:Rs:S:t:T:vVxw:W: opt ; do
3388 while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPq:r:s:S:t:T:UvVxX:w:W:z opt ; do
3389 case "$opt" in
3390 1) ONETRACK=y ;;
3391 a) ACTIONS="$OPTARG" ;;
3392 A) EXPACTIONS="$OPTARG" ;;
3393 b) BATCHNORM=y ;;
3394 B) NOBATCHREPLAYGAIN=y ;;
3395 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
3396 C) DISCID="$( echo ${OPTARG#abcde.} | tr -d /)" ;;
3397 d) CDROM="$OPTARG" ;;
3398 D) set -x ;;
3399 h) usage; exit ;;
3400 e) ERASEENCODEDSTATUS=y ;;
3401 E) ENCODING="$OPTARG" ;;
3402 f) FORCE=y ;;
3403 g) NOGAP=y ;;
3404 i) INLINETAG=y ;;
3405 j) MAXPROCS="$OPTARG" ;;
3406 k) KEEPWAVS=y ;;
3407 l) LOWDISK=y ;;
3408 L) CDDBUSELOCAL=y ;;
3409 n) CDDBAVAIL=n ;;
3410 N) INTERACTIVE=n ;;
3411 m) DOSPLAYLIST=y ;;
3412 M) DOCUE=y ;;
3413 o) OUTPUTTYPE="$OPTARG" ;;
3414 p) PADTRACKS=y ;;
3415 P) USEPIPES=y ;;
3416 q) QUALITYLEVEL="$OPTARG" ;;
3417 r) REMOTEHOSTS="$OPTARG" ;;
3418 R) CDDBLOCALRECURSIVE=y ;;
3419 s) SHOWCDDBFIELDS="$OPTARG" ;;
3420 S) CDSPEEDVALUE="$OPTARG" ;;
3421 t) STARTTRACKNUMBER="$OPTARG" ;;
3422 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
3423 U) CDDBPROTO=5 ;;
3424 v)
3425 echo "This is abcde v$VERSION."
3426 echo "Usage: abcde [options] [tracks]"
3427 echo "abcde -h for extra help"
3428 exit
3429 ;;
3430 V) EXTRAVERBOSE=$(($EXTRAVERBOSE + 1)) ;;
3431 x) EJECTCD="y" ;;
3432 X) CUE2DISCID="$OPTARG" ;;
3433 w) COMMENT="$OPTARG" ;;
3434 W) if echo $OPTARG | grep "[[:digit:]]" > /dev/null 2>&1 ; then
3435 STARTTRACKNUMBER="${OPTARG}01"
3436 STARTTRACKNUMBERTAG="y"
3437 COMMENT="CD${OPTARG}"
3438 DISCNUMBER="${OPTARG}"
3439 else
3440 log error "argument of -W must be integer"
3441 exit 1
3442 fi
3443 ;;
3444 z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
3445 ?) usage; exit ;;
3446 esac
3447 done
3448
3449 shift $(($OPTIND - 1))
3450
3451 # Here it comes the worse part of the whole thing. From here until we start
3452 # ripping, we have a mixture of sanity checks, verifications, default settigs
3453 # and other crazy stuff that interdepends, but hey, someone has to do it.
3454
3455 # If NOCDDBQUERY is set, don't query the CDDB server.
3456 if [ "$NOCDDBQUERY" = "y" ]; then
3457 CDDBAVAIL="n"
3458 fi
3459
3460 # If the user specified a flac file, then switch to special flac mode
3461 if echo "$CDROM" | grep -i '.flac$' > /dev/null 2>&1 ; then
3462 if [ ! -f "$CDROM" ]; then
3463 log error "the defined file for FLAC ripping cannot be found" >&2
3464 exit 1
3465 fi
3466 vecho warning "switching to flac CDROMREADERSYNTAX..."
3467 CDROMREADERSYNTAX=flac
3468 # We have a builtin version of cue2discid...
3469 case "$CUE2DISCID" in
3470 builtin);;
3471 *) NEEDCUE2DISCID=y;;
3472 esac
3473 NEEDMETAFLAC=y
3474 EJECTCD=n
3475 fi
3476
3477 # If the user provided a DISCID, disable eject
3478 if [ -n "$DISCID" ] || [ "$CDROMREADERSYNTAX" = "flac" ]; then EJECTCD=n ; fi
3479
3480 # Check the available cd rippers in the system, from the ones we know.
3481 if [ "$CDROMREADERSYNTAX" = "" ]; then
3482 for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
3483 if new_checkexec $DEFAULT_CDROMREADER; then
3484 CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
3485 break
3486 fi
3487 done
3488 if [ "$CDROMREADERSYNTAX" = "" ]; then
3489 log error "no cdreader found in your PATH"
3490 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3491 exit 1
3492 fi
3493 fi
3494
3495 # Decide if we can continue.
3496 if [ "$ONETRACK" = "y" ]; then
3497 # FIXME # remove check as soon as we find out about the other readers
3498 case "$CDROMREADERSYNTAX" in
3499 flac) ;;
3500 cdparanoia) ;;
3501 cdda2wav | icedax) ;;
3502 *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
3503 exit 1 ;;
3504 esac
3505 if [ "$BATCHNORM" = "y" ]; then
3506 log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
3507 BATCHNORM=n
3508 fi
3509 if [ "$NOGAP" = "y" ]; then
3510 log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
3511 NOGAP=n
3512 fi
3513 # It does not matter how many tracks we want. In ONETRACK mode we grab them all
3514 # FIXME # allow ranges of tracks to be selected for onetrack ripping
3515 if [ $# -gt 0 ]; then
3516 log warning "ONETRACK mode selected, grabbing all tracks..."
3517 fi
3518 else
3519 while [ $# -gt 0 ]; do
3520 # Range parsing code courtesy of Vincent Ho
3521 # Cleaned up to use shell built-ins by Charles Steinkuehler
3522 if [ "${1#*[^0-9-]}" != "$1" ]; then
3523 log error "syntax error while processing track numbers ($1)"
3524 exit 1
3525 else
3526 RSTART=${1%%-*}
3527 REND=${1##*-}
3528 while [ ${RSTART:=1} -le ${REND:=0} ] ; do
3529 TRACKQUEUE="$TRACKQUEUE $RSTART"
3530 RSTART=$(( $RSTART + 1 ))
3531 done
3532 fi
3533 shift
3534 done
3535 fi
3536
3537 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
3538 # List of experimental actions: retag,transcode
3539
3540 # Determine what actions are to be done from $ACTIONS and set the
3541 # following environment variables for them:
3542 DOCDDB=n
3543 DOREAD=n
3544 DONORMALIZE=n
3545 DOPREPROCESS=n
3546 DOENCODE=n
3547 DOPOSTPROCESS=n
3548 DOTAG=n
3549 DOMOVE=n
3550 DOREPLAYGAIN=n
3551 DOPLAYLIST=n
3552 DOCLEAN=n
3553 ## FIXME ## Lets keep compatibility with -M
3554 [ "$DOCUE" != "y" ] && DOCUE=n
3555
3556 for ACTION in $(echo $ACTIONS | tr , \ )
3557 do
3558 case $ACTION in
3559 default) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOCLEAN=y;;
3560 cue) DOCUE=y ; MAKECUEFILE=y ;;
3561 cddb) DOCDDB=y;;
3562 read) DOREAD=y;;
3563 normalize) DONORMALIZE=y; DOREAD=y;;
3564 # preprocess) DOPREPROCESS=y; DOREAD=y;;
3565 encode) DOENCODE=y; DOREAD=y;;
3566 # postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
3567 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3568 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3569 replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
3570 playlist) DOCDDB=y; DOPLAYLIST=y;;
3571 clean) DOCLEAN=y;;
3572 esac
3573 done
3574
3575 if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
3576 # FIXME # should we abort on error or just inform the user?
3577 log warning "selected both normalize and replaygain actions"
3578 fi
3579
3580 for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
3581 case $SHOWCDDBFIELD in
3582 y*|Y*) SHOWCDDBYEAR="y";;
3583 g*|G*) SHOWCDDBGENRE="y";;
3584 *) ;;
3585 esac
3586 done
3587
3588 # At this point a CDROM has to be defined, so we check it exists.
3589 if [ X"$CDROM" != "X" ] ; then
3590 if ( [ "$CDROMREADERSYNTAX" = "cdda2wav" ] || [ "$CDROMREADERSYNTAX" = "icedax" ] ) && [ "$NEEDCDROMID" = "y" ] ; then
3591 if [ "$OSFLAVOUR" = "FBSD" ]; then
3592 if echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then :; else
3593 log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
3594 log error "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
3595 exit 1
3596 fi
3597 fi
3598 elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
3599 log error "CDROM device cannot be found."
3600 exit 1
3601 fi
3602 # avoid processing if we are not going to hit the CDROM.
3603 elif [ X"$DOREAD" = "Xy" ]; then
3604 log error "CDROM has not been defined or cannot be found"
3605 exit 1
3606 fi
3607
3608 # USEPIPES pre-tests, before we get into more serious stuff
3609 # Not compatible with:
3610 # - multiple outputs
3611 # - normalize
3612 # - lowdisk algorithm
3613 # - anything else?
3614 if [ X"$USEPIPES" = "Xy" ]; then
3615 if [ $(echo "$OUTPUTTYPE" | tr , \ | wc -w ) -gt 1 ]; then
3616 log error "Unix pipes not compatible with multiple outputs"
3617 exit 1
3618 fi
3619 if [ X"$DONORMALIZE" = "Xy" ]; then
3620 log error "Unix pipes not compatible with normalizer"
3621 # FIXME # Do we need to exit or shall we just disable the mode?
3622 exit 1
3623 fi
3624 if [ X"$BATCHNORM" = "Xy" ]; then
3625 log error "Unix pipes not compatible with BATCHNORM encoding"
3626 exit 1
3627 fi
3628 if [ X"$NOGAP" = "Xy" ]; then
3629 log error "Unix pipes not compatible with NOGAP encoding"
3630 exit 1
3631 fi
3632 if [ X"$DOENCODE" = "Xn" ]; then
3633 vecho warning "Disabling Unix pipes since we are not encoding!"
3634 USEPIPES=n
3635 fi
3636 if [ X"$LOWDISK" = "Xy" ]; then
3637 log error "Unix pipes not compatible with lowdisk algorithm"
3638 exit 1
3639 fi
3640 fi
3641
3642 # LOWDISK pre-tests, before we get into more problematic stuff
3643 # Not compatible with anything that needs all the files in the hard disc:
3644 # - BATCHNORM
3645 # - NOGAP lame mode
3646 if [ X"$LOWDISK" = "Xy" ]; then
3647 if [ X"$BATCHNORM" = "Xy" ]; then
3648 log error "Unix pipes not compatible with BATCHNORM encoding"
3649 exit 1
3650 fi
3651 if [ X"$NOGAP" = "Xy" ]; then
3652 log error "Unix pipes not compatible with NOGAP encoding"
3653 exit 1
3654 fi
3655 fi
3656
3657 # BATCHNORM pre-tests, before we get into serious problems
3658 # Not compatible with
3659 if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
3660 vecho warning "Disabling BATCHNORM since we are not normalizing!"
3661 BATCHNORM=n
3662 fi
3663
3664 # Check the encoding format from the ones available in the system, if nothing has been configured.
3665 if [ X"$OUTPUTTYPE" = "X" ]; then
3666 for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
3667 DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
3668 DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
3669 if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
3670 OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
3671 vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
3672 break
3673 fi
3674 done
3675 if [ X"$OUTPUTTYPE" = "X" ]; then
3676 log error "no encoder found in the PATH"
3677 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3678 exit 1
3679 fi
3680 fi
3681
3682 # Decide which CDROM reader we're gonna use
3683 case "$CDROMREADERSYNTAX" in
3684 cdparanoia|debug)
3685 CDROMREADER="$CDPARANOIA"
3686 CDROMREADEROPTS="$CDPARANOIAOPTS"
3687 ;;
3688 cdda2wav | icedax)
3689 CDROMREADER="$CDDA2WAV"
3690 CDROMREADEROPTS="$CDDA2WAVOPTS"
3691 ;;
3692 dagrab)
3693 CDROMREADER="$DAGRAB"
3694 CDROMREADEROPTS="$DAGRABOPTS"
3695 ;;
3696 cddafs)
3697 CDROMREADER="$CDDAFS"
3698 CDROMREADEROPTS="$CDDAFSOPTS"
3699 ;;
3700 flac)
3701 CDROMREADER="$FLAC"
3702 CDROMREADEROPTS="$FLACOPTS"
3703 ;;
3704 esac
3705
3706 # There's only one normalize...
3707 case "$NORMALIZERSYNTAX" in
3708 default|normalize)
3709 NORMALIZER="$NORMALIZE"
3710 NORMALIZEROPTS="$NORMALIZEOPTS"
3711 ;;
3712 esac
3713
3714 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
3715 if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
3716 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr \ \|| tr , \ | tr \| \ )"; do
3717 case "$OUTPUT" in
3718 vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3719 mp3:*) MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3720 flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3721 spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3722 mpc:*) MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3723 m4a:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3724 esac
3725 done
3726 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
3727 TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
3728 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
3729 done
3730 OUTPUTTYPE="$TEMPOUTPUTTYPE"
3731 fi
3732
3733 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
3734 # for flacs and speexenc for speex and mppenc for mpps and faac for m4as
3735
3736 # Getting ready for multiple output changes
3737 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
3738 do
3739 case $OUTPUT in
3740 vorbis|ogg)
3741 [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
3742 [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
3743 [ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
3744 OGGOUTPUTCONTAINER=ogg
3745 ;;
3746 mp3)
3747 [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
3748 [ "$DOTAG" = "y" ] && NEEDTAGGER=y
3749 [ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
3750 ;;
3751 flac)
3752 [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
3753 [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
3754 [ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
3755 [ "$ONETRACK" = "y" ] && [ "$DOCUE" = "y" ] && NEEDMETAFLAC=y
3756 ;;
3757 spx)
3758 [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
3759 # [ "$DOREPLAYGAIN" = "y" ] &&
3760 ;;
3761 mpc)
3762 [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc
3763 [ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y
3764 ;;
3765 m4a)
3766 [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
3767 [ "$DOTAG" = "y" ] && CHECKATOMICPARSLEY=y
3768 ;;
3769 wav)
3770 if [ "$KEEPWAVS" = "y" ]; then
3771 vecho "Setting the KEEPWAVS option, since the resulting wav files were requested..."
3772 fi
3773 KEEPWAVS=move
3774 ;;
3775 *) log error "Invalid OUTPUTTYPE defined"
3776 exit 1
3777 ;;
3778 esac
3779 done
3780
3781 # decide which encoder
3782 case "$MP3ENCODERSYNTAX" in
3783 lame)
3784 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
3785 MP3ENCODER="$LAME"
3786 ;;
3787 toolame)
3788 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$TOOLAMEOPTS}"
3789 MP3ENCODER="$TOOLAME"
3790 ;;
3791 gogo)
3792 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
3793 MP3ENCODER="$GOGO"
3794 ;;
3795 bladeenc)
3796 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
3797 MP3ENCODER="$BLADEENC"
3798 ;;
3799 l3enc)
3800 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
3801 MP3ENCODER="$L3ENC"
3802 ;;
3803 xingmp3enc)
3804 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
3805 MP3ENCODER="$XINGMP3ENC"
3806 ;;
3807 mp3enc)
3808 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
3809 MP3ENCODER="$MP3ENC"
3810 ;;
3811 esac
3812 case "$OGGENCODERSYNTAX" in
3813 vorbize)
3814 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
3815 OGGENCODER="$VORBIZE"
3816 ;;
3817 oggenc)
3818 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
3819 OGGENCODER="$OGGENC"
3820 ;;
3821 esac
3822 case "$FLACENCODERSYNTAX" in
3823 flac)
3824 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
3825 FLACENCODER="$FLAC"
3826 if [ "$DOREPLAYGAIN" = "y" ]; then
3827 FLACENCODEROPTS="${FLACENCODEROPTS} --replay-gain"
3828 fi
3829 # FLAC streams can be encapsulated on a Ogg transport layer
3830 if echo "$FLACENCODEROPTS" | grep -E -- "(^| )--ogg($| )" > /dev/null 2>&1 ;then
3831 log error "FLAC on an Ogg container is not yet supported"
3832 log error "due to problem with adding comments to such files"
3833 exit 1
3834 FLACOUTPUTCONTAINER=ogg
3835 else
3836 FLACOUTPUTCONTAINER=flac
3837 fi
3838 ;;
3839 esac
3840 case "$SPEEXENCODERSYNTAX" in
3841 speexenc)
3842 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
3843 SPEEXENCODER="$SPEEXENC"
3844 ;;
3845 esac
3846 case "$MPPENCODERSYNTAX" in
3847 mppenc)
3848 MPPENCODEROPTS="${MPPENCODEROPTSCLI:-$MPPENCOPTS}"
3849 MPPENCODER="$MPPENC"
3850 ;;
3851 esac
3852 case "$AACENCODERSYNTAX" in
3853 faac)
3854 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
3855 AACENCODER="$AACENC"
3856 ;;
3857 esac
3858
3859 # and which tagger
3860 if [ "$ID3TAGV" = "1" ]; then
3861 TAGGER="$ID3"
3862 TAGGEROPTS="$ID3OPTS"
3863 else
3864 TAGGER="$ID3V2"
3865 TAGGEROPTS="$ID3V2OPTS"
3866 fi
3867
3868 # NOGAP is specific to lame. Other encoders fail ...
3869 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
3870 log warning "the NOGAP option is specific to lame. Deactivating..."
3871 NOGAP=n
3872 fi
3873
3874 # Options for mkcue
3875 case "$CUEREADERSYNTAX" in
3876 default|mkcue)
3877 CUEREADEROPTS="${CDROM}"
3878 CUEREADER="$MKCUE"
3879 ;;
3880 esac
3881
3882 # which information retrieval tool are we using?
3883 case "$CDDBTOOL" in
3884 cddb) ;;
3885 musicbrainz) ;;
3886 esac
3887
3888 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
3889 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
3890 log error "FLAC on an Ogg container is not yet supported"
3891 log error "due to problem with adding comments to such files"
3892 exit 1
3893 OGGOUTPUTCONTAINER=ogg.ogg
3894 FLACOUTPUTCONTAINER=flac.ogg
3895 vecho warning "modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
3896 fi
3897
3898 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
3899
3900 if [ "$ENCNICE" ]; then
3901 ENCNICE="-n $ENCNICE"
3902 fi
3903 if [ "$READNICE" ]; then
3904 READNICE="-n $READNICE"
3905 fi
3906 if [ "$DISTMP3NICE" ]; then
3907 DISTMP3NICE="-n $DISTMP3NICE"
3908 fi
3909
3910 # Don't check for stuff if it's not needed
3911 if [ "$REMOTEHOSTS" ]; then
3912 NEEDDISTMP3=y
3913 fi
3914 if [ "$DONORMALIZE" = "y" ]; then
3915 NEEDNORMALIZER=y
3916 fi
3917 if [ "$EJECTCD" = "y" ]; then
3918 NEEDEJECT=y
3919 fi
3920 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
3921 if [ "$CDDBMETHOD" = "cddb" ]; then
3922 NEEDHTTPGET=y
3923 elif [ "$CDDBMETHOD" = "musicbrainz" ]; then
3924 :
3925 fi
3926 fi
3927 if [ "$DOCUE" = "y" ]; then
3928 NEEDCUEREADER=y
3929 fi
3930
3931 if [ X"$CDSPEEDVALUE" != "X" ] && [ "$DOREAD" = "y" ]; then
3932 case "$CDROMREADERSYNTAX" in
3933 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
3934 ### FIXME ### translate "cue2discid" from python to bash
3935 flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ; CDSPEEDVALUE="" ;;
3936 *) NEEDCDSPEED=y ;;
3937 esac
3938 fi
3939
3940 ###USEPIPESSUPPORT###
3941
3942 # Rippers with USEPIPE support
3943 # FIXME # Include here all the rippers we can figure out support pipes
3944 PIPERIPPER_cdparanoia="-"
3945 PIPERIPPER_debug="-"
3946 PIPERIPPER_flac="-c "
3947
3948 # Encoders with USEPIPE support
3949 # FIXME # Include here all the encoders we can figure out support pipes
3950 PIPE_lame="-"
3951 PIPE_bladeenc="-"
3952 PIPE_oggenc="-"
3953 PIPE_flac="-"
3954
3955 # Figure out if we can use pipes with the ripper/encoder combination
3956 # exit otherwise
3957 if [ "$USEPIPES" = "y" ]; then
3958 PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
3959 case "$OUTPUT" in
3960 mp3)
3961 PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
3962 vorbis|ogg)
3963 PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
3964 flac)
3965 PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
3966 spx)
3967 PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
3968 mpc)
3969 PIPEENCODERSVARCHECK="PIPE_$MPPENCODER" ;;
3970 esac
3971 decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
3972 if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
3973 [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
3974 log error "no support for pipes with given ripper"
3975 log error "read the USEPIPES file from the source tarball to get help."
3976 log error "On a Debian system, it is under /usr/share/doc/abcde/USEPIPES.gz"
3977 exit 1;
3978 fi
3979 decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
3980 if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
3981 [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
3982 log error "no support for pipes with given encoder"
3983 log error "read the USEPIPES file from the source tarball to help"
3984 log error "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz"
3985 exit 1;
3986 fi
3987 fi
3988
3989 # Make sure a buncha things exist
3990 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
3991 $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
3992 $AACENCODER $CDDBTOOL \
3993 ${NEEDATOMICPARSLEY+$ATOMICPARSLEY} \
3994 ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
3995 ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
3996 ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
3997 ${NEEDDISKUTIL+diskutil} ${NEEDCDSPEED+$CDSPEED} \
3998 ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
3999 ${NEEDMPPGAIN+$MPPGAIN} ${NEEDCUEREADER+$CUEREADER} \
4000 ${NEEDCUE2DISCID+$CUE2DISCID}
4001 do
4002 checkexec "$X"
4003 done
4004
4005 if [ "$CHECKATOMICPARSLEY" = "y" ]; then
4006 if ! new_checkexec "$ATOMICPARSLEY"; then
4007 echo "WARNING: $ATOMICPARSLEY Not Found Not Post-Tagging!"
4008 DOTAG='n'
4009 else
4010 echo "Using $ATOMICPARSLEY To Tag AAC Tracks."
4011 fi
4012 fi
4013
4014 # And last but not least, check if we can diff between files. We do not abort,
4015 # since diffing is not critical...
4016 if [ -x $(which $DIFF) ]; then :; else
4017 vecho warning "Disabling diff since we cannot find it in the \$PATH..."
4018 DIFF=""
4019 fi
4020
4021 ## Now that we have metaflac, check if we need cue2discid
4022 #case $CDROMREADERSYNTAX in
4023 # flac)
4024 # TRACKINFO=$($METAFLAC --show-tag=CDDB $CDROM | cut -d"=" -f2 | grep -E "[a-f0-9]{8}")
4025 # if [ "$TRACKINFO" = "" ]; then
4026 # checkexec ${NEEDCUE2DISCID+$CUE2DISCID}
4027 # fi
4028 # ;;
4029 #esac
4030
4031 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
4032 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
4033 HTTPGET="$HTTPGET $HTTPGETOPTS"
4034
4035 # Here it used to say:
4036 # One thousand lines in, we can start doing stuff with things
4037 # Well, right now we are at line 3737 ;)
4038
4039 # Export needed things so they can be read in this subshell
4040 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
4041 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
4042
4043 if [ "$DOREAD" = "y" ]; then
4044 # User-definable function to set some things. Use it for
4045 # - closing the CD tray with eject -t
4046 # - set the CD speed value with eject -x
4047 vecho -n "Executing customizable pre-read function... "
4048
4049 pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
4050
4051 vecho "done."
4052 fi
4053
4054 # Get ABCDETEMPDIR created and status file initialized
4055 do_discid
4056
4057 if [ "$DOCDDB" = "y" ]; then
4058 # start with a sane default:
4059 CDDBLOCALSTATUS=notfound
4060 if [ $CDDBUSELOCAL = "y" ]; then
4061 do_localcddb
4062 fi
4063 if checkstatus cddb-choice > /dev/null; then
4064 :
4065 else
4066 if [ "$CDDBLOCALSTATUS" = "notfound" ] ; then
4067 case "$CDDBMETHOD" in
4068 cddb)
4069 do_cddbstat
4070 do_cddbquery
4071 do_cddbread
4072 ;;
4073 musicbrainz)
4074 do_musicbrainz
4075 ;;
4076 esac
4077 fi
4078 CHOICE=$(checkstatus cddb-choice)
4079 if [ $CHOICE = 0 ] ; then
4080 # We don't have any information at all; try to fall back
4081 # to CD-Text for basic information
4082 vecho "No CDDB information found, trying cdtext from the CD"
4083 do_cdtext
4084 fi
4085 fi
4086 do_cddbedit
4087
4088 eval "$($CDDBTOOL parse "$CDDBDATA")"
4089 fi
4090
4091 # Before reading tracks, we set the speed of the device
4092
4093 if [ X"$CDSPEEDVALUE" != "X" ]; then
4094 case "$CDROMREADERSYNTAX" in
4095 cdparanoia|debug) ;;
4096 flac) ;;
4097 *) do_cdspeed ;;
4098 esac
4099 fi
4100
4101 # Define the first and last track, since we might need them later in several places
4102 FIRSTTRACK=$( get_first $TRACKQUEUE )
4103 LASTTRACK=$( get_last $TRACKQUEUE )
4104
4105 if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
4106 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
4107 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
4108 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
4109 fi
4110
4111 if checkstatus onetrack ; then ONETRACK=y ; fi
4112
4113 if [ "$ONETRACK" = "y" ]; then
4114 # Reuse the CUEFILE in case we created it (now or in a previous run)
4115 if CUEFILE=$(checkstatus cuefile); then
4116 IMPORTCUESHEET=y
4117 fi
4118 fi
4119
4120 # Create playlist if needed (backgroundable) and start reading in tracks
4121
4122 (
4123
4124 if [ ! "$ONETRACK" = "y" ]; then
4125 if [ "$DOPLAYLIST" = "y" ]; then
4126 echo Creating playlist... >&2
4127 do_playlist
4128 fi
4129 fi
4130
4131 # For the lowdisk option, only one program is running at once so the encoder
4132 # can be unsilenced right away.
4133 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
4134 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4135 fi
4136
4137 if [ "$ONETRACK" = "y" ]; then
4138 TRACKS="$FIRSTTRACK"
4139 if [ "$USEPIPES" = "y" ]; then
4140 if checkstatus readencodetrack-$FIRSTTRACK; then :; else
4141 do_cdread onetrack $FIRSTTRACK $LASTTRACK | do_encode $FIRSTTRACK %local0% > /dev/null 2>&1
4142 fi
4143 else
4144 if checkstatus readtrack-$FIRSTTRACK; then :; else
4145 do_cdread onetrack $FIRSTTRACK $LASTTRACK
4146 fi
4147 fi
4148 else
4149 for UTRACKNUM in $TRACKQUEUE
4150 do
4151 if [ "$DOREAD" = "y" ]; then
4152 if [ "$USEPIPES" = "y" ]; then
4153 if checkstatus readencodetrack-$UTRACKNUM; then :; else
4154 # Read, pipe, shut up!
4155 do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
4156 fi
4157 else
4158 if checkstatus readtrack-$UTRACKNUM; then :; else
4159 do_cdread $UTRACKNUM
4160 fi
4161 if [ "$?" != "0" ]; then
4162 # CD read failed - don't give the goahead to
4163 # the encoder
4164 echo NO
4165 exit
4166 fi
4167 fi
4168 fi
4169 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ]; then
4170 :
4171 else
4172 # If we are not reading, set the encode output to loud already, so
4173 # that we can see the output of the first track.
4174 if [ "$MAXPROCS" = "1" ] && [ ! "$DOREAD" = "y" ]; then
4175 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4176 fi
4177 echo NEXTTRACK # Get the encoder machine churning again
4178 if [ "$DOREAD" = "y" ]; then
4179 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
4180 until checkstatus encodetrack-$UTRACKNUM
4181 do
4182 if checkerrors encodetrack-$UTRACKNUM; then
4183 break
4184 fi
4185 sleep 2
4186 done
4187 fi
4188 fi
4189 fi
4190 done
4191 fi
4192
4193 # Now that we're done the encoding can be loud again -
4194 # if we're not using SMP.
4195 if [ "$MAXPROCS" = "1" ]; then
4196 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4197 fi
4198
4199 # All tracks read, start encoding.
4200 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ] || [ "$ONETRACK" = "y" ]; then
4201 echo NEXTTRACK
4202 fi
4203
4204 # Execute the user-defined post_read funtion before ejecting CD
4205 post_read
4206
4207 # We are now finished with the cdrom - it can be safely ejected. Note that
4208 # abcde will not have completed yet.
4209 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
4210 # We check if the disk we are processing is actually the disk inside the
4211 # CD tray. If not, we do not eject the CD, since it might be so that the
4212 # user ejected it manually.
4213 #CURRENTTRACKINFO=$($CDDISCID $CDROM)
4214 #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
4215 # More FreeBSD bits.
4216 if [ X"$(uname)" = X"FreeBSD" ] ; then
4217 # FreeBSD eject uses the EJECT environment variable to name the CDROM
4218 # but in this script EJECT is in the envionment and names the program
4219 eject=$EJECT
4220 unset EJECT
4221 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
4222 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
4223 $eject $EJECTOPTS $cd
4224 elif [ X"$(uname)" = X"Darwin" ] ; then
4225 diskutil eject ${CDROM#/dev/} 0
4226 else
4227 $EJECT $EJECTOPTS "$CDROM"
4228 fi
4229 #fi
4230 fi
4231
4232 ) | (
4233
4234 ## Do we need to pre-process
4235 #if [ x"$PREPROCESS" = "x" ] ; then
4236 # cat
4237 #else
4238 # for PRETRACKNUM in $TRACKQUEUE
4239 # do
4240 # read GOAHEAD
4241 # if [ "$GOAHEAD" = "NO" ]; then break; fi
4242 # PREPROCEED=
4243 # until [ $PREPROCEED ]
4244 # do
4245 # if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
4246 # # all locations are working, wait and try again later
4247 # if [ ! $PREPROCEED ]; then sleep 3; fi
4248 # done
4249 # ( do_preprocess $PRETRACKNUM
4250 # echo "NEXTTRACK"
4251 # ) &
4252 # done
4253 #fi
4254 #
4255 #) | (
4256
4257 # In BATCHNORM and/or NOGAP modes, we want all tracks to be read first.
4258 #BACK
4259 if [ "$BATCHNORM" = "y" ] || [ "$NOGAP" = "y" ]; then
4260 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
4261 if [ "$GOAHEAD" = "NO" ]; then break; fi
4262 for LASTTRACK in $TRACKQUEUE; do :; done
4263 if checkstatus readtrack-$LASTTRACK; then
4264 if [ "$DONORMALIZE" = "y" ] && [ "$BATCHNORM" = "y" ]; then
4265 if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
4266 if checkerrors batch-normalize; then exit 1; fi
4267 fi
4268 if [ "$DOENCODE" = "y" ] && [ "$NOGAP" = "y" ]; then
4269 if [ "$DONORMALIZE" = "y" ]; then
4270 for UTRACKNUM in $TRACKQUEUE
4271 do
4272 if checkstatus readtrack-$UTRACKNUM; then
4273 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
4274 fi
4275 done
4276 fi
4277 if checkstatus encodetrack-$LASTTRACK; then :; else do_nogap_encode; fi
4278 if checkerrors nogap-encode; then exit 1; fi
4279 fi
4280 fi
4281 fi
4282
4283 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
4284 if [ "$ONETRACK" = "y" ] ; then
4285 TRACKQUEUE="$FIRSTTRACK"
4286 TRACKS="$FIRSTTRACK"
4287 fi
4288
4289 # Do the encoding, including parallelization of remote encoding
4290 # Figure out where each track is going to be encoded
4291 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
4292 if [ "$MAXPROCS" != "0" ]; then
4293 for NUM in $(f_seq_row 1 "$MAXPROCS")
4294 do
4295 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
4296 done
4297 fi
4298 # Strip whitespace
4299 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
4300 for UTRACKNUM in $TRACKQUEUE
4301 do
4302 # Wait for our cue
4303 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
4304 if [ "$GOAHEAD" = "NO" ]; then break; fi
4305 # find out where this track is to be encoded
4306 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
4307 # Make sure we have a place to encode this, if not, exit stage right
4308 if [ -z "$ENCODELOCATIONS" ]; then
4309 continue
4310 fi
4311 PROCEED=
4312 until [ $PROCEED ]
4313 do
4314 for LOCATION in $ENCODELOCATIONS
4315 do
4316 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
4317 # check first if a track has ever been assigned to this location
4318 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
4319 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
4320 if checkerrors encodetrack-$PREVIOUSTRACK; then
4321 for TEMPLOCATION in $ENCODELOCATIONS
4322 do
4323 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
4324 TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
4325 fi
4326 done
4327 ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
4328 ABORT=y
4329 PROCEED=y
4330 break
4331 fi
4332 # We're still here, this location must have been previously assigned,
4333 # and last completed without error - check if it's done with the
4334 # previous track yet
4335 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
4336 done
4337 # all locations are working, wait and try again later
4338 if [ ! $PROCEED ]; then sleep 3; fi
4339 done
4340 # Record the location we're about to encode the next track at
4341 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
4342 fi
4343 # Don't proceed with the rest of the loop if we can't encode
4344 if [ "$ABORT" ]; then continue; fi
4345 ## FIXME ## Add here
4346 ## run_command tagtrack-$OUTPUT-$1 $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="$ABCDETEMPDIR/$CUEFILE"} --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
4347 # Set TRACKNUM, TRACKNAME
4348 if [ -e "$CDDBDATA" ]; then
4349 if [ "$ONETRACK" = "y" ]; then
4350 TRACKNAME="$DALBUM"
4351 TRACKNUM="$FIRSTTRACK"
4352 splitvarious
4353 else
4354 TRACKNUM=$UTRACKNUM
4355 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
4356 getcddbinfo TRACKNAME
4357 splitvarious
4358 fi
4359 fi
4360 # You can't encode a file which needs to be normalized before finishing
4361 # You can't tag a file before it's finished encoding -
4362 # thus all of this is backgrounded together
4363 (
4364 if [ "$DONORMALIZE" = "y" ]; then
4365 if checkstatus readtrack-$UTRACKNUM; then
4366 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
4367 fi
4368 fi
4369 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
4370 if checkstatus readtrack-$UTRACKNUM; then
4371 #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
4372 if [ "$DONORMALIZE" = "y" ]; then
4373 if checkstatus normalizetrack-$UTRACKNUM; then
4374 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4375 fi
4376 else
4377 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4378 fi
4379 fi
4380 fi
4381 if [ "$DOTAG" = "y" ]; then
4382 if checkstatus encodetrack-$UTRACKNUM; then
4383 if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
4384 fi
4385 # Lets tag the cue file
4386 if checkstatus cleancuefile >/dev/null; then :; else
4387 if checkstatus cuefile >/dev/null ; then
4388 do_cleancue
4389 fi
4390 fi
4391 fi
4392 if [ "$DOMOVE" = "y" ]; then
4393 if checkstatus tagtrack-$UTRACKNUM; then
4394 if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
4395 fi
4396 fi
4397 ) &
4398 done
4399
4400
4401 # Go through it again and make sure there's no distmp3 stragglers, otherwise
4402 # we'll delete the files they're working on
4403 # Do NOT play ball if there is no ball to play (so ABORT if needed)
4404 ## FIXME ## Check also for files which are encoded using PIPEs.
4405 if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ] && [ ! "$ABORT" ]; then
4406 PROCEED=
4407 until [ $PROCEED ]
4408 do
4409 PROCEED=y
4410 for LOCATION in $ENCODELOCATIONS
4411 do
4412 CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
4413 # "How can he give us a status update, if he's DEAD?"
4414 if checkstatus encodetrack-$CHECKTRACK; then
4415 continue
4416 fi
4417 # Nothing to see here please go quietly back to your homes
4418 if [ -z "$CHECKTRACK" ]; then continue; fi
4419 # You're still here? Maybe there is something...
4420 if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
4421 done
4422 # hold up
4423 if [ ! $PROCEED ]; then sleep 5; fi
4424 done
4425 fi
4426 # If the above didn't catch the stragglers, this will
4427 wait
4428 if [ "$DOREPLAYGAIN" = "y" ]; then
4429 do_replaygain
4430 fi
4431
4432 # Execute the user-defined post_encode function before cleaning up
4433 post_encode
4434
4435 # Check to see if run_command logged any errors
4436 if [ -f "$ABCDETEMPDIR/errors" ]; then
4437 log error "The following commands failed to run:"
4438 cat "$ABCDETEMPDIR/errors"
4439 # Don't clean up
4440 DOCLEAN=n
4441 fi
4442 if [ "$KEEPWAVS" = "y" ];then
4443 # Don't clean up
4444 DOCLEAN=n
4445 fi
4446 # Check if we have moved all the formats we had previously encoded, if we are not using the FORCE.
4447 if [ "$DOCLEAN" = "y" ] && [ ! "$FORCE" = "y" ]; then
4448 ENCODED_FORMATS=$(grep -E "^encodetrack-(.{3,6})-(.{1,2})$" "$ABCDETEMPDIR/status" | cut -d"-" -f2 | sort -u | tr '\n' '|')
4449 MOVED_FORMATS=$(grep -E "^movetrack-output-(.{3,6})$" "$ABCDETEMPDIR/status" | cut -d"-" -f3 | sort -u | tr '\n' '|')
4450 if [ "$ENCODED_FORMATS" != "$MOVED_FORMATS" ]; then
4451 log warning "The encoded formats does not match with the moved ones"
4452 log warning "Formats encoded: $( echo $ENCODED_FORMATS | tr "|" " " )"
4453 log warning "Formats moved: $( echo $MOVED_FORMATS | tr "|" " " )"
4454 log warning "Use \"abcde -a clean -f -C $DISCID\" to force the removal of the remaining data."
4455 DOCLEAN=n
4456 fi
4457 fi
4458 if [ "$DOCLEAN" = "y" ]; then
4459 # Wipe all the evidence
4460 # Gimme gimme gimme some more time!
4461 sleep 5
4462 rm -rf "$ABCDETEMPDIR"
4463 echo "Finished."
4464 else
4465 echo "Finished. Not cleaning $ABCDETEMPDIR."
4466 fi
4467 )
4468 exit 0
4469
4470 # b:is_bash
4471 # vim:tabstop=4