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