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