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