Recursive CDDB local dir 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 cat "$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=$X
1661 if [ "$INTERACTIVE" = "y" ]; then
1662 while [ $CDDBLOCALCHOICENUM -lt 0 ] || [ $CDDBLOCALCHOICENUM -gt $CDDBLOCALCHOICES ]; do
1663 echo -n "Locally cached CDDB entries found. Which one would you like to use (0 for none)? [0-$CDDBLOCALCHOICES]: " >&2
1664 read CDDBLOCALRESP
1665 [ x"$CDDBLOCALRESP" = "x" ] && CDDBLOCALRESP="1"
1666 done
1667 else
1668 ### FIXME ###
1669 echo "Selected ..."
1670 CDDBLOCALRESP=y
1671 fi
1672 if [ ! "$CDDBLOCALRESP" = "0" ]; then
1673 #echo "Using local copy of CDDB data"
1674 echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1"
1675 cat "$ABCDETEMPDIR/cddblocalread.$CDDBLOCALRESP" >> "$ABCDETEMPDIR/cddbread.1"
1676 echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
1677 echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
1678 do_cddbparse "$ABCDETEMPDIR/cddbread.1" > "$ABCDETEMPDIR/cddbchoices"
1679 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1680 CDDBLOCALSTATUS="found"
1681 else
1682 #echo "Not using local copy of CDDB data"
1683 CDDBLOCALSTATUS="notfound"
1684 fi
1685 ;;
1686 single)
1687 # List out disc title/author and contents
1688 do_cddbparse "${CDDBLOCALFILE}"
1689 echo -n "Locally cached CDDB entry found, use it? [y/n] (y): " >&2
1690 if [ "$INTERACTIVE" = "y" ]; then
1691 read USELOCALRESP
1692 while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
1693 echo -n 'Invalid selection. Please answer "y" or "n": ' >&2
1694 read USELOCALRESP
1695 done
1696 [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
1697 else
1698 echo "y" >&2
1699 fi
1700 if [ "$USELOCALRESP" = "y" ]; then
1701 #echo "Using local copy of CDDB data"
1702 echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1"
1703 cat "${CDDBLOCALFILE}" >> "$ABCDETEMPDIR/cddbread.1"
1704 echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
1705 echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
1706 do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
1707 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1708 CDDBLOCALSTATUS="single"
1709 else
1710 #echo "Not using local copy of CDDB data"
1711 CDDBLOCALSTATUS="notfound"
1712 fi
1713 ;;
1714 none)
1715 CDDBLOCALSTATUS="notfound"
1716 ;;
1717 esac
1718 fi
1719 }
1720
1721 do_musicbrainzstat ()
1722 {
1723 :
1724 }
1725
1726 do_musizbrainz ()
1727 {
1728 :
1729 }
1730
1731 # do_cddbstat
1732 do_cddbstat ()
1733 {
1734 # Perform CDDB protocol version check if it hasn't already been done
1735 if checkstatus cddb-statcomplete; then :; else
1736 if [ "$CDDBAVAIL" = "n" ]; then
1737 ERRORCODE=no_query
1738 echo 503 > "$ABCDETEMPDIR/cddbstat"
1739 else
1740 rc=1
1741 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1742 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1743 while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
1744 vecho "Checking CDDB server status..."
1745 $CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
1746 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
1747 case "$RESPONSECODE" in
1748 210) # 210 OK, status information follows (until terminating `.')
1749 rc=0;
1750 ;;
1751 501|*) # 501 Illegal CDDB protocol level: <n>.
1752 CDDBPROTO=`expr $CDDBPROTO - 1`
1753 ;;
1754 esac
1755 done
1756 if test $rc -eq 1; then
1757 CDDBAVAIL="n"
1758 fi
1759 fi
1760 echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
1761 fi
1762 }
1763
1764
1765 # do_cddbquery
1766 do_cddbquery ()
1767 {
1768 CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
1769 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
1770
1771 # Perform CDDB query if it hasn't already been done
1772 if checkstatus cddb-querycomplete; then :; else
1773 if [ "$CDDBAVAIL" = "n" ]; then
1774 ERRORCODE=no_query
1775 echo 503 > "$ABCDETEMPDIR/cddbquery"
1776 # The default CDDBLOCALSTATUS is "notfound"
1777 # This part will be triggered if the user CDDB repo does not
1778 # contain the entry, or if we are not trying to use the repo.
1779 else
1780 vecho "Querying the CDDB server..."
1781 CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
1782 CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
1783 $CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
1784 ERRORCODE=$?
1785 case $ERRORCODE in
1786 0) # success
1787 ;;
1788 12|13|14)
1789 # no match found in database,
1790 # wget/fetch error, or user requested not to use CDDB
1791 # Make up an error code (503) that abcde
1792 # will recognize in do_cddbread
1793 # and compensate by making a template
1794 echo 503 > "$ABCDETEMPDIR/cddbquery"
1795 ;;
1796 *) # strange and unknown error
1797 echo ERRORCODE=$ERRORCODE
1798 echo "abcde: $CDDBTOOL returned unknown error code"
1799 ;;
1800 esac
1801 fi
1802 echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
1803 fi
1804 }
1805
1806 # do_cddbread
1807 do_cddbread ()
1808 {
1809 # If it's not to be used, generate a template.
1810 # Then, display it (or them) and let the user choose/edit it
1811 if checkstatus cddb-readcomplete; then :; else
1812 vecho "Obtaining CDDB results..."
1813 # If CDDB is to be used, interpret the query results and read all
1814 # the available entries.
1815 rm -f "$ABCDETEMPDIR/cddbchoices"
1816 CDDBCHOICES=1 # Overridden by multiple matches
1817 RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
1818 case "$RESPONSECODE" in
1819 200)
1820 # One exact match, retrieve it
1821 # 200 [section] [discid] [artist] / [title]
1822 if checkstatus cddb-read-1-complete; then :; else
1823 echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
1824 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
1825 echo "done." >> "$ABCDETEMPDIR/cddbchoices"
1826 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1827 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1828 fi
1829 # List out disc title/author and contents
1830 echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
1831 for TRACK in $(f_seq_row 1 $TRACKS)
1832 do
1833 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1834 done
1835 echo >> "$ABCDETEMPDIR/cddbchoices"
1836 ;;
1837 202|403|409|503)
1838 # No match
1839 case "$RESPONSECODE" in
1840 202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
1841 403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
1842 503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
1843 esac
1844 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
1845 # List out disc title/author and contents of template
1846 echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
1847 UNKNOWNDISK=y
1848 for TRACK in $(f_seq_row 1 $TRACKS)
1849 do
1850 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1851 done
1852 echo >> "$ABCDETEMPDIR/cddbchoices"
1853 echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
1854 echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
1855 ;;
1856 210|211)
1857 # Multiple exact, (possibly multiple) inexact matches
1858 IN=
1859 if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
1860 if [ "$(wc -l < "$ABCDETEMPDIR/cddbquery" | tr -d ' ')" -eq 3 ]; then
1861 echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
1862 tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
1863 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1864 else
1865 echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
1866 fi
1867 vecho -n "Retrieving multiple matches... "
1868 grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
1869 read DISCINFO # eat top line
1870 while read DISCINFO
1871 do
1872 X=$(expr $X + 1)
1873 if checkstatus cddb-read-$X-complete; then :; else
1874 $CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
1875 echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
1876 fi
1877 # List out disc title/author and contents
1878 echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
1879 for TRACK in $(f_seq_row 1 $TRACKS)
1880 do
1881 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1882 done
1883 echo >> "$ABCDETEMPDIR/cddbchoices"
1884 done )
1885 vecho "done."
1886 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1887 ;;
1888 999)
1889 # Using local copy.
1890 for TRACK in $(f_seq_row 1 $TRACKS)
1891 do
1892 echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
1893 done
1894 echo >> "$ABCDETEMPDIR/cddbchoices"
1895 echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
1896 echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
1897 ;;
1898 esac
1899 echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
1900 fi
1901 }
1902
1903 # do_cddbedit
1904 do_cddbedit ()
1905 {
1906 if checkstatus cddb-edit >/dev/null; then
1907 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
1908 VARIOUSARTISTS="$(checkstatus variousartists)"
1909 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
1910 return 0
1911 fi
1912 if [ "$INTERACTIVE" = "y" ]; then
1913 # We should show the CDDB results both when we are not using the local CDDB repo
1914 # or when we are using it but we could not find a proper match
1915 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
1916 # Display the $ABCDETEMPDIR/cddbchoices file created above
1917 # Pick a pager so that if the tracks overflow the screen the user can still view everything
1918 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
1919 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
1920 CHOICE=$(checkstatus cddb-choice)
1921 if [ -n "$CHOICE" ] ; then
1922 case $CDDBCHOICES in
1923 -1) if head -1 "$ABCDETEMPDIR/cddbquery" | grep -q "^$" ; then
1924 log error "CDDB query failed!"
1925 exit 1
1926 else
1927 cat "$ABCDETEMPDIR/cddbchoices"
1928 fi
1929 ;;
1930 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
1931 *)
1932 echo "Selected: #$CHOICE"
1933 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
1934 ;;
1935 esac
1936 else
1937 # The user has a choice to make, display the info in a pager if necessary
1938 if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
1939 page "$ABCDETEMPDIR/cddbchoices"
1940 else
1941 # It's all going to fit in one page, cat it
1942 cat "$ABCDETEMPDIR/cddbchoices" >&2
1943 fi
1944
1945 CDDBCHOICENUM=""
1946 # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
1947 CDCHOICENUM=-1
1948 # I'll take CDDB read #3 for $400, Alex
1949 while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
1950 echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
1951 read CDDBCHOICE
1952 [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
1953 if echo $CDDBCHOICE | egrep -q "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" ; then
1954 if [ ! X"$DIFF" = "X" ]; then
1955 PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
1956 PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
1957 if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
1958 [ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
1959 [ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then
1960 echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBCHOICES" >&2
1961 else
1962 # We parse the 2 choices to diff, store them in temporary files and diff them.
1963 for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
1964 do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE"
1965 done
1966 echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/cddbread.diff"
1967 $DIFF $DIFFOPTS "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/cddbread.diff"
1968 if [ $(cat "$ABCDETEMPDIR/cddbread.diff" | wc -l) -ge 24 ]; then
1969 page "$ABCDETEMPDIR/cddbread.diff"
1970 else
1971 cat "$ABCDETEMPDIR/cddbread.diff" >&2
1972 fi
1973 fi
1974 else
1975 echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2
1976 fi
1977 elif echo $CDDBCHOICE | egrep -q "[[:space:]]*[[:digit:]]+[[:space:]]*" ; then
1978 # Make sure we get a valid choice
1979 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
1980 if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then
1981 echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2
1982 fi
1983 fi
1984 done
1985 if [ "$CDCHOICENUM" = "0" ]; then
1986 vecho "Creating empty CDDB template..."
1987 UNKNOWNDISK=y
1988 $CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
1989 else
1990 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
1991 do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
1992 fi
1993 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
1994 fi
1995 fi
1996 else
1997 # We need some code to show the selected option when local repository is selected and we have found a match
1998 vecho "Using cached CDDB match..." >&2
1999 # Display the $ABCDETEMPDIR/cddbchoices file created above
2000 # Pick a pager so that if the tracks overflow the screen the user can still view everything
2001 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2002 CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
2003 CHOICE=$(checkstatus cddb-choice)
2004 if [ "$USELOCALRESP" = "y" ]; then :; else
2005 if [ -n "$CHOICE" ] ; then
2006 case $CDDBCHOICES in
2007 0)
2008 UNKNOWNDISK=y
2009 echo "Selected template."
2010 ;;
2011 1) cat "$ABCDETEMPDIR/cddbchoices" ;;
2012 *)
2013 echo "Selected: #$CHOICE"
2014 do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
2015 ;;
2016 esac
2017 fi
2018 fi
2019 fi
2020 fi
2021 else
2022 # We're noninteractive - pick the first choice.
2023 # But in case we run a previous instance and selected a choice, use it.
2024 if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
2025 # Show the choice if we are not using the locally stored one
2026 # or when the local search failed to find a match.
2027 PREVIOUSCHOICE=$(checkstatus cddb-choice)
2028 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2029 #if [ "$PREVIOUSCHOICE" ]; then
2030 cat "$ABCDETEMPDIR/cddbchoices"
2031 #fi
2032 fi
2033 if [ ! -z "$PREVIOUSCHOICE" ] ; then
2034 CDCHOICENUM=$PREVIOUSCHOICE
2035 else
2036 CDCHOICENUM=1
2037 echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
2038 fi
2039 echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
2040 fi
2041 fi
2042
2043 # sanity check
2044 if checkstatus cddb-choice >/dev/null; then :; else
2045 echo "abcde: internal error: cddb-choice not recorded." >&2
2046 exit 1
2047 fi
2048 CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
2049 echo -n "Edit selected CDDB data? [y/n] (" >&2
2050 if [ "$INTERACTIVE" = "y" ]; then
2051 if [ "$UNKNOWNDISK" = "y" ]; then
2052 echo -n "y): " >&2
2053 read EDITCDDB
2054 [ "$EDITCDDB" != "n" ] && EDITCDDB=y
2055 else
2056 echo -n "n): " >&2
2057 read EDITCDDB
2058 fi
2059 else
2060 echo "n): n" >&2
2061 EDITCDDB=n
2062 fi
2063 if [ "$EDITCDDB" = "y" ]; then
2064 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
2065
2066 # Use the debian sensible-editor wrapper to pick the editor that the
2067 # user has requested via their $EDITOR environment variable
2068 if [ -x "/usr/bin/sensible-editor" ]; then
2069 /usr/bin/sensible-editor "$CDDBDATA"
2070 elif [ -n "$EDITOR" ]; then
2071 if [ -x $(which "${EDITOR%%\ *}") ]; then
2072 # That failed, try to load the preferred editor, starting
2073 # with their EDITOR variable
2074 eval $(echo "$EDITOR") \"$CDDBDATA\"
2075 fi
2076 # If that fails, check for a vi
2077 elif which vi >/dev/null 2>&1; then
2078 vi "$CDDBDATA"
2079 elif [ -x /usr/bin/vim ]; then
2080 /usr/bin/vim "$CDDBDATA"
2081 elif [ -x /usr/bin/vi ]; then
2082 /usr/bin/vi "$CDDBDATA"
2083 elif [ -x /bin/vi ]; then
2084 /bin/vi "$CDDBDATA"
2085 # nano should be on all (modern, i.e., sarge) debian systems
2086 elif which nano >/dev/null 2>&1 ; then
2087 nano "$CDDBDATA"
2088 elif [ -x /usr/bin/nano ]; then
2089 /usr/bin/nano "$CDDBDATA"
2090 # mg should be on all OpenBSD systems
2091 elif which mg >/dev/null 2>&1 ; then
2092 mg "$CDDBDATA"
2093 elif [ -x /usr/bin/mg ]; then
2094 /usr/bin/mg "$CDDBDATA"
2095 # bomb out
2096 else
2097 log warning "no editor available. Check your EDITOR environment variable."
2098 fi
2099 # delete editor backup file if it exists
2100 if [ -w "$CDDBDATA~" ]; then
2101 rm -f "$CDDBDATA~"
2102 fi
2103 fi
2104
2105 # Some heuristics first. Look at Disc Title, and if it starts with
2106 # "Various", then we'll assume Various Artists
2107 if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2- -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
2108 echo "Looks like a Multi-Artist CD" >&2
2109 VARIOUSARTISTS=y
2110 else
2111 echo -n "Is the CD multi-artist? [y/n] (n): " >&2
2112 if [ "$INTERACTIVE" = "y" ]; then
2113 read VARIOUSARTISTS
2114 else
2115 echo n >&2
2116 VARIOUSARTISTS=n
2117 fi
2118 fi
2119 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
2120 # Set a default
2121 DEFAULTSTYLE=1
2122 # Need NUMTRACKS before cddb-tool will return it:
2123 NUMTRACKS=$(egrep '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
2124 if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2125 # More than 1/2 tracks contain a "/", so guess forward
2126 DEFAULTSTYLE=1
2127 elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2128 # More than 1/2 contain a "-", so guess forward-dash
2129 DEFAULTSTYLE=2
2130 elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
2131 # More than 1/2 contain something in parens, so guess trailing-paren
2132 DEFAULTSTYLE=6
2133 fi
2134
2135 echo "1) Artist / Title" >&2
2136 echo "2) Artist - Title" >&2
2137 echo "3) Title / Artist" >&2
2138 echo "4) Title - Artist" >&2
2139 echo "5) Artist: Title" >&2
2140 echo "6) Title (Artist)" >&2
2141 echo "7) This is a single-artist CD" >&2
2142 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
2143 if [ "$INTERACTIVE" = "y" ]; then
2144 read VARIOUSARTISTSTYLE
2145 else
2146 echo $DEFAULTSTYLE >&2
2147 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2148 fi
2149 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2150 # If they press Enter, then the default style (0) was chosen
2151 while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
2152 echo "Invalid selection. Please choose a number between 1 and 7."
2153 echo -n "Selection [1-7]: "
2154 read VARIOUSARTISTSTYLE
2155 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
2156 done
2157 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
2158 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
2159 fi
2160 vecho "Selected: $VARIOUSARTISTSTYLE"
2161 case "$VARIOUSARTISTSTYLE" in
2162 1) # Artist / Title
2163 VARIOUSARTISTSTYLE=forward
2164 ;;
2165 2) # Artist - Title
2166 VARIOUSARTISTSTYLE=forward-dash
2167 ;;
2168 3) # Title / Artist
2169 VARIOUSARTISTSTYLE=reverse
2170 ;;
2171 4) # Title - Artist
2172 VARIOUSARTISTSTYLE=reverse-dash
2173 ;;
2174 5) # Artist: Title
2175 VARIOUSARTISTSTYLE=colon
2176 ;;
2177 6) # Title (Artist)
2178 VARIOUSARTISTSTYLE=trailing-paren
2179 ;;
2180 7) # Single Artist
2181 VARIOUSARTISTS=n
2182 ;;
2183 esac
2184 fi
2185
2186 echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
2187 echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
2188
2189 if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
2190 if [ "$CDDBDATAMD5SUM" != "" ] && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
2191 # This works but does not have the necessary error checking
2192 # yet. If you are familiar with the CDDB spec
2193 # (see http://www.freedb.org/src/latest/DBFORMAT)
2194 # and can create an error-free entry on your own, then put
2195 # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
2196 # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
2197 # your abcde.conf to change the email address submissions are
2198 # sent to.
2199
2200 # submit the modified file, if they want
2201 if [ "$NOSUBMIT" != "y" ]; then
2202 echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
2203 read YESNO
2204 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
2205 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
2206 do
2207 echo -n 'Invalid selection. Please answer "y" or "n": '
2208 read YESNO
2209 done
2210 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
2211 echo -n "Sending..."
2212 $CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
2213 echo "done."
2214 fi
2215 fi
2216 fi
2217 fi
2218 ### FIXME ###
2219 # User CDDBLOCALPOLICY to find out if we store the file or not...
2220 # Cache edited CDDB entry in the user's cddb dir
2221 if [ "$CDDBCOPYLOCAL" = "y" ]; then
2222 # Make sure the cache directory exists
2223 mkdir -p $CDDBLOCALDIR
2224 cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
2225 fi
2226
2227 echo "cddb-edit" >> "$ABCDETEMPDIR/status"
2228 }
2229
2230 # do_cdread [tracknumber]
2231 # do_cdread onetrack [firsttrack] [lasttrack]
2232 #
2233 do_cdread ()
2234 {
2235 # The commands here don't go through run_command because they're never supposed to be silenced
2236 # return codes need to be doublechecked anyway, however
2237 if [ "$1" = "onetrack" ]; then
2238 # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
2239 # FIXME # Until then, we grab the whole CD in one track, no matter what
2240 # the user said
2241 # We need the first and last track for cdda2wav
2242 FIRSTTRACK=$2
2243 LASTTRACK=$3
2244 UTRACKNUM=$FIRSTTRACK
2245 case "$CDROMREADERSYNTAX" in
2246 flac) READTRACKNUMS="$FIRSTTRACK.1-$(($LASTTRACK + 1)).0" ;;
2247 cdparanoia) READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
2248 cdda2wav) READTRACKNUMS="$FIRSTTRACK+$LASTRACK" ;;
2249 *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
2250 exit 1 ;;
2251 esac
2252 else
2253 UTRACKNUM=$1
2254 fi
2255 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
2256 if [ "$USEPIPES" = "y" ]; then
2257 TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
2258 FILEARG="$( eval echo "\$$TEMPARG" )"
2259 REDIR=""
2260 PIPE_MESSAGE="and encoding "
2261 else
2262 WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
2263 case "$CDROMREADERSYNTAX" in
2264 ## FIXME ## Find the cases for dagrab and flac, to avoid exceptions
2265 flac)
2266 FILEARG="--output-name=$WAVDATA"
2267 ;;
2268 dagrab)
2269 FILEARG="-f $WAVDATA"
2270 ;;
2271 *)
2272 FILEARG="$WAVDATA"
2273 ;;
2274 esac
2275 REDIR=">&2"
2276 fi
2277 if [ "$1" = "onetrack" ]; then
2278 echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
2279 else
2280 if [ -r "$CDDBDATA" ]; then
2281 do_getcddbinfo TRACKNAME
2282 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
2283 else
2284 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
2285 fi
2286 fi
2287 case "$CDROMREADERSYNTAX" in
2288 ### FIXME ### use an exception for flac, since it uses -o
2289 ### FIXME ### Shall we just use -o $FILEARG ??
2290 flac)
2291 nice $READNICE $FLAC -d --cue=${READTRACKNUMS:-$UTRACKNUM.1-$(($UTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;;
2292 cdparanoia)
2293 echo "nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;" > /tmp/log
2294 nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;
2295 cdda2wav)
2296 if [ "$OSFLAVOUR" = "OSX" ] ; then
2297 # Hei, we have to unmount the device before running anything like cdda2wav in OSX
2298 disktool -u ${CDROM#/dev/} 0
2299 # Also, in OSX the cdrom device for cdda2wav changes...
2300 CDDA2WAVCDROM="IODVDServices"
2301 elif [ "$OSFLAVOUR" = "FBSD" ] ; then
2302 CDDA2WAVCDROM="$CDROMID"
2303 else
2304 if [ "$CDROMID" = "" ]; then
2305 CDDA2WAVCDROM="$CDROM"
2306 else
2307 CDDA2WAVCDROM="$CDROMID"
2308 fi
2309 fi
2310 nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR
2311 ;;
2312 ## FIXME ## We have an exception for dagrab, since it uses -f
2313 ## FIXME ## Shall we just use -f $FILEARG ??
2314 dagrab) nice $READNICE $CDROMREADER -d $CDROM -v $UTRACKNUM "$FILEARG" $REDIR
2315 ;;
2316 cddafs)
2317 # Find the track's mounted path
2318 REALTRACKNUM=$(expr $UTRACKNUM + 0)
2319 FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
2320 FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
2321 # If the file exists, copy it
2322 if [ -e "$FILEPATH" ] ; then
2323 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" $REDIR
2324 else
2325 false
2326 fi ;;
2327 debug) nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS $CDROM -w $UTRACKNUM-[:1] "$FILEARG" $REDIR
2328 ;;
2329 esac
2330 RETURN=$?
2331 # If we get some error or we get some missing wav
2332 # (as long as we dont use pipes)
2333 if [ "$RETURN" != "0" -o \( ! -s "$WAVDATA" -a X"$USEPIPES" != "Xy" \) ]; then
2334 # Thank goodness errors is only machine-parseable up to the
2335 # first colon, otherwise this woulda sucked
2336 if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
2337 RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
2338 fi
2339 if [ "$USEPIPES" = "y" ]; then
2340 echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2341 else
2342 echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
2343 fi
2344 return $RETURN
2345 else
2346 if [ "$USEPIPES" = "y" ]; then
2347 echo readencodetrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2348 else
2349 echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
2350 if [ "$1" = "onetrack" ]; then
2351 echo onetrack >> "$ABCDETEMPDIR/status"
2352 fi
2353 fi
2354 fi
2355 }
2356
2357 # do_cdspeed
2358 # No values accepted, only uses env variables
2359 do_cdspeed ()
2360 {
2361 if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
2362 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
2363 else
2364 echo "abcde: unable to set the device speed" >&2
2365 fi
2366 }
2367
2368 # vecho [message]
2369 #
2370 # vecho outputs a message if EXTRAVERBOSE is selected
2371 vecho ()
2372 {
2373 if [ x"$EXTRAVERBOSE" != "x" ]; then
2374 case $1 in
2375 warning) log warning "$@" ;;
2376 *) echo "$@" ;;
2377 esac
2378 fi
2379 }
2380
2381 # decho [message]
2382 #
2383 # decho outputs a debug message if DEBUG is selected
2384 decho ()
2385 {
2386 if [ x"$DEBUG" != "x" ]; then
2387 if echo $1 | grep -q "^\[" ; then
2388 DEBUGECHO=$(echo "$@" | tr -d '[]')
2389 echo "[DEBUG] $DEBUGECHO: `eval echo \\$${DEBUGECHO}`"
2390 else
2391 echo "[DEBUG] $1"
2392 fi
2393 fi
2394 }
2395
2396 # User-redefinable functions
2397 # Custom filename munging:
2398 mungefilename ()
2399 {
2400 #echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
2401 echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
2402 }
2403
2404 # Custom genre munging:
2405 mungegenre ()
2406 {
2407 echo $CDGENRE | tr "[:upper:]" "[:lower:]"
2408 }
2409
2410 # pre_read
2411 # Empty pre_read function, to be defined in the configuration file.
2412 pre_read ()
2413 {
2414 :
2415 }
2416
2417 # post_read
2418 # Empty post_read function, to be defined in the configuration file.
2419 post_read ()
2420 {
2421 :
2422 }
2423
2424 ###############################################################################
2425 # End of functions
2426 #
2427 # Start of execution
2428 ###############################################################################
2429
2430 # Builtin defaults
2431
2432 # CDDB
2433 # Defaults to FreeDB, but a python musicbrainz can be used
2434 CDDBMETHOD=cddb
2435 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
2436 CDDBSUBMIT=freedb-submit@freedb.org
2437 CDDBPROTO=5
2438 HELLOINFO="$(whoami)@$(hostname)"
2439 CDDBCOPYLOCAL="n"
2440 CDDBLOCALPOLICY="always"
2441 CDDBLOCALRECURSIVE="y"
2442 CDDBLOCALDIR="$HOME/.cddb"
2443 CDDBUSELOCAL="n"
2444
2445 # List of fields we parse and show during the CDDB parsing...
2446 SHOWCDDBFIELDS="year,genre"
2447
2448 INTERACTIVE=y
2449 #CDROMREADERSYNTAX=cdparanoia
2450 ENCODERSYNTAX=default
2451
2452 MP3ENCODERSYNTAX=default
2453 OGGENCODERSYNTAX=default
2454 FLACENCODERSYNTAX=default
2455 SPEEXENCODERSYNTAX=default
2456 MPPENCODERSYNTAX=default
2457 AACENCODERSYNTAX=default
2458 NORMALIZERSYNTAX=default
2459 CUEREADERSYNTAX=default
2460
2461 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
2462 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
2463 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
2464 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
2465 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
2466 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
2467 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2468 PLAYLISTDATAPREFIX=''
2469 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
2470 VAPLAYLISTDATAPREFIX=''
2471 DOSPLAYLIST=n
2472 COMMENT=''
2473 ID3TAGV=2
2474 ENCNICE=10
2475 READNICE=10
2476 DISTMP3NICE=10
2477 VARIOUSARTISTS=n
2478 VARIOUSARTISTSTYLE=forward
2479 KEEPWAVS=n
2480 PADTRACKS=n
2481 NOGAP=n
2482 BATCHNORM=n
2483
2484 # If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
2485 # i.e. CDROMID="1,0,0"
2486 CDROMID=""
2487 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
2488 # If we are using the ide-scsi emulation layer, we need to define a "g"
2489 CDPARANOIACDROMBUS="d"
2490
2491 # program paths - defaults to checking your $PATH
2492 # mp3
2493 LAME=lame
2494 TOOLAME=toolame
2495 GOGO=gogo
2496 BLADEENC=bladeenc
2497 L3ENC=l3enc
2498 XINGMP3ENC=xingmp3enc
2499 MP3ENC=mp3enc
2500 # ogg
2501 VORBIZE=vorbize
2502 OGGENC=oggenc
2503 # flac
2504 FLAC=flac
2505 # speex
2506 SPEEXENC=speexenc
2507 # mpp (Musepack)
2508 MPPENC=mppenc
2509 # m4a
2510 AACENC=faac
2511
2512 ID3=id3
2513 ID3V2=id3v2
2514 EYED3=eyeD3
2515 CDPARANOIA=cdparanoia
2516 CDDA2WAV=cdda2wav
2517 DAGRAB=dagrab
2518 CDDAFS=cp
2519 CDDISCID=cd-discid
2520 CDDBTOOL=cddb-tool
2521 MUSICBRAINZ=musicbrainz-get-tracks
2522 EJECT=eject
2523 MD5SUM=md5sum
2524 DISTMP3=distmp3
2525 VORBISCOMMENT=vorbiscomment
2526 METAFLAC=metaflac
2527 NORMALIZE=normalize-audio
2528 CDSPEED=eject
2529 VORBISGAIN=vorbisgain
2530 MP3GAIN=mp3gain
2531 MPPGAIN=replaygain
2532 MKCUE=mkcue
2533 MKTOC=cdrdao
2534 DIFF=diff
2535 CUE2DISCID=cue2discid
2536
2537 # Options for programs called from abcde
2538 # mp3
2539 LAMEOPTS=
2540 TOOLAMEOPTS=
2541 GOGOOPTS=
2542 BLADEENCOPTS=
2543 L3ENCOPTS=
2544 XINGMP3ENCOPTS=
2545 MP3ENCOPTS=
2546 # ogg
2547 VORBIZEOPTS=
2548 OGGENCOPTS=
2549 # flac
2550 FLACOPTS=
2551 # speex
2552 SPEEXENCOPTS=
2553 # mpc
2554 MPPENCOPTS=
2555 # m4a
2556 AACENCOPTS=
2557
2558 ID3OPTS=
2559 ID3V2OPTS=
2560 CDPARANOIAOPTS=
2561 CDDA2WAVOPTS=
2562 DAGRABOPTS=
2563 CDDAFSOPTS="-f"
2564 CDDBTOOLOPTS=
2565 EJECTOPTS=
2566 DISTMP3OPTS=
2567 NORMALIZEOPTS=
2568 CDSPEEDOPTS="-x"
2569 CDSPEEDVALUE=
2570 MKCUEOPTS=
2571 MKTOCOPTS=""
2572 VORBISCOMMENTOPTS="-R"
2573 METAFLACOPTS="--no-utf8-convert"
2574 DIFFOPTS=
2575
2576 # Default to one process if -j isn't specified
2577 MAXPROCS=1
2578
2579 # List of actions to perform - by default, run to completion
2580 ACTIONS=cddb,read,encode,tag,move,clean
2581
2582 # This option is basicaly for Debian package dependencies:
2583 # List of prefered outputs - by default, run with whatever we have in the path
2584 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:lame,mp3:bladeenc,spx:speex
2585
2586 # List of prefered cdromreaders - by default, run whichever we have in the path
2587 DEFAULT_CDROMREADERS="cdparanoia cdda2wav"
2588
2589 # Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for Linux/OpenBSD/NetBSD.
2590 # Let's use these checkings to determine the OS flavour, which will be used later
2591 if [ X$(uname) = "XFreeBSD" ] ; then
2592 HTTPGET=fetch
2593 MD5SUM=md5
2594 NEEDCDROMID=y
2595 OSFLAVOUR=FBSD
2596 elif [ X$(uname) = "XDarwin" ] ; then
2597 HTTPGET=curl
2598 OSFLAVOUR=OSX
2599 # We should have disktool in OSX, but let's be sure...
2600 NEEDDISKTOOL=y
2601 CDROMREADERSYNTAX=cddafs
2602 elif [ X$(uname) = "XOpenBSD" ] ; then
2603 HTTPGET=wget
2604 MD5SUM=md5
2605 elif [ X$(uname) = "XNetBSD" ] ; then
2606 HTTPGET=ftp
2607 MD5SUM=md5
2608 else
2609 HTTPGET=wget
2610 fi
2611
2612 # If CDDBAVAIL is set to n, no CDDB read is done
2613 # If USEID3 is set to n, no ID3 tagging is done
2614 CDDBAVAIL=y
2615 USEID3=y
2616 USEID3V2=y
2617
2618 if [ -z "$OUTPUTDIR" ]; then
2619 OUTPUTDIR=$(pwd)
2620 fi
2621
2622 if [ -z "$WAVOUTPUTDIR" ]; then
2623 WAVOUTPUTDIR="$OUTPUTDIR"
2624 fi
2625
2626 # Load system defaults
2627 if [ -r /etc/abcde.conf ]; then
2628 . /etc/abcde.conf
2629 fi
2630 # Load user preference defaults
2631 if [ -r $HOME/.abcde.conf ]; then
2632 . $HOME/.abcde.conf
2633 fi
2634
2635 # By this time, we need some HTTPGETOPTS already defined.
2636 # If the user has defined a non-default HTTPGET method, we should not be empty.
2637
2638 if [ "$HTTPGETOPTS" = "" ] ; then
2639 case $HTTPGET in
2640 wget) HTTPGETOPTS="-q -O -";;
2641 curl) HTTPGETOPTS="-f -s";;
2642 fetch)HTTPGETOPTS="-q -o -";;
2643 ftp) HTTPGETOPTS="-q -o -";;
2644 *) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
2645 esac
2646 fi
2647
2648 # If the CDROM has not been set yet, find a suitable one.
2649 # If this is a devfs system, default to /dev/cdroms/cdrom0
2650 # instead of /dev/cdrom
2651 if [ "$CDROM" = "" ] ; then
2652 if [ -e /dev/cdroms/cdrom0 ]; then
2653 CDROM=/dev/cdroms/cdrom0
2654 elif [ -e /dev/cdrom ]; then
2655 CDROM=/dev/cdrom
2656 elif [ -e /dev/cd0c ]; then
2657 CDROM=/dev/cd0c
2658 elif [ -e /dev/acd0c ]; then
2659 CDROM=/dev/acd0c
2660 elif [ -e /dev/disk1 ]; then
2661 CDROM=/dev/disk1
2662 fi
2663 fi
2664
2665 # Parse command line options
2666 #while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPr:Rs:S:t:T:vVxw:W: opt ; do
2667 while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPr:s:S:t:T:uvVxw:W:z opt ; do
2668 case "$opt" in
2669 1) ONETRACK=y ;;
2670 a) ACTIONS="$OPTARG" ;;
2671 A) EXPACTIONS="$OPTARG" ;;
2672 b) BATCHNORM=y ;;
2673 B) NOBATCHREPLAYGAIN=y ;;
2674 c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
2675 C) DISCID="$( echo ${OPTARG#abcde.} | tr -d /)" ;;
2676 d) CDROM="$OPTARG" ;;
2677 D) set -x ;;
2678 e) ERASEENCODEDSTATUS=y ;;
2679 h) usage; exit ;;
2680 e) ERASEENCODEDSTATUS=y ;;
2681 E) ENCODING="$OPTARG" ;;
2682 f) FORCE=y ;;
2683 g) NOGAP=y ;;
2684 i) INLINETAG=y ;;
2685 j) MAXPROCS="$OPTARG" ;;
2686 k) KEEPWAVS=y ;;
2687 l) LOWDISK=y ;;
2688 L) CDDBUSELOCAL=y ;;
2689 n) CDDBAVAIL=n ;;
2690 N) INTERACTIVE=n ;;
2691 m) DOSPLAYLIST=y ;;
2692 M) MAKECUEFILE=y ;;
2693 o) OUTPUTTYPE="$OPTARG" ;;
2694 p) PADTRACKS=y ;;
2695 P) USEPIPES=y ;;
2696 r) REMOTEHOSTS="$OPTARG" ;;
2697 R) DOREPLAYGAIN=y ;;
2698 s) SHOWCDDBFIELDS="$OPTARG" ;;
2699 S) CDSPEEDVALUE="$OPTARG" ;;
2700 t) STARTTRACKNUMBER="$OPTARG" ;;
2701 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
2702 u) CDDBPROTO=6 ;;
2703 v)
2704 echo "This is abcde v$VERSION."
2705 echo "Usage: abcde [options] [tracks]"
2706 echo "abcde -h for extra help"
2707 exit
2708 ;;
2709 V) EXTRAVERBOSE="y" ;;
2710 x) EJECTCD="y" ;;
2711 w) COMMENT="$OPTARG" ;;
2712 W) if echo $OPTARG | grep -q "[[:digit:]]" ; then
2713 STARTTRACKNUMBER="${OPTARG}01" ; STARTTRACKNUMBERTAG="y" ; COMMENT="CD${OPTARG}"
2714 else
2715 log error "argument of -W must be integer"
2716 exit 1
2717 fi
2718 ;;
2719 z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
2720 ?) usage; exit ;;
2721 esac
2722 done
2723
2724 shift $(($OPTIND - 1))
2725
2726 # If the user specified a flac file, then switch to special flac mode
2727 if echo $CDROM | grep -i -q '.flac$'; then
2728 vecho "abcde: switching to flac CDROMREADERSYNTAX..."
2729 CDROMREADERSYNTAX=flac
2730 if [ "$EJECTCD" = "y" ];then
2731 vecho "abcde: CDROM flac mode, deactivating EJECTCD..."
2732 EJECTCD=n
2733 fi
2734 fi
2735
2736 # If the user provided a DISCID, disable eject
2737 if [ -n "$DISCID" ]; then EJECTCD=n ; fi
2738
2739 # Check the available cd rippers in the system, from the ones we know.
2740 if [ "$CDROMREADERSYNTAX" = "" ]; then
2741 for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
2742 if [ -x $( which $DEFAULT_CDROMREADER ) ]; then
2743 CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
2744 break
2745 fi
2746 done
2747 if [ "$CDROMREADERSYNTAX" = "" ]; then
2748 log error "no cdreader found in your PATH"
2749 log error "hints: are all dependencies installed? has the \$PATH been modified?"
2750 exit 1
2751 fi
2752 fi
2753
2754 # Decide if we can continue.
2755 if [ "$ONETRACK" = "y" ]; then
2756 # FIXME # remove check as soon as we find out about the other readers
2757 case "$CDROMREADERSYNTAX" in
2758 flac) ;;
2759 cdparanoia) ;;
2760 cdda2wav) ;;
2761 *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
2762 exit 1 ;;
2763 esac
2764 if [ "$BATCHNORM" = "y" ]; then
2765 log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
2766 BATCHNORM=n
2767 fi
2768 if [ "$NOGAP" = "y" ]; then
2769 log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
2770 NOGAP=n
2771 fi
2772 # It does not matter how many tracks we want. In ONETRACK mode we grab them all
2773 # FIXME # allow ranges of tracks to be selected for onetrack ripping
2774 if [ $# -gt 0 ]; then
2775 log warning "ONETRACK mode selected, grabbing all tracks..."
2776 fi
2777 else
2778 while [ $# -gt 0 ]; do
2779 # Range parsing code courtesy of Vincent Ho
2780 RSTART=$(echo $1 | cut -f1 -d-)
2781 REND=$(echo $1 | cut -f2 -d-)
2782 if [ "$RSTART" = "$REND" ]; then
2783 NEWTRACKS="$RSTART"
2784 else
2785 NEWTRACKS=$(f_seq_line $RSTART $REND)
2786 fi
2787 TRACKQUEUE=$(echo "$TRACKQUEUE" "$NEWTRACKS")
2788 shift
2789 done
2790 fi
2791
2792 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
2793 # List of experimental actions: retag,transcode
2794
2795 # Determine what actions are to be done from $ACTIONS and set the
2796 # following environment variables for them:
2797 DOCDDB=n
2798 DOREAD=n
2799 DONORMALIZE=n
2800 DOPREPROCESS=n
2801 DOENCODE=n
2802 DOPOSTPROCESS=n
2803 DOTAG=n
2804 DOMOVE=n
2805 DOREPLAYGAIN=n
2806 DOPLAYLIST=n
2807 DOCLEAN=n
2808
2809 for ACTION in $(echo $ACTIONS | tr , \ )
2810 do
2811 case $ACTION in
2812 cddb) DOCDDB=y;;
2813 read) DOREAD=y;;
2814 normalize) DONORMALIZE=y; DOREAD=y;;
2815 # preprocess) DOPREPROCESS=y; DOREAD=y;;
2816 encode) DOENCODE=y; DOREAD=y;;
2817 # postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
2818 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
2819 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
2820 replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
2821 playlist) DOCDDB=y; DOPLAYLIST=y;;
2822 clean) DOCLEAN=y;;
2823 esac
2824 done
2825
2826 if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
2827 # FIXME # should we abort on error or just inform the user?
2828 log warning "selected both normalize and replaygain actions"
2829 fi
2830
2831 for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
2832 case $SHOWCDDBFIELD in
2833 y*|Y*) SHOWCDDBYEAR="y";;
2834 g*|G*) SHOWCDDBGENRE="y";;
2835 *) ;;
2836 esac
2837 done
2838
2839 # Sanity checks:
2840
2841 # At this point a CDROM has to be defined, so we check it exists.
2842 if [ X"$CDROM" != "X" ] ; then
2843 if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
2844 if [ "$OSFLAVOUR" = "FBSD" ]; then
2845 if ! echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then
2846 log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
2847 log error "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
2848 exit 1
2849 fi
2850 fi
2851 elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
2852 log error "CDROM device cannot be found."
2853 exit 1
2854 fi
2855 # avoid processing if we are not going to hit the CDROM.
2856 elif [ X"$DOREAD" = "Xy" ]; then
2857 log error "CDROM has not been defined or cannot be found"
2858 exit 1
2859 fi
2860
2861 # USEPIPES pre-tests, before we get into more serious stuff
2862 # Not compatible with:
2863 # - multiple outputs
2864 # - normalize
2865 # - lowdisk algorithm
2866 # - anything else?
2867 if [ X"$USEPIPES" = "Xy" ]; then
2868 if [ $(echo "$OUTPUTTYPE" | tr , \ | wc -w ) -gt 1 ]; then
2869 log error "Unix pipes not compatible with multiple outputs"
2870 exit 1
2871 fi
2872 if [ X"$DONORMALIZE" = "Xy" ]; then
2873 log error "Unix pipes not compatible with normalizer"
2874 # FIXME # Do we need to exit or shall we just disable the mode?
2875 exit 1
2876 fi
2877 if [ X"$BATCHNORM" = "Xy" ]; then
2878 log error "Unix pipes not compatible with BATCHNORM encoding"
2879 exit 1
2880 fi
2881 if [ X"$NOGAP" = "Xy" ]; then
2882 log error "Unix pipes not compatible with NOGAP encoding"
2883 exit 1
2884 fi
2885 if [ X"$DOENCODE" = "Xn" ]; then
2886 vecho warning "Disabling Unix pipes since we are not encoding!"
2887 USEPIPES=n
2888 fi
2889 if [ X"$LOWDISK" = "Xy" ]; then
2890 log error "Unix pipes not compatible with lowdisk algorithm"
2891 exit 1
2892 fi
2893 fi
2894
2895 # LOWDISK pre-tests, before we get into more problematic stuff
2896 # Not compatible with anything that needs all the files in the hard disc:
2897 # - BATCHNORM
2898 # - NOGAP lame mode
2899 if [ X"$LOWDISK" = "Xy" ]; then
2900 if [ X"$BATCHNORM" = "Xy" ]; then
2901 log error "Unix pipes not compatible with BATCHNORM encoding"
2902 exit 1
2903 fi
2904 if [ X"$NOGAP" = "Xy" ]; then
2905 log error "Unix pipes not compatible with NOGAP encoding"
2906 exit 1
2907 fi
2908 fi
2909
2910 # BATCHNORM pre-tests, before we get into serious problems
2911 # Not compatible with
2912 if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
2913 vecho warning "Disabling BATCHNORM since we are not normalizing!"
2914 BATCHNORM=n
2915 fi
2916
2917 # Check the encoding format from the ones available in the system, if nothing has been configured in the system.
2918 if [ X"$OUTPUTTYPE" = "X" ]; then
2919 for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
2920 DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
2921 DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
2922 if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
2923 OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
2924 vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
2925 break
2926 fi
2927 done
2928 if [ X"$OUTPUTTYPE" = "X" ]; then
2929 log error "no encoder found in the PATH"
2930 log error "hints: are all dependencies installed? has the \$PATH been modified?"
2931 exit 1
2932 fi
2933 fi
2934
2935 # Decide which CDROM reader we're gonna use
2936 case "$CDROMREADERSYNTAX" in
2937 cdparanoia|debug)
2938 CDROMREADER="$CDPARANOIA"
2939 CDROMREADEROPTS="$CDPARANOIAOPTS"
2940 ;;
2941 cdda2wav)
2942 CDROMREADER="$CDDA2WAV"
2943 CDROMREADEROPTS="$CDDA2WAVOPTS"
2944 ;;
2945 dagrab)
2946 CDROMREADER="$DAGRAB"
2947 CDROMREADEROPTS="$DAGRABOPTS"
2948 ;;
2949 cddafs)
2950 CDROMREADER="$CDDAFS"
2951 CDROMREADEROPTS="$CDDAFSOPTS"
2952 ;;
2953 flac)
2954 CDROMREADER="$FLAC"
2955 CDROMREADEROPTS="$FLACOPTS"
2956 ;;
2957 esac
2958
2959 # There's only one normalize...
2960 case "$NORMALIZERSYNTAX" in
2961 default|normalize)
2962 NORMALIZER="$NORMALIZE"
2963 NORMALIZEROPTS="$NORMALIZEOPTS"
2964 ;;
2965 esac
2966
2967 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
2968 if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
2969 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
2970 case "$OUTPUT" in
2971 vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2972 mp3:*) MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2973 flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2974 spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2975 mpc:*) MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2976 m4a:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
2977 esac
2978 done
2979 for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
2980 TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
2981 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
2982 done
2983 OUTPUTTYPE="$TEMPOUTPUTTYPE"
2984 fi
2985
2986 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
2987 # for flacs and speexenc for speex and mppenc for mpps and faac for m4as
2988
2989 # Getting ready for multiple output changes
2990 for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
2991 do
2992 case $OUTPUT in
2993 vorbis|ogg)
2994 [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
2995 [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
2996 [ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
2997 OGGOUTPUTCONTAINER=ogg
2998 ;;
2999 mp3)
3000 [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
3001 [ "$DOTAG" = "y" ] && NEEDTAGGER=y
3002 [ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
3003 ;;
3004 flac)
3005 [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
3006 [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
3007 [ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
3008 ;;
3009 spx)
3010 [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
3011 # [ "$DOREPLAYGAIN" = "y" ] &&
3012 ;;
3013 mpc)
3014 [ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc
3015 [ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y
3016 ;;
3017 m4a)
3018 [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
3019 ;;
3020 wav)
3021 if [ "$KEEPWAVS" = "y" ]; then
3022 vecho "Unsetting the KEEPWAVS option, since the resulting wav files were requested..."
3023 fi
3024 KEEPWAVS=move
3025 ;;
3026 *) log error "Invalid OUTPUTTYPE defined"
3027 exit 1
3028 ;;
3029 esac
3030 done
3031
3032 # decide which encoder
3033 case "$MP3ENCODERSYNTAX" in
3034 lame)
3035 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
3036 MP3ENCODER="$LAME"
3037 ;;
3038 toolame)
3039 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$TOOLAMEOPTS}"
3040 MP3ENCODER="$TOOLAME"
3041 ;;
3042 gogo)
3043 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
3044 MP3ENCODER="$GOGO"
3045 ;;
3046 bladeenc)
3047 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
3048 MP3ENCODER="$BLADEENC"
3049 ;;
3050 l3enc)
3051 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
3052 MP3ENCODER="$L3ENC"
3053 ;;
3054 xingmp3enc)
3055 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
3056 MP3ENCODER="$XINGMP3ENC"
3057 ;;
3058 mp3enc)
3059 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
3060 MP3ENCODER="$MP3ENC"
3061 ;;
3062 esac
3063 case "$OGGENCODERSYNTAX" in
3064 vorbize)
3065 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
3066 OGGENCODER="$VORBIZE"
3067 ;;
3068 oggenc)
3069 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
3070 OGGENCODER="$OGGENC"
3071 ;;
3072 esac
3073 case "$FLACENCODERSYNTAX" in
3074 flac)
3075 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
3076 FLACENCODER="$FLAC"
3077 # FLAC streams can be encapsulated on a Ogg transport layer
3078 if echo "$FLACENCODEROPTS" | egrep -q -- "(^| )--ogg($| )" ;then
3079 log error "FLAC on an Ogg container is not yet supported"
3080 log error "due to problem with adding comments to such files"
3081 exit 1
3082 FLACOUTPUTCONTAINER=ogg
3083 else
3084 FLACOUTPUTCONTAINER=flac
3085 fi
3086 ;;
3087 esac
3088 case "$SPEEXENCODERSYNTAX" in
3089 speexenc)
3090 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
3091 SPEEXENCODER="$SPEEXENC"
3092 ;;
3093 esac
3094 case "$MPPENCODERSYNTAX" in
3095 mppenc)
3096 MPPENCODEROPTS="${MPPENCODEROPTSCLI:-$MPPENCOPTS}"
3097 MPPENCODER="$MPPENC"
3098 ;;
3099 esac
3100 case "$AACENCODERSYNTAX" in
3101 faac)
3102 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
3103 AACENCODER="$AACENC"
3104 ;;
3105 esac
3106 # and which tagger
3107
3108 if [ "$ID3TAGV" = "1" ]; then
3109 TAGGER="$ID3"
3110 TAGGEROPTS="$ID3OPTS"
3111 else
3112 TAGGER="$ID3V2"
3113 TAGGEROPTS="$ID3V2OPTS"
3114 fi
3115
3116 # Specific for NOGAP is the use of lame. Another encoder fails...
3117 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
3118 log warning "the NOGAP option is specific of lame. Deactivating..."
3119 NOGAP=n
3120 fi
3121
3122 # Options for mkcue
3123 case "$CUEREADERSYNTAX" in
3124 default|mkcue)
3125 CUEREADEROPTS="${CDROM}"
3126 CUEREADER="$MKCUE"
3127 ;;
3128 esac
3129
3130 # which information retrieval tool are we using?
3131 case "$CDDBTOOL" in
3132 cddb) ;;
3133 musicbrainz) ;;
3134 esac
3135
3136 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
3137 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
3138 log error "FLAC on an Ogg container is not yet supported"
3139 log error "due to problem with adding comments to such files"
3140 exit 1
3141 OGGOUTPUTCONTAINER=ogg.ogg
3142 FLACOUTPUTCONTAINER=flac.ogg
3143 vecho warning "modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
3144 fi
3145
3146 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
3147
3148 if [ "$ENCNICE" ]; then
3149 ENCNICE="-n $ENCNICE"
3150 fi
3151 if [ "$READNICE" ]; then
3152 READNICE="-n $READNICE"
3153 fi
3154 if [ "$DISTMP3NICE" ]; then
3155 DISTMP3NICE="-n $DISTMP3NICE"
3156 fi
3157
3158 # Don't check for stuff if it's not needed
3159 if [ "$REMOTEHOSTS" ]; then
3160 NEEDDISTMP3=y
3161 fi
3162 if [ "$DONORMALIZE" = "y" ]; then
3163 NEEDNORMALIZER=y
3164 fi
3165 if [ "$EJECTCD" = "y" ]; then
3166 NEEDEJECT=y
3167 fi
3168 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
3169 if [ "$CDDBMETHOD" = "cddb" ]; then
3170 NEEDHTTPGET=y
3171 elif [ "$CDDBMETHOD" = "musicbrainz" ]; then
3172 :
3173 fi
3174 fi
3175 if [ "$MAKECUEFILE" = "y" ]; then
3176 NEEDCUEREADER=y
3177 fi
3178
3179 if [ X"$CDSPEEDVALUE" != "X" ]; then
3180 case "$CDROMREADERSYNTAX" in
3181 cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
3182 ### FIXME ### translate "cue2discid" from python to bash
3183 flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ;;
3184 *) NEEDCDSPEED=y ;;
3185 esac
3186 fi
3187
3188 ###USEPIPESSUPPORT###
3189
3190 # Rippers with USEPIPE support
3191 # FIXME # Include here all the rippers we can figure out support pipes
3192 PIPERIPPER_cdparanoia="-"
3193 PIPERIPPER_debug="-"
3194 PIPERIPPER_flac="-c "
3195
3196 # Encoders with USEPIPE support
3197 # FIXME # Include here all the encoders we can figure out support pipes
3198 PIPE_lame="-"
3199 PIPE_bladeenc="-"
3200 PIPE_oggenc="-"
3201 PIPE_flac="-"
3202
3203 # Figure out if we can use pipes with the ripper/encoder combination
3204 # exit otherwise
3205 if [ "$USEPIPES" = "y" ]; then
3206 PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
3207 case "$OUTPUT" in
3208 mp3)
3209 PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
3210 vorbis|ogg)
3211 PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
3212 flac)
3213 PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
3214 spx)
3215 PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
3216 mpc)
3217 PIPEENCODERSVARCHECK="PIPE_$MPPENCODER" ;;
3218 esac
3219 decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
3220 if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
3221 [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
3222 log error "no support for pipes with given ripper"
3223 log error "read the USEPIPES file from the source tarball to get help."
3224 log error "On a Debian system, it is under /usr/share/doc/abcde/USEPIPES.gz"
3225 exit 1;
3226 fi
3227 decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
3228 if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
3229 [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
3230 log error "no support for pipes with given encoder"
3231 log error "read the USEPIPES file from the source tarball to help"
3232 log error "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz"
3233 exit 1;
3234 fi
3235 fi
3236
3237 # Make sure a buncha things exist
3238 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
3239 $OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
3240 ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
3241 ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
3242 ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
3243 ${NEEDDISKTOOL+disktool} ${NEEDCDSPEED+$CDSPEED} \
3244 ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
3245 ${NEEDMPPGAIN+$MPPGAIN} \
3246 ${NEEDCUEREADER+$CUEREADER} ${NEEDCUE2DISCID+$CUE2DISCID}
3247 do
3248 # Cut off the command-line options we just added in
3249 X=$(echo $X | cut -d' ' -f2)
3250 if [ "$(which $X)" = "" ]; then
3251 log error "$X is not in your path." >&2
3252 exit 1
3253 elif [ ! -x $(which $X) ]; then
3254 log error "$X is not executable." >&2
3255 exit 1
3256 fi
3257 done
3258
3259 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
3260 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
3261 HTTPGET="$HTTPGET $HTTPGETOPTS"
3262
3263 # And last but not least, check if we can diff between files
3264 if [ -x $(which $DIFF) ]; then :; else
3265 vecho warning "Disabling diff since we cannot find it in the \$PATH..."
3266 DIFF=""
3267 fi
3268
3269 # Here it used to say:
3270 # One thousand lines in, we can start doing stuff with things
3271 # Well, right now we are at line 2736 ;)
3272
3273 # Export needed things so they can be read in this subshell
3274 export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
3275 export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
3276
3277 if [ "$DOREAD" = "y" ]; then
3278 # User-definable function to set some things. Use it for
3279 # - closing the CD tray with eject -t
3280 # - set the CD speed value with eject -x
3281 vecho -n "Executing customizable pre-read function... "
3282
3283 pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
3284
3285 vecho "done."
3286 fi
3287
3288 case "$CDDBMETHOD" in
3289 cddb)
3290 do_discid # Get ABCDETEMPDIR created and status file initialized
3291 ;;
3292 musicbrainz)
3293 do_musicbrainz
3294 ;;
3295 esac
3296
3297 if [ "$DOCDDB" = "y" ]; then
3298 if [ $CDDBUSELOCAL = "y" ]; then
3299 do_localcddb
3300 fi
3301 if checkstatus cddb-choice > /dev/null; then
3302 :
3303 else
3304 if [ "$CDDBLOCALSTATUS" = "notfound" ] ; then
3305 case "$CDDBMETHOD" in
3306 cddb)
3307 do_cddbstat
3308 do_cddbquery
3309 do_cddbread
3310 ;;
3311 musicbrainz)
3312 do_musicbrainz
3313 ;;
3314 esac
3315 fi
3316 fi
3317 do_cddbedit
3318
3319 eval "$($CDDBTOOL parse "$CDDBDATA")"
3320 fi
3321
3322 # Before reading tracks, we set the speed of the device
3323
3324 if [ X"$CDSPEEDVALUE" != "X" ]; then
3325 case "$CDROMREADERSYNTAX" in
3326 cdparanoia|debug) ;;
3327 flac) ;;
3328 *) do_cdspeed ;;
3329 esac
3330 fi
3331
3332 # Define the first and last track, since we might need them later in several places
3333 FIRSTTRACK=$( get_first $TRACKQUEUE )
3334 LASTTRACK=$( get_last $TRACKQUEUE )
3335
3336 if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
3337 mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
3338 grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
3339 | grep -v ^encode-output > "$ABCDETEMPDIR/status"
3340 fi
3341
3342 # Create playlist if needed (backgroundable) and start reading in tracks
3343
3344 (
3345
3346 if [ ! "$ONETRACK" = "y" ]; then
3347 if [ "$DOPLAYLIST" = "y" ]; then
3348 echo Creating playlist... >&2
3349 do_playlist
3350 fi
3351 fi
3352
3353 # For the lowdisk option, only one program is running at once so the encoder
3354 # can be unsilenced right away.
3355 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
3356 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
3357 fi
3358
3359 if [ "$ONETRACK" = "y" ]; then
3360 TRACKS="$FIRSTTRACK"
3361 if checkstatus readtrack-$FIRSTTRACK; then :; else
3362 if [ "$USEPIPES" = "y" ]; then
3363 do_cdread onetrack $FIRSTTRACK $LASTTRACK | do_encode $FIRSTTRACK %local0% > /dev/null 2>&1
3364 else
3365 do_cdread onetrack $FIRSTTRACK $LASTTRACK
3366 fi
3367 fi
3368 else
3369 for UTRACKNUM in $TRACKQUEUE
3370 do
3371 if [ "$DOREAD" = "y" ]; then
3372 if [ "$USEPIPES" = "y" ]; then
3373 if checkstatus readencodetrack-$UTRACKNUM; then :; else
3374 # Read, pipe, shut up!
3375 do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
3376 fi
3377 else
3378 if checkstatus readtrack-$UTRACKNUM; then :; else
3379 do_cdread $UTRACKNUM
3380 fi
3381 if [ "$?" != "0" ]; then
3382 # CD read failed - don't give the goahead to
3383 # the encoder
3384 echo NO
3385 exit
3386 fi
3387 fi
3388 fi
3389 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ]; then
3390 :
3391 else
3392 # If we are not reading, set the encode output to loud already, so
3393 # that we can see the output of the first track.
3394 if [ "$MAXPROCS" = "1" ] && [ ! "$DOREAD" = "y" ]; then
3395 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
3396 fi
3397 echo NEXTTRACK # Get the encoder machine churning again
3398 if [ "$DOREAD" = "y" ]; then
3399 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
3400 until checkstatus encodetrack-$UTRACKNUM
3401 do
3402 if checkerrors encodetrack-$UTRACKNUM; then
3403 break
3404 fi
3405 sleep 2
3406 done
3407 fi
3408 fi
3409 fi
3410 done
3411 fi
3412
3413 # Now that we're done the encoding can be loud again -
3414 # if we're not using SMP.
3415 if [ "$MAXPROCS" = "1" ]; then
3416 echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
3417 fi
3418
3419 # All tracks read, start encoding.
3420 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ] || [ "$ONETRACK" = "y" ]; then
3421 echo NEXTTRACK
3422 fi
3423
3424 # Execute the user-defined post_read funtion before ejecting CD
3425 post_read
3426
3427 # We are now finished with the cdrom - it can be safely ejected. Note that
3428 # abcde will not have completed yet.
3429 if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
3430 # We check if the disk we are processing is actually the disk inside the
3431 # CD tray. If not, we do not eject the CD, since it might be so that the
3432 # user ejected it manually.
3433 #CURRENTTRACKINFO=$($CDDISCID $CDROM)
3434 #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
3435 # More FreeBSD bits.
3436 if [ X"$(uname)" = X"FreeBSD" ] ; then
3437 # FreeBSD eject uses the EJECT environment variable to name the CDROM
3438 # but in this script EJECT is in the envionment and names the program
3439 eject=$EJECT
3440 unset EJECT
3441 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
3442 cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
3443 $eject $EJECTOPTS $cd
3444 elif [ X"$(uname)" = X"Darwin" ] ; then
3445 disktool -e ${CDROM#/dev/} 0
3446 else
3447 $EJECT $EJECTOPTS $CDROM
3448 fi
3449 #fi
3450 fi
3451
3452 ) | (
3453
3454 ## Do we need to pre-process
3455 #if [ x"$PREPROCESS" = "x" ] ; then
3456 # cat
3457 #else
3458 # for PRETRACKNUM in $TRACKQUEUE
3459 # do
3460 # read GOAHEAD
3461 # if [ "$GOAHEAD" = "NO" ]; then break; fi
3462 # PREPROCEED=
3463 # until [ $PREPROCEED ]
3464 # do
3465 # if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
3466 # # all locations are working, wait and try again later
3467 # if [ ! $PREPROCEED ]; then sleep 3; fi
3468 # done
3469 # ( do_preprocess $PRETRACKNUM
3470 # echo "NEXTTRACK"
3471 # ) &
3472 # done
3473 #fi
3474 #
3475 #) | (
3476
3477 # In BATCHNORM and/or NOGAP modes, we want all tracks to be read first.
3478 #BACK
3479 if [ "$BATCHNORM" = "y" ] || [ "$NOGAP" = "y" ]; then
3480 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
3481 if [ "$GOAHEAD" = "NO" ]; then break; fi
3482 for LASTTRACK in $TRACKQUEUE; do :; done
3483 if checkstatus readtrack-$LASTTRACK; then
3484 if [ "$DONORMALIZE" = "y" ] && [ "$BATCHNORM" = "y" ]; then
3485 if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
3486 if checkerrors batch-normalize; then exit 1; fi
3487 fi
3488 if [ "$DOENCODE" = "y" ] && [ "$NOGAP" = "y" ]; then
3489 if [ "$DONORMALIZE" = "y" ]; then
3490 for UTRACKNUM in $TRACKQUEUE
3491 do
3492 if checkstatus readtrack-$UTRACKNUM; then
3493 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
3494 fi
3495 done
3496 fi
3497 if checkstatus encodetrack-$LASTTRACK; then :; else do_nogap_encode; fi
3498 if checkerrors nogap-encode; then exit 1; fi
3499 fi
3500 fi
3501 fi
3502
3503 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
3504 if [ "$ONETRACK" = "y" ] ; then
3505 TRACKQUEUE="$FIRSTTRACK"
3506 TRACKS="$FIRSTTRACK"
3507 fi
3508
3509 # Do the encoding, including parallelization of remote encoding
3510 # Figure out where each track is going to be encoded
3511 ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
3512 if [ "$MAXPROCS" != "0" ]; then
3513 for NUM in $(f_seq_row 1 "$MAXPROCS")
3514 do
3515 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
3516 done
3517 fi
3518 # Strip whitespace
3519 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
3520 for UTRACKNUM in $TRACKQUEUE
3521 do
3522 # Wait for our cue
3523 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
3524 if [ "$GOAHEAD" = "NO" ]; then break; fi
3525 # find out where this track is to be encoded
3526 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
3527 # Make sure we have a place to encode this, if not, exit stage right
3528 if [ -z "$ENCODELOCATIONS" ]; then
3529 continue
3530 fi
3531 PROCEED=
3532 until [ $PROCEED ]
3533 do
3534 for LOCATION in $ENCODELOCATIONS
3535 do
3536 PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
3537 # check first if a track has ever been assigned to this location
3538 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
3539 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
3540 if checkerrors encodetrack-$PREVIOUSTRACK; then
3541 for TEMPLOCATION in $ENCODELOCATIONS
3542 do
3543 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
3544 TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
3545 fi
3546 done
3547 ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
3548 ABORT=y
3549 PROCEED=y
3550 break
3551 fi
3552 # We're still here, this location must have been previously assigned,
3553 # and last completed without error - check if it's done with the
3554 # previous track yet
3555 if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
3556 done
3557 # all locations are working, wait and try again later
3558 if [ ! $PROCEED ]; then sleep 3; fi
3559 done
3560 # Record the location we're about to encode the next track at
3561 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
3562 fi
3563 # Don't proceed with the rest of the loop if we can't encode
3564 if [ "$ABORT" ]; then continue; fi
3565 # Set TRACKNUM, TRACKNAME
3566 if [ -e "$CDDBDATA" ]; then
3567 if [ "$ONETRACK" = "y" ]; then
3568 TRACKNAME="$DALBUM"
3569 TRACKNUM="$FIRSTTRACK"
3570 splitvarious
3571 else
3572 TRACKNUM=$UTRACKNUM
3573 CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
3574 do_getcddbinfo TRACKNAME
3575 splitvarious
3576 fi
3577 fi
3578 # You can't encode a file which needs to be normalized before finishing
3579 # You can't tag a file before it's finished encoding -
3580 # thus all of this is backgrounded together
3581 (
3582 if [ "$DONORMALIZE" = "y" ]; then
3583 if checkstatus readtrack-$UTRACKNUM; then
3584 if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
3585 fi
3586 fi
3587 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
3588 if checkstatus readtrack-$UTRACKNUM; then
3589 #if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
3590 if [ "$DONORMALIZE" = "y" ]; then
3591 if checkstatus normalizetrack-$UTRACKNUM; then
3592 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
3593 fi
3594 else
3595 if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
3596 fi
3597 fi
3598 fi
3599 if [ "$DOTAG" = "y" ]; then
3600 if checkstatus encodetrack-$UTRACKNUM; then
3601 if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
3602 fi
3603 # Lets tag the cue file
3604 if checkstatus cleancuefile >/dev/null; then :; else
3605 if checkstatus cuefile >/dev/null ; then
3606 do_cleancue
3607 fi
3608 fi
3609 fi
3610 if [ "$DOMOVE" = "y" ]; then
3611 if checkstatus tagtrack-$UTRACKNUM; then
3612 if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
3613 fi
3614 fi
3615 ) &
3616 done
3617
3618
3619 # Go through it again and make sure there's no distmp3 stragglers, otherwise
3620 # we'll delete the files they're working on
3621 ## FIXME ## Check also for files which are encoded using PIPEs.
3622 if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
3623 PROCEED=
3624 until [ $PROCEED ]
3625 do
3626 PROCEED=y
3627 for LOCATION in $ENCODELOCATIONS
3628 do
3629 CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
3630 # "How can he give us a status update, if he's DEAD?"
3631 if checkstatus encodetrack-$CHECKTRACK; then
3632 continue
3633 fi
3634 # Nothing to see here please go quietly back to your homes
3635 if [ -z "$CHECKTRACK" ]; then continue; fi
3636 # You're still here? Maybe there is something...
3637 if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
3638 done
3639 # hold up
3640 if [ ! $PROCEED ]; then sleep 5; fi
3641 done
3642 fi
3643 # If the above didn't catch the stragglers, this will
3644 wait
3645 if [ "$DOREPLAYGAIN" = "y" ]; then
3646 do_replaygain
3647 fi
3648
3649 # Check to see if run_command logged any errors
3650 if [ -f "$ABCDETEMPDIR/errors" ]; then
3651 log error "The following commands failed to run:"
3652 cat "$ABCDETEMPDIR/errors"
3653 # Don't clean up
3654 DOCLEAN=n
3655 fi
3656 if [ "$KEEPWAVS" = "y" ];then
3657 # Don't clean up
3658 DOCLEAN=n
3659 fi
3660 # Check if we have moved all the formats we had previously encoded, if we are not using the FORCE.
3661 if [ "$DOCLEAN" = "y" ] && [ ! "$FORCE" = "y" ]; then
3662 ENCODED_FORMATS=$(egrep "^encodetrack-(.{3,6})-(.{1,2})$" "$ABCDETEMPDIR/status" | cut -d"-" -f2 | sort -u | tr