#!/bin/sh

# jukebox - http://raf.org/jukebox/
#
# Copyright (C) 2002 raf <raf@raf.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# 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
# or visit http://www.gnu.org/copyleft/gpl.html

# rip - read an audio cd to wav/mp3/ogg/flac... files and create a tocfile
#
# 20021208 raf <raf@raf.org>

# Set defaults and load configuration

cdr_rdev="0,0,0"
cdrd_spd="40"
cdr_rip="cdparanoia"
wav_enc="bladeenc"
enc_bits="192"
juke_toc='00*.toc'
juke_root="/mnt/music"
juke_names="simple"

[ -r /etc/jukebox.conf ] && . /etc/jukebox.conf
[ -r ~/.jukeboxrc ] && . ~/.jukeboxrc

help()
{
	name="`basename $0`"
	echo "NAME"
	echo
	echo "$name - read an audio cd to wav/mp3/ogg/flac... files and create a tocfile"
	echo
	echo "SYNOPSIS"
	echo
	echo "  $name [options] artist-name/album-title"
	echo "  options:"
	echo "    -h, --help         - Show the help message then exit"
	echo "    -V, --version      - Show the version message then exit"
	echo
	echo "    -n, --norip        - Do not read CD (tracks already present)"
	echo "    -w, --wav          - Leave in wav format (do not encode)"
	echo "    -k, --keep         - Keep the wav files (after encoding)"
	echo "    -t, --notoc        - Do not ask to create a tocfile"
	echo "    -e, --noedit       - Do not ask to edit the tocfile"
	echo "    -m, --noname       - Do not ask to name the track files"
	echo "    -g, --notag        - Do not ask to tag the track files"
	echo
	echo "    -C, --cdda2wav     - Read CD with cdda2wav"
	echo "    -P, --cdparanoia   - Read CD with cdparanoia"
	echo "    -R, --reader cmd   - Read CD with arbitrary \"cmd\""
	echo
	echo "    -L, --lame         - Encode as mp3 with lame (lossy)"
	echo "    -N, --notlame      - Encode as mp3 with notlame (lossy)"
	echo "    -G, --gogo         - Encode as mp3 with gogo (lossy, fast)"
	echo "    -B, --bladeenc     - Encode as mp3 with bladeenc (lossy)"
	echo "    -O, --oggenc       - Encode as ogg with oggenc (lossy, smart)"
	echo "    -F, --flac         - Encode as flac with flac (lossless)"
	echo "    -E, --encoder cmd  - Encode with arbitrary \"cmd\""
	echo
	echo "    -2, --2args fmt    - The -E cmd takes in.wav and out.fmt (not *.wav)"
	echo "    -b, --bitrate kbps - Override default bitrate ($enc_bits)"
	echo "    -r, --root dir     - Override default music directory ($juke_root)"
	echo
	echo "DESCRIPTION"
	echo
	echo "$name reads an audio cd (unless -n) into wav files and then encodes"
	echo "the wav files into a smaller format such as mp3, ogg or flac (unless -w)."
	echo "The default reader and encoder programs to use and the default encoding"
	echo "bitrate are specified in /etc/jukebox.conf. The -C, -P and -R options"
	echo "override the default reader. The -L, -N, -G, -B, -O, -F and -E options"
	echo "override the default encoder. The -b option overrides the default bitrate"
	echo "(unless -E). After encoding the tracks, the wav files are removed (unless -k)."
	echo
	echo "If an encoder specified with the -E command takes lame-style arguments"
	echo "(i.e. \"in.wav\" and \"out.mp3\" rather than just \"*.wav\") then use"
	echo "the -2 option whose argument specifies the suffix for the output files."
	echo
	echo "The argument is the directory in which to place the track files."
	echo "This directory is interpreted as being relative to the first directory"
	echo "listed in the juke_root variable in /etc/jukebox.conf. This is $juke_root"
	echo "by default. It can be overridden with the -r option. It is expected that"
	echo "the directory argument will comprise two parts. The top level is the"
	echo "artist directory and the level below that is the album directory. This"
	echo "isn't strictly necessary, though. If a directory is not specified, the"
	echo "track files are placed in the current directory."
	echo
	echo "After reading the tracks but before encoding them, $name asks if you want"
	echo "to create a table of contents file (unless -t). If so, rip asks if you want"
	echo "to retrieve cddb information from freedb.org. If so, the tocfile is populated"
	echo "with this information. Finally, you can check/categorise the tocfile using"
	echo "\$EDITOR or /bin/vi (unless -e). The tocfile is called something like"
	echo "\"00-<artist>-<title>.toc\" (based on the juke_toc variable in /etc/jukebox.conf)."
	echo
	echo "After creating the table of contents and encoding the track files,"
	echo "rip asks if you want to name the track files (unless -m) to something"
	echo "more descriptive than that which results from cd reader software"
	echo "(i.e. track##.cdda.mp3 or audio_##.mp3). If so, toc2names uses the"
	echo "table of contents to provide suggestions for all track names but the"
	echo "user must confirm or override each suggestion."
	echo
	echo "After naming track files, rip asks if you want to tag the files (unless -g)."
	echo "If so, toc2tags uses the table of contents to supply the tag information."
	echo "The genre is taken to be the first word in the \"Jukebox:\" header which"
	echo "should be the category obtained via cddb. The only formats that can be"
	echo "tagged are mp3, ogg and flac."
	echo
	echo "EXAMPLES"
	echo
	echo "Rip a CD for use by the jukebox"
	echo
	echo "  rip janis-joplin/cheap-thrills"
	echo
	echo "Rip a CD to the current directory, leaving in wav format"
	echo
	echo "  rip -w"
	echo
	echo "Rip a CD to the current directory, encoding to the default format"
	echo
	echo "  rip"
	echo
	echo "FILES"
	echo
	echo "  /etc/jukebox.conf - System wide configuration file"
	echo "  ~/.jukeboxrc      - User specific configuration file"
	echo
	echo "SEE ALSO"
	echo
	echo "  rip(1), riptrack(1), mktoc(1), toc2names(1), toc2tags(1),"
	echo "  cdr(1), cdrw(1), burn(1), burnw(1), cdbackup(1), mp3backup(1),"
	echo "  jukebox(1), jukeboxc(1), jukeboxc.jar(1), jukeboxd(8),"
	echo "  jukeboxd-init.d(8), jukebox.conf(5),"
	echo "  http://raf.org/jukebox/Jukebox-HOWTO"
	echo
	echo "AUTHOR"
	echo
	echo "raf <raf@raf.org>"
	echo
	exit 0
}

version() { echo "rip-0.1"; exit 0; }
die() { echo "`basename $0`: $@" >&2; exit 1; }

# Check the arguments

getopt -T >&- 2>&- || eval set -- `getopt -q -o hVr:nwktemgCPR:LNGBOFE:2:b: -l help,version,root:,norip,wav,keep,notoc,noedit,noname,notag,cdda2wav,cdparanoia,reader:,lame,notlame,gogo,bladeenc,oggenc,flac,encoder:,2args:,bitrate: -- "$@"`

root="$juke_root"
rip="yes"
enc="yes"
args="many"
fmt="mp3"
rm="yes"
toc="yes"
edit="yes"
name="yes"
tag="yes"
dir=""

while :
do
	case "$1" in
		-h|--help) help;;
		-V|--version) version;;
		-r|--root) shift; root="$1";;
		-n|--norip) rip="no";;
		-w|--wav) enc="no"; tag="no";;
		-k|--keep) rm="no";;
		-t|--notoc) toc="no";;
		-e|--noedit) edit="no";;
		-m|--noname) name="no";;
		-g|--notag) tag="no";;
		-C|--cdda2wav) cdr_rip="cdda2wav";;
		-P|--cdparanoia) cdr_rip="cdparanoia";;
		-R|--reader) shift; cdr_rip="$1";;
		-L|--lame) wav_enc="lame";;
		-N|--notlame) wav_enc="notlame";;
		-G|--gogo) wav_enc="gogo";;
		-B|--bladeenc) wav_enc="bladeenc";;
		-O|--oggenc) wav_enc="oggenc";;
		-F|--flac) wav_enc="flac";;
		-E|--encoder) shift; wav_enc="$1";;
		-2|--2args) shift; fmt="$1"; args="two";;
		-b|--bitrate) shift; enc_bits="$1";;
		-[^-]*) die "Invalid option: $1 (Note: options can't be combined on this system)";;
		--?*) die "Invalid option: $1";;
		--) ;;
		*) dir="$1"; break;;
	esac
	shift
done

[ -n "$root" ] && root="`echo $root | sed 's/[,: ].*$//'`"
[ -n "$root" -a ! -d "$root" ] && die "$root is not a directory"
[ -n "$root" -a ! -w "$root" ] && die "$root is not writable"
[ -z "$dir" -a ! -w "." ] && die "The current directory is not writable"
[ "$rip" = "no" -a "$toc" = "no" -a "$enc" = "no" ] && die "Nothing to do"

# Create directory in which to place track files and tocfile

if [ x"$dir" != "x" ];
then
	album="${root:+$root/}$dir"

	if [ ! -d "$album" ]
	then
		mkdir -p "$album" || die "Failed to mkdir $album"
	fi

	cd "$album" || die "Failed to cd $album"
fi

# Prepare the command arguments

case "$cdr_rip" in
	cdda2wav)   rip_args="-B -O wav -D $cdr_rdev -S $cdrd_spd";;
	cdparanoia) rip_args="-B -w -S $cdrd_spd";;
esac

case "$wav_enc" in
	lame|notlame|gogo) wav_enc_args="-b $enc_bits"; args="two";;
	bladeenc)          wav_enc_args="-br $enc_bits"; args="many";;
	oggenc)            wav_enc_args="--bitrate $enc_bits"; args="many";;
	flac)              wav_enc_args="-V8"; args="many";;
esac

# Read the cd into wav files

do_rip()
{
	[ -z "$cdr_rip" ] && die "Reader software not specified"
	$cdr_rip $rip_args
	rm -f *.inf
}

# Encode as mp3/ogg/flac...

do_encode()
{
	[ -z "$wav_enc" ] && die "Encoder software not specified"
	case "$args" in
		many)
			$wav_enc $wav_enc_args *.wav && [ "$rm" = "yes" ] && rm -f *.wav
			;;

		two)
			for infile in *.wav
			do
				outfile="`echo $infile | sed 's/\.wav$//'`.$fmt"
				$wav_enc $wav_enc_args "$infile" "$outfile" && [ "$rm" = "yes" ] && rm -f "$infile"
			done
			;;
	esac
}

# Ask the user a question (default to 'y')

ask()
{
	echo -n "$1 ([y]/n): "
	read response
	[ x"$response" != "xn" ]
}

# Create a table of contents

do_mktoc()
{
	if ask "Create a TOC file?"
	then
		eval `perl -e '
			my ($dir, $style, $tocfile) = @ARGV;
			my ($artist) = $dir =~ /^([^\/]+)/;
			my ($album) = $dir =~ /([^\/]+)$/;
			my $prefix = ($style eq "complex") ? " " : "-";
			my $a = (defined $artist) ? "$prefix$artist" : "";
			my $t = (defined $album) ? "$prefix$album" : "";
			$tocfile =~ s/\*/$a$t/;
			$artist =~ s/^([a-z])/\U$1/; $artist =~ s/-([a-z])/-\U$1/g; $artist =~ s/-/ /g;
			$album =~ s/^([a-z])/\U$1/; $album =~ s/-([a-z])/-\U$1/g; $album =~ s/-/ /g;
			print "tocfile=\"$tocfile\";\n";
			print "artist=\"$artist\";\n";
			print "album=\"$album\";\n";
		' "$dir" "$juke_names" "$juke_toc"`
		mktoc -t "$tocfile" "$artist" "$album"
		[ "$edit" = "yes" ] && do_edit
	fi
}

# Edit the table of contents

do_edit()
{
	ask "Edit the toc file?" && "${EDITOR:-/bin/vi}" "$tocfile"
}

# Name the track files

do_toc2names()
{
	ask "Name track files?" && toc2names
}

# Tag the track files

do_toc2tags()
{
	ask "Tag the track files?" && toc2tags
}

# Rip/encode an audio CD, make/edit a tocfile, name/tag the track files

[ "$rip" = "yes" ] && do_rip
[ "$toc" = "yes" ] && do_mktoc
[ "$enc" = "yes" ] && do_encode
[ "`ls -1 $juke_toc 2>&-`" = "" ] && exit 0
[ "$name" = "yes" ] && do_toc2names
[ "$tag" = "yes" ] && do_toc2tags

# vi:set ts=4 sw=4
