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