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