Initial import from tla repo
[zcdrip] / zcdrip.in
1 #!/bin/zsh
2
3 ## Copyright (C) 2006 - 2008 Steve Youngs
4
5 ## Author:        Steve Youngs <steve@sxemacs.org>
6 ## Maintainer:    Steve Youngs <steve@sxemacs.org>
7 ## Created:       <2006-08-08>
8 ## Time-stamp:    <Thursday Jun 12, 2008 12:29:31 steve>
9
10 ## Redistribution and use in source and binary forms, with or without
11 ## modification, are permitted provided that the following conditions
12 ## are met:
13 ##
14 ## 1. Redistributions of source code must retain the above copyright
15 ##    notice, this list of conditions and the following disclaimer.
16 ##
17 ## 2. Redistributions in binary form must reproduce the above copyright
18 ##    notice, this list of conditions and the following disclaimer in the
19 ##    documentation and/or other materials provided with the distribution.
20 ##
21 ## 3. Neither the name of the author nor the names of any contributors
22 ##    may be used to endorse or promote products derived from this
23 ##    software without specific prior written permission.
24 ##
25 ## THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
26 ## IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 ## WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 ## DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 ## FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 ## CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 ## SUBSTITUTE GOODS OR SERVICES# LOSS OF USE, DATA, OR PROFITS# OR
32 ## BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 ## WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
34 ## OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
35 ## IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
37 ### Commentary:
38 ## 
39 ##    Ease the process of ripping audio CDs to .mp3 or .ogg.  See
40 ##    help (zcdrip -h) for full details.
41 ##
42
43 ### Todo:
44 ##    
45 ##    o Partial album ripping.  Specify track numbers or a range of
46 ##      track numbers to only rip/encode those tracks.
47 ##
48 ##    o Ripping from music DVDs
49 ##
50
51 ### Bugs:
52 ##
53 ##    Bugs?  What bugs?  Seriously though, if you find any, let me
54 ##    know.
55 ##
56
57 # Debug
58 [[ -n $DEBUG ]] && set -x; zdebug=${TMPPREFIX}/zdebug
59
60 ### Code:
61 ourname=${0##*/}
62
63 # Version info.
64 VERSION=@VERSION@
65 COPYRIGHT="Copyright (C) 2006 - 2008 Steve Youngs <steve@sxemacs.org>"
66
67 version_str="${ourname}: ${VERSION}
68 ${COPYRIGHT}"
69
70 _version () { echo $version_str }
71
72 # Help
73 usage ()
74 {
75     # If you use eshell you will have a problem displaying this help.
76     # This is the only part of the script that eshell has a problem
77     # with, but if you really want to be able to view this help in
78     # eshell, create a symlink and call it `ecdrip'.
79
80     [[ ${LINES} -lt 70 && $TERM != dumb ]] && _doc=${PAGER:-less} || _doc=cat
81     [[ $ourname == ecdrip ]] && _doc=cat
82     $_doc<<EOF
83
84                                $ourname
85          ${VERSION}
86
87
88 Synopsis:
89 --------
90
91   $ourname 
92         [ -moi ] [ --mp3 | --ogg ] [ -r FILE ] [ --interactive | --rcfile=FILE ]
93         [ -a ALBUM ] [ --album=ALBUM ] [ -s ARTIST ] [ --sameartist=ARTIST ]
94         [ -t ENCODING_TYPE ] [ --type=ENCODING_TYPE ] [ -f | --flac_copy ]
95         [ -e FILE | --edit_rcfile=FILE ] [ -O | --online ] [ -d DIR | --dir=DIR ]
96   $ourname 
97         [ -h | --help ]
98   $ourname
99         [ -V | --version ]
100
101 Description:
102 -----------
103
104   $ourname is a "frontend" to the process of ripping audio (cdda) CDs
105   to a hard disk and encoding the audio tracks to either MP3 format or
106   Ogg Vorbis format.
107
108   File names are auto-generated from track titles, with illegal
109   characters removed and spaces converted to underscores.
110
111   Track title, artist, and album names are added to the ID3 tags or
112   Vorbis comments header.
113
114 Options:
115 -------
116
117   -a ALBUM
118   --album=ALBUM
119         Specify the ALBUM name.  Argument ALBUM is _NOT_ optional.
120         Whitespace and punctuation is permitted, but you must protect
121         them from the shell.  If this option is omitted, the album
122         name will be prompted for.
123
124   -d DIR
125   --dir=DIR
126         Save encoded files to the directory, DIR.  If flac encoding
127         is also requested, see '--flac_copy' option below, the flac
128         files will be saved to DIR/flac.  If this option is omitted,
129         it defaults to 'PWD/ARTIST/ALBUM' the album name is first
130         converted to a sane filename.
131
132   -e FILE
133   --edit_rcfile=FILE
134         Edit/create rcfile, FILE, in an editor.  If the environment
135         variable EDITOR is not set, vi is used.  This implicitly sets
136         rcfile, see '--rcfile' option below.
137
138   -f
139   --flac_copy
140         In addition to encoding the CD audio tracks to MP3 or Ogg
141         Vorbis, create a FLAC audio file for archival purposes.
142
143   -h
144   --help
145         Display this help text and exit.
146
147   -i
148   --interactive
149         Prompt for track titles and artist names.
150
151   -m
152   --mp3
153         Specify MP3 encoding.
154
155   -o
156   --ogg
157         Specify Ogg Vorbis encoding.
158
159   -O
160   --online
161         Attempt to grab the track info from freedb.freedb.org.
162
163   -r FILE
164   --rcfile=FILE
165         Get track titles and artist names from FILE.  Argument FILE
166         is _NOT_ optional.  The format of FILE is:
167
168            Artist Name|Track Title
169
170         One "record" per line.  Whitespace and punctuation is permitted,
171         blank lines are not.  And there is no "comment" lines.
172
173   -s ARTIST
174   --sameartist=ARTIST
175         All tracks on the album are by the same ARTIST.  Argument
176         ARTIST is _NOT_ optional.
177
178   -t ENCODING_TYPE
179   --type=ENCODING_TYPE
180         This is an alternative to using the -m or -o options.
181         Use ENCODING_TYPE to encode the audio.  Valid values for
182         ENCODING_TYPE are "mp3", "ogg".
183
184   -V
185   --version
186         Display version info and exit.
187
188 Requirements:
189 ------------
190
191     zsh         http://www.zsh.org/  (mandatory)
192
193     cdparanoia  http://www.xiph.org/paranoia/
194                 For ripping the audio tracks from CD. (mandatory)
195
196     lame        http://www.mp3dev.org/
197                 For encoding to MP3 format. (optional if encoding to
198                 Ogg Vorbis)
199
200     oggenc      http://www.xiph.org/
201                 For encoding to Ogg Vorbis format (optional if encoding
202                 to MP3)
203
204     flac        http://flac.sourceforge.net/
205                 For additionally storing audio tracks in FLAC format.
206                 (optional)
207
208 Files:
209 -----
210
211     ${TMPPREFIX}/$ourname.log
212                 A log of the incoming TCP traffic from the CDDB server.
213                 This will be kept if debugging is turned on, otherwise
214                 it is deleted upon successful exit.
215
216     $zdebug
217                 Some extra debugging info is logged here.
218
219     rcfile
220                 Where $ourname gets track info from.  It can be
221                 specified on the command line (see -r above) when
222                 not using an online CDDB server, otherwise it is
223                 created automatically by $ourname.
224
225 Environment Variables:
226 ---------------------
227
228   Some aspects of $ourname can be tweaked by setting the following
229   environment variables.
230
231     DEBUG       Set to a non-nil string to turn on debugging.
232
233     zcddb       CDDB server to use (default: freedb.freedb.org).
234
235     zuser       Name used to log into CDDB server (default: $USER).
236
237     zhost       Host used to log into CDDB server (default: $HOST).
238
239     zedit       Set to a non-nil string to force $ourname to invoke an
240                 editor to create a rcfile.
241
242     zcomment    Extra comment field/value to add to ID3 tags/Vorbis 
243                 comments (default: "Encoded with $ourname").
244
245   Occasionally, the CDDB entries for a given CD are either wrong or
246   have not been formatted correctly.  In an attempt to compensate for
247   these types of quirks you can set the following environment variables
248   with $ourname invocation to override the madness...
249
250     ARTIST      Override the artist field.
251
252     ALBUM       Override the album name.
253
254     YEAR        Override year.
255
256     GENRE       Override genre.
257
258 Example Usage:
259 -------------
260
261   Probably the most common usage would be to encode to Ogg/Vorbis
262   format using track info obtained from freedb.freedb.org.  Like
263   this...
264
265     \$ $ourname -oO
266
267   Encode to MP3 format, prompting for album name, year, genre, artist,
268   and track titles...
269
270     \$ $ourname -mi
271
272   Encode to Ogg/Vorbis, set album name on the command line, taking
273   track title info from a file, and make a FLAC format backup copy of
274   each track...
275
276     \$ $ourname -a "The Album Name" -o -f -r /path/to/rcfile
277
278   Encode to Ogg/Vorbis, taking track info from a online CDDB server,
279   and override the genre for the album...
280
281     \$ GENRE=alternate $ourname -oO
282
283 Exit Status:
284 -----------
285
286   $ourname will return the following status codes on exit:
287
288     0 -- Clean exit (no errors)
289     2 -- Command line option error
290     3 -- Missing external command
291     4 -- CDDB error
292
293 Debugging:
294 ---------
295
296   If you call $ourname with the environment variable DEBUG set to a
297   non nil value, for example: DEBUG=yes $ourname <opts>, $ourname will
298   be called with "set -x".
299
300   "set -x" spams your stdout with a _LOT_ of messages, it would most
301   likely pay you to redirect stdout/stderr to a file.
302
303 ${COPYRIGHT}
304
305 EOF
306 }
307
308 # Convert song title to something resembling a sane filename... no
309 # whitespace, no punctuation, etc.  Also adds .ogg/.mp3 extension.
310 fnamefix ()
311 {
312     local psub="[[:cntrl:],\*\?\`';/\\\\\"]"
313     local prep=""
314     local wsub="[[:space:][:blank:]]"
315     local wrep="_"
316
317     setopt extendedglob
318
319     for (( i=1; i<=$tracks; ++i )); do
320         tf=$filename[$i]
321         tf=${tf//\\t/ }
322         tf=${tf//${~psub}/$prep}
323         tf=${tf//[ ]##/ }
324         tf=${tf//${~wsub}/$wrep}
325         filename[$i]=$tf.$prepargs[1]
326     done
327 }
328
329 ### freedb magic
330 _freedb_login ()
331 {
332     local args
333     if [[ -z $1 ]]; then
334         print invalid args >&2
335         return 1
336     fi
337
338     args="$@"
339     # login
340     tcp_send "cddb hello $args"
341     tcp_expect -T 10 -s $ourname "*Hello and welcome*"
342     if [[ $? -eq 2 ]]; then
343         print Timeout waiting for cddb server >&2
344         exit 4
345     fi
346     # set protocol level
347     tcp_send "proto 6"
348     tcp_expect -T 10 -s $ourname "*CDDB protocol*"
349     if [[ $? -eq 2 ]]; then
350         print Timeout waiting for cddb server >&2
351         exit 4
352     fi
353     return 0
354 }
355
356 _parse_cddb ()
357 {
358     local various=yes
359     art=$(grep DTITLE $zlog|cut -d= -f2|cut -d/ -f1|sed '1!d')
360     art=${art/%[[:space:]]/}
361     art=${art//'&'/'\&'}
362
363     # Possibly override.
364     art=${ARTIST:-$art}
365
366     # Artist
367     if [[ "$art" != "Various Artists" && "$art" != "Various" ]]; then
368         various=no
369     fi
370
371     # Album, year, genre, number or tracks
372     album=$(grep DTITLE $zlog|cut -d= -f2|cut -d/ -f2)
373     album=${album/#[[:space:]]/}
374     album=${album//[[:cntrl:]]/}
375     year=$(grep DYEAR $zlog|cut -d= -f2)
376     year=${year//[[:cntrl:]]/}
377     genre=$(grep DGENRE $zlog|cut -d= -f2)
378     genre=${genre//[[:cntrl:]]/}
379     tracks=$zid[2]
380
381     # Possibly override album, year, genre
382     album=${ALBUM:-$album}
383     year=${YEAR:-$year}
384     genre=${GENRE:-$genre}
385
386     # print what we got when we're debugging
387     if [[ -n $DEBUG ]]; then
388         printf "Artist: %s\nAlbum: %s\nYear: %s\nGenre: %s\nNum Tracks: %s\n" \
389             $art $album $year $genre $tracks > $zdebug
390         printf "Various: %s\n" $various >> $zdebug
391         echo --- Titles --- >> $zdebug
392         grep TTITLE $zlog >> $zdebug
393     fi
394
395     # create an rcfile
396     if [[ $various == yes || -n $(grep TTITLE $zlog|grep $art) ]]; then
397         grep TTITLE $zlog|cut -d= -f2|sed 's@ [-/] @|@' > $rcfile
398     else
399         grep TTITLE $zlog|cut -d= -f2 > $rcfile
400         sed -i "s@^@${art}|@g" $rcfile
401     fi
402     
403 }
404
405 _freedb_read ()
406 {
407     if [[ -z $1 ]]; then
408         print invalid args >&2
409         return 1
410     fi
411
412     tcp_send "cddb read $1 $2"
413     tcp_expect -T 25 -s $ourname "*PLAYORDER*"
414     if [[ $? -eq 2 ]]; then
415         print Timeout waiting for cddb server >&2
416         exit 4
417     fi
418
419     _parse_cddb
420     
421 }
422
423 _freedb_query ()
424 {
425     if [[ -z $1 ]]; then
426         print invalid args >&2
427         return 1
428     fi
429
430     tcp_send "cddb query $zid"
431     tcp_expect -T 10 -p idx -s $ourname "*No match for disc ID*" \
432         "<-\[$ourname\] 200*" "<-\[$ourname\] .*"
433     if [[ $? -eq 2 ]]; then
434         print Timeout waiting for cddb server >&2
435         exit 4
436     fi
437     case $idx in
438         (1)
439             print No entry listed for disc: $zid[1] >&2
440             print You will have to do this disc manually >&2
441             exit 4
442             ;;
443         (2)
444             category=$TCP_LINE
445             category=${category/*200 /}
446             category=${category/ $zid[1]*/}
447             _freedb_read $category $zid[1]
448             ;;
449         (3)
450             echo Multiple entries found...
451             echo
452             tmulti=(${(ps:\r:)${tcp_expect_lines}})
453             [[ $tmulti[1] == *inexact* ]] && exact=no
454             tmulti[1]=${tmulti[1]:#${tmulti[1]}}
455             multi=($tmulti)
456             for (( i=1; i<${#multi}; ++i )); do
457                 multi[$i]=${multi[$i]/<-\[$ourname\] /}
458                 printf "\t[%s]%s\n" $i $multi[$i]
459             done
460             echo
461             echo -n "Which CDDB entry (q to quit): "
462             read choice
463             case $choice in
464                 ([qQ]) do_offline; exit 0 ;;
465                 ([^[:digit:]]) 
466                     print Invalid response >&2
467                     do_offline
468                     exit 2
469                     ;;
470                 ([[:digit:]])
471                     category=$multi[$choice]
472                     if [[ $exact == no ]]; then
473                         tcategory=(${(ps: :)category})
474                         _freedb_read $tcategory[1,2]
475                     else
476                         category=${category/ $zid[1]*/}
477                         _freedb_read $category $zid[1]
478                     fi
479                     ;;
480                 (*)
481                     print Unknown error >&2
482                     do_offline
483                     exit 2
484                     ;;
485             esac
486             ;;
487         (*) print Unknown error >&2 ;;
488     esac
489 }
490
491 do_online ()
492 {
493     autoload -U tcp_open
494     autoload -U tcp_log
495     [[ -n $DEBUG ]] || TCP_SILENT=nodebugging
496
497     zcddb=${zcddb:-freedb.freedb.org}
498     port=8880
499     zuser=${zuser:-$USER}
500     zhost=${zhost:-$HOST}
501     proto=6
502     zlog=${TMPPREFIX}/zcdrip.log
503
504     # open the log and connect
505     tcp_log $zlog
506     tcp_open $zcddb $port $ourname
507     tcp_expect -T 10 -s $ourname "<-\[$ourname\] 201*ready*"
508     if [[ $? -eq 2 ]]; then
509         print Timeout waiting for cddb server >&2
510         exit 4
511     else
512         _freedb_login $zuser $zhost $ourname $VERSION
513     fi
514
515     # query cddb server to find out if the CD is listed
516     _freedb_query $zid
517
518 }
519
520 # Close tcp connection
521 do_offline ()
522 {
523     tcp_close $ourname
524     tcp_log -c
525 }
526
527 # Tidy up if not debugging
528 cleanup ()
529 {
530     rm -f $zlog $rcfile $zdebug
531     unset ARTIST ALBUM YEAR GENRE
532 }
533
534 # convert album/artist name into a sane filename for output dir
535 _album_to_dir ()
536 {
537     local talbum=$album
538     local tart=$art
539     local psub="[[:cntrl:],\`';/\\\\\"]"
540     local prep=""
541     local wsub="[[:space:][:blank:]]"
542     local wrep="_"
543
544     setopt extendedglob
545
546     talbum=${talbum//\\t/ }
547     talbum=${talbum//${~psub}/$prep}
548     talbum=${talbum//[ ]##/ }
549     talbum=${talbum//${~wsub}/$wrep}
550
551     tart=${tart//\\t/ }
552     tart=${tart//${~psub}/$prep}
553     tart=${tart//[ ]##/ }
554     tart=${tart//${~wsub}/$wrep}
555
556     # Various Artists is sometimes "Various" and other times "Various
557     # Artists", we'll call them all "Various_Artists".
558     if [[ "${tart}" == "Various" ]]; then
559         tart=Various_Artists
560     fi
561
562     dir=$(pwd)/${tart}/${talbum}
563     [[ -d ${dir} ]] || mkdir -p ${dir}
564     [[ $keep_flac == yes ]] && fdir=${dir}/flac; mkdir -p ${fdir}
565 }
566         
567
568 # Store song titles, artist, and album names.
569 prep ()
570 {
571     zid=($(zdiscid))
572     tracks=$zid[2]
573
574     [[ -d ${TMPPREFIX} ]] || mkdir -p ${TMPPREFIX}
575
576     if [[ $online == yes ]]; then
577         do_online
578         do_offline
579     fi
580
581     typeset -A artist
582     typeset -A song
583     typeset -A filename
584
585     if [[ $zedit == yes && -n $rcfile ]]; then
586         _zedit=${EDITOR:-vi}
587         cat>$rcfile<<EOF
588 The format of this file is...
589     Artist Name|Track Title
590 One "record" per line.  Punctuation and whitespace is OK.
591 You MUST delete these instructions before saving.
592 EOF
593         $_zedit $rcfile
594     fi
595
596     if [[ -z $album ]]; then
597         echo -n "Please enter the name of this album: "
598         read album
599         echo
600     fi
601
602     [[ -n $dir ]] || _album_to_dir
603
604     if [[ ! -d ${dir} ]]; then
605         mkdir -p ${dir}
606         if [[ $keep_flac == yes && ! -d ${fdir} ]]; then
607             mkdir -p ${fdir}
608         fi
609     fi
610
611     if [[ -z $year ]]; then
612         echo -n "Please enter the year this album was released: "
613         read year
614         echo
615     fi
616
617     if [[ -z $genre ]]; then
618         echo -n "Please enter the genre of this album: "
619         read genre
620         echo
621     fi
622
623     zcomment=${zcomment:-"Encoded with $ourname"}
624
625     if [[ $prepargs[2] == yes ]]; then
626         for (( i=1; i<=$tracks; ++i )); do
627             if [[ -n $art ]]; then
628                 artist[$i]=$art
629             else
630                 echo -n "Track $i artist: "
631                 read art
632                 artist[$i]=$art
633                 unset art
634             fi
635             echo -n "Track $i title: "
636             read sg
637             song[$i]=$sg
638             filename[$i]=$sg
639         done
640     else
641         IFS="|"
642         i=0
643         while read art sg; do
644             (( ++i ))
645             artist[$i]=$art
646             sg=${sg/#[[:space:]]/}
647             sg=${sg//[[:cntrl:]]/}
648             song[$i]=${sg}
649             filename[$i]=${sg}
650         done < $prepargs[3]
651     fi
652
653     fnamefix $prepargs[1]
654     wavfile=dumpaudio.wav
655     ${prepargs[1]}rip
656
657     [[ -n $DEBUG ]] || cleanup
658 }
659
660 # Flac
661 flacenc ()
662 {
663     file=$1
664     shift                       # pop off $1 (flacfile)
665     flac -8 --delete-input-file -o ${fdir}/${file} ${1}
666     shift                       # pop off next arg (wavfile)
667     for tag in title artist album year genre tracknumber comment; do
668         metaflac --set-tag="$tag=${1}" ${fdir}/${file}
669         shift
670     done
671 }
672
673 flactomp3 ()
674 {
675     flac=$1
676     mp3=$2
677
678     # tags
679     title=$(metaflac --show-tag=title|cut -d= -f2)
680     artist=$(metaflac --show-tag=artist|cut -d= -f2)
681     album=$(metaflac --show-tag=album|cut -d= -f2)
682     year=$(metaflac --show-tag=year|cut -d= -f2)
683     genre=$(metaflac --show-tag=genre|cut -d= -f2)
684     track=$(metaflac --show-tag=tracknumber|cut -d= -f2)
685     comment=$(metaflac --show-tag=comment|cut -d= -f2)
686
687     flac -c -d $flac|lame -h --tt ${title} --ta ${artist} --tl ${album} \
688         --ty $year --tg $genre --tn $track --tc ${comment} - $mp3
689 }
690
691 # Encode to MP3
692 mp3rip ()
693 {
694     # Work around lame being too anal about genre
695     lame --genre-list|grep ${genre} 1>/dev/null || genre=Other
696
697     for (( i=1; i<=$tracks; ++i )); do
698         echo MP3-Ripping: $song[$i], by: $artist[$i], to: $filename[$i]
699         cdparanoia -X $i $wavfile
700         if [[ -f $wavfile ]]; then
701             if [[ $keep_flac == yes ]]; then
702                 flacfile=${filename[$i]/%mp3/flac}
703                 flacenc ${flacfile} ${wavfile} $song[$i] $artist[$i] $album \
704                     $year $genre $i $zcomment
705                 flactomp3 ${flacfile} ${dir}/$filename[$i]
706             else
707                 lame -h --tt $song[$i] --ta $artist[$i] --tl $album \
708                     --ty $year --tg $genre --tc $zcomment $wavfile \
709                     --tn $i ${dir}/$filename[$i]
710             fi
711         fi
712         [[ -f $wavfile ]] && rm -f $wavfile
713     done
714 }
715
716 # Encode to OGG Vorbis
717 oggrip ()
718 {
719     for (( i=1; i<=$tracks; ++i )); do
720         echo OGG-Ripping: $song[$i], by: $artist[$i], to: $filename[$i]
721         cdparanoia -X $i $wavfile
722         if [[ -f $wavfile ]]; then
723             if [[ $keep_flac == yes ]]; then
724                 flacfile=${filename[$i]/%ogg/flac}
725                 flacenc ${flacfile} ${wavfile} $song[$i] $artist[$i] $album \
726                     $year $genre $i $zcomment
727                 oggenc -q3 -o ${dir}/$filename[$i] ${fdir}/$flacfile
728             else
729                 oggenc -q3 -o ${dir}/$filename[$i] -t $song[$i] -a $artist[$i] \
730                     -l $album -d $year -G $genre -c "comment=$zcomment" \
731                     -N $i $wavfile
732                 rm $wavfile
733             fi
734         fi
735     done
736 }
737
738 # Make sure we have everything we need.
739 # This might be a little over the top, but I don't see any point in
740 # checking for `oggenc' if you are encoding to MP3, likewise, there's
741 # no point in checking for `lame' if you are encoding to Ogg Vorbis.
742 chkreqs ()
743 {
744     reqs=(cdparanoia lame oggenc flac)
745     whence -w $reqs[1] 1>/dev/null
746     if [[ $? -gt 0 ]]; then
747         echo $ourname: error: Missing $reqs[1] >&2
748         rv=3
749     fi
750     case $atype in
751         (mp3)
752             whence -w $reqs[2] 1>/dev/null
753             if [[ $? -gt 0 ]]; then
754                 echo $ourname: error: Missing $reqs[2] >&2
755                 rv=3
756            fi
757             ;;
758         (ogg)
759             whence -w $reqs[3] 1>/dev/null
760             if [[ $? -gt 0 ]]; then
761                 echo $ourname: error: Missing $reqs[3] >&2
762                 rv=3
763             fi
764             ;;
765     esac
766     if [[ $keep_flac == yes ]]; then
767         whence -w $reqs[4] 1>/dev/null
768         if [[ $? -gt 0 ]]; then
769             echo $ourname: error: Missing $reqs[4] >&2
770             rv=3
771         fi
772     fi
773     if [[ $rv -eq 3 ]]; then
774         exit $rv
775     else
776         return 0
777     fi
778 }
779         
780
781 # Command line parsing
782 args=mofihVO-:r:a:s:t:e:d:
783 flavour=0
784 rc=0
785 interactive=no
786 rcfile=" "
787 zedit=" "
788
789 while getopts $args opts; do
790     case $opts in
791         (-)
792             case $OPTARG in
793                 (mp3) atype=mp3; (( ++flavour )) ;;
794                 (ogg) atype=ogg; (( ++flavour )) ;;
795                 (edit_rcfile?*)
796                     rcfile=${OPTARG/edit_rcfile=/}
797                     (( ++rc ))
798                     zedit=yes
799                     ;;
800                 (flac_copy) keep_flac=yes ;;
801                 (type?*) atype=${OPTARG/type=/}; (( ++flavour )) ;;
802                 (interactive) interactive=yes; (( ++rc )) ;;
803                 (online) online=yes; (( ++rc )); rcfile=${TMPPREFIX}/zrcfile ;;
804                 (rcfile?*) rcfile=${OPTARG/rcfile=/}; (( ++rc )) ;;
805                 (album?*) album=${OPTARG/album=/} ;;
806                 (sameartist?*) art=${OPTARG/sameartist=/} ;;
807                 (dir?*) dir=${OPTARG/dir=/} ;;
808                 (version) _version; exit 0 ;;
809                 (help) cmd=usage; rv=0 ;;
810                 (*) 
811                     echo $ourname: error: bad option: --$OPTARG >&2
812                     exit 2
813                     ;;
814             esac
815             ;;
816         (i) interactive=yes; (( ++rc )) ;;
817         (O) online=yes; (( ++rc )); rcfile=${TMPPREFIX}/zrcfile ;;
818         (m) atype=mp3; (( ++flavour )) ;;
819         (o) atype=ogg; (( ++flavour )) ;;
820         (e) rcfile=$OPTARG; (( ++rc )); zedit=yes ;;
821         (f) keep_flac=yes ;;
822         (r) rcfile=$OPTARG; (( ++rc )) ;;
823         (a) album=$OPTARG ;;
824         (s) art=$OPTARG ;;
825         (t) atype=$OPTARG; (( ++flavour )) ;;
826         (d) dir=$OPTARG ;;
827         (V) _version; exit 0 ;;
828         (h) cmd=usage; rv=0 ;;
829         (*) rv=2 ;;
830     esac
831 done
832 shift $(( $OPTIND - 1 ))
833
834 if [[ $cmd != usage ]]; then
835     case $flavour in
836         (0)
837             echo $ourname: error: no audio format specified >&2
838             if [[ $rc -ne 1 ]]; then
839                 echo $ourname: error: improper use of interactice/rcfile option >&2
840             fi
841             rv=2
842             ;;
843         (1)
844             if [[ $rc -ne 1 ]]; then
845                 echo $ourname: error: improper use of interactive/rcfile option >&2
846                 rv=2
847             else
848                 typeset -A prepargs
849                 prepargs=(1 $atype 2 $interactive 3 $rcfile 4 $zedit)
850                 chkreqs
851                 prep $prepargs
852             fi
853             ;;
854         (*)
855             echo $ourname: error: multiple or invalid audio formats specified >&2
856             if [[ $rc -ne 1 ]]; then
857                 echo $ourname: error: improper use of interactice/rcfile option >&2
858             fi
859             rv=2
860             ;;
861     esac
862 else
863     usage
864 fi
865
866 exit $rv
867
868 ### zcdrip ends here