#!/usr/bin/perl
#
#NAME
#  CDsortTOC - process cddb track list
#
#SYNOPSIS
#  CDsortTOC [file]..
#
#DESCRIPTION
#  This processes a list of tracks from a CD, as produced by cddb. We can also
#  spot  the track*.wav files produced by cdparanoia, and convert them to MP3.
#  But the main purpose of this program is to generate an HTML file that lists
#  the tracks in a nice, neat <table> form.
#
#  The input (file or stdin) has the following format:
#
#artist: [name of band or musician(s)]
#title: [CD's title]
#category: misc
#cddbid: 12345678
#trackno: 17
#track  1: Track title
#track  2: Track title
#track  3: Track title
#...
#
#
#OPTIONS
#  We use '+' to mean "on" and '-' to mean "off"; either may be  the  default.
#  "Name"  means  the  basename  of  the  file,  derived from the title.  Thus
#  "Name.mp3" for a tune "Joe's Jig" would be "JoesJig.mp3".
#
#  -abc
#  +abc
#   Produce an "ABC" column with 
#
#  -html
#  +html
#
#  -mp3
#  +mp3
#
#  -ndx
#  +ndx
#
#  -wav
#  +wav
#
#  -words
#  +words
#
#EXAMPLES
#
#FILES
#
#BUGS
#
#SEE ALSO
#
#AUTHOR
#  John Chambers <jc@trillian.mit.edu>
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

$| = 1;
($P = $0) =~ s".*/"";
$V = $ENV{"V_$P"} || 1;
$exitstat = 0;
$htmlfile = "tracklist.html";
$lnks = 1;
$ttlopt = 1;
$timopt = 1;

for $arg (@ARGV) {
	++$args;
	if (($flg,$opt) = ($arg =~ /^([-+])(.*)/)) {
		$o = lc($opt);
		if ($o eq 'all') {
			print "$P: Writing everything:\n" if $V>0;
			&allopts();
		} elsif ($o eq 'html') {
			++$opts; ++$htmlopt;
			print "$P: Writing HTML.\n" if $V>0;
		} elsif ($o eq 'mp3') {
			++$opts; ++$mp3opt; ++$lnks;
			print "$P: Writing MP3.\n" if $V>0;
		} elsif ($o eq 'wav') {
			++$opts; ++$wavopt; ++$lnks;
			print "$P: Linking WAV.\n" if $V>0;
		} elsif ($o eq 'abc') {
			++$opts; ++$abcopt; ++$lnks;
			print "$P: Linking ABC.\n" if $V>0;
		} elsif ($o eq 'ndx') {
			++$opts; ++$ndxopt; ++$lnks;
			print "$P: Linking Index.\n" if $V>0;
		} elsif ($o eq 'words') {
			++$opts; ++$wrdopt; ++$lnks;
			print "$P: Linking Words.\n" if $V>0;
		} else {
			print STDERR "$P: Unknown option \"$opt\" ignored.\n";
		}
	} elsif (-f $arg) {
		++$files;
		unless (open(F,$arg)) {
			print STDERR "$P: Can't read \"$arg\" ($!)\n";
			next;
		}
		while ($line = <F>) {
			&onetrack($line);
		}
		close F;
	} else {
		print STDERR "$P: Unknown arg \"$arg\" ignored.\n";
	}
}
unless ($files) {
	while ($line = <STDIN>) {
		&onetrack($line);
	}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Generate the WAV output.

if ($wavopt) {
	writeWAVs();
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Generate the MP3 output.

if ($mp3opt) {
	writeMP3s();
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# Generate the HTML output.

if ($htmlopt) {
	if (open(HTML,">$htmlfile")) {
		print "$P: Writing \"$htmlfile\"\n" if $V>1;
		writeHTML();
	} else {
		print STDERR "$P: Can't write \"$htmlfile\" ($!)\n" if $V>1;
	}
}

exit $exitstat; 
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub allopts {
	++$htmlopt;
	print "$P: Writing HTML.\n" if $V>1;
	++$mp3opt;
	print "$P: Writing MP3.\n" if $V>1;
	++$wavopt;
	print "$P: Linking WAV.\n" if $V>1;
	++$abcopt;
	print "$P: Linking ABC.\n" if $V>1;
	++$ndxopt;
	print "$P: Linking Index.\n" if $V>1;
	++$wrdopt;
	print "$P: Linking Words.\n" if $V>1;
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub writeHTML {
	local($t,$eng,$ndx,$pth,$tim,$nam,$src,$ttl,$wavnam);
	print "$P: Writing \"$htmlfile\"\n" if $V>0;
	print HTML "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n";
	print HTML "<html>\n";
	print HTML "<head>\n";
	if ($ttl = $Hdr{'title'}) {
		print HTML "<title>$ttl</title>\n";
	} else {
		print HTML "<title>___ ___ ___</title>\n";
	}
	print HTML "</head>\n";
	print HTML "<body>\n";
	if ($ttl) {
		print HTML "<center><H1>$ttl</H1></center>\n";
	} else {
		print HTML "<center><H1>___ ___ ___</H1></center>\n";
	}
	if ($artist = $Hdr{'artist'}) {
		print HTML "<center><b>by $artist</b></center>\n";
	}
	print HTML "<hr>\n";
	print HTML "<table border>\n";
	for ($t = 0; $t <= $maxtrack; $t++) {
		next unless $Ndx[$t];
		$ndx = $Ndx[$t];	# Track index number
		$pth = $Pth[$t];	# Track path
		$tim = $Tim[$t] || '?:??';	# Track time
		$nam = $Nam[$t];	# Track name
		$ttl = $Ttl[$t];	# Track title
		$eng = $Eng[$t];	# English title
		$src = $Src[$t];	# Source info
		$wavnam = $wavopt ? "$nam.wav" : $pth;
		print HTML "\t<tr>\n";		# Row 1: files, title
		$lnks = 0;
		if ($ndxopt) {	# Index
			print HTML "\t\t<th>\n";
			print HTML "\t\t\t$ndx\n";
			print HTML "\t\t</th>\n";
			++$lnks;
		}
		if ($wavopt) {	# WAV
			print HTML "\t\t<td>\n";
			print HTML "\t\t\t<a href='$wavnam'>WAV</a>\n";
			print HTML "\t\t</td>\n";
			++$lnks;
		}
		if ($mp3opt) {	# MP3
			print HTML "\t\t<td>\n";
			print HTML "\t\t\t<a href='$nam.mp3'>MP3</a>\n";
			print HTML "\t\t</td>\n";
			++$lnks;
		}
		if ($abcopt) {	# ABC
			print HTML "\t\t<td>\n";
			print HTML "\t\t\t<a href='$nam.abc'>ABC</a>\n";
			print HTML "\t\t</td>\n";
			++$lnks;
		}
		if ($wrdopt) {	# Words
			print HTML "\t\t<td>\n";
			print HTML "\t\t\t<a href='$nam.txt'>Words</a>\n";
			print HTML "\t\t</td>\n";
			++$lnks;
		}
#		if ($ttlopt) {	# Title
#			print HTML "\t\t<td>\n";
#			print HTML "\t\t\t$ttl\n";
#			print HTML "\t\t</td>\n";
#		}
		if ($timopt) {	# Time
			print HTML "\t\t<td align=right>\n";
			print HTML "\t\t\t$tim\n";
			print HTML "\t\t</td>\n";
		}
		print HTML "\t</tr>\n";
		print HTML "\t<tr>\n";		# Row 2: Space for text
		print HTML "\t\t<td></td>\n";
		print HTML "\t\t</td>\n";
		print HTML "\t\t<td>\n";
		print HTML "\t\t\t$ttl<br>\n" if $ttl;
		print HTML "\t\t\t$eng<br>\n" if $eng;
		print HTML "\t\t\t$src<br>\n" if $src;
		print HTML "\t\t</td>\n";
		print HTML "\t</tr>\n";
	}
	print HTML "</table>\n";
	print HTML "</body>\n";
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub writeMP3s {
	local($t,$cmd);
	local($ndx,$pth,$tim,$nam,$ttl);
	print "$P: Converting tracks to MP3 ...\n" if $V>0;
	for ($t = 0; $t <= $maxtrack; $t++) {
		next unless $Ndx[$t];
		$ndx = $Ndx[$t];	# Track index number
		$pth = $Pth[$t];	# Track path
		$tim = $Tim[$t];	# Track time
		$nam = $Nam[$t];	# Track name
		$ttl = $Ttl[$t];	# Track title
		print "$P: MP3 $t $ttl ...\n";
		$ttl =~ s/'/\\'/g;
		$cmd = "lame -h --tt '$ttl' $pth $nam.mp3";
		system $cmd;
	}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub writeWAVs {
	local($t,$cmd);
	local($ndx,$pth,$tim,$nam,$ttl);
	print "$P: Linking tracks to WAV ...\n" if $V>0;
	for ($t = 0; $t <= $maxtrack; $t++) {
		next unless $Ndx[$t];
		$ndx = $Ndx[$t];	# Track index number
		$pth = $Pth[$t];	# Track path
#		$tim = $Tim[$t];	# Track time
		$nam = $Nam[$t];	# Track name
		$ttl = $Ttl[$t];	# Track title
		print "$P: Track $t is \"$nam\".\n";
		$cmd = "ln -f $pth $nam.wav";
		system $cmd;
	}
}

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
sub onetrack {
	local($line) = @_;
	local($t,$ttl);
	$line =~ s/[\s\r]+$//;
	return unless $line;
	if ($line =~ /^\s*#/) {
		return;
	}
	if ($line =~ /^(\w+):\s*(.*)$/) {
		$Hdr{$1} = $2;
		return;
	}
	if ($line =~ /^track\s+(\d+):\s*(.*)$/) {	# Title: Description
		$t = int($1);
		$dsc = $2;	# Track description
		$maxtrack = $t if ($maxtrack < $t);
		$Ndx[$t] = $tt = sprintf("%02d",$t);	# Track index number
		if (-f "track$tt.cdda.wav") {
			$Pth[$t] = "track$tt.cdda.wav";	# Track path
		}
		if (($ttl,$eng,$src) = ($dsc =~ /^(.*) \((.*)\) *- *(.*)$/)) {
			$Ttl[$t] = $1;			# Title in whatever form
			$Eng[$t] = $2;			# English title
			$Src[$t] = $3;			# Source/origin
		} elsif (($ttl,$src) = ($dsc =~ /^(.*) *- *(.*)$/)) {
			$Ttl[$t] = $1;			# Title in whatever form
			$Src[$t] = $3;			# Source/origin
		} elsif (($ttl,$eng) = ($dsc =~ /^(.*) *\((.*)\)$/)) {
			$Ttl[$t] = $1;			# Title in whatever form
			$Eng[$t] = $2;			# English title
		} else {
			$Ttl[$t] = $ttl = $dsc || '_____';
		}
		($nam = $ttl) =~ s/[^\w\s]+//g;
		$nam =~ s/\b([a-z])/\u$1/g;
		$nam =~ s/\s+//g;
		$Nam[$t] = "${tt}_$nam";	# TrackName (for file names)
		return;
	}
	if ($line =~ /^(\d+)\t([^\t]+)\t([^\t]+)\t([^\t]+)\t([^\t]+)$/) {
		$t = int($1);
		$maxtrack = $t if ($maxtrack < $t);
		$Ndx[$t] = $1;	# Track index number
		$Pth[$t] = $2;	# Track path
		$Tim[$t] = $3;	# Track time
		$Nam[$t] = $4;	# Track name
		$Ttl[$t] = $5;	# Track title
		return;
	}
	print STDERR "$P: Can't parse line:\n\t$line\n";
}
