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