#!/usr/bin/perl -w
#
# cdstat -- show the current status of the CD in the drive verbosely
#
# $dotat: scripts/cdstat,v 1.23 2003/05/12 11:43:24 fanf2 Exp $

use strict;

use IO::Socket;

my $debug;
if (@ARGV == 1 and $ARGV[0] =~ /^-(d+)$/) {
	$debug = length $1;
} else {
	$debug = 0;
}

my $CDINFO = "$ENV{HOME}/.cdinfo";

sub debug (@) {
	print STDERR @_ if $debug;
}

debug "-- debugging level $debug\n";
exit if $debug > 3;

my $cddb;
sub cddbnew () {
	$cddb = new IO::Socket::INET (PeerAddr => 'freedb.freedb.org',
				      PeerPort => 888)
	    or die "$0: socket: $!\n";
	$cddb->autoflush;
}
sub cddbrecv () {
	my $line = $cddb->getline;
	$line =~ s/\r//;
	debug "<- ", $line;
	return $line;
}
sub cddbsend ($) {
	my $line = shift;
	debug "-> $line\n";
	print $cddb "$line\n";
}
sub cddbchk () {
	my $line = cddbrecv;
	$line =~ /^2/ or die "$0: bad server response: $line";
	return $line;
}
sub cddbcmd ($) {
	cddbsend shift;
	return cddbchk;
}
sub cddblines () {
	my @lines;
	my $line;
	while ($line = cddbrecv) {
		last if $line =~ /^\.\s+$/;
		push @lines, $line;
	}
	return @lines;
}

sub getcdinfo () {

	my @info = `cdcontrol info`;
	debug map "** $_", @info;
	@info = @info[3..$#info];
	my @block = map { s/^\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+.*/
                          sprintf "%3s  %08s  %08s  ", $1, $2, $3/se;
			  $4 + 150; } @info;
	my $length = int ($block[-1] / 75);
	my $tracks = $#block;
	pop @block;
	pop @info;

	cddbnew;
	cddbchk;
	cddbcmd "cddb hello fanf dotat.at cdstat 1";
	my $cdid = cddbcmd "discid $tracks @block $length";
	$cdid =~ s/.* is (\w+).*/$1/s;
	my $line = cddbcmd "cddb query $cdid $tracks @block $length";
	die "$0: unknown CD\n" if $line =~ /^202/;
	my $genre;
	if ($line =~ /^200 (\w+)/) {
		$genre = $1;
	} elsif ($line =~ /^211/) {
		my @line = cddblines
		    or die "$0: no CDs in list\n";
		if ($line[0] =~ /^(\w+) (\w+) /) {
			$genre = $1;
			$cdid = $2;
		}
	}
	die "$0: unknown server response: $line"
	    unless defined $genre;
	cddbcmd "cddb read $genre $cdid";
	my $title;
	for my $line (cddblines) {
		$title = $1 if $line =~ m/^DTITLE=(.*)/s;
		$info[$1] .= $2 if $line =~ m/^TTITLE(\d+)=([\S ]*)\s*$/s;
	}
	cddbcmd "quit";
	return $title, map "$_\n", @info;
}

my $cdid = `cdcontrol cdid`;
debug "** $cdid";
$cdid =~ s/^CDID=(\w+)\s+/$1/s
    or die "$0: unknown CDID: $cdid";
my $cdinfo = "$CDINFO/$cdid";

my @info;
if (-f $cdinfo) {
	debug "!! locally cached\n";
	open CDINFO, "< $cdinfo"
	    or die "$0: open < $cdinfo: $!\n";
	@info = <CDINFO>;
	close CDINFO;
} elsif ($debug < 2) {
	@info = getcdinfo;
	mkdir $CDINFO, 0777 unless -d $CDINFO;
	open CDINFO, "> $cdinfo"
	    or die "$0: open > $cdinfo: $!\n";
	print CDINFO @info;
	close CDINFO
	    or die "$0: writing $cdinfo: $!\n";
} else {
	@info = getcdinfo;
}
my $tracks = $#info;

my $status = `cdcontrol status audio`;
debug "** $status";
$status =~ /^[^<]*<([^>]*)>[^=]*= ([-0-9]+)[^=]*= ([-0-9:.]+)$/
    or die "$0: unknown status: $status";
my $current_status = $1;
my $current_track = $2;
my $current_position = $3;
$info[$current_track] =~ s/^ />/;

print @info;
print "$current_status at $current_position in track $current_track of $tracks\n";
