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