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