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