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