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