#!/usr/bin/perl
#
# Tag MP3 files with ID3 info using CDDB
# Create info.txt file in the corresponding directory
#
# $Id: cdtag,v 1.8 2002/05/26 17:48:40 dds Exp $
#
# (C) Copyright 2000-2002 Diomidis Spinellis
# 
# Permission to use, copy, and distribute this software and its
# documentation for any purpose and without fee is hereby granted,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation.
# 
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
# 

use Getopt::Std;

$opt_t = "track%02d.mp3";

getopts('dbi:f:t:');

if ($#ARGV != -1) {
	print STDERR "$0: usage $0 [-db] [-i file_format] [-f cd-id_filename]\n";
	print STDERR "
	-b	Batch process, do not ask user to disambiguate
	-d	Enable CDDB debugging
	-i	Tag files with ID3 info
	-f	Specify cd-id filename (otherwise probe the CD in the driver)
	-t	Specify track name format (default track%02d.mp3)
";
	exit 1;
}

exit 1 if ($opt_b && -r 'info.txt');

use CDDB;
$cddb = new CDDB( Host  => 'freedb.freedb.de',
		     Port  => 8880,
		     Debug => $opt_d
		   );

if ($opt_f) {
	open(IDS, $opt_f) || die "Unable to get CD id from $opt_f: $!\n";
	$ids = <IDS>;
	if ($ids =~m /^track/) {
		# Long line format
		$ids = '';
		$tracks = $len = 0;
		while (<IDS>) {
			chop;
			if (/^CDDB DISCID: (.*)/) {
				$ids = "$1 $tracks$ids $len";
			} elsif (/^$/ || /leadout/) {
				next;
			} elsif (/\s*\d+\s+(\d+)\s+\d+\s+\w+\s+(\d+):(\d+):(\d+)/) {
				$len += (($2 * 60) + $3) * 60 + $4;
				$tracks++;
				$ids .= " $1";
			}
		}
	}
	print "ids=[$ids]\n";
	close(IDS);
} else {
	$ids = `cd-discid /dev/cdrom`;
}

@ids = split(/\s+/, $ids);

$tracks = join(' ', @ids[1..$#ids-1]);

@discs = $cddb->get_discs(@ids[0], $tracks, @ids[$#ids]);
if ($#discs > 0 && !$opt_b) {
	print "Select disk\n\n";
	$i = 0;
	foreach $disc (@discs) {
		($genre, $cddb_id, $title) = @{$discs[$i]};
		print "$i. $title ($genre)\n";
	}
	print "Enter no:";
	$discno = <STDIN>;
} elsif ($#discs == -1) {
	print "No disc found\n";
	@discs = $cddb->disconnect();
	exit 1;
} else {
	$discno = 0;
}

($genre, $cddb_id, $title) = @{$discs[$discno]};
($artist, $album) = ($title =~ m/^(.*)\s*\/\s*(.*)$/);
print "Genre = $genre, id=$cddb_id\n";
$disc_info = $cddb->get_disc_details($genre, $cddb_id);
if (!defined($disc_info)) {
	$cddb->disconnect();
	exit 1;
}

@ttitles = @{$disc_info->{'ttitles'}};

$genre = 'Other' if ($genre eq 'misc');
$track = '00';
open(OUT, ">info.txt") || die;
$ids =~ s/\n//;
print OUT "# Disk information
DI $ids
AL $album
GE $genre
AR $artist
NT $ids[1]
DU $ids[$#ids]
";
for $title (@ttitles) {
	$track++;
	$fname = sprintf($opt_t, $track);
	if ($opt_i) {	# Tag files with id3
		system ("id3",
			'-t', $title, 
			'-T', $track,
			'-a', $artist,
			'-A', $album,
			'-g', $genre,
			$fname
			);
	}
	print OUT "TR $track\001$title\001$fname\n";
}
close(OUT);

# Use this to avoid infinite recursion from the CDDB destructor
@discs = $cddb->disconnect();

exit 0;
