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