2 # Copyright (c) 1998-2001 Robert Woodcock <rcw@debian.org>
3 # Copyright (c) 2003-2006 Jesus Climent <jesus.climent@hispalinux.es>
4 # Copyright (c) 2009-2012 Colin Tuckley <colint@debian.org>
5 # Copyright (c) 2012-2019 Steve McIntyre <93sam@@debian.org>
6 # Copyright (c) 2015-2017 Andrew Strong <andrew.david.strong@gmail.com>
7 # This code is hereby licensed for public consumption under either the
8 # GNU GPL v2 or greater, or Larry Wall's Artistic license - your choice.
10 # You should have received a copy of the GNU General Public License along
11 # with this program; if not, write to the Free Software Foundation, Inc.,
12 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 echo "This is abcde v$VERSION."
19 echo "Usage: abcde [options] [tracks]"
21 echo "-1 Encode the whole CD in a single file"
22 echo "-a <action1[,action2]...>"
23 echo " Actions to perform, comma separated:"
24 echo " (cddb,read,getalbumart,embedalbumart,normalize,encode,"
25 echo " tag,move,replaygain,playlist,clean)"
26 #echo "-A Experimental actions (retag, transcode)"
27 echo "-b Enable batch normalization"
28 echo "-B Embed albumart (this also activates getalbumart)"
30 echo " Specify a configuration file (overrides system and user config files)"
32 echo " Specify discid to resume from (only needed if you no longer have the cd)"
34 echo " Specify CDROM device to grab (flac uses a single-track flac file)"
35 echo "-D Debugging mode (equivalent to sh -x abcde)"
36 echo "-e Erase encoded track information from status file"
37 echo "-f Force operations that otherwise are considered harmful. Read \"man abcde\""
38 echo "-g Use \"lame --nogap\" for MP3 encoding. Disables low disk and pipes flags"
39 echo "-G Get album art by using the 'getalbumart' action"
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 "-m Modify playlist to include CRLF endings, to comply with some players"
47 #echo " WARNING: Deprecated. Use \"cue\" action"
48 #echo "-M Create a CUE file"
49 echo "-n No lookup. Don't query CDDB, just create and use template"
50 echo "-N Noninteractive. Never prompt for anything"
51 echo "-o <type1[,type2]...>"
52 echo " Output file type(s), comma separated"
53 echo " (vorbis,mp3,flac,spx,mpc,wav,m4a,opus,mka,wv,ape,mp2,tta,aiff)."
54 echo " Defaults to vorbis"
55 echo "-O Allow Override of album art lookup"
56 echo "-p Pad track numbers with 0's (if less than 10 tracks)"
57 echo "-P Use UNIX pipes to read+encode without wav files"
58 echo "-Q CD lookup method(s), comma separated"
59 echo " (musicbrainz,cddb,cdtext). Defaults to musicbrainz".
60 echo "-r <host1[,host2]...>"
61 echo " Also encode on these remote hosts"
63 echo " Show fields from the CDDB info (year,genre)"
64 echo "-S <#> Set the CD speed"
65 echo "-t <#> Start the track numbering at a given number"
66 echo "-T <#> Same as -t but modifies tag numbering"
67 echo "-U Do NOT use UNICODE (UTF8) tags and comments"
68 echo "-v Show version number and exit"
69 echo "-V Be a bit more verbose about what is happening behind the scenes"
70 echo "-x Eject CD after all tracks are read"
72 echo " Add a comment to the CD tracks"
73 echo "-W <#> Concatenate CDs: -T #01 -w \"CD #\""
74 echo "-z Use debug CDROMREADERSYNTAX option (needs cdparanoia)"
76 echo "Tracks is a space-delimited list of tracks to grab."
77 echo "Ranges specified with hyphens are allowed (i.e., 1-5)."
79 #echo "Double hyphens are used to concatenate tracks"
84 echo "$@" >> "${ABCDETEMPDIR}/status"
87 # log [level] [message]
89 # log outputs the right message in a common format
95 error) >&2 echo "[ERROR] abcde: $@" >&2 ;;
96 warning) >&2 echo "[WARNING] $@" >&2 ;;
97 info) >&4 echo "[INFO] $@" ;;
101 # Functions to replace the need of seq, which is too distribution dependent.
115 if echo "$i" | grep "[[:digit:]]" > /dev/null 2>&1 ; then
123 log error "syntax error while processing track numbers ($i)"
128 # Functions to replace the need of awk {print $1} and {print $NF}
131 if [ X"$1" = "X" ]; then
132 for first in $(cat); do
143 if [ X"$1" = "X" ]; then
144 for stdin in $(cat); do
148 for last in $@ ; do :; done
153 # checkstatus [blurb]
154 # Returns "0" if the blurb was found, returns 1 if it wasn't
155 # Puts the blurb content, if available, on stdout.
156 # Otherwise, returns "".
159 # Take the last line in the status file if there's multiple matches
161 BLURB=$(grep -E "$PATTERN" "${ABCDETEMPDIR}/status" | tail -n 1)
163 if [ -z "$BLURB" ]; then
168 # See if there's a = in it
169 if ( echo "$BLURB" | grep -q '=' ); then
170 echo "$BLURB" | cut -f2- -d=
176 # checkwarnings [blurb]
177 # Returns "0" if the blurb was found (meaning there was an warning),
178 # returns 1 if it wasn't (yes this is a little backwards).
179 # Does not print the blurb on stdout.
180 # Otherwise, returns "".
183 if [ -e "${ABCDETEMPDIR}/warnings" ]; then :; else
186 # Take the last line in the status file if there's multiple matches
188 BLURB=$(grep -E "$PATTERN" "${ABCDETEMPDIR}/warnings" | tail -n 1)
190 if [ -z "$BLURB" ]; then
191 # negative, we did not have a negative...
194 # affirmative, we had a negative...
199 # checkerrors [blurb]
200 # Returns "0" if the blurb was found (meaning there was an error),
201 # returns 1 if it wasn't (yes this is a little backwards).
202 # Does not print the blurb on stdout.
203 # Otherwise, returns "".
206 if [ -e "${ABCDETEMPDIR}/errors" ]; then :; else
209 # Take the last line in the status file if there's multiple matches
211 BLURB=$(grep -E "$PATTERN" "${ABCDETEMPDIR}/errors" | tail -n 1)
213 if [ -z "$BLURB" ]; then
214 # negative, we did not have a negative...
217 # affirmative, we had a negative...
223 # Display a file. If it's too long to fit the current terminal size,
224 # find the right pager in the system and use it
228 local NUM_LINES=$(wc -l < "$PAGEFILE")
231 # Check the terminal length every time we're called - the user
232 # might have resized since last time we were here
234 if new_checkexec tput; then
238 # If tput didn't work, 24 will do...
239 if [ -z "$LINES" ]; then
243 # Is the text long enough to need a pager?
244 if [ "$NUM_LINES" -ge $LINES ]; then
246 # Use the debian sensible-pager wrapper to pick the pager user
247 # has requested via their $PAGER environment variable
248 if [ -x "/usr/bin/sensible-pager" ]; then
249 /usr/bin/sensible-pager "$PAGEFILE"
250 elif [ -x "$PAGER" ]; then
251 # That failed, try to load the preferred pager, starting
252 # with their PAGER variable
254 # If that fails, check for less
255 elif [ -x /usr/bin/less ]; then
256 /usr/bin/less -f "$PAGEFILE"
257 # more should be on all UNIX systems
258 elif [ -x /bin/more ]; then
259 /bin/more "$PAGEFILE"
261 # No bananas, just cat the thing
265 # No, just cat the thing
270 # run_command [blurb] [command...]
271 # Runs a command, silently if necessary, and updates the status file
277 # See if this is supposed to be silent
278 if [ "$(checkstatus encode-output)" = "loud" ]; then
282 # Special case for SMP, since
283 # encoder output is never displayed, don't mute echos
284 if [ -z "$BLURB" ] && [ "$MAXPROCS" != "1" ]; then
293 normalize|normalize-audio)
294 if [ "$RETURN" = "2" ]; then
295 # File was already normalized.
300 if [ "$RETURN" != "0" ]; then
301 # Put an error in the errors file. For various reasons we
302 # can't capture a copy of the program's output but we can
303 # log what we attempted to execute and the error code
304 # returned by the program.
305 if [ "$BLURB" ]; then
308 echo "${TWEAK}returned code $RETURN: $@" >> "${ABCDETEMPDIR}/errors"
309 return $RETURN # Do not pass go, do not update the status file
311 if [ "$BLURB" ]; then
312 echo "$BLURB" >> "${ABCDETEMPDIR}/status"
316 # relpath() and slash() are Copyright (c) 1999 Stuart Ballard and
317 # distributed under the terms of the GNU GPL v2 or later, at your option
319 # Function to determine if a word contains a slash.
328 # Function to give the relative path from one file to another.
329 # Usage: relpath fromfile tofile
330 # eg relpath music/Artist/Album.m3u music/Artist/Album/Song.mp3
331 # (the result would be Album/Song.mp3)
332 # Output is relative path to $2 from $1 on stdout
334 # This code has the following restrictions:
335 # Multiple ////s are not collapsed into single /s, with strange effects.
336 # Absolute paths and ../s are handled wrong in FR (but they work in TO)
337 # If FR is a directory it must have a trailing /
345 /*) ;; # No processing is needed for absolute paths
347 # Loop through common prefixes, ignoring them.
348 while slash "$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
350 FR="$(echo "$FR" | cut -d/ -f2-)"
351 TO="$(echo "$TO" | cut -d/ -f2-)"
353 # Loop through directory portions left in FR, adding appropriate ../s.
356 FR="$(echo "$FR" | cut -d/ -f2-)"
367 if [ ! "$@" = "" ]; then
368 # Cut off any command-line option we added in
369 X=$(echo "$@" | cut -d' ' -f2)
370 WHICH=$(which "$X" 2>/dev/null)
371 if [ -z "$WHICH" ]; then
373 elif [ ! -x "$WHICH" ]; then
382 if [ ! "$@" = "" ]; then
383 # Cut off any command-line option we added in
384 X=$(echo "$@" | cut -d' ' -f2)
385 # Test for built-in abcde.function
386 [ "$X" != "${X#abcde.}" ] && type "$X" >/dev/null 2>&1 && return
387 WHICH=$(which "$X" 2>/dev/null)
388 if [ -z "$WHICH" ]; then
389 log error "$X is not in your path." >&2
390 log info "Define the full path to the executable if it exists on your system." >&2
391 if [ -e /etc/debian_version ] ; then
394 MISSING_PACKAGE=vorbis-tools
396 lame|flac|cd-discid|eject|mkcue|icedax|glyrc)
400 log info "Hint: sudo apt-get install $MISSING_PACKAGE" >&2
403 elif [ ! -x "$WHICH" ]; then
404 log error "$X is not executable." >&2
410 # diffentries <filename> <max_value> <entry1>,<entry2>
411 # max_value: the range of entries goes from 1 to <max_value>
416 local CDDBDIFFCHOICES=$1
418 local CDDBDIFFCHOICE="$@"
419 if [ ! X"$DIFF" = "X" ]; then
420 PARSECHOICE1=$(echo "$CDDBDIFFCHOICE" | cut -d"," -f1 | xargs printf %d 2>/dev/null)
421 PARSECHOICE2=$(echo "$CDDBDIFFCHOICE" | cut -d"," -f2 | xargs printf %d 2>/dev/null)
422 if [ "$PARSECHOICE1" -lt 1 ] || [ "$PARSECHOICE1" -gt "$CDDBDIFFCHOICES" ] || \
423 [ "$PARSECHOICE2" -lt 1 ] || [ "$PARSECHOICE2" -gt "$CDDBDIFFCHOICES" ] || \
424 [ "$PARSECHOICE1" -eq "$PARSECHOICE2" ]; then
425 echo "Invalid diff range." >&2
426 echo "Please select two comma-separated numbers between 1 and $CDDBDIFFCHOICES" >&2
428 # We parse the 2 choices to diff, store them in temporary files and diff them.
429 for PARSECHOICE in $(echo "$CDDBDIFFCHOICE" | tr , \ ); do
430 do_cddbparse "${ABCDETEMPDIR}/$FILENAME.$PARSECHOICE" > "${ABCDETEMPDIR}/$FILENAME.parsechoice.$PARSECHOICE"
432 echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "${ABCDETEMPDIR}/$FILENAME.diff"
433 $DIFF $DIFFOPTS "${ABCDETEMPDIR}/$FILENAME.parsechoice.$PARSECHOICE1" \
434 "${ABCDETEMPDIR}/$FILENAME.parsechoice.$PARSECHOICE2" >> "${ABCDETEMPDIR}/$FILENAME.diff"
435 page "${ABCDETEMPDIR}/$FILENAME.diff"
438 echo "The diff program was not found in your path." >&2
439 echo "Please choose a number between 0 and $CDDBDIFFCHOICES." >&2
444 # Finds an specific field from cddbinfo
449 TRACKNAME="$(grep -a "^TTITLE$CDDBTRACKNUM=" "$CDDBDATA" | head -n 1 | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
452 TRACKNAME="$(grep -a "^TTITLE$CDDBTRACKNUM=" "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
455 grep -a "^EXTT$CDDBTRACKNUM=" "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\\n/\n/g'
461 # Get the track number we are going to use for different actions
464 if [ -n "$STARTTRACKNUMBER" ] ; then
465 # Get the trackpadding from the current track, also trim whitespace for MacOSX
466 CURRENTTRACKPADDING=$(echo -n "$UTRACKNUM" | wc -c | tr -d ' ')
467 REALTRACKNUM=$(expr $UTRACKNUM + 0) # Unpad
468 TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $((${REALTRACKNUM} + ${STARTTRACKNUMBER} - ${FIRSTTRACK})))
470 TRACKNUM=${UTRACKNUM}
476 # Calculate cddb disc ids without requiring specialized helper programs.
477 # largely copied from cd-discid and musicbrainz examples. some of the steps
478 # don't make sense, but they're necessary to match the ids generated by other
481 ## FIXME ## Right now, we get 2 frames more than with cue2discid ??
482 # data@petit:~$ sh /tmp/cue2discid /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac
483 # processing offsetimes 00:00:00 04:47:10 08:20:37 11:46:46 17:45:36 21:41:57 27:32:21 32:03:73 35:39:28 38:27:33 43:50:38 44:42:34
484 # 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2895
485 # data@petit:~$ metaflac --export-cuesheet-to=- /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac| python /home/data/sources/abcde/trunk/examples/cue2discid
486 # 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2893
488 # Variables: OFFSETS, TRACKS, LEADOUT, [LEADIN]
491 if [ X"$LEADOUT" = "X" ]; then
492 log warning "Error trying to calculate disc ids without lead-out information."
496 # default to a two second lead-in
498 LEADIN=${LEADIN:=150}
500 # number of cdframes per second
503 # reset cddb checksum for cddb disc-id calululation
507 for OFFSET in $OFFSETS
509 COOKEDOFFSETS="${COOKEDOFFSETS} $(($OFFSET + $LEADIN))"
511 OFFSETTIME=$(( ($OFFSET + $LEADIN) / $CDFRAMES ))
512 while [ $OFFSETTIME -gt 0 ]; do
513 CDDBCKSUM=$(($CDDBCKSUM + $OFFSETTIME % 10))
514 OFFSETTIME=$(($OFFSETTIME / 10))
519 COOKEDOFFSETS="${COOKEDOFFSETS:1}" # eat the leading space
521 PREGAP=$(echo $OFFSETS | cut -f1 -d' ')
522 TOTALTIME=$(( (($LEADOUT + $LEADIN + $PREGAP) / $CDFRAMES) - (($LEADIN + $PREGAP) / $CDFRAMES)))
524 vvecho "makeids: PREGAP $PREGAP, LEADIN $LEADIN, LEADOUT $LEADOUT"
526 # Calculate both the cddb discid *and* the musicbrainz discid
527 # now. We'll use the cddb discid for reference in most cases
528 # for consistency, but we also have the musicbrainz discid for
530 printf -v CDDBDISCID "%08lx" $(( ($CDDBCKSUM % 0xff) * 16777216 | $TOTALTIME * 256 | $TRACKS))
531 CDDBTRACKINFO="${CDDBDISCID} $((TRACKS)) ${COOKEDOFFSETS} $((($LEADOUT + $LEADIN + $IDMAGICNUM) / $CDFRAMES))"
535 # FIXME: don't assume the first track is 1
536 MBDISCID=$($MUSICBRAINZ --command calcid --discinfo 1 $TRACKS $LEADIN $(($PREGAP + $LEADOUT)) $OFFSETS)
538 if [ $error != 0 ]; then
539 log error "$MUSICBRAINZ failed to run; ABORT"
542 MBTRACKINFO="${MBDISCID} $((TRACKS)) ${COOKEDOFFSETS} $((($LEADOUT + $LEADIN + $IDMAGICNUM) / $CDFRAMES))"
549 if checkstatus replaygain; then :; else
550 run_command "" echo "Adding replaygain information..."
551 for TMPOUTPUT in $( echo "$OUTPUTTYPE" | tr , \ )
555 OUTPUT=$OGGOUTPUTCONTAINER
558 OUTPUT=$OPUSOUTPUTCONTAINER
561 OUTPUT=$FLACOUTPUTCONTAINER
569 for UTRACKNUM in $TRACKQUEUE
571 CDDBTRACKNUM=$(expr $UTRACKNUM - 1) # Unpad
572 getcddbinfo TRACKNAME
574 TRACKFILE="$(mungetrackname "$TRACKNAME")"
575 ARTISTFILE="$(mungeartistname "$TRACKARTIST")"
576 ALBUMFILE="$(mungealbumname "$DALBUM")"
577 GENRE="$(mungegenre "$GENRE")"
578 YEAR=${CDYEAR:-$CDYEAR}
580 if [ "$ONETRACK" = "y" ]; then
581 if [ "$VARIOUSARTISTS" = "y" ]; then
582 OUTPUTFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\")"
584 OUTPUTFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\")"
587 if [ "$VARIOUSARTISTS" = "y" ]; then
588 OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT"\")"
590 OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT"\")"
593 OUTPUTFILES[$REPLAYINDEX]="$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
594 (( REPLAYINDEX = $REPLAYINDEX + 1 ))
598 run_command "replaygain-flac" nice $ENCNICE $METAFLAC $FLACGAINOPTS "${OUTPUTFILES[@]}"
601 run_command "replaygain-vorbis" nice $ENCNICE $VORBISGAIN $VORBISGAINOPTS "${OUTPUTFILES[@]}"
604 run_command "replaygain-mp3" nice $ENCNICE $MP3GAIN $MP3GAINOPTS "${OUTPUTFILES[@]}"
607 run_command "replaygain-mpc" nice $ENCNICE $MPCGAIN "${OUTPUTFILES[@]}"
610 run_command "replaygain-wv" nice $ENCNICE $WVGAIN $WVGAINOPTS "${OUTPUTFILES[@]}"
615 if checkerrors "replaygain-.{3,6}"; then :; else
616 run_command "replaygain" true
621 # This code splits the a Various Artist track name from one of the following
624 # forward: Artist / Track
625 # forward-dash: Artist - Track
626 # reverse: Track / Artist
627 # reverse-dash: Track - Artist
628 # colon: Artist: Track
629 # trailing-paren: Artist (Track)
632 # VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
635 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
636 case "$VARIOUSARTISTSTYLE" in
638 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's- / -~-g')"
639 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
640 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
643 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's, - ,~,g')"
644 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
645 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
648 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's- / -~-g')"
649 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
650 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
653 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's, - ,~,g')"
654 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
655 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
658 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's-: -~-g')"
659 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
660 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
663 DTITLEARTIST="$(echo "$TRACKNAME" | sed 's,^\(.*\) (\(.*\)),\1~\2,')"
664 TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
665 TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
668 elif [ "$VARIOUSARTISTS" = "y" ] && [ "$ONETRACK" = "y" ]; then
669 TRACKARTIST="Various"
671 TRACKARTIST="$DARTIST"
676 local genre=$(echo "${@}" | tr 'A-Z' 'a-z')
680 "classic rock") id=1 ;;
698 "industrial") id=19 ;;
699 "alternative") id=20 ;;
701 "death metal") id=22 ;;
703 "soundtrack") id=24 ;;
704 "euro-techno") id=25 ;;
708 "jazz+funk") id=29 ;;
711 "classical") id=32 ;;
712 "instrumental") id=33 ;;
716 "sound clip") id=37 ;;
719 "alt. rock") id=40 ;;
724 "meditative") id=45 ;;
725 "instrum. pop") id=46 ;;
726 "instrum. rock") id=47 ;;
730 "techno-indust.") id=51 ;;
731 "electronic") id=52 ;;
733 "eurodance") id=54 ;;
735 "southern rock") id=56 ;;
740 "christian rap") id=61 ;;
741 "pop/funk"|"pop / funk") id=62 ;;
743 "native american") id=64 ;;
746 "psychadelic") id=67 ;;
748 "showtunes") id=69 ;;
752 "acid punk") id=73 ;;
753 "acid jazz") id=74 ;;
757 "rock & roll") id=78 ;;
758 "hard rock") id=79 ;;
760 "folk/rock") id=81 ;;
761 "national folk") id=82 ;;
768 "bluegrass") id=89 ;;
769 "avantgarde") id=90 ;;
770 "gothic rock") id=91 ;;
771 "progress. rock") id=92 ;;
772 "psychadel. rock") id=93 ;;
773 "symphonic rock") id=94 ;;
774 "slow rock") id=95 ;;
777 "easy listening") id=98 ;;
783 "chamber music") id=104 ;;
785 "symphony") id=106 ;;
786 "booty bass") id=107 ;;
788 "porn groove") id=109 ;;
790 "slow jam") id=111 ;;
794 "folklore") id=115 ;;
796 "power ballad") id=117 ;;
797 "rhythmic soul") id=118 ;;
798 "freestyle") id=119 ;;
800 "punk rock") id=121 ;;
801 "drum solo") id=122 ;;
802 "a capella") id=123 ;;
803 "euro-house") id=124 ;;
804 "dance hall") id=125 ;;
806 "drum & bass") id=127 ;;
807 "club-house") id=128 ;;
808 "hardcore") id=129 ;;
812 "negerpunk") id=133 ;;
813 "polsk punk") id=134 ;;
815 "christian gangsta rap") id=136 ;;
816 "heavy metal") id=137 ;;
817 "black metal") id=138 ;;
818 "crossover") id=139 ;;
819 "contemporary christian")id=140 ;;
820 "christian rock") id=141 ;;
821 "merengue") id=142 ;;
823 "thrash metal") id=144 ;;
826 "synthpop") id=147 ;;
827 "rock/pop"|"rock / pop") id=148 ;;
834 # do_tag [tracknumber]
835 # id3 tags a filename
837 # TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC,
838 # COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE
841 COMMENTOUTPUT="$(eval echo "${COMMENT}")"
842 if [ -z "$COMMENTOUTPUT" ]; then
843 COMMENTOUTPUT="$(getcddbinfo TRACK-INFO)"
845 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)
846 run_command "" echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
847 # If we want to start the tracks with a given number, we need to modify the
848 # TRACKNUM value before evaluation
849 if [ -n "$STARTTRACKNUMBERTAG" ] ; then
852 for OUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
856 # id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
857 GENREID=$(do_getgenreid "${CDGENRE}")
858 # Set TPE2 in case we have a Various Artists rip.
860 if [ "$VARIOUSARTISTS" = "y" ]; then
866 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE \
867 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
868 -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" \
869 -y "$CDYEAR" -g "$GENREID" \
870 -T "${TRACKNUM:-$1}" \
871 "${ABCDETEMPDIR}/track$1.$OUTPUT"
874 # FIXME # track numbers in mp3 come with 1/10, so we cannot
875 # happily substitute them with $TRACKNUM
876 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE \
877 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
878 -A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" \
879 -y "$CDYEAR" -g "$GENREID" \
880 -T "${TRACKNUM:-$1}/$TRACKS" \
881 ${TPE2:+--TPE2 "$TPE2"} \
882 "${ABCDETEMPDIR}/track$1.$OUTPUT"
885 # FIXME # track numbers in mp3 come with 1/10, so we cannot
886 # happily substitute them with $TRACKNUM
887 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE \
888 $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
889 -A "$DALBUM" -a "$TRACKARTIST" -s "$TRACKNAME" \
890 -y "$CDYEAR" -g "$GENREID" \
891 -t "${TRACKNUM:-$1}" ${TRACKNUM:+-T "$TRACKS"} \
892 "${ABCDETEMPDIR}/track$1.$OUTPUT"
895 # FIXME # track numbers in mp3 come with 1/10, so we cannot
896 # happily substitute them with $TRACKNUM
898 eyed3_06) addopts=( \
899 ${ENCODING:+--set-encoding="$ENCODING"} \
900 ${TPE2:+--set-text-frame=TPE2:"$TPE2"} \
901 # We set 'recording-date' so the date tag will show
902 # in Audacious, vlc and friends... Andrew.
903 ${CDYEAR:+--set-text-frame="TDRC:$CDYEAR"} \
904 ${COMMENTOUTPUT:+--comment=::"$COMMENTOUTPUT"} \
907 ${ENCODING:+--encoding="$ENCODING"} \
908 ${TPE2:+--text-frame=TPE2:"$TPE2"} \
909 # We set 'recording-date' so the date tag will show
910 # in Audacious, vlc and friends... Andrew.
911 ${CDYEAR:+--text-frame="TDRC:$CDYEAR"} \
912 ${COMMENTOUTPUT:+--comment "$COMMENTOUTPUT"} \
915 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE $TAGGER $TAGGEROPTS \
917 -a "$TRACKARTIST" -t "$TRACKNAME" \
918 -G "$GENREID" -n "${TRACKNUM:-$1}" \
919 ${TRACKNUM:+-N "$TRACKS"} \
921 "${ABCDETEMPDIR}/track$1.$OUTPUT"
924 log error "Internal error: ID3SYNTAX has an illegal value"
930 case "$OGGENCODERSYNTAX" in
932 # vorbiscomment can't do in-place modification, mv the file first
933 if [ -f "${ABCDETEMPDIR}/track$1.$OGGOUTPUTCONTAINER" ] && \
934 [ ! -f "${ABCDETEMPDIR}/track$1.uncommented.$OGGOUTPUTCONTAINER" ]; then
935 mv "${ABCDETEMPDIR}/track$1.$OGGOUTPUTCONTAINER" \
936 "${ABCDETEMPDIR}/track$1.uncommented.$OGGOUTPUTCONTAINER"
940 # https://www.xiph.org/vorbis/doc/v-comment.html
942 echo ARTIST="$TRACKARTIST"
944 echo TITLE="$TRACKNAME"
945 if [ -n "$CDYEAR" ]; then
948 if [ -n "$CDGENRE" ]; then
949 echo GENRE="$CDGENRE"
951 echo TRACKNUMBER="${TRACKNUM:-$1}"
952 # TRACKTOTAL is not in the proposed, minimal list of standard field names from
953 # xiph.org: https://www.xiph.org/vorbis/doc/v-comment.html but is in common usage
954 # and read by mediainfo, ffprobe, vlc, Aqualung, ogg123, Foobar. And now abcde :)
955 # The tag is quietly ignored by Audacious, MPlayer, mpv, XMMS....
956 echo TRACKTOTAL="${TRACKS}"
957 if [ -n "$DISCNUMBER" ]; then
958 echo DISCNUMBER="$DISCNUMBER"
960 echo CDDB="${CDDBDISCID}"
961 if [ "$(eval echo ${COMMENT})" != "" ]; then
962 case "$COMMENTOUTPUT" in
963 *=*) echo "$COMMENTOUTPUT";;
964 *) echo COMMENT="$COMMENTOUTPUT";;
967 ) | run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE \
968 $VORBISCOMMENT $VORBISCOMMENTOPTS -w \
969 "${ABCDETEMPDIR}/track$1.uncommented.$OGGOUTPUTCONTAINER" \
970 "${ABCDETEMPDIR}/track$1.$OGGOUTPUTCONTAINER"
971 # Doublecheck that the commented file was created
972 # successfully before wiping the original
973 if [ -f "${ABCDETEMPDIR}/track$1.$OGGOUTPUTCONTAINER" ]; then
974 rm -f "${ABCDETEMPDIR}/track$1.uncommented.$OGGOUTPUTCONTAINER"
976 mv "${ABCDETEMPDIR}/track$1.uncommented.$OGGOUTPUTCONTAINER" \
977 "${ABCDETEMPDIR}/track$1.$OGGOUTPUTCONTAINER"
983 run_command "tagtrack-$OUTPUT-$1" true
986 run_command "tagtrack-$OUTPUT-$1" true
989 run_command "tagtrack-$OUTPUT-$1" true
993 echo ARTIST="$TRACKARTIST"
995 echo TITLE="$TRACKNAME"
996 if [ -n "$CDYEAR" ]; then
999 if [ -n "$CDGENRE" ]; then
1000 echo GENRE="$CDGENRE"
1002 echo TRACKNUMBER="${TRACKNUM:-$1}"
1003 # TRACKTOTAL is not in the proposed, minimal list of standard field names from
1004 # xiph.org: https://www.xiph.org/vorbis/doc/v-comment.html but is in common usage
1005 # and read by mediainfo, ffprobe, vlc, Aqualung, ogg123, Foobar. And now abcde :)
1006 # The tag is quietly ignored by Audacious, MPlayer, mpv, XMMS....
1007 echo TRACKTOTAL="${TRACKS}"
1008 if [ -n "$DISCNUMBER" ]; then
1009 echo DISCNUMBER="$DISCNUMBER"
1011 echo CDDB="${CDDBDISCID}"
1012 if [ -n "$(eval echo "${COMMENT}")" ]; then
1013 case "$COMMENTOUTPUT" in
1014 *=*) echo "$COMMENTOUTPUT";;
1015 *) echo COMMENT="$COMMENTOUTPUT";;
1018 ) | run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE $METAFLAC $METAFLACOPTS \
1019 ${IMPORTCUESHEET:+--import-cuesheet-from="${ABCDETEMPDIR}/$CUEFILE"} \
1020 --import-tags-from=- "${ABCDETEMPDIR}/track$1.$FLACOUTPUTCONTAINER"
1023 run_command "tagtrack-$OUTPUT-$1" true
1026 run_command "tagtrack-$OUTPUT-$1" true
1029 run_command "tagtrack-$OUTPUT-$1" true
1032 # This tagging syntax is suitable for Robert Muth's application 'apetag', the Monkey's Audio
1033 # Console port (mac) used for encoding does not have the ability to tag.
1034 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE "$APETAG" -i "${ABCDETEMPDIR}/track$1.ape" -m overwrite \
1035 -p artist="$TRACKARTIST" -p album="$DALBUM" -p title="$TRACKNAME" -p track="${TRACKNUM:-$1}" \
1036 -p year="$CDYEAR" -p genre="$CDGENRE" ${COMMENTOUTPUT:+-p comment="$COMMENTOUTPUT"}
1039 # Using Mutagen's mid3v2 for tagging with id3v2.4.0. Interesting enough vlc, MPlayer and XMMS ignore
1040 # these tags but they are read by Audacious, Xine, Aqualung, mediainfo, ffplay, ffprobe. FFmpeg does
1041 # not currently tag mp2 audio so twolame and FFmpeg will both use mid3v2...
1042 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE "$MID3V2" --verbose -A "$DALBUM" \
1043 -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" -g "$CDGENRE" \
1044 -T "${TRACKNUM:-$1}/$TRACKS" ${TPE2:+--TPE2 "$TPE2"} \
1045 ${COMMENTOUTPUT:+--comment="$COMMENTOUTPUT"} \
1046 "${ABCDETEMPDIR}/track$1.mp2"
1049 run_command "tagtrack-$OUTPUT-$1" true
1052 case "$AACENCODERSYNTAX" in
1054 # We will use inline tagging...
1055 run_command "tagtrack-$OUTPUT-$1" true
1058 # Tag post encode with neroAacTag...
1059 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE "$NEROAACTAG" \
1060 "${ABCDETEMPDIR}/track$1.m4a" \
1061 -meta:artist="$TRACKARTIST" -meta:album="$DALBUM" \
1062 -meta:title="$TRACKNAME" -meta:track="${TRACKNUM:-$1}" \
1063 -meta:year="$CDYEAR" -meta:genre="$CDGENRE" -meta:comment="$COMMENT"
1066 run_command "tagtrack-$OUTPUT-$1" true
1069 run_command "tagtrack-$OUTPUT-$1" true
1072 # Tag post encode with AtomicParsley. Note that previous problems with seg fault when using
1073 # 'overWrite' cannot be reproduced with newer versions: https://bitbucket.org/wez/atomicparsley
1074 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE "$ATOMICPARSLEY" \
1075 "${ABCDETEMPDIR}/track$1.m4a" --artist="$TRACKARTIST" --album="$DALBUM" \
1076 --title="$TRACKNAME" --tracknum="${TRACKNUM:-$1}" \
1077 --year="$CDYEAR" --genre="$CDGENRE" --comment="$COMMENT" \
1078 $ATOMICPARSLEYOPTS --overWrite
1081 run_command "tagtrack-$OUTPUT-$1" true
1086 # We use mid3v2 tagging for True Audio:
1087 run_command "tagtrack-$OUTPUT-$1" nice $ENCNICE "$MID3V2" --verbose -A "$DALBUM" \
1088 -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" -g "$CDGENRE" \
1089 -T "${TRACKNUM:-$1}/$TRACKS" ${TPE2:+--TPE2 "$TPE2"} \
1090 ${COMMENTOUTPUT:+--comment="$COMMENTOUTPUT"} "${ABCDETEMPDIR}/track$1.tta"
1093 run_command "tagtrack-$OUTPUT-$1" true
1097 if checkerrors "tagtrack-(.{3,6})-$1"; then :; else
1098 run_command "tagtrack-$1" true
1104 # OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
1107 # The commands here don't go through run_command because they're never
1108 # supposed to be silenced
1109 echo "Encoding gapless MP3 tracks: $TRACKQUEUE"
1110 for OUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
1114 case "$MP3ENCODERSYNTAX" in
1117 cd "${ABCDETEMPDIR}"
1119 for THISTRACKNUM in $TRACKQUEUE
1121 TRACKFILES="$TRACKFILES track$THISTRACKNUM.wav"
1123 nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS --nogap $TRACKFILES
1125 if [ "$RETURN" != "0" ]; then
1126 echo "nogap-encode: $MP3ENCODER returned code $RETURN" >> "${ABCDETEMPDIR}/errors"
1128 for THISTRACKNUM in $TRACKQUEUE
1130 run_command "encodetrack-$OUTPUT-$THISTRACKNUM" true
1139 if checkerrors "nogap-encode"; then :; else
1140 if [ ! "$KEEPWAVS" = "y" ] ; then
1141 if [ ! "$KEEPWAVS" = "move" ] ; then
1146 # Other encoders fall through to normal encoding as the tracks have not
1147 # been entered in the status file.
1150 # do_encode [tracknumber] [hostname]
1151 # If no hostname is specified, encode locally
1153 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS,
1154 # DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
1157 if [ "$USEPIPES" = "y" ]; then
1160 TEMPARG="PIPE_$MP3ENCODERSYNTAX"
1163 TEMPARG="PIPE_$OGGENCODERSYNTAX"
1166 TEMPARG="PIPE_$OPUSENCODERSYNTAX"
1169 TEMPARG="PIPE_$MKAENCODERSYNTAX"
1172 TEMPARG="PIPE_$AIFFENCODERSYNTAX"
1175 TEMPARG="PIPE_$FLACENCODERSYNTAX"
1178 TEMPARG="PIPE_$SPEEXENCODER"
1181 TEMPARG="PIPE_$MPCENCODER"
1184 TEMPARG="PIPE_$WVENCODERSYNTAX"
1187 TEMPARG="PIPE_$TTAENCODERSYNTAX"
1190 TEMPARG="PIPE_$AACENCODERSYNTAX"
1193 TEMPARG="PIPE_$AACENCODERSYNTAX"
1196 IN="$( eval echo "\$$TEMPARG" )"
1198 IN="${ABCDETEMPDIR}/track$1.wav"
1200 # We need IN to proceed, if we are not using pipes.
1201 if [ -s "$IN" ] || [ X"$USEPIPES" = "Xy" ] ; then
1202 for TMPOUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
1204 case "$TMPOUTPUT" in
1206 OUTPUT=$OGGOUTPUTCONTAINER
1209 OUTPUT=$OPUSOUTPUTCONTAINER
1212 OUTPUT=$MKAOUTPUTCONTAINER
1215 OUTPUT=$AIFFOUTPUTCONTAINER
1218 OUTPUT=$FLACOUTPUTCONTAINER
1224 OUT="${ABCDETEMPDIR}/track$1.$OUTPUT"
1225 if [ "$NOGAP" = "y" ] && checkstatus "encodetrack-$OUTPUT-$1" ; then
1228 if [ X"$USEPIPES" = "Xy" ]; then
1230 # We need a way to store the creation of the files when using PIPES
1231 RUN_COMMAND_PIPES="run_command encodetrack-$OUTPUT-$1 true"
1232 # When piping it does not make sense to have a higher nice for
1233 # reading than for encoding, since it will be hold by the
1234 # encoding process. Setting an effective nice, to calm down a
1235 # bit the reading process.
1236 EFFECTIVE_NICE=$READNICE
1238 run_command "" echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
1239 RUN_COMMAND="run_command encodetrack-$OUTPUT-$1"
1240 EFFECTIVE_NICE=$ENCNICE
1246 case "$MP3ENCODERSYNTAX" in
1247 lame|gogo) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
1248 bladeenc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" "$OUT" ;;
1249 l3enc|xingmp3enc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
1250 mp3enc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
1254 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
1261 case "$OGGENCODERSYNTAX" in
1262 vorbize) $RUN_COMMAND nice $EFFECTIVE_NICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
1263 oggenc) $RUN_COMMAND nice $EFFECTIVE_NICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
1267 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
1274 case "$OPUSENCODERSYNTAX" in
1276 # Tag the file at encode time, as it can't be done after encoding.
1277 if [ "$DOTAG" = "y" ]; then
1278 $RUN_COMMAND nice $EFFECTIVE_NICE $OPUSENCODER $OPUSENCODEROPTS \
1279 --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" \
1280 --genre "$CDGENRE" --date "$CDYEAR" --comment TRACKNUMBER="$1" \
1281 ${COMMENT:+--comment COMMENT="$COMMENT"} "$IN" "$OUT"
1283 $RUN_COMMAND nice $EFFECTIVE_NICE $OPUSENCODER $OPUSENCODEROPTS "$IN" "$OUT"
1289 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
1294 case "$MKAENCODERSYNTAX" in
1296 if [ "$DOTAG" = "y" ]; then
1297 $RUN_COMMAND nice $EFFECTIVE_NICE $MKAENCODER -i "$IN" $MKAENCODEROPTS \
1298 -metadata artist="$TRACKARTIST" -metadata album="$DALBUM" \
1299 -metadata title="$TRACKNAME" -metadata track="${TRACKNUM:-$1}" \
1300 -metadata date="$CDYEAR" -metadata genre="$CDGENRE" \
1301 -metadata comment="$COMMENT" "$OUT"
1303 $RUN_COMMAND nice $EFFECTIVE_NICE $MKAENCODER -i "$IN" $MKAENCODEROPTS "$OUT"
1309 case "$AIFFENCODERSYNTAX" in
1311 if [ "$DOTAG" = "y" ]; then
1312 $RUN_COMMAND nice $EFFECTIVE_NICE $AIFFENCODER -i "$IN" $AIFFENCODEROPTS \
1313 -metadata artist="$TRACKARTIST" -metadata album="$DALBUM" \
1314 -metadata title="$TRACKNAME" -metadata track="${TRACKNUM:-$1}" \
1315 -metadata date="$CDYEAR" -metadata genre="$CDGENRE" \
1316 -metadata comment="$COMMENT" "$OUT"
1318 $RUN_COMMAND nice $EFFECTIVE_NICE $AIFFENCODER -i "$IN" $AIFFENCODEROPTS "$OUT"
1326 case "$FLACENCODERSYNTAX" in
1327 flac) $RUN_COMMAND nice $EFFECTIVE_NICE $FLACENCODER -f $FLACENCODEROPTS -o "$OUT" "$IN" ;;
1332 vecho "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
1333 $RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
1338 if [ -n "$(eval echo "${COMMENT}")" ]; then
1341 *) COMMENT="COMMENT=$COMMENT" ;;
1344 # Tag the file at encode time, as it can't be done after encoding.
1345 if [ "$DOTAG" = "y" ]; then
1346 $RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS \
1347 --author "$TRACKARTIST" --title "$TRACKNAME" \
1348 ${COMMENT:+--comment "$COMMENT"} "$IN" "$OUT"
1350 $RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
1354 # Tag the file inline at encode time.
1355 if [ "$DOTAG" = "y" ]; then
1356 $RUN_COMMAND nice $EFFECTIVE_NICE $MPCENCODER $MPCENCODEROPTS \
1357 --artist "$TRACKARTIST" --album "$DALBUM" \
1358 --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" \
1359 --year "$CDYEAR" ${COMMENT:+--comment "$COMMENT"} "$IN" "$OUT"
1361 $RUN_COMMAND nice $EFFECTIVE_NICE $MPCENCODER $MPCENCODEROPTS "$IN" "$OUT"
1365 case "$TTAENCODERSYNTAX" in
1366 # tta is the newer version with a small syntax change...
1368 $RUN_COMMAND nice $EFFECTIVE_NICE $TTAENCODER -e $TTAENCODEROPTS "$IN" "$OUT"
1371 $RUN_COMMAND nice $EFFECTIVE_NICE $TTAENCODER -e $TTAENCODEROPTS "$IN" -o "$OUT"
1376 case "$WVENCODERSYNTAX" in
1378 if [ "$DOTAG" = "y" ]; then
1379 $RUN_COMMAND nice $EFFECTIVE_NICE $WVENCODER $WVENCODEROPTS \
1380 -w Artist="$TRACKARTIST" -w Album="$DALBUM" \
1381 -w Title="$TRACKNAME" -w Track="$1" -w Genre="$CDGENRE" \
1382 -w Year="$CDYEAR" ${COMMENT:+-w Comment="$COMMENT"} "$IN" -o "$OUT"
1384 $RUN_COMMAND nice $EFFECTIVE_NICE $WVENCODER $WVENCODEROPTS "$IN" -o "$OUT"
1388 if [ "$DOTAG" = "y" ]; then
1389 $RUN_COMMAND nice $EFFECTIVE_NICE $WVENCODER -i "$IN" $WVENCODEROPTS \
1390 -metadata artist="$TRACKARTIST" \
1391 -metadata album="$DALBUM" -metadata title="$TRACKNAME" \
1392 -metadata track="${TRACKNUM:-$1}" -metadata date="$CDYEAR" \
1393 -metadata genre="$CDGENRE" -metadata comment="$COMMENT" "$OUT"
1395 $RUN_COMMAND nice $EFFECTIVE_NICE $WVENCODER -i "$IN" $WVENCODEROPTS "$OUT"
1401 $RUN_COMMAND nice $EFFECTIVE_NICE $APENCODER "$IN" "$OUT" $APENCODEROPTS
1404 case "$MP2ENCODERSYNTAX" in
1406 $RUN_COMMAND nice $EFFECTIVE_NICE $MP2ENCODER $MP2ENCODEROPTS "$IN" "$OUT"
1409 $RUN_COMMAND nice $EFFECTIVE_NICE $MP2ENCODER -i "$IN" $MP2ENCODEROPTS "$OUT"
1414 # aac container is only used to catch faac encoded files where faac
1415 # is compiled without mp4 support (with libmp4v2).
1416 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER $AACENCODEROPTS -o "$OUT" "$IN"
1419 case "$AACENCODERSYNTAX" in
1421 if [ "$DOTAG" = "y" ]; then
1422 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER $AACENCODEROPTS \
1423 --artist "$TRACKARTIST" --album "$DALBUM" \
1424 --title "$TRACKNAME" --track "${TRACKNUM:-$1}" \
1425 --year "$CDYEAR" --genre "$CDGENRE" --comment "$COMMENT" -o "$OUT" "$IN"
1427 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER $AACENCODEROPTS -o "$OUT" "$IN"
1431 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER $AACENCODEROPTS -if "$IN" -of "$OUT"
1434 if [ "$DOTAG" = "y" ]; then
1435 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER $AACENCODEROPTS \
1436 --artist "$TRACKARTIST" --album "$DALBUM" \
1437 --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" \
1438 --date "$CDYEAR" --comment "$COMMENT" "$IN" -o "$OUT"
1440 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER $AACENCODEROPTS "$IN" -o "$OUT"
1444 if [ "$DOTAG" = "y" ]; then
1445 $RUN_COMMAND nice $EFFECTIVE_NICE $WINE $AACENCODER $AACENCODEROPTS \
1446 --artist "$TRACKARTIST" --album "$DALBUM" \
1447 --title "$TRACKNAME" --track "${TRACKNUM:-$1}" \
1448 --date "$CDYEAR" --genre "$CDGENRE" --comment "$COMMENT" -o "$OUT" "$IN"
1450 $RUN_COMMAND nice $EFFECTIVE_NICE $WINE $AACENCODER $AACENCODEROPTS -o "$OUT" "$IN"
1454 $RUN_COMMAND nice $EFFECTIVE_NICE $WINE $AACENCODER $AACENCODEROPTS "$IN" "$OUT"
1457 if [ "$DOTAG" = "y" ]; then
1458 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER -i "$IN" \
1459 $AACENCODEROPTS -metadata artist="$TRACKARTIST" \
1460 -metadata album="$DALBUM" -metadata title="$TRACKNAME" \
1461 -metadata track="${TRACKNUM:-$1}" -metadata date="$CDYEAR" \
1462 -metadata genre="$CDGENRE" -metadata comment="$COMMENT" "$OUT"
1464 $RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER -i "$IN" $AACENCODEROPTS "$OUT"
1470 # In case of wav output we need nothing. Just keep the wavs.
1471 # But we need the following to allow full logging and subsequent
1472 # successful cleaning of ${ABCDETEMPDIR}.
1473 echo "encodetrack-$OUTPUT-$UTRACKNUM" >> "${ABCDETEMPDIR}/status"
1478 # Only remove .wav if the encoding succeeded
1479 if checkerrors "encodetrack-(.{3,6})-$1"; then :; else
1480 run_command "encodetrack-$1" true
1481 if [ ! "$KEEPWAVS" = "y" ] ; then
1482 if [ ! "$KEEPWAVS" = "move" ] ; then
1488 run_command "" echo "HEH! The file we were about to encode disappeared:"
1489 run_command "" echo ">> $IN"
1490 run_command "encodetrack-$1" false
1494 # do_preprocess [tracknumber]
1496 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX,
1497 # OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
1500 # IN="${ABCDETEMPDIR}/track$1.wav"
1501 # # We need IN to proceed.
1502 # if [ -s "$IN" ] ; then
1503 # for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
1505 # #OUT="${ABCDETEMPDIR}/track$1.$OUTPUT"
1506 # run_command "" echo "Pre-processing track $1 of $TRACKS..."
1507 # case "$POSTPROCESSFORMAT" in
1509 # run_command "preprocess-$OUTPUT-$1" nice $PRENICE $WAV_PRE $IF $OF ;;
1511 # run_command "preprocess-$OUTPUT-$1" nice $PRENICE $MP3_PRE $IF $OF ;;
1513 # run_command "preprocess-$OUTPUT-$1" nice $PRENICE $OGG_PRE $IF $OF ;;
1515 # run_command "preprocess-$OUTPUT-$1" nice $PRENICE $FLAC_PRE $IF $OF ;;
1517 # run_command "preprocess-$OUTPUT-$1" nice $PRENICE $SPX_PRE $IF $OF ;;
1520 # # Only remove .wav if the encoding succeeded
1521 # if checkerrors "preprocess-(.{3,4})-$1"; then
1522 # run_command "preprocess-$1" false
1524 # run_command "preprocess-$1" true
1527 # if [ "$(checkstatus encode-output)" = "loud" ]; then
1528 # echo "HEH! The file we were about to pre-process disappeared:"
1531 # run_command "preprocess-$1" false
1536 # do_postprocess [tracknumber]
1538 # TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS,
1539 # DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
1542 # for POSTPROCESSFORMAT in $(echo $POSTPROCESSFORMATS | tr , \ )
1544 # IN="${ABCDETEMPDIR}/track$1.$POSTPROCESSFORMAT"
1545 # # We need IN to proceed.
1546 # if [ -s "$IN" ] ; then
1547 # #OUT="${ABCDETEMPDIR}/track$1.$OUTPUT"
1548 # run_command "" echo "Post-processing track $1 of $TRACKS..."
1549 # case "$POSTPROCESSFORMAT" in
1551 # run_command "postprocess-$OUTPUT-$1" nice $POSTNICE $MP3_POST $IF $OF ;;
1553 # run_command "postprocess-$OUTPUT-$1" nice $POSTNICE $OGG_POST $IF $OF ;;
1555 # run_command "postprocess-$OUTPUT-$1" nice $POSTNICE $FLAC_POST $IF $OF ;;
1557 # run_command "postprocess-$OUTPUT-$1" nice $POSTNICE $SPX_POST $IF $OF ;;
1559 # # Only remove .wav if the encoding succeeded
1560 # if checkerrors "postprocess-(.{3,4})-$1"; then
1561 # run_command "postprocess-$1" false
1563 # run_command "postprocess-$1" true
1566 # if [ "$(checkstatus encode-output)" = "loud" ]; then
1567 # echo "HEH! The file we were about to post-process disappeared:"
1570 # run_command "postprocess-$1" false
1585 # MP3GAIN, MP3GAINOPTS, VORBISGAIN, VORBISGAINOPTS, MPCGAIN
1589 # The commands here don't go through run_command because they're never supposed to be silenced
1590 echo "Batch analizing gain in tracks: $TRACKQUEUE"
1592 cd "${ABCDETEMPDIR}"
1595 for UTRACKNUM in $TRACKQUEUE
1597 TRACKFILES="$TRACKFILES track$UTRACKNUM.mp3"
1599 # FIXME # Hard-coded batch option!
1600 $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
1602 if [ "$RETURN" != "0" ]; then
1603 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> "${ABCDETEMPDIR}/errors"
1605 for UTRACKNUM in $TRACKQUEUE
1607 echo "normalizetrack-$UTRACKNUM" >> "${ABCDETEMPDIR}/status"
1613 # do_batch_normalize
1615 # NORMALIZER, NORMALIZEROPTS
1616 do_batch_normalize ()
1618 # The commands here don't go through run_command because they're never supposed to be silenced
1619 echo "Batch normalizing tracks: $TRACKQUEUE"
1621 cd "${ABCDETEMPDIR}"
1624 for UTRACKNUM in $TRACKQUEUE
1626 TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
1628 # XXX: Hard-coded batch option!
1629 $NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
1631 if [ "$RETURN" != "0" ]; then
1632 echo "batch-normalize: $NORMALIZER returned code $RETURN" >> "${ABCDETEMPDIR}/errors"
1634 for UTRACKNUM in $TRACKQUEUE
1636 echo "normalizetrack-$UTRACKNUM" >> "${ABCDETEMPDIR}/status"
1642 # do_normalize [tracknumber]
1644 # TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
1647 IN="${ABCDETEMPDIR}/track$1.wav"
1648 if [ -e "$IN" ] ; then
1649 run_command "" echo "Normalizing track $1 of $TRACKS: $TRACKNAME..."
1650 run_command "normalizetrack-$1" $NORMALIZER $NORMALIZEROPTS "$IN"
1652 if [ "$(checkstatus encode-output)" = "loud" ]; then
1653 echo "HEH! The file we were about to normalize disappeared:"
1656 run_command "normalizetrack-$1" false "File $IN was not found"
1660 # do_move [tracknumber]
1661 # Deduces the outfile from environment variables
1662 # Creates directory if necessary
1664 # TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, CDYEAR
1667 for TMPOUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
1669 # For now, set OUTPUT as TMPOUTPUT, and then change it once we have
1670 # defined the OUTPUTFILE:
1673 # Create ALBUMFILE, ARTISTFILE, TRACKFILE
1674 ALBUMFILE="$(mungealbumname "$DALBUM")"
1675 ARTISTFILE="$(mungeartistname "$TRACKARTIST")"
1676 TRACKFILE="$(mungetrackname "$TRACKNAME")"
1677 GENRE="$(mungegenre "$GENRE")"
1678 YEAR=${CDYEAR:-$CDYEAR}
1679 # If we want to start the tracks with a given number, we need to modify
1680 # the TRACKNUM value before evaluation
1682 # Supported variables for OUTPUTFORMAT are GENRE, YEAR, ALBUMFILE,
1683 # ARTISTFILE, TRACKFILE, and TRACKNUM.
1684 if [ "$ONETRACK" = "y" ]; then
1685 if [ "$VARIOUSARTISTS" = "y" ]; then
1686 OUTPUTFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\")"
1688 OUTPUTFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\")"
1691 if [ "$VARIOUSARTISTS" = "y" ]; then
1692 OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT"\")"
1694 OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT"\")"
1697 if checkerrors "tagtrack-$OUTPUT-$1"; then :; else
1698 # Once we know the specific output was successful, we can change
1699 # the OUTPUT to the value containing the container
1702 OUTPUT=$OGGOUTPUTCONTAINER
1705 OUTPUT=$OPUSOUTPUTCONTAINER
1708 OUTPUT=$MKAOUTPUTCONTAINER
1711 OUTPUT=$AIFFOUTPUTCONTAINER
1714 OUTPUT=$FLACOUTPUTCONTAINER
1720 # Check that the directory for OUTPUTFILE exists, if it doesn't, create it
1721 OUTPUTFILEDIR="$(dirname "$OUTPUTDIR/$OUTPUTFILE")"
1724 if [ "$DOCLEAN" != "y" ] && [ "$FORCE" != "y" ]; then
1725 # FIXME # introduce warnings?
1728 # mkdir -p shouldn't return an error if the directory already exists
1729 mkdir -p "$OUTPUTFILEDIR"
1730 run_command "movetrack-$1" mv "${ABCDETEMPDIR}/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
1731 if checkstatus "movetrack-output-$OUTPUT"; then :; else
1732 run_command "movetrack-output-$OUTPUT" true
1737 # mkdir -p shouldn't return an error if the directory already exists
1738 mkdir -p "$OUTPUTFILEDIR"
1739 run_command "movetrack-$1" mv "${ABCDETEMPDIR}/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
1740 if checkstatus "movetrack-output-$OUTPUT"; then :; else
1741 run_command "movetrack-output-$OUTPUT" true
1745 # Lets move the cue file
1746 if CUEFILE=$(checkstatus cuefile) >/dev/null ; then
1747 if [ -r "${ABCDETEMPDIR}/$CUEFILE" ]; then
1748 if checkstatus "movecue-$OUTPUT"; then :; else
1749 # Silence the Copying output since it overlaps with encoding processes...
1750 #run_command "" vecho "Copying cue file to its destination directory..."
1751 if checkstatus onetrack >/dev/null ; then
1754 if [ "$DOCLEAN" != "y" ] && [ "$FORCE" != "y" ]; then
1755 # We dont have the dir, since it was not created before.
1758 run_command "movecue-$OUTPUT" cp "${ABCDETEMPDIR}/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.cue"
1761 # NOTE: Creating a cue file with the 3-char-extension files is to comply with
1762 # http://brianvictor.tripod.com/mp3cue.htm#details
1763 [a-z0-9][a-z0-9][a-z0-9])
1764 run_command "movecue-$OUTPUT" cp "${ABCDETEMPDIR}/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.cue"
1767 run_command "movecue-$OUTPUT" cp "${ABCDETEMPDIR}/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT.cue"
1771 run_command "movecue-$OUTPUT" cp "${ABCDETEMPDIR}/$CUEFILE" "$OUTPUTFILEDIR/$CUEFILE"
1773 echo "movecue-$OUTPUT" >> "${ABCDETEMPDIR}/status"
1782 # Create the playlist if wanted
1784 # PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
1785 # VARIOUSARTISTS, OUTPUTDIR
1788 for TMPOUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
1792 OUTPUT=$OGGOUTPUTCONTAINER
1795 OUTPUT=$OPUSOUTPUTCONTAINER
1798 OUTPUT=$MKAOUTPUTCONTAINER
1801 OUTPUT=$AIFFOUTPUTCONTAINER
1804 OUTPUT=$FLACOUTPUTCONTAINER
1810 # Create a playlist file for the playlist data to go into.
1811 # We used to wipe it out if it existed. Now we request permission if interactive.
1812 for LASTTRACK in $TRACKQUEUE; do :; done
1813 ALBUMFILE="$(mungealbumname "$DALBUM")"
1814 ARTISTFILE="$(mungeartistname "$DARTIST")"
1815 GENRE="$(mungegenre "$GENRE")"
1816 YEAR=${CDYEAR:-$CDYEAR}
1817 if [ "$VARIOUSARTISTS" = "y" ] ; then
1818 PLAYLISTFILE="$(eval echo "$VAPLAYLISTFORMAT")"
1820 PLAYLISTFILE="$(eval echo "$PLAYLISTFORMAT")"
1822 FINALPLAYLISTDIR="$(dirname "$OUTPUTDIR/$PLAYLISTFILE")"
1823 mkdir -p "$FINALPLAYLISTDIR"
1824 if [ -s "$OUTPUTDIR/$PLAYLISTFILE" ]; then
1825 echo -n "Erase, Append to, or Keep the existing playlist file? [e/a/k] (e): " >&2
1826 if [ "$INTERACTIVE" = "y" ]; then
1827 while [ "$DONE" != "y" ]; do
1829 case $ERASEPLAYLIST in
1830 e|E|a|A|k|K) DONE=y ;;
1831 "") ERASEPLAYLIST=e ; DONE=y ;;
1839 # Once we erase the playlist, we use append to create the new one.
1840 [ "$ERASEPLAYLIST" = "e" ] || [ "$ERASEPLAYLIST" = "E" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE" && ERASEPLAYLIST=a
1842 # The playlist does not exist, so we can safelly use append to create the new list
1845 if [ "$ERASEPLAYLIST" = "a" ] || [ "$ERASEPLAYLIST" = "A" ]; then
1846 touch "$OUTPUTDIR/$PLAYLISTFILE"
1847 for UTRACKNUM in $TRACKQUEUE
1849 # Shares some code with do_move since the filenames have to match
1850 CDDBTRACKNUM=$(expr $UTRACKNUM - 1) # Unpad
1851 getcddbinfo TRACKNAME
1853 TRACKFILE="$(mungetrackname "$TRACKNAME")"
1854 ARTISTFILE="$(mungeartistname "$TRACKARTIST")"
1855 ALBUMFILE="$(mungealbumname "$DALBUM")"
1856 # If we want to start the tracks with a given number, we need to modify the
1857 # TRACKNUM value before evaluation
1859 if [ "$VARIOUSARTISTS" = "y" ]; then
1860 OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT\"")"
1862 OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT\"")"
1864 if [ "$VARIOUSARTISTS" = "y" ]; then
1865 if [ "$VAPLAYLISTDATAPREFIX" ] ; then
1866 echo "${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1868 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1871 if [ "$PLAYLISTDATAPREFIX" ]; then
1872 echo "${PLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1874 relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
1879 ## this will convert the playlist to have CRLF line-endings, if specified
1880 ## (some hardware players insist on CRLF endings)
1881 if [ "$DOSPLAYLIST" = "y" ]; then
1882 awk '{sub("\r$",""); printf "%s\r\n", $0}' "$OUTPUTDIR/$PLAYLISTFILE" > "${ABCDETEMPDIR}/PLAYLISTFILE.tmp"
1883 cat "${ABCDETEMPDIR}/PLAYLISTFILE.tmp" | sed 's/\//\\/' > "$OUTPUTDIR/$PLAYLISTFILE"
1885 echo "playlistcomplete" >> "${ABCDETEMPDIR}/status"
1890 # This function reads a cuefile on stdin and writes an extended
1891 # cddb query on stdout. Any PREGAP for track 1 is properly
1892 # handled, although cue files embedded in FLAC files do not
1893 # appear to properly store the PREGAP setting. :(
1894 abcde.cue2discid () {
1899 while [ "$val" -gt 0 ] ; do
1900 ret=$(( $ret + ( $val % 10) ))
1901 val=$(( $val / 10 ))
1911 local first second third
1913 second=$(( $2 + 0 ))
1916 echo $(( ((($first * 60) + $second) * 75) + $third ))
1926 while read line ; do
1933 if [ "$2" -eq 1 ] ; then
1935 START=$(( $LBA + $PREGAP + $OFFSET ))
1937 X=$(cddb_sum $(( $START / 75 )) )
1942 PREGAP=$(msf2lba $2)
1947 LEADOUT=$(( $4 / 588 ))
1950 LEADIN=$(( $3 / 588 ))
1959 LEADOUT=$(( $LEADOUT + $LEADIN ))
1961 LENGTH=$(( $LEADOUT/75 - $TRACK1/75 ))
1962 CDDBDISCID=$(( ( $N % 255 ) * 2**24 | $LENGTH * 2**8 | $TRACKS ))
1963 printf %08x %i ${CDDBDISCID} $TRACKS
1966 while [ $j -le $TRACKS ] ; do
1967 eval echo -n "\" \$TRACK$j\""
1970 echo $(( $LEADOUT / 75 ))
1974 # abcde.mkcue [--wholedisk]
1975 # This creates a cuefile directly from the extended discid information
1976 # The --wholedisk option controls whether we're ripping data from the
1977 # start of track one or from the start of the disk (usually, but not
1978 # always the same thing!)
1980 # Track one leadin/pregap (if any) handeling:
1981 # --wholedisk specified:
1984 # INDEX 01 <pregap value>
1985 # Remaining track index values unchanged from disc TOC
1987 # --wholedisk not specified
1989 # PREGAP <pregap value>
1991 # Remaining track index values offset by <pregap value>
1998 printf "$1%02i:%02i:%02i\n" $(($2/4500)) $((($2/75)%60)) $(($2%75))
2001 local MODE DISCID TRACKS
2005 if [ "$1" = "--wholedisk" ] ; then
2011 vecho "One track is $ONETRACK"
2012 TRACKFILE="$(mungetrackname "$TRACKNAME")"
2013 ARTISTFILE="$(mungeartistname "$TRACKARTIST")"
2014 ALBUMFILE="$(mungealbumname "$DALBUM")"
2015 if [ "$ONETRACK" = "y" ]; then
2016 if [ "$VARIOUSARTISTS" = "y" ]; then
2017 CUEWAVFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\" | sed -e 's@^.*/@@').$OUTPUT"
2019 CUEWAVFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\" | sed -e 's@^.*/@@').$OUTPUT"
2021 vecho "Cue wav file is $CUEWAVFILE"
2023 CUEWAVFILE="dummy.wav"
2026 set -- $CDDBTRACKINFO
2032 echo "REM DISCID $DISCID"
2033 echo FILE \""$CUEWAVFILE"\" WAVE
2035 if [ $1 -ne 150 ] && [ $MODE = "PREGAP" ] ; then
2042 while [ $i -le "$TRACKS" ] ; do
2043 LBA=$(( $1 - $OFFSET ))
2044 printf " TRACK %02i AUDIO\n" $i
2045 if [ "$i" -eq 1 ] && [ "$1" -ne 150 ] ; then
2046 if [ "$MODE" = PREGAP ] ; then
2047 echomsf " PREGAP " $(($"OFFSET" - 150))
2049 echo " INDEX 00 00:00:00"
2052 echomsf " INDEX 01 " "$LBA"
2059 # This is essentially the start of things
2062 if [ -z "${CDDBDISCID}" ]; then
2063 vecho -n "Getting CD track info... "
2064 # In OSX, unmount the disc before a query
2065 if [ "$OSFLAVOUR" = "OSX" ]; then
2066 diskutil unmount "${CDROM#/dev/}"
2068 case "$CDROMREADERSYNTAX" in
2070 if $METAFLAC $METAFLACOPTS --export-cuesheet-to=- "$CDROM" > /dev/null 2>&1 ; then
2071 case "$CUE2DISCID" in
2072 # FIXME # right now we have 2 cue2discid internal
2073 # implementations: builtin and abcde.cue2discid. Test
2074 # both of them and decide which one we want to use.
2076 #vecho "Using builtin cue2discid implementation..."
2077 CUESHEET="$(metaflac $METAFLACOPTS --export-cuesheet-to=- "$CDROM")"
2079 #TRACKS=$(echo $CUESHEET | grep -E "TRACK \+[[:digit:]]\+ \+AUDIO" |wc -l)
2081 OFFSETTIMES=( $(echo "$CUESHEET" | sed -n -e's/\ *INDEX 01\ \+//p' ) )
2082 TRACKS=${#OFFSETTIMES[@]}
2084 vecho "processing offsetimes ${OFFSETTIMES[@]}"
2085 for OFFSETTIME in ${OFFSETTIMES[@]}; do
2086 OFFSETS="$OFFSETS $(( 10#${OFFSETTIME:0:2} * 4500 + 10#${OFFSETTIME:3:2} * 75 + 10#${OFFSETTIME:6:2} ))"
2089 LEADOUT=$(( $(echo "$CUESHEET" | grep lead-out | get_last) * 75 / 44100 ))
2090 LEADIN=$(( $(echo "$CUESHEET" | grep lead-in | get_last) * 75 / 44100 ))
2094 #vecho "Using external python cue2discid implementation..."
2095 CDDBTRACKINFO=$($METAFLAC $METAFLACOPTS --export-cuesheet-to=- "$CDROM" | $CUE2DISCID)
2099 log error "the input flac file does not contain a cuesheet."
2104 CDPARANOIAOUTPUT="$( $CDROMREADER -"$CDPARANOIACDROMBUS" "$CDROM" -Q --verbose 2>&1 )"
2106 if [ ! "$RET" = "0" ];then
2107 log warning "something went wrong while querying the CD... Maybe a DATA CD or the CD is not loaded?"
2110 TRACKS="$(echo "$CDPARANOIAOUTPUT" | grep -E '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ')"
2111 CDPARANOIAAUDIOTRACKS="$TRACKS"
2113 LEADOUT="$(echo "$CDPARANOIAOUTPUT" | grep -Eo '^TOTAL[[:space:]]+([[:digit:]]+)' | get_last)"
2114 OFFSETS="$(echo "$CDPARANOIAOUTPUT" | awk '/^ +.*\[/ {print $4}')"
2118 # Calculate the cddb discid in all
2119 # cases now. We'll use the cddb discid
2120 # for reference in most cases for
2121 # consistency. Also calculate the
2122 # musicbrainz discid if we need it.
2123 CDDBTRACKINFO=$($CDDISCID "$CDROM")
2124 if [ "$CDDISCID_NEEDS_PAUSE"x = "y"x ]; then
2127 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)
2128 case "$CDDBMETHOD" in
2130 MBTRACKINFO=$($MUSICBRAINZ --command id --device "$CDROM")
2132 if [ $error != 0 ]; then
2133 log error "$MUSICBRAINZ failed to run; ABORT"
2136 MBDISCID=$(echo "$MBTRACKINFO" | cut -d' ' -f1)
2140 # Make sure there's a CD in there by checking cd-discid's return code
2141 if [ ! "$?" = "0" ]; then
2142 if [ "$CDROMREADERSYNTAX" = "flac" ] ; then
2143 log error "cuesheet information from the flac file could not be read."
2144 log error "Perhaps the flac file does not contain a cuesheet?."
2147 log error "CD could not be read. Perhaps there's no CD in the drive?"
2151 # In OSX, remount the disc again
2152 if [ "$OSFLAVOUR" = "OSX" ]; then
2153 diskutil mount "${CDROM#/dev/}"
2156 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -f1 -d' ')
2158 CDDBTRACKINFO=$(cat "$WAVOUTPUTDIR/abcde.${CDDBDISCID}/cddbdiscid")
2161 # Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.
2162 # This needs to be done now because a section of the resuming code will need
2165 # get the number of digits to pad TRACKNUM with - we'll use this later
2166 # a CD can only hold 99 tracks, but since we support a feature for starting
2167 # numbering the tracks from a given number, we might need to set it as a
2168 # variable for the user to define... or obtain it somehow.
2169 if [ "$PADTRACKS" = "y" ] ; then
2173 ABCDETEMPDIR="$WAVOUTPUTDIR/abcde.${CDDBDISCID}"
2174 if [ -z "$TRACKQUEUE" ]; then
2175 if [ ! "$STRIPDATATRACKS" = "n" ]; then
2176 case "$CDROMREADERSYNTAX" in
2177 cdparanoia|libcdio|debug)
2178 if [ "$WEHAVEACD" = "y" ]; then
2179 vecho "Querying the CD for audio tracks..."
2180 CDPARANOIAOUTPUT="$( $CDROMREADER -"$CDPARANOIACDROMBUS" "$CDROM" -Q --verbose 2>&1 )"
2182 if [ ! "$RET" = "0" ];then
2183 log warning "something went wrong while querying the CD... Maybe a DATA CD?"
2185 TRACKS="$(echo "$CDPARANOIAOUTPUT" | grep -E '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ')"
2186 CDPARANOIAAUDIOTRACKS="$TRACKS"
2188 # Previous versions of abcde would store the tracks on a file, instead of the status record.
2189 if [ -f "${ABCDETEMPDIR}/cdparanoia-audio-tracks" ]; then
2190 echo "cdparanoia-audio-tracks=$( cat "${ABCDETEMPDIR}/cdparanoia-audio-tracks" )" >> "${ABCDETEMPDIR}/status"
2191 rm -f "${ABCDETEMPDIR}/cdparanoia-audio-tracks"
2193 if [ -f "${ABCDETEMPDIR}/status" ] && TRACKS=$(checkstatus cdparanoia-audio-tracks); then :; else
2194 TRACKS=$(echo "$CDDBTRACKINFO" | cut -f2 -d' ')
2198 *) TRACKS=$(echo "$CDDBTRACKINFO" | cut -f2 -d' ') ;;
2201 TRACKS=$(echo "$CDDBTRACKINFO" | cut -f2 -d' ')
2203 if echo "$TRACKS" | grep "[[:digit:]]" > /dev/null 2>&1 ;then :;else
2204 log info "The disc does not contain any tracks. Giving up..."
2207 echo -n "Grabbing entire CD - tracks: "
2208 if [ ! "$PADTRACKS" = "y" ] ; then
2209 TRACKNUMPADDING=$(echo -n $TRACKS | wc -c | tr -d ' ')
2212 TRACKS=$(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
2214 while [ $X -le $TRACKS ]
2216 PT=$(printf "%0.${TRACKNUMPADDING}d" $X)
2217 TRACKQUEUE="$TRACKQUEUE $PT"
2222 TRACKS=$(echo "$CDDBTRACKINFO" | cut -f2 -d' ')
2223 # User-supplied track queue.
2224 # Weed out non-numbers, whitespace, then sort and weed out duplicates
2225 TRACKQUEUE=$(echo "$TRACKQUEUE" | sed 's-[^0-9 ]--g' | tr ' ' '\n' | grep -v ^$ | sort -n | uniq | tr '\n' ' ' | sed 's- $--g')
2226 # Once cleaned, obtain the highest value in the trackqueue for number padding
2227 for LASTTRACK in $TRACKQUEUE; do :; done
2228 if [ ! "$PADTRACKS" = "y" ] ; then
2229 TRACKNUMPADDING=$(echo -n "$LASTTRACK" | wc -c | tr -d ' ')
2231 # Now we normalize the trackqueue
2232 for TRACK in $TRACKQUEUE; do
2233 PADTRACKNUM=$(printf "%0.${TRACKNUMPADDING}d" $(expr ${TRACK} + 0 ))
2234 PADTRACKQUEUE="$PADTRACKQUEUE $PADTRACKNUM"
2236 TRACKQUEUE="$PADTRACKQUEUE"
2237 echo Grabbing tracks: "$TRACKQUEUE"
2240 QUEUEDTRACKS=$(echo $TRACKQUEUE | wc -w | tr -d ' ')
2242 # We have the discid, create a temp directory after it to store all the temp
2245 if [ -e "${ABCDETEMPDIR}" ]; then
2246 echo -n "abcde: attempting to resume from ${ABCDETEMPDIR}"
2247 # It already exists, see if it's a directory
2248 if [ ! -d "${ABCDETEMPDIR}" ]; then
2249 # This is a file/socket/fifo/device/etc, not a directory
2252 echo "abcde: file ${ABCDETEMPDIR} already exists and does not belong to abcde." >&2
2253 echo "Please investigate, remove it, and rerun abcde." >&2
2257 # It's a directory, let's see if it's writable by us
2258 if [ ! -r "${ABCDETEMPDIR}" ] || [ ! -w "${ABCDETEMPDIR}" ] || [ ! -x "${ABCDETEMPDIR}" ]; then
2259 # Nope, complain and exit
2261 echo "abcde: directory ${ABCDETEMPDIR} already exists and is not writeable." >&2
2262 echo "Please investigate, remove it, and rerun abcde." >&2
2266 # Check to see the version of abcde that was used. If it's not
2267 # the same version as we are, bail.
2268 RESUME_VERSION="$(checkstatus abcde-version)"
2269 if [ "$RESUME_VERSION" != "$VERSION" ]; then
2270 # Nope, complain and exit
2272 echo "abcde: Working directory ${ABCDETEMPDIR} was created using version $RESUME_VERSION." >&2
2273 echo "abcde: Current version is $VERSION." >&2
2274 echo "abcde: Refusing to resume with a version mismatch." >&2
2275 echo "Please remove it, and rerun abcde." >&2
2279 # See if it's populated
2280 if [ ! -f "${ABCDETEMPDIR}/cddbdiscid" ]; then
2281 # Wipe and start fresh
2282 echo "abcde: ${ABCDETEMPDIR}/cddbdiscid not found. Abcde must remove and recreate" >&2
2283 echo -n "this directory to continue. Continue [y/N]? " >&2
2284 if [ "$INTERACTIVE" = "y" ]; then
2290 if [ "$ANSWER" != "y" ]; then
2293 rm -rf "${ABCDETEMPDIR}" || exit 1
2294 mkdir -p "${ABCDETEMPDIR}"
2295 if [ "$?" -gt "0" ]; then
2296 # Directory already exists or could not be created
2297 echo "abcde: Temp directory ${ABCDETEMPDIR} could not be created." >&2
2301 # Everything is fine. Check for ^encodetracklocation-
2302 # and encode-output entries in the status file and
2303 # remove them. These are not relevant across sessions.
2304 echo "Resuming" >> "${ABCDETEMPDIR}/status"
2305 if [ -f "${ABCDETEMPDIR}/status" ]; then
2306 mv "${ABCDETEMPDIR}/status" "${ABCDETEMPDIR}/status.old"
2307 grep -v ^encodetracklocation- < "${ABCDETEMPDIR}/status.old" \
2308 | grep -v ^encode-output > "${ABCDETEMPDIR}/status"
2310 # Remove old error messages
2311 if [ -f "${ABCDETEMPDIR}/errors" ]; then
2312 rm -f "${ABCDETEMPDIR}/errors"
2316 # We are starting from scratch
2317 mkdir -p "${ABCDETEMPDIR}"
2318 if [ "$?" -gt "0" ]; then
2319 # Directory already exists or could not be created
2320 echo "abcde: Temp directory ${ABCDETEMPDIR} could not be created." >&2
2323 cat /dev/null > "${ABCDETEMPDIR}/status"
2324 # Store the abcde version in the status file.
2325 echo "abcde-version=$VERSION" >> "${ABCDETEMPDIR}/status"
2327 if [ X"$DOCUE" = "Xy" ] && [ X"$WEHAVEACD" = "Xy" ]; then
2328 if checkstatus cuefile > /dev/null 2>&1 ; then :; else
2329 CUEFILE=cue-$(echo "$CDDBTRACKINFO" | cut -f1 -d' ').txt
2330 vecho "Creating cue file..."
2331 case "$CDROMREADERSYNTAX" in
2333 if $METAFLAC --export-cuesheet-to=- "$CDROM" > "${ABCDETEMPDIR}/$CUEFILE"; then
2334 echo "cuefile=$CUEFILE" >> "${ABCDETEMPDIR}/status"
2336 log warning "the input flac file does not contain a cuesheet."
2340 if $CUEREADER $CUEREADEROPTS > "${ABCDETEMPDIR}/$CUEFILE"; then
2341 echo "cuefile=$CUEFILE" >> "${ABCDETEMPDIR}/status"
2343 log warning "reading the CUE sheet is still considered experimental"
2344 log warning "and there was a problem with the CD reading. abcde will continue,"
2345 log warning "but consider reporting the problem to the abcde authors"
2351 # If we got the CDPARANOIA status and it is not recorded, save it now
2352 if [ -n "$CDPARANOIAAUDIOTRACKS" ]; then
2353 if checkstatus cdparanoia-audio-tracks > /dev/null 2>&1; then :; else
2354 echo "cdparanoia-audio-tracks=$CDPARANOIAAUDIOTRACKS" >> "${ABCDETEMPDIR}/status"
2358 # Create the discid files
2359 echo "$CDDBTRACKINFO" > "${ABCDETEMPDIR}/cddbdiscid"
2360 case "$CDDBMETHOD" in
2362 echo "$MBTRACKINFO" > "${ABCDETEMPDIR}/mbdiscid"
2368 # Create a proper CUE file based on the CUE file we created before.
2371 if CUEFILE_IN="${ABCDETEMPDIR}"/$(checkstatus cuefile); then
2372 CUEFILE_OUT=$CUEFILE_IN.out
2373 ### FIXME ### checkstatus cddb
2374 if [ -e "$CDDBDATA" ]; then
2375 vecho "Adding metadata to the cue file..."
2376 # FIXME It doesn't preserve spaces! Why?
2377 # FIXME parse $track into PERFORMER and TITLE - abcde already has code for this?
2379 echo "PERFORMER \"$DARTIST\"" >> "$CUEFILE_OUT"
2380 echo "TITLE \"$DALBUM\"" >> "$CUEFILE_OUT"
2381 # Set IFS to <newline> to prevent read from swallowing spaces and tabs
2385 cat "$CUEFILE_IN" | while read line
2387 if echo "$line" | grep "INDEX 01" > /dev/null 2>&1 ; then
2388 # FIXME # Possible patch: remove the line above, uncomment the 2 lines below.
2389 # echo "$line" >> "$CUEFILE_OUT"
2390 # if echo "$line" | grep "^[[:space:]]*TRACK" > /dev/null 2>&1 ; then
2391 eval track="\$TRACK$n"
2393 echo " TITLE \"$track\"" >> "$CUEFILE_OUT"
2394 # When making a single-track rip, put the
2395 # actual file name into the file declaration
2396 # in the cue file so that it is usable by
2397 # music players and the like
2398 elif [ "$ONETRACK" = "y" ] &&
2399 echo "$line" | grep '^FILE "dummy.wav" WAVE' > /dev/null 2>&1 ; then
2401 TRACKFILE="$(mungetrackname "$TRACKNAME")"
2402 ARTISTFILE="$(mungeartistname "$TRACKARTIST")"
2403 ALBUMFILE="$(mungealbumname "$DALBUM")"
2405 if [ "$VARIOUSARTISTS" = "y" ]; then
2406 OUTPUTFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\" | sed -e 's@^.*/@@').$OUTPUT"
2408 OUTPUTFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\" | sed -e 's@^.*/@@').$OUTPUT"
2411 echo "FILE \"$OUTPUTFILE\" WAVE" >> "$CUEFILE_OUT"
2414 # FIXME # If the lines above are uncommented, remove the line below.
2415 echo "$line" >> "$CUEFILE_OUT"
2418 mv "$CUEFILE_OUT" "$CUEFILE_IN"
2419 echo "cleancuefile" >> "${ABCDETEMPDIR}/status"
2425 # Parses a CDDB file and outputs the title and the track names.
2426 # Variables: CDDBFILE
2430 # List out disc title/author and contents
2431 if [ "$ONETRACK" = "y" ]; then
2432 vecho "ONETRACK mode selected: displaying only the title of the CD..."
2434 echo "---- $(grep -a DTITLE "${CDDBPARSEFILE}" | cut '-d=' -f2- | tr -d \\r\\n ) ----"
2435 if [ X"$SHOWCDDBYEAR" = "Xy" ]; then
2436 PARSEDYEAR=$(grep -a DYEAR "${CDDBPARSEFILE}" | cut '-d=' -f2-)
2437 if [ ! X"$PARSEDYEAR" = "X" ]; then
2438 echo "Year: $PARSEDYEAR"
2441 if [ X"$SHOWCDDBGENRE" = "Xy" ]; then
2442 PARSEDGENRE=$(grep -a DGENRE "${CDDBPARSEFILE}" | cut '-d=' -f2-)
2443 if [ ! X"$PARSEDGENRE" = "X" ]; then
2444 echo "Genre: $PARSEDGENRE"
2447 if [ ! "$ONETRACK" = "y" ]; then
2448 for TRACK in $(f_seq_row 1 $TRACKS)
2450 echo "$TRACK": "$(grep -a ^TTITLE$(($TRACK - 1))= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
2456 # Check for a local CDDB file, and report success
2457 do_localcddb_read ()
2459 if checkstatus cddb-readcomplete && checkstatus cddb-choice >/dev/null; then :; else
2461 CDDBLOCALSTATUS="notfound"
2462 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)
2465 if [ "$CDDBLOCALRECURSIVE" = "y" ]; then
2466 CDDBLOCALRESULTS="$(find "${CDDBLOCALDIR}" -name "${CDDBDISCID}" -type f 2> /dev/null)"
2467 if [ ! "${CDDBLOCALRESULTS}" = "" ]; then
2468 if (( $(echo "${CDDBLOCALRESULTS}" | wc -l) == 1 )); then
2469 CDDBLOCALFILE="${CDDBLOCALRESULTS}"
2470 CDDBLOCALMATCH=single
2471 elif (( $(echo "${CDDBLOCALRESULTS}" | wc -l) > 1 )); then
2472 CDDBLOCALMATCH=multiple
2477 elif [ "$CDDBLOCALMATCH" = "none" ] && [ -r "${CDDBLOCALDIR}/${CDDBDISCID}" ]; then
2478 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
2479 CDDBLOCALMATCH=single
2484 # If the user has selected to check a local CDDB repo, we proceed with it
2485 case $CDDBLOCALMATCH in
2487 echo "Processing multiple matching CDDB entries..." > "${ABCDETEMPDIR}/cddblocalchoices"
2489 echo "$CDDBLOCALRESULTS" | while read RESULT ; do
2491 # List out disc title/author and contents
2492 CDDBLOCALREAD="${ABCDETEMPDIR}/cddblocalread.$X"
2493 cat "$RESULT" > "${CDDBLOCALREAD}"
2496 do_cddbparse "${CDDBLOCALREAD}"
2498 ##FIXME## QUICK HACK !!!!
2499 if [ ! "$INTERACTIVE" = "y" ]; then break ; fi
2500 } >> "${ABCDETEMPDIR}/cddblocalchoices"
2502 page "${ABCDETEMPDIR}/cddblocalchoices"
2503 CDDBLOCALCHOICES=$( echo "$CDDBLOCALRESULTS" | wc -l )
2504 # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
2505 CDDBLOCALCHOICENUM=-1
2506 if [ "$INTERACTIVE" = "y" ]; then
2507 while [ "$CDDBLOCALCHOICENUM" -lt 0 ] || [ "$CDDBLOCALCHOICENUM" -gt "$CDDBLOCALCHOICES" ]; do
2508 echo "Locally cached CDDB entries found." >&2
2509 echo -n "Which one would you like to use (0 for none)? [0-$CDDBLOCALCHOICES]: " >&2
2510 read CDDBLOCALCHOICE
2511 [ x"$CDDBLOCALCHOICE" = "x" ] && CDDBLOCALCHOICE="1"
2512 # FIXME # Introduce diff's
2513 if echo $CDDBLOCALCHOICE | grep -E "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2514 diffentries cddblocalread "$CDDBLOCALCHOICES" "$CDDBLOCALCHOICE"
2515 elif echo $CDDBLOCALCHOICE | grep -E "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2516 # Make sure we get a valid choice
2517 CDDBLOCALCHOICENUM=$(echo $CDDBLOCALCHOICE | xargs printf %d 2>/dev/null)
2518 if [ "$CDDBLOCALCHOICENUM" -lt 0 ] || [ "$CDDBLOCALCHOICENUM" -gt "$CDDBLOCALCHOICES" ]; then
2519 echo "Invalid selection. Please choose a number between 0 and $CDDBLOCALCHOICES." >&2
2524 CDDBLOCALCHOICENUM=1
2526 if [ ! "$CDDBLOCALCHOICENUM" = "0" ]; then
2527 #echo "Using local copy of CDDB data"
2528 echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "${ABCDETEMPDIR}/cddbread.1"
2529 cat "${ABCDETEMPDIR}/cddblocalread.$CDDBLOCALCHOICENUM" >> "${ABCDETEMPDIR}/cddbread.1"
2530 echo "local" > "${ABCDETEMPDIR}/datasource.1"
2531 echo 999 > "${ABCDETEMPDIR}/cddbquery" # Assuming 999 isn't used by CDDB
2532 echo cddb-readcomplete >> "${ABCDETEMPDIR}/status"
2533 do_cddbparse "${ABCDETEMPDIR}/cddbread.1" > "${ABCDETEMPDIR}/cddbchoices"
2534 echo cddb-choice=1 >> "${ABCDETEMPDIR}/status"
2535 CDDBLOCALSTATUS="found"
2537 #echo "Not using local copy of CDDB data"
2538 CDDBLOCALSTATUS="notfound"
2542 # List out disc title/author and contents
2543 do_cddbparse "${CDDBLOCALFILE}"
2544 #if [ "$CDROMREADERSYNTAX" = "flac" ] ; then
2545 # echo -n "Embedded cuesheet entry found, use it [Y/n]? " >&2
2547 echo -n "Locally cached CDDB entry found, use it [Y/n]? " >&2
2549 if [ "$INTERACTIVE" = "y" ]; then
2551 while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
2552 echo -n 'Invalid selection. Please answer "y" or "n": ' >&2
2555 [ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
2559 if [ "$USELOCALRESP" = "y" ]; then
2560 #echo "Using local copy of CDDB data"
2561 echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "${ABCDETEMPDIR}/cddbread.1"
2562 cat "${CDDBLOCALFILE}" >> "${ABCDETEMPDIR}/cddbread.1"
2563 echo "local" > "${ABCDETEMPDIR}/datasource.1"
2564 echo 999 > "${ABCDETEMPDIR}/cddbquery" # Assuming 999 isn't used by CDDB
2565 echo cddb-readcomplete >> "${ABCDETEMPDIR}/status"
2566 do_cddbparse "${CDDBLOCALFILE}" > "${ABCDETEMPDIR}/cddbchoices"
2567 echo cddb-choice=1 >> "${ABCDETEMPDIR}/status"
2568 CDDBLOCALSTATUS="single"
2570 #echo "Not using local copy of CDDB data"
2571 CDDBLOCALSTATUS="notfound"
2575 CDDBLOCALSTATUS="notfound"
2582 # Try to read CD-Text from the drive using icedax / cdda2wav
2585 if new_checkexec icedax; then
2586 CDTEXT_READER=icedax
2587 elif new_checkexec cdda2wav; then
2588 CDTEXT_READER=cdda2wav
2590 # Didn't find either, bail
2594 if checkstatus cdtext-readcomplete; then
2595 NUM_RESPONSES=$(checkstatus "cdtext-entries")
2596 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + $NUM_RESPONSES))
2597 vecho "Re-using existing data from CD-Text"
2599 vecho "Obtaining CD-Text results..."
2600 local SOURCE_WORKDIR="${ABCDETEMPDIR}/data-cdtext"
2601 mkdir -p "${SOURCE_WORKDIR}"
2603 if [ "$OSFLAVOUR" = "OSX" ] ; then
2604 # Hei, we have to unmount the device before running anything like cdda2wav/icedax in OSX
2605 diskutil unmount "${CDROM#/dev/}"
2606 # Also, in OSX the cdrom device for cdda2wav/icedax changes...
2607 CDDA2WAVCDROM="IODVDServices"
2608 elif [ "$OSFLAVOUR" = "FBSD" ] || [ "$OSFLAVOUR" = "IRIX" ]; then
2609 CDDA2WAVCDROM="$CDROMID"
2611 if [ "$CDROMID" = "" ]; then
2612 CDDA2WAVCDROM="$CDROM"
2614 CDDA2WAVCDROM="$CDROMID"
2618 # Do we have CD-Text on the disc (and can the drive read it?)
2620 cd "${SOURCE_WORKDIR}" && rm -f audio.* audio_*
2621 # Even redirect fd 0 to our output file. It seems cdda2wav
2622 # writes to stdin too these days. Bizarre, buggy
2623 # behaviour! Should be harmless for icedax.
2624 ${CDTEXT_READER} -J -v titles -D "${CDDA2WAVCDROM}" > "${SOURCE_WORKDIR}/cd-text" 2>&1 0>&1
2626 grep -a -q '^CD-Text: detected' "${SOURCE_WORKDIR}/cd-text"
2628 if [ $ERRORCODE -ne 0 ]; then
2629 # No CD-Text found, bail
2633 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + 1))
2634 # Make an empty template
2635 $CDDBTOOL template "$(cat "${ABCDETEMPDIR}/cddbdiscid")" > "${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}"
2636 echo "cddb-read-${NUM_CDDB_MATCHES}-complete" >> "${ABCDETEMPDIR}/status"
2637 rm -f "${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}"
2639 # XXX FIXME - this is a hack and should be replaced by proper
2640 # character set tracking for the CDDB data we have.
2641 if [ "$CDDBPROTO" -ge 6 ]; then
2642 # convert to Unicode
2643 iconv -f iso-8859-1 -t utf-8 <"${SOURCE_WORKDIR}/audio.cddb" >"${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}"
2645 # copy verbatim, assuming CD-TEXT is in ISO-8859-1 format
2646 # apparently icedax/cdda2wav have no support for 16-bit
2647 # characters yet, either
2648 cp -p "${SOURCE_WORKDIR}/audio.cddb" "${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}"
2651 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)
2652 ATITLE=$(grep -a -e '^DTITLE=' "${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}" | cut -c8- | tr -d \\r\\n)
2653 echo "CD-Text" > "${SOURCE_WORKDIR}/datasource.${NUM_CDDB_MATCHES}"
2654 echo "none ${CDDBDISCID} ${ATITLE}" >> "${SOURCE_WORKDIR}/cddbquery.${NUM_CDDB_MATCHES}"
2657 cd "${SOURCE_WORKDIR}"
2658 rm -f audio_* audio.*
2659 for file in cddbread.* cddbquery.* datasource.*; do
2660 if [ -f "$file" ]; then
2661 cp "$file" "${ABCDETEMPDIR}"
2665 echo "cdtext-readcomplete" >> "${ABCDETEMPDIR}/status"
2666 echo "cdtext-entries=1" >> "${ABCDETEMPDIR}/status"
2670 # do_musicbrainz_read
2671 # Work with the musicbrainz WS API, then transform the results here so
2672 # they look (very) like the results from CDDB. Maybe not the best way
2673 # to go, but it Works For Me (TM)
2675 # List out all the matches individually into $SOURCE_WORKDIR/cddbread.X
2677 do_musicbrainz_read ()
2679 if checkstatus musicbrainz-readcomplete; then
2680 NUM_RESPONSES=$(checkstatus "musicbrainz-entries")
2681 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + $NUM_RESPONSES))
2682 vecho "Re-using existing data from $NUM_RESPONSES Musicbrainz match(es)"
2684 vecho "Obtaining Musicbrainz results..."
2685 # If MB is to be used, interpret the query results and read all
2686 # the available entries.
2687 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)
2688 MBDISCID=$(echo "$MBTRACKINFO" | cut -d' ' -f1)
2689 local SOURCE_WORKDIR="${ABCDETEMPDIR}/data-musicbrainz"
2690 mkdir -p "${SOURCE_WORKDIR}"
2691 ${MUSICBRAINZ} --command data --discid "${MBDISCID}" --workdir "${SOURCE_WORKDIR}" --start ${NUM_CDDB_MATCHES}
2693 if [ $error != 0 ]; then
2694 log error "$MUSICBRAINZ failed to run; ABORT"
2698 # Check for no matches.
2699 # The helper script will write disc matches out to
2700 # cddbread.*. Count how many we have
2701 NUM_RESPONSES=$(ls -1 "${SOURCE_WORKDIR}"/cddbread.* 2>/dev/null | wc -l)
2702 if [ $NUM_RESPONSES -gt 0 ] ; then
2703 # One or more exact matches
2705 while [ $i -le $NUM_RESPONSES ]; do
2706 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + 1))
2708 echo cddb-read-${NUM_CDDB_MATCHES}-complete >> "${ABCDETEMPDIR}/status"
2709 ATITLE=$(grep -a -e '^DTITLE=' "${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}" | cut -c8- | tr -d \\r\\n)
2710 echo "none ${CDDBDISCID} ${ATITLE}" >> "${SOURCE_WORKDIR}/cddbquery.${NUM_CDDB_MATCHES}"
2711 echo "Musicbrainz" > "${SOURCE_WORKDIR}/datasource.${NUM_CDDB_MATCHES}"
2712 cp -f "${SOURCE_WORKDIR}/"*."${NUM_CDDB_MATCHES}" "${ABCDETEMPDIR}"
2715 echo "musicbrainz-readcomplete" >> "${ABCDETEMPDIR}/status"
2716 echo "musicbrainz-entries=$NUM_RESPONSES" >> "${ABCDETEMPDIR}/status"
2723 local SOURCE_WORKDIR="${ABCDETEMPDIR}/data-cddb"
2724 mkdir -p "${SOURCE_WORKDIR}"
2730 # Perform CDDB protocol version check if it hasn't already been done
2731 if checkstatus cddb-statcomplete; then :; else
2732 if [ "$CDDBAVAIL" = "n" ]; then
2734 echo 503 > "${SOURCE_WORKDIR}/cddbstat"
2737 CDDBUSER=$(echo "$HELLOINFO" | cut -f1 -d'@')
2738 CDDBHOST=$(echo "$HELLOINFO" | cut -f2- -d'@')
2739 while [ $rc -eq 1 ] && [ "$CDDBPROTO" -ge 3 ]; do
2740 vecho "Checking CDDB server status..."
2741 $CDDBTOOL stat "$CDDBURL" "$CDDBUSER" "$CDDBHOST" "$CDDBPROTO" > "${SOURCE_WORKDIR}/cddbstat"
2742 RESPONSECODE=$(head -n 1 "${SOURCE_WORKDIR}/cddbstat" | cut -f1 -d' ')
2743 case "$RESPONSECODE" in
2744 210) # 210 OK, status information follows (until terminating `.')
2747 501) # 501 Illegal CDDB protocol level: <n>.
2748 CDDBPROTO=$(($CDDBPROTO - 1))
2750 *) # Try a cddb query, since freedb2.org doesn't support the stat or ver commands
2751 # FreeDB TESTCD disc-id is used for query
2752 $CDDBTOOL query "$CDDBURL" "$CDDBPROTO" "$CDDBUSER" "$CDDBHOST" 03015501 1 296 344 > "${SOURCE_WORKDIR}/cddbstat"
2753 RESPONSECODE=$(head -n 1 "${SOURCE_WORKDIR}/cddbstat" | cut -f1 -d' ')
2754 case "$RESPONSECODE" in
2755 2??) # Server responded, everything seems OK
2765 if [ $rc -eq 1 ]; then
2769 echo cddb-statcomplete >> "${ABCDETEMPDIR}/status"
2776 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)
2777 CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
2779 # Perform CDDB query if it hasn't already been done
2780 if checkstatus cddb-querycomplete; then :; else
2781 if [ "$CDDBAVAIL" = "n" ]; then
2783 echo 503 > "${SOURCE_WORKDIR}/cddbquery"
2784 # The default CDDBLOCALSTATUS is "notfound"
2785 # This part will be triggered if the user CDDB repo does not
2786 # contain the entry, or if we are not trying to use the repo.
2788 vecho "Querying the CDDB server..."
2789 CDDBUSER=$(echo "$HELLOINFO" | cut -f1 -d'@')
2790 CDDBHOST=$(echo "$HELLOINFO" | cut -f2- -d'@')
2791 $CDDBTOOL query "$CDDBURL" "$CDDBPROTO" "$CDDBUSER" "$CDDBHOST" "$CDDBTRACKINFO" > "${SOURCE_WORKDIR}/cddbquery"
2797 # no match found in database, wget/fetch error,
2798 # or user requested not to use CDDB. Make up an
2799 # error code (503) that abcde will recognize later
2800 # and compensate by making a template
2801 echo 503 > "${SOURCE_WORKDIR}/cddbquery"
2803 *) # strange and unknown error
2804 echo "ERRORCODE=$ERRORCODE"
2805 echo "abcde: $CDDBTOOL returned unknown error code"
2809 echo cddb-querycomplete >> "${ABCDETEMPDIR}/status"
2816 # If it's not to be used, generate a template.
2817 # Then, display it (or them) and let the user choose/edit it
2818 if checkstatus cddb-readcomplete; then
2819 NUM_RESPONSES=$(checkstatus "cddb-entries")
2820 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + $NUM_RESPONSES))
2821 vecho "Re-using existing data from $NUM_RESPONSES cddb match(es)"
2823 RESPONSECODE=$(head -n 1 "${SOURCE_WORKDIR}/cddbquery" | cut -f1 -d' ')
2824 vecho "Obtaining CDDB results..."
2825 case "$RESPONSECODE" in
2827 # One exact match, retrieve it
2828 # 200 [section] [discid] [artist] / [title]
2830 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + $NUM_RESPONSES))
2831 $CDDBTOOL read "$CDDBURL" "$CDDBPROTO" "$CDDBUSER" "$CDDBHOST" \
2832 $(cut -f2,3 -d' ' "${SOURCE_WORKDIR}/cddbquery") \
2833 > "${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}"
2834 cat "${SOURCE_WORKDIR}/cddbquery" | cut -f2- -d' ' > "${SOURCE_WORKDIR}/cddbquery.${NUM_CDDB_MATCHES}"
2835 echo "cddb" > "${SOURCE_WORKDIR}/datasource.${NUM_CDDB_MATCHES}"
2836 echo "cddb-read-${NUM_CDDB_MATCHES}-complete" >> "${ABCDETEMPDIR}/status"
2838 202|403|409|500|503)
2839 # TODO: Explain these error codes a little more accurately:
2840 # http://ftp.freedb.org/pub/freedb/misc/freedb_CDDB_protcoldoc.zip
2841 # No match response:
2844 # Multiple exact, (possibly multiple) inexact matches
2845 vecho -n "Retrieving multiple matches... "
2846 grep -v '^[.]$' "${SOURCE_WORKDIR}/cddbquery" | (
2847 # IN A SUB-SHELL - VARIABLES MODIFIED
2848 # HERE DO NOT PERSIST IN THE PARENT
2849 read DISCINFO # eat top line
2852 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + 1))
2853 if checkstatus "cddb-read-${NUM_CDDB_MATCHES}-complete"; then :; else
2854 $CDDBTOOL read "$CDDBURL" "$CDDBPROTO" "$CDDBUSER" "$CDDBHOST" \
2855 $(echo "$DISCINFO" | cut -f1,2 -d' ') \
2856 > "${SOURCE_WORKDIR}/cddbread.${NUM_CDDB_MATCHES}"
2857 echo "$DISCINFO" > "${SOURCE_WORKDIR}/cddbquery.${NUM_CDDB_MATCHES}"
2858 echo "cddb" > "${SOURCE_WORKDIR}/datasource.${NUM_CDDB_MATCHES}"
2859 echo "cddb-read-${NUM_CDDB_MATCHES}-complete" >> "${ABCDETEMPDIR}/status"
2862 # Need to re-count the entries here to be able
2863 # to incrememnt $NUM_CDDB_MATCHES in the
2865 NUM_RESPONSES=$(ls -1 "${SOURCE_WORKDIR}"/datasource.* 2>/dev/null | wc -l)
2866 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + $NUM_RESPONSES))
2872 NUM_CDDB_MATCHES=$(($NUM_CDDB_MATCHES + $NUM_RESPONSES))
2873 echo "cddb-read-${NUM_CDDB_MATCHES}-complete" >> "${ABCDETEMPDIR}/status"
2877 cd "${SOURCE_WORKDIR}"
2878 for file in cddbread.* cddbquery.* datasource.*; do
2879 if [ -f "$file" ]; then
2880 cp "$file" "${ABCDETEMPDIR}"
2884 echo "cddb-readcomplete" >> "${ABCDETEMPDIR}/status"
2885 echo "cddb-entries=$NUM_RESPONSES" >> "${ABCDETEMPDIR}/status"
2892 if checkstatus cddb-edit >/dev/null; then
2893 CDDBDATA="${ABCDETEMPDIR}/cddbread.$(checkstatus cddb-choice)"
2894 VARIOUSARTISTS="$(checkstatus variousartists)"
2895 VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
2898 if [ "$INTERACTIVE" = "y" ]; then
2899 # We should show the CDDB results both when we are not using the local CDDB repo
2900 # or when we are using it but we could not find a proper match
2901 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
2902 # Display the ${ABCDETEMPDIR}/cddbchoices file created above
2903 if [ -r "${ABCDETEMPDIR}/cddbchoices" ]; then
2904 CHOICE=$(checkstatus cddb-choice)
2905 if [ -n "$CHOICE" ] ; then
2906 case $NUM_CDDB_MATCHES in
2907 1) cat "${ABCDETEMPDIR}/cddbchoices" ;;
2909 ATITLE=$(grep -a ^DTITLE= "${ABCDETEMPDIR}/cddbread.$CHOICE" | cut -f2- -d= | tr -d \\r\\n)
2910 SOURCE=$(cat "${ABCDETEMPDIR}/datasource.$CHOICE")
2911 echo "Selected: #$CDCHOICENUM ($SOURCE) ($ATITLE)"
2912 do_cddbparse "${ABCDETEMPDIR}/cddbread.$CHOICE"
2916 page "${ABCDETEMPDIR}/cddbchoices"
2918 # Setting the choice to an impossible integer to avoid errors in the numeric comparisons
2920 # I'll take CDDB read #3 for $400, Alex
2921 while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $NUM_CDDB_MATCHES ]; do
2922 echo -n "Which entry would you like abcde to use (0 for none)? [0-$NUM_CDDB_MATCHES]: " >&2
2924 [ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
2925 if echo $CDDBCHOICE | grep -E "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2926 if [ ! X"$DIFF" = "X" ]; then
2927 PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
2928 PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
2929 if [ "$PARSECHOICE1" -lt 1 ] || [ "$PARSECHOICE1" -gt "$NUM_CDDB_MATCHES" ] || \
2930 [ "$PARSECHOICE2" -lt 1 ] || [ "$PARSECHOICE2" -gt "$NUM_CDDB_MATCHES" ] || \
2931 [ "$PARSECHOICE1" -eq "$PARSECHOICE2" ]; then
2932 echo "Invalid diff range." >&2
2933 echo "Please select two comma-separated numbers between 1 and $NUM_CDDB_MATCHES" >&2
2935 # We parse the 2 choices to diff, store them in temporary files and diff them.
2936 for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
2937 do_cddbparse "${ABCDETEMPDIR}/cddbread.$PARSECHOICE" \
2938 > "${ABCDETEMPDIR}/cddbread.parsechoice.$PARSECHOICE"
2940 echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." \
2941 > "${ABCDETEMPDIR}/cddbread.diff"
2942 $DIFF $DIFFOPTS "${ABCDETEMPDIR}/cddbread.parsechoice.$PARSECHOICE1" \
2943 "${ABCDETEMPDIR}/cddbread.parsechoice.$PARSECHOICE2" \
2944 >> "${ABCDETEMPDIR}/cddbread.diff"
2945 page "${ABCDETEMPDIR}/cddbread.diff"
2948 echo "The diff program was not found in your path." >&2
2949 echo "Please choose a number between 0 and $NUM_CDDB_MATCHES." >&2
2951 elif echo $CDDBCHOICE | grep -E "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
2952 # Make sure we get a valid choice
2953 CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
2954 if [ "$CDCHOICENUM" -lt 0 ] || [ "$CDCHOICENUM" -gt "$NUM_CDDB_MATCHES" ]; then
2955 echo "Invalid selection. Please choose a number between 0 and $NUM_CDDB_MATCHES." >&2
2959 if [ "$CDCHOICENUM" = "0" ]; then
2960 vecho "Creating empty CDDB template..."
2962 $CDDBTOOL template $(cat "${ABCDETEMPDIR}/cddbdiscid") > "${ABCDETEMPDIR}/cddbread.0"
2963 echo "template" > "${ABCDETEMPDIR}/datasource.0"
2965 ATITLE=$(grep -a ^DTITLE= "${ABCDETEMPDIR}/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n)
2966 SOURCE=$(cat "${ABCDETEMPDIR}/datasource.$CDCHOICENUM")
2967 echo "Selected: #$CDCHOICENUM ($SOURCE) ($ATITLE)" >&2
2969 do_cddbparse "${ABCDETEMPDIR}/cddbread.$CDCHOICENUM"
2970 echo "cddb-choice=$CDCHOICENUM" >> "${ABCDETEMPDIR}/status"
2974 # We need some code to show the selected option when local repository is selected and we have found a match
2975 vecho "Using cached CDDB match..." >&2
2976 # Display the ${ABCDETEMPDIR}/cddbchoices file created above
2977 if [ -r "${ABCDETEMPDIR}/cddbchoices" ]; then
2978 CHOICE=$(checkstatus cddb-choice)
2979 if [ "$USELOCALRESP" = "y" ]; then :; else
2980 if [ -n "$CHOICE" ] ; then
2981 case $NUM_CDDB_MATCHES in
2984 echo "Selected template."
2986 1) cat "${ABCDETEMPDIR}/cddbchoices" ;;
2988 echo "Selected: #$CHOICE"
2989 do_cddbparse "${ABCDETEMPDIR}/cddbread.$CHOICE"
2997 # We're noninteractive - pick the first choice.
2998 # But in case we run a previous instance and selected a choice, use it.
2999 if [ -r "${ABCDETEMPDIR}/cddbchoices" ]; then
3000 # Show the choice if we are not using the locally stored one
3001 # or when the local search failed to find a match.
3002 PREVIOUSCHOICE=$(checkstatus cddb-choice)
3003 if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
3004 #if [ "$PREVIOUSCHOICE" ]; then
3005 cat "${ABCDETEMPDIR}/cddbchoices"
3008 if [ ! -z "$PREVIOUSCHOICE" ] ; then
3009 CDCHOICENUM=$PREVIOUSCHOICE
3012 echo "cddb-choice=$CDCHOICENUM" >> "${ABCDETEMPDIR}/status"
3014 echo "Selected: #$CDCHOICENUM ($(grep -a ^DTITLE= "${ABCDETEMPDIR}/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
3019 if checkstatus cddb-choice >/dev/null; then :; else
3020 echo "abcde: internal error: cddb-choice not recorded." >&2
3023 CDDBDATA="${ABCDETEMPDIR}/cddbread.$(checkstatus cddb-choice)"
3024 CDDBSOURCE=$(cat "${ABCDETEMPDIR}/datasource.$(checkstatus cddb-choice)")
3025 echo -n "Edit selected CDDB data " >&2
3026 if [ "$INTERACTIVE" = "y" ]; then
3027 if [ "$UNKNOWNDISK" = "y" ]; then
3028 echo -n "[Y/n]? " >&2
3030 [ "$EDITCDDB" != "n" ] && EDITCDDB=y
3032 echo -n "[y/N]? " >&2
3039 if [ "$EDITCDDB" = "y" ]; then
3040 CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
3042 # Use the debian sensible-editor wrapper to pick the editor that the
3043 # user has requested via their $EDITOR environment variable
3044 if [ -x "/usr/bin/sensible-editor" ]; then
3045 /usr/bin/sensible-editor "$CDDBDATA"
3046 elif [ -n "$EDITOR" ]; then
3047 if [ -x "$(which "${EDITOR%%\ *}")" ]; then
3048 # That failed, try to load the preferred editor, starting
3049 # with their EDITOR variable
3052 # If that fails, check for a vi
3053 elif which vi >/dev/null 2>&1; then
3055 elif [ -x /usr/bin/vim ]; then
3056 /usr/bin/vim "$CDDBDATA"
3057 elif [ -x /usr/bin/vi ]; then
3058 /usr/bin/vi "$CDDBDATA"
3059 elif [ -x /bin/vi ]; then
3061 # nano should be on all (modern, i.e., sarge) debian systems
3062 elif which nano >/dev/null 2>&1 ; then
3064 elif [ -x /usr/bin/nano ]; then
3065 /usr/bin/nano "$CDDBDATA"
3066 # mg should be on all OpenBSD systems
3067 elif which mg >/dev/null 2>&1 ; then
3069 elif [ -x /usr/bin/mg ]; then
3070 /usr/bin/mg "$CDDBDATA"
3073 log warning "no editor available. Check your EDITOR environment variable."
3075 # delete editor backup file if it exists
3076 if [ -w "$CDDBDATA~" ]; then
3081 # Some heuristics first. Look at Disc Title, and if it starts with
3082 # "Various", then we'll assume Various Artists
3083 if [ "$(grep -a ^DTITLE= "$CDDBDATA" | cut -f2- -d= | grep -aEci '^(various|soundtrack|varios|sonora|ost)')" != "0" ]; then
3084 echo "Looks like a Multi-Artist CD" >&2
3087 echo -n "Is the CD multi-artist [y/N]? " >&2
3088 if [ "$INTERACTIVE" = "y" ]; then
3095 if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
3098 # Need NUMTRACKS before cddb-tool will return it:
3099 NUMTRACKS=$(grep -a -E '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
3100 if [ "$(grep -ac "^TTITLE.*\/" "$CDDBDATA")" -gt "$(( $NUMTRACKS / 2 ))" ]; then
3101 # More than 1/2 tracks contain a "/", so guess forward
3103 elif [ "$(grep -ac "^TTITLE.*\-" "$CDDBDATA")" -gt "$(( $NUMTRACKS / 2 ))" ]; then
3104 # More than 1/2 contain a "-", so guess forward-dash
3106 elif [ "$(grep -ac "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(( $NUMTRACKS / 2 ))" ]; then
3107 # More than 1/2 contain something in parens, so guess trailing-paren
3111 echo "1) Artist / Title" >&2
3112 echo "2) Artist - Title" >&2
3113 echo "3) Title / Artist" >&2
3114 echo "4) Title - Artist" >&2
3115 echo "5) Artist: Title" >&2
3116 echo "6) Title (Artist)" >&2
3117 echo "7) This is a single-artist CD" >&2
3118 echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
3119 if [ "$INTERACTIVE" = "y" ]; then
3120 read VARIOUSARTISTSTYLE
3122 echo $DEFAULTSTYLE >&2
3123 VARIOUSARTISTSTYLE=$DEFAULTSTYLE
3125 VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
3126 # If they press Enter, then the default style (0) was chosen
3127 while [ "$VARIOUSARTISTSTYLE" -lt 0 ] || [ "$VARIOUSARTISTSTYLE" -gt 7 ]; do
3128 echo "Invalid selection. Please choose a number between 1 and 7."
3129 echo -n "Selection [1-7]: "
3130 read VARIOUSARTISTSTYLE
3131 VARIOUSARTISTSTYLE=$(echo "0$VARIOUSARTISTSTYLE" | xargs printf "%d")
3133 if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
3134 VARIOUSARTISTSTYLE="$DEFAULTSTYLE"
3136 vecho "Selected: $VARIOUSARTISTSTYLE"
3137 case "$VARIOUSARTISTSTYLE" in
3139 VARIOUSARTISTSTYLE=forward
3142 VARIOUSARTISTSTYLE=forward-dash
3145 VARIOUSARTISTSTYLE=reverse
3148 VARIOUSARTISTSTYLE=reverse-dash
3151 VARIOUSARTISTSTYLE=colon
3154 VARIOUSARTISTSTYLE=trailing-paren
3162 echo "variousartists=$VARIOUSARTISTS" >> "${ABCDETEMPDIR}/status"
3163 echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "${ABCDETEMPDIR}/status"
3165 if [ "$EDITCDDB" = "y" ] && [ "$CDDBSOURCE" = "cddb" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
3166 if [ "$CDDBDATAMD5SUM" != "" ] && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
3167 # This works but does not have the necessary error checking
3168 # yet. If you are familiar with the CDDB spec
3169 # (see http://www.freedb.org/src/latest/DBFORMAT)
3170 # and can create an error-free entry on your own, then put
3171 # UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
3172 # abcde.conf to enable it. Put CDDBSUBMIT=email@address in
3173 # your abcde.conf to change the email address submissions are
3176 # submit the modified file, if they want
3177 if [ "$NOSUBMIT" != "y" ]; then
3178 echo -n "Do you want to submit this entry to $CDDBSUBMIT [y/N]? "
3180 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
3181 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
3183 echo -n 'Invalid selection. Please answer "y" or "n": '
3186 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
3187 echo -n "Sending..."
3188 $CDDBTOOL send "$CDDBDATA" "$CDDBSUBMIT"
3195 # User CDDBLOCALPOLICY to find out if we store the file or not...
3196 # Cache edited CDDB entry in the user's cddb dir
3197 if [ "$CDDBCOPYLOCAL" = "y" ]; then
3198 # Make sure the cache directory exists
3199 mkdir -p "$CDDBLOCALDIR"
3200 NUM_LINES=$(( $(wc -l < "$CDDBDATA") - 1 ))
3201 OUTPUT_FILE="$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)"
3202 tail -n "$NUM_LINES" < "$CDDBDATA" > "${CDDBLOCALDIR}/${OUTPUT_FILE}"
3205 echo "cddb-edit" >> "${ABCDETEMPDIR}/status"
3209 # try to download CD cover
3212 if checkstatus "get-album-art"; then :; else
3214 ALBUMFILE="$(mungealbumname "$DALBUM")"
3215 ARTISTFILE="$(mungeartistname "$DARTIST")"
3216 GENRE="$(mungegenre "$GENRE")"
3217 YEAR=${CDYEAR:-$CDYEAR}
3218 # have we got a musicbrainz mbid or amazon asin?
3219 case "$CDDBMETHOD" in
3221 # try musicbrainz mbid
3222 if [ -s "${ABCDETEMPDIR}/mbid.$(checkstatus cddb-choice)" ]; then
3223 MBID=$(cat "${ABCDETEMPDIR}/mbid.$(checkstatus cddb-choice)")
3224 vecho "trying to get cover from coverartarchive.orq with musicbrainz mbid $MBID" >&2
3225 ALBUMARTURL="http://coverartarchive.org/release/$MBID/front"
3226 vecho "cover URL: $ALBUMARTURL" >&2
3227 $HTTPGET "$ALBUMARTURL" > "${ABCDETEMPDIR}/$ALBUMARTFILE"
3228 if [ $? -ne 0 ]; then
3229 vecho "could not download cover from musicbrainz" >&2
3231 if [ -s "${ABCDETEMPDIR}/asin.$(checkstatus cddb-choice)" ]; then
3232 ASIN=$(cat "${ABCDETEMPDIR}/asin.$(checkstatus cddb-choice)")
3233 vecho "trying to get cover from amazon.com with asin $ASIN" >&2
3234 ALBUMARTURL="http://ec1.images-amazon.com/images/P/$ASIN.01.LZZZZZZZZ.jpg"
3235 vecho "cover URL: $ALBUMARTURL" >&2
3236 $HTTPGET "$ALBUMARTURL" > "${ABCDETEMPDIR}/$ALBUMARTFILE"
3237 if [ $? -ne 0 ]; then
3238 vecho "could not download cover from amazon" >&2
3240 # Check that size is reasonable; sometimes when there is no cover image
3241 # on amazon.com a 1x1 pixel gif image will be downloaded instead:
3242 FILESIZE=$(wc -c < "${ABCDETEMPDIR}/$ALBUMARTFILE")
3243 if [ "$FILESIZE" -lt 1024 ]; then
3244 rm "${ABCDETEMPDIR}/$ALBUMARTFILE"
3245 vecho "could not download cover from amazon" >&2
3249 vecho "no amazon ID found" >&2
3253 vecho "no musicbrainz ID found" >&2
3258 if [ ! -s "${ABCDETEMPDIR}/$ALBUMARTFILE" ]; then
3259 vecho "trying to get cover with glyrc for $ARTISTFILE / $ALBUMFILE" >&2
3260 env LC_ALL=C $GLYRC cover --artist "$ARTISTFILE" --album "$ALBUMFILE" --write "${ABCDETEMPDIR}/$ALBUMARTFILE" $GLYRCOPTS
3261 if [ $? -ne 0 ]; then
3262 vecho "could not download cover with glyrc" >&2
3267 if [ "$INTERACTIVE" = "y" ]; then
3268 if [ -s "${ABCDETEMPDIR}/$ALBUMARTFILE" ]; then
3269 # display properties of coverart when identify is available
3270 if new_checkexec "$IDENTIFY"; then
3271 $IDENTIFY $IDENTIFYOPTS "${ABCDETEMPDIR}/$ALBUMARTFILE" >&2
3273 # display coverart when DISPLAY is set and display command is available
3274 if new_checkexec "$DISPLAYCMD" && [ "$DISPLAY" != "" ]; then
3275 $DISPLAYCMD $DISPLAYCMDOPTS "${ABCDETEMPDIR}/$ALBUMARTFILE" >&2 &
3278 # nothing downloaded yet
3279 vecho "automatic album art downloading failed" >&2
3281 # see if the user can find a better album art manually
3282 if [ ! -s "${ABCDETEMPDIR}/$ALBUMARTFILE" ] || \
3283 [ "$OVERRIDEALBUMARTDOWNLOAD" = "y" ]; then
3284 echo -n "Do you want to enter URL or local path for the album art [y/N]? " >&2
3286 while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
3287 [ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
3289 echo -n 'Invalid selection. Please answer "y" or "n": ' >&2
3292 if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
3293 echo -n "Enter URL or local path (ENTER to cancel) :" >&2
3295 if [ ! -z "$ALBUMARTURL" ]; then
3296 if [[ ${ALBUMARTURL} =~ (https?|ftp|file)://.* ]]; then
3297 $HTTPGET "$ALBUMARTURL" > "${ABCDETEMPDIR}/$ALBUMARTFILE"
3298 if [ ! -s "${ABCDETEMPDIR}/$ALBUMARTFILE" ]; then
3299 vecho "unable to download $ALBUMARTURL" >&2
3301 else # it's a local path
3302 cp "$ALBUMARTURL" "${ABCDETEMPDIR}/$ALBUMARTFILE"
3303 if [ ! -s "${ABCDETEMPDIR}/$ALBUMARTFILE" ]; then
3304 vecho "unable to copy $ALBUMARTURL to ${ABCDETEMPDIR}/$ALBUMARTFILE" >&2
3311 # convert to ALBUMARTTYPE if ImageMagick is available, if not assume correct type
3312 if [ -s "${ABCDETEMPDIR}/$ALBUMARTFILE" ] && new_checkexec "$IDENTIFY"; then
3313 ALBUMARTURLTYPE=$($IDENTIFY "${ABCDETEMPDIR}/$ALBUMARTFILE" | cut -d' ' -f2)
3314 if [ "$ALBUMARTURLTYPE" != "$ALBUMARTTYPE" ] || [ "$ALBUMARTALWAYSCONVERT" = "y" ]; then
3315 if new_checkexec "$CONVERT"; then
3316 mv "${ABCDETEMPDIR}/$ALBUMARTFILE" "${ABCDETEMPDIR}/$ALBUMARTFILE.tmp"
3317 $CONVERT "${ABCDETEMPDIR}/$ALBUMARTFILE.tmp" $CONVERTOPTS "${ABCDETEMPDIR}/$ALBUMARTFILE"
3318 rm -f "${ABCDETEMPDIR}/$ALBUMARTFILE.tmp"
3320 rm -f "${ABCDETEMPDIR}/$ALBUMARTFILE"
3321 vecho "sorry, cannot convert $ALBUMARTURLTYPE to $ALBUMARTTYPE" >&2
3322 vecho "without ImageMagick convert" >&2
3326 # copy to target directories
3327 if [ -s "${ABCDETEMPDIR}/$ALBUMARTFILE" ]; then
3328 for OUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
3330 # put cover in the same place as the album
3331 if [ "$ONETRACK" = "y" ] ; then
3332 if [ "$VARIOUSARTISTS" = "y" ] ; then
3333 ALBUMARTDIR="$(eval echo "$VAONETRACKOUTPUTFORMAT")"
3335 ALBUMARTDIR="$(eval echo "$ONETRACKOUTPUTFORMAT")"
3338 if [ "$VARIOUSARTISTS" = "y" ] ; then
3339 ALBUMARTDIR="$(eval echo "$VAOUTPUTFORMAT")"
3341 ALBUMARTDIR="$(eval echo "$OUTPUTFORMAT")"
3344 FINALALBUMARTDIR="$(dirname "$OUTPUTDIR/$ALBUMARTDIR")"
3345 vecho "copying cover to target directory $FINALALBUMARTDIR" >&2
3346 mkdir -p "$FINALALBUMARTDIR"
3347 cp "${ABCDETEMPDIR}/$ALBUMARTFILE" "$FINALALBUMARTDIR"
3349 rm -f "${ABCDETEMPDIR}/$ALBUMARTFILE"
3350 echo "get-album-art=$ALBUMARTURL" >> "${ABCDETEMPDIR}/status"
3352 log warning "could not get cover"
3353 echo "get-album-art=none" >> "${ABCDETEMPDIR}/status"
3358 # Optionally embed the albumart downloaded by the getalbumart fuction.
3359 # FIXME: It would be nice to have this also selectable from within the
3360 # FIXME: getalbumart function itself. Andrew
3364 ALBUMFILE="$(mungealbumname "$DALBUM")"
3365 ARTISTFILE="$(mungeartistname "$DARTIST")"
3366 GENRE="$(mungegenre "$GENRE")"
3367 YEAR=${CDYEAR:-$CDYEAR}
3369 # Allow for multiple output formats:
3370 for OUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
3372 # Find the output directory for multi track encodes:
3373 if [ "$ONETRACK" != "y" ] ; then
3374 if [ "$VARIOUSARTISTS" = "y" ] ; then
3375 FINDPATH="$(eval echo "$VAOUTPUTFORMAT")"
3377 FINDPATH="$(eval echo "$OUTPUTFORMAT")"
3380 # Find the output directory for single track encodes:
3381 if [ "$ONETRACK" = "y" ] ; then
3382 if [ "$VARIOUSARTISTS" = "y" ] ; then
3383 FINDPATH="$(eval echo "$VAONETRACKOUTPUTFORMAT")"
3385 FINDPATH="$(eval echo "$ONETRACKOUTPUTFORMAT")"
3389 FINALDIR="$(dirname "$OUTPUTDIR/$FINDPATH")"
3392 # Instructions for each format, feel free to add more. It would be nice to
3393 # make the backup directory selectable and perhaps also have an option for
3394 # the bold to simply have the image deleted. Work for another day... Andrew.
3395 if [ -e "$ALBUMARTFILE" ] ; then
3400 "$EYED3" --add-image "$ALBUMARTFILE":FRONT_COVER "$i"
3402 mkdir "$FINALDIR"/albumart_backup
3403 mv "$ALBUMARTFILE" "$FINALDIR"/albumart_backup
3404 vecho "Successfully embedded the album art into your $OUTPUT tracks" >&2
3409 "$METAFLAC" --import-picture-from="$ALBUMARTFILE" "$i"
3411 mkdir "$FINALDIR"/albumart_backup
3412 mv "$ALBUMARTFILE" "$FINALDIR"/albumart_backup
3413 vecho "Successfully embedded the album art into your $OUTPUT tracks" >&2
3418 "$ATOMICPARSLEY" "$i" --artwork "$ALBUMARTFILE" --overWrite
3420 mkdir "$FINALDIR"/albumart_backup
3421 mv "$ALBUMARTFILE" "$FINALDIR"/albumart_backup
3422 vecho "Successfully embedded the album art into your $OUTPUT tracks" >&2
3427 "$WVTAG" --write-binary-tag "Cover Art (Front)=@$ALBUMARTFILE" "$i"
3429 mkdir "$FINALDIR"/albumart_backup
3430 mv "$ALBUMARTFILE" "$FINALDIR"/albumart_backup
3431 vecho "Successfully embedded the album art into your $OUTPUT tracks" >&2
3435 # This technique is drawn from 2 sources (the first link being the primary source):
3436 # 1. https://github.com/biapy/howto.biapy.com/blob/master/various/mussync-tools
3437 # 2. https://github.com/acabal/scripts/blob/master/ogg-cover-art
3438 # In abcde a few steps are used in this sequence:
3440 # 1. Create a 'legal' header for the cover art image
3441 # 2. Makes a copy of the existing tags
3442 # 3. base64 the cover art image
3443 # 4. Copy the original tags + the base64 image back to the original ogg file
3445 # Might need some fine tuning but it is a start for abcde 2.9. Andrew.
3446 # FIXME: I am not sure if there is a maximum size for images converted in this
3447 # way, but this could be perhaps handled by CONVERTOPTS called from do_getalbumart.
3449 # First some variables we can reuse:
3450 # Use MIMETYPECOVER to allow use of either png or the more common jpeg:
3451 MIMETYPECOVER=$(file -b --mime-type "$ALBUMARTFILE")
3452 EXPORTTAGS="${ABCDETEMPDIR}/export_ogg_tags"
3453 BUILDHEADER="${ABCDETEMPDIR}/build_header"
3454 # Now build the header, gory details are here:
3455 # https://xiph.org/flac/format.html#metadata_block_picture
3457 printf "0: %.8x" 3 | xxd -r -g0 > "$BUILDHEADER"
3459 printf "0: %.8x" $(echo -n "$MIMETYPECOVER" | wc -c) | xxd -r -g0 >> "$BUILDHEADER"
3461 echo -n "$MIMETYPECOVER" >> "$BUILDHEADER"
3462 # Description length. FIXME: I have used 'Cover Image' but I am not sure
3463 # if this is better left as an empty field. Andrew
3464 printf "0: %.8x" $(echo -n "Cover Image" | wc -c) | xxd -r -g0 >> "$BUILDHEADER"
3466 echo -n "Cover Image" >> "$BUILDHEADER"
3468 printf "0: %.8x" 0 | xxd -r -g0 >> "$BUILDHEADER"
3470 printf "0: %.8x" 0 | xxd -r -g0 >> "$BUILDHEADER"
3471 # Picture color depth:
3472 printf "0: %.8x" 0 | xxd -r -g0 >> "$BUILDHEADER"
3473 # Picture color count:
3474 printf "0: %.8x" 0 | xxd -r -g0 >> "$BUILDHEADER"
3476 printf "0: %.8x" $(wc -c "$ALBUMARTFILE" | cut --delimiter=' ' --fields=1) | xxd -r -g0 >> "$BUILDHEADER"
3477 # cat the image file:
3478 cat "$ALBUMARTFILE" >> "$BUILDHEADER"
3479 # Now process each ogg file by first exporting the original tags then
3480 # appending the cover image and finally copying the whole thing back
3481 # to the original image:
3484 # Make a backup of the existing tags:
3485 "$VORBISCOMMENT" --list --raw "$i" > "EXPORTTAGS"
3486 # base64 the file and then mix it all together with the exported tags:
3487 echo "metadata_block_picture=$(base64 --wrap=0 < "$BUILDHEADER")" >> "EXPORTTAGS"
3488 # Update the original ogg file with exported tags and the appended base64'd image:
3489 "$VORBISCOMMENT" --write --raw --commentfile "EXPORTTAGS" "$i"
3490 # Delete the EXPORTTAGS file ready to be recreated for the next file in the loop,
3491 # note that the header file BUILDHEADER will be reused for each file in the loop:
3494 mkdir "$FINALDIR"/albumart_backup
3495 mv "$ALBUMARTFILE" "$FINALDIR"/albumart_backup
3496 vecho "Successfully embedded the album art into your $OUTPUT tracks" >&2
3498 *) vecho "Sorry, abcde does not embed album art for the $OUTPUT container..." >&2
3501 vecho "Suitable cover image not found, no embedding done..." >&2
3506 # do_cdread [tracknumber]
3507 # do_cdread onetrack [firsttrack] [lasttrack]
3511 # The commands here don't go through run_command because they're never supposed to be silenced
3512 # return codes need to be doublechecked anyway, however
3513 if [ "$1" = "onetrack" ]; then
3514 # FIXME # Add the possibility of grabbing ranges of tracks in onetrack
3515 # FIXME # Until then, we grab the whole CD in one track, no matter what
3517 # We need the first and last track for cdda2wav/icedax
3519 LASTTRACK=$(expr $3 + 0) # Unpad
3520 UTRACKNUM=$FIRSTTRACK
3521 case "$CDROMREADERSYNTAX" in
3522 flac) READTRACKNUMS="-" ;;
3525 # Add a variable to check if tracks are provided in command line and if not, rip the whole CD
3526 # We must make sure to rip from sector 0, both lines below work
3527 # READTRACKNUMS="-- -$LASTTRACK" ;;
3528 READTRACKNUMS="[.0]-" ;;
3529 cdda2wav | icedax) READTRACKNUMS="$FIRSTTRACK+$LASTTRACK" ;;
3530 pird) READTRACKNUMS="$FIRSTTRACK..$LASTTRACK" ;;
3531 *) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
3537 CDDBTRACKNUM=$(expr $UTRACKNUM - 1) # Unpad
3538 if [ "$USEPIPES" = "y" ]; then
3539 TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
3540 FILEARG="$( eval echo "\$$TEMPARG" )"
3541 PIPE_MESSAGE="and encoding "
3543 WAVDATA="${ABCDETEMPDIR}/track$UTRACKNUM.wav"
3544 case "$CDROMREADERSYNTAX" in
3545 ## FIXME ## Find the cases for flac, to avoid exceptions
3547 FILEARG="--output-name=$WAVDATA"
3554 if [ "$1" = "onetrack" ]; then
3555 echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
3557 if [ -r "$CDDBDATA" ]; then
3558 getcddbinfo TRACKNAME
3559 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
3561 echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
3564 case "$CDROMREADERSYNTAX" in
3565 ### FIXME ### use an exception for flac, since it uses -o
3566 ### FIXME ### Shall we just use -o $FILEARG ??
3568 # Avoid problems with math expressions by unpadding the given UTRACKNUM
3569 STRIPTRACKNUM=$(expr $UTRACKNUM + 0 )
3570 nice $READNICE $FLAC -d -f --cue="${READTRACKNUMS:-$STRIPTRACKNUM.1-$(($STRIPTRACKNUM + 1)).0}" "$FILEARG" "$CDROM" ;;
3572 if [ "$USEPIPES" = "y" ]; then
3573 nice $READNICE $CDROMREADER -"$CDPARANOIACDROMBUS" "$CDROM" "${READTRACKNUMS:-$UTRACKNUM}" "$FILEARG"
3575 nice $READNICE $CDROMREADER -"$CDPARANOIACDROMBUS" "$CDROM" "${READTRACKNUMS:-$UTRACKNUM}" "$FILEARG" >&2
3579 if [ "$OSFLAVOUR" = "OSX" ] ; then
3580 # Hei, we have to unmount the device before running anything like cdda2wav/icedax in OSX
3581 diskutil unmount "${CDROM#/dev/}"
3582 # Also, in OSX the cdrom device for cdda2wav/icedax changes...
3583 CDDA2WAVCDROM="IODVDServices"
3584 elif [ "$OSFLAVOUR" = "FBSD" ] || [ "$OSFLAVOUR" = "IRIX" ]; then
3585 CDDA2WAVCDROM="$CDROMID"
3587 if [ "$CDROMID" = "" ]; then
3588 CDDA2WAVCDROM="$CDROM"
3590 CDDA2WAVCDROM="$CDROMID"
3593 if [ "$USEPIPES" = "y" ]; then
3594 nice $READNICE $CDROMREADER -D "$CDDA2WAVCDROM" -t "${READTRACKNUMS:-$UTRACKNUM}" "$FILEARG"
3596 nice $READNICE $CDROMREADER -D "$CDDA2WAVCDROM" -t "${READTRACKNUMS:-$UTRACKNUM}" "$FILEARG" >&2
3600 # I cannot get USEPIPES to work with dagrab so just this:
3601 nice $READNICE $CDROMREADER -d "$CDROM" -f "$FILEARG" -v "$UTRACKNUM" >&2
3604 if [ "$USEPIPES" = "y" ]; then
3605 nice $READNICE $CDROMREADER -j "${READTRACKNUMS:-$UTRACKNUM}" "$CDROM" "$FILEARG"
3607 # Write ripped audio data to stdout and redirect to $FILEARG.
3608 # Progress is written to stderr by default and thus >&2 is not required.
3609 nice $READNICE $CDROMREADER -j "${READTRACKNUMS:-$UTRACKNUM}" "$CDROM" "$PIPERIPPER_pird" > "$FILEARG"
3613 # Find the track's mounted path
3614 REALTRACKNUM=$(expr $UTRACKNUM + 0) # Unpad
3615 FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
3616 FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
3617 # If the file exists, copy it
3618 if [ -e "$FILEPATH" ] ; then
3619 if [ "$USEPIPES" = "y" ]; then
3620 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG"
3622 nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" >&2
3628 if [ "$USEPIPES" = "y" ]; then
3629 nice $READNICE $CDROMREADER -"$CDPARANOIACDROMBUS" "$CDROM" -w "$UTRACKNUM-[:1]" "$FILEARG"
3631 nice $READNICE $CDROMREADER -"$CDPARANOIACDROMBUS" "$CDROM" -w "$UTRACKNUM-[:1]" "$FILEARG" >&2
3636 # If we get some error or we get some missing wav
3637 # (as long as we dont use pipes)
3638 if [ "$RETURN" != "0" ] || ( [ ! -s "$WAVDATA" ] && [ X"$USEPIPES" != "Xy" ] ); then
3639 # Thank goodness errors is only machine-parseable up to the
3640 # first colon, otherwise this woulda sucked
3641 if [ "$RETURN" = "0" ] || [ ! -s "$WAVDATA" ]; then
3642 RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
3644 if [ "$USEPIPES" = "y" ]; then
3645 echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "${ABCDETEMPDIR}/errors"
3647 echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "${ABCDETEMPDIR}/errors"
3651 if [ "$USEPIPES" = "y" ]; then
3652 echo "readencodetrack-$UTRACKNUM" >> "${ABCDETEMPDIR}/status"
3654 echo "readtrack-$UTRACKNUM" >> "${ABCDETEMPDIR}/status"
3656 if [ "$1" = "onetrack" ]; then
3657 echo onetrack >> "${ABCDETEMPDIR}/status"
3663 # No values accepted, only uses env variables
3666 if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
3667 vecho "Setting CD speed to ${CDSPEEDVALUE}x"
3669 echo "abcde: unable to set the device speed" >&2
3675 # vecho outputs a message if EXTRAVERBOSE is 1 or more
3678 if [ x"$EXTRAVERBOSE" != "x" ] && [ "$EXTRAVERBOSE" -gt 0 ] ; then
3680 warning) shift ; log warning "$@" ;;
3688 # vvecho outputs a message if EXTRAVERBOSE is 2 or more
3691 if [ x"$EXTRAVERBOSE" != "x" ] && [ "$EXTRAVERBOSE" -gt 1 ] ; then
3693 warning) shift ; log warning "$@" ;;
3701 # decho outputs a debug message if DEBUG is selected
3704 if [ x"$DEBUG" != "x" ]; then
3705 if echo "$1" | grep "^\[" > /dev/null 2>&1 ; then
3706 DEBUGECHO=$(echo "$@" | tr -d '[]')
3707 echo >&4 "[DEBUG] $DEBUGECHO: $(eval echo \\$${DEBUGECHO})"
3709 echo >&4 "[DEBUG] $1"
3714 # User-redefinable functions
3715 # Custom filename munging:
3718 echo "$@" | sed -e 's/^\.*//' -e 's/ /_/g' | tr -d ":><|*/\"'?[:cntrl:]"
3721 # Custom filename munging specific to track names:
3727 # Custom filename munging specific to artist names:
3733 # Custom filename munging specific to album names:
3739 # Custom genre munging:
3742 echo "$CDGENRE" | tr "[:upper:]" "[:lower:]"
3746 # Empty pre_read function, to be defined in the configuration file.
3753 # Empty post_read function, to be defined in the configuration file.
3760 # Empty post_encode function, to be defined in the configuration file.
3766 ###############################################################################
3769 # Start of execution
3770 ###############################################################################
3775 # Currently three supported options ("musicbrainz", "cddb" for freedb.org and "cdtext")
3776 CDDBMETHOD=musicbrainz
3777 CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
3778 CDDBSUBMIT=freedb-submit@freedb.org
3780 HELLOINFO="$(whoami)@$(hostname)"
3782 CDDBLOCALPOLICY="always"
3783 CDDBLOCALRECURSIVE="y"
3784 CDDBLOCALDIR="$HOME/.cddb"
3787 # List of fields we parse and show during the CDDB parsing...
3788 SHOWCDDBFIELDS="year,genre"
3791 #CDROMREADERSYNTAX=cdparanoia
3792 ENCODERSYNTAX=default
3794 MP3ENCODERSYNTAX=default
3795 OGGENCODERSYNTAX=default
3796 OPUSENCODERSYNTAX=default
3797 MKAENCODERSYNTAX=default
3798 AIFFENCODERSYNTAX=default
3799 FLACENCODERSYNTAX=default
3800 SPEEXENCODERSYNTAX=default
3801 MPCENCODERSYNTAX=default
3802 WVENCODERSYNTAX=default
3803 TTAENCODERSYNTAX=default
3804 APENCODERSYNTAX=default
3805 MP2ENCODERSYNTAX=default
3806 AACENCODERSYNTAX=default
3807 NORMALIZERSYNTAX=default
3808 CUEREADERSYNTAX=default
3810 OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
3811 # Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
3812 #VAOUTPUTFORMAT=${OUTPUTFORMAT}
3813 VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
3814 ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
3815 VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
3816 PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
3817 PLAYLISTDATAPREFIX=''
3818 VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
3819 VAPLAYLISTDATAPREFIX=''
3821 OVERRIDEALBUMARTDOWNLOAD=n
3828 VARIOUSARTISTSTYLE=forward
3835 # If using scsi devices, cdda2wav/icedax needs a CDROMID, instead of a device node
3836 # i.e. CDROMID="1,0,0"
3838 # If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
3839 # If we are using the ide-scsi emulation layer, we need to define a "g"
3840 CDPARANOIACDROMBUS="d"
3842 # program paths - defaults to checking your $PATH
3848 XINGMP3ENC=xingmp3enc
3862 # WVENC is retained in abcde 2.7.1 for backwards compatibility
3866 # True Audio: 'tta' is the newer version, 'ttaenc' is the older version:
3876 NEROAACENC=neroAacEnc
3878 # Note that the qaac PATH will almost always require adjustment
3879 # as it is a Windows application being run through Wine. More
3880 # detailed notes in the sample abcde.conf file in the abcde tarball.
3883 # The path to 'avconv' rather than 'ffmpeg'can be used here:
3891 VORBISCOMMENT=vorbiscomment
3893 NEROAACTAG=neroAacTag
3894 ATOMICPARSLEY=AtomicParsley
3898 CDPARANOIA=cdparanoia
3899 CD_PARANOIA="cd-paranoia"
3904 CDDISCID="cd-discid"
3906 MUSICBRAINZ=abcde-musicbrainz-tool
3910 NORMALIZE="normalize-audio"
3912 VORBISGAIN=vorbisgain
3916 # For Wavpack replay gain we set both the default of 'track gain'
3917 # as well as this option for 'album gain'. Better media players
3918 # such as vlc can select either or neither. Andrew.
3929 # Options for programs called from abcde:
3932 # These options needed by FFmpeg for tagging and selection of id3v2 version:
3933 # 1. '-write_id3v2 1' allows id3v2 tagging while '-write_id3v2 0' disables tagging
3934 # 2. '-id3v2_version 4' gives version id3v2.4 while '3' gives id3v2.3
3935 AIFFENCOPTS="-write_id3v2 1 -id3v2_version 4"
3947 VORBISGAINOPTS="--album"
3951 # The flac option is a workaround for an error where flac fails
3952 # to encode with error 'floating point exception'. This is flac
3953 # error in get_console_width(), corrected in flac 1.3.1
3955 FLACGAINOPTS="--add-replay-gain"
3962 # True Audio has no useful options but it is here anyway :)
3965 # Monkey's Audio Console (mac) chokes without a mode setting
3966 # so we set one here.
3973 # fdkaac chokes without either a bitrate or bitrate-mode specified so
3974 # we set bitrate here.
3975 FDKAACENCOPTS='--bitrate 192k'
3997 VORBISCOMMENTOPTS="-R"
3998 METAFLACOPTS="--no-utf8-convert"
4003 DISPLAYCMDOPTS="-resize 512x512 -title abcde_album_art"
4005 # Defaults for album art downloads
4006 ALBUMARTFILE="cover.jpg"
4008 ALBUMARTALWAYSCONVERT="n"
4010 # Default to one process if -j isn't specified
4013 # List of actions to perform - by default, run to completion
4014 ACTIONS=cddb,read,encode,tag,move,clean
4016 # This option is basically for Debian package dependencies:
4017 # List of preferred outputs - by default, run with whatever we have in the path
4018 DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:lame,mp3:bladeenc,spx:speex,m4a:fdkaac:opus
4020 # List of preferred cdromreaders - by default, run whichever we have in the path
4021 DEFAULT_CDROMREADERS="cdparanoia icedax cdda2wav libcdio pird"
4023 # fd for when `vecho` and `log info` called with redirected stdout
4026 # Assume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for
4027 # Linux/OpenBSD. ftp is user for NetBSD.
4028 # Let's use these checkings to determine the OS flavour, which will be used
4031 if [ X"$UNAME" = "XFreeBSD" ] ; then
4036 elif [ X"$UNAME" = "XDarwin" ] ; then
4038 # By default md5sum is not installed, use md5 instead:
4041 # We should have diskutil in OSX, but let's be sure...
4043 CDROMREADERSYNTAX=cddafs
4044 # We won't find the eject program in OSX, and doing checkexec will fail further below...
4046 elif [ X"$UNAME" = "XOpenBSD" ] ; then
4050 elif [ X"$UNAME" = "XNetBSD" ] ; then
4054 elif [ X"$UNAME" = X"SunOS" ] ; then
4058 elif [ X"$UNAME" = X"IRIX64" ] ; then
4062 # Apparently necessary - see
4063 # https://abcde.einval.com/bugzilla/show_bug.cgi?id=29
4064 CDDISCID_NEEDS_PAUSE=y
4069 # If CDDBAVAIL is set to n, no CDDB read is done
4073 # But before we get into business, let us chop off any GREP environmental
4078 if [ -z "$OUTPUTDIR" ]; then
4082 if [ -z "$WAVOUTPUTDIR" ]; then
4083 WAVOUTPUTDIR="$OUTPUTDIR"
4086 # Load system defaults
4087 if [ -r /etc/abcde.conf ]; then
4090 # Load user preference defaults
4091 if [ -r "$HOME/.abcde.conf" ]; then
4092 . "$HOME/.abcde.conf"
4095 # By this time, we need some HTTPGETOPTS already defined.
4096 # If the user has defined a non-default HTTPGET method, we should not be empty.
4098 if [ "$HTTPGETOPTS" = "" ] ; then
4100 wget) HTTPGETOPTS="-q -nv -e timestamping=off -O -";;
4101 curl) HTTPGETOPTS="-f -s -L";;
4102 fetch)HTTPGETOPTS="-q -o -";;
4103 ftp) HTTPGETOPTS="-a -V -o - ";;
4104 *) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
4108 # If the CDROM has not been set yet, find a suitable one.
4109 # If this is a devfs system, default to /dev/cdroms/cdrom0
4110 # instead of /dev/cdrom
4111 if [ "$CDROM" = "" ] ; then
4112 if [ -e /dev/cdroms/cdrom0 ]; then
4113 CDROM=/dev/cdroms/cdrom0
4114 elif [ "$OSFLAVOUR" = "OSX" ] && [[ $(diskutil list) =~ CD_part[^/]*(disk.)$'\n' ]]; then
4115 CDROM=/dev/${BASH_REMATCH[1]}
4116 elif [ -e /dev/cdrom ]; then
4118 elif [ -e /dev/sr0 ]; then
4120 elif [ -e /dev/cd0c ]; then
4122 elif [ -e /dev/acd0c ]; then
4124 elif [ -e /dev/disk1 ]; then
4129 # We used to use EXTRAVERBOSE=y to turn on more debug output. Now
4130 # that's changed to a number to allow for more control. Deal with
4131 # EXTRAVERBOSE=y/n, set it to 1/0 for backwards compatibility.
4132 case "$EXTRAVERBOSE" in
4141 # Parse command line options
4142 while getopts 1a:bBc:C:d:DefgGhj:klLmMnNo:pPQ:r:s:S:t:T:UvVxX:w:W:z opt ; do
4145 a) ACTIONS="$OPTARG" ;;
4146 A) EXPACTIONS="$OPTARG" ;;
4148 B) GETALBUMART=y ; EMBEDALBUMART=y ;;
4149 c) if [ -e "$OPTARG" ]; then
4152 log error "config file \"$OPTARG\" cannot be found."
4156 C) CDDBDISCID="$( echo "${OPTARG#abcde.}" | tr -d /)" ;;
4157 d) CDROM="$OPTARG" ;;
4160 e) ERASEENCODEDSTATUS=y ;;
4161 E) ENCODING="$OPTARG" ;;
4166 j) MAXPROCS="$OPTARG" ;;
4169 L) CDDBUSELOCAL=y ;;
4174 o) OUTPUTTYPE="$OPTARG" ;;
4175 O) OVERRIDEALBUMARTDOWNLOAD=y ;;
4178 Q) CDDBMETHOD="$OPTARG" ;;
4179 r) REMOTEHOSTS="$OPTARG" ;;
4180 R) CDDBLOCALRECURSIVE=y ;;
4181 s) SHOWCDDBFIELDS="$OPTARG" ;;
4182 S) CDSPEEDVALUE="$OPTARG" ;;
4183 t) STARTTRACKNUMBER="$OPTARG" ;;
4184 T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
4187 echo "This is abcde v$VERSION."
4188 echo "Usage: abcde [options] [tracks]"
4189 echo "abcde -h for extra help"
4192 V) EXTRAVERBOSE=$(($EXTRAVERBOSE + 1)) ;;
4194 X) CUE2DISCID="$OPTARG" ;;
4195 w) COMMENT="$OPTARG" ;;
4196 W) if echo "$OPTARG" | grep "[[:digit:]]" > /dev/null 2>&1 ; then
4197 STARTTRACKNUMBER="${OPTARG}$(printf "%02d" "${STARTTRACKNUMBER:-01}")"
4198 STARTTRACKNUMBERTAG="y"
4199 COMMENT="CD${OPTARG}"
4200 DISCNUMBER="${OPTARG}"
4202 log error "argument of -W must be integer"
4206 z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
4211 shift $(($OPTIND - 1))
4213 # Here it comes the worse part of the whole thing. From here until we start
4214 # ripping, we have a mixture of sanity checks, verifications, default settigs
4215 # and other crazy stuff that interdepends, but hey, someone has to do it.
4217 # If NOCDDBQUERY is set, don't query the CDDB server.
4218 if [ "$NOCDDBQUERY" = "y" ]; then
4222 # If the user specified a flac file, then switch to special flac mode
4223 if echo "$CDROM" | grep -i '.flac$' > /dev/null 2>&1 ; then
4224 if [ ! -f "$CDROM" ]; then
4225 log error "the defined file for FLAC ripping cannot be found" >&2
4228 vecho warning "switching to flac CDROMREADERSYNTAX..."
4229 CDROMREADERSYNTAX=flac
4230 # We have a builtin version of cue2discid...
4231 case "$CUE2DISCID" in
4233 *) NEEDCUE2DISCID=y;;
4239 # If the user provided a CDDBDISCID, disable eject
4240 if [ -n "${CDDBDISCID}" ] || [ "$CDROMREADERSYNTAX" = "flac" ]; then EJECTCD=n ; fi
4242 # Check the available cd rippers in the system, from the ones we know.
4243 if [ "$CDROMREADERSYNTAX" = "" ]; then
4244 for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
4245 if new_checkexec "$DEFAULT_CDROMREADER"; then
4246 CDROMREADERSYNTAX="$DEFAULT_CDROMREADER"
4250 if [ "$CDROMREADERSYNTAX" = "" ]; then
4251 log error "no cdreader found in your PATH"
4252 log error "hints: are all dependencies installed? has the \$PATH been modified?"
4257 # Decide if we can continue.
4258 if [ "$ONETRACK" = "y" ]; then
4259 # FIXME # remove check as soon as we find out about the other readers
4260 case "$CDROMREADERSYNTAX" in
4262 cdparanoia | libcdio) ;;
4263 cdda2wav | icedax) ;;
4265 *) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
4268 if [ "$BATCHNORM" = "y" ]; then
4269 log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
4272 if [ "$NOGAP" = "y" ]; then
4273 log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
4276 # It does not matter how many tracks we want. In ONETRACK mode we grab them all
4277 # FIXME # allow ranges of tracks to be selected for onetrack ripping
4278 if [ $# -gt 0 ]; then
4279 log warning "ONETRACK mode selected, grabbing all tracks..."
4282 while [ $# -gt 0 ]; do
4283 # Range parsing code courtesy of Vincent Ho
4284 # Cleaned up to use shell built-ins by Charles Steinkuehler
4285 if [ "${1#*[^0-9-]}" != "$1" ]; then
4286 log error "syntax error while processing track numbers ($1)"
4291 while [ "${RSTART:=1}" -le "${REND:=0}" ] ; do
4292 TRACKQUEUE="$TRACKQUEUE $RSTART"
4293 RSTART=$(( $RSTART + 1 ))
4300 # List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
4301 # List of experimental actions: retag,transcode
4303 # Determine what actions are to be done from $ACTIONS and set the
4304 # following environment variables for them:
4316 ## FIXME ## Lets keep compatibility with -M
4317 [ "$DOCUE" != "y" ] && DOCUE=n
4319 for ACTION in $(echo "$ACTIONS" | tr , \ )
4322 default) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOCLEAN=y;;
4323 cue) DOCUE=y ; MAKECUEFILE=y ;;
4326 normalize) DONORMALIZE=y; DOREAD=y;;
4327 # preprocess) DOPREPROCESS=y; DOREAD=y;;
4328 encode) DOENCODE=y; DOREAD=y;;
4329 # postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
4330 tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
4331 move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
4332 replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
4333 playlist) DOCDDB=y; DOPLAYLIST=y;;
4335 getalbumart) GETALBUMART=y;;
4336 embedalbumart) GETALBUMART=y; EMBEDALBUMART=y;;
4340 if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
4341 # FIXME # should we abort on error or just inform the user?
4342 log warning "selected both normalize and replaygain actions"
4345 for SHOWCDDBFIELD in $(echo "$SHOWCDDBFIELDS" | tr , \ ); do
4346 case $SHOWCDDBFIELD in
4347 y*|Y*) SHOWCDDBYEAR="y";;
4348 g*|G*) SHOWCDDBGENRE="y";;
4353 # At this point a CDROM has to be defined, so we check it exists.
4354 if [ X"$CDROM" != "X" ] ; then
4355 if [ "$NEEDCDROMID" = "y" ] ; then
4356 if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] || [ "$CDROMREADERSYNTAX" = "icedax" ]; then
4357 if [ "$OSFLAVOUR" = "IRIX" ]; then
4358 if [ -z "$CDROMID" ]; then
4359 CDROMID="$(echo "$CDROM" | sed -e 's;/dev/scsi/sc\([0-9]*\)d\([0-9]*\)l\([0-9]*\)$;\1,\2,\3;')"
4362 if ! echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then
4363 log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
4364 log error "Use \"cdrecord -scanbus\" to obtain an adequate ID and set CDROMID accordingly"
4368 elif [ ! -e "$CDROM" ] && [ X"$DOREAD" = "Xy" ]; then
4369 log error "CDROM device cannot be found."
4372 # avoid processing if we are not going to hit the CDROM.
4373 elif [ X"$DOREAD" = "Xy" ]; then
4374 log error "CDROM has not been defined or cannot be found"
4378 # USEPIPES pre-tests, before we get into more serious stuff
4379 # Not compatible with:
4380 # - multiple outputs
4382 # - lowdisk algorithm
4384 if [ X"$USEPIPES" = "Xy" ]; then
4385 NUM_OUTPUT_TYPES="$(echo "$OUTPUTTYPE" | tr , \ | wc -w )"
4386 if [ "$NUM_OUTPUT_TYPES" -gt 1 ]; then
4387 log error "Unix pipes not compatible with multiple outputs"
4390 if [ X"$DONORMALIZE" = "Xy" ]; then
4391 log error "Unix pipes not compatible with normalizer"
4392 # FIXME # Do we need to exit or shall we just disable the mode?
4395 if [ X"$BATCHNORM" = "Xy" ]; then
4396 log error "Unix pipes not compatible with BATCHNORM encoding"
4399 if [ X"$NOGAP" = "Xy" ]; then
4400 log error "Unix pipes not compatible with NOGAP encoding"
4403 if [ X"$DOENCODE" = "Xn" ]; then
4404 vecho warning "Disabling Unix pipes since we are not encoding!"
4407 if [ X"$LOWDISK" = "Xy" ]; then
4408 log error "Unix pipes not compatible with lowdisk algorithm"
4413 # LOWDISK pre-tests, before we get into more problematic stuff
4414 # Not compatible with anything that needs all the files in the hard disc:
4417 if [ X"$LOWDISK" = "Xy" ]; then
4418 if [ X"$BATCHNORM" = "Xy" ]; then
4419 log error "Unix pipes not compatible with BATCHNORM encoding"
4422 if [ X"$NOGAP" = "Xy" ]; then
4423 log error "Unix pipes not compatible with NOGAP encoding"
4428 # BATCHNORM pre-tests, before we get into serious problems
4429 # Not compatible with
4430 if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
4431 vecho warning "Disabling BATCHNORM since we are not normalizing!"
4435 # Check the encoding format from the ones available in the system, if nothing has been configured.
4436 if [ X"$OUTPUTTYPE" = "X" ]; then
4437 for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
4438 DEFAULT_OUTPUT_FORMAT="$(echo "$DEFAULT_OUTPUT" | cut -d ":" -f 1)"
4439 DEFAULT_OUTPUT_BINARY="$(echo "$DEFAULT_OUTPUT" | cut -d ":" -f 2)"
4440 if [ -x "$(which "$DEFAULT_OUTPUT_BINARY")" ] ; then
4441 OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
4442 vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
4446 if [ X"$OUTPUTTYPE" = "X" ]; then
4447 log error "no encoder found in the PATH"
4448 log error "hints: are all dependencies installed? has the \$PATH been modified?"
4453 # Decide which CDROM reader we're gonna use
4454 case "$CDROMREADERSYNTAX" in
4456 CDROMREADER="$CDPARANOIA"
4457 CDROMREADEROPTS="$CDPARANOIAOPTS"
4460 # GNU's libcdio package will use cd-paranoia but I believe will be happy with
4461 # the standard cdparanoia options. If I am wrong this will need to be fixed :).
4462 CDROMREADER="$CD_PARANOIA"
4463 CDROMREADEROPTS="$CDPARANOIAOPTS"
4466 CDROMREADER="$CDDA2WAV"
4467 CDROMREADEROPTS="$CDDA2WAVOPTS"
4470 CDROMREADER="$DAGRAB"
4471 CDROMREADEROPTS="$DAGRABOPTS"
4475 CDROMREADEROPTS="$PIRDOPTS"
4478 CDROMREADER="$CDDAFS"
4479 CDROMREADEROPTS="$CDDAFSOPTS"
4483 CDROMREADEROPTS="$FLACOPTS"
4487 # There's only one normalize...
4488 case "$NORMALIZERSYNTAX" in
4490 NORMALIZER="$NORMALIZE"
4491 NORMALIZEROPTS="$NORMALIZEOPTS"
4495 # Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
4496 case "$OUTPUTTYPE" in *:*)
4497 for OUTPUT in $(echo "$OUTPUTTYPE" | tr \ \|| tr , \ ); do
4498 OUTPUT="$(echo "$OUTPUT" | tr \| \ )"
4500 vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4501 opus:*) OPUSENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4502 mka:*) MKAENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4503 aiff:*) AIFFENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4504 mp3:*) MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4505 flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4506 spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4507 mpc:*) MPCENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4508 wv:*) WVENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4509 tta:*) TTAENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4510 ape:*) APENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4511 mp2:*) MP2ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4512 m4a:*|aac:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
4515 # Allows commandline selection of options while using multiple outputs.
4516 # Example: abcde -o 'flac:-8,mp3:-b 320' Patch by Matthias Andree.
4517 for OUTPUT in $(echo "$OUTPUTTYPE" | tr -d ' ' | tr , ' '); do
4518 TEMPOUTPUT=${OUTPUT%%:*}
4519 TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
4521 OUTPUTTYPE="$TEMPOUTPUTTYPE"
4525 # If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
4526 # for flacs and speexenc for speex and mpcenc for mpcs and fdkaac for m4as and
4527 # wavpack for wvs...
4529 # Getting ready for multiple output changes
4530 for OUTPUT in $(echo "$OUTPUTTYPE" | tr , \ )
4534 [ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
4535 [ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
4536 [ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
4537 OGGOUTPUTCONTAINER=ogg
4540 [ "$OPUSENCODERSYNTAX" = "default" ] && OPUSENCODERSYNTAX=opusenc
4541 OPUSOUTPUTCONTAINER=opus
4544 [ "$MKAENCODERSYNTAX" = "default" ] && MKAENCODERSYNTAX=ffmpeg
4545 MKAOUTPUTCONTAINER=mka
4548 [ "$AIFFENCODERSYNTAX" = "default" ] && AIFFENCODERSYNTAX=ffmpeg
4549 AIFFOUTPUTCONTAINER=aiff
4552 [ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
4553 [ "$DOTAG" = "y" ] && NEEDTAGGER=y
4554 [ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
4555 [ "$EMBEDALBUMART" = "y" ] && NEEDEYED3=y
4558 [ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
4559 [ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
4560 [ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
4561 [ "$ONETRACK" = "y" ] && [ "$DOCUE" = "y" ] && NEEDMETAFLAC=y
4562 [ "$EMBEDALBUMART" = "y" ] && NEEDMETAFLAC=y
4565 [ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
4566 # [ "$DOREPLAYGAIN" = "y" ] &&
4569 [ "$MPCENCODERSYNTAX" = "default" ] && MPCENCODERSYNTAX=mpcenc
4570 [ "$DOREPLAYGAIN" = "y" ] && NEEDMPCGAIN=y
4573 [ "$WVENCODERSYNTAX" = "default" ] && WVENCODERSYNTAX=wavpack
4575 [ "$DOREPLAYGAIN" = "y" ] && NEEDWVGAIN=y
4576 [ "$WVENCODERSYNTAX" = "ffmpeg" ] && DOREPLAYGAIN=n
4577 [ "$EMBEDALBUMART" = "y" ] && NEEDWVTAG=y
4580 [ "$APENCODERSYNTAX" = "default" ] && APENCODERSYNTAX=mac
4581 [ "$DOTAG" = "y" ] && NEEDAPETAG=y
4584 [ "$MP2ENCODERSYNTAX" = "default" ] && MP2ENCODERSYNTAX=twolame
4585 [ "$DOTAG" = "y" ] && NEEDMID3V2=y
4586 [ "$MP2ENCODERSYNTAX" = "ffmpeg" ] && [ "$DOTAG" = "y" ] && NEEDMID3V2=y
4589 [ "$TTAENCODERSYNTAX" = "default" ] && TTAENCODERSYNTAX=tta
4590 [ "$DOTAG" = "y" ] && NEEDMID3V2=y
4591 [ "$TTAENCODERSYNTAX" = "ttaenc" ] && [ "$DOTAG" = "y" ] && NEEDMID3V2=y
4594 [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
4596 # Neither Faac nor AtomicParsley can tag the .aac files which are used for faac
4597 # compiled without libmp4v2... Andrew.
4600 [ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=fdkaac
4601 [ "$AACENCODERSYNTAX" = "faac" ] && [ "$DOTAG" = "y" ] && CHECKFAACBUILD=y
4602 [ "$AACENCODERSYNTAX" = "neroAacEnc" ] && NEEDNEROAACTAG=y
4603 [ "$AACENCODERSYNTAX" = "qaac" ] && NEEDWINE=y
4604 [ "$AACENCODERSYNTAX" = "fhgaacenc" ] && NEEDWINE=y && NEEDATOMICPARSLEY=y
4605 [ "$AACENCODERSYNTAX" = "ffmpeg" ] && [ "$DOTAG" = "y" ]
4606 [ "$EMBEDALBUMART" = "y" ] && NEEDATOMICPARSLEY=y
4609 if [ "$KEEPWAVS" = "y" ]; then
4610 vecho "Setting the KEEPWAVS option, since the resulting wav files were requested..."
4614 *) log error "Invalid OUTPUTTYPE defined"
4620 # decide which encoder
4621 case "$MP3ENCODERSYNTAX" in
4623 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
4627 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
4631 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
4632 MP3ENCODER="$BLADEENC"
4635 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
4639 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
4640 MP3ENCODER="$XINGMP3ENC"
4643 MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
4644 MP3ENCODER="$MP3ENC"
4647 case "$OGGENCODERSYNTAX" in
4649 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
4650 OGGENCODER="$VORBIZE"
4653 OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
4654 OGGENCODER="$OGGENC"
4657 case "$OPUSENCODERSYNTAX" in
4659 OPUSENCODEROPTS="${OPUSENCODEROPTSCLI:-$OPUSENCOPTS}"
4660 OPUSENCODER="$OPUSENC"
4663 case "$MKAENCODERSYNTAX" in
4665 MKAENCODEROPTS="${MKAENCODEROPTSCLI:-$FFMPEGENCOPTS}"
4666 MKAENCODER="$FFMPEG"
4669 case "$AIFFENCODERSYNTAX" in
4671 AIFFENCODEROPTS="${AIFFENCODEROPTSCLI:-$AIFFENCOPTS}"
4672 AIFFENCODER="$FFMPEG"
4675 case "$FLACENCODERSYNTAX" in
4677 FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
4679 if [ "$DOREPLAYGAIN" = "y" ]; then
4680 FLACENCODEROPTS="${FLACENCODEROPTS} --replay-gain"
4682 # FLAC streams can be encapsulated on a Ogg transport layer
4683 if echo "$FLACENCODEROPTS" | grep -E -- "(^| )--ogg($| )" > /dev/null 2>&1 ;then
4684 log error "FLAC on an Ogg container is not yet supported"
4685 log error "due to problem with adding comments to such files"
4687 FLACOUTPUTCONTAINER=ogg
4689 FLACOUTPUTCONTAINER=flac
4693 case "$SPEEXENCODERSYNTAX" in
4695 SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
4696 SPEEXENCODER="$SPEEXENC"
4699 case "$MPCENCODERSYNTAX" in
4701 MPCENCODEROPTS="${MPCENCODEROPTSCLI:-$MPCENCOPTS}"
4702 MPCENCODER="$MPCENC"
4705 case "$WVENCODERSYNTAX" in
4707 # Syntax changed slightly between abcde 2.7 and abcde 2.7.1,
4708 # and in the interests of backward compatibility:
4709 if [ -z "$WAVPACKENCOPTS" ] && [ -n "$WVENCOPTS" ]; then
4710 WVENCODEROPTS="${WVENCODEROPTSCLI:-$WVENCOPTS}"
4711 WVENCODER="$WAVPACK"
4713 WVENCODEROPTS="${WVENCODEROPTSCLI:-$WAVPACKENCOPTS}"
4714 WVENCODER="$WAVPACK"
4718 WVENCODEROPTS="${WVENCODEROPTSCLI:-$FFMPEGENCOPTS}"
4722 case "$TTAENCODERSYNTAX" in
4724 TTAENCODEROPTS="${TTAENCODEROPTSCLI:-$TTAENCOPTS}"
4728 TTAENCODEROPTS="${TTAENCODEROPTSCLI:-$TTAENCOPTS}"
4729 TTAENCODER="$TTAENC"
4732 case "$APENCODERSYNTAX" in
4734 APENCODEROPTS="${APENCODEROPTSCLI:-$APENCOPTS}"
4738 case "$MP2ENCODERSYNTAX" in
4740 MP2ENCODEROPTS="${MP2ENCODEROPTSCLI:-$TWOLAMENCOPTS}"
4741 MP2ENCODER="$TWOLAME"
4744 MP2ENCODEROPTS="${MP2ENCODEROPTSCLI:-$FFMPEGENCOPTS}"
4745 MP2ENCODER="$FFMPEG"
4748 case "$AACENCODERSYNTAX" in
4749 # Some elaborate 'if' work to keep backward compatibility for those
4750 # who don't realise that AACENCOPTS does not work with abcde from
4751 # version 2.7 onwards.
4753 if [ -z "$FAACENCOPTS" ] && [ -n "$AACENCOPTS" ]; then
4754 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
4757 AACENCODEROPTS="${AACENCODEROPTSCLI:-$FAACENCOPTS}"
4762 if [ -z "$NEROAACENCOPTS" ] && [ -n "$AACENCOPTS" ]; then
4763 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
4764 AACENCODER="$NEROAACENC"
4766 AACENCODEROPTS="${AACENCODEROPTSCLI:-$NEROAACENCOPTS}"
4767 AACENCODER="$NEROAACENC"
4771 if [ -z "$FDKAACENCOPTS" ] && [ -n "$AACENCOPTS" ]; then
4772 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
4773 AACENCODER="$FDKAAC"
4775 AACENCODEROPTS="${AACENCODEROPTSCLI:-$FDKAACENCOPTS}"
4776 AACENCODER="$FDKAAC"
4780 if [ -z "$QAACENCOPTS" ] && [ -n "$AACENCOPTS" ]; then
4781 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
4784 AACENCODEROPTS="${AACENCODEROPTSCLI:-$QAACENCOPTS}"
4789 if [ -z "$FHGAACENCOPTS" ] && [ -n "$AACENCOPTS" ]; then
4790 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
4791 AACENCODER="$FHGAACENC"
4793 AACENCODEROPTS="${AACENCODEROPTSCLI:-$FHGAACENCOPTS}"
4794 AACENCODER="$FHGAACENC"
4798 if [ -z "$FFMPEGENCOPTS" ] && [ -n "$AACENCOPTS" ]; then
4799 AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
4800 AACENCODER="$FFMPEG"
4802 AACENCODEROPTS="${AACENCODEROPTSCLI:-$FFMPEGENCOPTS}"
4803 AACENCODER="$FFMPEG"
4813 TAGGEROPTS="$ID3OPTS"
4818 TAGGEROPTS="$ID3V2OPTS"
4823 TAGGEROPTS="$ID3TAGOPTS"
4827 # Note that eyeD3 is set to tag in utf-16 (below). This causes
4828 # trouble with CDDBPROTO=5 (which we test here) but also
4829 # with cached cddb files in latin1 (which we cannot test).
4830 if [ "$CDDBPROTO" -lt 6 ]; then
4831 log warning "You cannot have id3v2.4 tags encoded in latin1. Setting CDDBPROTO to 6 for now."
4834 # eyeD3 version 0.7 changed syntax
4835 if $EYED3 --help 2>&1 | grep -q -- --set-encoding ; then
4836 # only if it offers the --set-encoding, assume <= 0.6.x
4838 TAGGEROPTS="--set-encoding utf16-LE $EYED3OPTS"
4840 # anything wrong, any failure, assume >= 0.7
4842 TAGGEROPTS="--encoding utf16 $EYED3OPTS"
4846 log error "Error: ID3TAGV must be either \"id3v1\", \"id3v2.3\" or \"id3v2.4\""
4851 # NOGAP is specific to lame. Other encoders fail ...
4852 if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
4853 log warning "the NOGAP option is specific to lame. Deactivating..."
4858 case "$CUEREADERSYNTAX" in
4860 CUEREADEROPTS="${CDROM}"
4864 CUEREADEROPTS="$MKCUEOPTS ${CDROM}"
4869 # which information retrieval tool are we using?
4875 # Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
4876 if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
4877 log error "FLAC on an Ogg container is not yet supported"
4878 log error "due to problem with adding comments to such files"
4880 OGGOUTPUTCONTAINER=ogg.ogg
4881 FLACOUTPUTCONTAINER=flac.ogg
4882 vecho warning "modified file endings due to conflicting transport"
4883 vecho warning "layers in Ogg/Vorbis and Ogg/FLAC"
4886 # Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
4888 if [ "$ENCNICE" ]; then
4889 ENCNICE="-n $ENCNICE"
4891 if [ "$READNICE" ]; then
4892 READNICE="-n $READNICE"
4894 if [ "$DISTMP3NICE" ]; then
4895 DISTMP3NICE="-n $DISTMP3NICE"
4898 # Don't check for stuff if it's not needed
4899 if [ "$REMOTEHOSTS" ]; then
4902 if [ "$DONORMALIZE" = "y" ]; then
4905 if [ "$EJECTCD" = "y" ]; then
4908 if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
4909 # Need an http tool to be able to do CDDB
4915 if [ "$DOCUE" = "y" ]; then
4919 if [ X"$CDSPEEDVALUE" != "X" ] && [ "$DOREAD" = "y" ]; then
4920 case "$CDROMREADERSYNTAX" in
4921 cdparanoia|libcdio|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
4922 pird) CDROMREADEROPTS="$PIRDOPTS -s $CDSPEEDVALUE" ;;
4923 ### FIXME ### translate "cue2discid" from python to bash
4924 flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ; CDSPEEDVALUE="" ;;
4929 if [ "$GETALBUMART" = "y" ]; then
4934 ###USEPIPESSUPPORT###
4936 # Rippers with USEPIPE support
4937 PIPERIPPER_cdparanoia="-"
4938 PIPERIPPER_libcdio="-"
4939 # Note that by default in abcde cdda2wav redirects to icedax.
4940 PIPERIPPER_cdda2wav="-"
4941 PIPERIPPER_debug="-"
4942 PIPERIPPER_flac="-c "
4945 # Encoders with USEPIPE support
4948 PIPE_bladeenc="stdin"
4961 # Both neroAacEnc and fdkaac seem to manage without the addition of
4962 # the 'ignorelength' option in PIPE_$AACENCODERSYNTAX when piping
4963 # in this manner. Andrew.
4967 # Figure out if we can use pipes with the ripper/encoder combination
4969 if [ "$USEPIPES" = "y" ]; then
4970 PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
4973 PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
4975 PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
4977 PIPEENCODERSVARCHECK="PIPE_$OPUSENCODERSYNTAX" ;;
4979 PIPEENCODERSVARCHECK="PIPE_$MKAENCODERSYNTAX" ;;
4981 PIPEENCODERSVARCHECK="PIPE_$AIFFENCODERSYNTAX" ;;
4983 PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
4985 PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODERSYNTAX" ;;
4987 PIPEENCODERSVARCHECK="PIPE_$MPCENCODERSYNTAX" ;;
4989 PIPEENCODERSVARCHECK="PIPE_$WVENCODERSYNTAX" ;;
4991 PIPEENCODERSVARCHECK="PIPE_$TTAENCODERSYNTAX" ;;
4993 PIPEENCODERSVARCHECK="PIPE_$AACENCODERSYNTAX" ;;
4995 PIPEENCODERSVARCHECK="PIPE_$AACENCODERSYNTAX" ;;
4997 decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
4998 if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
4999 [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
5000 log error "no support for pipes with given ripper"
5001 log error "read the FAQ file from the source tarball to get help."
5004 decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
5005 if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
5006 [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
5007 log error "no support for pipes with given encoder"
5008 log error "read the FAQ file from the source tarball to get help"
5013 # Make sure a buncha things exist
5014 for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
5015 $OGGENCODER $OPUSENCODER $MKAENCODER $FLACENCODER $SPEEXENCODER $MPCENCODER \
5016 $AACENCODER $WVENCODER $CDDBTOOL $APENCODER $MP2ENCODER $TTAENCODER $AIFFENCODER \
5017 ${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
5018 ${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
5019 ${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
5020 ${NEEDDISKUTIL+diskutil} ${NEEDCDSPEED+$CDSPEED} \
5021 ${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
5022 ${NEEDMPCGAIN+$MPCGAIN} ${NEEDCUEREADER+$CUEREADER} \
5023 ${NEEDWVGAIN+WVGAIN} ${NEEDAPETAG+$APETAG} \
5024 ${NEEDCUE2DISCID+$CUE2DISCID} ${NEEDNEROAACTAG+$NEROAACTAG} \
5025 ${NEEDGLYRC+$GLYRC} ${NEEDWINE+$WINE} ${NEEDATOMICPARSLEY+$ATOMICPARSLEY} \
5026 ${NEEDMID3V2+$MID3V2} ${NEEDEYED3+$EYED3} ${NEEDWVTAG+$WVTAG}
5031 # Under Debian and Ubuntu faac is compiled without libmp4v2 which means no support
5032 # for the mp4 container and no tagging capability. (AtomicParsley also cannot tag
5033 # these files). The resulting files are actually ADTS streams which belong in an
5034 # aac container and with some version sniffing this is all cleaned up below. If
5035 # faac is compiled with libmp4v2 inline tagging occurs with faac.
5037 # FIXME: Should this be in this location? (Better incorporated into the checks above.)
5038 if [ "$CHECKFAACBUILD" = "y" ] && [ "$AACENCODERSYNTAX" = "faac" ] ; then
5039 if faac --help 2>&1 | grep -q -F 'MP4 support unavailable.'; then
5040 echo "WARNING: Your copy of Faac does not have mp4 support"
5041 echo "WARNING: Encoding untagged files to aac..."
5042 # Replace m4a with aac for single and multi-output encodes:
5043 OUTPUTTYPE=$(echo "$OUTPUTTYPE" | sed 's/m4a/aac/')
5045 echo "Using Faac to Tag AAC Tracks..."
5049 # And last but not least, check if we can diff between files. We do not abort,
5050 # since diffing is not critical...
5051 if [ -x "$(which "$DIFF")" ]; then :; else
5052 vecho warning "Disabling diff since we cannot find it in the \$PATH..."
5056 ## Now that we have metaflac, check if we need cue2discid
5057 #case $CDROMREADERSYNTAX in
5059 # CDDBTRACKINFO=$($METAFLAC --show-tag=CDDB $CDROM | cut -d"=" -f2 | grep -E "[a-f0-9]{8}")
5060 # if [ "$CDDBTRACKINFO" = "" ]; then
5061 # checkexec ${NEEDCUE2DISCID+$CUE2DISCID}
5066 CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
5067 CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
5068 HTTPGET="$HTTPGET $HTTPGETOPTS"
5070 # Here it used to say:
5071 # One thousand lines in, we can start doing stuff with things
5072 # Well, right now we are at line 3737 ;)
5073 # Hey, for grins, as of 2016-08-30 this is now line 4814! -GR
5075 # Export needed things so they can be read in this subshell
5076 export CDDBTOOL # Path and options for the tool to query CDDB
5077 export ABCDETEMPDIR # Path to the tmpdir for this rip
5078 export TRACKQUEUE # 0-padded list of tracks to be processed
5079 export LOWDISK # Are we using the low-diskspace algorithm?
5080 export EJECTCD # Should we eject the CD when we're finished ripping?
5081 export EJECT # The commend to use to eject the CD, if we have one
5082 export EJECTOPTS # Options to that command
5083 export CDROM # Device path for the CD device
5084 export CDDBDATA # The filename we're using for CD lookup data
5085 export REMOTEHOSTS # List of remote hosts for parallel encoding, if given
5086 export MAXPROCS # The number of *local* encodes to do in parallel
5087 export HTTPGET # Program to use to grab files via http
5088 export MD5SUM # Program to calculate MD5 checksums
5090 if [ "$DOREAD" = "y" ]; then
5091 # User-definable function to set some things. Use it for
5092 # - closing the CD tray with eject -t
5093 # - set the CD speed value with eject -x
5094 vecho -n "Executing customizable pre-read function... "
5096 pre_read # Execute the user-defined pre-read function. Close the CD with it.
5101 # Get ABCDETEMPDIR created and status file initialized
5104 if [ "$DOCDDB" = "y" ]; then
5105 # start with a sane default:
5106 CDDBLOCALSTATUS=notfound
5107 if [ $CDDBUSELOCAL = "y" ]; then
5110 if checkstatus cddb-choice > /dev/null; then
5114 if [ "$CDDBLOCALSTATUS" = "notfound" ] ; then
5116 for CDDBMETHCHOICE in $(echo "$CDDBMETHOD" | tr -d ' ' | tr , ' ')
5118 addstatus "Lookup method $idx: $CDDBMETHCHOICE"
5120 vecho "Found $NUM_CDDB_MATCHES matches so far"
5121 vecho "Trying lookup method ${CDDBMETHCHOICE}"
5123 # Run all the desired data acquisition methods, in the order
5124 # specified by the user. Each will use its own temporary
5125 # subdirectory, then copy the cddbread.* etc. files up into
5127 case "$CDDBMETHCHOICE" in
5138 echo "Unknown lookup method $CDDBMETHCHOICE. Aborting." >&2
5145 rm -f "${ABCDETEMPDIR}/cddbchoices"
5146 CDDBDISCID=$(echo "$CDDBTRACKINFO" | cut -d' ' -f1)
5148 if [ $NUM_CDDB_MATCHES = 0 ]; then
5149 # If we got no matches, we need to
5150 # generate a blank CDDB template.
5151 vecho "Unable to find any matches, generating unknown template."
5152 echo "No lookup matches." >> "${ABCDETEMPDIR}/cddbchoices"
5153 $CDDBTOOL template $(cat "${ABCDETEMPDIR}/cddbdiscid") > "${ABCDETEMPDIR}/cddbread.0"
5154 echo "template" > "${ABCDETEMPDIR}/datasource.0"
5155 # List out disc title/author and contents of template
5156 echo ---- Unknown Artist / Unknown Album ---- >> "${ABCDETEMPDIR}/cddbchoices"
5158 for TRACK in $(f_seq_row 1 $TRACKS)
5160 echo "$TRACK:" "$(grep -a ^TTITLE$(($TRACK - 1))= "${ABCDETEMPDIR}/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "${ABCDETEMPDIR}/cddbchoices"
5162 echo >> "${ABCDETEMPDIR}/cddbchoices"
5163 echo cddb-read-0-complete >> "${ABCDETEMPDIR}/status"
5164 echo cddb-choice=0 >> "${ABCDETEMPDIR}/status"
5165 echo 503 > "${ABCDETEMPDIR}/cddbquery"
5167 # We have matches; create the cddbchoices and cddbquery
5168 # files from all the inputs we have
5169 if [ $NUM_CDDB_MATCHES = 1 ]; then
5170 echo "Retrieved 1 match..." >> "${ABCDETEMPDIR}/cddbchoices"
5171 echo -n "200 " > "${ABCDETEMPDIR}/cddbquery"
5172 cat "${ABCDETEMPDIR}/cddbquery.1" >> "${ABCDETEMPDIR}/cddbquery"
5174 echo "Retrieved $NUM_CDDB_MATCHES matches..." >> "${ABCDETEMPDIR}/cddbchoices"
5175 echo "210 Found exact matches, list follows (until terminating .)" > "${ABCDETEMPDIR}/cddbquery"
5176 for X in $(f_seq_row 1 $NUM_CDDB_MATCHES)
5178 cat "${ABCDETEMPDIR}/cddbquery.$X" >> "${ABCDETEMPDIR}/cddbquery"
5180 echo "." >> "${ABCDETEMPDIR}/cddbquery"
5183 for X in $(f_seq_row 1 $NUM_CDDB_MATCHES)
5185 ATITLE=$(grep -a -e '^DTITLE=' "${ABCDETEMPDIR}/cddbread.$X" | cut -c8- | tr -d \\r\\n)
5186 SOURCE=$(cat "${ABCDETEMPDIR}/datasource.$X")
5187 echo "#$X ($SOURCE): ---- ${ATITLE} ----" >> "${ABCDETEMPDIR}/cddbchoices"
5188 for TRACK in $(f_seq_row 1 $TRACKS)
5190 echo "$TRACK:" "$(grep -a ^TTITLE$(($TRACK - 1))= "${ABCDETEMPDIR}/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "${ABCDETEMPDIR}/cddbchoices"
5192 echo >> "${ABCDETEMPDIR}/cddbchoices"
5199 eval "$($CDDBTOOL parse "$CDDBDATA")"
5202 # Before reading tracks, we set the speed of the device
5204 if [ X"$CDSPEEDVALUE" != "X" ]; then
5205 case "$CDROMREADERSYNTAX" in
5206 cdparanoia|libcdio|debug) ;;
5213 # Define the first and last track, since we might need them later in several places
5214 FIRSTTRACK=$( get_first $TRACKQUEUE )
5215 LASTTRACK=$( get_last $TRACKQUEUE )
5217 if [ -f "${ABCDETEMPDIR}/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
5218 mv "${ABCDETEMPDIR}/status" "${ABCDETEMPDIR}/status.old"
5219 grep -v ^encodetracklocation- < "${ABCDETEMPDIR}/status.old" \
5220 | grep -v ^encode-output > "${ABCDETEMPDIR}/status"
5223 if checkstatus onetrack ; then ONETRACK=y ; fi
5225 if [ "$ONETRACK" = "y" ]; then
5226 # Reuse the CUEFILE in case we created it (now or in a previous run)
5227 if CUEFILE=$(checkstatus cuefile); then
5232 # Create playlist if needed (backgroundable) and start reading in tracks
5236 if [ ! "$ONETRACK" = "y" ]; then
5237 if [ "$DOPLAYLIST" = "y" ]; then
5238 echo Creating playlist... >&2
5243 if [ "$GETALBUMART" = "y" ]; then
5247 # For the lowdisk option, only one program is running at once so the encoder
5248 # can be unsilenced right away.
5249 if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
5250 echo "encode-output=loud" >> "${ABCDETEMPDIR}/status"
5253 if [ "$ONETRACK" = "y" ]; then
5255 if [ "$USEPIPES" = "y" ]; then
5256 if checkstatus "readencodetrack-$FIRSTTRACK"; then :; else
5257 do_cdread onetrack $FIRSTTRACK $LASTTRACK | do_encode $FIRSTTRACK %local0% > /dev/null 2>&1
5260 if checkstatus "readtrack-$FIRSTTRACK"; then :; else
5261 do_cdread onetrack $FIRSTTRACK $LASTTRACK
5265 for UTRACKNUM in $TRACKQUEUE
5267 if [ "$DOREAD" = "y" ]; then
5268 if [ "$USEPIPES" = "y" ]; then
5269 if checkstatus "readencodetrack-$UTRACKNUM"; then :; else
5270 # Read, pipe, shut up!
5271 do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
5274 if checkstatus "readtrack-$UTRACKNUM"; then :; else
5275 do_cdread $UTRACKNUM
5277 if [ "$?" != "0" ]; then
5278 # CD read failed - don't give the goahead to
5285 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ]; then
5288 # If we are not reading, set the encode output to loud already, so
5289 # that we can see the output of the first track.
5290 if [ "$MAXPROCS" = "1" ] && [ ! "$DOREAD" = "y" ]; then
5291 echo "encode-output=loud" >> "${ABCDETEMPDIR}/status"
5293 echo NEXTTRACK # Get the encoder machine churning again
5294 if [ "$DOREAD" = "y" ]; then
5295 if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
5296 until checkstatus "encodetrack-$UTRACKNUM"
5298 if checkerrors "encodetrack-$UTRACKNUM"; then
5309 # Now that we're done the encoding can be loud again -
5310 # if we're not using SMP.
5311 if [ "$MAXPROCS" = "1" ]; then
5312 echo "encode-output=loud" >> "${ABCDETEMPDIR}/status"
5315 # All tracks read, start encoding.
5316 if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ] || [ "$ONETRACK" = "y" ]; then
5320 # Execute the user-defined post_read function before ejecting CD
5323 # We are now finished with the cdrom - it can be safely ejected. Note that
5324 # abcde will not have completed yet.
5325 if [ "$EJECTCD" = "y" ]; then
5326 # We check if the disk we are processing is actually the disk inside the
5327 # CD tray. If not, we do not eject the CD, since it might be so that the
5328 # user ejected it manually.
5329 #CURRENTTRACKINFO=$($CDDISCID $CDROM)
5330 #if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$CDDBTRACKINFO" ] ; then
5331 # More FreeBSD bits.
5332 if [ X"$UNAME" = X"FreeBSD" ] ; then
5333 # FreeBSD eject uses the EJECT environment variable to name the CDROM
5334 # but in this script EJECT is in the envionment and names the program
5337 # The FreeBSD eject needs "adc0" not "/dev/adc0c"
5338 cd="$(echo "$CDROM" | sed -e 's=.*/==;s=[a-h]$==;')"
5339 $eject $EJECTOPTS $cd
5340 elif [ X"$UNAME" = X"Darwin" ] ; then
5341 diskutil eject "${CDROM#/dev/}" 0
5342 elif [ -x "$(which "$EJECT")" ]; then
5343 $EJECT $EJECTOPTS "$CDROM"
5350 ## Do we need to pre-process
5351 #if [ x"$PREPROCESS" = "x" ] ; then
5354 # for PRETRACKNUM in $TRACKQUEUE
5357 # if [ "$GOAHEAD" = "NO" ]; then break; fi
5359 # until [ $PREPROCEED ]
5361 # if checkstatus "readtrack-$PRETRACKNUM"; then PREPROCEED=y; break; fi
5362 # # all locations are working, wait and try again later
5363 # if [ ! $PREPROCEED ]; then sleep 3; fi
5365 # ( do_preprocess $PRETRACKNUM
5373 # In BATCHNORM and/or NOGAP modes, we want all tracks to be read first.
5375 if [ "$BATCHNORM" = "y" ] || [ "$NOGAP" = "y" ]; then
5376 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
5377 if [ "$GOAHEAD" != "NO" ]; then
5378 for LASTTRACK in $TRACKQUEUE; do :; done
5379 if checkstatus "readtrack-$LASTTRACK"; then
5380 if [ "$DONORMALIZE" = "y" ] && [ "$BATCHNORM" = "y" ]; then
5381 if checkstatus "normalizetrack-$LASTTRACK"; then :; else do_batch_normalize; fi
5382 if checkerrors batch-normalize; then exit 1; fi
5384 if [ "$DOENCODE" = "y" ] && [ "$NOGAP" = "y" ]; then
5385 if [ "$DONORMALIZE" = "y" ]; then
5386 for UTRACKNUM in $TRACKQUEUE
5388 if checkstatus "readtrack-$UTRACKNUM"; then
5389 if checkstatus "normalizetrack-$UTRACKNUM"; then :; else do_normalize "$UTRACKNUM"; fi
5393 if checkstatus "encodetrack-$LASTTRACK"; then :; else do_nogap_encode; fi
5394 if checkerrors nogap-encode; then exit 1; fi
5400 # If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
5401 if [ "$ONETRACK" = "y" ] ; then
5402 TRACKQUEUE="$FIRSTTRACK"
5403 TRACKS="$FIRSTTRACK"
5406 # Do the encoding, including parallelization of remote encoding
5407 # Figure out where each track is going to be encoded
5408 ENCODELOCATIONS="$(echo "$REMOTEHOSTS" | tr , ' ')"
5409 if [ "$MAXPROCS" != "0" ]; then
5410 for NUM in $(f_seq_row 1 $MAXPROCS)
5412 ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
5416 ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
5417 for UTRACKNUM in $TRACKQUEUE
5420 read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
5421 if [ "$GOAHEAD" = "NO" ]; then break; fi
5422 # find out where this track is to be encoded
5423 if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ]; then
5424 # Make sure we have a place to encode this, if not, exit stage right
5425 if [ -z "$ENCODELOCATIONS" ]; then
5431 for LOCATION in $ENCODELOCATIONS
5433 PREVIOUSTRACK="$(checkstatus "encodetracklocation-$LOCATION")"
5434 # check first if a track has ever been assigned to this location
5435 if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
5436 # If it errored out, rebuild $ENCODELOCATIONS without this location in it
5437 if checkerrors "encodetrack-$PREVIOUSTRACK"; then
5438 for TEMPLOCATION in $ENCODELOCATIONS
5440 if [ "$TEMPLOCATION" != "$LOCATION" ]; then
5441 TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
5444 ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
5449 # We're still here, this location must have been previously assigned,
5450 # and last completed without error - check if it's done with the
5451 # previous track yet
5452 if checkstatus "encodetrack-$PREVIOUSTRACK"; then PROCEED=y; break; fi
5454 # all locations are working, wait and try again later
5455 if [ ! "$PROCEED" ]; then sleep 3; fi
5457 # Record the location we're about to encode the next track at
5458 echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "${ABCDETEMPDIR}/status"
5460 # Don't proceed with the rest of the loop if we can't encode
5461 if [ "$ABORT" ]; then continue; fi
5462 ## FIXME ## Add here
5463 ## run_command "tagtrack-$OUTPUT-$1" $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="${ABCDETEMPDIR}/$CUEFILE"} --import-tags-from=- "${ABCDETEMPDIR}/track$1.$FLACOUTPUTCONTAINER"
5464 # Set TRACKNUM, TRACKNAME
5465 if [ -e "$CDDBDATA" ]; then
5466 if [ "$ONETRACK" = "y" ]; then
5468 TRACKNUM="$FIRSTTRACK"
5471 TRACKNUM="$UTRACKNUM"
5472 CDDBTRACKNUM=$(expr $UTRACKNUM - 1) # Unpad
5473 getcddbinfo TRACKNAME
5477 # You can't encode a file which needs to be normalized before finishing
5478 # You can't tag a file before it's finished encoding -
5479 # thus all of this is backgrounded together
5481 if [ "$DONORMALIZE" = "y" ]; then
5482 if checkstatus "readtrack-$UTRACKNUM"; then
5483 if checkstatus "normalizetrack-$UTRACKNUM"; then :; else do_normalize "$UTRACKNUM"; fi
5486 if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ]; then
5487 if checkstatus "readtrack-$UTRACKNUM"; then
5488 if [ "$DONORMALIZE" = "y" ]; then
5489 if checkstatus "normalizetrack-$UTRACKNUM"; then
5490 if checkstatus "encodetrack-$UTRACKNUM"; then :; else do_encode "$UTRACKNUM" "$LOCATION" "$OUTPUT"; fi
5493 if checkstatus "encodetrack-$UTRACKNUM"; then :; else do_encode "$UTRACKNUM" "$LOCATION" "$OUTPUT"; fi
5497 if [ "$DOTAG" = "y" ]; then
5498 if checkstatus "encodetrack-$UTRACKNUM"; then
5499 if checkstatus "tagtrack-$UTRACKNUM"; then :; else do_tag "$UTRACKNUM"; fi
5501 # Lets tag the cue file
5502 if checkstatus cleancuefile >/dev/null; then :; else
5503 if checkstatus cuefile >/dev/null ; then
5508 if [ "$DOMOVE" = "y" ]; then
5509 if checkstatus "tagtrack-$UTRACKNUM"; then
5510 if checkstatus "movetrack-$UTRACKNUM"; then :; else do_move "$UTRACKNUM"; fi
5517 # Go through it again and make sure there's no distmp3 stragglers, otherwise
5518 # we'll delete the files they're working on
5519 # Do NOT play ball if there is no ball to play (so ABORT if needed)
5520 ## FIXME ## Check also for files which are encoded using PIPEs.
5521 if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ] && [ ! "$ABORT" ]; then
5526 for LOCATION in $ENCODELOCATIONS
5528 CHECKTRACK="$(checkstatus "encodetracklocation-$LOCATION")"
5529 # "How can he give us a status update, if he's DEAD?"
5530 if checkstatus "encodetrack-$CHECKTRACK"; then
5533 # Nothing to see here please go quietly back to your homes
5534 if [ -z "$CHECKTRACK" ]; then continue; fi
5535 # You're still here? Maybe there is something...
5536 if checkstatus "encodetrack-$CHECKTRACK"; then :; else PROCEED= ; break; fi
5539 if [ ! $PROCEED ]; then sleep 5; fi
5542 # If the above didn't catch the stragglers, this will
5544 if [ "$DOREPLAYGAIN" = "y" ]; then
5548 if [ "$EMBEDALBUMART" = "y" ]; then
5552 # Execute the user-defined post_encode function before cleaning up
5555 # Check to see if run_command logged any errors
5556 if [ -f "${ABCDETEMPDIR}/errors" ]; then
5557 log error "The following commands failed to run:"
5558 cat "${ABCDETEMPDIR}/errors"
5562 if [ "$KEEPWAVS" = "y" ];then
5566 # Check if we have moved all the formats we had previously encoded, if we are not using the FORCE.
5567 if [ "$DOCLEAN" = "y" ] && [ ! "$FORCE" = "y" ]; then
5568 ENCODED_FORMATS=$(grep -E "^encodetrack-(.{3,6})-(.{1,2})$" "${ABCDETEMPDIR}/status" | cut -d"-" -f2 | sort -u | tr '\n' '|')
5569 MOVED_FORMATS=$(grep -E "^movetrack-output-(.{3,6})$" "${ABCDETEMPDIR}/status" | cut -d"-" -f3 | sort -u | tr '\n' '|')
5570 if [ "$ENCODED_FORMATS" != "$MOVED_FORMATS" ]; then
5571 log warning "The encoded formats does not match with the moved ones"
5572 log warning "Formats encoded: $( echo "$ENCODED_FORMATS" | tr "|" " " )"
5573 log warning "Formats moved: $( echo "$MOVED_FORMATS" | tr "|" " " )"
5574 log warning "Use \"abcde -a clean -f -C ${CDDBDISCID}\" to force the removal of the remaining data."
5578 if [ "$DOCLEAN" = "y" ]; then
5579 # Wipe all the evidence
5580 # Gimme gimme gimme some more time!
5582 rm -rf "${ABCDETEMPDIR}"
5585 echo "Finished. Not cleaning ${ABCDETEMPDIR}."