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