[Abcde-users] Problem with 'abcde -d disc.flac'
Charles Steinkuehler
charles at steinkuehler.net
Sat Dec 1 19:17:36 GMT 2018
On 11/27/2018 2:13 AM, Bjørn Forsman wrote:
> Hi Charles,
>
> On Tue, 27 Nov 2018 at 00:19, Charles Steinkuehler
> <charles at steinkuehler.net> wrote:
>
>> If anyone is interested, I can dredge up my local changes and see
>> about merging into the latest abcde. Here's the Debian BTS issue I
>> filed about this in 2006:
>>
>> https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=377240
>
> Yes, I would definitely be interested. (I have not found a way to
> non-lossy backup my CDs yet.)
OK, I can't find the magic USB stick that had my Debian install for
ripping CDs, but it would be an ancient version anyway.
I do have my changes and configurations backed up, so I'm working on
getting a new Debian Stretch based system setup for testing. In the
meantime, I have reviewed my setup and I suspect the issues you're
having may simply be due to your configuration file and how you're
calling abcde.
The "interesting" non-default settings I have in my abcde.conf file
include:
CUEREADERSYNTAX=toc2cue
CUE2DISCID=abcde.cue2discid
MKCUE=abcde.mkcue
I also call abcde with the (required) -1 switch, to tell it to rip the
entire CD. I actually didn't call abcde directly when ripping, but
created a rip-cd and rip-flac wrapper script so I didn't have to
remember all the magic command-line switches. In addition, the setup
keeps a local cache of the cddb data so once the flac file is ripped
and the cddb data is acquired, it's possible to re-rip from the flac
files without any user interaction and any custom tweaks made to the
song titles and such in the cddb data will be incorporated when
tagging the new files (I re-ripped my entire flac library a few times
back in the old days when mp3 encoding on Linux was still pretty new).
I'm attaching my setup and script files, along with the (ancient)
version of abcde that they go with, mostly for reference in case
something has dramatically changed. I'll try to get full-disk ripping
working with the latest abcde this weekend, but I've got some holiday
parties to go to as well. Let me know if you beat me to getting
something working! :)
NOTE:
The rip scripts are setup so the flac files are exactly the same as
the CD data, but when ripping to mp3 (or other formats) the entire CD
is batch-normalized.
The support for an abcde.opts file next to the flac file is so various
artist disks could be automatically ripped. The heuristics for
setting the VARIOUSARTISTS flag don't work on all disks, so I added a
way to force the flag to be set (pretty much all the option letters
were already taken, so I use "various" without a dash as the option to
force VARIOUSARTISTS=y). Maybe this has improved since 2010? :)
--
Charles Steinkuehler
charles at steinkuehler.net
-------------- next part --------------
#!/bin/bash
# Copyright (c) 1998-2001 Robert Woodcock <rcw at debian.org>
# Copyright (c) 2003-2006 Jesus Climent <jesus.climent at hispalinux.es>
# This code is hereby licensed for public consumption under either the
# GNU GPL v2 or greater, or Larry Wall's Artistic license - your choice.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Copyright for this work is to expire January 1, 2010, after which it
# shall be public domain.
#
# $Id: abcde 223 2006-08-05 20:41:19Z data $
VERSION='2.3.99-$Revision: 223 $'
usage ()
{
echo "This is abcde v$VERSION."
echo "Usage: abcde [options] [tracks]"
echo "Options:"
echo "-1 Encode the whole CD in a single file"
echo "-a <action1[,action2]...>"
echo " Actions to perform:"
echo " cddb,read,normalize,encode,tag,move,replaygain,playlist,clean"
#echo "-A Experimental actions (retag, transcode)"
echo "-b Enable batch normalization"
#echo "-B Disable batch replaygain (do file by file)"
echo "-c <file>"
echo " Specify a configuration file (overrides system and user config files)"
echo "-C <discid#>"
echo " Specify discid to resume from (only needed if you no longer have the cd)"
echo "-d <device>"
echo " Specify CDROM device to grab (flac uses a single-track flac file)"
echo "-D Debugging mode (equivalent to sh -x abcde)"
echo "-e Erase encoded track information from status file"
echo "-f Force operations that otherwise are considered harmful. Read \"man abcde\""
echo "-g Use \"lame --nogap\" for MP3 encoding. Disables low disk and pipes flags"
echo "-h This help information"
#echo "-i Tag files while encoding, when possible (local only) -NWY-"
echo "-j <#> Number of encoder processes to run at once (localhost)"
echo "-k Keep the wav tracks for later use"
echo "-l Use low disk space algorithm"
echo "-L Use local CDDB storage directory"
echo "-n No lookup. Don't query CDDB, just create and use template"
echo "-N Noninteractive. Never prompt for anything"
echo "-m Modify playlist to include CRLF endings, to comply with some players"
echo " WARNING: Deprecated. Use \"cue\" action"
echo "-M Create a CUE file"
echo "-o <type1[,type2]...>"
echo " Output file type(s) (vorbis,mp3,flac,spx,mpc,wav,m4a). Defaults to vorbis"
echo "-p Pad track numbers with 0's (if less than 10 tracks)"
echo "-P Use UNIX pipes to read+encode without wav files"
echo "-r <host1[,host2]...>"
echo " Also encode on these remote hosts"
echo "-R Use local CDDB in recursive mode"
echo "-s <field>"
echo " Show dielfs from the CDDB info (year,genre)"
echo "-S <#> Set the CD speed"
echo "-t <#> Start the track numbering at a given number"
echo "-T <#> Same as -t but modifies tag numbering"
echo "-U Do NOT use UNICODE (UTF8) tags and comments"
echo "-v Show version number and exit"
echo "-V Be a bit more verbose about what is happening behind the scenes"
echo "-x Eject CD after all tracks are read"
echo "-w <comment>"
echo " Add a comment to the CD tracks"
echo "-W <#> Contatenate CDs: -T #01 -w \"CD #\""
echo "-z Use debug CDROMREADERSYNTAX option (needs cdparanoia)"
echo ""
echo "Tracks is a space-delimited list of tracks to grab."
echo "Ranges specified with hyphens are allowed (i.e., 1-5)."
echo ""
#echo "Double hyphens are used to concatenate tracks"
}
addstatus ()
{
echo "$@" >> "$ABCDETEMPDIR/status"
}
# log [level] [message]
#
# log outputs the right message in a common format
log ()
{
BLURB="$1"
shift
case $BLURB in
error) echo "[ERROR] abcde: $@" >&2 ;;
warning) echo "[WARNING] $@" >&2 ;;
info) echo "[INFO] $@" ;;
esac
}
# Funtions to replace the need of seq, which is too distribution dependant.
f_seq_row ()
{
i=$1
while [ $i -ne `expr $2 + 1` ]
do
echo $i
i=`expr $i + 1`
done
}
f_seq_line ()
{
i=$1
if echo $i | grep "[[:digit:]]" > /dev/null 2>&1 ; then
while [ $i -ne `expr $2 + 1` ]
do
printf $i" "
i=`expr $i + 1`
done
echo
else
log error "syntax error while processing track numbers"
exit 1
fi
}
# Functions to replace the need of awk {print $1} and {print $NF}
get_first()
{
if [ X"$1" = "X" ]; then
for first in `cat`; do
break
done
else
first=$1
fi
echo $first
}
get_last()
{
if [ X"$1" = "X" ]; then
for stdin in `cat`; do
last=$stdin
done
else
for last in $@ ; do :; done
fi
echo $last
}
# checkstatus [blurb]
# Returns "0" if the blurb was found, returns 1 if it wasn't
# Puts the blurb content, if available, on stdout.
# Otherwise, returns "".
checkstatus ()
{
# Take the last line in the status file if there's multiple matches
PATTERN="^$1(=.*)?$"
BLURB=$(egrep $PATTERN "$ABCDETEMPDIR/status" | tail -n 1)
if [ -z "$BLURB" ]; then
# No matches found
return 1
else
# Matches found
# See if there's a = in it
if [ "$(echo $BLURB | grep -c =)" != "0" ]; then
echo "$(echo $BLURB | cut -f2- -d=)"
fi
return 0
fi
}
# checkwarnings [blurb]
# Returns "0" if the blurb was found (meaning there was an warning),
# returns 1 if it wasn't (yes this is a little backwards).
# Does not print the blurb on stdout.
# Otherwise, returns "".
checkwarnings ()
{
if [ -e "$ABCDETEMPDIR/warnings" ]; then :; else
return 1
fi
# Take the last line in the status file if there's multiple matches
PATTERN="^$1(:.*)?$"
BLURB="$(egrep $PATTERN "$ABCDETEMPDIR/warnings" | tail -n 1)"
if [ -z "$BLURB" ]; then
# negative, we did not have a negative...
return 1
else
# affirmative, we had a negative...
return 0
fi
}
# checkerrors [blurb]
# Returns "0" if the blurb was found (meaning there was an error),
# returns 1 if it wasn't (yes this is a little backwards).
# Does not print the blurb on stdout.
# Otherwise, returns "".
checkerrors ()
{
if [ -e "$ABCDETEMPDIR/errors" ]; then :; else
return 1
fi
# Take the last line in the status file if there's multiple matches
PATTERN="^$1(:.*)?$"
BLURB="$(egrep $PATTERN "$ABCDETEMPDIR/errors" | tail -n 1)"
if [ -z "$BLURB" ]; then
# negative, we did not have a negative...
return 1
else
# affirmative, we had a negative...
return 0
fi
}
# page [file]
# Finds the right pager in the system to display a file
page ()
{
PAGEFILE="$1"
# Use the debian sensible-pager wrapper to pick the pager
# user has requested via their $PAGER environment variable
if [ -x "/usr/bin/sensible-pager" ]; then
/usr/bin/sensible-pager "$PAGEFILE"
elif [ -x "$PAGER" ]; then
# That failed, try to load the preferred editor, starting
# with their PAGER variable
$PAGER "$PAGEFILE"
# If that fails, check for less
elif [ -x /usr/bin/less ]; then
/usr/bin/less -f "$PAGEFILE"
# more should be on all UNIX systems
elif [ -x /bin/more ]; then
/bin/more "$PAGEFILE"
else
# No bananas, just cat the thing
cat "$PAGEFILE" >&2
fi
}
# run_command [blurb] [command...]
# Runs a command, silently if necessary, and updates the status file
run_command ()
{
BLURB="$1"
shift
# See if this is supposed to be silent
if [ "$(checkstatus encode-output)" = "loud" ]; then
"$@" >&2
RETURN=$?
else
# Special case for SMP, since
# encoder output is never displayed, don't mute echos
if [ -z "$BLURB" -a "$MAXPROCS" != "1" ]; then
"$@" >&2
RETURN=$?
else
"$@" >/dev/null 2>&1
RETURN=$?
fi
fi
case "$1" in
normalize|normalize-audio)
if [ "$RETURN" = "2" ]; then
# File was already normalized.
RETURN=0
fi
;;
esac
if [ "$RETURN" != "0" ]; then
# Put an error in the errors file. For various reasons we
# can't capture a copy of the program's output but we can
# log what we attempted to execute and the error code
# returned by the program.
if [ "$BLURB" ]; then
TWEAK="$BLURB: "
fi
echo "${TWEAK}returned code $RETURN: $@" >> "$ABCDETEMPDIR/errors"
return $RETURN # Do not pass go, do not update the status file
fi
if [ "$BLURB" ]; then
echo $BLURB >> "$ABCDETEMPDIR/status"
fi
}
# relpath() and slash() are Copyright (c) 1999 Stuart Ballard and
# distributed under the terms of the GNU GPL v2 or later, at your option
# Function to determine if a word contains a slash.
slash ()
{
case "$1" in
*/*) return 0;;
*) return 1;;
esac
}
# Function to give the relative path from one file to another.
# Usage: relpath fromfile tofile
# eg relpath music/Artist/Album.m3u music/Artist/Album/Song.mp3
# (the result would be Album/Song.mp3)
# Output is relative path to $2 from $1 on stdout
# This code has the following restrictions:
# Multiple ////s are not collapsed into single /s, with strange effects.
# Absolute paths and ../s are handled wrong in FR (but they work in TO)
# If FR is a directory it must have a trailing /
relpath ()
{
FR="$1"
TO="$2"
case "$TO" in
/*) ;; # No processing is needed for absolute paths
*)
# Loop through common prefixes, ignoring them.
while slash "$FR" && [ "$(echo "$FR" | cut -d/ -f1)" = "$(echo "$TO" | cut -d/ -f1)" ]
do
FR="$(echo "$FR" | cut -d/ -f2-)"
TO="$(echo "$TO" | cut -d/ -f2-)"
done
# Loop through directory portions left in FR, adding appropriate ../s.
while slash "$FR"
do
FR="$(echo "$FR" | cut -d/ -f2-)"
TO="../$TO"
done
;;
esac
echo $TO
}
new_checkexec ()
{
if [ ! "$@" = "" ]; then
# Cut off any command-line option we added in
X=$(echo $@ | cut -d' ' -f2)
if [ "$(which $X)" = "" ]; then
return 1
elif [ ! -x $(which $X) ]; then
return 2
fi
fi
return 0
}
checkexec ()
{
if [ ! "$@" = "" ]; then
# Cut off any command-line option we added in
X=$(echo $@ | cut -d' ' -f2)
# Test for built-in abcde.function
[ "$X" != "${X#abcde.}" ] && type $X >/dev/null 2>&1 && return
if [ "$(which $X)" = "" ]; then
log error "$X is not in your path." >&2
log info "Define the full path to the executable if it exists on your system." >&2
exit 1
elif [ ! -x "$(which $X)" ]; then
log error "$X is not executable." >&2
exit 1
fi
fi
}
# diffentries <filename> <max_value> <entry1>,<entry2>
# max_value: the range of entries goes from 1 to <max_value>
diffentries ()
{
FILENAME=$1
shift
local CDDBDIFFCHOICES=$1
shift
local CDDBDIFFCHOICE="$@"
if [ ! X"$DIFF" = "X" ]; then
PARSECHOICE1=$(echo $CDDBDIFFCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
PARSECHOICE2=$(echo $CDDBDIFFCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBDIFFCHOICES ] || \
[ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBDIFFCHOICES ] || \
[ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then
echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBDIFFCHOICES" >&2
else
# We parse the 2 choices to diff, store them in temporary files and diff them.
for PARSECHOICE in $(echo $CDDBDIFFCHOICE | tr , \ ); do
do_cddbparse "$ABCDETEMPDIR/$FILENAME.$PARSECHOICE" > "$ABCDETEMPDIR/$FILENAME.parsechoice.$PARSECHOICE"
done
echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/$FILENAME.diff"
$DIFF $DIFFOPTS "$ABCDETEMPDIR/$FILENAME.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/$FILENAME.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/$FILENAME.diff"
if [ $(cat "$ABCDETEMPDIR/$FILENAME.diff" | wc -l) -ge 24 ]; then
page "$ABCDETEMPDIR/$FILENAME.diff"
else
cat "$ABCDETEMPDIR/$FILENAME.diff" >&2
fi
fi
else
echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBDIFFCHOICES." >&2
fi
}
# getcddbinfo
# Finds an specific field from cddbinfo
getcddbinfo()
{
case $1 in
TRACKNAME1)
TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | head -n 1 | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
;;
TRACKNAME)
TRACKNAME="$(grep ^TTITLE$CDDBTRACKNUM= "$CDDBDATA" | cut -f2- -d= | tr -d \[:cntrl:\] | sed 's/\ \+$//')"
;;
esac
}
# gettracknum
# Get the track number we are going to use for different actions
gettracknum()
{
if [ -n "$STARTTRACKNUMBER" ] ; then
# Get the trackpadding from the current track
CURRENTTRACKPADDING=$(echo -n $UTRACKNUM | wc -c)
TRACKNUM=$( printf %0.${CURRENTTRACKPADDING}d $(expr ${UTRACKNUM} + ${STARTTRACKNUMBER} - $FIRSTTRACK ))
else
TRACKNUM=${UTRACKNUM}
fi
}
# makeids
#
# Calculate cddb disc ids without requiring specialized helper programs.
# largely copied from cd-discid and musicbrainz examples. some of the steps
# don't make sense, but they're necessary to match the ids generated by other
# programs.
#
## FIXME ## Right now, we get 2 frames more than with cue2discid ??
# data at petit:~$ sh /tmp/cue2discid /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac
# 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
# 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2895
# data at petit:~$ metaflac --export-cuesheet-to=- /home/data/tmp/flac/01.Roisin_Murphy--Ruby_Blue.flac| python /home/data/sources/abcde/trunk/examples/cue2discid
# 980b4b0c 12 150 21685 37687 53146 80061 97782 124071 144448 160603 173208 197438 201334 2893
#
# Variables: OFFSETS, TRACKS, LEADOUT, [LEADIN]
makeids ()
{
if [ X"$LEADOUT" = "X" ]; then
log warning "Error trying to calculate disc ids without lead-out information."
exit 1
fi
# default to a two second lead-in
IDMAGICNUM=150
LEADIN=${LEADIN:=150}
# number of cdframes per second
CDFRAMES=75
# reset cddb checksum for cddb disc-id calululation
CDDBCKSUM=0
COOKEDOFFSETS=""
for OFFSET in $(echo $OFFSETS)
do
COOKEDOFFSETS="${COOKEDOFFSETS} $(($OFFSET + $LEADIN))"
OFFSETTIME=$(( ($OFFSET + $LEADIN) / $CDFRAMES ))
while [ $OFFSETTIME -gt 0 ]; do
CDDBCKSUM=$(($CDDBCKSUM + $OFFSETTIME % 10))
OFFSETTIME=$(($OFFSETTIME / 10))
done
done
COOKEDOFFSETS="${COOKEDOFFSETS:1}" # eat the leading space
PREGAP=$(($(echo $OFFSETS | cut -f1 -d' ')))
TOTALTIME=$(( (($LEADOUT + $LEADIN + $PREGAP) / $CDFRAMES) - (($LEADIN + $PREGAP) / $CDFRAMES)))
printf -v HEXSUM "%08lx" $(( ($CDDBCKSUM % 0xff) << 24 | $TOTALTIME << 8 | $TRACKS))
TRACKINFO="${HEXSUM} $((TRACKS)) ${COOKEDOFFSETS} $((($LEADOUT + $LEADIN + $IDMAGICNUM) / $CDFRAMES))"
}
do_replaygain()
{
if checkstatus replaygain; then :; else
run_command "" echo "Adding replygain information..."
for TMPOUTPUT in $( echo $OUTPUTTYPE | tr , \ )
do
case $TMPOUTPUT in
vorbis|ogg)
OUTPUT=$OGGOUTPUTCONTAINER
;;
flac)
OUTPUT=$FLACOUTPUTCONTAINER
;;
*)
OUTPUT=$TMPOUTPUT
;;
esac
OUTPUTFILES=""
REPLAYINDEX=0
for UTRACKNUM in $TRACKQUEUE
do
CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
getcddbinfo TRACKNAME
splitvarious
TRACKFILE="$(mungefilename "$TRACKNAME")"
ARTISTFILE="$(mungefilename "$TRACKARTIST")"
ALBUMFILE="$(mungefilename "$DALBUM")"
gettracknum
if [ "$ONETRACK" = "y" ]; then
if [ "$VARIOUSARTISTS" = "y" ]; then
OUTPUTFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\")"
else
OUTPUTFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\")"
fi
else
if [ "$VARIOUSARTISTS" = "y" ]; then
OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT"\")"
else
OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT"\")"
fi
fi
OUTPUTFILES[$REPLAYINDEX]="$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
(( REPLAYINDEX = $REPLAYINDEX + 1 ))
done
case "$OUTPUT" in
flac)
run_command replaygain-flac nice $ENCNICE $METAFLAC --add-replay-gain "${OUTPUTFILES[@]}"
;;
vorbis|ogg)
run_command replaygain-vorbis nice $ENCNICE $VORBISGAIN --album "${OUTPUTFILES[@]}"
;;
mp3)
run_command replaygain-mp3 nice $ENCNICE $MP3GAIN -a "${OUTPUTFILES[@]}"
;;
mpc)
run_command replaygain-mpc nice $ENCNICE $MPPGAIN --auto "${OUTPUTFILES[@]}"
;;
*);;
esac
done
if checkerrors "replaygain-.{3,6}"; then :; else
run_command replaygain true
fi
fi
}
# This code splits the a Various Artist track name from one of the following
# forms:
#
# forward: Artist / Track
# forward-dash: Artist - Track
# reverse: Track / Artist
# reverse-dash: Track - Artist
# colon: Artist: Track
# trailing-paren: Artist (Track)
#
# variables used:
# VARIOUSARTISTS, VARIOUSARTISTSTYLE, TRACKNAME, TRACKARTIST
splitvarious ()
{
if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
case "$VARIOUSARTISTSTYLE" in
forward)
DTITLEARTIST="$(echo "$TRACKNAME" | sed 's- / -~-g')"
TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
;;
forward-dash)
DTITLEARTIST="$(echo "$TRACKNAME" | sed 's, - ,~,g')"
TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
;;
reverse)
DTITLEARTIST="$(echo "$TRACKNAME" | sed 's- / -~-g')"
TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
;;
reverse-dash)
DTITLEARTIST="$(echo "$TRACKNAME" | sed 's, - ,~,g')"
TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
;;
colon)
DTITLEARTIST="$(echo "$TRACKNAME" | sed 's-: -~-g')"
TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
TRACKNAME="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
;;
trailing-paren)
DTITLEARTIST="$(echo "$TRACKNAME" | sed 's,^\(.*\) (\(.*\)),\1~\2,')"
TRACKARTIST="$(echo "$DTITLEARTIST" | cut -f2 -d~)"
TRACKNAME="$(echo "$DTITLEARTIST" | cut -f1 -d~)"
;;
esac
elif [ "$VARIOUSARTISTS" = "y" ] && [ "$ONETRACK" = "y" ]; then
TRACKARTIST="Various"
else
TRACKARTIST="$DARTIST"
fi
}
do_getgenreid () {
local id="${@}"
local genre=$(echo "${@}" | tr '[A-Z]' '[a-z]')
case ${genre} in
"blues") id=0 ;;
"classic rock") id=1 ;;
"country") id=2 ;;
"dance") id=3 ;;
"disco") id=4 ;;
"funk") id=5 ;;
"grunge") id=6 ;;
"hip-hop") id=7 ;;
"jazz") id=8 ;;
"metal") id=9 ;;
"new age") id=10 ;;
"oldies") id=11 ;;
"other") id=12 ;;
"pop") id=13 ;;
"r&b") id=14 ;;
"rap") id=15 ;;
"reggae") id=16 ;;
"rock") id=17 ;;
"techno") id=18 ;;
"industrial") id=19 ;;
"alternative") id=20 ;;
"ska") id=21 ;;
"death metal") id=22 ;;
"pranks") id=23 ;;
"soundtrack") id=24 ;;
"euro-techno") id=25 ;;
"ambient") id=26 ;;
"trip-hop") id=27 ;;
"vocal") id=28 ;;
"jazz+funk") id=29 ;;
"fusion") id=30 ;;
"trance") id=31 ;;
"classical") id=32 ;;
"instrumental") id=33 ;;
"acid") id=34 ;;
"house") id=35 ;;
"game") id=36 ;;
"sound clip") id=37 ;;
"gospel") id=38 ;;
"noise") id=39 ;;
"alt. rock") id=40 ;;
"bass") id=41 ;;
"soul") id=42 ;;
"punk") id=43 ;;
"space") id=44 ;;
"meditative") id=45 ;;
"instrum. pop") id=46 ;;
"instrumental pop") id=46 ;;
"instrum. rock") id=47 ;;
"instrumental rock") id=47 ;;
"ethnic") id=48 ;;
"gothic") id=49 ;;
"darkwave") id=50 ;;
"techno-indust.") id=51 ;;
"electronic") id=52 ;;
"pop-folk") id=53 ;;
"eurodance") id=54 ;;
"dream") id=55 ;;
"southern rock") id=56 ;;
"comedy") id=57 ;;
"cult") id=58 ;;
"gangsta") id=59 ;;
"top 40") id=60 ;;
"christian rap") id=61 ;;
"pop/funk"|"pop / funk") id=62 ;;
"jungle") id=63 ;;
"native american") id=64 ;;
"cabaret") id=65 ;;
"new wave") id=66 ;;
psych[ae]delic) id=67 ;;
"rave") id=68 ;;
"showtunes") id=69 ;;
"trailer") id=70 ;;
"lo-fi") id=71 ;;
"tribal") id=72 ;;
"acid punk") id=73 ;;
"acid jazz") id=74 ;;
"polka") id=75 ;;
"retro") id=76 ;;
"musical") id=77 ;;
"rock & roll") id=78 ;;
"hard rock") id=79 ;;
"folk") id=80 ;;
"folk/rock") id=81 ;;
"national folk") id=82 ;;
"swing") id=83 ;;
"fusion") id=84 ;;
"bebob") id=85 ;;
"latin") id=86 ;;
"revival") id=87 ;;
"celtic") id=88 ;;
"bluegrass") id=89 ;;
"avantgarde") id=90 ;;
"gothic rock") id=91 ;;
"progress. rock") id=92 ;;
"progressive rock") id=92 ;;
psych[ae]del.\ rock) id=93 ;;
psych[ae]delic\ rock) id=93 ;;
"symphonic rock") id=94 ;;
"slow rock") id=95 ;;
"big band") id=96 ;;
"chorus") id=97 ;;
"easy listening") id=98 ;;
"acoustic") id=99 ;;
"humour") id=100 ;;
"speech") id=101 ;;
"chanson") id=102 ;;
"opera") id=103 ;;
"chamber music") id=104 ;;
"sonata") id=105 ;;
"symphony") id=106 ;;
"booty bass") id=107 ;;
"primus") id=108 ;;
"porn groove") id=109 ;;
"satire") id=110 ;;
"slow jam") id=111 ;;
"club") id=112 ;;
"tango") id=113 ;;
"samba") id=114 ;;
"folklore") id=115 ;;
"ballad") id=116 ;;
"power ballad") id=117 ;;
"rhythmic soul") id=118 ;;
"freestyle") id=119 ;;
"duet") id=120 ;;
"punk rock") id=121 ;;
"drum solo") id=122 ;;
"a capella") id=123 ;;
"euro-house") id=124 ;;
"dance hall") id=125 ;;
"goa") id=126 ;;
"drum & bass") id=127 ;;
"club-house") id=128 ;;
"hardcore") id=129 ;;
"terror") id=130 ;;
"indie") id=131 ;;
"britpop") id=132 ;;
"negerpunk") id=133 ;;
"polsk punk") id=134 ;;
"beat") id=135 ;;
"christian gangsta rap") id=136 ;;
"heavy metal") id=137 ;;
"black metal") id=138 ;;
"crossover") id=139 ;;
"contemporary christian")id=140 ;;
"christian rock") id=141 ;;
"merengue") id=142 ;;
"salsa") id=143 ;;
"thrash metal") id=144 ;;
"anime") id=145 ;;
"jpop") id=146 ;;
"synthpop") id=147 ;;
"rock/pop"|"rock / pop") id=148 ;;
"pop/rock"|"pop / rock") id=148 ;;
# *) return 1 ;;
esac
echo "${id}"
return 0
}
# do_tag [tracknumber]
# id3 tags a filename
# variables used:
# TRACKS, TRACKNAME, TRACKARTIST, TAGGER, TAGGEROPTS, VORBISCOMMENT, METAFLAC,
# COMMENT, DALBUM, DARTIST, CDYEAR, CDGENRE, VARIOUSARTISTS (and temporarily) ID3TAGV
do_tag ()
{
COMMENTOUTPUT="$(eval echo ${COMMENT})"
CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
run_command '' echo "Tagging track $1 of $TRACKS: $TRACKNAME..."
# If we want to start the tracks with a given number, we need to modify the
# TRACKNUM value before evaluation
if [ -n "$STARTTRACKNUMBERTAG" ] ; then
gettracknum
fi
for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
do
case "$OUTPUT" in
mp3)
# id3v2 v0.1.9 claims to have solved the -c bug, so we merge both id3 and id3v2
GENREID=$(do_getgenreid "${CDGENRE}")
case "$ID3SYNTAX" in
id3);;
eyed3)
# FIXME # track numbers in mp3 come with 1/10, so we cannot
# happily substitute them with $TRACKNUM
if [ "$VARIOUSARTISTS" = "y" ] ; then
run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS \
--comment=::"$COMMENTOUTPUT" -A "$DALBUM" \
--set-text-frame="TCMP:1" --set-text-frame="TPE2:$DARTIST" \
-a "$TRACKARTIST" -t "$TRACKNAME" -Y "$CDYEAR" \
-G "$GENREID" -n "${TRACKNUM:-$1}" "${TRACKNUM:+-N $TRACKS}" \
"${ENCODING:+--set-encoding=$ENCODING}" \
"$ABCDETEMPDIR/track$1.$OUTPUT"
else
run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS \
--comment=::"$COMMENTOUTPUT" -A "$DALBUM" \
-a "$TRACKARTIST" -t "$TRACKNAME" -Y "$CDYEAR" \
-G "$GENREID" -n "${TRACKNUM:-$1}" "${TRACKNUM:+-N $TRACKS}" \
"${ENCODING:+--set-encoding=$ENCODING}" \
"$ABCDETEMPDIR/track$1.$OUTPUT"
fi
;;
# FIXME # Still not activated...
id3ed)
run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
-a "$DALBUM" -n "$TRACKARTIST" -s "$TRACKNAME" -y "$CDYEAR" \
-g "$GENREID" -k "${TRACKNUM:-$1}" \
"$ABCDETEMPDIR/track$1.$OUTPUT"
;;
*)
# FIXME # track numbers in mp3 come with 1/10, so we cannot
# happily substitute them with $TRACKNUM
if [ "$VARIOUSARTISTS" = "y" ] ; then
run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
--TPE2 "$DARTIST" \
-A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" \
-g "$GENREID" -T "${TRACKNUM:-$1/$TRACKS}" \
"$ABCDETEMPDIR/track$1.$OUTPUT"
run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $EYED3 $EYED3OPTS \
--set-text-frame="TCMP:1" \
"$ABCDETEMPDIR/track$1.$OUTPUT"
else
run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $TAGGER $TAGGEROPTS -c "$COMMENTOUTPUT" \
-A "$DALBUM" -a "$TRACKARTIST" -t "$TRACKNAME" -y "$CDYEAR" \
-g "$GENREID" -T "${TRACKNUM:-$1/$TRACKS}" \
"$ABCDETEMPDIR/track$1.$OUTPUT"
fi
;;
esac
;;
vorbis|ogg)
case "$OGGENCODERSYNTAX" in
vorbize|oggenc)
# vorbiscomment can't do in-place modification, mv the file first
if [ -f "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" -a ! -f "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" ]; then
mv "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
fi
(
# These are from http://www.xiph.org/ogg/vorbis/doc/v-comment.html
echo ARTIST="$TRACKARTIST"
echo ALBUM="$DALBUM"
echo TITLE="$TRACKNAME"
if [ -n "$CDYEAR" ]; then
echo DATE="$CDYEAR"
fi
if [ -n "$CDGENRE" ]; then
echo GENRE="$CDGENRE"
fi
echo TRACKNUMBER=${TRACKNUM:-$1}
echo CDDB=$CDDBDISCID
if [ "$(eval echo ${COMMENT})" != "" ]; then
case "$COMMENTOUTPUT" in
*=*) echo "$COMMENTOUTPUT";;
*) echo COMMENT="$COMMENTOUTPUT";;
esac
fi
) | run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $VORBISCOMMENT $VORBISCOMMENTOPTS -w \
"$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
# Doublecheck that the commented file was created successfully before wiping the original
if [ -f "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER" ]; then
rm -f "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER"
else
mv "$ABCDETEMPDIR/track$1.uncommented.$OGGOUTPUTCONTAINER" "$ABCDETEMPDIR/track$1.$OGGOUTPUTCONTAINER"
fi
;;
esac
;;
flac)
(
echo ARTIST="$TRACKARTIST"
echo ALBUM="$DALBUM"
echo TITLE="$TRACKNAME"
if [ -n "$CDYEAR" ]; then
echo DATE="$CDYEAR"
fi
if [ -n "$CDGENRE" ]; then
echo GENRE="$CDGENRE"
fi
echo TRACKNUMBER="${TRACKNUM:-$1}"
echo CDDB="$CDDBDISCID"
if [ "$(eval echo ${COMMENT})" != "" ]; then
case "$COMMENTOUTPUT" in
*=*) echo "$COMMENTOUTPUT";;
*) echo COMMENT="$COMMENTOUTPUT";;
esac
fi
) | run_command tagtrack-$OUTPUT-$1 nice $ENCNICE $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="$ABCDETEMPDIR/$CUEFILE"} --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
;;
spx)
run_command tagtrack-$OUTPUT-$1 true
;;
mpc)
run_command tagtrack-$OUTPUT-$1 true
;;
m4a)
run_command tagtrack-$OUTPUT-$1 true
;;
wav)
run_command tagtrack-$OUTPUT-$1 true
;;
esac
done
if checkerrors "tagtrack-(.{3,6})-$1"; then :; else
run_command tagtrack-$1 true
fi
}
# do_nogap_encode
# variables used:
# OUTPUTTYPE, {FOO}ENCODERSYNTAX, ENCNICE, ENCODER, ENCODEROPTS
do_nogap_encode ()
{
# The commands here don't go through run_command because they're never supposed to be silenced
echo "Encoding gapless MP3 tracks: $TRACKQUEUE"
for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
do
case "$OUTPUT" in
mp3)
case "$MP3ENCODERSYNTAX" in
lame|toolame)
(
cd "$ABCDETEMPDIR"
TRACKFILES=
for UTRACKNUM in $TRACKQUEUE
do
TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
done
nice $ENCNICE $MP3ENCODER $MP3ENCODEROPTS --nogap $TRACKFILES
RETURN=$?
if [ "$RETURN" != "0" ]; then
echo "nogap-encode: $ENCODER returned code $RETURN" >> errors
else
for UTRACKNUM in $TRACKQUEUE
do
run_command encodetrack-$OUTPUT-$UTRACKNUM true
#run_command encodetrack-$UTRACKNUM true
done
fi
)
;;
esac
;;
esac
done
if checkerrors "nogap-encode"; then :; else
if [ ! "$KEEPWAVS" = "y" ] ; then
if [ ! "$KEEPWAVS" = "move" ] ; then
rm -f "$IN"
fi
fi
fi
# Other encoders fall through to normal encoding as the tracks
# have not been entered in the status file.
}
# do_encode [tracknumber] [hostname]
# If no hostname is specified, encode locally
# variables used:
# TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
do_encode ()
{
if [ "$USEPIPES" = "y" ]; then
case "$OUTPUT" in
mp3)
TEMPARG="PIPE_$MP3ENCODERSYNTAX"
;;
vorbis|ogg)
TEMPARG="PIPE_$OGGENCODERSYNTAX"
;;
flac)
TEMPARG="PIPE_$FLACENCODERSYNTAX"
;;
spx)
TEMPARG="PIPE_$SPEEXENCODER"
;;
mpc)
TEMPARG="PIPE_$MPPENCODER"
;;
m4a)
TEMPARG="PIPE_$MPPENCODER"
;;
esac
IN="$( eval echo "\$$TEMPARG" )"
else
IN="$ABCDETEMPDIR/track$1.wav"
case "$OUTPUT" in
mp3)
case "$MP3ENCODERSYNTAX" in
# FIXME # check if mp3enc needs -if for pipes
# FIXME # I have not been able to find a working mp3enc binary
mp3enc)
FILEARG="-if $IN"
;;
*)
FILEARG="$IN"
;;
esac
;;
*)
FILEARG="$IN"
;;
esac
fi
# We need IN to proceed, if we are not using pipes.
if [ -s "$IN" -o X"$USEPIPES" = "Xy" ] ; then
for TMPOUTPUT in $(echo $OUTPUTTYPE | tr , \ )
do
case "$TMPOUTPUT" in
vorbis|ogg)
OUTPUT=$OGGOUTPUTCONTAINER
;;
flac)
OUTPUT=$FLACOUTPUTCONTAINER
;;
*)
OUTPUT=$TMPOUTPUT
;;
esac
OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
if [ "$NOGAP" = "y" ] && checkstatus encodetrack-$OUTPUT-$1 ; then
continue
fi
if [ X"$USEPIPES" = "Xy" ]; then
RUN_COMMAND=""
# We need a way to store the creation of the files when using PIPES
RUN_COMMAND_PIPES="run_command encodetrack-$OUTPUT-$1 true"
# When pipping it does not make sense to have a higher nice for
# reading than for encoding, since it will be hold by the
# encoding process. Setting an effective nice, to calm down a
# bit the reading process.
EFFECTIVE_NICE=$READNICE
else
run_command '' echo "Encoding track $1 of $TRACKS: $TRACKNAME..."
RUN_COMMAND="run_command encodetrack-$OUTPUT-$1"
EFFECTIVE_NICE=$ENCNICE
fi
case "$OUTPUT" in
mp3)
case "$2" in
%local*%)
case "$MP3ENCODERSYNTAX" in
lame|toolame|gogo) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER $MP3ENCODEROPTS "$IN" "$OUT" ;;
bladeenc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER $MP3ENCODEROPTS -quit "$IN" ;;
l3enc|xingmp3enc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER "$IN" "$OUT" $MP3ENCODEROPTS ;;
# FIXME # Relates to the previous FIXME since it might need the "-if" removed.
mp3enc) $RUN_COMMAND nice $EFFECTIVE_NICE $MP3ENCODER -if "$IN" -of "$OUT" $MP3ENCODEROPTS ;;
esac
;;
*)
$RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
;;
esac
;;
vorbis|ogg)
case "$2" in
%local*%)
case "$OGGENCODERSYNTAX" in
vorbize) $RUN_COMMAND nice $EFFECTIVE_NICE $OGGENCODER $OGGENCODEROPTS -w "$OUT" "$IN" ;;
oggenc) $RUN_COMMAND nice $EFFECTIVE_NICE $OGGENCODER $OGGENCODEROPTS -o "$OUT" "$IN" ;;
esac
;;
*)
$RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" >/dev/null 2>&1
;;
esac
;;
flac)
case "$2" in
%local*%)
case "$FLACENCODERSYNTAX" in
flac) $RUN_COMMAND nice $EFFECTIVE_NICE $FLACENCODER -f $FLACENCODEROPTS -o "$OUT" "$IN" ;;
esac
;;
*)
vecho -n "DISTMP3:"
vecho "$DISTMP3 $DISTMP3OPTS $2 $IN $OUT >/dev/null 2>&1"
$RUN_COMMAND nice $DISTMP3NICE $DISTMP3 $DISTMP3OPTS "$2" "$IN" "$OUT" > /dev/null 2>&1
;;
esac
;;
spx)
if [ "$(eval echo ${COMMENT})" != "" ]; then
case "$COMMENT" in
*=*) ;;
*) COMMENT="COMMENT=$COMMENT" ;;
esac
COMMENT="--comment \"$COMMENT\""
fi
# Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
if [ ! "$DOTAG" = "y" ]; then
$RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS --author "$TRACKARTIST" --title "$TRACKNAME" "$COMMENT" "$IN" "$OUT"
else
$RUN_COMMAND nice $EFFECTIVE_NICE $SPEEXENCODER $SPEEXENCODEROPTS "$IN" "$OUT"
fi
;;
mpc)
# MPP/MP+(Musepack) format (.mpc) is done locally, with inline
# tagging.
# I tried compiling the mppenc from corecodecs.org and got some
# errors, so I have not tried it myself.
## FIXME ## Needs some cleanup to determine if an empty tag sent
## FIXME ## to the encoder ends up empty.
$RUN_COMMAND nice $EFFECTIVE_NICE $MPPENCODER $MPPENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" "$IN" "$OUT"
;;
m4a)
# Quick hack to avoid tagging Ogg/Speex, since there is no other way to tag than inline tagging
if [ ! "$DOTAG" = "y" ]; then
$RUN_COMMAND nice $EFFECTIVE_NICE $AACENCODER $AACENCODEROPTS --artist "$TRACKARTIST" --album "$DALBUM" --title "$TRACKNAME" --track "$1" --genre "$CDGENRE" --year "$CDYEAR" --comment "$COMMENT" -o "$OUT" "$IN"
else
$RUN_COMMAND nice $ENCNICE $AACENCODER $AACENCODEROPTS -o "$OUT" "$IN"
fi
;;
wav)
# In case of wav output we need nothing. Just keep the wavs.
;;
esac
$RUN_COMMAND_PIPES
done
# Only remove .wav if the encoding succeeded
if checkerrors "encodetrack-(.{3,6})-$1"; then :; else
run_command encodetrack-$1 true
if [ ! "$KEEPWAVS" = "y" ] ; then
if [ ! "$KEEPWAVS" = "move" ] ; then
rm -f "$IN"
fi
fi
fi
else
run_command "" echo "HEH! The file we were about to encode disappeared:"
run_command "" echo ">> $IN"
run_command encodetrack-$1 false
fi
}
# do_preprocess [tracknumber]
# variables used:
# TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
#do_preprocess ()
#{
# IN="$ABCDETEMPDIR/track$1.wav"
# # We need IN to proceed.
# if [ -s "$IN" ] ; then
# for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
# do
# #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
# run_command '' echo "Pre-processing track $1 of $TRACKS..."
# case "$POSTPROCESSFORMAT" in
# all|wav*)
# run_command preprocess-$OUTPUT-$1 nice $PRENICE $WAV_PRE $IF $OF ;;
# mp3)
# run_command preprocess-$OUTPUT-$1 nice $PRENICE $MP3_PRE $IF $OF ;;
# ogg)
# run_command preprocess-$OUTPUT-$1 nice $PRENICE $OGG_PRE $IF $OF ;;
# flac)
# run_command preprocess-$OUTPUT-$1 nice $PRENICE $FLAC_PRE $IF $OF ;;
# spx)
# run_command preprocess-$OUTPUT-$1 nice $PRENICE $SPX_PRE $IF $OF ;;
# esac
# done
# # Only remove .wav if the encoding succeeded
# if checkerrors "preprocess-(.{3,4})-$1"; then
# run_command preprocess-$1 false
# else
# run_command preprocess-$1 true
# fi
# else
# if [ "$(checkstatus encode-output)" = "loud" ]; then
# echo "HEH! The file we were about to pre-process disappeared:"
# echo ">> $IN"
# fi
# run_command preprocess-$1 false
# fi
#}
# do_postprocess [tracknumber]
# variables used:
# TRACKS, TRACKNAME, TRACKARTIST, DISTMP3, DISTMP3OPTS, {FOO}ENCODERSYNTAX, OUTPUTTYPE, ENCODEROPTS, DALBUM, DARTIST, ENCNICE, CDYEAR, CDGENRE, COMMENT
#do_postprocess ()
#{
# for POSTPROCESSFORMAT in $(echo $POSTPROCESSFORMATS | tr , \ )
# do
# IN="$ABCDETEMPDIR/track$1.$POSTPROCESSFORMAT"
# # We need IN to proceed.
# if [ -s "$IN" ] ; then
# #OUT="$ABCDETEMPDIR/track$1.$OUTPUT"
# run_command '' echo "Post-processing track $1 of $TRACKS..."
# case "$POSTPROCESSFORMAT" in
# mp3)
# run_command postprocess-$OUTPUT-$1 nice $POSTNICE $MP3_POST $IF $OF ;;
# ogg)
# run_command postprocess-$OUTPUT-$1 nice $POSTNICE $OGG_POST $IF $OF ;;
# flac)
# run_command postprocess-$OUTPUT-$1 nice $POSTNICE $FLAC_POST $IF $OF ;;
# spx)
# run_command postprocess-$OUTPUT-$1 nice $POSTNICE $SPX_POST $IF $OF ;;
# esac
# # Only remove .wav if the encoding succeeded
# if checkerrors "postprocess-(.{3,4})-$1"; then
# run_command postprocess-$1 false
# else
# run_command postprocess-$1 true
# fi
# else
# if [ "$(checkstatus encode-output)" = "loud" ]; then
# echo "HEH! The file we were about to post-process disappeared:"
# echo ">> $IN"
# fi
# run_command postprocess-$1 false
# fi
# done
#}
# do_single_gain
# variables used:
# FIXME #
do_single_gain ()
{
:
}
# do_batch_gain
# variables used:
# MP3GAIN, MP3GAINOPTS, VORBISGAIN, VORBISGAINOPTS, MPPGAIN, MPPGAINOPTS
# FIXME #
do_batch_gain ()
{
# The commands here don't go through run_command because they're never supposed to be silenced
echo "Batch analizing gain in tracks: $TRACKQUEUE"
(
cd "$ABCDETEMPDIR"
BLURB=
TRACKFILES=
for UTRACKNUM in $TRACKQUEUE
do
MP3FILES="$TRACKFILES track$UTRACKNUM.mp3"
done
# FIXME # Hard-coded batch option!
$NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
RETURN=$?
if [ "$RETURN" != "0" ]; then
echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
else
for UTRACKNUM in $TRACKQUEUE
do
echo normalizetrack-$UTRACKNUM >> status
done
fi
)
}
# do_batch_normalize
# variables used:
# NORMALIZER, NORMALIZEROPTS
do_batch_normalize ()
{
# The commands here don't go through run_command because they're never supposed to be silenced
echo "Batch normalizing tracks: $TRACKQUEUE"
(
cd "$ABCDETEMPDIR"
BLURB=
TRACKFILES=
for UTRACKNUM in $TRACKQUEUE
do
TRACKFILES="$TRACKFILES track$UTRACKNUM.wav"
done
# XXX: Hard-coded batch option!
$NORMALIZER -b $NORMALIZEROPTS $TRACKFILES
RETURN=$?
if [ "$RETURN" != "0" ]; then
echo "batch-normalize: $NORMALIZER returned code $RETURN" >> errors
else
for UTRACKNUM in $TRACKQUEUE
do
echo normalizetrack-$UTRACKNUM >> status
done
fi
)
}
# do_normalize [tracknumber]
# variables used:
# TRACKS, TRACKNAME, NORMALIZER, NORMALIZEROPTS
do_normalize ()
{
IN="$ABCDETEMPDIR/track$1.wav"
if [ -e "$IN" ] ; then
run_command '' echo "Normalizing track $1 of $TRACKS: $TRACKNAME..."
run_command normalizetrack-$1 $NORMALIZER $NORMALIZEROPTS "$IN"
else
if [ "$(checkstatus encode-output)" = "loud" ]; then
echo "HEH! The file we were about to normalize disappeared:"
echo ">> $IN"
fi
run_command normalizetrack-$1 false "File $IN was not found"
fi
}
# do_move [tracknumber]
# Deduces the outfile from environment variables
# Creates directory if necessary
# variables used:
# TRACKNUM, TRACKNAME, TRACKARTIST, DALBUM, OUTPUTFORMAT, CDGENRE, CDYEAR
do_move ()
{
for TMPOUTPUT in $(echo $OUTPUTTYPE | tr , \ )
do
# For now, set OUTPUT as TMPOUTPUT, and then change it once we have
# defined the OUTPUTFILE:
OUTPUT="$TMPOUTPUT"
# Create ALBUMFILE, ARTISTFILE, TRACKFILE
# Munge filenames as follows:
# ' ' -> '_'
# '/' -> '_'
# ''' -> ''
# '?' -> ''
# Eat control characters
ALBUMFILE="$(mungefilename "$DALBUM")"
ARTISTFILE="$(mungefilename "$TRACKARTIST")"
TRACKFILE="$(mungefilename "$TRACKNAME")"
GENRE="$(mungegenre "$GENRE")"
YEAR=${CDYEAR:-$CDYEAR}
# If we want to start the tracks with a given number, we need to modify
# the TRACKNUM value before evaluation
gettracknum
# Supported variables for OUTPUTFORMAT are GENRE, YEAR, ALBUMFILE,
# ARTISTFILE, TRACKFILE, and TRACKNUM.
if [ "$ONETRACK" = "y" ]; then
if [ "$VARIOUSARTISTS" = "y" ]; then
OUTPUTFILE="$(eval echo \""$VAONETRACKOUTPUTFORMAT"\")"
else
OUTPUTFILE="$(eval echo \""$ONETRACKOUTPUTFORMAT"\")"
fi
else
if [ "$VARIOUSARTISTS" = "y" ]; then
OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT"\")"
else
OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT"\")"
fi
fi
if checkerrors "tagtrack-$OUTPUT-$1"; then :; else
# Once we know the specific output was successful, we can change
# the OUTPUT to the value containing the container
case $TMPOUTPUT in
vorbis|ogg)
OUTPUT=$OGGOUTPUTCONTAINER
;;
flac)
OUTPUT=$FLACOUTPUTCONTAINER
;;
*)
OUTPUT=$TMPOUTPUT
;;
esac
# Check that the directory for OUTPUTFILE exists, if it doesn't, create it
OUTPUTFILEDIR="$(dirname "$OUTPUTDIR/$OUTPUTFILE")"
case $OUTPUT in
wav)
if [ "$DOCLEAN" != "y" ] && [ "$FORCE" != "y" ]; then
# FIXME # introduce warnings?
:
else
# mkdir -p shouldn't return an error if the directory already exists
mkdir -p "$OUTPUTFILEDIR"
run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
if checkstatus movetrack-output-$OUTPUT; then :; else
run_command movetrack-output-$OUTPUT true
fi
fi
;;
*)
# mkdir -p shouldn't return an error if the directory already exists
mkdir -p "$OUTPUTFILEDIR"
run_command movetrack-$1 mv "$ABCDETEMPDIR/track$1.$OUTPUT" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT"
if checkstatus movetrack-output-$OUTPUT; then :; else
run_command movetrack-output-$OUTPUT true
fi
;;
esac
# Lets move the toc file
if TOCFILE=$(checkstatus tocfile) >/dev/null ; then
if [ -r "$ABCDETEMPDIR/$TOCFILE" ]; then
if checkstatus movetoc-$OUTPUT; then :; else
# Silence the Copying output since it overlaps with encoding processes...
#run_command '' vecho "Copying toc file to its destination directory..."
if checkstatus onetrack >/dev/null ; then
case $OUTPUT in
wav)
if [ "$DOCLEAN" != "y" ] && [ "$FORCE" != "y" ]; then
# We dont have the dir, since it was not created before.
:
else
run_command movetoc-$OUTPUT cp "$ABCDETEMPDIR/$TOCFILE" "$OUTPUTDIR/$OUTPUTFILE.toc"
fi
;;
# NOTE: Creating a toc file with the 3-char-extension files is to comply with
# http://brianvictor.tripod.com/mp3cue.htm#details
[a-z0-9][a-z0-9][a-z0-9])
run_command movetoc-$OUTPUT cp "$ABCDETEMPDIR/$TOCFILE" "$OUTPUTDIR/$OUTPUTFILE.toc"
;;
*)
run_command movetoc-$OUTPUT cp "$ABCDETEMPDIR/$TOCFILE" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT.toc"
;;
esac
else
run_command movetoc-$OUTPUT cp "$ABCDETEMPDIR/$TOCFILE" "$OUTPUTFILEDIR/$TOCFILE"
fi
echo movetoc-$OUTPUT >> "$ABCDETEMPDIR/status"
fi
fi
fi
# Lets move the cue file
if CUEFILE=$(checkstatus cuefile) >/dev/null ; then
if [ -r "$ABCDETEMPDIR/$CUEFILE" ]; then
if checkstatus movecue-$OUTPUT; then :; else
# Silence the Copying output since it overlaps with encoding processes...
#run_command '' vecho "Copying cue file to its destination directory..."
if checkstatus onetrack >/dev/null ; then
case $OUTPUT in
wav)
if [ "$DOCLEAN" != "y" ] && [ "$FORCE" != "y" ]; then
# We dont have the dir, since it was not created before.
:
else
run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.cue"
fi
;;
# NOTE: Creating a cue file with the 3-char-extension files is to comply with
# http://brianvictor.tripod.com/mp3cue.htm#details
[a-z0-9][a-z0-9][a-z0-9])
run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.cue"
;;
*)
run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTDIR/$OUTPUTFILE.$OUTPUT.cue"
;;
esac
else
run_command movecue-$OUTPUT cp "$ABCDETEMPDIR/$CUEFILE" "$OUTPUTFILEDIR/$CUEFILE"
fi
echo movecue-$OUTPUT >> "$ABCDETEMPDIR/status"
fi
fi
fi
fi
done
}
# do_playlist
# Create the playlist if wanted
# Variables used:
# PLAYLISTFORMAT, PLAYLISTDATAPREFIX, VAPLAYLISTFORMAT, VAPLAYLISTDATAPREFIX,
# VARIOUSARTISTS, OUTPUTDIR
do_playlist ()
{
for TMPOUTPUT in $(echo $OUTPUTTYPE | tr , \ )
do
case $TMPOUTPUT in
vorbis|ogg)
OUTPUT=$OGGOUTPUTCONTAINER
;;
flac)
OUTPUT=$FLACOUTPUTCONTAINER
;;
*)
OUTPUT=$TMPOUTPUT
;;
esac
# Create a playlist file for the playlist data to go into.
# We used to wipe it out if it existed. Now we request permision if interactive.
for LASTTRACK in $TRACKQUEUE; do :; done
ALBUMFILE="$(mungefilename "$DALBUM")"
ARTISTFILE="$(mungefilename "$DARTIST")"
GENRE="$(mungegenre "$GENRE")"
YEAR=${CDYEAR:-$CDYEAR}
if [ "$VARIOUSARTISTS" = "y" ] ; then
PLAYLISTFILE="$(eval echo "$VAPLAYLISTFORMAT")"
else
PLAYLISTFILE="$(eval echo "$PLAYLISTFORMAT")"
fi
FINALPLAYLISTDIR="$(dirname "$OUTPUTDIR/$PLAYLISTFILE")"
mkdir -p "$FINALPLAYLISTDIR"
if [ -s "$OUTPUTDIR/$PLAYLISTFILE" ]; then
echo -n "Erase, Append to, or Keep the existing playlist file? [e/a/k] (e): " >&2
if [ "$INTERACTIVE" = "y" ]; then
while [ "$DONE" != "y" ]; do
read ERASEPLAYLIST
case $ERASEPLAYLIST in
e|E|a|A|k|K) DONE=y ;;
"") ERASEPLAYLIST=e ; DONE=y ;;
*) ;;
esac
done
else
echo e >&2
ERASEPLAYLIST=e
fi
# Once we erase the playlist, we use append to create the new one.
[ "$ERASEPLAYLIST" = "e" -o "$ERASEPLAYLIST" = "E" ] && rm -f "$OUTPUTDIR/$PLAYLISTFILE" && ERASEPLAYLIST=a
else
# The playlist does not exist, so we can safelly use append to create the new list
ERASEPLAYLIST=a
fi
if [ "$ERASEPLAYLIST" = "a" -o "$ERASEPLAYLIST" = "A" ]; then
touch "$OUTPUTDIR/$PLAYLISTFILE"
for UTRACKNUM in $TRACKQUEUE
do
# Shares some code with do_move since the filenames have to match
CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
getcddbinfo TRACKNAME
splitvarious
TRACKFILE="$(mungefilename "$TRACKNAME")"
ARTISTFILE="$(mungefilename "$TRACKARTIST")"
ALBUMFILE="$(mungefilename "$DALBUM")"
# If we want to start the tracks with a given number, we need to modify the
# TRACKNUM value before evaluation
gettracknum
if [ "$VARIOUSARTISTS" = "y" ]; then
OUTPUTFILE="$(eval echo \""$VAOUTPUTFORMAT\"")"
else
OUTPUTFILE="$(eval echo \""$OUTPUTFORMAT\"")"
fi
if [ "$VARIOUSARTISTS" = "y" ]; then
if [ "$VAPLAYLISTDATAPREFIX" ] ; then
echo ${VAPLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
else
relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
fi
else
if [ "$PLAYLISTDATAPREFIX" ]; then
echo ${PLAYLISTDATAPREFIX}$OUTPUTFILE.$OUTPUT >> "$OUTPUTDIR/$PLAYLISTFILE"
else
relpath "$PLAYLISTFILE", "$OUTPUTFILE.$OUTPUT" >> "$OUTPUTDIR/$PLAYLISTFILE"
fi
fi
done
fi
## this will convert the playlist to have CRLF line-endings, if specified
## (some hardware players insist on CRLF endings)
if [ "$DOSPLAYLIST" = "y" ]; then
awk '{substr("\r",""); printf "%s\r\n", $0}' "$OUTPUTDIR/$PLAYLISTFILE" > "$ABCDETEMPDIR/PLAYLISTFILE.tmp"
# mv -f "$ABCDETEMPDIR/PLAYLISTFILE.tmp" "$OUTPUTDIR/$PLAYLISTFILE"
cat "$ABCDETEMPDIR/PLAYLISTFILE.tmp" | sed 's/\//\\/' > "$OUTPUTDIR/$PLAYLISTFILE"
fi
echo "playlistcomplete" >> "$ABCDETEMPDIR/status"
done
}
# abcde.cue2discid
# This function reads a cuefile on stdin and writes an extended
# cddb query on stdout. Any PREGAP for track 1 is properly
# handled, although cue files embedded in FLAC files do not
# appear to properly store the PREGAP setting. :(
abcde.cue2discid () {
cddb_sum () {
val=$1
ret=0
while [ $val -gt 0 ] ; do
ret=$(( $ret + ( $val % 10) ))
val=$(( $val / 10 ))
done
echo $ret
}
msf2lba () {
OIFS="$IFS"
IFS=":"
set -- $1
IFS="$OIFS"
local first second third
first=$(expr ${1} + 0 )
second=$(expr ${2} + 0 )
third=$(expr ${3} + 0 )
echo $(( ((($first * 60) + $second) * 75) + $third ))
}
OFFSET=150
PREGAP=0
LEADOUT=0
LEADIN=88200
i=0
N=0
while read line ; do
set -- $line
case "$1" in
TRACK) i=$(( i + 1 ))
;;
INDEX) if [ "$2" -eq 1 ] ; then
LBA=$(msf2lba $3)
START=$(( $LBA + $PREGAP + $OFFSET ))
eval TRACK$i=$START
X=$(cddb_sum $(( $START / 75 )) )
N=$(( $N + $X ))
fi
;;
PREGAP) PREGAP=$(msf2lba $2)
;;
REM) case "$2" in
FLAC__lead-out)
LEADOUT=$(( $4 / 588 ))
;;
FLAC__lead-in)
LEADIN=$(( $3 / 588 ))
;;
esac
;;
esac
done
TRACKS=$i
LEADOUT=$(( $LEADOUT + $LEADIN ))
LENGTH=$(( $LEADOUT/75 - $TRACK1/75 ))
DISCID=$(( ( $N % 255 ) * 2**24 | $LENGTH * 2**8 | $TRACKS ))
printf "%08x %i" $DISCID $TRACKS
j=1
while [ $j -le $TRACKS ] ; do
eval echo -n "\" \$TRACK$j\""
j=$((j+1))
done
echo " $(( $LEADOUT / 75 ))"
}
# abcde.mkcue
# abcde.mkcue [--wholedisk]
# This creates a cuefile directly from the extended discid information
# The --wholedisk option controls whether we're ripping data from the
# start of track one or from the start of the disk (usually, but not
# always the same thing!)
#
# Track one leadin/pregap (if any) handeling:
# --wholedisk specified:
# TRACK 01 AUDIO
# INDEX 00 00:00:00
# INDEX 01 <pregap value>
# Remaining track index values unchanged from disc TOC
#
# --wholedisk not specified
# TRACK 01 AUDIO
# PREGAP <pregap value>
# INDEX 01 00:00:00
# Remaining track index values offset by <pregap value>
#
# Variables used:
# TRACKINFO
abcde.mkcue () {
echomsf () {
printf "$1%02i:%02i:%02i\n" $(($2/4500)) $((($2/75)%60)) $(($2%75))
}
local MODE DISCID TRACKS
local i OFFSET LBA
if [ "$1" = --wholedisc ] ; then
MODE=INDEX
else
MODE=PREGAP
fi
set -- $TRACKINFO
DISCID=$1
TRACKS=$2
shift 2
echo REM DISCID $DISCID
echo FILE \"dummy.wav\" WAVE
if [ $1 -ne 150 -a $MODE = PREGAP ] ; then
OFFSET=$1
else
OFFSET=150
fi
i=1
while [ $i -le "$TRACKS" ] ; do
LBA=$(( $1 - $OFFSET ))
printf " TRACK %02i AUDIO\n" $i
if [ $i -eq 1 -a $1 -ne 150 ] ; then
if [ $MODE = PREGAP ] ; then
echomsf " PREGAP " $(($OFFSET-150))
else
echo " INDEX 00 00:00:00"
fi
fi
echomsf " INDEX 01 " $LBA
i=$(($i+1))
shift
done
}
# do_discid
# This essentially the start of things
do_discid ()
{
# Query the CD to get the track info, unless the user specified -C
# or we are using some actions which do not need the CDDB data at all
#if [ ! X"$EXPACTIONS" = "X" ]; then
# :
#elif [ -z "$DISCID" ]; then
if [ -z "$DISCID" ]; then
vecho -n "Getting CD track info... "
# In OSX, unmount the disc before a query
if [ "$OSFLAVOUR" = "OSX" ]; then
disktool -u ${CDROM#/dev/}
fi
case "$CDROMREADERSYNTAX" in
flac)
if $METAFLAC $METAFLACOPTS --export-cuesheet-to=- "$CDROM" > /dev/null 2>&1 ; then
case "$CUE2DISCID" in
# FIXME # right now we have 2 cue2discid internal
# implementations: builtin and abcde.cue2discid. Test
# both of them and decide which one we want to use.
builtin)
#vecho "Using builtin cue2discid implementation..."
CUESHEET="$(metaflac $METAFLACOPTS --export-cuesheet-to=- "$CDROM")"
#TRACKS=$(echo $CUESHEET | egrep "TRACK \+[[:digit:]]\+ \+AUDIO" |wc -l)
#TRACKS=0
OFFSETTIMES=( $(echo "$CUESHEET" | sed -n -e's/\ *INDEX 01\ \+//p' ) )
TRACKS=${#OFFSETTIMES[@]}
unset OFFSETS
#echo "processing offsetimes ${OFFSETTIMES[@]}"
for OFFSETTIME in ${OFFSETTIMES[@]}; do
OFFSETS="$OFFSETS $(( 10#${OFFSETTIME:0:2} * 4500 + 10#${OFFSETTIME:3:2} * 75 + 10#${OFFSETTIME:6:2} ))"
#OFFSETS[${#OFFSETS[*]}]=$(( 10#${OFFSETTIME:0:2} * 4500 + 10#${OFFSETTIME:3:2} * 75 + 10#${OFFSETTIME:6:2} ))
done
LEADOUT=$(( $(echo "$CUESHEET" | grep lead-out | get_last) / 44100 * 75 ))
LEADIN=$(( $(echo "$CUESHEET" | grep lead-in | get_last) / 44100 * 75 ))
makeids
;;
*)
#vecho "Using external python cue2discid implementation..."
TRACKINFO=$($METAFLAC $METAFLACOPTS --export-cuesheet-to=- "$CDROM" | $CUE2DISCID)
;;
esac
else
log error "the input flac file does not contain a cuesheet."
exit 1
fi
;;
# cdparanoia|debug)
# CDPARANOIAOUTPUT="$( $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -Q --verbose 2>&1 )"
# RET=$?
# if [ ! "$RET" = "0" ];then
# log warning "something went wrong while querying the CD... Maybe a DATA CD?"
# fi
#
# TRACKS="$(echo "$CDPARANOIAOUTPUT" | egrep '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ')"
# CDPARANOIAAUDIOTRACKS="$TRACKS"
#
# LEADOUT="$(echo "$CDPARANOIAOUTPUT" | egrep -o '^TOTAL[[:space:]]+([[:digit:]]+)' | get_last)"
# OFFSETS="$(echo "$CDPARANOIAOUTPUT" | sed -n -e's/^ .* \([0-9]\+\) \[.*/\1/p')"
# makeids
# ;;
*)
case "$CDDBMETHOD" in
cddb) TRACKINFO=$($CDDISCID "$CDROM") ;;
# FIXME # musicbrainz needs a cleanup
musicbrainz) TRACKINFO=$($MUSICBRAINZ -c "$CDROM" ) ;;
esac
;;
esac
# Make sure there's a CD in there by checking cd-discid's return code
if [ ! "$?" = "0" ]; then
if [ "$CDROMREADERSYNTAX" = "flac" ] ; then
log error "cuesheet information from the flac file could not be read."
log error "Perhaps the flac file does not contain a cuesheet?."
exit 1
else
log error "CD could not be read. Perhaps there's no CD in the drive?"
exit 1
fi
fi
# In OSX, remount the disc again
if [ "$OSFLAVOUR" = "OSX" ]; then
disktool -m ${CDROM#/dev/}
fi
WEHAVEACD=y
DISCID=$(echo $TRACKINFO | cut -f1 -d' ')
else
TRACKINFO=$(cat "$WAVOUTPUTDIR/abcde.$DISCID/discid")
fi
# Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.
# This needs to be done now because a section of the resuming code will need
# it later.
# get the number of digits to pad TRACKNUM with - we'll use this later
# a CD can only hold 99 tracks, but since we support a feature for starting
# numbering the tracks from a given number, we might need to set it as a
# variable for the user to define... or obtain it somehow.
if [ "$PADTRACKS" = "y" ] ; then
TRACKNUMPADDING=2
fi
ABCDETEMPDIR="$WAVOUTPUTDIR/abcde.$(echo $TRACKINFO | cut -f1 -d' ')"
if [ -z "$TRACKQUEUE" ]; then
if [ ! "$STRIPDATATRACKS" = "n" ]; then
case "$CDROMREADERSYNTAX" in
cdparanoia|debug)
if [ "$WEHAVEACD" = "y" ]; then
vecho "Querying the CD for audio tracks..."
CDPARANOIAOUTPUT="$( $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -Q --verbose 2>&1 )"
RET=$?
if [ ! "$RET" = "0" ];then
log warning "something went wrong while querying the CD... Maybe a DATA CD?"
fi
TRACKS="$(echo "$CDPARANOIAOUTPUT" | egrep '^[[:space:]]+[[:digit:]]' | tail -n 1 | get_first | tr -d "." | tr '\n' ' ')"
CDPARANOIAAUDIOTRACKS="$TRACKS"
else
# Previous versions of abcde would store the tracks on a file, instead of the status record.
if [ -f "$ABCDETEMPDIR/cdparanoia-audio-tracks" ]; then
echo cdparanoia-audio-tracks=$( cat "$ABCDETEMPDIR/cdparanoia-audio-tracks" ) >> "$ABCDETEMPDIR/status"
rm -f "$ABCDETEMPDIR/cdparanoia-audio-tracks"
fi
if [ -f "$ABCDETEMPDIR/status" ] && TRACKS=$(checkstatus cdparanoia-audio-tracks); then :; else
TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
fi
fi
;;
*) TRACKS=$(echo $TRACKINFO | cut -f2 -d' ') ;;
esac
else
TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
fi
if echo "$TRACKS" | grep "[[:digit:]]" > /dev/null 2>&1 ;then :;else
log info "The disc does not contain any tracks. Giving up..."
exit 0
fi
echo -n "Grabbing entire CD - tracks: "
if [ ! "$PADTRACKS" = "y" ] ; then
TRACKNUMPADDING=$(echo -n $TRACKS | wc -c | tr -d ' ')
fi
TRACKS=$(printf "%0.${TRACKNUMPADDING}d" $TRACKS)
X=0
while [ "$X" -ne "$TRACKS" ]
do
X=$(printf "%0.${TRACKNUMPADDING}d" $(expr $X + 1))
TRACKQUEUE=$(echo $TRACKQUEUE $X)
done
echo $TRACKQUEUE
else
TRACKS=$(echo $TRACKINFO | cut -f2 -d' ')
# User-supplied track queue.
# Weed out non-numbers, whitespace, then sort and weed out duplicates
TRACKQUEUE=$(echo $TRACKQUEUE | sed 's-[^0-9 ]--g' | tr ' ' '\n' | grep -v ^$ | sort -n | uniq | tr '\n' ' ' | sed 's- $--g')
# Once cleaned, obtain the highest value in the trackqueue for number padding
for LASTTRACK in $TRACKQUEUE; do :; done
if [ ! "$PADTRACKS" = "y" ] ; then
TRACKNUMPADDING=$(echo -n $LASTTRACK | wc -c | tr -d ' ')
fi
# Now we normalize the trackqueue
for TRACK in $TRACKQUEUE ; do
TRACKNUM=$(printf %0.${TRACKNUMPADDING}d $(expr ${TRACK} + 0 ))
PADTRACKQUEUE=$(echo $PADTRACKQUEUE $TRACKNUM)
done
TRACKQUEUE=$PADTRACKQUEUE
echo Grabbing tracks: "$TRACKQUEUE"
fi
QUEUEDTRACKS=$(echo $TRACKQUEUE | wc -w | tr -d ' ')
# We have the discid, create a temp directory after it to store all the temp
# info
if [ -e "$ABCDETEMPDIR" ]; then
echo -n "abcde: attempting to resume from $ABCDETEMPDIR"
# It already exists, see if it's a directory
if [ ! -d "$ABCDETEMPDIR" ]; then
# This is a file/socket/fifo/device/etc, not a directory
# Complain and exit
echo >&2
echo "abcde: file $ABCDETEMPDIR already exists and does not belong to abcde." >&2
echo "Please investigate, remove it, and rerun abcde." >&2
exit 1
fi
echo -n .
# It's a directory, let's see if it's owned by us
if [ ! -O "$ABCDETEMPDIR" ]; then
# Nope, complain and exit
echo >&2
echo "abcde: directory $ABCDETEMPDIR already exists and is not owned by you." >&2
echo "Please investigate, remove it, and rerun abcde." >&2
exit 1
fi
echo .
# See if it's populated
if [ ! -f "$ABCDETEMPDIR/discid" ]; then
# Wipe and start fresh
echo "abcde: $ABCDETEMPDIR/discid not found. Abcde must remove and recreate" >&2
echo -n "this directory to continue. Continue? [y/n] (n)" >&2
if [ "$INTERACTIVE" = "y" ]; then
read ANSWER
else
echo y >&2
ANSWER=y
fi
if [ "$ANSWER" != "y" ]; then
exit 1
fi
rm -rf "$ABCDETEMPDIR" || exit 1
mkdir -p "$ABCDETEMPDIR"
if [ "$?" -gt "0" ]; then
# Directory already exists or could not be created
echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
exit 1
fi
else
# Everything is fine. Check for ^encodetracklocation-
# and encode-output entries in the status file and
# remove them. These are not relevant across sessions.
if [ -f "$ABCDETEMPDIR/status" ]; then
mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
| grep -v ^encode-output > "$ABCDETEMPDIR/status"
fi
# Remove old error messages
if [ -f "$ABCDETEMPDIR/errors" ]; then
rm -f "$ABCDETEMPDIR/errors"
fi
fi
else
# We are starting from scratch
mkdir -p "$ABCDETEMPDIR"
if [ "$?" -gt "0" ]; then
# Directory already exists or could not be created
echo "abcde: Temp directory $ABCDETEMPDIR could not be created." >&2
exit 1
fi
cat /dev/null > "$ABCDETEMPDIR/status"
# Store the abcde version in the status file.
echo "abcde-version=$VERSION" >> "$ABCDETEMPDIR/status"
fi
}
do_toc()
{
if [ X"$DOTOC" = "Xy" -a X"$WEHAVEACD" = "Xy" ]; then
if checkstatus tocfile > /dev/null 2>&1 ; then :; else
TOCFILE=toc-$(echo "$TRACKINFO" | cut -f1 -d' ').txt
if $TOCREADER $TOCREADEROPTS "$CDROM" "$ABCDETEMPDIR/$TOCFILE"; then
echo tocfile=$TOCFILE >> "$ABCDETEMPDIR/status"
fi
fi
fi
}
do_cue()
{
if [ X"$DOCUE" = "Xy" -a X"$WEHAVEACD" = "Xy" ]; then
if checkstatus cuefile > /dev/null 2>&1 ; then :; else
CUEFILE=cue-$(echo "$TRACKINFO" | cut -f1 -d' ').txt
vecho "Creating cue file..."
case $CDROMREADERSYNTAX in
flac)
if $METAFLAC --export-cuesheet-to=- "$CDROM" > "$ABCDETEMPDIR/$CUEFILE"; then
echo cuefile=$CUEFILE >> "$ABCDETEMPDIR/status"
else
log warning "the input flac file does not contain a cuesheet."
fi
;;
*)
case $CUEREADERSYNTAX in
default|mkcue)
if $CUEREADER $CUEREADEROPTS > "$ABCDETEMPDIR/$CUEFILE"; then
echo cuefile=$CUEFILE >> "$ABCDETEMPDIR/status"
else
log warning "reading the CUE sheet is still considered experimental"
log warning "and there was a problem with the CD reading. abcde will continue,"
log warning "but consider reporting the problem to the abcde author"
fi
;;
toc2cue)
if TOCFILE="$ABCDETEMPDIR"/$(checkstatus tocfile); then
if $CUEREADER $CUEREADEROPTS "$TOCFILE" "$ABCDETEMPDIR/$CUEFILE"; then
echo cuefile=$CUEFILE >> "$ABCDETEMPDIR/status"
else
log warning "toc to cuesheet conversion failed."
fi
else
log warning "cuesheet conversion failed: cannot read toc file."
fi
;;
esac
;;
esac
fi
fi
# If we got the CDPARANOIA status and it is not recorded, save it now
if [ -n "$CDPARANOIAAUDIOTRACKS" ]; then
if checkstatus cdparanoia-audio-tracks > /dev/null 2>&1; then :; else
echo cdparanoia-audio-tracks=$CDPARANOIAAUDIOTRACKS >> "$ABCDETEMPDIR/status"
fi
fi
# Create the discid file
echo "$TRACKINFO" > "$ABCDETEMPDIR/discid"
if checkstatus cddbmethod > /dev/null 2>&1 ; then :; else
echo "cddbmethod=$CDDBMETHOD" >> "$ABCDETEMPDIR/status"
fi
}
# do_cleancue
# Create a proper CUE file based on the CUE file we created before.
do_cleancue()
{
if CUEFILE_IN="$ABCDETEMPDIR"/$(checkstatus cuefile); then
CUEFILE_OUT=$CUEFILE_IN.out
### FIXME ### checkstatus cddb
if [ -e "$CDDBDATA" ]; then
vecho "Adding metadata to the cue file..."
# FIXME It doesn't preserve spaces! Why?
# FIXME parse $track into PERFORMER and TITLE - abcde already has code for this?
n=1
echo "PERFORMER \"$DARTIST\"" >> "$CUEFILE_OUT"
echo "TITLE \"$DALBUM\"" >> "$CUEFILE_OUT"
# Set IFS to <newline> to prevent read from swallowing spaces and tabs
OIFS="$IFS"
IFS='
'
cat "$CUEFILE_IN" | while read line
do
if echo "$line" | grep "INDEX 01" > /dev/null 2>&1 ; then
# FIXME # Possible patch: remove the line above, uncomment the 2 lines below.
# echo "$line" >> "$CUEFILE_OUT"
# if echo "$line" | grep "^[[:space:]]*TRACK" > /dev/null 2>&1 ; then
eval track="\$TRACK$n"
n=$(expr $n + 1)
echo " TITLE \"$track\"" >> "$CUEFILE_OUT"
fi
# FIXME # If the lines above are uncommented, remove the line below.
echo "$line" >> "$CUEFILE_OUT"
done
IFS="$OIFS"
mv "$CUEFILE_OUT" "$CUEFILE_IN"
echo "cleancuefile" >> "$ABCDETEMPDIR/status"
fi
fi
}
# do_cddbparse
# Parses a CDDB file and outputs the title and the track names.
# Variables: CDDBFILE
do_cddbparse ()
{
CDDBPARSEFILE="$1"
# List out disc title/author and contents
if [ "$ONETRACK" = "y" ]; then
vecho "ONETRACK mode selected: displaying only the title of the CD..."
fi
echo "---- $(grep DTITLE "${CDDBPARSEFILE}" | cut '-d=' -f2- | tr -d \\r\\n ) ----"
if [ X"$SHOWCDDBYEAR" = "Xy" ]; then
PARSEDYEAR=$(grep DYEAR "${CDDBPARSEFILE}" | cut '-d=' -f2-)
if [ ! X"$PARSEDYEAR" = "X" ]; then
echo "Year: $PARSEDYEAR"
fi
fi
if [ X"$SHOWCDDBGENRE" = "Xy" ]; then
PARSEDGENRE=$(grep DGENRE "${CDDBPARSEFILE}" | cut '-d=' -f2-)
if [ ! X"$PARSEDGENRE" = "X" ]; then
echo "Genre: $PARSEDGENRE"
fi
fi
if [ ! "$ONETRACK" = "y" ]; then
for TRACK in $(f_seq_row 1 $TRACKS)
do
echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "${CDDBPARSEFILE}" | cut -f2- -d= | tr -d \\r\\n)"
done
fi
}
# do_localcddb
# Check for a local CDDB file, and report success
do_localcddb ()
{
if checkstatus cddb-readcomplete && checkstatus cddb-choice >/dev/null; then :; else
CDDBLOCALSTATUS="notfound"
CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
USELOCALRESP="y"
if [ "$CDDBLOCALRECURSIVE" = "y" ]; then
CDDBLOCALRESULTS="$(find ${CDDBLOCALDIR} -name "${CDDBDISCID}" -type f 2> /dev/null)"
if [ ! "${CDDBLOCALRESULTS}" = "" ]; then
if (( $(echo "${CDDBLOCALRESULTS}" | wc -l) == 1 )); then
CDDBLOCALFILE="${CDDBLOCALRESULTS}"
CDDBLOCALMATCH=single
elif (( $(echo "${CDDBLOCALRESULTS}" | wc -l) > 1 )); then
CDDBLOCALMATCH=multiple
fi
else
CDDBLOCALMATCH=none
fi
elif [ "$CDDBLOCALMATCH" = "none" ] && [ -r "${CDDBLOCALDIR}/${CDDBDISCID}" ]; then
CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
CDDBLOCALMATCH=single
else
CDDBLOCALMATCH=none
fi
# If the user has selected to check a local CDDB repo, we proceed with it
case $CDDBLOCALMATCH in
multiple)
echo "Processing multiple matching CDDB entries..." > "$ABCDETEMPDIR/cddblocalchoices"
X=0
echo "$CDDBLOCALRESULTS" | while read RESULT ; do
X=$(expr $X + 1)
# List out disc title/author and contents
CDDBLOCALREAD="$ABCDETEMPDIR/cddblocalread.$X"
cat "$RESULT" > "${CDDBLOCALREAD}"
{
echo -n "#$X: "
do_cddbparse "${CDDBLOCALREAD}"
echo ""
##FIXME## QUICK HACK !!!!
if [ ! "$INTERACTIVE" = "y" ]; then break ; fi
} >> "$ABCDETEMPDIR/cddblocalchoices"
done
if [ $(cat "$ABCDETEMPDIR/cddblocalchoices" | wc -l) -ge 24 ] && [ "$INTERACTIVE" = "y" ]; then
page "$ABCDETEMPDIR/cddblocalchoices"
else
# It's all going to fit in one page, cat it
cat "$ABCDETEMPDIR/cddblocalchoices" >&2
fi
CDDBLOCALCHOICES=$( echo "$CDDBLOCALRESULTS" | wc -l )
# Setting the choice to an impossible integer to avoid errors in the numeric comparisons
CDDBLOCALCHOICENUM=-1
if [ "$INTERACTIVE" = "y" ]; then
while [ $CDDBLOCALCHOICENUM -lt 0 ] || [ $CDDBLOCALCHOICENUM -gt $CDDBLOCALCHOICES ]; do
echo -n "Locally cached CDDB entries found. Which one would you like to use (0 for none)? [0-$CDDBLOCALCHOICES]: " >&2
read CDDBLOCALCHOICE
[ x"$CDDBLOCALCHOICE" = "x" ] && CDDBLOCALCHOICE="1"
# FIXME # Introduce diff's
if echo $CDDBLOCALCHOICE | egrep "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
diffentries cddblocalread "$CDDBLOCALCHOICES" "$CDDBLOCALCHOICE"
elif echo $CDDBLOCALCHOICE | egrep "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
# Make sure we get a valid choice
CDDBLOCALCHOICENUM=$(echo $CDDBLOCALCHOICE | xargs printf %d 2>/dev/null)
if [ $CDDBLOCALCHOICENUM -lt 0 ] || [ $CDDBLOCALCHOICENUM -gt $CDDBLOCALCHOICES ]; then
echo "Invalid selection. Please choose a number between 0 and $CDDBLOCALCHOICES." >&2
fi
fi
done
else
### FIXME ###
#echo "Selected ..."
CDDBLOCALRESP=y
CDDBLOCALCHOICENUM=1
fi
if [ ! "$CDDBLOCALCHOICENUM" = "0" ]; then
#echo "Using local copy of CDDB data"
echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1"
cat "$ABCDETEMPDIR/cddblocalread.$CDDBLOCALCHOICENUM" >> "$ABCDETEMPDIR/cddbread.1"
echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
do_cddbparse "$ABCDETEMPDIR/cddbread.1" > "$ABCDETEMPDIR/cddbchoices"
echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
CDDBLOCALSTATUS="found"
else
#echo "Not using local copy of CDDB data"
CDDBLOCALSTATUS="notfound"
fi
;;
single)
# List out disc title/author and contents
do_cddbparse "${CDDBLOCALFILE}"
#if [ "$CDROMREADERSYNTAX" = "flac" ] ; then
# echo -n "Embedded cuesheet entry found, use it? [y/n] (y): " >&2
#else
echo -n "Locally cached CDDB entry found, use it? [y/n] (y): " >&2
#fi
if [ "$INTERACTIVE" = "y" ]; then
read USELOCALRESP
while [ "$USELOCALRESP" != "y" ] && [ "$USELOCALRESP" != "n" ] && [ "$USELOCALRESP" != "" ] ; do
echo -n 'Invalid selection. Please answer "y" or "n": ' >&2
read USELOCALRESP
done
[ x"$USELOCALRESP" = "x" ] && USELOCALRESP="y"
else
echo "y" >&2
fi
if [ "$USELOCALRESP" = "y" ]; then
#echo "Using local copy of CDDB data"
echo "# DO NOT ERASE THIS LINE! Added by abcde to imitate cddb output" > "$ABCDETEMPDIR/cddbread.1"
cat "${CDDBLOCALFILE}" >> "$ABCDETEMPDIR/cddbread.1"
echo 999 > "$ABCDETEMPDIR/cddbquery" # Assuming 999 isn't used by CDDB
echo cddb-readcomplete >> "$ABCDETEMPDIR/status"
do_cddbparse "${CDDBLOCALFILE}" > "$ABCDETEMPDIR/cddbchoices"
echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
CDDBLOCALSTATUS="single"
else
#echo "Not using local copy of CDDB data"
CDDBLOCALSTATUS="notfound"
fi
;;
none)
CDDBLOCALSTATUS="notfound"
;;
esac
fi
}
do_musicbrainzstat ()
{
:
}
do_musicbrainz ()
{
# Use MBE_TOCGetCDIndexId on a perl query
:
}
# do_cddbstat
do_cddbstat ()
{
# Perform CDDB protocol version check if it hasn't already been done
if checkstatus cddb-statcomplete; then :; else
if [ "$CDDBAVAIL" = "n" ]; then
ERRORCODE=no_query
echo 503 > "$ABCDETEMPDIR/cddbstat"
else
rc=1
CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
while test $rc -eq 1 -a $CDDBPROTO -ge 3; do
vecho "Checking CDDB server status..."
$CDDBTOOL stat $CDDBURL $CDDBUSER $CDDBHOST $CDDBPROTO > "$ABCDETEMPDIR/cddbstat"
RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
case "$RESPONSECODE" in
210) # 210 OK, status information follows (until terminating `.')
rc=0
;;
501) # 501 Illegal CDDB protocol level: <n>.
CDDBPROTO=`expr $CDDBPROTO - 1`
;;
*) # Try a cddb query, since freedb2.org doesn't support the stat or ver commands
# FreeDB TESTCD disc-id is used for query
$CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST 03015501 1 296 344 > "$ABCDETEMPDIR/cddbstat"
RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbstat" | cut -f1 -d' ')
case "$RESPONSECODE" in
2??) # Server responded, everything seems OK
rc=0
;;
esac
;;
esac
done
if test $rc -eq 1; then
CDDBAVAIL="n"
fi
fi
echo cddb-statcomplete >> "$ABCDETEMPDIR/status"
fi
}
# do_cddbquery
do_cddbquery ()
{
CDDBDISCID=$(echo $TRACKINFO | cut -d' ' -f1)
CDDBLOCALFILE="${CDDBLOCALDIR}/${CDDBDISCID}"
# Perform CDDB query if it hasn't already been done
if checkstatus cddb-querycomplete; then :; else
if [ "$CDDBAVAIL" = "n" ]; then
ERRORCODE=no_query
echo 503 > "$ABCDETEMPDIR/cddbquery"
# The default CDDBLOCALSTATUS is "notfound"
# This part will be triggered if the user CDDB repo does not
# contain the entry, or if we are not trying to use the repo.
else
vecho "Querying the CDDB server..."
CDDBUSER=$(echo $HELLOINFO | cut -f1 -d'@')
CDDBHOST=$(echo $HELLOINFO | cut -f2- -d'@')
$CDDBTOOL query $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $TRACKINFO > "$ABCDETEMPDIR/cddbquery"
ERRORCODE=$?
case $ERRORCODE in
0) # success
;;
12|13|14)
# no match found in database,
# wget/fetch error, or user requested not to use CDDB
# Make up an error code (503) that abcde
# will recognize in do_cddbread
# and compensate by making a template
echo 503 > "$ABCDETEMPDIR/cddbquery"
;;
*) # strange and unknown error
echo ERRORCODE=$ERRORCODE
echo "abcde: $CDDBTOOL returned unknown error code"
;;
esac
fi
echo cddb-querycomplete >> "$ABCDETEMPDIR/status"
fi
}
# do_cddbread
do_cddbread ()
{
# If it's not to be used, generate a template.
# Then, display it (or them) and let the user choose/edit it
if checkstatus cddb-readcomplete; then :; else
vecho "Obtaining CDDB results..."
# If CDDB is to be used, interpret the query results and read all
# the available entries.
rm -f "$ABCDETEMPDIR/cddbchoices"
CDDBCHOICES=1 # Overridden by multiple matches
RESPONSECODE=$(head -n 1 "$ABCDETEMPDIR/cddbquery" | cut -f1 -d' ')
case "$RESPONSECODE" in
200)
# One exact match, retrieve it
# 200 [section] [discid] [artist] / [title]
if checkstatus cddb-read-1-complete; then :; else
echo -n "Retrieving 1 CDDB match..." >> "$ABCDETEMPDIR/cddbchoices"
$CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(cut -f2,3 -d' ' "$ABCDETEMPDIR/cddbquery") > "$ABCDETEMPDIR/cddbread.1"
echo "done." >> "$ABCDETEMPDIR/cddbchoices"
echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
fi
# List out disc title/author and contents
echo ---- "$(cut '-d ' -f4- "$ABCDETEMPDIR/cddbquery")" ---- >> "$ABCDETEMPDIR/cddbchoices"
for TRACK in $(f_seq_row 1 $TRACKS)
do
echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
done
echo >> "$ABCDETEMPDIR/cddbchoices"
;;
202|403|409|503)
# No match
case "$RESPONSECODE" in
202) echo "No CDDB match." >> "$ABCDETEMPDIR/cddbchoices" ;;
403|409) echo "CDDB entry is corrupt, or the handshake failed." >> "$ABCDETEMPDIR/cddbchoices" ;;
503) echo "CDDB unavailable." >> "$ABCDETEMPDIR/cddbchoices" ;;
esac
$CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
# List out disc title/author and contents of template
echo ---- Unknown Artist / Unknown Album ---- >> "$ABCDETEMPDIR/cddbchoices"
UNKNOWNDISK=y
for TRACK in $(f_seq_row 1 $TRACKS)
do
echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.0" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
done
echo >> "$ABCDETEMPDIR/cddbchoices"
echo cddb-read-0-complete >> "$ABCDETEMPDIR/status"
echo cddb-choice=0 >> "$ABCDETEMPDIR/status"
;;
210|211)
# Multiple exact, (possibly multiple) inexact matches
IN=
if [ "$RESPONSECODE" = "211" ]; then IN=in; fi
if [ "$(wc -l < "$ABCDETEMPDIR/cddbquery" | tr -d ' ')" -eq 3 ]; then
echo "One ${IN}exact match:" >> "$ABCDETEMPDIR/cddbchoices"
tail -n +2 "$ABCDETEMPDIR/cddbquery" | head -n 1 >> "$ABCDETEMPDIR/cddbchoices"
echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
else
echo "Multiple ${IN}exact matches:" >> "$ABCDETEMPDIR/cddbchoices"
fi
vecho -n "Retrieving multiple matches... "
grep -v ^[.]$ "$ABCDETEMPDIR/cddbquery" | ( X=0
read DISCINFO # eat top line
while read DISCINFO
do
X=$(expr $X + 1)
if checkstatus cddb-read-$X-complete; then :; else
$CDDBTOOL read $CDDBURL $CDDBPROTO $CDDBUSER $CDDBHOST $(echo $DISCINFO | cut -f1,2 -d' ') > "$ABCDETEMPDIR/cddbread.$X"
echo cddb-read-$X-complete >> "$ABCDETEMPDIR/status"
fi
# List out disc title/author and contents
echo \#$X: ---- "$DISCINFO" ---- >> "$ABCDETEMPDIR/cddbchoices"
for TRACK in $(f_seq_row 1 $TRACKS)
do
echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.$X" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
done
echo >> "$ABCDETEMPDIR/cddbchoices"
done )
vecho "done."
CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
;;
999)
# Using local copy.
for TRACK in $(f_seq_row 1 $TRACKS)
do
echo $TRACK: "$(grep ^TTITLE$(expr $TRACK - 1)= "$ABCDETEMPDIR/cddbread.1" | cut -f2- -d= | tr -d \\r\\n)" >> "$ABCDETEMPDIR/cddbchoices"
done
echo >> "$ABCDETEMPDIR/cddbchoices"
echo cddb-read-1-complete >> "$ABCDETEMPDIR/status"
echo cddb-choice=1 >> "$ABCDETEMPDIR/status"
;;
esac
echo "cddb-readcomplete" >> "$ABCDETEMPDIR/status"
fi
}
# do_cddbedit
do_cddbedit ()
{
if checkstatus cddb-edit >/dev/null; then
CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
VARIOUSARTISTS="$(checkstatus variousartists)"
VARIOUSARTISTSTYLE="$(checkstatus variousartiststyle)"
return 0
fi
if [ "$INTERACTIVE" = "y" ]; then
# We should show the CDDB results both when we are not using the local CDDB repo
# or when we are using it but we could not find a proper match
if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
# Display the $ABCDETEMPDIR/cddbchoices file created above
# Pick a pager so that if the tracks overflow the screen the user can still view everything
if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
CHOICE=$(checkstatus cddb-choice)
if [ -n "$CHOICE" ] ; then
case $CDDBCHOICES in
-1) if head -1 "$ABCDETEMPDIR/cddbquery" | grep "^$" > /dev/null 2>&1 ; then
log error "CDDB query failed!"
exit 1
else
cat "$ABCDETEMPDIR/cddbchoices"
fi
;;
1) cat "$ABCDETEMPDIR/cddbchoices" ;;
*)
echo "Selected: #$CHOICE"
do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
;;
esac
else
# The user has a choice to make, display the info in a pager if necessary
if [ $(cat "$ABCDETEMPDIR/cddbchoices" | wc -l) -ge 24 ]; then
page "$ABCDETEMPDIR/cddbchoices"
else
# It's all going to fit in one page, cat it
cat "$ABCDETEMPDIR/cddbchoices" >&2
fi
CDDBCHOICENUM=""
# Setting the choice to an impossible integer to avoid errors in the numeric comparisons
CDCHOICENUM=-1
# I'll take CDDB read #3 for $400, Alex
while [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; do
echo -n "Which entry would you like abcde to use (0 for none)? [0-$CDDBCHOICES]: " >&2
read CDDBCHOICE
[ X"$CDDBCHOICE" = "X" ] && CDDBCHOICE=1
if echo $CDDBCHOICE | egrep "[[:space:]]*[[:digit:]]+,[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
if [ ! X"$DIFF" = "X" ]; then
PARSECHOICE1=$(echo $CDDBCHOICE | cut -d"," -f1 | xargs printf %d 2>/dev/null)
PARSECHOICE2=$(echo $CDDBCHOICE | cut -d"," -f2 | xargs printf %d 2>/dev/null)
if [ $PARSECHOICE1 -lt 1 ] || [ $PARSECHOICE1 -gt $CDDBCHOICES ] || \
[ $PARSECHOICE2 -lt 1 ] || [ $PARSECHOICE2 -gt $CDDBCHOICES ] || \
[ $PARSECHOICE1 -eq $PARSECHOICE2 ]; then
echo "Invalid diff range. Please select two coma-separated numbers between 1 and $CDDBCHOICES" >&2
else
# We parse the 2 choices to diff, store them in temporary files and diff them.
for PARSECHOICE in $(echo $CDDBCHOICE | tr , \ ); do
do_cddbparse "$ABCDETEMPDIR/cddbread.$PARSECHOICE" > "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE"
done
echo "Showing diff between choices $PARSECHOICE1 and $PARSECHOICE2..." > "$ABCDETEMPDIR/cddbread.diff"
$DIFF $DIFFOPTS "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE1" "$ABCDETEMPDIR/cddbread.parsechoice.$PARSECHOICE2" >> "$ABCDETEMPDIR/cddbread.diff"
if [ $(cat "$ABCDETEMPDIR/cddbread.diff" | wc -l) -ge 24 ]; then
page "$ABCDETEMPDIR/cddbread.diff"
else
cat "$ABCDETEMPDIR/cddbread.diff" >&2
fi
fi
else
echo "The diff program was not found in your path. Please choose a number between 0 and $CDDBCHOICES." >&2
fi
elif echo $CDDBCHOICE | egrep "[[:space:]]*[[:digit:]]+[[:space:]]*" > /dev/null 2>&1 ; then
# Make sure we get a valid choice
CDCHOICENUM=$(echo $CDDBCHOICE | xargs printf %d 2>/dev/null)
if [ $CDCHOICENUM -lt 0 ] || [ $CDCHOICENUM -gt $CDDBCHOICES ]; then
echo "Invalid selection. Please choose a number between 0 and $CDDBCHOICES." >&2
fi
fi
done
if [ "$CDCHOICENUM" = "0" ]; then
vecho "Creating empty CDDB template..."
UNKNOWNDISK=y
$CDDBTOOL template $(cat "$ABCDETEMPDIR/discid") > "$ABCDETEMPDIR/cddbread.0"
else
echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
do_cddbparse "$ABCDETEMPDIR/cddbread.$CDCHOICENUM"
fi
echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
fi
fi
else
# We need some code to show the selected option when local repository is selected and we have found a match
vecho "Using cached CDDB match..." >&2
# Display the $ABCDETEMPDIR/cddbchoices file created above
# Pick a pager so that if the tracks overflow the screen the user can still view everything
if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
CDDBCHOICES=$(expr $(cat "$ABCDETEMPDIR/cddbquery" | wc -l) - 2)
CHOICE=$(checkstatus cddb-choice)
if [ "$USELOCALRESP" = "y" ]; then :; else
if [ -n "$CHOICE" ] ; then
case $CDDBCHOICES in
0)
UNKNOWNDISK=y
echo "Selected template."
;;
1) cat "$ABCDETEMPDIR/cddbchoices" ;;
*)
echo "Selected: #$CHOICE"
do_cddbparse "$ABCDETEMPDIR/cddbread.$CHOICE"
;;
esac
fi
fi
fi
fi
else
# We're noninteractive - pick the first choice.
# But in case we run a previous instance and selected a choice, use it.
if [ -r "$ABCDETEMPDIR/cddbchoices" ]; then
# Show the choice if we are not using the locally stored one
# or when the local search failed to find a match.
PREVIOUSCHOICE=$(checkstatus cddb-choice)
if [ "$CDDBUSELOCAL" = "y" ] && [ "$CDDBLOCALSTATUS" = "notfound" ] || [ ! "$CDDBUSELOCAL" = "y" ]; then
#if [ "$PREVIOUSCHOICE" ]; then
cat "$ABCDETEMPDIR/cddbchoices"
#fi
fi
if [ ! -z "$PREVIOUSCHOICE" ] ; then
CDCHOICENUM=$PREVIOUSCHOICE
else
CDCHOICENUM=1
echo "cddb-choice=$CDCHOICENUM" >> "$ABCDETEMPDIR/status"
fi
echo "Selected: #$CDCHOICENUM ($(grep ^DTITLE= "$ABCDETEMPDIR/cddbread.$CDCHOICENUM" | cut -f2- -d= | tr -d \\r\\n))" >&2
fi
fi
# sanity check
if checkstatus cddb-choice >/dev/null; then :; else
echo "abcde: internal error: cddb-choice not recorded." >&2
exit 1
fi
CDDBDATA="$ABCDETEMPDIR/cddbread.$(checkstatus cddb-choice)"
echo -n "Edit selected CDDB data? [y/n] (" >&2
if [ "$INTERACTIVE" = "y" ]; then
if [ "$UNKNOWNDISK" = "y" ]; then
echo -n "y): " >&2
read EDITCDDB
[ "$EDITCDDB" != "n" ] && EDITCDDB=y
else
echo -n "n): " >&2
read EDITCDDB
fi
else
echo "n): n" >&2
EDITCDDB=n
fi
if [ "$EDITCDDB" = "y" ]; then
CDDBDATAMD5SUM=$($MD5SUM "$CDDBDATA" | cut -d " " -f 1);
# Use the debian sensible-editor wrapper to pick the editor that the
# user has requested via their $EDITOR environment variable
if [ -x "/usr/bin/sensible-editor" ]; then
/usr/bin/sensible-editor "$CDDBDATA"
elif [ -n "$EDITOR" ]; then
if [ -x $(which "${EDITOR%%\ *}") ]; then
# That failed, try to load the preferred editor, starting
# with their EDITOR variable
eval $(echo "$EDITOR") \"$CDDBDATA\"
fi
# If that fails, check for a vi
elif which vi >/dev/null 2>&1; then
vi "$CDDBDATA"
elif [ -x /usr/bin/vim ]; then
/usr/bin/vim "$CDDBDATA"
elif [ -x /usr/bin/vi ]; then
/usr/bin/vi "$CDDBDATA"
elif [ -x /bin/vi ]; then
/bin/vi "$CDDBDATA"
# nano should be on all (modern, i.e., sarge) debian systems
elif which nano >/dev/null 2>&1 ; then
nano "$CDDBDATA"
elif [ -x /usr/bin/nano ]; then
/usr/bin/nano "$CDDBDATA"
# mg should be on all OpenBSD systems
elif which mg >/dev/null 2>&1 ; then
mg "$CDDBDATA"
elif [ -x /usr/bin/mg ]; then
/usr/bin/mg "$CDDBDATA"
# bomb out
else
log warning "no editor available. Check your EDITOR environment variable."
fi
# delete editor backup file if it exists
if [ -w "$CDDBDATA~" ]; then
rm -f "$CDDBDATA~"
fi
fi
# Some heuristics first. Look at Disc Title, and if it starts with
# "Various", then we'll assume Various Artists
if [ "$(grep ^DTITLE= "$CDDBDATA" | cut -f2- -d= | egrep -ci '^(various|soundtrack|varios|sonora|ost)')" != "0" -o \
"$VARIOUSARTISTS" = "y" ]; then
echo "Looks like a Multi-Artist CD" >&2
VARIOUSARTISTS=y
else
echo -n "Is the CD multi-artist? [y/n] (n): " >&2
if [ "$INTERACTIVE" = "y" ]; then
read VARIOUSARTISTS
else
echo n >&2
VARIOUSARTISTS=n
fi
fi
if [ "$VARIOUSARTISTS" = "y" ] && [ ! "$ONETRACK" = "y" ]; then
# Set a default
DEFAULTSTYLE=1
# Need NUMTRACKS before cddb-tool will return it:
NUMTRACKS=$(egrep '^TTITLE[0-9]+=' "$CDDBDATA" | wc -l)
if [ "$(grep -c "^TTITLE.*\/" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
# More than 1/2 tracks contain a "/", so guess forward
DEFAULTSTYLE=1
elif [ "$(grep -c "^TTITLE.*\-" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
# More than 1/2 contain a "-", so guess forward-dash
DEFAULTSTYLE=2
elif [ "$(grep -c "^TTITLE.*(.*)" "$CDDBDATA")" -gt "$(expr $NUMTRACKS / 2 )" ]; then
# More than 1/2 contain something in parens, so guess trailing-paren
DEFAULTSTYLE=6
fi
echo "1) Artist / Title" >&2
echo "2) Artist - Title" >&2
echo "3) Title / Artist" >&2
echo "4) Title - Artist" >&2
echo "5) Artist: Title" >&2
echo "6) Title (Artist)" >&2
echo "7) This is a single-artist CD" >&2
echo -n "Which style of multiple artist entries is it? [1-7] ($DEFAULTSTYLE): " >&2
if [ "$INTERACTIVE" = "y" ]; then
read VARIOUSARTISTSTYLE
else
echo $DEFAULTSTYLE >&2
VARIOUSARTISTSTYLE=$DEFAULTSTYLE
fi
VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
# If they press Enter, then the default style (0) was chosen
while [ $VARIOUSARTISTSTYLE -lt 0 ] || [ $VARIOUSARTISTSTYLE -gt 7 ]; do
echo "Invalid selection. Please choose a number between 1 and 7."
echo -n "Selection [1-7]: "
read VARIOUSARTISTSTYLE
VARIOUSARTISTSTYLE=$(echo 0$VARIOUSARTISTSTYLE | xargs printf %d)
done
if [ "$VARIOUSARTISTSTYLE" = "0" ]; then
VARIOUSARTISTSTYLE=$DEFAULTSTYLE
fi
vecho "Selected: $VARIOUSARTISTSTYLE"
case "$VARIOUSARTISTSTYLE" in
1) # Artist / Title
VARIOUSARTISTSTYLE=forward
;;
2) # Artist - Title
VARIOUSARTISTSTYLE=forward-dash
;;
3) # Title / Artist
VARIOUSARTISTSTYLE=reverse
;;
4) # Title - Artist
VARIOUSARTISTSTYLE=reverse-dash
;;
5) # Artist: Title
VARIOUSARTISTSTYLE=colon
;;
6) # Title (Artist)
VARIOUSARTISTSTYLE=trailing-paren
;;
7) # Single Artist
VARIOUSARTISTS=n
;;
esac
fi
echo "variousartists=$VARIOUSARTISTS" >> "$ABCDETEMPDIR/status"
echo "variousartiststyle=$VARIOUSARTISTSTYLE" >> "$ABCDETEMPDIR/status"
if [ "$EDITCDDB" = "y" ] && [ "$UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE" = "y" ]; then
if [ "$CDDBDATAMD5SUM" != "" ] && [ "$CDDBDATAMD5SUM" != "$($MD5SUM "$CDDBDATA" | cut -d " " -f 1)" ]; then
# This works but does not have the necessary error checking
# yet. If you are familiar with the CDDB spec
# (see http://www.freedb.org/src/latest/DBFORMAT)
# and can create an error-free entry on your own, then put
# UNINTENTIONALLY_ANGER_THE_FREEDB_PEOPLE=y in your
# abcde.conf to enable it. Put CDDBSUBMIT=email at address in
# your abcde.conf to change the email address submissions are
# sent to.
# submit the modified file, if they want
if [ "$NOSUBMIT" != "y" ]; then
echo -n "Do you want to submit this entry to $CDDBSUBMIT? [y/n] (n): "
read YESNO
while [ "$YESNO" != "y" ] && [ "$YESNO" != "n" ] && [ "$YESNO" != "Y" ] && \
[ "$YESNO" != "N" ] && [ "$YESNO" != "" ]
do
echo -n 'Invalid selection. Please answer "y" or "n": '
read YESNO
done
if [ "$YESNO" = "y" ] || [ "$YESNO" = "Y" ]; then
echo -n "Sending..."
$CDDBTOOL send "$CDDBDATA" $CDDBSUBMIT
echo "done."
fi
fi
fi
fi
### FIXME ###
# User CDDBLOCALPOLICY to find out if we store the file or not...
# Cache edited CDDB entry in the user's cddb dir
if [ "$CDDBCOPYLOCAL" = "y" ]; then
# Make sure the cache directory exists
mkdir -p $CDDBLOCALDIR
cat "$CDDBDATA" | tail -n $(expr $(cat "$CDDBDATA" | wc -l ) - 1 ) > ${CDDBLOCALDIR}/$(echo "$TRACKINFO" | cut -d' ' -f1)
fi
echo "cddb-edit" >> "$ABCDETEMPDIR/status"
}
# do_cdread [tracknumber]
# do_cdread onetrack [firsttrack] [lasttrack]
#
do_cdread ()
{
# The commands here don't go through run_command because they're never supposed to be silenced
# return codes need to be doublechecked anyway, however
if [ "$1" = "onetrack" ]; then
# FIXME # Add the possibility of grabbing ranges of tracks in onetrack
# FIXME # Until then, we grab the whole CD in one track, no matter what
# the user said
# We need the first and last track for cdda2wav
FIRSTTRACK=$2
LASTTRACK=$(expr $3 + 0)
UTRACKNUM=$FIRSTTRACK
case "$CDROMREADERSYNTAX" in
flac) READTRACKNUMS="$FIRSTTRACK.1-$(($LASTTRACK + 1)).0" ;;
cdparanoia)
#XX FIXME XX
# Add a variable to check if tracks are provided in command line and if not, use "0-" to rip the tracks
#READTRACKNUMS="$FIRSTTRACK-$LASTTRACK" ;;
READTRACKNUMS="[00:00:00.00]-$LASTRACK" ;;
cdda2wav) READTRACKNUMS="$FIRSTTRACK+$LASTTRACK" ;;
*) echo "abcde error: $CDROMREADERSYNTAX does not support ONETRACK mode"
exit 1 ;;
esac
else
UTRACKNUM=$1
fi
CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
if [ "$USEPIPES" = "y" ]; then
TEMPARG="PIPERIPPER_$CDROMREADERSYNTAX"
FILEARG="$( eval echo "\$$TEMPARG" )"
REDIR=""
PIPE_MESSAGE="and encoding "
else
WAVDATA="$ABCDETEMPDIR/track$UTRACKNUM.wav"
case "$CDROMREADERSYNTAX" in
## FIXME ## Find the cases for dagrab and flac, to avoid exceptions
flac)
FILEARG="--output-name=$WAVDATA"
;;
dagrab)
FILEARG="-f $WAVDATA"
;;
*)
FILEARG="$WAVDATA"
;;
esac
REDIR=">&2"
fi
if [ "$1" = "onetrack" ]; then
echo "Grabbing ${PIPE_MESSAGE}tracks $UTRACKNUM - $LASTTRACK as one track ..." >&2
else
if [ -r "$CDDBDATA" ]; then
getcddbinfo TRACKNAME
echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM: $TRACKNAME..." >&2
else
echo "Grabbing ${PIPE_MESSAGE}track $UTRACKNUM..." >&2
fi
fi
case "$CDROMREADERSYNTAX" in
### FIXME ### use an exception for flac, since it uses -o
### FIXME ### Shall we just use -o $FILEARG ??
flac)
# Avoid problems wit math expressions by unpadding the given UTRACKNUM
STRIPTRACKNUM=$(expr $UTRACKNUM + 0)
nice $READNICE $FLAC -d -f --cue=${READTRACKNUMS:-$STRIPTRACKNUM.1-$(($STRIPTRACKNUM + 1)).0} "$FILEARG" "$CDROM" ;;
cdparanoia)
nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR ;;
cdda2wav)
if [ "$OSFLAVOUR" = "OSX" ] ; then
# Hei, we have to unmount the device before running anything like cdda2wav in OSX
disktool -u ${CDROM#/dev/} 0
# Also, in OSX the cdrom device for cdda2wav changes...
CDDA2WAVCDROM="IODVDServices"
elif [ "$OSFLAVOUR" = "FBSD" ] ; then
CDDA2WAVCDROM="$CDROMID"
else
if [ "$CDROMID" = "" ]; then
CDDA2WAVCDROM="$CDROM"
else
CDDA2WAVCDROM="$CDROMID"
fi
fi
nice $READNICE $CDROMREADER -D $CDDA2WAVCDROM -t ${READTRACKNUMS:-$UTRACKNUM} "$FILEARG" $REDIR
;;
## FIXME ## We have an exception for dagrab, since it uses -f
## FIXME ## Shall we just use -f $FILEARG ??
dagrab) nice $READNICE $CDROMREADER -d "$CDROM" -v $UTRACKNUM "$FILEARG" $REDIR
;;
cddafs)
# Find the track's mounted path
REALTRACKNUM=$(expr $UTRACKNUM + 0)
FILEPATH=$(mount | grep "$CDROM on" | sed 's/^[^ ]* on \(.*\) (.*/\1/')
FILEPATH=$(find "$FILEPATH" | grep "/$REALTRACKNUM ");
# If the file exists, copy it
if [ -e "$FILEPATH" ] ; then
nice $READNICE $CDROMREADER "$FILEPATH" "$FILEARG" $REDIR
else
false
fi ;;
debug) nice $READNICE $CDROMREADER -$CDPARANOIACDROMBUS "$CDROM" -w $UTRACKNUM-[:1] "$FILEARG" $REDIR
;;
esac
RETURN=$?
# If we get some error or we get some missing wav
# (as long as we dont use pipes)
if [ "$RETURN" != "0" -o \( ! -s "$WAVDATA" -a X"$USEPIPES" != "Xy" \) ]; then
# Thank goodness errors is only machine-parseable up to the
# first colon, otherwise this woulda sucked
if [ "$RETURN" = "0" -a ! -s "$WAVDATA" ]; then
RETURN=73 # fake a return code as cdparanoia return 0 also on aborted reads
fi
if [ "$USEPIPES" = "y" ]; then
echo "readencodetrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
else
echo "readtrack-$UTRACKNUM: $CDROMREADER returned code $RETURN" >> "$ABCDETEMPDIR/errors"
fi
return $RETURN
else
if [ "$USEPIPES" = "y" ]; then
echo readencodetrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
else
echo readtrack-$UTRACKNUM >> "$ABCDETEMPDIR/status"
fi
if [ "$1" = "onetrack" ]; then
echo onetrack >> "$ABCDETEMPDIR/status"
fi
fi
}
# do_cdspeed
# No values accepted, only uses env variables
do_cdspeed ()
{
if "$CDSPEED" "$CDSPEEDOPTS" "$CDSPEEDVALUE" >/dev/null ; then
vecho "Setting CD speed to ${CDSPEEDVALUE}x"
else
echo "abcde: unable to set the device speed" >&2
fi
}
# vecho [message]
#
# vecho outputs a message if EXTRAVERBOSE is selected
vecho ()
{
if [ x"$EXTRAVERBOSE" != "x" ]; then
case $1 in
warning) shift ; log warning "$@" ;;
*) echo "$@" ;;
esac
fi
}
# decho [message]
#
# decho outputs a debug message if DEBUG is selected
decho ()
{
if [ x"$DEBUG" != "x" ]; then
if echo $1 | grep "^\[" > /dev/null 2>&1 ; then
DEBUGECHO=$(echo "$@" | tr -d '[]')
echo "[DEBUG] $DEBUGECHO: `eval echo \\$${DEBUGECHO}`"
else
echo "[DEBUG] $1"
fi
fi
}
# User-redefinable functions
# Custom filename munging:
mungefilename ()
{
#echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
echo "$@" | sed s,:,\ -,g | tr \ / __ | tr -d \'\"\?\[:cntrl:\]
}
# Custom genre munging:
mungegenre ()
{
echo $CDGENRE | tr "[:upper:]" "[:lower:]"
}
# pre_read
# Empty pre_read function, to be defined in the configuration file.
pre_read ()
{
:
}
# post_read
# Empty post_read function, to be defined in the configuration file.
post_read ()
{
:
}
###############################################################################
# End of functions
#
# Start of execution
###############################################################################
# Builtin defaults
# CDDB
# Defaults to FreeDB, but a python musicbrainz can be used
CDDBMETHOD=cddb
CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
CDDBSUBMIT=freedb-submit at freedb.org
CDDBPROTO=6
HELLOINFO="$(whoami)@$(hostname)"
CDDBCOPYLOCAL="n"
CDDBLOCALPOLICY="always"
CDDBLOCALRECURSIVE="y"
CDDBLOCALDIR="$HOME/.cddb"
CDDBUSELOCAL="n"
# List of fields we parse and show during the CDDB parsing...
SHOWCDDBFIELDS="year,genre"
INTERACTIVE=y
#CDROMREADERSYNTAX=cdparanoia
ENCODERSYNTAX=default
MP3ENCODERSYNTAX=default
OGGENCODERSYNTAX=default
FLACENCODERSYNTAX=default
SPEEXENCODERSYNTAX=default
MPPENCODERSYNTAX=default
AACENCODERSYNTAX=default
NORMALIZERSYNTAX=default
CUEREADERSYNTAX=default
TOCREADERSYNTAX=default
OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
# Use the following VAOUTPUTFORMAT to revert to 2.0.x VA format:
#VAOUTPUTFORMAT=${OUTPUTFORMAT}
VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
ONETRACKOUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${ALBUMFILE}'
VAONETRACKOUTPUTFORMAT='Various-${ALBUMFILE}/${ALBUMFILE}'
PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
PLAYLISTDATAPREFIX=''
VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
VAPLAYLISTDATAPREFIX=''
DOSPLAYLIST=n
COMMENT=''
ID3TAGV=2
ENCNICE=10
READNICE=10
DISTMP3NICE=10
VARIOUSARTISTS=n
VARIOUSARTISTSTYLE=forward
KEEPWAVS=n
PADTRACKS=n
NOGAP=n
BATCHNORM=n
NOCDDBQUERY=n
# If using scsi devices, cdda2wav needs a CDROMID, instead of a device node
# i.e. CDROMID="1,0,0"
CDROMID=""
# If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
# If we are using the ide-scsi emulation layer, we need to define a "g"
CDPARANOIACDROMBUS="d"
# program paths - defaults to checking your $PATH
# mp3
LAME=lame
TOOLAME=toolame
GOGO=gogo
BLADEENC=bladeenc
L3ENC=l3enc
XINGMP3ENC=xingmp3enc
MP3ENC=mp3enc
# ogg
VORBIZE=vorbize
OGGENC=oggenc
# flac
FLAC=flac
# speex
SPEEXENC=speexenc
# mpp (Musepack)
MPPENC=mppenc
# m4a
AACENC=faac
ID3=id3
ID3V2=id3v2
EYED3=eyeD3
CDPARANOIA=cdparanoia
CDDA2WAV=cdda2wav
DAGRAB=dagrab
CDDAFS=cp
CDDISCID=cd-discid
CDDBTOOL=cddb-tool
MUSICBRAINZ=musicbrainz-get-tracks
EJECT=eject
MD5SUM=md5sum
DISTMP3=distmp3
VORBISCOMMENT=vorbiscomment
METAFLAC=metaflac
NORMALIZE=normalize-audio
CDSPEED=eject
VORBISGAIN=vorbisgain
MP3GAIN=mp3gain
MPPGAIN=replaygain
CDRDAO=cdrdao
TOC2CUE=toc2cue
MKCUE=mkcue
DIFF=diff
CUE2DISCID=builtin
# Options for programs called from abcde
# mp3
LAMEOPTS=
TOOLAMEOPTS=
GOGOOPTS=
BLADEENCOPTS=
L3ENCOPTS=
XINGMP3ENCOPTS=
MP3ENCOPTS=
# ogg
VORBIZEOPTS=
OGGENCOPTS=
# flac
FLACOPTS=
# speex
SPEEXENCOPTS=
# mpc
MPPENCOPTS=
# m4a
AACENCOPTS=
ID3OPTS=
ID3V2OPTS=
CDPARANOIAOPTS=
CDDA2WAVOPTS=
DAGRABOPTS=
CDDAFSOPTS="-f"
CDDBTOOLOPTS=
EJECTOPTS=
DISTMP3OPTS=
NORMALIZEOPTS=
CDSPEEDOPTS="-x"
CDSPEEDVALUE=
MKCUEOPTS=
MKTOCOPTS=""
VORBISCOMMENTOPTS="-R"
METAFLACOPTS="--no-utf8-convert"
DIFFOPTS=
# Default to one process if -j isn't specified
MAXPROCS=1
# List of actions to perform - by default, run to completion
ACTIONS=cddb,read,encode,tag,move,clean
# This option is basicaly for Debian package dependencies:
# List of prefered outputs - by default, run with whatever we have in the path
DEFAULT_OUTPUT_BINARIES=vorbis:oggenc,flac:flac,mp3:toolame,mp3:lame,mp3:bladeenc,spx:speex,m4a:faac
# List of prefered cdromreaders - by default, run whichever we have in the path
DEFAULT_CDROMREADERS="cdparanoia cdda2wav"
# Asume fetch if under FreeBSD. curl is used for Mac OS X. wget is used for
# Linux/OpenBSD. ftp is user for NetBSD.
# Let's use these checkings to determine the OS flavour, which will be used
# later
if [ X$(uname) = "XFreeBSD" ] ; then
HTTPGET=fetch
MD5SUM=md5
NEEDCDROMID=y
OSFLAVOUR=FBSD
elif [ X$(uname) = "XDarwin" ] ; then
HTTPGET=curl
OSFLAVOUR=OSX
# We should have disktool in OSX, but let's be sure...
NEEDDISKTOOL=y
CDROMREADERSYNTAX=cddafs
elif [ X$(uname) = "XOpenBSD" ] ; then
HTTPGET=wget
MD5SUM=md5
OSFLAVOUR=OBSD
elif [ X$(uname) = "XNetBSD" ] ; then
HTTPGET=ftp
MD5SUM=md5
OSFLAVOUR=NBSD
elif [ X$(uname) = "SunOS" ] ; then
HTTPGET=""
MD5SUM=md5
OSFLAVOUR=SunOS
else
HTTPGET=wget
fi
# If CDDBAVAIL is set to n, no CDDB read is done
# If USEID3 is set to n, no ID3 tagging is done
CDDBAVAIL=y
USEID3=y
USEID3V2=y
if [ -z "$OUTPUTDIR" ]; then
OUTPUTDIR=$(pwd)
fi
if [ -z "$WAVOUTPUTDIR" ]; then
WAVOUTPUTDIR="$OUTPUTDIR"
fi
# Load system defaults
if [ -r /etc/abcde.conf ]; then
. /etc/abcde.conf
fi
# Load user preference defaults
if [ -r $HOME/.abcde.conf ]; then
. $HOME/.abcde.conf
fi
# By this time, we need some HTTPGETOPTS already defined.
# If the user has defined a non-default HTTPGET method, we should not be empty.
if [ "$HTTPGETOPTS" = "" ] ; then
case $HTTPGET in
wget) HTTPGETOPTS="-q -O -";;
curl) HTTPGETOPTS="-f -s";;
fetch)HTTPGETOPTS="-q -o -";;
ftp) HTTPGETOPTS="-a -V -o - ";;
*) log warning "HTTPGET in non-standard and HTTPGETOPTS are not defined." ;;
esac
fi
# If the CDROM has not been set yet, find a suitable one.
# If this is a devfs system, default to /dev/cdroms/cdrom0
# instead of /dev/cdrom
if [ "$CDROM" = "" ] ; then
if [ -e /dev/cdroms/cdrom0 ]; then
CDROM=/dev/cdroms/cdrom0
elif [ -e /dev/cdrom ]; then
CDROM=/dev/cdrom
elif [ -e /dev/cd0c ]; then
CDROM=/dev/cd0c
elif [ -e /dev/acd0c ]; then
CDROM=/dev/acd0c
elif [ -e /dev/disk1 ]; then
CDROM=/dev/disk1
fi
fi
# Parse command line options
#while getopts 1a:bc:C:d:Dehj:klLmMnNo:pPr:Rs:S:t:T:vVxw:W: opt ; do
while getopts 1a:bBc:C:d:Defghj:klLmMnNo:pPr:s:S:t:T:UvVxX:w:W:z opt ; do
case "$opt" in
1) ONETRACK=y ;;
a) ACTIONS="$OPTARG" ;;
A) EXPACTIONS="$OPTARG" ;;
b) BATCHNORM=y ;;
B) BATCHNORM=n ;;
c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
C) DISCID="$( echo ${OPTARG#abcde.} | tr -d /)" ;;
d) CDROM="$OPTARG" ;;
D) set -x ;;
h) usage; exit ;;
e) ERASEENCODEDSTATUS=y ;;
E) ENCODING="$OPTARG" ;;
f) FORCE=y ;;
g) NOGAP=y ;;
i) INLINETAG=y ;;
j) MAXPROCS="$OPTARG" ;;
k) KEEPWAVS=y ;;
l) LOWDISK=y ;;
L) CDDBUSELOCAL=y ;;
n) CDDBAVAIL=n ;;
N) INTERACTIVE=n ;;
m) DOSPLAYLIST=y ;;
M) DOCUE=y ;;
o) OUTPUTTYPE="$OPTARG" ;;
p) PADTRACKS=y ;;
P) USEPIPES=y ;;
r) REMOTEHOSTS="$OPTARG" ;;
R) CDDBLOCALRECURSIVE=y ;;
s) SHOWCDDBFIELDS="$OPTARG" ;;
S) CDSPEEDVALUE="$OPTARG" ;;
t) STARTTRACKNUMBER="$OPTARG" ;;
T) STARTTRACKNUMBER="$OPTARG" ; STARTTRACKNUMBERTAG="y" ;;
U) CDDBPROTO=5 ;;
v)
echo "This is abcde v$VERSION."
echo "Usage: abcde [options] [tracks]"
echo "abcde -h for extra help"
exit
;;
V) EXTRAVERBOSE="y" ;;
x) EJECTCD="y" ;;
X) CUE2DISCID="$OPTARG" ;;
w) COMMENT="$OPTARG" ;;
W) if echo $OPTARG | grep "[[:digit:]]" > /dev/null 2>&1 ; then
STARTTRACKNUMBER="${OPTARG}$(printf %02d ${STARTTRACKNUMBER:-01})" ; STARTTRACKNUMBERTAG="y" ; COMMENT="CD${OPTARG}"
else
log error "argument of -W must be integer"
exit 1
fi
;;
z) DEBUG=y ; CDROMREADERSYNTAX=debug ; EJECTCD="n" ;;
?) usage; exit ;;
esac
done
shift $(($OPTIND - 1))
if [ "$1" = various ] ; then
VARIOUSARTISTS=y
shift
fi
# Here it comes the worse part of the whole thing. From here until we start
# ripping, we have a mixture of sanity checks, verifications, default settigs
# and other crazy stuff that interdepends, but hey, someone has to do it.
# If NOCDDBQUERY is set, don't query the CDDB server.
if [ "$NOCDDBQUERY" = "y" ]; then
CDDBAVAIL="n"
fi
# If the user specified a flac file, then switch to special flac mode
if echo "$CDROM" | grep -i '.flac$' > /dev/null 2>&1 ; then
if [ ! -f "$CDROM" ]; then
log error "the defined file for FLAC ripping cannot be found" >&2
exit 1
fi
vecho warning "switching to flac CDROMREADERSYNTAX..."
CDROMREADERSYNTAX=flac
# We have a builtin version of cue2discid...
case "$CUE2DISCID" in
builtin);;
*) NEEDCUE2DISCID=y;;
esac
NEEDMETAFLAC=y
EJECTCD=n
fi
# If the user provided a DISCID, disable eject
if [ -n "$DISCID" ] || [ "$CDROMREADERSYNTAX" = "flac" ]; then EJECTCD=n ; fi
# Check the available cd rippers in the system, from the ones we know.
if [ "$CDROMREADERSYNTAX" = "" ]; then
for DEFAULT_CDROMREADER in $DEFAULT_CDROMREADERS; do
if new_checkexec $DEFAULT_CDROMREADER; then
CDROMREADERSYNTAX=$DEFAULT_CDROMREADER
break
fi
done
if [ "$CDROMREADERSYNTAX" = "" ]; then
log error "no cdreader found in your PATH"
log error "hints: are all dependencies installed? has the \$PATH been modified?"
exit 1
fi
fi
# Decide if we can continue.
if [ "$ONETRACK" = "y" ]; then
# FIXME # remove check as soon as we find out about the other readers
case "$CDROMREADERSYNTAX" in
flac) ;;
cdparanoia) ;;
cdda2wav) ;;
*) log error "$CDROMREADERSYNTAX does not support ONETRACK mode"
exit 1 ;;
esac
if [ "$BATCHNORM" = "y" ]; then
log warning "BATCHNORM mode is not compatible with ONETRACK mode. Disabling..."
BATCHNORM=n
fi
if [ "$NOGAP" = "y" ]; then
log warning "NOGAP mode is not compatible with ONETRACK mode. Disabling..."
NOGAP=n
fi
# It does not matter how many tracks we want. In ONETRACK mode we grab them all
# FIXME # allow ranges of tracks to be selected for onetrack ripping
if [ $# -gt 0 ]; then
log warning "ONETRACK mode selected, grabbing all tracks..."
fi
else
while [ $# -gt 0 ]; do
# Range parsing code courtesy of Vincent Ho
# Cleaned up to use shell built-ins by Charles Steinkuehler
if [ "${1#*[^0-9-]}" != "$1" ]; then
log error "syntax error while processing track numbers"
else
RSTART=${1%%-*}
REND=${1##*-}
while [ ${RSTART:=1} -le ${REND:=0} ] ; do
TRACKQUEUE="$TRACKQUEUE $RSTART"
RSTART=$(( $RSTART + 1 ))
done
fi
shift
done
fi
# List of valid actions: cddb,read,normalize,encode,tag,move,playlist,clean
# List of experimental actions: retag,transcode
# Determine what actions are to be done from $ACTIONS and set the
# following environment variables for them:
DOCDDB=n
DOREAD=n
DONORMALIZE=n
DOPREPROCESS=n
DOENCODE=n
DOPOSTPROCESS=n
DOTAG=n
DOMOVE=n
DOREPLAYGAIN=n
DOPLAYLIST=n
DOCLEAN=n
DOCUE=n
DOTOC=n
for ACTION in $(echo $ACTIONS | tr , \ )
do
case $ACTION in
default) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOCLEAN=y;;
cue) DOCUE=y ; MAKECUEFILE=y ;;
toc) DOTOC=y ;;
cddb) DOCDDB=y;;
read) DOREAD=y;;
normalize) DONORMALIZE=y; DOREAD=y;;
# preprocess) DOPREPROCESS=y; DOREAD=y;;
encode) DOENCODE=y; DOREAD=y;;
# postprocess) DOPREPROCESS=y; DOENCODE=y; DOREAD=y;;
tag) DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
move) DOMOVE=y; DOTAG=y; DOREAD=y; DOENCODE=y; DOCDDB=y;;
replaygain) DOCDDB=y; DOREAD=y; DOENCODE=y; DOTAG=y; DOMOVE=y; DOREPLAYGAIN=y;;
playlist) DOCDDB=y; DOPLAYLIST=y;;
clean) DOCLEAN=y;;
esac
done
if [ "$DONORMALIZE" = "y" ] && [ "$DOREPLAYGAIN" = "y" ]; then
# FIXME # should we abort on error or just inform the user?
log warning "selected both normalize and replaygain actions"
fi
for SHOWCDDBFIELD in $(echo $SHOWCDDBFIELDS | tr , \ ); do
case $SHOWCDDBFIELD in
y*|Y*) SHOWCDDBYEAR="y";;
g*|G*) SHOWCDDBGENRE="y";;
*) ;;
esac
done
# At this point a CDROM has to be defined, so we check it exists.
if [ X"$CDROM" != "X" ] ; then
if [ "$CDROMREADERSYNTAX" = "cdda2wav" ] && [ "$NEEDCDROMID" = "y" ] ; then
if [ "$OSFLAVOUR" = "FBSD" ]; then
if echo "$CDROMID" | grep "^[0-9],[0-9],[0-9]$" >/dev/null 2>&1 ; then :; else
log error "CDROMID not in the right format for $CDROMREADERSYNTAX"
log error "Use \"cdrecord -scanbus\" to obtain a adecuate ID an set CDROMID accordingly"
exit 1
fi
fi
elif [ ! -e "$CDROM" -a X"$DOREAD" = "Xy" ]; then
log error "CDROM device cannot be found."
exit 1
fi
# avoid processing if we are not going to hit the CDROM.
elif [ X"$DOREAD" = "Xy" ]; then
log error "CDROM has not been defined or cannot be found"
exit 1
fi
# USEPIPES pre-tests, before we get into more serious stuff
# Not compatible with:
# - multiple outputs
# - normalize
# - lowdisk algorithm
# - anything else?
if [ X"$USEPIPES" = "Xy" ]; then
if [ $(echo "$OUTPUTTYPE" | tr , \ | wc -w ) -gt 1 ]; then
log error "Unix pipes not compatible with multiple outputs"
exit 1
fi
if [ X"$DONORMALIZE" = "Xy" ]; then
log error "Unix pipes not compatible with normalizer"
# FIXME # Do we need to exit or shall we just disable the mode?
exit 1
fi
if [ X"$BATCHNORM" = "Xy" ]; then
log error "Unix pipes not compatible with BATCHNORM encoding"
exit 1
fi
if [ X"$NOGAP" = "Xy" ]; then
log error "Unix pipes not compatible with NOGAP encoding"
exit 1
fi
if [ X"$DOENCODE" = "Xn" ]; then
vecho warning "Disabling Unix pipes since we are not encoding!"
USEPIPES=n
fi
if [ X"$LOWDISK" = "Xy" ]; then
log error "Unix pipes not compatible with lowdisk algorithm"
exit 1
fi
fi
# LOWDISK pre-tests, before we get into more problematic stuff
# Not compatible with anything that needs all the files in the hard disc:
# - BATCHNORM
# - NOGAP lame mode
if [ X"$LOWDISK" = "Xy" ]; then
if [ X"$BATCHNORM" = "Xy" ]; then
log error "Unix pipes not compatible with BATCHNORM encoding"
exit 1
fi
if [ X"$NOGAP" = "Xy" ]; then
log error "Unix pipes not compatible with NOGAP encoding"
exit 1
fi
fi
# BATCHNORM pre-tests, before we get into serious problems
# Not compatible with
if [ "$BATCHNORM" = "y" ] && [ "$DONORMALIZE" = "n" ]; then
vecho warning "Disabling BATCHNORM since we are not normalizing!"
BATCHNORM=n
fi
# Check the encoding format from the ones available in the system, if nothing has been configured in the system.
if [ X"$OUTPUTTYPE" = "X" ]; then
for DEFAULT_OUTPUT in $( echo "$DEFAULT_OUTPUT_BINARIES" | tr , \ ); do
DEFAULT_OUTPUT_FORMAT="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 1)"
DEFAULT_OUTPUT_BINARY="$(echo $DEFAULT_OUTPUT | cut -d ":" -f 2)"
if [ -x $(which $DEFAULT_OUTPUT_BINARY) ] ; then
OUTPUTTYPE=$DEFAULT_OUTPUT_FORMAT
vecho "No default output type defined. Autoselecting $OUTPUTTYPE..." >&2
break
fi
done
if [ X"$OUTPUTTYPE" = "X" ]; then
log error "no encoder found in the PATH"
log error "hints: are all dependencies installed? has the \$PATH been modified?"
exit 1
fi
fi
# Decide which CDROM reader we're gonna use
case "$CDROMREADERSYNTAX" in
cdparanoia|debug)
CDROMREADER="$CDPARANOIA"
CDROMREADEROPTS="$CDPARANOIAOPTS"
;;
cdda2wav)
CDROMREADER="$CDDA2WAV"
CDROMREADEROPTS="$CDDA2WAVOPTS"
;;
dagrab)
CDROMREADER="$DAGRAB"
CDROMREADEROPTS="$DAGRABOPTS"
;;
cddafs)
CDROMREADER="$CDDAFS"
CDROMREADEROPTS="$CDDAFSOPTS"
;;
flac)
CDROMREADER="$FLAC"
CDROMREADEROPTS="$FLACOPTS"
;;
esac
# There's only one normalize...
case "$NORMALIZERSYNTAX" in
default|normalize)
NORMALIZER="$NORMALIZE"
NORMALIZEROPTS="$NORMALIZEOPTS"
;;
esac
# Allow -o OUTPUT(1):OPTIONS(1),...,OUTPUT(N):OPTIONS(N) mode of operation
if echo "$OUTPUTTYPE" | grep ":" > /dev/null 2>&1 ; then
for OUTPUT in "$(echo "$OUTPUTTYPE" | tr \ \|| tr , \ | tr \| \ )"; do
case "$OUTPUT" in
vorbis:*|ogg:*) OGGENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
mp3:*) MP3ENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
flac:*) FLACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
spx:*) SPEEXENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
mpc:*) MPPENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
m4a:*) AACENCODEROPTSCLI="$( echo $OUTPUT | cut -d: -f2- )" ;;
esac
done
for OUTPUT in "$(echo "$OUTPUTTYPE" | tr , \ )"; do
TEMPOUTPUT=$( echo "$OUTPUT" | cut -d: -f1 )
TEMPOUTPUTTYPE="${TEMPOUTPUTTYPE:+$TEMPOUTPUTTYPE,}$TEMPOUTPUT"
done
OUTPUTTYPE="$TEMPOUTPUTTYPE"
fi
# If nothing has been specified, use oggenc for oggs and lame for mp3s and flac
# for flacs and speexenc for speex and mppenc for mpps and faac for m4as
# Getting ready for multiple output changes
for OUTPUT in $(echo $OUTPUTTYPE | tr , \ )
do
case $OUTPUT in
vorbis|ogg)
[ "$OGGENCODERSYNTAX" = "default" ] && OGGENCODERSYNTAX=oggenc
[ "$DOTAG" = "y" ] && NEEDCOMMENTER=y
[ "$DOREPLAYGAIN" = "y" ] && NEEDVORBISGAIN=y
OGGOUTPUTCONTAINER=ogg
;;
mp3)
[ "$MP3ENCODERSYNTAX" = "default" ] && MP3ENCODERSYNTAX=lame
[ "$DOTAG" = "y" ] && NEEDTAGGER=y
[ "$DOREPLAYGAIN" = "y" ] && NEEDMP3GAIN=y
;;
flac)
[ "$FLACENCODERSYNTAX" = "default" ] && FLACENCODERSYNTAX=flac
[ "$DOTAG" = "y" ] && NEEDMETAFLAC=y
[ "$DOREPLAYGAIN" = "y" ] && NEEDMETAFLAC=y
[ "$ONETRACK" = "y" ] && [ "$DOCUE" = "y" ] && NEEDMETAFLAC=y
;;
spx)
[ "$SPEEXENCODERSYNTAX" = "default" ] && SPEEXENCODERSYNTAX=speexenc
# [ "$DOREPLAYGAIN" = "y" ] &&
;;
mpc)
[ "$MPPENCODERSYNTAX" = "default" ] && MPPENCODERSYNTAX=mppenc
[ "$DOREPLAYGAIN" = "y" ] && NEEDMPPGAIN=y
;;
m4a)
[ "$AACENCODERSYNTAX" = "default" ] && AACENCODERSYNTAX=faac
;;
wav)
if [ "$KEEPWAVS" = "y" ]; then
vecho "Setting the KEEPWAVS option, since the resulting wav files were requested..."
fi
KEEPWAVS=move
;;
*) log error "Invalid OUTPUTTYPE defined"
exit 1
;;
esac
done
# decide which encoder
case "$MP3ENCODERSYNTAX" in
lame)
MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$LAMEOPTS}"
MP3ENCODER="$LAME"
;;
toolame)
MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$TOOLAMEOPTS}"
MP3ENCODER="$TOOLAME"
;;
gogo)
MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$GOGOOPTS}"
MP3ENCODER="$GOGO"
;;
bladeenc)
MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$BLADEENCOPTS}"
MP3ENCODER="$BLADEENC"
;;
l3enc)
MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$L3ENCOPTS}"
MP3ENCODER="$L3ENC"
;;
xingmp3enc)
MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$XINGMP3ENCOPTS}"
MP3ENCODER="$XINGMP3ENC"
;;
mp3enc)
MP3ENCODEROPTS="${MP3ENCODEROPTSCLI:-$MP3ENCOPTS}"
MP3ENCODER="$MP3ENC"
;;
esac
case "$OGGENCODERSYNTAX" in
vorbize)
OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$VORBIZEOPTS}"
OGGENCODER="$VORBIZE"
;;
oggenc)
OGGENCODEROPTS="${OGGENCODEROPTSCLI:-$OGGENCOPTS}"
OGGENCODER="$OGGENC"
;;
esac
case "$FLACENCODERSYNTAX" in
flac)
FLACENCODEROPTS="${FLACENCODEROPTSCLI:-$FLACOPTS}"
FLACENCODER="$FLAC"
# FLAC streams can be encapsulated on a Ogg transport layer
if echo "$FLACENCODEROPTS" | egrep -- "(^| )--ogg($| )" > /dev/null 2>&1 ;then
log error "FLAC on an Ogg container is not yet supported"
log error "due to problem with adding comments to such files"
exit 1
FLACOUTPUTCONTAINER=ogg
else
FLACOUTPUTCONTAINER=flac
fi
;;
esac
case "$SPEEXENCODERSYNTAX" in
speexenc)
SPEEXENCODEROPTS="${SPEEXENCODEROPTSCLI:-$SPEEXENCOPTS}"
SPEEXENCODER="$SPEEXENC"
;;
esac
case "$MPPENCODERSYNTAX" in
mppenc)
MPPENCODEROPTS="${MPPENCODEROPTSCLI:-$MPPENCOPTS}"
MPPENCODER="$MPPENC"
;;
esac
case "$AACENCODERSYNTAX" in
faac)
AACENCODEROPTS="${AACENCODEROPTSCLI:-$AACENCOPTS}"
AACENCODER="$AACENC"
;;
esac
# and which tagger
if [ "$ID3TAGV" = "1" ]; then
TAGGER="$ID3"
TAGGEROPTS="$ID3OPTS"
else
case "$ID3SYNTAX" in
eyed3)
TAGGER="$EYED3"
TAGGEROPTS="$EYED3OPTS"
;;
*)
TAGGER="$ID3V2"
TAGGEROPTS="$ID3V2OPTS"
;;
esac
fi
# Specific for NOGAP is the use of lame. Another encoder fails...
if [ "$NOGAP" = "y" ] && [ ! "$MP3ENCODER" = "lame" ]; then
log warning "the NOGAP option is specific of lame. Deactivating..."
NOGAP=n
fi
# Options for TOC reader
case "$TOCREADERSYNTAX" in
default|cdrdao)
TOCREADEROPTS="read-toc --device"
TOCREADER="$CDRDAO"
;;
esac
# Options for mkcue
case "$CUEREADERSYNTAX" in
default|mkcue)
CUEREADEROPTS="${CDROM}"
CUEREADER="$MKCUE"
;;
toc2cue)
CUEREADEROPTS=""
CUEREADER="$TOC2CUE"
esac
# which information retrieval tool are we using?
case "$CDDBTOOL" in
cddb) ;;
musicbrainz) ;;
esac
# Check if both OGGEOUTPUTCONTAINER and FLACOUTPUTCONTAINER are the same, and differentiante them
if [ X"$OGGOUTPUTCONTAINER" = "Xogg" ] && [ X"$FLACOUTPUTCONTAINER" = "Xogg" ]; then
log error "FLAC on an Ogg container is not yet supported"
log error "due to problem with adding comments to such files"
exit 1
OGGOUTPUTCONTAINER=ogg.ogg
FLACOUTPUTCONTAINER=flac.ogg
vecho warning "modified file endings due to conflicting transport layers in Ogg/Vorbis and Ogg/FLAC"
fi
# Clean up nice options (either use '-n NICELEVEL or -NICELEVEL')
if [ "$ENCNICE" ]; then
ENCNICE="-n $ENCNICE"
fi
if [ "$READNICE" ]; then
READNICE="-n $READNICE"
fi
if [ "$DISTMP3NICE" ]; then
DISTMP3NICE="-n $DISTMP3NICE"
fi
# Don't check for stuff if it's not needed
if [ "$REMOTEHOSTS" ]; then
NEEDDISTMP3=y
fi
if [ "$DONORMALIZE" = "y" ]; then
NEEDNORMALIZER=y
fi
if [ "$EJECTCD" = "y" ]; then
NEEDEJECT=y
fi
if [ ! "$CDDBAVAIL" = "n" ] && [ "$DOCDDB" = "y" ]; then
if [ "$CDDBMETHOD" = "cddb" ]; then
NEEDHTTPGET=y
elif [ "$CDDBMETHOD" = "musicbrainz" ]; then
:
fi
fi
if [ "$DOCUE" = "y" ]; then
NEEDCUEREADER=y
if [ "$CUEREADERSYNTAX" = "toc2cue" ]; then
DOTOC=y
fi
fi
if [ "$DOTOC" = "y" ]; then
NEEDTOCREADER=y
fi
if [ X"$CDSPEEDVALUE" != "X" ] && [ "$DOREAD" = "y" ]; then
case "$CDROMREADERSYNTAX" in
cdparanoia|debug) CDROMREADEROPTS="$CDPARANOIAOPTS -S $CDSPEEDVALUE" ;;
### FIXME ### translate "cue2discid" from python to bash
flac) NEEDMETAFLAC=y ; NEEDCUE2DISCID=y ; CDSPEEDVALUE="" ;;
*) NEEDCDSPEED=y ;;
esac
fi
###USEPIPESSUPPORT###
# Rippers with USEPIPE support
# FIXME # Include here all the rippers we can figure out support pipes
PIPERIPPER_cdparanoia="-"
PIPERIPPER_debug="-"
PIPERIPPER_flac="-c "
# Encoders with USEPIPE support
# FIXME # Include here all the encoders we can figure out support pipes
PIPE_lame="-"
PIPE_bladeenc="-"
PIPE_oggenc="-"
PIPE_flac="-"
# Figure out if we can use pipes with the ripper/encoder combination
# exit otherwise
if [ "$USEPIPES" = "y" ]; then
PIPERIPPERSVARCHECK="PIPERIPPER_${CDROMREADERSYNTAX}"
case "$OUTPUT" in
mp3)
PIPEENCODERSVARCHECK="PIPE_$MP3ENCODERSYNTAX" ;;
vorbis|ogg)
PIPEENCODERSVARCHECK="PIPE_$OGGENCODERSYNTAX" ;;
flac)
PIPEENCODERSVARCHECK="PIPE_$FLACENCODERSYNTAX" ;;
spx)
PIPEENCODERSVARCHECK="PIPE_$SPEEXENCODER" ;;
mpc)
PIPEENCODERSVARCHECK="PIPE_$MPPENCODER" ;;
esac
decho "PIPERIPPERSVARCHECK: $( eval echo "\$$PIPERIPPERSVARCHECK" )"
if [ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "$" ] || \
[ "$( eval echo "\$$PIPERIPPERSVARCHECK" )" = "" ] ; then
log error "no support for pipes with given ripper"
log error "read the USEPIPES file from the source tarball to get help."
log error "On a Debian system, it is under /usr/share/doc/abcde/USEPIPES.gz"
exit 1;
fi
decho "PIPEENCODERSVARCHECK: $( eval echo "\$$PIPEENCODERSVARCHECK" )"
if [ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "$" ] || \
[ "$( eval echo "\$$PIPEENCODERSVARCHECK" )" = "" ] ; then
log error "no support for pipes with given encoder"
log error "read the USEPIPES file from the source tarball to help"
log error "on a Debian system, read /usr/share/doc/abcde/USEPIPES.gz"
exit 1;
fi
fi
# Make sure a buncha things exist
for X in $CDROMREADER $CDDISCID ${NEEDTAGGER+$TAGGER} $MP3ENCODER \
$OGGENCODER $FLACENCODER $SPEEXENCODER $MPPENCODER \
$AACENCODER \
${NEEDHTTPGET+$HTTPGET} ${NEEDDISTMP3+$DISTMP3} \
${NEEDCOMMENTER+$VORBISCOMMENT} ${NEEDMETAFLAC+$METAFLAC} \
${NEEDNORMALIZER+$NORMALIZER} ${NEEDEJECT+$EJECT} \
${NEEDDISKTOOL+disktool} ${NEEDCDSPEED+$CDSPEED} \
${NEEDVORBISGAIN+$VORBISGAIN} ${NEEDMP3GAIN+$MP3GAIN} \
${NEEDMPPGAIN+$MPPGAIN} ${NEEDTOCREADER+$TOCREADER} \
${NEEDCUEREADER+$CUEREADER} ${NEEDCUE2DISCID+$CUE2DISCID}
do
checkexec "$X"
done
# And last but not least, check if we can diff between files. We do not abort,
# since diffing is not critical...
if [ -x $(which $DIFF) ]; then :; else
vecho warning "Disabling diff since we cannot find it in the \$PATH..."
DIFF=""
fi
## Now that we have metaflac, check if we need cue2discid
#case $CDROMREADERSYNTAX in
# flac)
# TRACKINFO=$($METAFLAC --show-tag=CDDB $CDROM | cut -d"=" -f2 | egrep "[a-f0-9]{8}")
# if [ "$TRACKINFO" = "" ]; then
# checkexec ${NEEDCUE2DISCID+$CUE2DISCID}
# fi
# ;;
#esac
CDROMREADER="$CDROMREADER $CDROMREADEROPTS"
CDDBTOOL="$CDDBTOOL $CDDBTOOLOPTS"
HTTPGET="$HTTPGET $HTTPGETOPTS"
# Here it used to say:
# One thousand lines in, we can start doing stuff with things
# Well, right now we are at line 3306 ;)
# Export needed things so they can be read in this subshell
export CDDBTOOL ABCDETEMPDIR TRACKQUEUE LOWDISK EJECTCD EJECT EJECTOPTS
export CDROM CDDBDATA REMOTEHOSTS MAXPROCS HTTPGET MD5SUM
if [ "$DOREAD" = "y" ]; then
# User-definable function to set some things. Use it for
# - closing the CD tray with eject -t
# - set the CD speed value with eject -x
vecho -n "Executing customizable pre-read function... "
pre_read # Execute the user-defined pre-read funtion. Close the CD with it.
vecho "done."
fi
case "$CDDBMETHOD" in
cddb)
do_discid # Get ABCDETEMPDIR created and status file initialized
;;
musicbrainz)
do_musicbrainz id
;;
esac
if [ "$DOCDDB" = "y" ]; then
# start with a sane default:
CDDBLOCALSTATUS=notfound
if [ $CDDBUSELOCAL = "y" ]; then
do_localcddb
fi
if checkstatus cddb-choice > /dev/null; then
:
else
if [ "$CDDBLOCALSTATUS" = "notfound" ] ; then
case "$CDDBMETHOD" in
cddb)
do_cddbstat
do_cddbquery
do_cddbread
;;
musicbrainz)
do_musicbrainz
;;
esac
fi
fi
do_cddbedit
eval "$($CDDBTOOL parse "$CDDBDATA")"
fi
if [ X"$DOTOC" = "Xy" ]; then
do_toc
fi
if [ X"$DOCUE" = "Xy" ]; then
do_cue
fi
# Before reading tracks, we set the speed of the device
if [ X"$CDSPEEDVALUE" != "X" ]; then
case "$CDROMREADERSYNTAX" in
cdparanoia|debug) ;;
flac) ;;
*) do_cdspeed ;;
esac
fi
# Define the first and last track, since we might need them later in several places
FIRSTTRACK=$( get_first $TRACKQUEUE )
LASTTRACK=$( get_last $TRACKQUEUE )
if [ -f "$ABCDETEMPDIR/status" ] && [ X"$ERASEENCODEDSTATUS" = "Xy" ]; then
mv "$ABCDETEMPDIR/status" "$ABCDETEMPDIR/status.old"
grep -v ^encodetracklocation- < "$ABCDETEMPDIR/status.old" \
| grep -v ^encode-output > "$ABCDETEMPDIR/status"
fi
if checkstatus onetrack ; then ONETRACK=y ; fi
if [ "$ONETRACK" = "y" ]; then
# Reuse the CUEFILE in case we created it (now or in a previous run)
if CUEFILE=$(checkstatus cuefile); then
IMPORTCUESHEET=y
fi
fi
# Create playlist if needed (backgroundable) and start reading in tracks
(
if [ ! "$ONETRACK" = "y" ]; then
if [ "$DOPLAYLIST" = "y" ]; then
echo Creating playlist... >&2
do_playlist
fi
fi
# For the lowdisk option, only one program is running at once so the encoder
# can be unsilenced right away.
if [ "$LOWDISK" = "y" ] || [ "$ONETRACK" = "y" ]; then
echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
fi
if [ "$ONETRACK" = "y" ]; then
TRACKS="$FIRSTTRACK"
if [ "$USEPIPES" = "y" ]; then
if checkstatus readencodetrack-$FIRSTTRACK; then :; else
do_cdread onetrack $FIRSTTRACK $LASTTRACK | do_encode $FIRSTTRACK %local0% > /dev/null 2>&1
fi
else
if checkstatus readtrack-$FIRSTTRACK; then :; else
do_cdread onetrack $FIRSTTRACK $LASTTRACK
fi
fi
else
for UTRACKNUM in $TRACKQUEUE
do
if [ "$DOREAD" = "y" ]; then
if [ "$USEPIPES" = "y" ]; then
if checkstatus readencodetrack-$UTRACKNUM; then :; else
# Read, pipe, shut up!
do_cdread $UTRACKNUM | do_encode $UTRACKNUM %local0% > /dev/null 2>&1
fi
else
if checkstatus readtrack-$UTRACKNUM; then :; else
do_cdread $UTRACKNUM
fi
if [ "$?" != "0" ]; then
# CD read failed - don't give the goahead to
# the encoder
echo NO
exit
fi
fi
fi
if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ]; then
:
else
# If we are not reading, set the encode output to loud already, so
# that we can see the output of the first track.
if [ "$MAXPROCS" = "1" ] && [ ! "$DOREAD" = "y" ]; then
echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
fi
echo NEXTTRACK # Get the encoder machine churning again
if [ "$DOREAD" = "y" ]; then
if [ "$LOWDISK" = "y" ] && [ "$DOENCODE" = "y" ]; then
until checkstatus encodetrack-$UTRACKNUM
do
if checkerrors encodetrack-$UTRACKNUM; then
break
fi
sleep 2
done
fi
fi
fi
done
fi
# Now that we're done the encoding can be loud again -
# if we're not using SMP.
if [ "$MAXPROCS" = "1" ]; then
echo "encode-output=loud" >> "$ABCDETEMPDIR/status"
fi
# All tracks read, start encoding.
if [ "$NOGAP" = "y" ] || [ "$BATCHNORM" = "y" ] || [ "$ONETRACK" = "y" ]; then
echo NEXTTRACK
fi
# Execute the user-defined post_read funtion before ejecting CD
post_read
# We are now finished with the cdrom - it can be safely ejected. Note that
# abcde will not have completed yet.
if [ "$EJECTCD" = "y" ] && [ -x $(which $EJECT) ]; then
# We check if the disk we are processing is actually the disk inside the
# CD tray. If not, we do not eject the CD, since it might be so that the
# user ejected it manually.
#CURRENTTRACKINFO=$($CDDISCID $CDROM)
#if if [ "$?" != "1" ] && [ "$CURRENTTRACKINFO" = "$TRACKINFO" ] ; then
# More FreeBSD bits.
if [ X"$(uname)" = X"FreeBSD" ] ; then
# FreeBSD eject uses the EJECT environment variable to name the CDROM
# but in this script EJECT is in the envionment and names the program
eject=$EJECT
unset EJECT
# The FreeBSD eject needs "adc0" not "/dev/adc0c"
cd="$(echo $CDROM | sed -e 's=.*/==;s=[a-h]$==;')"
$eject $EJECTOPTS $cd
elif [ X"$(uname)" = X"Darwin" ] ; then
disktool -e ${CDROM#/dev/} 0
else
$EJECT $EJECTOPTS "$CDROM"
fi
#fi
fi
) | (
## Do we need to pre-process
#if [ x"$PREPROCESS" = "x" ] ; then
# cat
#else
# for PRETRACKNUM in $TRACKQUEUE
# do
# read GOAHEAD
# if [ "$GOAHEAD" = "NO" ]; then break; fi
# PREPROCEED=
# until [ $PREPROCEED ]
# do
# if checkstatus readtrack-$PRETRACKNUM; then PREPROCEED=y; break; fi
# # all locations are working, wait and try again later
# if [ ! $PREPROCEED ]; then sleep 3; fi
# done
# ( do_preprocess $PRETRACKNUM
# echo "NEXTTRACK"
# ) &
# done
#fi
#
#) | (
# In BATCHNORM and/or NOGAP modes, we want all tracks to be read first.
#BACK
if [ "$BATCHNORM" = "y" ] || [ "$NOGAP" = "y" ]; then
read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
if [ "$GOAHEAD" = "NO" ]; then break; fi
for LASTTRACK in $TRACKQUEUE; do :; done
if checkstatus readtrack-$LASTTRACK; then
if [ "$DONORMALIZE" = "y" ] && [ "$BATCHNORM" = "y" ]; then
if checkstatus normalizetrack-$LASTTRACK; then :; else do_batch_normalize; fi
if checkerrors batch-normalize; then exit 1; fi
fi
if [ "$DOENCODE" = "y" ] && [ "$NOGAP" = "y" ]; then
if [ "$DONORMALIZE" = "y" ]; then
for UTRACKNUM in $TRACKQUEUE
do
if checkstatus readtrack-$UTRACKNUM; then
if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
fi
done
fi
if checkstatus encodetrack-$LASTTRACK; then :; else do_nogap_encode; fi
if checkerrors nogap-encode; then exit 1; fi
fi
fi
fi
# If we are using ONETRACK, we can proceed with the normal encoding using just the $FIRSTTRACK as TRACKQUEUE
if [ "$ONETRACK" = "y" ] ; then
TRACKQUEUE="$FIRSTTRACK"
TRACKS="$FIRSTTRACK"
fi
# Do the encoding, including parallelization of remote encoding
# Figure out where each track is going to be encoded
ENCODELOCATIONS="$(echo $REMOTEHOSTS | tr , ' ')"
if [ "$MAXPROCS" != "0" ]; then
for NUM in $(f_seq_row 1 "$MAXPROCS")
do
ENCODELOCATIONS="$ENCODELOCATIONS %local$NUM%"
done
fi
# Strip whitespace
ENCODELOCATIONS=$(echo $ENCODELOCATIONS)
for UTRACKNUM in $TRACKQUEUE
do
# Wait for our cue
read GOAHEAD # For blocking - will contain either "NO" or "NEXTTRACK"
if [ "$GOAHEAD" = "NO" ]; then break; fi
# find out where this track is to be encoded
if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
# Make sure we have a place to encode this, if not, exit stage right
if [ -z "$ENCODELOCATIONS" ]; then
continue
fi
PROCEED=
until [ $PROCEED ]
do
for LOCATION in $ENCODELOCATIONS
do
PREVIOUSTRACK="$(checkstatus encodetracklocation-$LOCATION)"
# check first if a track has ever been assigned to this location
if [ -z "$PREVIOUSTRACK" ]; then PROCEED=y; break; fi
# If it errored out, rebuild $ENCODELOCATIONS without this location in it
if checkerrors encodetrack-$PREVIOUSTRACK; then
for TEMPLOCATION in $ENCODELOCATIONS
do
if [ "$TEMPLOCATION" != "$LOCATION" ]; then
TEMPENCODELOCATIONS="$TEMPENCODELOCATIONS $TEMPLOCATION"
fi
done
ENCODELOCATIONS=$(echo $TEMPENCODELOCATIONS)
ABORT=y
PROCEED=y
break
fi
# We're still here, this location must have been previously assigned,
# and last completed without error - check if it's done with the
# previous track yet
if checkstatus encodetrack-$PREVIOUSTRACK; then PROCEED=y; break; fi
done
# all locations are working, wait and try again later
if [ ! $PROCEED ]; then sleep 3; fi
done
# Record the location we're about to encode the next track at
echo "encodetracklocation-$LOCATION=$UTRACKNUM" >> "$ABCDETEMPDIR/status"
fi
# Don't proceed with the rest of the loop if we can't encode
if [ "$ABORT" ]; then continue; fi
## FIXME ## Add here
## run_command tagtrack-$OUTPUT-$1 $METAFLAC $METAFLACOPTS ${IMPORTCUESHEET:+--import-cuesheet-from="$ABCDETEMPDIR/$CUEFILE"} --import-tags-from=- "$ABCDETEMPDIR/track$1.$FLACOUTPUTCONTAINER"
# Set TRACKNUM, TRACKNAME
if [ -e "$CDDBDATA" ]; then
if [ "$ONETRACK" = "y" ]; then
TRACKNAME="$DALBUM"
TRACKNUM="$FIRSTTRACK"
splitvarious
else
TRACKNUM=$UTRACKNUM
CDDBTRACKNUM=$(expr $UTRACKNUM - 1)
getcddbinfo TRACKNAME
splitvarious
fi
fi
# You can't encode a file which needs to be normalized before finishing
# You can't tag a file before it's finished encoding -
# thus all of this is backgrounded together
(
if [ "$DONORMALIZE" = "y" ]; then
if checkstatus readtrack-$UTRACKNUM; then
if checkstatus normalizetrack-$UTRACKNUM; then :; else do_normalize $UTRACKNUM; fi
fi
fi
if [ "$DOENCODE" = "y" -a "$USEPIPES" != "y" ]; then
if checkstatus readtrack-$UTRACKNUM; then
#if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION; fi
if [ "$DONORMALIZE" = "y" ]; then
if checkstatus normalizetrack-$UTRACKNUM; then
if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
fi
else
if checkstatus encodetrack-$UTRACKNUM; then :; else do_encode $UTRACKNUM $LOCATION $OUTPUT; fi
fi
fi
fi
if [ "$DOTAG" = "y" ]; then
if checkstatus encodetrack-$UTRACKNUM; then
if checkstatus tagtrack-$UTRACKNUM; then :; else do_tag $UTRACKNUM; fi
fi
# Lets tag the cue file
if checkstatus cleancuefile >/dev/null; then :; else
if checkstatus cuefile >/dev/null ; then
do_cleancue
fi
fi
fi
if [ "$DOMOVE" = "y" ]; then
if checkstatus tagtrack-$UTRACKNUM; then
if checkstatus movetrack-$UTRACKNUM; then :; else do_move $UTRACKNUM; fi
fi
fi
) &
done
# Go through it again and make sure there's no distmp3 stragglers, otherwise
# we'll delete the files they're working on
# Do NOT play ball if there is no ball to play (so ABORT if needed)
## FIXME ## Check also for files which are encoded using PIPEs.
if [ "$DOENCODE" = "y" ] && [ "$USEPIPES" != "y" ] && [ ! "$ABORT" ]; then
PROCEED=
until [ $PROCEED ]
do
PROCEED=y
for LOCATION in $ENCODELOCATIONS
do
CHECKTRACK="$(checkstatus encodetracklocation-$LOCATION)"
# "How can he give us a status update, if he's DEAD?"
if checkstatus encodetrack-$CHECKTRACK; then
continue
fi
# Nothing to see here please go quietly back to your homes
if [ -z "$CHECKTRACK" ]; then continue; fi
# You're still here? Maybe there is something...
if checkstatus encodetrack-$CHECKTRACK; then :; else PROCEED= ; break; fi
done
# hold up
if [ ! $PROCEED ]; then sleep 5; fi
done
fi
# If the above didn't catch the stragglers, this will
wait
if [ "$DOREPLAYGAIN" = "y" ]; then
do_replaygain
fi
# Check to see if run_command logged any errors
if [ -f "$ABCDETEMPDIR/errors" ]; then
log error "The following commands failed to run:"
cat "$ABCDETEMPDIR/errors"
# Don't clean up
DOCLEAN=n
fi
if [ "$KEEPWAVS" = "y" ];then
# Don't clean up
DOCLEAN=n
fi
# Check if we have moved all the formats we had previously encoded, if we are not using the FORCE.
if [ "$DOCLEAN" = "y" ] && [ ! "$FORCE" = "y" ]; then
ENCODED_FORMATS=$(egrep "^encodetrack-(.{3,6})-(.{1,2})$" "$ABCDETEMPDIR/status" | cut -d"-" -f2 | sort -u | tr '\n' '|')
MOVED_FORMATS=$(egrep "^movetrack-output-(.{3,6})$" "$ABCDETEMPDIR/status" | cut -d"-" -f3 | sort -u | tr '\n' '|')
if [ "$ENCODED_FORMATS" != "$MOVED_FORMATS" ]; then
log warning "The encoded formats does not match with the moved ones"
log warning "Formats encoded: $( echo $ENCODED_FORMATS | tr "|" " " )"
log warning "Formats moved: $( echo $MOVED_FORMATS | tr "|" " " )"
log warning "Use \"abcde -a clean -f -C $DISCID\" to force the removal of the remaining data."
DOCLEAN=n
fi
fi
if [ "$DOCLEAN" = "y" ]; then
# Wipe all the evidence
# Gimme gimme gimme some more time!
sleep 5
rm -rf "$ABCDETEMPDIR"
echo "Finished."
else
echo "Finished. Not cleaning $ABCDETEMPDIR."
fi
)
exit 0
# b:is_bash
# vim:tabstop=4
-------------- next part --------------
# System defaults for abcde version 2.2.x
# Nothing in this file is uncommented by default.
#
# If you wish to override these system-wide settings, create your own
# .abcde.conf file in your home directory.
# CDDB options
# If you wish to use a different CDDB server, edit this line.
# If you just wanted to use a proxy server, just set your http_proxy
# environment variable - wget will use it correctly.
#CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
#CDDBURL="http://freedb2.org:80/~cddb/cddb.cgi"
#CDDBURL="http://us.freedb.org:80/~cddb/cddb.cgi"
#CDDBURL="http://freedb2.org:80/~cddb/cddb.cgi"
CDDBURL="http://freedb.freedb.org/~cddb/cddb.cgi"
# The CDDB protocol level.
# Right now 5 is latin1 output and 6 is UTF8 encoding.
#CDDBPROTO=6
# The CDDB protocol requires hello information, including a valid username
# and hostname. If you feel paranoid about giving away such info, edit this
# line - the format is username at hostname.
#HELLOINFO="`whoami`@`hostname`"
# This controls the email address CDDB changes are submitted to.
#CDDBSUBMIT=freedb-submit at freedb.org
# The following options control whether or not fetched CDDB entries
# are cached locally in $CDDBLOCALDIR
CDDBCOPYLOCAL="y"
CDDBLOCALDIR="/home/media/music/cddb"
#CDDBLOCALRECURSIVE="y"
# If NOSUBMIT is set to y, then abcde will never prompt asking if you
# wish to submit your edited cddb file.
#NOSUBMIT=n
# If NOCDDBQUERY is set to y, then abcde will never even try to access
# the CDDB server; running abcde will automatically drop you into a
# blank cddb file to edit at your leisure. This is the same as the
# -n option. NOCDDBQUERY=y implies NOSUBMIT=y.
#NOCDDBQUERY=n
# Select here if you want to use the locally stored CDDB entries.
# This is useful if you do a lot of editing to those CDDB entries.
# Also, other tools like Grip store CDDB entries under $HOME/.cddb,
# so they can be reused when ripping CDs.
CDDBUSELOCAL="y"
# List, separated with a comma, the fields we want the parsing function to
# output. Defaults to YEAR and GENRE, for a complete list of fields provided by
# CDDB.
# The fields are not case sensitive. Actually, "y,g" will work as fine as "Y,G"
# or "YEAR, GENRE"
#SHOWCDDBFIELDS=year,genre
# Specify the style of encoder to use here -
# oggenc, vorbize - for OGGENCODERSYNTAX
# lame, gogo, bladeenc, l3enc, xingmp3enc, mp3enc - for MP3ENCODERSYNTAX
# flac - the only supported for FLACENCODERSYNTAX at the moment
# speexenc - the only encoder for SPEEXENCODERSYNTAX
# mppenc - encoder for MPPENCODERSYNTAX
# default is a valid option for oggenc, lame, flac, speexenc and mppenc.
# Currently this affects the default location of the binary, the variable
# to pick encoder command-line options from, and where the options are
# given.
#MP3ENCODERSYNTAX=default
#MP3ENCODERSYNTAX=toolame
#OGGENCODERSYNTAX=default
#FLACENCODERSYNTAX=default
#SPEEXENCODERSYNTAX=default
#MPPENCODERSYNTAX=default
#AACENCODERSYNTAX=default
# Specify the syntax of the normalize binary here - so far only 'normalize'
# is supported.
#NORMALIZERSYNTAX=default
# CD reader program to use - currently recognized options are 'cdparanoia',
# 'cdda2wav', 'dagrab', 'cddafs' (Mac OS X only) and 'flac'.
#CDROMREADERSYNTAX=cdparanoia
# CUE reader syntax for the CUE reader program to use.
# abcde supports 2 CUE modes: 'mkcue' and 'abcde.mkcue' so you can set the
# MKCUE variable accordingly. The 'abcde.mkcue' uses an internal
# implementation, without the need of an external program.
#CUEREADERSYNTAX=default
CUEREADERSYNTAX=toc2cue
# Specify the program to convert a CUE sheet back to a CD disc ID for CDDB queries.
# Select between '/path/to/cue2discid' (provided as an example) or
# 'abcde.cue2discid', implemented internaly.
CUE2DISCID=abcde.cue2discid
# Keep the wav files after encoding. Set it to "y" and remove "clean" from
# the list of default actions, since we purge the temp directory as default.
#KEEPWAVS=n
# Track padding: force abcde to pad tracks using 0, so every song uses a two
# digit entry. If set to "y", even a single song encoding outputs a file like
# 01.my_song.ext
#PADTRACKS=n
PADTRACKS=y
# Define if you want abcde to be non-interactive.
# Keep in mind that there is no way to deactivate it right now in the command
# line, so setting this option makes abcde to be always non-interactive.
#INTERACTIVE=n
# Specify 'nice'ness of the encoder, the CD reader and the distmp3 proc.
# This is a relative 'nice'ness (that is, if the parent process is at a
# nice level of 12, and the ENCNICE is set to 3, then the encoder will
# run with an absolute nice value of 15. Note also, that setting these
# to be empty will result in some default niceness increase (4 in tcsh
# and 10 using the bsdutils' nice).
#ENCNICE=10
#READNICE=10
#DISTMP3NICE=10
# Paths of programs to use
#LAME=lame
#TOOLAME=toolame
#GOGO=gogo
#BLADEENC=bladeenc
#L3ENC=l3enc
#XINGMP3ENC=xingmp3enc
#MP3ENC=mp3enc
#VORBIZE=vorbize
#OGGENC=oggenc
#FLAC=flac
#SPEEXENC=speexenc
#MPPENC=mppenc
#AACENC=faac
#ID3=id3
#ID3V2=id3v2
EYED3=eyeD3
#CDPARANOIA=cdparanoia
#CDDA2WAV=cdda2wav
#CDDAFS=cp
#CDDISCID=cd-discid
#CDDBTOOL=cddb-tool
#EJECT=eject
#MD5SUM=md5sum
#DISTMP3=distmp3
#VORBISCOMMENT=vorbiscomment
#METAFLAC=metaflac
#NORMALIZE=normalize-audio
#CDSPEED=eject
#VORBISGAIN=vorbisgain
#CDRDAO=cdrdao
#TOC2CUE=toc2cue
#TOC2CUE=toc3cue
#MKCUE=mkcue
MKCUE=abcde.mkcue
CUE2DISCID=abcde.cue2discid
#DIFF=diff
# Options to call programs with:
# If HTTPGET is modified, the HTTPGETOPTS options should also be defined
# accordingly. If HTTPGET is changed, the default options will be set,
# if HTTPGETOPTS is empty or not defined.
#HTTPGET=wget
# for fetch (FreeBSD): HTTPGETOPTS="-q -o -"
# for wget: HTTPGETOPTS="-q -O -"
# for curl (MacOSX): HTTPGETOPTS="-f -s"
#HTTPGETOPTS="-q -O -"
# MP3:
LAMEOPTS="--preset fast standard --replaygain-accurate"
#TOOLAMEOPTS=
#GOGOOPTS=
#BLADEENCOPTS=
#L3ENCOPTS=
#XINGMP3ENCOPTS=
#MP3ENCOPTS=
# Ogg:
#VORBIZEOPTS=
OGGENCOPTS="-q 5"
# FLAC:
FLACOPTS="--best -S X"
# Speex:
#SPEEXENCOPTS=
# MPP/MP+ (Musepack):
# For the encoder options take a look at the manpage. Set them like this:
# MPPENCOPTS='--xtreme' if you wish to set more options then:
# MPPENCOPTS='--xtreme --skip 20 --fade 10'
#MPPENCOPTS=
# M4A/AAC
#AACENCOPTS=
#ID3SYNTAX=eyed3
#ID3OPTS=
#ID3V2OPTS=
#EYED3OPTS="--to-v2.3"
EYED3OPTS=""
#CDPARANOIAOPTS="-O 30 --never-skip" # Plextor PX-712A = /dev/cdrom
#CDPARANOIAOPTS="-O 30 --never-skip -S 4" # Plextor PX-712A = /dev/cdrom
#CDPARANOIAOPTS="-O 48 --never-skip" # Asus DRW-1608P2 = /dev/scd0
CDPARANOIAOPTS="-O 96 --never-skip" # Pioneer DVR-XD10 = /dev/scd0
#CDDA2WAVOPTS=
#CDDAFSOPTS="-f"
#CDDBTOOLOPTS=
#EJECTOPTS=
#DISTMP3OPTS=
#NORMALIZEOPTS=
#CDSPEEDOPTS="-x"
#CDSPEEDVALUE=""
#MKCUEOPTS=""
#MKTOCOPTS=""
#DIFFOPTS=""
#VORBISCOMMENTOPTS="-R"
VORBISCOMMENTOPTS=""
#METAFLACOPTS="--no-utf8-convert"
METAFLACOPTS=""
#DIFFOPTS=""
# Actions to take
# Comma-separated list of one or more of the following:
# cddb,toc,cue,read,normalize,encode,tag,move,playlist,clean,default
# encode implies read
# normalize implies read
# tag implies cddb,read,encode
# move implies cddb,read,encode,tag
# playlist implies cddb
# An action can be added to the "default" action by specifying it along with
# "default", without having to repeat the default ones:
# ACTIONS=default,playlist
# The default action list (referenced as "default") is defined in the following
# comment:
#ACTIONS=cddb,read,encode,tag,move,clean
ACTIONS=default,normalize
# CD device you want to read from
# It can be defined as a singletrack flac file, but since it might change from
# file to file it makes little sense to define it here.
#CDROM=/dev/cdrom
CDROM=/dev/scd0
# If we are using the IDE bus, we need CDPARANOIACDROMBUS defined as "d"
# If we are using the ide-scsi emulation layer, we need to define a "g"
#CDPARANOIACDROMBUS="d"
# If you'd like to make a default location that overrides the current
# directory for putting mp3's, uncomment this.
#OUTPUTDIR=`pwd`
OUTPUTDIR=/home/media/music
# Or if you'd just like to put the temporary .wav files somewhere else
# you can specify that here
#WAVOUTPUTDIR=`pwd`
# OUTPUTTYPE can be either "ogg", "mp3", "flac" or "spx", or a combination
# of them separated with ",": "ogg,mp3".
#OUTPUTTYPE=ogg
OUTPUTTYPE="mp3"
# Output filename format - change this to reflect your inner desire to
# organize things differently than everyone else :)
# You have the following variables at your disposal:
# OUTPUT, GENRE, ALBUMFILE, ARTISTFILE, TRACKFILE, and TRACKNUM.
# Make sure to single-quote this variable. abcde will automatically create
# the directory portion of this filename.
# NOTICE: OUTPUTTYPE has been deprecated in the OUTPUTFORMAT string.
# Since multiple-output was integrated we always append the file type
# to the files. Remove it from your user defined string if you are getting
# files like ".ogg.ogg".
#OUTPUTFORMAT='${ARTISTFILE}-${ALBUMFILE}/${TRACKNUM}.${TRACKFILE}'
OUTPUTFORMAT='${OUTPUT}/$(CSSingleDir)/$(CSAlbumDir)/${TRACKNUM}.${TRACKFILE}'
# Like OUTPUTFORMAT but for Various Artists discs.
#VAOUTPUTFORMAT='Various-${ALBUMFILE}/${TRACKNUM}.${ARTISTFILE}-${TRACKFILE}'
VAOUTPUTFORMAT='${OUTPUT}/$(CSVariousDir)/$(CSAlbumDir)/${TRACKNUM}.${ARTISTFILE} - ${TRACKFILE}'
# Like OUTPUTFORMAT and VAOUTPUTFORMAT but for the ONEFILE rips.
ONETRACKOUTPUTFORMAT=$OUTPUTFORMAT
VAONETRACKOUTPUTFORMAT='${OUTPUT}/$(CSVariousDir)/$(CSAlbumDir)/${TRACKNUM}.${TRACKFILE}'
# Define how many encoders to run at once. This makes for huge speedups
# on SMP systems. Defaults to 1. Equivalent to -j.
#MAXPROCS=2
# Support for systems with low disk space:
# n: Default parallelization (read entire CD in while encoding)
# y: No parallelization (rip, encode, rip, encode...)
#LOWDISK=n
# If set to y, enables batch mode normalization, which preserves relative
# volume differences between tracks of an album.
BATCHNORM=y
# Enables nogap encoding when using the 'lame' encoder.
#NOGAP
# Set the playlist file location format. Uses the same variables and format
# as OUTPUTFORMAT. If the playlist is specified to be in a subdirectory, it
# will be created for you and the playlist will reference files from that
# subdirectory.
#PLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
PLAYLISTFORMAT='${OUTPUT}/$(CSSingleDir)/$(CSAlbumDir).${OUTPUT}.m3u'
# If you want to prefix every filename in a playlist with an arbitrary
# string (such as 'http://you/yourstuff/'), use this option
#PLAYLISTDATAPREFIX=''
#Like PLAYLIST{FORMAT,DATAPREFIX} but for Various Artists discs:
#VAPLAYLISTFORMAT='${ARTISTFILE}-${ALBUMFILE}.${OUTPUT}.m3u'
VAPLAYLISTFORMAT='${OUTPUT}/$(CSVariousDir)/$(CSAlbumDir).${OUTPUT}.m3u'
#VAPLAYLISTDATAPREFIX=''
#This will give the playlist CR-LF line-endings, if set to "y".
#(some hardware players insist on CR-LF line-endings)
#DOSPLAYLIST=n
# Custom filename munging:
# By default, abcde will do the following to CDDB data to get a useful
# filename:
# * Translate colons to a space and a dash for Windows compatibility
# * Eat control characters, single quotes, and question marks
# * Translate spaces and forward slashes to underscores
# * Translate stars into pluses.
# To change that, redefine the mungefilename function.
# mungefilename receives the CDDB data (artist, track, title, whatever)
# as $1 and outputs it on stdout.
mungefilename ()
{
# echo "$@" | sed s,:,\ -,g | tr \ /\* __+ | tr -d \'\"\?\[:cntrl:\]
echo "$@" | sed s,:,\ -,g | tr /\*\<\> _+__ | tr -d \"\?\[:cntrl:\]
}
# Custom genre munging:
# By default we just transform uppercase to lowercase. Not much of a fancy
# function, with not much use, but one can disable it or just turn the first
# Uppercase.
#mungegenre ()
#{
# echo $CDGENRE | tr "[:upper:]" "[:lower:]"
#}
# CHARLES STEINKUEHLER
# Custom function to put some genres (Single Artist) in their own directory
CSArtist ()
{
local ARTIST="$1"
# Remove leading "The ", if present
ARTIST="${ARTIST#The }"
# Remove trailing period, if present (confuses windows clients!)
ARTIST="${ARTIST%.}"
echo "$ARTIST"
}
# CHARLES STEINKUEHLER
# Custom function to put some genres (Single Artist) in their own directory
CSSingleDir ()
{
local ARTISTDIR=$(CSArtist "$ARTISTFILE")
case ${GENRE} in
soundtrack) echo Soundtracks ;;
holiday|christmas)
echo "Holiday/${ARTISTDIR}" ;;
classical) echo "Classical/${ARTISTDIR}" ;;
child*) echo "Children/${ARTISTDIR}" ;;
book*) echo "Books/${ARTISTDIR}" ;;
*) echo "${ARTISTDIR}" ;;
esac
}
# CHARLES STEINKUEHLER
# Custom function to put some genres (Various Artists) in their own directory
CSVariousDir ()
{
case ${GENRE} in
soundtrack) echo Soundtracks ;;
holiday|christmas)
echo Holiday/Various ;;
classical) echo "Classical/Various" ;;
child*) echo "Children/Various" ;;
book*) echo "Books/Various" ;;
*) echo Various ;;
esac
}
# CHARLES STEINKUEHLER
# Custom function to put some genres (Various Artists) in their own directory
CSAlbumDir ()
{
local ALBUM="${ALBUMFILE}"
# Remove trailing period, if present (confuses windows clients!)
ALBUM="${ALBUM%.}"
echo "$ALBUM"
}
# Custom pre-read function
# By default it does nothing.
# You can set some things to get abcde function in better ways:
# * Close the CD tray using eject -t (if available in eject and supported by
# your CD device.
# * Set the CD speed. You can also use the built-in options, but you can also
# set it here. In Debian, eject -x and cdset -x do the job.
# KEEP IN MIND that executables included in pre_read must be in your $PATH or
# you have to define them with full /path/to/binary
# Uncomment and substitute the ":" with your commands.
#pre_read ()
#{
#:
#}
# Custom post-read function
# By default it does nothing.
# You can set some things to get abcde function in better ways:
# * Store a copy of the CD TOC.
# KEEP IN MIND that executables included in post_read must be in your $PATH or
# you have to define them with full /path/to/binary
# Uncomment and substitute the ":" with your commands.
#post_read ()
#{
#:
#}
# If you'd like to have abcde eject the cdrom after all the tracks have been
# read, uncomment the following line.
#EJECTCD=y
EJECTCD=y
# To encode on the remote machines foo, bar, baz, quux, and qiix, as well as
# on the local machine (requires distmp3 to be installed on local machine and
# distmp3host to be installed and running on all remote machines - see README)
#REMOTEHOSTS=foo,bar,baz,quux,qiix
# Set to obtain some information about actions happening in the background
# Useful if you have a slow network or CDDB servers seem unresponsive.
#EXTRAVERBOSE=n
-------------- next part --------------
#/bin/bash
read_opts ()
{
# Load system defaults
if [ -r /etc/abcde.conf ]; then
. /etc/abcde.conf
fi
# Load user preference defaults
if [ -r $HOME/.abcde.conf ]; then
. $HOME/.abcde.conf
fi
# If the CDROM has not been set yet, find a suitable one.
# If this is a devfs system, default to /dev/cdroms/cdrom0
# instead of /dev/cdrom
if [ "$CDROM" = "" ] ; then
if [ -e /dev/cdroms/cdrom0 ]; then
CDROM=/dev/cdroms/cdrom0
elif [ -e /dev/cdrom ]; then
CDROM=/dev/cdrom
elif [ -e /dev/cd0c ]; then
CDROM=/dev/cd0c
elif [ -e /dev/acd0c ]; then
CDROM=/dev/acd0c
elif [ -e /dev/disk1 ]; then
CDROM=/dev/disk1
fi
fi
while getopts :c:d: opt ; do
case "$opt" in
c) if [ -e "$OPTARG" ] ; then . "$OPTARG" ; else log error "config file \"$OPTARG\" cannot be found." ; exit 1 ; fi ;;
d) CDROM="$OPTARG" ;;
?) ;;
esac
done
}
# Fincd CDROM Device:
read_opts "$@"
# Make sure CD is in the drive
eject -t "$CDROM"
# Rip the CD
abcde -1 -a default,cue -o flac -t 0 -V "$@"
# Beep when we're done...
echo -e \\007
-------------- next part --------------
#/bin/bash
FLACDIR=`dirname "$1"`
BASE=`basename "$1"`
OPTS=""
case "$BASE"
in
00\.*)
;;
[1-9]00\.*)
OPTS="-W ${BASE:0:1}"
;;
*) echo ERROR!!! Unknown flac file index! "$BASE" >&2
;;
esac
if [ -r "$FLACDIR/abcde.opts" ] ; then
abcde $OPTS -d "$@" `cat "$FLACDIR/abcde.opts"`
else
abcde $OPTS -d "$@"
fi
More information about the Abcde-users
mailing list