#!/bin/sh
# Copyright (c) 1998,1999 Robert Woodcock <rcw@debian.org>
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

VERSION=0.6

# Command line options:
# -e	Edit CDDB info before continuing
# -d    CDROM device
# [0-x] Track numbers to encode (no wildcard support yet)

function usage ()
{
echo "This is cdgrab v$VERSION."
echo "Usage: cdgrab [options] [tracks]"
echo "Options:"
echo "-d    Specify CDROM device to grab"
echo "-e    Edit returned CDDB information before using"
echo "-h    This help information"
echo "Tracks is a space-delimited list of tracks to grab."
echo "No wildcards accepted yet."
}

# Builtin defaults
CDDBURL="http://cddb.cddb.com/~cddb/cddb.cgi"
HELLOINFO="`whoami`+`hostname`+cdgrab+$VERSION"
CDROM=/dev/cdrom
CDROMREADERSYNTAX=cdparanoia
ENCODERSYNTAX=lamer
OUTPUTFORMAT='${ARTISTFILE}/${TRACKFILE}.mp3'

# program paths - defaults to checking your path
LAMER=lamer
BLADEENC=bladeenc
L3ENC=l3enc
ID3=id3
CDPARANOIA=cdparanoia
CDDA2WAV=cdda2wav
WGET=wget
CDDISCID=cd-discid

# Options for programs called from cdgrab
LAMEROPTS=
BLADEENCOPTS=
L3ENCOPTS=
ID3OPTS=
CDPARANOIAOPTS=
CDDA2WAVOPTS=
WGETOPTS=

if [ "$OUTPUTDIR" = "" ]; then
	OUTPUTDIR=`pwd`
fi
# Load system defaults
if [ -r /etc/cdgrab.conf ]; then
	. /etc/cdgrab.conf
fi
# Load user preference defaults
if [ -r $HOME/.cdgrab.conf ]; then
	. $HOME/.cdgrab.conf
fi

# Parse command line options
while getopts d:eh opt ; do
	case "$opt" in
		d) CDROM="$OPTARG" ;;
		e) EDITCDDB="y" ;;
		h) usage; exit ;;
	esac
done

shift $(($OPTIND - 1))

while [ $# -gt 0 ]; do
	TRACKQUEUE=`echo "$TRACKQUEUE" $1`
	shift
done

# Decide which CDROM reader we're gonna use
case "$CDROMREADERSYNTAX" in
	cdparanoia) CDROMREADER="$CDPARANOIA $CDPARANOIAOPTS" ;;
	cdda2wav) CDROMREADER="$CDDA2WAV $CDDA2WAVOPTS" ;;
esac

# and which encoder
case "$ENCODERSYNTAX" in
	lamer) ENCODER="$LAMER $LAMEROPTS" ;;
	bladeenc) ENCODER="$BLADEENC $BLADEENCOPTS" ;;
	l3enc) ENCODER="$L3ENC $L3ENCOPTS" ;;
esac
	
# Make sure a buncha things exist
for X in $CDROMREADER $CDDISCID $ID3 $ENCODER $WGET
do
	# Cut off the command-line options we just added in
	X=`echo $X | cut -d' ' -f2`
	if [ "`which $X`" = "" ]; then
		echo "cdgrab error: $X is not in your path."
		exit 1
	elif [ \! -x `which $X` ]; then
		echo "cdgrab error: $X is not executable."
		exit 1
	fi 
done

# Query the CD to get the track info
echo -n "Getting CD track info... "
TRACKINFO=`$CDDISCID $CDROM`

# Make sure there's a CD in there by checking cd-discid's return code
if [ "$?" = "1" ]; then
	echo "cdgrab error: CD could not be read. Perhaps there's no CD in the drive?"
	exit 1
fi

# Get a full enumeration of tracks, sort it, and put it in the TRACKQUEUE.

TRACKS=`echo $TRACKINFO | cut -f2 -d' '`

if [ "$TRACKQUEUE" = "" ]; then
	echo -n "Grabbing entire CD - tracks: "
	X=0
	while [ "$X" != "$TRACKS" ]
	do
		X=`expr $X + 1`
		TRACKQUEUE=`echo "$TRACKQUEUE" $X`
	done
	echo $TRACKQUEUE
else
	TRACKQUEUE=`(for X in $TRACKQUEUE; do echo $X; done) | sort | uniq | xargs`
	echo Grabbing tracks: "$TRACKQUEUE"
fi

# TRACKQUEUE has now been sorted - get the last variable in the list
for X in $TRACKQUEUE; do :; done
# get the number of digits to pad TRACKNUM with - we'll use this down below
TRACKNUMPADDING=`echo -n $X | wc -c | xargs`
TRACKINFOPLUS=`echo $TRACKINFO | sed 's/ /+/g'`
echo -n "Looking up CD name.."
# Make CDDB query - protocol level = 4
CDINFO=`$WGET $WGETOPTS -O - "$CDDBURL?cmd=cddb+query+$TRACKINFOPLUS\&hello=$HELLOINFO\&proto=4" 2>/dev/null`
echo -n ".."
RESPONSECODE=`echo $CDINFO | cut -f1 -d' '`
# Deal with inexact or multiple exact matches here
# RESPONSECODE contains CDDB response code
# need to set CDINFO to <responsecode> <genre> <discid> <artist> / <albumtitle>
if [ $RESPONSECODE -gt 200 ]; then
	echo " Inexact or multiple matches found, please select one."
	CDCHOICES=`echo "$CDINFO" | tail +2 | grep -v ^[.]`
	NUMCDCHOICES=`echo "$CDCHOICES" | wc -l | xargs`
	echo "Number of CD choices: $NUMCDCHOICES"
	X=0
	while [ "$X" != "$NUMCDCHOICES" ]
	do
		X=`expr $X + 1`
		echo $X: `echo "$CDCHOICES" | head -$X | tail -1`
	done
	echo -n "Selection [1-$NUMCDCHOICES]: "
	read CDCHOICE
	# Make sure we get a valid choice
	CDCHOICENUM=`echo $CDCHOICE | xargs printf %d 2>/dev/null`
	while [ $CDCHOICENUM -lt 1 ] || [ $CDCHOICENUM -gt $NUMCDCHOICES ]
	do
		echo "Invalid selection. Please choose a number between 1 and $NUMCDCHOICES."
		echo -n "Selection [1-$NUMCDCHOICES]: "
		read CDCHOICE
		CDCHOICENUM=`echo $CDCHOICE | xargs printf %d 2>/dev/null`
	done
	# Selection is valid, use it
	CDINFO=`echo "200 $CDCHOICES" | head -$X | tail -1`
	echo Selected: $CDINFO
fi
CDDBGENRE=`echo $CDINFO | cut -f2 -d' '`
DISCID=`echo $CDINFO | cut -f3 -d' '`
# Create a tempfile
CDDBDATA=`mktemp $OUTPUTDIR/cdgrab.XXXXXX` || exit 1
# Make CDDB read - protocol level = 4
wget -O $CDDBDATA "$CDDBURL?cmd=cddb+read+$CDDBGENRE+$DISCID\&hello=$HELLOINFO\&proto=4" 2>/dev/null
echo ". done."
RESPONSECODE=`cat $CDDBDATA | head -1 | cut -f1 -d' '`
if [ $RESPONSECODE -gt 399 ]; then
	echo "cdgrab: CDDB error: `cat $CDDBDATA | head -1`"
	rm -f $CDDBDATA
	exit 1
fi
# Let user edit CDDB data if they requested such a thing
if [ "$EDITCDDB" = "y" ]; then
	# Try to load the preferred editor, starting with their
	# EDITOR variable
	if [ -x "$EDITOR" ]; then
		$EDITOR $CDDBDATA
	# If that fails, check for a vi
	elif [ -x /usr/bin/vi ]; then
		/usr/bin/vi $CDDBDATA
	# ae should be on all debian systems
	elif [ -x /bin/ae ]; then
		/bin/ae $CDDBDATA
	# bomb out
	else
		echo "No editor available. Check your EDITOR environment variable."
		exit 1
	fi
	# delete editor backup file if it exists
	if [ -w $CDDBDATA~ ]; then
		rm -f $CDDBDATA~
	fi
fi
# Get Artist and Album info from the CDDB response
DARTISTALBUM="`grep ^DTITLE= $CDDBDATA | cut -f2 -d= | sed 's- / -~-g'`"
DARTIST=`echo $DARTISTALBUM | cut -f1 -d~`
DALBUM=`echo $DARTISTALBUM | cut -f2 -d~ | tr -d \[:cntrl:\]`
echo Title: $DALBUM
echo Artist: $DARTIST
ARTISTFILE=`echo $DARTIST | tr \ / __ | tr -d \'\? | tr -d \[:cntrl:\]`
ALBUMFILE=`echo $DALBUM | tr \ / __ | tr -d \'\? | tr -d \[:cntrl:\]`
TRACKNAME=foo
OUTPUTFILE=`eval echo $OUTPUTFORMAT`
if [ \! -e `dirname $OUTPUTDIR/$OUTPUTFILE` ]; then
	mkdir -p `dirname $OUTPUTDIR/$OUTPUTFILE`;
fi
# Go through the tracks and list them all
# UTRACKNUM is the un-0-padded tracknum counter
for UTRACKNUM in $TRACKQUEUE
do
	CDDBTRACKNUM=`expr $UTRACKNUM - 1`
	TRACKNAME=`grep ^TTITLE$CDDBTRACKNUM= $CDDBDATA | cut -f2 -d= | tr -d \[:cntrl:\]`
	echo Track $TRACKNUM: $TRACKNAME
done
# Start ripping
for UTRACKNUM in $TRACKQUEUE
do
	TRACKNUM=`printf %0.${TRACKNUMPADDING}d ${UTRACKNUM}`
	CDDBTRACKNUM=`expr $UTRACKNUM - 1`
	TRACKNAME=`grep ^TTITLE$CDDBTRACKNUM= $CDDBDATA | cut -f2 -d= | tr -d \[:cntrl:\]`
	TRACKFILE=`echo $TRACKNAME | sed 's- -_-g' | tr -d \'\?/`
	echo "Grabbing track $UTRACKNUM: $TRACKNAME..."
	WAVDATA=`mktemp -u $OUTPUTDIR/cdgrab.currenttrack.XXXXXX`.wav || exit 1
	case "$CDROMREADERSYNTAX" in
		cdparanoia) $CDPARANOIA -d $CDROM -w $UTRACKNUM $WAVDATA ;;
		cdda2wav) $CDDA2WAV -D $CDROM -t $UTRACKNUM $WAVDATA ;;
	esac
	echo "Encoding track $UTRACKNUM: $TRACKNAME..."
	OUTPUTFILE=`eval echo $OUTPUTFORMAT`
	$ENCODER "$WAVDATA" "$OUTPUTDIR/$OUTPUTFILE"
	rm -f "$WAVDATA"
	echo "Tagging track $UTRACKNUM: $TRACKNAME..."
	$ID3 $ID3OPTS -A "$DALBUM" -a "$DARTIST" -t "$TRACKNAME" "$OUTPUTDIR/$OUTPUTFILE"
done

echo
echo "Finished."
rm -f $CDDBDATA
