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