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