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