* Updated changelog ;)
[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 "-M Create a CUE file"
50 echo "-o <type1[,type2]...>"
51 echo " Output file type(s) (vorbis,mp3,flac,spx,mpc,wav,m4a). Defaults to vorbis"
52 echo "-p Pad track numbers with 0's (if less than 10 tracks)"
53 echo "-P Use UNIX pipes to read+encode without wav files"
54 echo "-r <host1[,host2]...>"
55 echo " Also encode on these remote hosts"
56 echo "-R Use local CDDB in recursive mode"
57 echo "-s <field>"
58 echo " Show dielfs from the CDDB info (year,genre)"
59 echo "-S <#> Set the CD speed"
60 echo "-t <#> Start the track numbering at a given number"
61 echo "-T <#> Same as -t but modifies tag numbering"
62 echo "-u Use UNICODE (UTF8) tags and comments"
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 $METAFLAC --add-replay-gain "${OUTPUTFILES[@]}"
531 ;;
532 vorbis|ogg)
533 run_command replaygain-vorbis $VORBISGAIN --album "${OUTPUTFILES[@]}"
534 ;;
535 mp3)
536 run_command replaygain-mp3 $MP3GAIN -a "${OUTPUTFILES[@]}"
537 ;;
538 mpc)
539 run_command replaygain-mpc $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 $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 $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 $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 $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 $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 else
1012 run_command '' echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
1013 RUN_COMMAND="run_command encodetrack-$OUTPUT-$1"
1014 fi
1015 case "$OUTPUT" in
1016 mp3)
1017 case "$2" in
1018 %local*%)
1019 case "$MP3ENCODERSYNTAX" in
1020 lame|toolame|gogo) $RUN_COMMAND nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
1021 bladeenc) $RUN_COMMAND nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" ;;
1022 l3enc|xingmp3enc) $RUN_COMMAND nice $ENCNICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
1023 # FIXME # Relates to the previous FIXME since it might need the "-if" removed.
1024 mp3enc) $RUN_COMMAND nice $ENCNICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
1025 esac
1026 ;;
1027 *)
1028 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
1029 ;;
1030 esac
1031 ;;
1032 vorbis|ogg)
1033 case "$2" in
1034 %local*%)
1035 case "$OGGENCODERSYNTAX" in
1036 vorbize) $RUN_COMMAND nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
1037 oggenc) $RUN_COMMAND nice $ENCNICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
1038 esac
1039 ;;
1040 *)
1041 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
1042 ;;
1043 esac
1044 ;;
1045 flac)
1046 case "$2" in
1047 %local*%)
1048 case "$FLACENCODERSYNTAX" in
1049 flac) $RUN_COMMAND nice $ENCNICE $FLACENCODER -f $FLACENCODEROPTS -o "$OUT" "$IN" ;;
1050 esac
1051 ;;
1052 *)
1053 vecho -n "DISTMP3:"
1054 vecho "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
1055 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
1056 ;;
1057 esac
1058 ;;
1059 spx)
1060 if [ "$(eval echo ${COMMENT})" != "" ]; then
1061 case "$COMMENT" in
1062 *=*) ;;
1063 *) COMMENT="COMMENT=$COMMENT" ;;
1064 esac
1065 COMMENT="--comment \"$COMMENT\""
1066 fi
1067 # Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
1068 if [ ! "$DOTAG" = "y" ]; then
1069 $RUN_COMMAND nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" "$COMMENT" "$IN" "$OUT"
1070 else
1071 $RUN_COMMAND nice $ENCNICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
1072 fi
1073 ;;
1074 mpc)
1075 # MPP/MP+(Musepack) format (.mpc) is done locally, with inline
1076 # tagging.
1077 # I tried compiling the mppenc from corecodecs.org and got some
1078 # errors, so I have not tried it myself.
1079 ## FIXME ## Needs some cleanup to determine if an empty tag sent
1080 ## FIXME ## to the encoder ends up empty.
1081 $RUN_COMMAND nice $ENCNICE $MPPENCODER $MPPENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" "$IN" "$OUT"
1082 ;;
1083 m4a)
1084 # Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
1085 if [ ! "$DOTAG" = "y" ]; then
1086 $RUN_COMMAND nice $ENCNICE $AACENCODER $AACENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" -o "$OUT" "$IN"
1087
1088 else
1089 $RUN_COMMAND nice $ENCNICE $AACENCODER $AACENCODEROPTS -o "$OUT" "$IN"
1090 fi
1091 ;;
1092 wav)
1093 # In case of wav output we need nothing. Just keep the wavs.
1094 ;;
1095 esac
1096 $RUN_COMMAND_PIPES
1097 done
1098 # Only remove .wav if the encoding succeeded
1099 if checkerrors "encodetrack-(.{3,6})-$1"; then :; else
1100 run_command encodetrack-$1 true
1101 if [ ! "$KEEPWAVS" = "y" ] ; then
1102 if [ ! "$KEEPWAVS" = "move" ] ; then
1103 rm -f "$IN"
1104 fi
1105 fi
1106 fi
1107 else
1108 run_command "" echo "HEH! The file we were about to encode disappeared:"
1109 run_command "" echo ">> $IN"
1110 run_command encodetrack-$1 false
1111 fi
1112 }
1113
1114 # do_preprocess [tracknumber]
1115 # variables used:
1116 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
1117 #do_preprocess ()
1118 #{
1119 # IN="$ABCDETEMPDIR/track$1.wav"
1120 # # We need IN to proceed.
1121 # if [ -s "$IN" ] ; then
1122 # for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1123 # do
1124 # #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
1125 # run_command '' echo "Pre-processing track $1 of $TRACKS..."
1126 # case "$POSTPROCESSFORMAT" in
1127 # all|wav*)
1128 # run_command preprocess-$OUTPUT-$1 nice $PRENICE $WAV_PRE $IF $OF ;;
1129 # mp3)
1130 # run_command preprocess-$OUTPUT-$1 nice $PRENICE $MP3_PRE $IF $OF ;;
1131 # ogg)
1132 # run_command preprocess-$OUTPUT-$1 nice $PRENICE $OGG_PRE $IF $OF ;;
1133 # flac)
1134 # run_command preprocess-$OUTPUT-$1 nice $PRENICE $FLAC_PRE $IF $OF ;;
1135 # spx)
1136 # run_command preprocess-$OUTPUT-$1 nice $PRENICE $SPX_PRE $IF $OF ;;
1137 # esac
1138 # done
1139 # # Only remove .wav if the encoding succeeded
1140 # if checkerrors "preprocess-(.{3,4})-$1"; then
1141 # run_command preprocess-$1 false
1142 # else
1143 # run_command preprocess-$1 true
1144 # fi
1145 # else
1146 # if [ "$(checkstatus encode-output)" = "loud" ]; then
1147 # echo "HEH! The file we were about to pre-process disappeared:"
1148 # echo ">> $IN"
1149 # fi
1150 # run_command preprocess-$1 false
1151 # fi
1152 #}
1153
1154
1155 # do_postprocess [tracknumber]
1156 # variables used:
1157 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
1158 #do_postprocess ()
1159 #{
1160 # for POSTPROCESSFORMAT in $(echo $POSTPROCESSFORMATS | tr , \ )
1161 # do
1162 # IN="$ABCDETEMPDIR/track$1.$POSTPROCESSFORMAT"
1163 # # We need IN to proceed.
1164 # if [ -s "$IN" ] ; then
1165 # #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
1166 # run_command '' echo "Post-processing track $1 of $TRACKS..."
1167 # case "$POSTPROCESSFORMAT" in
1168 # mp3)
1169 # run_command postprocess-$OUTPUT-$1 nice $POSTNICE $MP3_POST $IF $OF ;;
1170 # ogg)
1171 # run_command postprocess-$OUTPUT-$1 nice $POSTNICE $OGG_POST $IF $OF ;;
1172 # flac)
1173 # run_command postprocess-$OUTPUT-$1 nice $POSTNICE $FLAC_POST $IF $OF ;;
1174 # spx)
1175 # run_command postprocess-$OUTPUT-$1 nice $POSTNICE $SPX_POST $IF $OF ;;
1176 # esac
1177 # # Only remove .wav if the encoding succeeded
1178 # if checkerrors "postprocess-(.{3,4})-$1"; then
1179 # run_command postprocess-$1 false
1180 # else
1181 # run_command postprocess-$1 true
1182 # fi
1183 # else
1184 # if [ "$(checkstatus encode-output)" = "loud" ]; then
1185 # echo "HEH! The file we were about to post-process disappeared:"
1186 # echo ">> $IN"
1187 # fi
1188 # run_command postprocess-$1 false
1189 # fi
1190 # done
1191 #}
1192
1193 # do_single_gain
1194 # variables used:
1195 # FIXME #
1196 do_single_gain ()
1197 {
1198 :
1199 }
1200
1201 # do_batch_gain
1202 # variables used:
1203 # MP3GAIN, MP3GAINOPTS, VORBISGAIN, VORBISGAINOPTS, MPPGAIN, MPPGAINOPTS
1204 # FIXME #
1205 do_batch_gain ()
1206 {
1207 # The commands here don't go through run_command because they're never supposed to be silenced
1208 echo "Batch analizing gain in tracks: $TRACKQUEUE"
1209 (
1210 cd "$ABCDETEMPDIR"
1211 BLURB=
1212 TRACKFILES=
1213 for UTRACKNUM in $TRACKQUEUE
1214 do
1215 MP3FILES="$TRACKFILES track$UTRACKNUM.mp3"
1216 done
1217 # FIXME # Hard-coded batch option!
1218 $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
1219 RETURN=$?
1220 if [ "$RETURN" != "0" ]; then
1221 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
1222 else
1223 for UTRACKNUM in $TRACKQUEUE
1224 do
1225 echo normalizetrack-$UTRACKNUM >> status
1226 done
1227 fi
1228 )
1229 }
1230
1231 # do_batch_normalize
1232 # variables used:
1233 # NORMALIZER, NORMALIZEROPTS
1234 do_batch_normalize ()
1235 {
1236 # The commands here don't go through run_command because they're never supposed to be silenced
1237 echo "Batch normalizing tracks: $TRACKQUEUE"
1238 (
1239 cd "$ABCDETEMPDIR"
1240 BLURB=
1241 TRACKFILES=
1242 for UTRACKNUM in $TRACKQUEUE
1243 do
1244 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
1245 done
1246 # XXX: Hard-coded batch option!
1247 $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
1248 RETURN=$?
1249 if [ "$RETURN" != "0" ]; then
1250 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
1251 else
1252 for UTRACKNUM in $TRACKQUEUE
1253 do
1254 echo normalizetrack-$UTRACKNUM >> status
1255 done
1256 fi
1257 )
1258 }
1259
1260 # do_normalize [tracknumber]
1261 # variables used:
1262 # TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
1263 do_normalize ()
1264 {
1265 IN="$ABCDETEMPDIR/track$1.wav"
1266 if [ -e "$IN" ] ; then
1267 run_command '' echo "Normalizing track $1 of $TRACKS: $TRACKNAME..."
1268 run_command normalizetrack-$1 $NORMALIZER $NORMALIZEROPTS "$IN"
1269 else
1270 if [ "$(checkstatus encode-output)" = "loud" ]; then
1271 echo "HEH! The file we were about to normalize disappeared:"
1272 echo ">> $IN"
1273 fi
1274 run_command normalizetrack-$1 false "File $IN was not found"
1275 fi
1276 }
1277
1278 # do_move [tracknumber]
1279 # Deduces the outfile from environment variables
1280 # Creates directory if necessary
1281 # variables used:
1282 # TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, CDYEAR
1283 do_move ()
1284 {
1285 for TMPOUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1286 do
1287 # For now, set OUTPUT as TMPOUTPUT, and then change it once we have
1288 # defined the OUTPUTFILE:
1289 OUTPUT="$TMPOUTPUT"
1290
1291 # Create ALBUMFILE, ARTISTFILE, TRACKFILE
1292 # Munge filenames as follows:
1293 # ' ' -> '_'
1294 # '/' -> '_'
1295 # ''' -> ''
1296 # '?' -> ''
1297 # Eat control characters
1298 ALBUMFILE="$(mungefilename "$DALBUM")"
1299 ARTISTFILE="$(mungefilename "$TRACKARTIST")"
1300 TRACKFILE="$(mungefilename "$TRACKNAME")"
1301 GENRE="$(mungegenre "$GENRE")"
1302 YEAR=${CDYEAR:-$CDYEAR}
1303 # If we want to start the tracks with a given number, we need to modify
1304 # the TRACKNUM value before evaluation
1305 gettracknum
1306 # Supported variables for OUTPUTFORMAT are GENRE, YEAR, ALBUMFILE,
1307 # ARTISTFILE, TRACKFILE, and TRACKNUM.
1308 if [ "$ONETRACK" = "y" ]; then
1309 if [ "$VARIOUSARTISTS" = "y" ]; then
1310 OUTPUTFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\")"
1311 else
1312 OUTPUTFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\")"
1313 fi
1314 else
1315 if [ "$VARIOUSARTISTS" = "y" ]; then
1316 OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT"\")"
1317 else
1318 OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT"\")"
1319 fi
1320 fi
1321 if checkerrors "tagtrack-$OUTPUT-$1"; then :; else
1322 # Once we know the specific output was successful, we can change
1323 # the OUTPUT to the value containing the container
1324 case $TMPOUTPUT in
1325 vorbis|ogg)
1326 OUTPUT=$OGGOUTPUTCONTAINER
1327 ;;
1328 flac)
1329 OUTPUT=$FLACOUTPUTCONTAINER
1330 ;;
1331 *)
1332 OUTPUT=$TMPOUTPUT
1333 ;;
1334 esac
1335 # Check that the directory for OUTPUTFILE exists, if it doesn't, create it
1336 OUTPUTFILEDIR="$(dirname "$OUTPUTDIR/$OUTPUTFILE")"
1337 case $OUTPUT in
1338 wav)
1339 if [ "$DOCLEAN" != "y" ] && [ "$FORCE" != "y" ]; then
1340 # FIXME # introduce warnings?
1341 :
1342 else
1343 # mkdir -p shouldn't return an error if the directory already exists
1344 mkdir -p "$OUTPUTFILEDIR"
1345 run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
1346 if checkstatus movetrack-output-$OUTPUT; then :; else
1347 run_command movetrack-output-$OUTPUT true
1348 fi
1349 fi
1350 ;;
1351 *)
1352 # mkdir -p shouldn't return an error if the directory already exists
1353 mkdir -p "$OUTPUTFILEDIR"
1354 run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
1355 if checkstatus movetrack-output-$OUTPUT; then :; else
1356 run_command movetrack-output-$OUTPUT true
1357 fi
1358 ;;
1359 esac
1360 # Lets move the cue file
1361 if CUEFILE=$(checkstatus cuefile) >/dev/null ; then
1362 if [ -r "$ABCDETEMPDIR/$CUEFILE" ]; then
1363 if checkstatus movecue-$OUTPUT; then :; else
1364 # Silence the Copying output since it overlaps with encoding processes...
1365 #run_command '' vecho "Copying cue file to its destination directory..."
1366 if checkstatus onetrack >/dev/null ; then
1367 case $OUTPUT in
1368 wav)
1369 if [ "$DOCLEAN" != "y" ] && [ "$FORCE" != "y" ]; then
1370 # We dont have the dir, since it was not created before.
1371 :
1372 else
1373 run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.cue"
1374 fi
1375 ;;
1376 # NOTE: Creating a cue file with the 3-char-extension files is to comply with
1377 # http://brianvictor.tripod.com/mp3cue.htm#details
1378 [a-z0-9][a-z0-9][a-z0-9])
1379 run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.cue"
1380 ;;
1381 *)
1382 run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT.cue"
1383 ;;
1384 esac
1385 else
1386 run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTFILEDIR/$CUEFILE"
1387 fi
1388 echo movecue-$OUTPUT >> "$ABCDETEMPDIR/status"
1389 fi
1390 fi
1391 fi
1392 fi
1393 done
1394 }
1395
1396 # do_playlist
1397 # Create the playlist if wanted
1398 # Variables used:
1399 # PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
1400 # VARIOUSARTISTS, OUTPUTDIR
1401 do_playlist ()
1402 {
1403 for TMPOUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1404 do
1405 case $TMPOUTPUT in
1406 vorbis|ogg)
1407 OUTPUT=$OGGOUTPUTCONTAINER
1408 ;;
1409 flac)
1410 OUTPUT=$FLACOUTPUTCONTAINER
1411 ;;
1412 *)
1413 OUTPUT=$TMPOUTPUT
1414 ;;
1415 esac
1416 # Create a playlist file for the playlist data to go into.
1417 # We used to wipe it out if it existed. Now we request permision if interactive.
1418 for LASTTRACK in $TRACKQUEUE; do :; done
1419 ALBUMFILE="$(mungefilename "$DALBUM")"
1420 ARTISTFILE="$(mungefilename "$DARTIST")"
1421 GENRE="$(mungegenre "$GENRE")"
1422 YEAR=${CDYEAR:-$CDYEAR}
1423 if [ "$VARIOUSARTISTS" = "y" ] ; then
1424 PLAYLISTFILE="$(eval echo "$VAPLAYLISTFORMAT")"
1425 else
1426 PLAYLISTFILE="$(eval echo "$PLAYLISTFORMAT")"
1427 fi
1428 FINALPLAYLISTDIR="$(dirname "$OUTPUTDIR/$PLAYLISTFILE")"
1429 mkdir -p "$FINALPLAYLISTDIR"
1430 if [ -s "$OUTPUTDIR/$PLAYLISTFILE" ]; then
1431 echo -n "Erase, Append to, or Keep the existing playlist file? [e/a/k] (e): " >&2
1432 if [ "$INTERACTIVE" = "y" ]; then
1433 while [ "$DONE" != "y" ]; do
1434 read ERASEPLAYLIST
1435 case $ERASEPLAYLIST in
1436 e|E|a|A|k|K) DONE=y ;;
1437 *) ;;
1438 esac
1439 done
1440 else
1441 echo e >&2
1442 ERASEPLAYLIST=e
1443 fi
1444 # Once we erase the playlist, we use append to create the new one.
1445 [ "$ERASEPLAYLIST" = "e" -o "$ERASEPLAYLIST" = "E" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE" && ERASEPLAYLIST=a
1446 else
1447 # The playlist does not exist, so we can safelly use append to create the new list
1448 ERASEPLAYLIST=a
1449 fi
1450 if [ "$ERASEPLAYLIST" = "a" -o "$ERASEPLAYLIST" = "A" ]; then
1451 touch "$OUTPUTDIR/$PLAYLISTFILE"
1452 for UTRACKNUM in $TRACKQUEUE
1453 do
1454 # Shares some code with do_move since the filenames have to match
1455 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
1456 getcddbinfo TRACKNAME
1457 splitvarious
1458 TRACKFILE="$(mungefilename "$TRACKNAME")"
1459 ARTISTFILE="$(mungefilename "$TRACKARTIST")"
1460 ALBUMFILE="$(mungefilename "$DALBUM")"
1461 # If we want to start the tracks with a given number, we need to modify the
1462 # TRACKNUM value before evaluation
1463 gettracknum
1464 if [ "$VARIOUSARTISTS" = "y" ]; then
1465 OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT\"")"
1466 else
1467 OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT\"")"
1468 fi
1469 if [ "$VARIOUSARTISTS" = "y" ]; then
1470 if [ "$VAPLAYLISTDATAPREFIX" ] ; then
1471 echo ${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
1472 else
1473 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1474 fi
1475 else
1476 if [ "$PLAYLISTDATAPREFIX" ]; then
1477 echo ${PLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
1478 else
1479 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1480 fi
1481 fi
1482 done
1483 fi
1484 ## this will convert the playlist to have CRLF line-endings, if specified
1485 ## (some hardware players insist on CRLF endings)
1486 if [ "$DOSPLAYLIST" = "y" ]; then
1487 awk '{substr("\r",""); printf "%s\r\n", $0}' "$OUTPUTDIR/$PLAYLISTFILE" > "$ABCDETEMPDIR/PLAYLISTFILE.tmp"
1488 # mv -f "$ABCDETEMPDIR/PLAYLISTFILE.tmp" "$OUTPUTDIR/$PLAYLISTFILE"
1489 cat "$ABCDETEMPDIR/PLAYLISTFILE.tmp" | sed 's/\//\\/' > "$OUTPUTDIR/$PLAYLISTFILE"
1490 fi
1491 echo "playlistcomplete" >> "$ABCDETEMPDIR/status"
1492 done
1493 }
1494
1495 # abcde.cue2discid
1496 # This function reads a cuefile on stdin and writes an extended
1497 # cddb query on stdout. Any PREGAP for track 1 is properly
1498 # handled, although cue files embedded in FLAC files do not
1499 # appear to properly store the PREGAP setting. :(
1500 abcde.cue2discid () {
1501
1502 cddb_sum () {
1503 val=$1
1504 ret=0
1505 while [ $val -gt 0 ] ; do
1506 ret=$(( $ret + ( $val % 10) ))
1507 val=$(( $val / 10 ))
1508 done
1509 echo $ret
1510 }
1511
1512 msf2lba () {
1513 OIFS="$IFS"
1514 IFS=":"
1515 set -- $1
1516 IFS="$OIFS"
1517
1518 echo $(( ((($1 * 60) + $2) * 75) + $3 ))
1519 }
1520
1521 OFFSET=150
1522 PREGAP=0
1523 LEADOUT=0
1524 LEADIN=88200
1525 i=0
1526 N=0
1527
1528 while read line ; do
1529 set -- $line
1530 case "$1" in
1531 TRACK) i=$(( i + 1 ))
1532 ;;
1533 INDEX) if [ "$2" -eq 1 ] ; then
1534 LBA=$(msf2lba $3)
1535 START=$(( $LBA + $PREGAP + $OFFSET ))
1536 eval TRACK$i=$START
1537 X=$(cddb_sum $(( $START / 75 )) )
1538 N=$(( $N + $X ))
1539 fi
1540 ;;
1541 PREGAP) PREGAP=$(msf2lba $2)
1542 ;;
1543 REM) case "$2" in
1544 FLAC__lead-out)
1545 LEADOUT=$(( $4 / 588 ))
1546 ;;
1547 FLAC__lead-in)
1548 LEADIN=$(( $3 / 588 ))
1549 ;;
1550 esac
1551 ;;
1552 esac
1553
1554 done
1555
1556 TRACKS=$i
1557 LEADOUT=$(( $LEADOUT + $LEADIN ))
1558
1559 LENGTH=$(( $LEADOUT/75 - $TRACK1/75 ))
1560 DISCID=$(( ( $N % 255 ) * 2**24 | $LENGTH * 2**8 | $TRACKS ))
1561 printf "%08x %i" $DISCID $TRACKS
1562
1563 j=1
1564 while [ $j -le $TRACKS ] ; do
1565 eval echo -n "\" \$TRACK$j\""
1566 j=$((j+1))
1567 done
1568 echo " $(( $LEADOUT / 75 ))"
1569 }
1570
1571 # abcde.mkcue
1572 # abcde.mkcue [--wholedisk]
1573 # This creates a cuefile directly from the extended discid information
1574 # The --wholedisk option controls whether we're ripping data from the
1575 # start of track one or from the start of the disk (usually, but not
1576 # always the same thing!)
1577 #
1578 # Track one leadin/pregap (if any) handeling:
1579 # --wholedisk specified:
1580 # TRACK 01 AUDIO
1581 # INDEX 00 00:00:00
1582 # INDEX 01 <pregap value>
1583 # Remaining track index values unchanged from disc TOC
1584 #
1585 # --wholedisk not specified
1586 # TRACK 01 AUDIO
1587 # PREGAP <pregap value>
1588 # INDEX 01 00:00:00
1589 # Remaining track index values offset by <pregap value>
1590 #
1591 # Variables used:
1592 # TRACKINFO
1593 abcde.mkcue () {
1594
1595 echomsf () {
1596 printf "$1%02i:%02i:%02i\n" $(($2/4500)) $((($2/75)%60)) $(($2%75))
1597 }
1598
1599 local MODE DISCID TRACKS
1600 local i OFFSET LBA
1601
1602
1603 if [ "$1" = --wholedisc ] ; then
1604 MODE=INDEX
1605 else
1606 MODE=PREGAP
1607 fi
1608
1609 set -- $TRACKINFO
1610
1611 DISCID=$1
1612 TRACKS=$2
1613 shift 2
1614
1615 echo REM DISCID $DISCID
1616 echo FILE \"dummy.wav\" WAVE
1617
1618 if [ $1 -ne 150 ] ; then
1619 if [ $MODE = PREGAP ] ; then
1620 OFFSET=$1
1621 else
1622 OFFSET=150
1623 fi
1624 fi
1625
1626 i=1
1627 while [ $i -le "$TRACKS" ] ; do
1628 LBA=$(( $1 - $OFFSET ))
1629 printf " TRACK %02i AUDIO\n" $i
1630 if [ $i -eq 1 -a $1 -ne 150 ] ; then
1631 if [ $MODE = PREGAP ] ; then
1632 echomsf " PREGAP " $(($OFFSET-150))
1633 else
1634 echo " INDEX 00 00:00:00"
1635 fi
1636 fi
1637 echomsf " INDEX 01 " $LBA
1638 i=$(($i+1))
1639 shift
1640 done
1641 }
1642
1643 # do_discid
1644 # This essentially the start of things
1645 do_discid ()
1646 {
1647 # Query the CD to get the track info, unless the user specified -C
1648 # or we are using some actions which do not need the CDDB data at all
1649 #if [ ! X"$EXPACTIONS" = "X" ]; then
1650 # :
1651 #elif [ -z "$DISCID" ]; then
1652 if [ -z "$DISCID" ]; then
1653 vecho -n "Getting CD track info... "
1654 # In OSX, unmount the disc before a query
1655 if [ "$OSFLAVOUR" = "OSX" ]; then
1656 disktool -u ${CDROM#/dev/}
1657 fi
1658 case "$CDROMREADERSYNTAX" in
1659 flac)
1660 if $METAFLAC $METAFLACOPTS --export-cuesheet-to=- "$CDROM" > /dev/null 2>&1 ; then
1661 case "$CUE2DISCID" in
1662 builtin)
1663 #vecho "Using builtin cue2discid implementation..."
1664 CUESHEET="$(metaflac $METAFLACOPTS --export-cuesheet-to=- "$CDROM")"
1665
1666 #TRACKS=$(echo $CUESHEET | egrep "TRACK \+[[:digit:]]\+ \+AUDIO" |wc -l)
1667 #TRACKS=0
1668 OFFSETTIMES=( $(echo "$CUESHEET" | sed -n -e's/\ *INDEX 01\ \+//p' ) )
1669 TRACKS=${#OFFSETTIMES[@]}
1670 unset OFFSETS
1671 #echo "processing offsetimes ${OFFSETTIMES[@]}"
1672 for OFFSETTIME in ${OFFSETTIMES[@]}; do
1673 OFFSETS="$OFFSETS $(( 10#${OFFSETTIME:0:2} * 4500 + 10#${OFFSETTIME:3:2} * 75 + 10#${OFFSETTIME:6:2} ))"
1674 #OFFSETS[${#OFFSETS[*]}]=$(( 10#${OFFSETTIME:0:2} * 4500 + 10#${OFFSETTIME:3:2} * 75 + 10#${OFFSETTIME:6:2} ))
1675 done
1676
1677 LEADOUT=$(( $(echo "$CUESHEET" | grep lead-out | get_last) / 44100 * 75 ))
1678 LEADIN=$(( $(echo "$CUESHEET" | grep lead-in | get_last) / 44100 * 75 ))
1679 makeids
1680 ;;
1681 *)
1682 #vecho "Using external python cue2discid implementation..."
1683 TRACKINFO=$($METAFLAC $METAFLACOPTS --export-cuesheet-to=- "$CDROM" | $CUE2DISCID)
1684 ;;
1685 esac
1686 else
1687 log error "the input flac file does not contain a cuesheet."
1688 exit 1
1689 fi
1690 ;;
1691 # cdparanoia|debug)
1692 # CDPARANOIAOUTPUT="$( $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -Q --verbose 2>&1 )"
1693 # RET=$?
1694 # if [ ! "$RET" = "0" ];then
1695 # log warning "something went wrong while querying the CD... Maybe a DATA CD?"
1696 # fi
1697 #
1698 # TRACKS="$(echo "$CDPARANOIAOUTPUT" | egrep '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ')"
1699 # CDPARANOIAAUDIOTRACKS="$TRACKS"
1700 #
1701 # LEADOUT="$(echo "$CDPARANOIAOUTPUT" | egrep -o '^TOTAL[[:space:]]+([[:digit:]]+)' | get_last)"
1702 # OFFSETS="$(echo "$CDPARANOIAOUTPUT" | sed -n -e's/^ .* \([0-9]\+\) \[.*/\1/p')"
1703 # makeids
1704 # ;;
1705 *)
1706 case "$CDDBMETHOD" in
1707 cddb) TRACKINFO=$($CDDISCID "$CDROM") ;;
1708 # FIXME # musicbrainz needs a cleanup
1709 musicbrainz) TRACKINFO=$($MUSICBRAINZ -c "$CDROM" ) ;;
1710 esac
1711 ;;
1712 esac
1713 # Make sure there's a CD in there by checking cd-discid's return code
1714 if [ ! "$?" = "0" ]; then
1715 if [ "$CDROMREADERSYNTAX" = "flac" ] ; then
1716 log error "cuesheet information from the flac file could not be read."
1717 log error "Perhaps the flac file does not contain a cuesheet?."
1718 exit 1
1719 else
1720 log error "CD could not be read. Perhaps there's no CD in the drive?"
1721 exit 1
1722 fi
1723 fi
1724 # In OSX, remount the disc again
1725 if [ "$OSFLAVOUR" = "OSX" ]; then
1726 disktool -m ${CDROM#/dev/}
1727 fi
1728 WEHAVEACD=y
1729 DISCID=$(echo $TRACKINFO | cut -f1 -d' ')
1730 else
1731 TRACKINFO=$(cat "$WAVOUTPUTDIR/abcde.$DISCID/discid")
1732 fi
1733
1734 # Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.
1735 # This needs to be done now because a section of the resuming code will need
1736 # it later.
1737
1738 # get the number of digits to pad TRACKNUM with - we'll use this later
1739 # a CD can only hold 99 tracks, but since we support a feature for starting
1740 # numbering the tracks from a given number, we might need to set it as a
1741 # variable for the user to define... or obtain it somehow.
1742 if [ "$PADTRACKS" = "y" ] ; then
1743 TRACKNUMPADDING=2
1744 fi
1745
1746 ABCDETEMPDIR="$WAVOUTPUTDIR/abcde.$(echo $TRACKINFO | cut -f1 -d' ')"
1747 if [ -z "$TRACKQUEUE" ]; then
1748 if [ ! "$STRIPDATATRACKS" = "n" ]; then
1749 case "$CDROMREADERSYNTAX" in
1750 cdparanoia|debug)
1751 if [ "$WEHAVEACD" = "y" ]; then
1752 vecho "Querying the CD for audio tracks..."
1753 CDPARANOIAOUTPUT="$( $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -Q --verbose 2>&1 )"
1754 RET=$?
1755 if [ ! "$RET" = "0" ];then
1756 log warning "something went wrong while querying the CD... Maybe a DATA CD?"
1757 fi
1758 TRACKS="$(echo "$CDPARANOIAOUTPUT" | egrep '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ')"
1759 CDPARANOIAAUDIOTRACKS="$TRACKS"
1760 else
1761 # Previous versions of abcde would store the tracks on a file, instead of the status record.
1762 if [ -f "$ABCDETEMPDIR/cdparanoia-audio-tracks" ]; then
1763 echo cdparanoia-audio-tracks=$( cat "$ABCDETEMPDIR/cdparanoia-audio-tracks" ) >> "$ABCDETEMPDIR/status"
1764 rm -f "$ABCDETEMPDIR/cdparanoia-audio-tracks"
1765 fi
1766 if [ -f "$ABCDETEMPDIR/status" ] && TRACKS=$(checkstatus cdparanoia-audio-tracks); then :; else
1767 TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
1768 fi
1769 fi
1770 ;;
1771 *) TRACKS=$(echo $TRACKINFO | cut -f2 -d' ') ;;
1772 esac
1773 else
1774 TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
1775 fi
1776 if echo "$TRACKS" | grep "[[:digit:]]" > /dev/null 2>&1 ;then :;else
1777 log info "The disc does not contain any tracks. Giving up..."
1778 exit 0
1779 fi
1780 echo -n "Grabbing entire CD - tracks: "
1781 if [ ! "$PADTRACKS" = "y" ] ; then
1782 TRACKNUMPADDING=$(echo -n $TRACKS | wc -c | tr -d ' ')
1783 fi
1784 TRACKS=$(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
1785 X=0
1786 while [ "$X" -ne "$TRACKS" ]
1787 do
1788 X=$(printf "%0.${TRACKNUMPADDING}d" $(expr $X + 1))
1789 TRACKQUEUE=$(echo $TRACKQUEUE $X)
1790 done
1791 echo $TRACKQUEUE
1792 else
1793 TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
1794 # User-supplied track queue.
1795 # Weed out non-numbers, whitespace, then sort and weed out duplicates
1796 TRACKQUEUE=$(echo $TRACKQUEUE | sed 's-[^0-9 ]--g' | tr ' ' '\n' | grep -v ^$ | sort -n | uniq | tr '\n' ' ' | sed 's- $--g')
1797 # Once cleaned, obtain the highest value in the trackqueue for number padding
1798 for LASTTRACK in $TRACKQUEUE; do :; done
1799 if [ ! "$PADTRACKS" = "y" ] ; then
1800 TRACKNUMPADDING=$(echo -n $LASTTRACK | wc -c | tr -d ' ')
1801 fi
1802 # Now we normalize the trackqueue
1803 for TRACK in $TRACKQUEUE ; do
1804 TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${TRACK} + 0 ))
1805 PADTRACKQUEUE=$(echo $PADTRACKQUEUE $TRACKNUM)
1806 done
1807 TRACKQUEUE=$PADTRACKQUEUE
1808 echo Grabbing tracks: "$TRACKQUEUE"
1809 fi
1810
1811 QUEUEDTRACKS=$(echo $TRACKQUEUE | wc -w | tr -d ' ')
1812
1813 # We have the discid, create a temp directory after it to store all the temp
1814 # info
1815
1816 if [ -e "$ABCDETEMPDIR" ]; then
1817 echo -n "abcde: attempting to resume from $ABCDETEMPDIR"
1818 # It already exists, see if it's a directory
1819 if [ ! -d "$ABCDETEMPDIR" ]; then
1820 # This is a file/socket/fifo/device/etc, not a directory
1821 # Complain and exit
1822 echo >&2
1823 echo "abcde: file $ABCDETEMPDIR already exists and does not belong to abcde." >&2
1824 echo "Please investigate, remove it, and rerun abcde." >&2
1825 exit 1
1826 fi
1827 echo -n .
1828 # It's a directory, let's see if it's owned by us
1829 if [ ! -O "$ABCDETEMPDIR" ]; then
1830 # Nope, complain and exit
1831 echo >&2
1832 echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
1833 echo "Please investigate, remove it, and rerun abcde." >&2
1834 exit 1
1835 fi
1836 echo .
1837 # See if it's populated
1838 if [ ! -f "$ABCDETEMPDIR/discid" ]; then
1839 # Wipe and start fresh
1840 echo "abcde: $ABCDETEMPDIR/discid not found. Abcde must remove and recreate" >&2
1841 echo -n "this directory to continue. Continue? [y/n] (n)" >&2
1842 if [ "$INTERACTIVE" = "y" ]; then
1843 read ANSWER
1844 else
1845 echo y >&2
1846 ANSWER=y
1847 fi
1848 if [ "$ANSWER" != "y" ]; then
1849 exit 1
1850 fi
1851 rm -rf "$ABCDETEMPDIR" || exit 1
1852 mkdir -p "$ABCDETEMPDIR"
1853 if [ "$?" -gt "0" ]; then
1854 # Directory already exists or could not be created
1855 echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
1856 exit 1
1857 fi
1858 else
1859 # Everything is fine. Check for ^encodetracklocation-
1860 # and encode-output entries in the status file and
1861 # remove them. These are not relevant across sessions.
1862 if [ -f "$ABCDETEMPDIR/status" ]; then
1863 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
1864 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
1865 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
1866 fi
1867 # Remove old error messages
1868 if [ -f "$ABCDETEMPDIR/errors" ]; then
1869 rm -f "$ABCDETEMPDIR/errors"
1870 fi
1871 fi
1872 else
1873 # We are starting from scratch
1874 mkdir -p "$ABCDETEMPDIR"
1875 if [ "$?" -gt "0" ]; then
1876 # Directory already exists or could not be created
1877 echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
1878 exit 1
1879 fi
1880 cat /dev/null > "$ABCDETEMPDIR/status"
1881 # Store the abcde version in the status file.
1882 echo "abcde-version=$VERSION" >> "$ABCDETEMPDIR/status"
1883 fi
1884 if [ X"$MAKECUEFILE" = "Xy" -a X"$WEHAVEACD" = "Xy" ]; then
1885 if checkstatus cuefile > /dev/null 2>&1 ; then :; else
1886 CUEFILE=cue-$(echo "$TRACKINFO" | cut -f1 -d' ').txt
1887 vecho "Creating cue file..."
1888 case $CDROMREADERSYNTAX in
1889 flac)
1890 if $METAFLAC --export-cuesheet-to=- "$CDROM" > "$ABCDETEMPDIR/$CUEFILE"; then
1891 echo cuefile=$CUEFILE >> "$ABCDETEMPDIR/status"
1892 else
1893 log warning "the input flac file does not contain a cuesheet."
1894 fi
1895 ;;
1896 *)
1897 if $CUEREADER $CUEREADEROPTS > "$ABCDETEMPDIR/$CUEFILE"; then
1898 echo cuefile=$CUEFILE >> "$ABCDETEMPDIR/status"
1899 else
1900 log warning "reading the CUE sheet is still considered experimental"
1901 log warning "and there was a problem with the CD reading. abcde will continue,"
1902 log warning "but consider reporting the problem to the abcde author"
1903 fi
1904 ;;
1905 esac
1906 fi
1907 fi
1908 # If we got the CDPARANOIA status and it is not recorded, save it now
1909 if [ -n "$CDPARANOIAAUDIOTRACKS" ]; then
1910 if checkstatus cdparanoia-audio-tracks > /dev/null 2>&1; then :; else
1911 echo cdparanoia-audio-tracks=$CDPARANOIAAUDIOTRACKS >> "$ABCDETEMPDIR/status"
1912 fi
1913 fi
1914
1915 # Create the discid file
1916 echo "$TRACKINFO" > "$ABCDETEMPDIR/discid"
1917 if checkstatus cddbmethod > /dev/null 2>&1 ; then :; else
1918 echo "cddbmethod=$CDDBMETHOD" >> "$ABCDETEMPDIR/status"
1919 fi
1920 }
1921
1922 # do_cleancue
1923 # Create a proper CUE file based on the CUE file we created before.
1924 do_cleancue()
1925 {
1926 if CUEFILE_IN="$ABCDETEMPDIR"/$(checkstatus cuefile); then
1927 CUEFILE_OUT=$CUEFILE_IN.out
1928 ### FIXME ### checkstatus cddb
1929 if [ -e "$CDDBDATA" ]; then
1930 vecho "Adding metadata to the cue file..."
1931 # FIXME It doesn't preserve spaces! Why?
1932 # FIXME parse $track into PERFORMER and TITLE - abcde already has code for this?
1933 n=1
1934 echo "PERFORMER \"$DARTIST\"" >> "$CUEFILE_OUT"
1935 echo "TITLE \"$DALBUM\"" >> "$CUEFILE_OUT"
1936 # Set IFS to <newline> to prevent read from swallowing spaces and tabs
1937 OIFS="$IFS"
1938 IFS='
1939 '
1940 cat "$CUEFILE_IN" | while read line
1941 do
1942 if echo "$line" | grep "INDEX 01" > /dev/null 2>&1 ; then
1943 # FIXME # Possible patch: remove the line above, uncomment the 2 lines below.
1944 # echo "$line" >> "$CUEFILE_OUT"
1945 # if echo "$line" | grep "^[[:space:]]*TRACK" > /dev/null 2>&1 ; then
1946 eval track="\$TRACK$n"
1947 n=$(expr $n + 1)
1948 echo " TITLE \"$track\"" >> "$CUEFILE_OUT"
1949 fi
1950 # FIXME # If the lines above are uncommented, remove the line below.
1951 echo "$line" >> "$CUEFILE_OUT"
1952 done
1953 IFS="$OIFS"
1954 mv "$CUEFILE_OUT" "$CUEFILE_IN"
1955 echo "cleancuefile" >> "$ABCDETEMPDIR/status"
1956 fi
1957 fi
1958 }
1959
1960 # do_cddbparse
1961 # Parses a CDDB file and outputs the title and the track names.
1962 # Variables: CDDBFILE
1963 do_cddbparse ()
1964 {
1965 CDDBPARSEFILE="$1"
1966 # List out disc title/author and contents
1967 if [ "$ONETRACK" = "y" ]; then
1968 vecho "ONETRACK mode selected: displaying only the title of the CD..."
1969 fi
1970 echo "---- $(grep DTITLE "${CDDBPARSEFILE}" | cut '-d=' -f2- | tr -d \\r\\n ) ----"
1971 if [ X"$SHOWCDDBYEAR" = "Xy" ]; then
1972 PARSEDYEAR=$(grep DYEAR "${CDDBPARSEFILE}" | cut '-d=' -f2-)
1973 if [ ! X"$PARSEDYEAR" = "X" ]; then
1974 echo "Year: $PARSEDYEAR"
1975 fi
1976 fi
1977 if [ X"$SHOWCDDBGENRE" = "Xy" ]; then
1978 PARSEDGENRE=$(grep DGENRE "${CDDBPARSEFILE}" | cut '-d=' -f2-)
1979 if [ ! X"$PARSEDGENRE" = "X" ]; then
1980 echo "Genre: $PARSEDGENRE"
1981 fi
1982 fi
1983 if [ ! "$ONETRACK" = "y" ]; then
1984 for TRACK in $(f_seq_row 1 $TRACKS)
1985 do
1986 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
1987 done
1988 fi
1989 }
1990
1991 # do_localcddb
1992 # Check for a local CDDB file, and report success
1993 do_localcddb ()
1994 {
1995 if checkstatus cddb-readcomplete && checkstatus cddb-choice >/dev/null; then :; else
1996
1997 CDDBLOCALSTATUS="notfound"
1998 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
1999 USELOCALRESP="y"
2000
2001 if [ "$CDDBLOCALRECURSIVE" = "y" ]; then
2002 CDDBLOCALRESULTS="$(find ${CDDBLOCALDIR} -name "${CDDBDISCID}" -type f 2> /dev/null)"
2003 if [ ! "${CDDBLOCALRESULTS}" = "" ]; then
2004 if (( $(echo "${CDDBLOCALRESULTS}" | wc -l) == 1 )); then
2005 CDDBLOCALFILE="${CDDBLOCALRESULTS}"
2006 CDDBLOCALMATCH=single
2007 elif (( $(echo "${CDDBLOCALRESULTS}" | wc -l) > 1 )); then
2008 CDDBLOCALMATCH=multiple
2009 fi
2010 else
2011 CDDBLOCALMATCH=none
2012 fi
2013 elif [ "$CDDBLOCALMATCH" = "none" ] && [ -r "${CDDBLOCALDIR}/${CDDBDISCID}" ]; then
2014 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
2015 CDDBLOCALMATCH=single
2016 else
2017 CDDBLOCALMATCH=none
2018 fi
2019
2020 # If the user has selected to check a local CDDB repo, we proceed with it
2021 case $CDDBLOCALMATCH in
2022 multiple)
2023 echo "Processing multiple matching CDDB entries..." > "$ABCDETEMPDIR/cddblocalchoices"
2024 X=0
2025 echo "$CDDBLOCALRESULTS" | while read RESULT ; do
2026 X=$(expr $X + 1)
2027 # List out disc title/author and contents
2028 CDDBLOCALREAD="$ABCDETEMPDIR/cddblocalread.$X"
2029 cat "$RESULT" > "${CDDBLOCALREAD}"
2030 {
2031 echo -n "#$X: "
2032 do_cddbparse "${CDDBLOCALREAD}"
2033 echo ""
2034 ##FIXME## QUICK HACK !!!!
2035 if [ ! "$INTERACTIVE" = "y" ]; then break ; fi
2036 } >> "$ABCDETEMPDIR/cddblocalchoices"
2037 done
2038 if [ $(cat "$ABCDETEMPDIR/cddblocalchoices" | wc -l) -ge 24 ] && [ "$INTERACTIVE" = "y" ]; then
2039 page "$ABCDETEMPDIR/cddblocalchoices"
2040 else
2041 # It's all going to fit in one page, cat it
2042 cat "$ABCDETEMPDIR/cddblocalchoices" >&2
2043 fi
2044 CDDBLOCALCHOICES=$( echo "$CDDBLOCALRESULTS" | wc -l )
2045 # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
2046 CDDBLOCALCHOICENUM=-1
2047 if [ "$INTERACTIVE" = "y" ]; then
2048 while [ $CDDBLOCALCHOICENUM -lt 0 ] || [ $CDDBLOCALCHOICENUM -gt $CDDBLOCALCHOICES ]; do
2049 echo -n "Locally cached CDDB entries found. Which one would you like to use (0 for none)? [0-$CDDBLOCALCHOICES]: " >&2
2050 read CDDBLOCALCHOICE
2051 [ x"$CDDBLOCALCHOICE" = "x" ] && CDDBLOCALCHOICE="1"
2052 # FIXME # Introduce diff's
2053 if echo $CDDBLOCALCHOICE | egrep "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2054 diffentries cddblocalread "$CDDBLOCALCHOICES" "$CDDBLOCALCHOICE"
2055 elif echo $CDDBLOCALCHOICE | egrep "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2056 # Make sure we get a valid choice
2057 CDDBLOCALCHOICENUM=$(echo $CDDBLOCALCHOICE | xargs printf %d 2>/dev/null)
2058 if [ $CDDBLOCALCHOICENUM -lt 0 ] || [ $CDDBLOCALCHOICENUM -gt $CDDBLOCALCHOICES ]; then
2059 echo "Invalid selection. Please choose a number between 0 and $CDDBLOCALCHOICES." >&2
2060 fi
2061 fi
2062 done
2063 else
2064 ### FIXME ###
2065 #echo "Selected ..."
2066 CDDBLOCALRESP=y
2067 CDDBLOCALCHOICENUM=1
2068 fi
2069 if [ ! "$CDDBLOCALCHOICENUM" = "0" ]; then
2070 #echo "Using local copy of CDDB data"
2071 echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1"
2072 cat "$ABCDETEMPDIR/cddblocalread.$CDDBLOCALCHOICENUM" >> "$ABCDETEMPDIR/cddbread.1"
2073 echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
2074 echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
2075 do_cddbparse "$ABCDETEMPDIR/cddbread.1" > "$ABCDETEMPDIR/cddbchoices"
2076 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2077 CDDBLOCALSTATUS="found"
2078 else
2079 #echo "Not using local copy of CDDB data"
2080 CDDBLOCALSTATUS="notfound"
2081 fi
2082 ;;
2083 single)
2084 # List out disc title/author and contents
2085 do_cddbparse "${CDDBLOCALFILE}"
2086 #if [ "$CDROMREADERSYNTAX" = "flac" ] ; then
2087 # echo -n "Embedded cuesheet entry found, use it? [y/n] (y): " >&2
2088 #else
2089 echo -n "Locally cached CDDB entry found, use it? [y/n] (y): " >&2
2090 #fi
2091 if [ "$INTERACTIVE" = "y" ]; then
2092 read USELOCALRESP
2093 while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
2094 echo -n 'Invalid selection. Please answer "y" or "n": ' >&2
2095 read USELOCALRESP
2096 done
2097 [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
2098 else
2099 echo "y" >&2
2100 fi
2101 if [ "$USELOCALRESP" = "y" ]; then
2102 #echo "Using local copy of CDDB data"
2103 echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1"
2104 cat "${CDDBLOCALFILE}" >> "$ABCDETEMPDIR/cddbread.1"
2105 echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
2106 echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
2107 do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
2108 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2109 CDDBLOCALSTATUS="single"
2110 else
2111 #echo "Not using local copy of CDDB data"
2112 CDDBLOCALSTATUS="notfound"
2113 fi
2114 ;;
2115 none)
2116 CDDBLOCALSTATUS="notfound"
2117 ;;
2118 esac
2119 fi
2120 }
2121
2122 do_musicbrainzstat ()
2123 {
2124 :
2125 }
2126
2127 do_musicbrainz ()
2128 {
2129 :
2130 }
2131
2132 # do_cddbstat
2133 do_cddbstat ()
2134 {
2135 # Perform CDDB protocol version check if it hasn't already been done
2136 if checkstatus cddb-statcomplete; then :; else
2137 if [ "$CDDBAVAIL" = "n" ]; then
2138 ERRORCODE=no_query
2139 echo 503 > "$ABCDETEMPDIR/cddbstat"
2140 else
2141 rc=1
2142 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
2143 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
2144 while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
2145 vecho "Checking CDDB server status..."
2146 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
2147 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
2148 case "$RESPONSECODE" in
2149 210) # 210 OK, status information follows (until terminating `.')
2150 rc=0;
2151 ;;
2152 501|*) # 501 Illegal CDDB protocol level: <n>.
2153 CDDBPROTO=`expr $CDDBPROTO - 1`
2154 ;;
2155 esac
2156 done
2157 if test $rc -eq 1; then
2158 CDDBAVAIL="n"
2159 fi
2160 fi
2161 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
2162 fi
2163 }
2164
2165
2166 # do_cddbquery
2167 do_cddbquery ()
2168 {
2169 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
2170 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
2171
2172 # Perform CDDB query if it hasn't already been done
2173 if checkstatus cddb-querycomplete; then :; else
2174 if [ "$CDDBAVAIL" = "n" ]; then
2175 ERRORCODE=no_query
2176 echo 503 > "$ABCDETEMPDIR/cddbquery"
2177 # The default CDDBLOCALSTATUS is "notfound"
2178 # This part will be triggered if the user CDDB repo does not
2179 # contain the entry, or if we are not trying to use the repo.
2180 else
2181 vecho "Querying the CDDB server..."
2182 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
2183 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
2184 $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
2185 ERRORCODE=$?
2186 case $ERRORCODE in
2187 0) # success
2188 ;;
2189 12|13|14)
2190 # no match found in database,
2191 # wget/fetch error, or user requested not to use CDDB
2192 # Make up an error code (503) that abcde
2193 # will recognize in do_cddbread
2194 # and compensate by making a template
2195 echo 503 > "$ABCDETEMPDIR/cddbquery"
2196 ;;
2197 *) # strange and unknown error
2198 echo ERRORCODE=$ERRORCODE
2199 echo "abcde: $CDDBTOOL returned unknown error code"
2200 ;;
2201 esac
2202 fi
2203 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
2204 fi
2205 }
2206
2207 # do_cddbread
2208 do_cddbread ()
2209 {
2210 # If it's not to be used, generate a template.
2211 # Then, display it (or them) and let the user choose/edit it
2212 if checkstatus cddb-readcomplete; then :; else
2213 vecho "Obtaining CDDB results..."
2214 # If CDDB is to be used, interpret the query results and read all
2215 # the available entries.
2216 rm -f "$ABCDETEMPDIR/cddbchoices"
2217 CDDBCHOICES=1 # Overridden by multiple matches
2218 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
2219 case "$RESPONSECODE" in
2220 200)
2221 # One exact match, retrieve it
2222 # 200 [section] [discid] [artist] / [title]
2223 if checkstatus cddb-read-1-complete; then :; else
2224 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
2225 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
2226 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
2227 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2228 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2229 fi
2230 # List out disc title/author and contents
2231 echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
2232 for TRACK in $(f_seq_row 1 $TRACKS)
2233 do
2234 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2235 done
2236 echo >> "$ABCDETEMPDIR/cddbchoices"
2237 ;;
2238 202|403|409|503)
2239 # No match
2240 case "$RESPONSECODE" in
2241 202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
2242 403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
2243 503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
2244 esac
2245 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2246 # List out disc title/author and contents of template
2247 echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
2248 UNKNOWNDISK=y
2249 for TRACK in $(f_seq_row 1 $TRACKS)
2250 do
2251 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2252 done
2253 echo >> "$ABCDETEMPDIR/cddbchoices"
2254 echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
2255 echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
2256 ;;
2257 210|211)
2258 # Multiple exact, (possibly multiple) inexact matches
2259 IN=
2260 if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
2261 if [ "$(wc -l < "$ABCDETEMPDIR/cddbquery" | tr -d ' ')" -eq 3 ]; then
2262 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
2263 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
2264 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2265 else
2266 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
2267 fi
2268 vecho -n "Retrieving multiple matches... "
2269 grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
2270 read DISCINFO # eat top line
2271 while read DISCINFO
2272 do
2273 X=$(expr $X + 1)
2274 if checkstatus cddb-read-$X-complete; then :; else
2275 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
2276 echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
2277 fi
2278 # List out disc title/author and contents
2279 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
2280 for TRACK in $(f_seq_row 1 $TRACKS)
2281 do
2282 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2283 done
2284 echo >> "$ABCDETEMPDIR/cddbchoices"
2285 done )
2286 vecho "done."
2287 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2288 ;;
2289 999)
2290 # Using local copy.
2291 for TRACK in $(f_seq_row 1 $TRACKS)
2292 do
2293 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
2294 done
2295 echo >> "$ABCDETEMPDIR/cddbchoices"
2296 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
2297 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
2298 ;;
2299 esac
2300 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
2301 fi
2302 }
2303
2304 # do_cddbedit
2305 do_cddbedit ()
2306 {
2307 if checkstatus cddb-edit >/dev/null; then
2308 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2309 VARIOUSARTISTS="$(checkstatus variousartists)"
2310 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
2311 return 0
2312 fi
2313 if [ "$INTERACTIVE" = "y" ]; then
2314 # We should show the CDDB results both when we are not using the local CDDB repo
2315 # or when we are using it but we could not find a proper match
2316 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2317 # Display the $ABCDETEMPDIR/cddbchoices file created above
2318 # Pick a pager so that if the tracks overflow the screen the user can still view everything
2319 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2320 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2321 CHOICE=$(checkstatus cddb-choice)
2322 if [ -n "$CHOICE" ] ; then
2323 case $CDDBCHOICES in
2324 -1) if head -1 "$ABCDETEMPDIR/cddbquery" | grep "^$" > /dev/null 2>&1 ; then
2325 log error "CDDB query failed!"
2326 exit 1
2327 else
2328 cat "$ABCDETEMPDIR/cddbchoices"
2329 fi
2330 ;;
2331 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
2332 *)
2333 echo "Selected: #$CHOICE"
2334 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
2335 ;;
2336 esac
2337 else
2338 # The user has a choice to make, display the info in a pager if necessary
2339 if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
2340 page "$ABCDETEMPDIR/cddbchoices"
2341 else
2342 # It's all going to fit in one page, cat it
2343 cat "$ABCDETEMPDIR/cddbchoices" >&2
2344 fi
2345
2346 CDDBCHOICENUM=""
2347 # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
2348 CDCHOICENUM=-1
2349 # I'll take CDDB read #3 for $400, Alex
2350 while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
2351 echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
2352 read CDDBCHOICE
2353 [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
2354 if echo $CDDBCHOICE | egrep "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2355 if [ ! X"$DIFF" = "X" ]; then
2356 PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
2357 PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
2358 if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
2359 [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
2360 [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then
2361 echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBCHOICES" >&2
2362 else
2363 # We parse the 2 choices to diff, store them in temporary files and diff them.
2364 for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
2365 do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE"
2366 done
2367 echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/cddbread.diff"
2368 $DIFF $DIFFOPTS "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/cddbread.diff"
2369 if [ $(cat "$ABCDETEMPDIR/cddbread.diff" | wc -l) -ge 24 ]; then
2370 page "$ABCDETEMPDIR/cddbread.diff"
2371 else
2372 cat "$ABCDETEMPDIR/cddbread.diff" >&2
2373 fi
2374 fi
2375 else
2376 echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2
2377 fi
2378 elif echo $CDDBCHOICE | egrep "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2379 # Make sure we get a valid choice
2380 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
2381 if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then
2382 echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2
2383 fi
2384 fi
2385 done
2386 if [ "$CDCHOICENUM" = "0" ]; then
2387 vecho "Creating empty CDDB template..."
2388 UNKNOWNDISK=y
2389 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
2390 else
2391 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2392 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
2393 fi
2394 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2395 fi
2396 fi
2397 else
2398 # We need some code to show the selected option when local repository is selected and we have found a match
2399 vecho "Using cached CDDB match..." >&2
2400 # Display the $ABCDETEMPDIR/cddbchoices file created above
2401 # Pick a pager so that if the tracks overflow the screen the user can still view everything
2402 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2403 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2404 CHOICE=$(checkstatus cddb-choice)
2405 if [ "$USELOCALRESP" = "y" ]; then :; else
2406 if [ -n "$CHOICE" ] ; then
2407 case $CDDBCHOICES in
2408 0)
2409 UNKNOWNDISK=y
2410 echo "Selected template."
2411 ;;
2412 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
2413 *)
2414 echo "Selected: #$CHOICE"
2415 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
2416 ;;
2417 esac
2418 fi
2419 fi
2420 fi
2421 fi
2422 else
2423 # We're noninteractive - pick the first choice.
2424 # But in case we run a previous instance and selected a choice, use it.
2425 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2426 # Show the choice if we are not using the locally stored one
2427 # or when the local search failed to find a match.
2428 PREVIOUSCHOICE=$(checkstatus cddb-choice)
2429 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2430 #if [ "$PREVIOUSCHOICE" ]; then
2431 cat "$ABCDETEMPDIR/cddbchoices"
2432 #fi
2433 fi
2434 if [ ! -z "$PREVIOUSCHOICE" ] ; then
2435 CDCHOICENUM=$PREVIOUSCHOICE
2436 else
2437 CDCHOICENUM=1
2438 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2439 fi
2440 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2441 fi
2442 fi
2443
2444 # sanity check
2445 if checkstatus cddb-choice >/dev/null; then :; else
2446 echo "abcde: internal error: cddb-choice not recorded." >&2
2447 exit 1
2448 fi
2449 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2450 echo -n "Edit selected CDDB data? [y/n] (" >&2
2451 if [ "$INTERACTIVE" = "y" ]; then
2452 if [ "$UNKNOWNDISK" = "y" ]; then
2453 echo -n "y): " >&2
2454 read EDITCDDB
2455 [ "$EDITCDDB" != "n" ] && EDITCDDB=y
2456 else
2457 echo -n "n): " >&2
2458 read EDITCDDB
2459 fi
2460 else
2461 echo "n): n" >&2
2462 EDITCDDB=n
2463 fi
2464 if [ "$EDITCDDB" = "y" ]; then
2465 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
2466
2467 # Use the debian sensible-editor wrapper to pick the editor that the
2468 # user has requested via their $EDITOR environment variable
2469 if [ -x "/usr/bin/sensible-editor" ]; then
2470 /usr/bin/sensible-editor "$CDDBDATA"
2471 elif [ -n "$EDITOR" ]; then
2472 if [ -x $(which "${EDITOR%%\ *}") ]; then
2473 # That failed, try to load the preferred editor, starting
2474 # with their EDITOR variable
2475 eval $(echo "$EDITOR") \"$CDDBDATA\"
2476 fi
2477 # If that fails, check for a vi
2478 elif which vi >/dev/null 2>&1; then
2479 vi "$CDDBDATA"
2480 elif [ -x /usr/bin/vim ]; then
2481 /usr/bin/vim "$CDDBDATA"
2482 elif [ -x /usr/bin/vi ]; then
2483 /usr/bin/vi "$CDDBDATA"
2484 elif [ -x /bin/vi ]; then
2485 /bin/vi "$CDDBDATA"
2486 # nano should be on all (modern, i.e., sarge) debian systems
2487 elif which nano >/dev/null 2>&1 ; then
2488 nano "$CDDBDATA"
2489 elif [ -x /usr/bin/nano ]; then
2490 /usr/bin/nano "$CDDBDATA"
2491 # mg should be on all OpenBSD systems
2492 elif which mg >/dev/null 2>&1 ; then
2493 mg "$CDDBDATA"
2494 elif [ -x /usr/bin/mg ]; then
2495 /usr/bin/mg "$CDDBDATA"
2496 # bomb out
2497 else
2498 log warning "no editor available. Check your EDITOR environment variable."
2499 fi
2500 # delete editor backup file if it exists
2501 if [ -w "$CDDBDATA~" ]; then
2502 rm -f "$CDDBDATA~"
2503 fi
2504 fi
2505
2506 # Some heuristics first. Look at Disc Title, and if it starts with
2507 # "Various", then we'll assume Various Artists
2508 if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2- -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
2509 echo "Looks like a Multi-Artist CD" >&2
2510 VARIOUSARTISTS=y
2511 else
2512 echo -n "Is the CD multi-artist? [y/n] (n): " >&2
2513 if [ "$INTERACTIVE" = "y" ]; then
2514 read VARIOUSARTISTS
2515 else
2516 echo n >&2
2517 VARIOUSARTISTS=n
2518 fi
2519 fi
2520 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
2521 # Set a default
2522 DEFAULTSTYLE=1
2523 # Need NUMTRACKS before cddb-tool will return it:
2524 NUMTRACKS=$(egrep '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
2525 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2526 # More than 1/2 tracks contain a "/", so guess forward
2527 DEFAULTSTYLE=1
2528 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2529 # More than 1/2 contain a "-", so guess forward-dash
2530 DEFAULTSTYLE=2
2531 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2532 # More than 1/2 contain something in parens, so guess trailing-paren
2533 DEFAULTSTYLE=6
2534 fi
2535
2536 echo "1) Artist / Title" >&2
2537 echo "2) Artist - Title" >&2
2538 echo "3) Title / Artist" >&2
2539 echo "4) Title - Artist" >&2
2540 echo "5) Artist: Title" >&2
2541 echo "6) Title (Artist)" >&2
2542 echo "7) This is a single-artist CD" >&2
2543 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
2544 if [ "$INTERACTIVE" = "y" ]; then
2545 read VARIOUSARTISTSTYLE
2546 else
2547 echo $DEFAULTSTYLE >&2
2548 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2549 fi
2550 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2551 # If they press Enter, then the default style (0) was chosen
2552 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
2553 echo "Invalid selection. Please choose a number between 1 and 7."
2554 echo -n "Selection [1-7]: "
2555 read VARIOUSARTISTSTYLE
2556 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2557 done
2558 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
2559 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2560 fi
2561 vecho "Selected: $VARIOUSARTISTSTYLE"
2562 case "$VARIOUSARTISTSTYLE" in
2563 1) # Artist / Title
2564 VARIOUSARTISTSTYLE=forward
2565 ;;
2566 2) # Artist - Title
2567 VARIOUSARTISTSTYLE=forward-dash
2568 ;;
2569 3) # Title / Artist
2570 VARIOUSARTISTSTYLE=reverse
2571 ;;
2572 4) # Title - Artist
2573 VARIOUSARTISTSTYLE=reverse-dash
2574 ;;
2575 5) # Artist: Title
2576 VARIOUSARTISTSTYLE=colon
2577 ;;
2578 6) # Title (Artist)
2579 VARIOUSARTISTSTYLE=trailing-paren
2580 ;;
2581 7) # Single Artist
2582 VARIOUSARTISTS=n
2583 ;;
2584 esac
2585 fi
2586
2587 echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
2588 echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
2589
2590 if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
2591 if [ "$CDDBDATAMD5SUM" != "" ] && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
2592 # This works but does not have the necessary error checking
2593 # yet. If you are familiar with the CDDB spec
2594 # (see http://www.freedb.org/src/latest/DBFORMAT)
2595 # and can create an error-free entry on your own, then put
2596 # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
2597 # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
2598 # your abcde.conf to change the email address submissions are
2599 # sent to.
2600
2601 # submit the modified file, if they want
2602 if [ "$NOSUBMIT" != "y" ]; then
2603 echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
2604 read YESNO
2605 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
2606 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
2607 do
2608 echo -n 'Invalid selection. Please answer "y" or "n": '
2609 read YESNO
2610 done
2611 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
2612 echo -n "Sending..."
2613 $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
2614 echo "done."
2615 fi
2616 fi
2617 fi
2618 fi
2619 ### FIXME ###
2620 # User CDDBLOCALPOLICY to find out if we store the file or not...
2621 # Cache edited CDDB entry in the user's cddb dir
2622 if [ "$CDDBCOPYLOCAL" = "y" ]; then
2623 # Make sure the cache directory exists
2624 mkdir -p $CDDBLOCALDIR
2625 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
2626 fi
2627
2628 echo "cddb-edit" >> "$ABCDETEMPDIR/status"
2629 }
2630
2631 # do_cdread [tracknumber]
2632 # do_cdread onetrack [firsttrack] [lasttrack]
2633 #
2634 do_cdread ()
2635 {
2636 # The commands here don't go through run_command because they're never supposed to be silenced
2637 # return codes need to be doublechecked anyway, however
2638 if [ "$1" = "onetrack" ]; then
2639 # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
2640 # FIXME # Until then, we grab the whole CD in one track, no matter what
2641 # the user said
2642 # We need the first and last track for cdda2wav
2643 FIRSTTRACK=$2
2644 LASTTRACK=$(expr $3 + 0)
2645 UTRACKNUM=$FIRSTTRACK
2646 case "$CDROMREADERSYNTAX" in
2647 flac) READTRACKNUMS="$FIRSTTRACK.1-$(($LASTTRACK + 1)).0" ;;
2648 cdparanoia)
2649 #XX FIXME XX
2650 # Add a variable to check if tracks are provided in command line and if not, use "0-" to rip the tracks
2651 READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
2652 cdda2wav) READTRACKNUMS="$FIRSTTRACK+$LASTTRACK" ;;
2653 *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
2654 exit 1 ;;
2655 esac
2656 else
2657 UTRACKNUM=$1
2658 fi
2659 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2660 if [ "$USEPIPES" = "y" ]; then
2661 TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
2662 FILEARG="$( eval echo "\$$TEMPARG" )"
2663 REDIR=""
2664 PIPE_MESSAGE="and encoding "
2665 else
2666 WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
2667 case "$CDROMREADERSYNTAX" in
2668 ## FIXME ## Find the cases for dagrab and flac, to avoid exceptions
2669 flac)
2670 FILEARG="--output-name=$WAVDATA"
2671 ;;
2672 dagrab)
2673 FILEARG="-f $WAVDATA"
2674 ;;
2675 *)
2676 FILEARG="$WAVDATA"
2677 ;;
2678 esac
2679 REDIR=">&2"
2680 fi
2681 if [ "$1" = "onetrack" ]; then
2682 echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
2683 else
2684 if [ -r "$CDDBDATA" ]; then
2685 getcddbinfo TRACKNAME
2686 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
2687 else
2688 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
2689 fi
2690 fi
2691 case "$CDROMREADERSYNTAX" in
2692 ### FIXME ### use an exception for flac, since it uses -o
2693 ### FIXME ### Shall we just use -o $FILEARG ??
2694 flac)
2695 # Avoid problems wit math expressions by unpadding the given UTRACKNUM
2696 STRIPTRACKNUM=$(expr $UTRACKNUM + 0)
2697 nice $READNICE $FLAC -d -f --cue=${READTRACKNUMS:-$STRIPTRACKNUM.1-$(($STRIPTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;;
2698 cdparanoia)
2699 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;
2700 cdda2wav)
2701 if [ "$OSFLAVOUR" = "OSX" ] ; then
2702 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
2703 disktool -u ${CDROM#/dev/} 0
2704 # Also, in OSX the cdrom device for cdda2wav changes...
2705 CDDA2WAVCDROM="IODVDServices"
2706 elif [ "$OSFLAVOUR" = "FBSD" ] ; then
2707 CDDA2WAVCDROM="$CDROMID"
2708 else
2709 if [ "$CDROMID" = "" ]; then
2710 CDDA2WAVCDROM="$CDROM"
2711 else
2712 CDDA2WAVCDROM="$CDROMID"
2713 fi
2714 fi
2715 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR
2716 ;;
2717 ## FIXME ## We have an exception for dagrab, since it uses -f
2718 ## FIXME ## Shall we just use -f $FILEARG ??
2719 dagrab) nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG" $REDIR
2720 ;;
2721 cddafs)
2722 # Find the track's mounted path
2723 REALTRACKNUM=$(expr $UTRACKNUM + 0)
2724 FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
2725 FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
2726 # If the file exists, copy it
2727 if [ -e "$FILEPATH" ] ; then
2728 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" $REDIR
2729 else
2730 false
2731 fi ;;
2732 debug) nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG" $REDIR
2733 ;;
2734 esac
2735 RETURN=$?
2736 # If we get some error or we get some missing wav
2737 # (as long as we dont use pipes)
2738 if [ "$RETURN" != "0" -o \( ! -s "$WAVDATA" -a X"$USEPIPES" != "Xy" \) ]; then
2739 # Thank goodness errors is only machine-parseable up to the
2740 # first colon, otherwise this woulda sucked
2741 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
2742 RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
2743 fi
2744 if [ "$USEPIPES" = "y" ]; then
2745 echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2746 else
2747 echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2748 fi
2749 return $RETURN
2750 else
2751 if [ "$USEPIPES" = "y" ]; then
2752 echo readencodetrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2753 else
2754 echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2755 fi
2756 if [ "$1" = "onetrack" ]; then
2757 echo onetrack >> "$ABCDETEMPDIR/status"
2758 fi
2759 fi
2760 }
2761
2762 # do_cdspeed
2763 # No values accepted, only uses env variables
2764 do_cdspeed ()
2765 {
2766 if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
2767 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
2768 else
2769 echo "abcde: unable to set the device speed" >&2
2770 fi
2771 }
2772
2773 # vecho [message]
2774 #
2775 # vecho outputs a message if EXTRAVERBOSE is selected
2776 vecho ()
2777 {
2778 if [ x"$EXTRAVERBOSE" != "x" ]; then
2779 case $1 in
2780 warning) shift ; log warning "$@" ;;
2781 *) echo "$@" ;;
2782 esac
2783 fi
2784 }
2785
2786 # decho [message]
2787 #
2788 # decho outputs a debug message if DEBUG is selected
2789 decho ()
2790 {
2791 if [ x"$DEBUG" != "x" ]; then
2792 if echo $1 | grep "^\[" > /dev/null 2>&1 ; then
2793 DEBUGECHO=$(echo "$@" | tr -d '[]')
2794 echo "[DEBUG] $DEBUGECHO: `eval echo \\$${DEBUGECHO}`"
2795 else
2796 echo "[DEBUG] $1"
2797 fi
2798 fi
2799 }
2800
2801 # User-redefinable functions
2802 # Custom filename munging:
2803 mungefilename ()
2804 {
2805 #echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
2806 echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
2807 }
2808
2809 # Custom genre munging:
2810 mungegenre ()
2811 {
2812 echo $CDGENRE | tr "[:upper:]" "[:lower:]"
2813 }
2814
2815 # pre_read
2816 # Empty pre_read function, to be defined in the configuration file.
2817 pre_read ()
2818 {
2819 :
2820 }
2821
2822 # post_read
2823 # Empty post_read function, to be defined in the configuration file.
2824 post_read ()
2825 {
2826 :
2827 }
2828
2829 ###############################################################################
2830 # End of functions
2831 #
2832 # Start of execution
2833 ###############################################################################
2834
2835 # Builtin defaults
2836
2837 # CDDB
2838 # Defaults to FreeDB, but a python musicbrainz can be used
2839 CDDBMETHOD=cddb
2840 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
2841 CDDBSUBMIT=freedb-submit@freedb.org
2842 CDDBPROTO=6
2843 HELLOINFO="$(whoami)@$(hostname)"
2844 CDDBCOPYLOCAL="n"
2845 CDDBLOCALPOLICY="always"
2846 CDDBLOCALRECURSIVE="y"
2847 CDDBLOCALDIR="$HOME/.cddb"
2848 CDDBUSELOCAL="n"
2849
2850 # List of fields we parse and show during the CDDB parsing...
2851 SHOWCDDBFIELDS="year,genre"
2852
2853 INTERACTIVE=y
2854 #CDROMREADERSYNTAX=cdparanoia
2855 ENCODERSYNTAX=default
2856
2857 MP3ENCODERSYNTAX=default
2858 OGGENCODERSYNTAX=default
2859 FLACENCODERSYNTAX=default
2860 SPEEXENCODERSYNTAX=default
2861 MPPENCODERSYNTAX=default
2862 AACENCODERSYNTAX=default
2863 NORMALIZERSYNTAX=default
2864 CUEREADERSYNTAX=default
2865
2866 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
2867 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
2868 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
2869 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
2870 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
2871 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
2872 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2873 PLAYLISTDATAPREFIX=''
2874 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2875 VAPLAYLISTDATAPREFIX=''
2876 DOSPLAYLIST=n
2877 COMMENT=''
2878 ID3TAGV=2
2879 ENCNICE=10
2880 READNICE=10
2881 DISTMP3NICE=10
2882 VARIOUSARTISTS=n
2883 VARIOUSARTISTSTYLE=forward
2884 KEEPWAVS=n
2885 PADTRACKS=n
2886 NOGAP=n
2887 BATCHNORM=n
2888 NOCDDBQUERY=n
2889
2890 # If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
2891 # i.e. CDROMID="1,0,0"
2892 CDROMID=""
2893 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
2894 # If we are using the ide-scsi emulation layer, we need to define a "g"
2895 CDPARANOIACDROMBUS="d"
2896
2897 # program paths - defaults to checking your $PATH
2898 # mp3
2899 LAME=lame
2900 TOOLAME=toolame
2901 GOGO=gogo
2902 BLADEENC=bladeenc
2903 L3ENC=l3enc
2904 XINGMP3ENC=xingmp3enc
2905 MP3ENC=mp3enc
2906 # ogg
2907 VORBIZE=vorbize
2908 OGGENC=oggenc
2909 # flac
2910 FLAC=flac
2911 # speex
2912 SPEEXENC=speexenc
2913 # mpp (Musepack)
2914 MPPENC=mppenc
2915 # m4a
2916 AACENC=faac
2917
2918 ID3=id3
2919 ID3V2=id3v2
2920 EYED3=eyeD3
2921 CDPARANOIA=cdparanoia
2922 CDDA2WAV=cdda2wav
2923 DAGRAB=dagrab
2924 CDDAFS=cp
2925 CDDISCID=cd-discid
2926 CDDBTOOL=cddb-tool
2927 MUSICBRAINZ=musicbrainz-get-tracks
2928 EJECT=eject
2929 MD5SUM=md5sum
2930 DISTMP3=distmp3
2931 VORBISCOMMENT=vorbiscomment
2932 METAFLAC=metaflac
2933 NORMALIZE=normalize-audio
2934 CDSPEED=eject
2935 VORBISGAIN=vorbisgain
2936 MP3GAIN=mp3gain
2937 MPPGAIN=replaygain
2938 MKCUE=mkcue
2939 MKTOC=cdrdao
2940 DIFF=diff
2941 CUE2DISCID=builtin
2942
2943 # Options for programs called from abcde
2944 # mp3
2945 LAMEOPTS=
2946 TOOLAMEOPTS=
2947 GOGOOPTS=
2948 BLADEENCOPTS=
2949 L3ENCOPTS=
2950 XINGMP3ENCOPTS=
2951 MP3ENCOPTS=
2952 # ogg
2953 VORBIZEOPTS=
2954 OGGENCOPTS=
2955 # flac
2956 FLACOPTS=
2957 # speex
2958 SPEEXENCOPTS=
2959 # mpc
2960 MPPENCOPTS=
2961 # m4a
2962 AACENCOPTS=
2963
2964 ID3OPTS=
2965 ID3V2OPTS=
2966 CDPARANOIAOPTS=
2967 CDDA2WAVOPTS=
2968 DAGRABOPTS=
2969 CDDAFSOPTS="-f"
2970 CDDBTOOLOPTS=
2971 EJECTOPTS=
2972 DISTMP3OPTS=
2973 NORMALIZEOPTS=
2974 CDSPEEDOPTS="-x"
2975 CDSPEEDVALUE=
2976 MKCUEOPTS=
2977 MKTOCOPTS=""
2978 VORBISCOMMENTOPTS="-R"
2979 METAFLACOPTS="--no-utf8-convert"
2980 DIFFOPTS=
2981
2982 # Default to one process if -j isn't specified
2983 MAXPROCS=1
2984
2985 # List of actions to perform - by default, run to completion
2986 ACTIONS=cddb,read,encode,tag,move,clean
2987
2988 # This option is basicaly for Debian package dependencies:
2989 # List of prefered outputs - by default, run with whatever we have in the path
2990 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:toolame,mp3:lame,mp3:bladeenc,spx:speex,m4a:faac
2991
2992 # List of prefered cdromreaders - by default, run whichever we have in the path
2993 DEFAULT_CDROMREADERS="cdparanoia cdda2wav"
2994
2995 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for
2996 # Linux/OpenBSD. ftp is user for NetBSD.
2997 # Let's use these checkings to determine the OS flavour, which will be used
2998 # later
2999 if [ X$(uname) = "XFreeBSD" ] ; then
3000 HTTPGET=fetch
3001 MD5SUM=md5
3002 NEEDCDROMID=y
3003 OSFLAVOUR=FBSD
3004 elif [ X$(uname) = "XDarwin" ] ; then
3005 HTTPGET=curl
3006 OSFLAVOUR=OSX
3007 # We should have disktool in OSX, but let's be sure...
3008 NEEDDISKTOOL=y
3009 CDROMREADERSYNTAX=cddafs
3010 elif [ X$(uname) = "XOpenBSD" ] ; then
3011 HTTPGET=wget
3012 MD5SUM=md5
3013 OSFLAVOUR=OBSD
3014 elif [ X$(uname) = "XNetBSD" ] ; then
3015 HTTPGET=ftp
3016 MD5SUM=md5
3017 OSFLAVOUR=NBSD
3018 elif [ X$(uname) = "SunOS" ] ; then
3019 HTTPGET=""
3020 MD5SUM=md5
3021 OSFLAVOUR=SunOS
3022 else
3023 HTTPGET=wget
3024 fi
3025
3026 # If CDDBAVAIL is set to n, no CDDB read is done
3027 # If USEID3 is set to n, no ID3 tagging is done
3028 CDDBAVAIL=y
3029 USEID3=y
3030 USEID3V2=y
3031
3032 if [ -z "$OUTPUTDIR" ]; then
3033 OUTPUTDIR=$(pwd)
3034 fi
3035
3036 if [ -z "$WAVOUTPUTDIR" ]; then
3037 WAVOUTPUTDIR="$OUTPUTDIR"
3038 fi
3039
3040 # Load system defaults
3041 if [ -r /etc/abcde.conf ]; then
3042 . /etc/abcde.conf
3043 fi
3044 # Load user preference defaults
3045 if [ -r $HOME/.abcde.conf ]; then
3046 . $HOME/.abcde.conf
3047 fi
3048
3049 # By this time, we need some HTTPGETOPTS already defined.
3050 # If the user has defined a non-default HTTPGET method, we should not be empty.
3051
3052 if [ "$HTTPGETOPTS" = "" ] ; then
3053 case $HTTPGET in
3054 wget) HTTPGETOPTS="-q -O -";;
3055 curl) HTTPGETOPTS="-f -s";;
3056 fetch)HTTPGETOPTS="-q -o -";;
3057 ftp) HTTPGETOPTS="-a -V -o - ";;
3058 *) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
3059 esac
3060 fi
3061
3062 # If the CDROM has not been set yet, find a suitable one.
3063 # If this is a devfs system, default to /dev/cdroms/cdrom0
3064 # instead of /dev/cdrom
3065 if [ "$CDROM" = "" ] ; then
3066 if [ -e /dev/cdroms/cdrom0 ]; then
3067 CDROM=/dev/cdroms/cdrom0
3068 elif [ -e /dev/cdrom ]; then
3069 CDROM=/dev/cdrom
3070 elif [ -e /dev/cd0c ]; then
3071 CDROM=/dev/cd0c
3072 elif [ -e /dev/acd0c ]; then
3073 CDROM=/dev/acd0c
3074 elif [ -e /dev/disk1 ]; then
3075 CDROM=/dev/disk1
3076 fi
3077 fi
3078
3079 # Parse command line options
3080 #while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPr:Rs:S:t:T:vVxw:W: opt ; do
3081 while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPr:s:S:t:T:uvVxX:w:W:z opt ; do
3082 case "$opt" in
3083 1) ONETRACK=y ;;
3084 a) ACTIONS="$OPTARG" ;;
3085 A) EXPACTIONS="$OPTARG" ;;
3086 b) BATCHNORM=y ;;
3087 B) NOBATCHREPLAYGAIN=y ;;
3088 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
3089 C) DISCID="$( echo ${OPTARG#abcde.} | tr -d /)" ;;
3090 d) CDROM="$OPTARG" ;;
3091 D) set -x ;;
3092 h) usage; exit ;;
3093 e) ERASEENCODEDSTATUS=y ;;
3094 E) ENCODING="$OPTARG" ;;
3095 f) FORCE=y ;;
3096 g) NOGAP=y ;;
3097 i) INLINETAG=y ;;
3098 j) MAXPROCS="$OPTARG" ;;
3099 k) KEEPWAVS=y ;;
3100 l) LOWDISK=y ;;
3101 L) CDDBUSELOCAL=y ;;
3102 n) CDDBAVAIL=n ;;
3103 N) INTERACTIVE=n ;;
3104 m) DOSPLAYLIST=y ;;
3105 M) MAKECUEFILE=y ;;
3106 o) OUTPUTTYPE="$OPTARG" ;;
3107 p) PADTRACKS=y ;;
3108 P) USEPIPES=y ;;
3109 r) REMOTEHOSTS="$OPTARG" ;;
3110 R) CDDBLOCALRECURSIVE=y ;;
3111 s) SHOWCDDBFIELDS="$OPTARG" ;;
3112 S) CDSPEEDVALUE="$OPTARG" ;;
3113 t) STARTTRACKNUMBER="$OPTARG" ;;
3114 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
3115 u) CDDBPROTO=6 ;;
3116 U) CDDBPROTO=5 ;;
3117 v)
3118 echo "This is abcde v$VERSION."
3119 echo "Usage: abcde [options] [tracks]"
3120 echo "abcde -h for extra help"
3121 exit
3122 ;;
3123 V) EXTRAVERBOSE="y" ;;
3124 x) EJECTCD="y" ;;
3125 X) CUE2DISCID="$OPTARG" ;;
3126 w) COMMENT="$OPTARG" ;;
3127 W) if echo $OPTARG | grep "[[:digit:]]" > /dev/null 2>&1 ; then
3128 STARTTRACKNUMBER="${OPTARG}01" ; STARTTRACKNUMBERTAG="y" ; COMMENT="CD${OPTARG}"
3129 else
3130 log error "argument of -W must be integer"
3131 exit 1
3132 fi
3133 ;;
3134 z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
3135 ?) usage; exit ;;
3136 esac
3137 done
3138
3139 shift $(($OPTIND - 1))
3140
3141 # Here it comes the worse part of the whole thing. From here until we start
3142 # ripping, we have a mixture of sanity checks, verifications, default settigs
3143 # and other crazy stuff that interdepends, but hey, someone has to do it.
3144
3145 # If NOCDDBQUERY is set, don't query the CDDB server.
3146 if [ "$NOCDDBQUERY" = "y" ]; then
3147 CDDBAVAIL="n"
3148 fi
3149
3150 # If the user specified a flac file, then switch to special flac mode
3151 if echo "$CDROM" | grep -i '.flac$' > /dev/null 2>&1 ; then
3152 if [ ! -f "$CDROM" ]; then
3153 log error "the defined file for FLAC ripping cannot be found" >&2
3154 exit 1
3155 fi
3156 vecho warning "switching to flac CDROMREADERSYNTAX..."
3157 CDROMREADERSYNTAX=flac
3158 # We have a builtin version of cue2discid...
3159 case "$CUE2DISCID" in
3160 builtin);;
3161 *) NEEDCUE2DISCID=y;;
3162 esac
3163 NEEDMETAFLAC=y
3164 EJECTCD=n
3165 fi
3166
3167 # If the user provided a DISCID, disable eject
3168 if [ -n "$DISCID" ] || [ "$CDROMREADERSYNTAX" = "flac" ]; then EJECTCD=n ; fi
3169
3170 # Check the available cd rippers in the system, from the ones we know.
3171 if [ "$CDROMREADERSYNTAX" = "" ]; then
3172 for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
3173 if new_checkexec $DEFAULT_CDROMREADER; then
3174 CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
3175 break
3176 fi
3177 done
3178 if [ "$CDROMREADERSYNTAX" = "" ]; then
3179 log error "no cdreader found in your PATH"
3180 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3181 exit 1
3182 fi
3183 fi
3184
3185 # Decide if we can continue.
3186 if [ "$ONETRACK" = "y" ]; then
3187 # FIXME # remove check as soon as we find out about the other readers
3188 case "$CDROMREADERSYNTAX" in
3189 flac) ;;
3190 cdparanoia) ;;
3191 cdda2wav) ;;
3192 *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
3193 exit 1 ;;
3194 esac
3195 if [ "$BATCHNORM" = "y" ]; then
3196 log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
3197 BATCHNORM=n
3198 fi
3199 if [ "$NOGAP" = "y" ]; then
3200 log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
3201 NOGAP=n
3202 fi
3203 # It does not matter how many tracks we want. In ONETRACK mode we grab them all
3204 # FIXME # allow ranges of tracks to be selected for onetrack ripping
3205 if [ $# -gt 0 ]; then
3206 log warning "ONETRACK mode selected, grabbing all tracks..."
3207 fi
3208 else
3209 while [ $# -gt 0 ]; do
3210 # Range parsing code courtesy of Vincent Ho
3211 RSTART=$(echo $1 | cut -f1 -d-)
3212 REND=$(echo $1 | cut -f2 -d-)
3213 if [ "$RSTART" = "$REND" ]; then
3214 NEWTRACKS="$RSTART"
3215 else
3216 NEWTRACKS=$(f_seq_line $RSTART $REND)
3217 fi
3218 TRACKQUEUE=$(echo "$TRACKQUEUE" "$NEWTRACKS")
3219 shift
3220 done
3221 fi
3222
3223 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
3224 # List of experimental actions: retag,transcode
3225
3226 # Determine what actions are to be done from $ACTIONS and set the
3227 # following environment variables for them:
3228 DOCDDB=n
3229 DOREAD=n
3230 DONORMALIZE=n
3231 DOPREPROCESS=n
3232 DOENCODE=n
3233 DOPOSTPROCESS=n
3234 DOTAG=n
3235 DOMOVE=n
3236 DOREPLAYGAIN=n
3237 DOPLAYLIST=n
3238 DOCLEAN=n
3239 DOCUE=n
3240
3241 for ACTION in $(echo $ACTIONS | tr , \ )
3242 do
3243 case $ACTION in
3244 default) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOCLEAN=y;;
3245 cue) DOCUE=y;;
3246 cddb) DOCDDB=y;;
3247 read) DOREAD=y;;
3248 normalize) DONORMALIZE=y; DOREAD=y;;
3249 # preprocess) DOPREPROCESS=y; DOREAD=y;;
3250 encode) DOENCODE=y; DOREAD=y;;
3251 # postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
3252 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3253 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3254 replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
3255 playlist) DOCDDB=y; DOPLAYLIST=y;;
3256 clean) DOCLEAN=y;;
3257 esac
3258 done
3259
3260 if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
3261 # FIXME # should we abort on error or just inform the user?
3262 log warning "selected both normalize and replaygain actions"
3263 fi
3264
3265 for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
3266 case $SHOWCDDBFIELD in
3267 y*|Y*) SHOWCDDBYEAR="y";;
3268 g*|G*) SHOWCDDBGENRE="y";;
3269 *) ;;
3270 esac
3271 done
3272
3273 # At this point a CDROM has to be defined, so we check it exists.
3274 if [ X"$CDROM" != "X" ] ; then
3275 if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
3276 if [ "$OSFLAVOUR" = "FBSD" ]; then
3277 if echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then :; else
3278 log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
3279 log error "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
3280 exit 1
3281 fi
3282 fi
3283 elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
3284 log error "CDROM device cannot be found."
3285 exit 1
3286 fi
3287 # avoid processing if we are not going to hit the CDROM.
3288 elif [ X"$DOREAD" = "Xy" ]; then
3289 log error "CDROM has not been defined or cannot be found"
3290 exit 1
3291 fi
3292
3293 # USEPIPES pre-tests, before we get into more serious stuff
3294 # Not compatible with:
3295 # - multiple outputs
3296 # - normalize
3297 # - lowdisk algorithm
3298 # - anything else?
3299 if [ X"$USEPIPES" = "Xy" ]; then
3300 if [ $(echo "$OUTPUTTYPE" | tr , \ | wc -w ) -gt 1 ]; then
3301 log error "Unix pipes not compatible with multiple outputs"
3302 exit 1
3303 fi
3304 if [ X"$DONORMALIZE" = "Xy" ]; then
3305 log error "Unix pipes not compatible with normalizer"
3306 # FIXME # Do we need to exit or shall we just disable the mode?
3307 exit 1
3308 fi
3309 if [ X"$BATCHNORM" = "Xy" ]; then
3310 log error "Unix pipes not compatible with BATCHNORM encoding"
3311 exit 1
3312 fi
3313 if [ X"$NOGAP" = "Xy" ]; then
3314 log error "Unix pipes not compatible with NOGAP encoding"
3315 exit 1
3316 fi
3317 if [ X"$DOENCODE" = "Xn" ]; then
3318 vecho warning "Disabling Unix pipes since we are not encoding!"
3319 USEPIPES=n
3320 fi
3321 if [ X"$LOWDISK" = "Xy" ]; then
3322 log error "Unix pipes not compatible with lowdisk algorithm"
3323 exit 1
3324 fi
3325 fi
3326
3327 # LOWDISK pre-tests, before we get into more problematic stuff
3328 # Not compatible with anything that needs all the files in the hard disc:
3329 # - BATCHNORM
3330 # - NOGAP lame mode
3331 if [ X"$LOWDISK" = "Xy" ]; then
3332 if [ X"$BATCHNORM" = "Xy" ]; then
3333 log error "Unix pipes not compatible with BATCHNORM encoding"
3334 exit 1
3335 fi
3336 if [ X"$NOGAP" = "Xy" ]; then
3337 log error "Unix pipes not compatible with NOGAP encoding"
3338 exit 1
3339 fi
3340 fi
3341
3342 # BATCHNORM pre-tests, before we get into serious problems
3343 # Not compatible with
3344 if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
3345 vecho warning "Disabling BATCHNORM since we are not normalizing!"
3346 BATCHNORM=n
3347 fi
3348
3349 # Check the encoding format from the ones available in the system, if nothing has been configured in the system.
3350 if [ X"$OUTPUTTYPE" = "X" ]; then
3351 for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
3352 DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
3353 DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
3354 if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
3355 OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
3356 vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
3357 break
3358 fi
3359 done
3360 if [ X"$OUTPUTTYPE" = "X" ]; then
3361 log error "no encoder found in the PATH"
3362 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3363 exit 1
3364 fi
3365 fi
3366
3367 # Decide which CDROM reader we're gonna use
3368 case "$CDROMREADERSYNTAX" in
3369 cdparanoia|debug)
3370 CDROMREADER="$CDPARANOIA"
3371 CDROMREADEROPTS="$CDPARANOIAOPTS"
3372 ;;
3373 cdda2wav)
3374 CDROMREADER="$CDDA2WAV"
3375 CDROMREADEROPTS="$CDDA2WAVOPTS"
3376 ;;
3377 dagrab)
3378 CDROMREADER="$DAGRAB"
3379 CDROMREADEROPTS="$DAGRABOPTS"
3380 ;;
3381 cddafs)
3382 CDROMREADER="$CDDAFS"
3383 CDROMREADEROPTS="$CDDAFSOPTS"
3384 ;;
3385 flac)
3386 CDROMREADER="$FLAC"
3387 CDROMREADEROPTS="$FLACOPTS"
3388 ;;
3389 esac
3390
3391 # There's only one normalize...
3392 case "$NORMALIZERSYNTAX" in
3393 default|normalize)
3394 NORMALIZER="$NORMALIZE"
3395 NORMALIZEROPTS="$NORMALIZEOPTS"
3396 ;;
3397 esac
3398
3399 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
3400 if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
3401 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr \ \|| tr , \ | tr \| \ )"; do
3402 case "$OUTPUT" in
3403 vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3404 mp3:*) MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3405 flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3406 spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3407 mpc:*) MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3408 m4a:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3409 esac
3410 done
3411 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
3412 TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
3413 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
3414 done
3415 OUTPUTTYPE="$TEMPOUTPUTTYPE"
3416 fi
3417
3418 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
3419 # for flacs and speexenc for speex and mppenc for mpps and faac for m4as
3420
3421 # Getting ready for multiple output changes
3422 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
3423 do
3424 case $OUTPUT in
3425 vorbis|ogg)
3426 [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
3427 [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
3428 [ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
3429 OGGOUTPUTCONTAINER=ogg
3430 ;;
3431 mp3)
3432 [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
3433 [ "$DOTAG" = "y" ] && NEEDTAGGER=y
3434 [ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
3435 ;;
3436 flac)
3437 [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
3438 [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
3439 [ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
3440 [ "$ONETRACK" = "y" ] && [ "$MAKECUEFILE" = "y" ] && NEEDMETAFLAC=y
3441 ;;
3442 spx)
3443 [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
3444 # [ "$DOREPLAYGAIN" = "y" ] &&
3445 ;;
3446 mpc)
3447 [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc
3448 [ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y
3449 ;;
3450 m4a)
3451 [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
3452 ;;
3453 wav)
3454 if [ "$KEEPWAVS" = "y" ]; then
3455 vecho "Setting the KEEPWAVS option, since the resulting wav files were requested..."
3456 fi
3457 KEEPWAVS=move
3458 ;;
3459 *) log error "Invalid OUTPUTTYPE defined"
3460 exit 1
3461 ;;
3462 esac
3463 done
3464
3465 # decide which encoder
3466 case "$MP3ENCODERSYNTAX" in
3467 lame)
3468 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
3469 MP3ENCODER="$LAME"
3470 ;;
3471 toolame)
3472 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$TOOLAMEOPTS}"
3473 MP3ENCODER="$TOOLAME"
3474 ;;
3475 gogo)
3476 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
3477 MP3ENCODER="$GOGO"
3478 ;;
3479 bladeenc)
3480 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
3481 MP3ENCODER="$BLADEENC"
3482 ;;
3483 l3enc)
3484 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
3485 MP3ENCODER="$L3ENC"
3486 ;;
3487 xingmp3enc)
3488 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
3489 MP3ENCODER="$XINGMP3ENC"
3490 ;;
3491 mp3enc)
3492 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
3493 MP3ENCODER="$MP3ENC"
3494 ;;
3495 esac
3496 case "$OGGENCODERSYNTAX" in
3497 vorbize)
3498 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
3499 OGGENCODER="$VORBIZE"
3500 ;;
3501 oggenc)
3502 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
3503 OGGENCODER="$OGGENC"
3504 ;;
3505 esac
3506 case "$FLACENCODERSYNTAX" in
3507 flac)
3508 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
3509 FLACENCODER="$FLAC"
3510 # FLAC streams can be encapsulated on a Ogg transport layer
3511 if echo "$FLACENCODEROPTS" | egrep -- "(^| )--ogg($| )" > /dev/null 2>&1 ;then
3512 log error "FLAC on an Ogg container is not yet supported"
3513 log error "due to problem with adding comments to such files"
3514 exit 1
3515 FLACOUTPUTCONTAINER=ogg
3516 else
3517 FLACOUTPUTCONTAINER=flac
3518 fi
3519 ;;
3520 esac
3521 case "$SPEEXENCODERSYNTAX" in
3522 speexenc)
3523 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
3524 SPEEXENCODER="$SPEEXENC"
3525 ;;
3526 esac
3527 case "$MPPENCODERSYNTAX" in
3528 mppenc)
3529 MPPENCODEROPTS="${MPPENCODEROPTSCLI:-$MPPENCOPTS}"
3530 MPPENCODER="$MPPENC"
3531 ;;
3532 esac
3533 case "$AACENCODERSYNTAX" in
3534 faac)
3535 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
3536 AACENCODER="$AACENC"
3537 ;;
3538 esac
3539
3540 # and which tagger
3541 if [ "$ID3TAGV" = "1" ]; then
3542 TAGGER="$ID3"
3543 TAGGEROPTS="$ID3OPTS"
3544 else
3545 TAGGER="$ID3V2"
3546 TAGGEROPTS="$ID3V2OPTS"
3547 fi
3548
3549 # Specific for NOGAP is the use of lame. Another encoder fails...
3550 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
3551 log warning "the NOGAP option is specific of lame. Deactivating..."
3552 NOGAP=n
3553 fi
3554
3555 # Options for mkcue
3556 case "$CUEREADERSYNTAX" in
3557 default|mkcue)
3558 CUEREADEROPTS="${CDROM}"
3559 CUEREADER="$MKCUE"
3560 ;;
3561 esac
3562
3563 # which information retrieval tool are we using?
3564 case "$CDDBTOOL" in
3565 cddb) ;;
3566 musicbrainz) ;;
3567 esac
3568
3569 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
3570 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
3571 log error "FLAC on an Ogg container is not yet supported"
3572 log error "due to problem with adding comments to such files"
3573 exit 1
3574 OGGOUTPUTCONTAINER=ogg.ogg
3575 FLACOUTPUTCONTAINER=flac.ogg
3576 vecho warning "modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
3577 fi
3578
3579 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
3580
3581 if [ "$ENCNICE" ]; then
3582 ENCNICE="-n $ENCNICE"
3583 fi
3584 if [ "$READNICE" ]; then
3585 READNICE="-n $READNICE"
3586 fi
3587 if [ "$DISTMP3NICE" ]; then
3588 DISTMP3NICE="-n $DISTMP3NICE"
3589 fi
3590
3591 # Don't check for stuff if it's not needed
3592 if [ "$REMOTEHOSTS" ]; then
3593 NEEDDISTMP3=y
3594 fi
3595 if [ "$DONORMALIZE" = "y" ]; then
3596 NEEDNORMALIZER=y
3597 fi
3598 if [ "$EJECTCD" = "y" ]; then
3599 NEEDEJECT=y
3600 fi
3601 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
3602 if [ "$CDDBMETHOD" = "cddb" ]; then
3603 NEEDHTTPGET=y
3604 elif [ "$CDDBMETHOD" = "musicbrainz" ]; then
3605 :
3606 fi
3607 fi
3608 if [ "$MAKECUEFILE" = "y" ]; then
3609 NEEDCUEREADER=y
3610 fi
3611
3612 if [ X"$CDSPEEDVALUE" != "X" ] && [ "$DOREAD" = "y" ]; then
3613 case "$CDROMREADERSYNTAX" in
3614 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
3615 ### FIXME ### translate "cue2discid" from python to bash
3616 flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ; CDSPEEDVALUE="" ;;
3617 *) NEEDCDSPEED=y ;;
3618 esac
3619 fi
3620
3621 ###USEPIPESSUPPORT###
3622
3623 # Rippers with USEPIPE support
3624 # FIXME # Include here all the rippers we can figure out support pipes
3625 PIPERIPPER_cdparanoia="-"
3626 PIPERIPPER_debug="-"
3627 PIPERIPPER_flac="-c "
3628
3629 # Encoders with USEPIPE support
3630 # FIXME # Include here all the encoders we can figure out support pipes
3631 PIPE_lame="-"
3632 PIPE_bladeenc="-"
3633 PIPE_oggenc="-"
3634 PIPE_flac="-"
3635
3636 # Figure out if we can use pipes with the ripper/encoder combination
3637 # exit otherwise
3638 if [ "$USEPIPES" = "y" ]; then
3639 PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
3640 case "$OUTPUT" in
3641 mp3)
3642 PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
3643 vorbis|ogg)
3644 PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
3645 flac)
3646 PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
3647 spx)
3648 PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
3649 mpc)
3650 PIPEENCODERSVARCHECK="PIPE_$MPPENCODER" ;;
3651 esac
3652 decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
3653 if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
3654 [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
3655 log error "no support for pipes with given ripper"
3656 log error "read the USEPIPES file from the source tarball to get help."
3657 log error "On a Debian system, it is under /usr/share/doc/abcde/USEPIPES.gz"
3658 exit 1;
3659 fi
3660 decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
3661 if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
3662 [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
3663 log error "no support for pipes with given encoder"
3664 log error "read the USEPIPES file from the source tarball to help"
3665 log error "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz"
3666 exit 1;
3667 fi
3668 fi
3669
3670 # Make sure a buncha things exist
3671 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
3672 $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
3673 $AACENCODER \
3674 ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
3675 ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
3676 ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
3677 ${NEEDDISKTOOL+disktool} ${NEEDCDSPEED+$CDSPEED} \
3678 ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
3679 ${NEEDMPPGAIN+$MPPGAIN} ${NEEDCUEREADER+$CUEREADER} \
3680 ${NEEDCUE2DISCID+$CUE2DISCID}
3681 do
3682 checkexec "$X"
3683 done
3684
3685 # And last but not least, check if we can diff between files. We do not abort,
3686 # since diffing is not critical...
3687 if [ -x $(which $DIFF) ]; then :; else
3688 vecho warning "Disabling diff since we cannot find it in the \$PATH..."
3689 DIFF=""
3690 fi
3691
3692 ## Now that we have metaflac, check if we need cue2discid
3693 #case $CDROMREADERSYNTAX in
3694 # flac)
3695 # TRACKINFO=$($METAFLAC --show-tag=CDDB $CDROM | cut -d"=" -f2 | egrep "[a-f0-9]{8}")
3696 # if [ "$TRACKINFO" = "" ]; then
3697 # checkexec ${NEEDCUE2DISCID+$CUE2DISCID}
3698 # fi
3699 # ;;
3700 #esac
3701
3702 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
3703 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
3704 HTTPGET="$HTTPGET $HTTPGETOPTS"
3705
3706 # Here it used to say:
3707 # One thousand lines in, we can start doing stuff with things
3708 # Well, right now we are at line 3306 ;)
3709
3710 # Export needed things so they can be read in this subshell
3711 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
3712 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
3713
3714 if [ "$DOREAD" = "y" ]; then
3715 # User-definable function to set some things. Use it for
3716 # - closing the CD tray with eject -t
3717 # - set the CD speed value with eject -x
3718 vecho -n "Executing customizable pre-read function... "
3719
3720 pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
3721
3722 vecho "done."
3723 fi
3724
3725 case "$CDDBMETHOD" in
3726 cddb)
3727 do_discid # Get ABCDETEMPDIR created and status file initialized
3728 ;;
3729 musicbrainz)
3730 do_musicbrainz id
3731 ;;
3732 esac
3733
3734 if [ "$DOCDDB" = "y" ]; then
3735 # start with a sane default:
3736 CDDBLOCALSTATUS=notfound
3737 if [ $CDDBUSELOCAL = "y" ]; then
3738 do_localcddb
3739 fi
3740 if checkstatus cddb-choice > /dev/null; then
3741 :
3742 else
3743 if [ "$CDDBLOCALSTATUS" = "notfound" ] ; then
3744 case "$CDDBMETHOD" in
3745 cddb)
3746 do_cddbstat
3747 do_cddbquery
3748 do_cddbread
3749 ;;
3750 musicbrainz)
3751 do_musicbrainz
3752 ;;
3753 esac
3754 fi
3755 fi
3756 do_cddbedit
3757
3758 eval "$($CDDBTOOL parse "$CDDBDATA")"
3759 fi
3760
3761 # Before reading tracks, we set the speed of the device
3762
3763 if [ X"$CDSPEEDVALUE" != "X" ]; then
3764 case "$CDROMREADERSYNTAX" in
3765 cdparanoia|debug) ;;
3766 flac) ;;
3767 *) do_cdspeed ;;
3768 esac
3769 fi
3770
3771 # Define the first and last track, since we might need them later in several places
3772 FIRSTTRACK=$( get_first $TRACKQUEUE )
3773 LASTTRACK=$( get_last $TRACKQUEUE )
3774
3775 if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
3776 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
3777 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
3778 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
3779 fi
3780
3781 if checkstatus onetrack ; then ONETRACK=y ; fi
3782
3783 if [ "$ONETRACK" = "y" ]; then
3784 # Reuse the CUEFILE in case we created it (now or in a previous run)
3785 if CUEFILE=$(checkstatus cuefile); then
3786 IMPORTCUESHEET=y
3787 fi
3788 fi
3789
3790 # Create playlist if needed (backgroundable) and start reading in tracks
3791
3792 (
3793
3794 if [ ! "$ONETRACK" = "y" ]; then
3795 if [ "$DOPLAYLIST" = "y" ]; then
3796 echo Creating playlist... >&2
3797 do_playlist
3798 fi
3799 fi
3800
3801 # For the lowdisk option, only one program is running at once so the encoder
3802 # can be unsilenced right away.
3803 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
3804 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
3805 fi
3806
3807 if [ "$ONETRACK" = "y" ]; then
3808 TRACKS="$FIRSTTRACK"
3809 if [ "$USEPIPES" = "y" ]; then
3810 if checkstatus readencodetrack-$FIRSTTRACK; then :; else
3811 do_cdread onetrack $FIRSTTRACK $LASTTRACK | do_encode $FIRSTTRACK %local0% > /dev/null 2>&1
3812 fi
3813 else
3814 if checkstatus readtrack-$FIRSTTRACK; then :; else
3815 do_cdread onetrack $FIRSTTRACK $LASTTRACK
3816 fi
3817 fi
3818 else
3819 for UTRACKNUM in $TRACKQUEUE
3820 do
3821 if [ "$DOREAD" = "y" ]; then
3822 if [ "$USEPIPES" = "y" ]; then
3823 if checkstatus readencodetrack-$UTRACKNUM; then :; else
3824 # Read, pipe, shut up!
3825 do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
3826 fi
3827 else
3828 if checkstatus readtrack-$UTRACKNUM; then :; else
3829 do_cdread $UTRACKNUM
3830 fi
3831 if [ "$?" != "0" ]; then
3832 # CD read failed - don't give the goahead to
3833 # the encoder
3834 echo NO
3835 exit
3836 fi
3837 fi
3838 fi
3839 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ]; then
3840 :
3841 else
3842 # If we are not reading, set the encode output to loud already, so
3843 # that we can see the output of the first track.
3844 if [ "$MAXPROCS" = "1" ] && [ ! "$DOREAD" = "y" ]; then
3845 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
3846 fi
3847 echo NEXTTRACK # Get the encoder machine churning again
3848 if [ "$DOREAD" = "y" ]; then
3849 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
3850 until checkstatus encodetrack-$UTRACKNUM
3851 do
3852 if checkerrors encodetrack-$UTRACKNUM; then
3853 break
3854 fi
3855 sleep 2
3856 done
3857 fi
3858 fi
3859 fi
3860 done
3861 fi
3862
3863 # Now that we're done the encoding can be loud again -
3864 # if we're not using SMP.
3865 if [ "$MAXPROCS" = "1" ]; then
3866 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
3867 fi
3868
3869 # All tracks read, start encoding.
3870 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ] || [ "$ONETRACK" = "y" ]; then
3871 echo NEXTTRACK
3872 fi
3873
3874 # Execute the user-defined post_read funtion before ejecting CD
3875 post_read
3876
3877 # We are now finished with the cdrom - it can be safely ejected. Note that
3878 # abcde will not have completed yet.
3879 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
3880 # We check if the disk we are processing is actually the disk inside the
3881 # CD tray. If not, we do not eject the CD, since it might be so that the
3882 # user ejected it manually.
3883 #CURRENTTRACKINFO=$($CDDISCID $CDROM)
3884 #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
3885 # More FreeBSD bits.
3886 if [ X"$(uname)" = X"FreeBSD" ] ; then
3887 # FreeBSD eject uses the EJECT environment variable to name the CDROM
3888 # but in this script EJECT is in the envionment and names the program
3889 eject=$EJECT
3890 unset EJECT
3891 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
3892 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
3893 $eject $EJECTOPTS $cd
3894 elif [ X"$(uname)" = X"Darwin" ] ; then
3895 disktool -e ${CDROM#/dev/} 0
3896 else
3897 $EJECT $EJECTOPTS "$CDROM"
3898 fi
3899 #fi
3900 fi
3901
3902 ) | (
3903
3904 ## Do we need to pre-process
3905 #if [ x"$PREPROCESS" = "x" ] ; then
3906 # cat
3907 #else
3908 # for PRETRACKNUM in $TRACKQUEUE
3909 # do
3910 # read GOAHEAD
3911 # if [ "$GOAHEAD" = "NO" ]; then break; fi
3912 # PREPROCEED=
3913 # until [ $PREPROCEED ]
3914 # do
3915 # if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
3916 # # all locations are working, wait and try again later
3917 # if [ ! $PREPROCEED ]; then sleep 3; fi
3918 # done
3919 # ( do_preprocess $PRETRACKNUM
3920 # echo "NEXTTRACK"
3921 # ) &
3922 # done
3923 #fi
3924 #
3925 #) | (
3926
3927 # In BATCHNORM and/or NOGAP modes, we want all tracks to be read first.
3928 #BACK
3929 if [ "$BATCHNORM" = "y" ] || [ "$NOGAP" = "y" ]; then
3930 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
3931 if [ "$GOAHEAD" = "NO" ]; then break; fi
3932 for LASTTRACK in $TRACKQUEUE; do :; done
3933 if checkstatus readtrack-$LASTTRACK; then
3934 if [ "$DONORMALIZE" = "y" ] && [ "$BATCHNORM" = "y" ]; then
3935 if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
3936 if checkerrors batch-normalize; then exit 1; fi
3937 fi
3938 if [ "$DOENCODE" = "y" ] && [ "$NOGAP" = "y" ]; then
3939 if [ "$DONORMALIZE" = "y" ]; then
3940 for UTRACKNUM in $TRACKQUEUE
3941 do
3942 if checkstatus readtrack-$UTRACKNUM; then
3943 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
3944 fi
3945 done
3946 fi
3947 if checkstatus encodetrack-$LASTTRACK; then :; else do_nogap_encode; fi
3948 if checkerrors nogap-encode; then exit 1; fi
3949 fi
3950 fi
3951 fi
3952
3953 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
3954 if [ "$ONETRACK" = "y" ] ; then
3955 TRACKQUEUE="$FIRSTTRACK"
3956 TRACKS="$FIRSTTRACK"
3957 fi
3958
3959 # Do the encoding, including parallelization of remote encoding
3960 # Figure out where each track is going to be encoded
3961 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
3962 if [ "$MAXPROCS" != "0" ]; then
3963 for NUM in $(f_seq_row 1 "$MAXPROCS")
3964 do
3965 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
3966 done
3967 fi
3968 # Strip whitespace
3969 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
3970 for UTRACKNUM in $TRACKQUEUE
3971 do
3972 # Wait for our cue
3973 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
3974 if [ "$GOAHEAD" = "NO" ]; then break; fi
3975 # find out where this track is to be encoded
3976 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
3977 # Make sure we have a place to encode this, if not, exit stage right
3978 if [ -z "$ENCODELOCATIONS" ]; then
3979 continue
3980 fi
3981 PROCEED=
3982 until [ $PROCEED ]
3983 do
3984 for LOCATION in $ENCODELOCATIONS
3985 do
3986 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
3987 # check first if a track has ever been assigned to this location
3988 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
3989 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
3990 if checkerrors encodetrack-$PREVIOUSTRACK; then
3991 for TEMPLOCATION in $ENCODELOCATIONS
3992 do
3993 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
3994 TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
3995 fi
3996 done
3997 ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
3998 ABORT=y
3999 PROCEED=y
4000 break
4001 fi
4002 # We're still here, this location must have been previously assigned,
4003 # and last completed without error - check if it's done with the
4004 # previous track yet
4005 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
4006 done
4007 # all locations are working, wait and try again later
4008 if [ ! $PROCEED ]; then sleep 3; fi
4009 done
4010 # Record the location we're about to encode the next track at
4011 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
4012 fi
4013 # Don't proceed with the rest of the loop if we can't encode
4014 if [ "$ABORT" ]; then continue; fi
4015 ## FIXME ## Add here
4016 ## run_command tagtrack-$OUTPUT-$1 $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="$ABCDETEMPDIR/$CUEFILE"} --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
4017 # Set TRACKNUM, TRACKNAME
4018 if [ -e "$CDDBDATA" ]; then
4019 if [ "$ONETRACK" = "y" ]; then
4020 TRACKNAME="$DALBUM"
4021 TRACKNUM="$FIRSTTRACK"
4022 splitvarious
4023 else
4024 TRACKNUM=$UTRACKNUM
4025 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
4026 getcddbinfo TRACKNAME
4027 splitvarious
4028 fi
4029 fi
4030 # You can't encode a file which needs to be normalized before finishing
4031 # You can't tag a file before it's finished encoding -
4032 # thus all of this is backgrounded together
4033 (
4034 if [ "$DONORMALIZE" = "y" ]; then
4035 if checkstatus readtrack-$UTRACKNUM; then
4036 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
4037 fi
4038 fi
4039 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
4040 if checkstatus readtrack-$UTRACKNUM; then
4041 #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
4042 if [ "$DONORMALIZE" = "y" ]; then
4043 if checkstatus normalizetrack-$UTRACKNUM; then
4044 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4045 fi
4046 else
4047 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4048 fi
4049 fi
4050 fi
4051 if [ "$DOTAG" = "y" ]; then
4052 if checkstatus encodetrack-$UTRACKNUM; then
4053 if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
4054 fi
4055 # Lets tag the cue file
4056 if checkstatus cleancuefile >/dev/null; then :; else
4057 if checkstatus cuefile >/dev/null ; then
4058 do_cleancue
4059 fi
4060 fi
4061 fi
4062 if [ "$DOMOVE" = "y" ]; then
4063 if checkstatus tagtrack-$UTRACKNUM; then
4064 if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
4065 fi
4066 fi
4067 ) &
4068 done
4069
4070
4071 # Go through it again and make sure there's no distmp3 stragglers, otherwise
4072 # we'll delete the files they're working on
4073 # Do NOT play ball if there is no ball to play (so ABORT if needed)
4074 ## FIXME ## Check also for files which are encoded using PIPEs.
4075 if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ] && [ ! "$ABORT" ]; then
4076 PROCEED=
4077 until [ $PROCEED ]
4078 do
4079 PROCEED=y
4080 for LOCATION in $ENCODELOCATIONS
4081 do
4082 CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
4083 # "How can he give us a status update, if he's DEAD?"
4084 if checkstatus encodetrack-$CHECKTRACK; then
4085 continue
4086 fi
4087 # Nothing to see here please go quietly back to your homes
4088 if [ -z "$CHECKTRACK" ]; then continue; fi
4089 # You're still here? Maybe there is something...
4090 if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
4091 done
4092 # hold up
4093 if [ ! $PROCEED ]; then sleep 5; fi
4094 done
4095 fi
4096 # If the above didn't catch the stragglers, this will
4097 wait
4098 if [ "$DOREPLAYGAIN" = "y" ]; then
4099 do_replaygain
4100 fi
4101
4102 # Check to see if run_command logged any errors
4103 if [ -f "$ABCDETEMPDIR/errors" ]; then
4104 log error "The following commands failed to run:"
4105 cat "$ABCDETEMPDIR/errors"
4106 # Don't clean up
4107 DOCLEAN=n
4108 fi
4109 if [ "$KEEPWAVS" = "y" ];then
4110 # Don't clean up
4111 DOCLEAN=n
4112 fi
4113 # Check if we have moved all the formats we had previously encoded, if we are not using the FORCE.
4114 if [ "$DOCLEAN" = "y" ] && [ ! "$FORCE" = "y" ]; then
4115 ENCODED_FORMATS=$(egrep "^encodetrack-(.{3,6})-(.{1,2})$" "$ABCDETEMPDIR/status" | cut -d"-" -f2 | sort -u | tr '\n' '|')
4116 MOVED_FORMATS=$(egrep "^movetrack-output-(.{3,6})$" "$ABCDETEMPDIR/status" | cut -d"-" -f3 | sort -u | tr '\n' '|')
4117 if [ "$ENCODED_FORMATS" != "$MOVED_FORMATS" ]; then
4118 log warning "The encoded formats does not match with the moved ones"
4119 log warning "Formats encoded: $( echo $ENCODED_FORMATS | tr "|" " " )"
4120 log warning "Formats moved: $( echo $MOVED_FORMATS | tr "|" " " )"
4121 log warning "Use \"abcde -a clean -f -C $DISCID\" to force the removal of the remaining data."
4122 DOCLEAN=n
4123 fi
4124 fi
4125 if [ "$DOCLEAN" = "y" ]; then
4126 # Wipe all the evidence
4127 # Gimme gimme gimme some more time!
4128 sleep 5
4129 rm -rf "$ABCDETEMPDIR"
4130 echo "Finished."
4131 else
4132 echo "Finished. Not cleaning $ABCDETEMPDIR."
4133 fi
4134 )
4135 exit 0
4136
4137 # b:is_bash
4138 # vim:tabstop=4