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