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