d0585f6c840630eb86679eed127b7699c7287daa
[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
437 CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
438 TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - $FIRSTTRACK ))
439 else
440 TRACKNUM=${UTRACKNUM}
441 fi
442 }
443
444 # makeids
445 #
446 # Calculate cddb disc ids without requiring specialized helper programs.
447 # largely copied from cd-discid and musicbrainz examples. some of the steps
448 # don't make sense, but they're necessary to match the ids generated by other
449 # programs.
450 #
451 ## FIXME ## Right now, we get 2 frames more than with cue2discid ??
452 # data@petit:~$ sh /tmp/cue2discid /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac
453 # processing offsetimes 00:00:00 04:47:10 08:20:37 11:46:46 17:45:36 21:41:57 27:32:21 32:03:73 35:39:28 38:27:33 43:50:38 44:42:34
454 # 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2895
455 # data@petit:~$ metaflac --export-cuesheet-to=- /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac| python /home/data/sources/abcde/trunk/examples/cue2discid
456 # 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2893
457 #
458 # Variables: OFFSETS, TRACKS, LEADOUT, [LEADIN]
459 makeids ()
460 {
461 if [ X"$LEADOUT" = "X" ]; then
462 log warning "Error trying to calculate disc ids without lead-out information."
463 exit 1
464 fi
465
466 # default to a two second lead-in
467 IDMAGICNUM=150
468 LEADIN=${LEADIN:=150}
469
470 # number of cdframes per second
471 CDFRAMES=75
472
473 # reset cddb checksum for cddb disc-id calululation
474 CDDBCKSUM=0
475
476 COOKEDOFFSETS=""
477 for OFFSET in $(echo $OFFSETS)
478 do
479 COOKEDOFFSETS="${COOKEDOFFSETS} $(($OFFSET + $LEADIN))"
480
481 OFFSETTIME=$(( ($OFFSET + $LEADIN) / $CDFRAMES ))
482 while [ $OFFSETTIME -gt 0 ]; do
483 CDDBCKSUM=$(($CDDBCKSUM + $OFFSETTIME % 10))
484 OFFSETTIME=$(($OFFSETTIME / 10))
485 done
486
487 done
488
489 COOKEDOFFSETS="${COOKEDOFFSETS:1}" # eat the leading space
490
491 PREGAP=$(($(echo $OFFSETS | cut -f1 -d' ')))
492 TOTALTIME=$(( (($LEADOUT + $LEADIN + $PREGAP) / $CDFRAMES) - (($LEADIN + $PREGAP) / $CDFRAMES)))
493
494 case "$CDDBMETHOD" in
495 cddb)
496 printf -v DISCID "%08lx" $(( ($CDDBCKSUM % 0xff) << 24 | $TOTALTIME << 8 | $TRACKS))
497 ;;
498 musicbrainz)
499 # FIXME: don't assume the first track is 1
500 echo "dasd: 1 $TRACKS $LEADIN $LEADOUT $OFFSETS "
501 DISCID=$($MUSICBRAINZ --command calcid --discinfo 1 $TRACKS $LEADIN $LEADOUT $OFFSETS)
502 ;;
503 esac
504
505 TRACKINFO="${DISCID} $((TRACKS)) ${COOKEDOFFSETS} $((($LEADOUT + $LEADIN + $IDMAGICNUM) / $CDFRAMES))"
506 }
507
508 do_replaygain()
509 {
510 if checkstatus replaygain; then :; else
511 run_command "" echo "Adding replaygain information..."
512 for TMPOUTPUT in $( echo $OUTPUTTYPE | tr , \ )
513 do
514 case $TMPOUTPUT in
515 vorbis|ogg)
516 OUTPUT=$OGGOUTPUTCONTAINER
517 ;;
518 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 \""$CUEWAVEFILE"\" 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 elif [ X$(uname) = "XOpenBSD" ] ; then
3365 HTTPGET=wget
3366 MD5SUM=md5
3367 OSFLAVOUR=OBSD
3368 elif [ X$(uname) = "XNetBSD" ] ; then
3369 HTTPGET=ftp
3370 MD5SUM=md5
3371 OSFLAVOUR=NBSD
3372 elif [ X$(uname) = "SunOS" ] ; then
3373 HTTPGET=""
3374 MD5SUM=md5
3375 OSFLAVOUR=SunOS
3376 else
3377 HTTPGET=wget
3378 fi
3379
3380 # If CDDBAVAIL is set to n, no CDDB read is done
3381 CDDBAVAIL=y
3382
3383 # There we go..
3384 # But before we get into business, let us chop off any GREP environmental
3385 # variables.
3386 GREP_OPTIONS=""
3387 GREP_COLOR=""
3388
3389 if [ -z "$OUTPUTDIR" ]; then
3390 OUTPUTDIR=$(pwd)
3391 fi
3392
3393 if [ -z "$WAVOUTPUTDIR" ]; then
3394 WAVOUTPUTDIR="$OUTPUTDIR"
3395 fi
3396
3397 # Load system defaults
3398 if [ -r /etc/abcde.conf ]; then
3399 . /etc/abcde.conf
3400 fi
3401 # Load user preference defaults
3402 if [ -r $HOME/.abcde.conf ]; then
3403 . $HOME/.abcde.conf
3404 fi
3405
3406 # By this time, we need some HTTPGETOPTS already defined.
3407 # If the user has defined a non-default HTTPGET method, we should not be empty.
3408
3409 if [ "$HTTPGETOPTS" = "" ] ; then
3410 case $HTTPGET in
3411 wget) HTTPGETOPTS="-q -nv -e timestamping=off -O -";;
3412 curl) HTTPGETOPTS="-f -s";;
3413 fetch)HTTPGETOPTS="-q -o -";;
3414 ftp) HTTPGETOPTS="-a -V -o - ";;
3415 *) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
3416 esac
3417 fi
3418
3419 # If the CDROM has not been set yet, find a suitable one.
3420 # If this is a devfs system, default to /dev/cdroms/cdrom0
3421 # instead of /dev/cdrom
3422 if [ "$CDROM" = "" ] ; then
3423 if [ -e /dev/cdroms/cdrom0 ]; then
3424 CDROM=/dev/cdroms/cdrom0
3425 elif [ "$OSFLAVOUR" = "OSX" ] && [[ $(diskutil list) =~ CD_part.*(disk.)$'\n' ]]; then
3426 CDROM=/dev/${BASH_REMATCH[1]}
3427 elif [ -e /dev/cdrom ]; then
3428 CDROM=/dev/cdrom
3429 elif [ -e /dev/sr0 ]; then
3430 CDROM=/dev/sr0
3431 elif [ -e /dev/cd0c ]; then
3432 CDROM=/dev/cd0c
3433 elif [ -e /dev/acd0c ]; then
3434 CDROM=/dev/acd0c
3435 elif [ -e /dev/disk1 ]; then
3436 CDROM=/dev/disk1
3437 fi
3438 fi
3439
3440 # We used to use EXTRAVERBOSE=y to turn on more debug output. Now
3441 # that's changed to a number to allow for more control. If
3442 # EXTRAVERBOSE=y, set it to 1 for backwards compatibility.
3443 if [ "$EXTRAVERBOSE" = "y" ]; then
3444 EXTRAVERBOSE=1
3445 fi
3446 if [ "$EXTRAVERBOSE" = "n" ]; then
3447 EXTRAVERBOSE=0
3448 fi
3449
3450 # Parse command line options
3451 #while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPq:r:Rs:S:t:T:vVxw:W: opt ; do
3452 while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPq:r:s:S:t:T:UvVxX:w:W:z opt ; do
3453 case "$opt" in
3454 1) ONETRACK=y ;;
3455 a) ACTIONS="$OPTARG" ;;
3456 A) EXPACTIONS="$OPTARG" ;;
3457 b) BATCHNORM=y ;;
3458 B) NOBATCHREPLAYGAIN=y ;;
3459 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
3460 C) DISCID="$( echo ${OPTARG#abcde.} | tr -d /)" ;;
3461 d) CDROM="$OPTARG" ;;
3462 D) set -x ;;
3463 h) usage; exit ;;
3464 e) ERASEENCODEDSTATUS=y ;;
3465 E) ENCODING="$OPTARG" ;;
3466 f) FORCE=y ;;
3467 g) NOGAP=y ;;
3468 i) INLINETAG=y ;;
3469 j) MAXPROCS="$OPTARG" ;;
3470 k) KEEPWAVS=y ;;
3471 l) LOWDISK=y ;;
3472 L) CDDBUSELOCAL=y ;;
3473 n) CDDBAVAIL=n ;;
3474 N) INTERACTIVE=n ;;
3475 m) DOSPLAYLIST=y ;;
3476 M) DOCUE=y ;;
3477 o) OUTPUTTYPE="$OPTARG" ;;
3478 p) PADTRACKS=y ;;
3479 P) USEPIPES=y ;;
3480 q) QUALITYLEVEL="$OPTARG" ;;
3481 r) REMOTEHOSTS="$OPTARG" ;;
3482 R) CDDBLOCALRECURSIVE=y ;;
3483 s) SHOWCDDBFIELDS="$OPTARG" ;;
3484 S) CDSPEEDVALUE="$OPTARG" ;;
3485 t) STARTTRACKNUMBER="$OPTARG" ;;
3486 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
3487 U) CDDBPROTO=5 ;;
3488 v)
3489 echo "This is abcde v$VERSION."
3490 echo "Usage: abcde [options] [tracks]"
3491 echo "abcde -h for extra help"
3492 exit
3493 ;;
3494 V) EXTRAVERBOSE=$(($EXTRAVERBOSE + 1)) ;;
3495 x) EJECTCD="y" ;;
3496 X) CUE2DISCID="$OPTARG" ;;
3497 w) COMMENT="$OPTARG" ;;
3498 W) if echo $OPTARG | grep "[[:digit:]]" > /dev/null 2>&1 ; then
3499 STARTTRACKNUMBER="${OPTARG}01"
3500 STARTTRACKNUMBERTAG="y"
3501 COMMENT="CD${OPTARG}"
3502 DISCNUMBER="${OPTARG}"
3503 else
3504 log error "argument of -W must be integer"
3505 exit 1
3506 fi
3507 ;;
3508 z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
3509 ?) usage; exit ;;
3510 esac
3511 done
3512
3513 shift $(($OPTIND - 1))
3514
3515 # Here it comes the worse part of the whole thing. From here until we start
3516 # ripping, we have a mixture of sanity checks, verifications, default settigs
3517 # and other crazy stuff that interdepends, but hey, someone has to do it.
3518
3519 # If NOCDDBQUERY is set, don't query the CDDB server.
3520 if [ "$NOCDDBQUERY" = "y" ]; then
3521 CDDBAVAIL="n"
3522 fi
3523
3524 # If the user specified a flac file, then switch to special flac mode
3525 if echo "$CDROM" | grep -i '.flac$' > /dev/null 2>&1 ; then
3526 if [ ! -f "$CDROM" ]; then
3527 log error "the defined file for FLAC ripping cannot be found" >&2
3528 exit 1
3529 fi
3530 vecho warning "switching to flac CDROMREADERSYNTAX..."
3531 CDROMREADERSYNTAX=flac
3532 # We have a builtin version of cue2discid...
3533 case "$CUE2DISCID" in
3534 builtin);;
3535 *) NEEDCUE2DISCID=y;;
3536 esac
3537 NEEDMETAFLAC=y
3538 EJECTCD=n
3539 fi
3540
3541 # If the user provided a DISCID, disable eject
3542 if [ -n "$DISCID" ] || [ "$CDROMREADERSYNTAX" = "flac" ]; then EJECTCD=n ; fi
3543
3544 # Check the available cd rippers in the system, from the ones we know.
3545 if [ "$CDROMREADERSYNTAX" = "" ]; then
3546 for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
3547 if new_checkexec $DEFAULT_CDROMREADER; then
3548 CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
3549 break
3550 fi
3551 done
3552 if [ "$CDROMREADERSYNTAX" = "" ]; then
3553 log error "no cdreader found in your PATH"
3554 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3555 exit 1
3556 fi
3557 fi
3558
3559 # Decide if we can continue.
3560 if [ "$ONETRACK" = "y" ]; then
3561 # FIXME # remove check as soon as we find out about the other readers
3562 case "$CDROMREADERSYNTAX" in
3563 flac) ;;
3564 cdparanoia) ;;
3565 cdda2wav | icedax) ;;
3566 *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
3567 exit 1 ;;
3568 esac
3569 if [ "$BATCHNORM" = "y" ]; then
3570 log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
3571 BATCHNORM=n
3572 fi
3573 if [ "$NOGAP" = "y" ]; then
3574 log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
3575 NOGAP=n
3576 fi
3577 # It does not matter how many tracks we want. In ONETRACK mode we grab them all
3578 # FIXME # allow ranges of tracks to be selected for onetrack ripping
3579 if [ $# -gt 0 ]; then
3580 log warning "ONETRACK mode selected, grabbing all tracks..."
3581 fi
3582 else
3583 while [ $# -gt 0 ]; do
3584 # Range parsing code courtesy of Vincent Ho
3585 # Cleaned up to use shell built-ins by Charles Steinkuehler
3586 if [ "${1#*[^0-9-]}" != "$1" ]; then
3587 log error "syntax error while processing track numbers ($1)"
3588 exit 1
3589 else
3590 RSTART=${1%%-*}
3591 REND=${1##*-}
3592 while [ ${RSTART:=1} -le ${REND:=0} ] ; do
3593 TRACKQUEUE="$TRACKQUEUE $RSTART"
3594 RSTART=$(( $RSTART + 1 ))
3595 done
3596 fi
3597 shift
3598 done
3599 fi
3600
3601 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
3602 # List of experimental actions: retag,transcode
3603
3604 # Determine what actions are to be done from $ACTIONS and set the
3605 # following environment variables for them:
3606 DOCDDB=n
3607 DOREAD=n
3608 DONORMALIZE=n
3609 DOPREPROCESS=n
3610 DOENCODE=n
3611 DOPOSTPROCESS=n
3612 DOTAG=n
3613 DOMOVE=n
3614 DOREPLAYGAIN=n
3615 DOPLAYLIST=n
3616 DOCLEAN=n
3617 ## FIXME ## Lets keep compatibility with -M
3618 [ "$DOCUE" != "y" ] && DOCUE=n
3619
3620 for ACTION in $(echo $ACTIONS | tr , \ )
3621 do
3622 case $ACTION in
3623 default) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOCLEAN=y;;
3624 cue) DOCUE=y ; MAKECUEFILE=y ;;
3625 cddb) DOCDDB=y;;
3626 read) DOREAD=y;;
3627 normalize) DONORMALIZE=y; DOREAD=y;;
3628 # preprocess) DOPREPROCESS=y; DOREAD=y;;
3629 encode) DOENCODE=y; DOREAD=y;;
3630 # postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
3631 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3632 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
3633 replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
3634 playlist) DOCDDB=y; DOPLAYLIST=y;;
3635 clean) DOCLEAN=y;;
3636 esac
3637 done
3638
3639 if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
3640 # FIXME # should we abort on error or just inform the user?
3641 log warning "selected both normalize and replaygain actions"
3642 fi
3643
3644 for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
3645 case $SHOWCDDBFIELD in
3646 y*|Y*) SHOWCDDBYEAR="y";;
3647 g*|G*) SHOWCDDBGENRE="y";;
3648 *) ;;
3649 esac
3650 done
3651
3652 # At this point a CDROM has to be defined, so we check it exists.
3653 if [ X"$CDROM" != "X" ] ; then
3654 if ( [ "$CDROMREADERSYNTAX" = "cdda2wav" ] || [ "$CDROMREADERSYNTAX" = "icedax" ] ) && [ "$NEEDCDROMID" = "y" ] ; then
3655 if [ "$OSFLAVOUR" = "FBSD" ]; then
3656 if echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then :; else
3657 log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
3658 log error "Use \"cdrecord -scanbus\" to obtain an adequate ID and set CDROMID accordingly"
3659 exit 1
3660 fi
3661 fi
3662 elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
3663 log error "CDROM device cannot be found."
3664 exit 1
3665 fi
3666 # avoid processing if we are not going to hit the CDROM.
3667 elif [ X"$DOREAD" = "Xy" ]; then
3668 log error "CDROM has not been defined or cannot be found"
3669 exit 1
3670 fi
3671
3672 # USEPIPES pre-tests, before we get into more serious stuff
3673 # Not compatible with:
3674 # - multiple outputs
3675 # - normalize
3676 # - lowdisk algorithm
3677 # - anything else?
3678 if [ X"$USEPIPES" = "Xy" ]; then
3679 if [ $(echo "$OUTPUTTYPE" | tr , \ | wc -w ) -gt 1 ]; then
3680 log error "Unix pipes not compatible with multiple outputs"
3681 exit 1
3682 fi
3683 if [ X"$DONORMALIZE" = "Xy" ]; then
3684 log error "Unix pipes not compatible with normalizer"
3685 # FIXME # Do we need to exit or shall we just disable the mode?
3686 exit 1
3687 fi
3688 if [ X"$BATCHNORM" = "Xy" ]; then
3689 log error "Unix pipes not compatible with BATCHNORM encoding"
3690 exit 1
3691 fi
3692 if [ X"$NOGAP" = "Xy" ]; then
3693 log error "Unix pipes not compatible with NOGAP encoding"
3694 exit 1
3695 fi
3696 if [ X"$DOENCODE" = "Xn" ]; then
3697 vecho warning "Disabling Unix pipes since we are not encoding!"
3698 USEPIPES=n
3699 fi
3700 if [ X"$LOWDISK" = "Xy" ]; then
3701 log error "Unix pipes not compatible with lowdisk algorithm"
3702 exit 1
3703 fi
3704 fi
3705
3706 # LOWDISK pre-tests, before we get into more problematic stuff
3707 # Not compatible with anything that needs all the files in the hard disc:
3708 # - BATCHNORM
3709 # - NOGAP lame mode
3710 if [ X"$LOWDISK" = "Xy" ]; then
3711 if [ X"$BATCHNORM" = "Xy" ]; then
3712 log error "Unix pipes not compatible with BATCHNORM encoding"
3713 exit 1
3714 fi
3715 if [ X"$NOGAP" = "Xy" ]; then
3716 log error "Unix pipes not compatible with NOGAP encoding"
3717 exit 1
3718 fi
3719 fi
3720
3721 # BATCHNORM pre-tests, before we get into serious problems
3722 # Not compatible with
3723 if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
3724 vecho warning "Disabling BATCHNORM since we are not normalizing!"
3725 BATCHNORM=n
3726 fi
3727
3728 # Check the encoding format from the ones available in the system, if nothing has been configured.
3729 if [ X"$OUTPUTTYPE" = "X" ]; then
3730 for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
3731 DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
3732 DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
3733 if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
3734 OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
3735 vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
3736 break
3737 fi
3738 done
3739 if [ X"$OUTPUTTYPE" = "X" ]; then
3740 log error "no encoder found in the PATH"
3741 log error "hints: are all dependencies installed? has the \$PATH been modified?"
3742 exit 1
3743 fi
3744 fi
3745
3746 # Decide which CDROM reader we're gonna use
3747 case "$CDROMREADERSYNTAX" in
3748 cdparanoia|debug)
3749 CDROMREADER="$CDPARANOIA"
3750 CDROMREADEROPTS="$CDPARANOIAOPTS"
3751 ;;
3752 cdda2wav | icedax)
3753 CDROMREADER="$CDDA2WAV"
3754 CDROMREADEROPTS="$CDDA2WAVOPTS"
3755 ;;
3756 dagrab)
3757 CDROMREADER="$DAGRAB"
3758 CDROMREADEROPTS="$DAGRABOPTS"
3759 ;;
3760 cddafs)
3761 CDROMREADER="$CDDAFS"
3762 CDROMREADEROPTS="$CDDAFSOPTS"
3763 ;;
3764 flac)
3765 CDROMREADER="$FLAC"
3766 CDROMREADEROPTS="$FLACOPTS"
3767 ;;
3768 esac
3769
3770 # There's only one normalize...
3771 case "$NORMALIZERSYNTAX" in
3772 default|normalize)
3773 NORMALIZER="$NORMALIZE"
3774 NORMALIZEROPTS="$NORMALIZEOPTS"
3775 ;;
3776 esac
3777
3778 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
3779 if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
3780 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr \ \|| tr , \ | tr \| \ )"; do
3781 case "$OUTPUT" in
3782 vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3783 opus:*) OPUSENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3784 mp3:*) MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3785 flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3786 spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3787 mpc:*) MPCENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3788 m4a:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
3789 esac
3790 done
3791 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
3792 TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
3793 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
3794 done
3795 OUTPUTTYPE="$TEMPOUTPUTTYPE"
3796 fi
3797
3798 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
3799 # for flacs and speexenc for speex and mpcenc for mpcs and faac for m4as
3800
3801 # Getting ready for multiple output changes
3802 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
3803 do
3804 case $OUTPUT in
3805 vorbis|ogg)
3806 [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
3807 [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
3808 [ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
3809 OGGOUTPUTCONTAINER=ogg
3810 ;;
3811 opus)
3812 [ "$OPUSENCODERSYNTAX" = "default" ] && OPUSENCODERSYNTAX=opusenc
3813 OPUSOUTPUTCONTAINER=opus
3814 ;;
3815 mp3)
3816 [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
3817 [ "$DOTAG" = "y" ] && NEEDTAGGER=y
3818 [ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
3819 ;;
3820 flac)
3821 [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
3822 [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
3823 [ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
3824 [ "$ONETRACK" = "y" ] && [ "$DOCUE" = "y" ] && NEEDMETAFLAC=y
3825 ;;
3826 spx)
3827 [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
3828 # [ "$DOREPLAYGAIN" = "y" ] &&
3829 ;;
3830 mpc)
3831 [ "$MPCENCODERSYNTAX" = "default" ] && MPCENCODERSYNTAX=mpcenc
3832 [ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y
3833 ;;
3834 m4a)
3835 [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
3836 [ "$DOTAG" = "y" ] && CHECKATOMICPARSLEY=y
3837 ;;
3838 wav)
3839 if [ "$KEEPWAVS" = "y" ]; then
3840 vecho "Setting the KEEPWAVS option, since the resulting wav files were requested..."
3841 fi
3842 KEEPWAVS=move
3843 ;;
3844 *) log error "Invalid OUTPUTTYPE defined"
3845 exit 1
3846 ;;
3847 esac
3848 done
3849
3850 # decide which encoder
3851 case "$MP3ENCODERSYNTAX" in
3852 lame)
3853 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
3854 MP3ENCODER="$LAME"
3855 ;;
3856 toolame)
3857 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$TOOLAMEOPTS}"
3858 MP3ENCODER="$TOOLAME"
3859 ;;
3860 gogo)
3861 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
3862 MP3ENCODER="$GOGO"
3863 ;;
3864 bladeenc)
3865 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
3866 MP3ENCODER="$BLADEENC"
3867 ;;
3868 l3enc)
3869 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
3870 MP3ENCODER="$L3ENC"
3871 ;;
3872 xingmp3enc)
3873 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
3874 MP3ENCODER="$XINGMP3ENC"
3875 ;;
3876 mp3enc)
3877 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
3878 MP3ENCODER="$MP3ENC"
3879 ;;
3880 esac
3881 case "$OGGENCODERSYNTAX" in
3882 vorbize)
3883 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
3884 OGGENCODER="$VORBIZE"
3885 ;;
3886 oggenc)
3887 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
3888 OGGENCODER="$OGGENC"
3889 ;;
3890 esac
3891 case "$OPUSENCODERSYNTAX" in
3892 opusenc)
3893 OPUSENCODEROPTS="${OPUSENCODEROPTSCLI:-$OPUSENCOPTS}"
3894 OPUSENCODER="$OPUSENC"
3895 ;;
3896 esac
3897 case "$FLACENCODERSYNTAX" in
3898 flac)
3899 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
3900 FLACENCODER="$FLAC"
3901 if [ "$DOREPLAYGAIN" = "y" ]; then
3902 FLACENCODEROPTS="${FLACENCODEROPTS} --replay-gain"
3903 fi
3904 # FLAC streams can be encapsulated on a Ogg transport layer
3905 if echo "$FLACENCODEROPTS" | grep -E -- "(^| )--ogg($| )" > /dev/null 2>&1 ;then
3906 log error "FLAC on an Ogg container is not yet supported"
3907 log error "due to problem with adding comments to such files"
3908 exit 1
3909 FLACOUTPUTCONTAINER=ogg
3910 else
3911 FLACOUTPUTCONTAINER=flac
3912 fi
3913 ;;
3914 esac
3915 case "$SPEEXENCODERSYNTAX" in
3916 speexenc)
3917 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
3918 SPEEXENCODER="$SPEEXENC"
3919 ;;
3920 esac
3921 case "$MPCENCODERSYNTAX" in
3922 mpcenc)
3923 MPCENCODEROPTS="${MPCENCODEROPTSCLI:-$MPCENCOPTS}"
3924 MPCENCODER="$MPCENC"
3925 ;;
3926 esac
3927 case "$AACENCODERSYNTAX" in
3928 faac)
3929 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
3930 AACENCODER="$AACENC"
3931 ;;
3932 esac
3933
3934 # and which tagger
3935 if [ "$ID3TAGV" = "1" ]; then
3936 TAGGER="$ID3"
3937 TAGGEROPTS="$ID3OPTS"
3938 else
3939 TAGGER="$EYED3"
3940 TAGGEROPTS="$EYED3OPTS"
3941 ID3SYNTAX=eyed3
3942 fi
3943
3944 # NOGAP is specific to lame. Other encoders fail ...
3945 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
3946 log warning "the NOGAP option is specific to lame. Deactivating..."
3947 NOGAP=n
3948 fi
3949
3950 # Options for mkcue
3951 case "$CUEREADERSYNTAX" in
3952 default|mkcue)
3953 CUEREADEROPTS="${CDROM}"
3954 CUEREADER="$MKCUE"
3955 ;;
3956 esac
3957
3958 # which information retrieval tool are we using?
3959 case "$CDDBTOOL" in
3960 cddb) ;;
3961 musicbrainz) ;;
3962 esac
3963
3964 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
3965 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
3966 log error "FLAC on an Ogg container is not yet supported"
3967 log error "due to problem with adding comments to such files"
3968 exit 1
3969 OGGOUTPUTCONTAINER=ogg.ogg
3970 FLACOUTPUTCONTAINER=flac.ogg
3971 vecho warning "modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
3972 fi
3973
3974 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
3975
3976 if [ "$ENCNICE" ]; then
3977 ENCNICE="-n $ENCNICE"
3978 fi
3979 if [ "$READNICE" ]; then
3980 READNICE="-n $READNICE"
3981 fi
3982 if [ "$DISTMP3NICE" ]; then
3983 DISTMP3NICE="-n $DISTMP3NICE"
3984 fi
3985
3986 # Don't check for stuff if it's not needed
3987 if [ "$REMOTEHOSTS" ]; then
3988 NEEDDISTMP3=y
3989 fi
3990 if [ "$DONORMALIZE" = "y" ]; then
3991 NEEDNORMALIZER=y
3992 fi
3993 if [ "$EJECTCD" = "y" ]; then
3994 NEEDEJECT=y
3995 fi
3996 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
3997 if [ "$CDDBMETHOD" = "cddb" ]; then
3998 NEEDHTTPGET=y
3999 elif [ "$CDDBMETHOD" = "musicbrainz" ]; then
4000 :
4001 fi
4002 fi
4003 if [ "$DOCUE" = "y" ]; then
4004 NEEDCUEREADER=y
4005 fi
4006
4007 if [ X"$CDSPEEDVALUE" != "X" ] && [ "$DOREAD" = "y" ]; then
4008 case "$CDROMREADERSYNTAX" in
4009 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
4010 ### FIXME ### translate "cue2discid" from python to bash
4011 flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ; CDSPEEDVALUE="" ;;
4012 *) NEEDCDSPEED=y ;;
4013 esac
4014 fi
4015
4016 ###USEPIPESSUPPORT###
4017
4018 # Rippers with USEPIPE support
4019 # FIXME # Include here all the rippers we can figure out support pipes
4020 PIPERIPPER_cdparanoia="-"
4021 PIPERIPPER_debug="-"
4022 PIPERIPPER_flac="-c "
4023
4024 # Encoders with USEPIPE support
4025 # FIXME # Include here all the encoders we can figure out support pipes
4026 PIPE_lame="-"
4027 PIPE_bladeenc="-"
4028 PIPE_oggenc="-"
4029 PIPE_opusenc="-"
4030 PIPE_flac="-"
4031
4032 # Figure out if we can use pipes with the ripper/encoder combination
4033 # exit otherwise
4034 if [ "$USEPIPES" = "y" ]; then
4035 PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
4036 case "$OUTPUT" in
4037 mp3)
4038 PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
4039 vorbis|ogg)
4040 PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
4041 opus)
4042 PIPEENCODERSVARCHECK="PIPE_$OPUSENCODERSYNTAX" ;;
4043 flac)
4044 PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
4045 spx)
4046 PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
4047 mpc)
4048 PIPEENCODERSVARCHECK="PIPE_$MPCENCODER" ;;
4049 esac
4050 decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
4051 if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
4052 [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
4053 log error "no support for pipes with given ripper"
4054 log error "read the USEPIPES file from the source tarball to get help."
4055 log error "On a Debian system, it is under /usr/share/doc/abcde/USEPIPES.gz"
4056 exit 1;
4057 fi
4058 decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
4059 if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
4060 [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
4061 log error "no support for pipes with given encoder"
4062 log error "read the USEPIPES file from the source tarball to help"
4063 log error "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz"
4064 exit 1;
4065 fi
4066 fi
4067
4068 # Make sure a buncha things exist
4069 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
4070 $OGGENCODER $OPUSENCODER $FLACENCODER $SPEEXENCODER $MPCENCODER \
4071 $AACENCODER $CDDBTOOL \
4072 ${NEEDATOMICPARSLEY+$ATOMICPARSLEY} \
4073 ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
4074 ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
4075 ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
4076 ${NEEDDISKUTIL+diskutil} ${NEEDCDSPEED+$CDSPEED} \
4077 ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
4078 ${NEEDMPPGAIN+$MPPGAIN} ${NEEDCUEREADER+$CUEREADER} \
4079 ${NEEDCUE2DISCID+$CUE2DISCID}
4080 do
4081 checkexec "$X"
4082 done
4083
4084 if [ "$CHECKATOMICPARSLEY" = "y" ]; then
4085 if ! new_checkexec "$ATOMICPARSLEY"; then
4086 echo "WARNING: $ATOMICPARSLEY Not Found Not Post-Tagging!"
4087 DOTAG='n'
4088 else
4089 echo "Using $ATOMICPARSLEY To Tag AAC Tracks."
4090 fi
4091 fi
4092
4093 # And last but not least, check if we can diff between files. We do not abort,
4094 # since diffing is not critical...
4095 if [ -x $(which $DIFF) ]; then :; else
4096 vecho warning "Disabling diff since we cannot find it in the \$PATH..."
4097 DIFF=""
4098 fi
4099
4100 ## Now that we have metaflac, check if we need cue2discid
4101 #case $CDROMREADERSYNTAX in
4102 # flac)
4103 # TRACKINFO=$($METAFLAC --show-tag=CDDB $CDROM | cut -d"=" -f2 | grep -E "[a-f0-9]{8}")
4104 # if [ "$TRACKINFO" = "" ]; then
4105 # checkexec ${NEEDCUE2DISCID+$CUE2DISCID}
4106 # fi
4107 # ;;
4108 #esac
4109
4110 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
4111 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
4112 HTTPGET="$HTTPGET $HTTPGETOPTS"
4113
4114 # Here it used to say:
4115 # One thousand lines in, we can start doing stuff with things
4116 # Well, right now we are at line 3737 ;)
4117
4118 # Export needed things so they can be read in this subshell
4119 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
4120 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
4121
4122 if [ "$DOREAD" = "y" ]; then
4123 # User-definable function to set some things. Use it for
4124 # - closing the CD tray with eject -t
4125 # - set the CD speed value with eject -x
4126 vecho -n "Executing customizable pre-read function... "
4127
4128 pre_read # Execute the user-defined pre-read function. Close the CD with it.
4129
4130 vecho "done."
4131 fi
4132
4133 # Get ABCDETEMPDIR created and status file initialized
4134 do_discid
4135
4136 if [ "$DOCDDB" = "y" ]; then
4137 # start with a sane default:
4138 CDDBLOCALSTATUS=notfound
4139 if [ $CDDBUSELOCAL = "y" ]; then
4140 do_localcddb
4141 fi
4142 if checkstatus cddb-choice > /dev/null; then
4143 :
4144 else
4145 if [ "$CDDBLOCALSTATUS" = "notfound" ] ; then
4146 case "$CDDBMETHOD" in
4147 cddb)
4148 do_cddbstat
4149 do_cddbquery
4150 do_cddbread
4151 ;;
4152 musicbrainz)
4153 do_musicbrainz
4154 ;;
4155 esac
4156 fi
4157 CHOICE=$(checkstatus cddb-choice)
4158 if [ "$CHOICE" = 0 ] ; then
4159 # We don't have any information at all; try to fall back
4160 # to CD-Text for basic information
4161 vecho "No CDDB information found, trying cdtext from the CD"
4162 do_cdtext
4163 fi
4164 fi
4165 do_cddbedit
4166
4167 eval "$($CDDBTOOL parse "$CDDBDATA")"
4168 fi
4169
4170 # Before reading tracks, we set the speed of the device
4171
4172 if [ X"$CDSPEEDVALUE" != "X" ]; then
4173 case "$CDROMREADERSYNTAX" in
4174 cdparanoia|debug) ;;
4175 flac) ;;
4176 *) do_cdspeed ;;
4177 esac
4178 fi
4179
4180 # Define the first and last track, since we might need them later in several places
4181 FIRSTTRACK=$( get_first $TRACKQUEUE )
4182 LASTTRACK=$( get_last $TRACKQUEUE )
4183
4184 if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
4185 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
4186 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
4187 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
4188 fi
4189
4190 if checkstatus onetrack ; then ONETRACK=y ; fi
4191
4192 if [ "$ONETRACK" = "y" ]; then
4193 # Reuse the CUEFILE in case we created it (now or in a previous run)
4194 if CUEFILE=$(checkstatus cuefile); then
4195 IMPORTCUESHEET=y
4196 fi
4197 fi
4198
4199 # Create playlist if needed (backgroundable) and start reading in tracks
4200
4201 (
4202
4203 if [ ! "$ONETRACK" = "y" ]; then
4204 if [ "$DOPLAYLIST" = "y" ]; then
4205 echo Creating playlist... >&2
4206 do_playlist
4207 fi
4208 fi
4209
4210 # For the lowdisk option, only one program is running at once so the encoder
4211 # can be unsilenced right away.
4212 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
4213 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4214 fi
4215
4216 if [ "$ONETRACK" = "y" ]; then
4217 TRACKS="$FIRSTTRACK"
4218 if [ "$USEPIPES" = "y" ]; then
4219 if checkstatus readencodetrack-$FIRSTTRACK; then :; else
4220 do_cdread onetrack $FIRSTTRACK $LASTTRACK | do_encode $FIRSTTRACK %local0% > /dev/null 2>&1
4221 fi
4222 else
4223 if checkstatus readtrack-$FIRSTTRACK; then :; else
4224 do_cdread onetrack $FIRSTTRACK $LASTTRACK
4225 fi
4226 fi
4227 else
4228 for UTRACKNUM in $TRACKQUEUE
4229 do
4230 if [ "$DOREAD" = "y" ]; then
4231 if [ "$USEPIPES" = "y" ]; then
4232 if checkstatus readencodetrack-$UTRACKNUM; then :; else
4233 # Read, pipe, shut up!
4234 do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
4235 fi
4236 else
4237 if checkstatus readtrack-$UTRACKNUM; then :; else
4238 do_cdread $UTRACKNUM
4239 fi
4240 if [ "$?" != "0" ]; then
4241 # CD read failed - don't give the goahead to
4242 # the encoder
4243 echo NO
4244 exit
4245 fi
4246 fi
4247 fi
4248 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ]; then
4249 :
4250 else
4251 # If we are not reading, set the encode output to loud already, so
4252 # that we can see the output of the first track.
4253 if [ "$MAXPROCS" = "1" ] && [ ! "$DOREAD" = "y" ]; then
4254 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4255 fi
4256 echo NEXTTRACK # Get the encoder machine churning again
4257 if [ "$DOREAD" = "y" ]; then
4258 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
4259 until checkstatus encodetrack-$UTRACKNUM
4260 do
4261 if checkerrors encodetrack-$UTRACKNUM; then
4262 break
4263 fi
4264 sleep 2
4265 done
4266 fi
4267 fi
4268 fi
4269 done
4270 fi
4271
4272 # Now that we're done the encoding can be loud again -
4273 # if we're not using SMP.
4274 if [ "$MAXPROCS" = "1" ]; then
4275 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
4276 fi
4277
4278 # All tracks read, start encoding.
4279 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ] || [ "$ONETRACK" = "y" ]; then
4280 echo NEXTTRACK
4281 fi
4282
4283 # Execute the user-defined post_read function before ejecting CD
4284 post_read
4285
4286 # We are now finished with the cdrom - it can be safely ejected. Note that
4287 # abcde will not have completed yet.
4288 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
4289 # We check if the disk we are processing is actually the disk inside the
4290 # CD tray. If not, we do not eject the CD, since it might be so that the
4291 # user ejected it manually.
4292 #CURRENTTRACKINFO=$($CDDISCID $CDROM)
4293 #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
4294 # More FreeBSD bits.
4295 if [ X"$(uname)" = X"FreeBSD" ] ; then
4296 # FreeBSD eject uses the EJECT environment variable to name the CDROM
4297 # but in this script EJECT is in the envionment and names the program
4298 eject=$EJECT
4299 unset EJECT
4300 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
4301 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
4302 $eject $EJECTOPTS $cd
4303 elif [ X"$(uname)" = X"Darwin" ] ; then
4304 diskutil eject ${CDROM#/dev/} 0
4305 else
4306 $EJECT $EJECTOPTS "$CDROM"
4307 fi
4308 #fi
4309 fi
4310
4311 ) | (
4312
4313 ## Do we need to pre-process
4314 #if [ x"$PREPROCESS" = "x" ] ; then
4315 # cat
4316 #else
4317 # for PRETRACKNUM in $TRACKQUEUE
4318 # do
4319 # read GOAHEAD
4320 # if [ "$GOAHEAD" = "NO" ]; then break; fi
4321 # PREPROCEED=
4322 # until [ $PREPROCEED ]
4323 # do
4324 # if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
4325 # # all locations are working, wait and try again later
4326 # if [ ! $PREPROCEED ]; then sleep 3; fi
4327 # done
4328 # ( do_preprocess $PRETRACKNUM
4329 # echo "NEXTTRACK"
4330 # ) &
4331 # done
4332 #fi
4333 #
4334 #) | (
4335
4336 # In BATCHNORM and/or NOGAP modes, we want all tracks to be read first.
4337 #BACK
4338 if [ "$BATCHNORM" = "y" ] || [ "$NOGAP" = "y" ]; then
4339 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
4340 if [ "$GOAHEAD" = "NO" ]; then break; fi
4341 for LASTTRACK in $TRACKQUEUE; do :; done
4342 if checkstatus readtrack-$LASTTRACK; then
4343 if [ "$DONORMALIZE" = "y" ] && [ "$BATCHNORM" = "y" ]; then
4344 if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
4345 if checkerrors batch-normalize; then exit 1; fi
4346 fi
4347 if [ "$DOENCODE" = "y" ] && [ "$NOGAP" = "y" ]; then
4348 if [ "$DONORMALIZE" = "y" ]; then
4349 for UTRACKNUM in $TRACKQUEUE
4350 do
4351 if checkstatus readtrack-$UTRACKNUM; then
4352 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
4353 fi
4354 done
4355 fi
4356 if checkstatus encodetrack-$LASTTRACK; then :; else do_nogap_encode; fi
4357 if checkerrors nogap-encode; then exit 1; fi
4358 fi
4359 fi
4360 fi
4361
4362 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
4363 if [ "$ONETRACK" = "y" ] ; then
4364 TRACKQUEUE="$FIRSTTRACK"
4365 TRACKS="$FIRSTTRACK"
4366 fi
4367
4368 # Do the encoding, including parallelization of remote encoding
4369 # Figure out where each track is going to be encoded
4370 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
4371 if [ "$MAXPROCS" != "0" ]; then
4372 for NUM in $(f_seq_row 1 "$MAXPROCS")
4373 do
4374 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
4375 done
4376 fi
4377 # Strip whitespace
4378 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
4379 for UTRACKNUM in $TRACKQUEUE
4380 do
4381 # Wait for our cue
4382 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
4383 if [ "$GOAHEAD" = "NO" ]; then break; fi
4384 # find out where this track is to be encoded
4385 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
4386 # Make sure we have a place to encode this, if not, exit stage right
4387 if [ -z "$ENCODELOCATIONS" ]; then
4388 continue
4389 fi
4390 PROCEED=
4391 until [ $PROCEED ]
4392 do
4393 for LOCATION in $ENCODELOCATIONS
4394 do
4395 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
4396 # check first if a track has ever been assigned to this location
4397 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
4398 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
4399 if checkerrors encodetrack-$PREVIOUSTRACK; then
4400 for TEMPLOCATION in $ENCODELOCATIONS
4401 do
4402 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
4403 TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
4404 fi
4405 done
4406 ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
4407 ABORT=y
4408 PROCEED=y
4409 break
4410 fi
4411 # We're still here, this location must have been previously assigned,
4412 # and last completed without error - check if it's done with the
4413 # previous track yet
4414 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
4415 done
4416 # all locations are working, wait and try again later
4417 if [ ! $PROCEED ]; then sleep 3; fi
4418 done
4419 # Record the location we're about to encode the next track at
4420 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
4421 fi
4422 # Don't proceed with the rest of the loop if we can't encode
4423 if [ "$ABORT" ]; then continue; fi
4424 ## FIXME ## Add here
4425 ## run_command tagtrack-$OUTPUT-$1 $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="$ABCDETEMPDIR/$CUEFILE"} --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
4426 # Set TRACKNUM, TRACKNAME
4427 if [ -e "$CDDBDATA" ]; then
4428 if [ "$ONETRACK" = "y" ]; then
4429 TRACKNAME="$DALBUM"
4430 TRACKNUM="$FIRSTTRACK"
4431 splitvarious
4432 else
4433 TRACKNUM=$UTRACKNUM
4434 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
4435 getcddbinfo TRACKNAME
4436 splitvarious
4437 fi
4438 fi
4439 # You can't encode a file which needs to be normalized before finishing
4440 # You can't tag a file before it's finished encoding -
4441 # thus all of this is backgrounded together
4442 (
4443 if [ "$DONORMALIZE" = "y" ]; then
4444 if checkstatus readtrack-$UTRACKNUM; then
4445 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
4446 fi
4447 fi
4448 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
4449 if checkstatus readtrack-$UTRACKNUM; then
4450 #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
4451 if [ "$DONORMALIZE" = "y" ]; then
4452 if checkstatus normalizetrack-$UTRACKNUM; then
4453 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4454 fi
4455 else
4456 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
4457 fi
4458 fi
4459 fi
4460 if [ "$DOTAG" = "y" ]; then
4461 if checkstatus encodetrack-$UTRACKNUM; then
4462 if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
4463 fi
4464 # Lets tag the cue file
4465 if checkstatus cleancuefile >/dev/null; then :; else
4466 if checkstatus cuefile >/dev/null ; then
4467 do_cleancue
4468 fi
4469 fi
4470 fi
4471 if [ "$DOMOVE" = "y" ]; then
4472 if checkstatus tagtrack-$UTRACKNUM; then
4473 if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
4474 fi
4475 fi
4476 ) &
4477 done
4478
4479
4480 # Go through it again and make sure there's no distmp3 stragglers, otherwise
4481 # we'll delete the files they're working on
4482 # Do NOT play ball if there is no ball to play (so ABORT if needed)
4483 ## FIXME ## Check also for files which are encoded using PIPEs.
4484 if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ] && [ ! "$ABORT" ]; then
4485 PROCEED=
4486 until [ $PROCEED ]
4487 do
4488 PROCEED=y
4489 for LOCATION in $ENCODELOCATIONS
4490 do
4491 CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
4492 # "How can he give us a status update, if he's DEAD?"
4493 if checkstatus encodetrack-$CHECKTRACK; then
4494 continue
4495 fi
4496 # Nothing to see here please go quietly back to your homes
4497 if [ -z "$CHECKTRACK" ]; then continue; fi
4498 # You're still here? Maybe there is something...
4499 if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
4500 done
4501 # hold up
4502 if [ ! $PROCEED ]; then sleep 5; fi
4503 done
4504 fi
4505 # If the above didn't catch the stragglers, this will
4506 wait
4507 if [ "$DOREPLAYGAIN" = "y" ]; then
4508 do_replaygain
4509 fi
4510
4511 # Execute the user-defined post_encode function before cleaning up
4512 post_encode
4513
4514 # Check to see if run_command logged any errors
4515 if [ -f "$ABCDETEMPDIR/errors" ]; then
4516 log error "The following commands failed to run:"
4517 cat "$ABCDETEMPDIR/errors"
4518 # Don't clean up
4519 DOCLEAN=n
4520 fi
4521 if [ "$KEEPWAVS" = "y" ];then
4522 # Don't clean up
4523 DOCLEAN=n
4524 fi
4525 # Check if we have moved all the formats we had previously encoded, if we are not using the FORCE.
4526 if [ "$DOCLEAN" = "y" ] && [ ! "$FORCE" = "y" ]; then
4527 ENCODED_FORMATS=$(grep -E "^encodetrack-(.{3,6})-(.{1,2})$" "$ABCDETEMPDIR/status" | cut -d"-" -f2 | sort -u | tr '\n' '|')
4528 MOVED_FORMATS=$(grep -E "^movetrack-output-(.{3,6})$" "$ABCDETEMPDIR/status" | cut -d"-" -f3 | sort -u | tr '\n' '|')
4529 if [ "$ENCODED_FORMATS" != "$MOVED_FORMATS" ]; then
4530 log warning "The encoded formats does not match with the moved ones"
4531 log warning "Formats encoded: $( echo $ENCODED_FORMATS | tr "|" " " )"
4532 log warning "Formats moved: $( echo $MOVED_FORMATS | tr "|" " " )"
4533 log warning "Use \"abcde -a clean -f -C $DISCID\" to force the removal of the remaining data."
4534 DOCLEAN=n
4535 fi
4536 fi
4537 if [ "$DOCLEAN" = "y" ]; then
4538 # Wipe all the evidence
4539 # Gimme gimme gimme some more time!
4540 sleep 5
4541 rm -rf "$ABCDETEMPDIR"
4542 echo "Finished."
4543 else
4544 echo "Finished. Not cleaning $ABCDETEMPDIR."
4545 fi
4546 )
4547 exit 0
4548
4549 # b:is_bash
4550 # vim:tabstop=4