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