#!/usr/bin/perl -I.
# -w
#
# Disc-Cover - using CDDB to create a cover for music cds. Default is
# to output a postscript file called 'artist_-_album.ps' provided the
# album is found in the CDDB database.
# Copyright (C) 1999 J.I. van Hemert
#
# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# Author: J.I. van Hemert <jvhemert@cs.leidenuniv.nl>
#
# Physical mail:
# LIACS - Leiden University
# Niels Bohrweg 1
# 2333 CA Leiden
# The Netherlands
#
# Last Revision: 08-Jan-2000 15:34
#

################################
# Default configuration values #
################################

my ($config_tmp_dir) = '/tmp';
my ($config_output_format) = 'ps';
my ($flag_force_cddb_lookup) = 0;
my ($config_device) = "/dev/cdrom";
my ($config_cddb_cache_directory) = "$ENV{HOME}/.cddb";
my ($config_cddb_server) = "http://freedb.freedb.org/cgi-bin/cddb.cgi";
#my ($config_cddb_server) = "http://cddb.cddb.org/~cddb/cddb.cgi";
my ($config_proxy_server) = undef; # something like: "http://proxy.some.server:8888/" blank=>none
my ($flag_with_extended_track_info) = 0;


#################################
# Non advisable to change these #
#################################

my ($bottomtextfront) = undef;
my ($version) = '0.9.6';
my ($process_number) = $$;
my ($flag_move_end_file) = 0;
my ($outputfile) = undef;
my ($inputfile) = undef;
my ($flag_remove_temporary_files) = 1;
my ($config_all_available_output_types) = 'tex dvi ps pdf cddb txt lbl';
my ($latex_global_packages) = 'rotating,isolatin1,graphicx';
my ($config_cover_picture) = undef;
my ($config_cover_picture_in_eps) = undef;
my ($flag_create_new) = 0;
my ($latex_global_oddsidemargin, $latex_global_evenside_margin, $latex_global_voffset, $latex_global_footskip, $latex_global_textheight) = ("0pt", "0pt", "-100pt", "0pt", "780pt");


########################
# Start of main progam #
########################


commandline();

if ($version =~ "beta")
{
	warn	"+----------------------------------+\n".
		"| This is a beta version.          |\n".
		"| It is for testing purposes only. |\n".
		"+----------------------------------+\n";
}

use strict;
use FreeDB;
#use Image::Magick;

my $cddb = new FreeDB;
$cddb->cddb_server($config_cddb_server);
$cddb->cdrom_device($config_device);
$cddb->cache_directory($config_cddb_cache_directory);

if (defined($config_proxy_server))
{
	$cddb->proxy_value($config_proxy_server);
}
if ($flag_force_cddb_lookup)
{
	$cddb->ignore_cache(1);
}

if ($flag_create_new)
{
	$cddb->create_new() || end_program("Could not create a new cddb file.");
}
elsif (!defined($inputfile))
{
	$cddb->fetch() or end_program("Could not fetch cdrom information.","Check if the connection to the internet works.", "If the file is not in the cddb database you can make a new file\nas follows: 'disc-cover -n -t cddb -o newfile.cddb'. Edit this file and insert\nthe titles and artist, then do: 'disc-cover -f newfile.cddb'.");
}
else
{
	my $cddb_contents = "";
	open (CDDB_FILE, "$inputfile") || end_program("Could not open file \"$inputfile\"", "Check if this file exists and if it is readable.");
	while (<CDDB_FILE>)
	{
		$cddb_contents = $cddb_contents.$_;
	}
	close (CDDB_FILE);
	$cddb->fetch($cddb_contents) || end_program("Could not parse file \"$inputfile\".", "Check if this is a cddb file.");
}

($bottomtextfront) = $cddb->disc_info() if (!defined($bottomtextfront));


if (!defined($outputfile))
{
	$outputfile = $cddb->artist.' - '.$cddb->title;
	$outputfile =~ s/ /_/g;
	$outputfile =~ s#/#:#g;
	chomp $outputfile;
}

if (defined($outputfile) and ($outputfile ne "-"))
{
	if ($config_output_format eq 'pdf') { $outputfile =~ s/(\.pdf){0,1}$/.pdf/; }
	if ($config_output_format eq 'lbl') { $outputfile =~ s/(\.lbl){0,1}$/.lbl/; }
	if ($config_output_format eq 'txt') { $outputfile =~ s/(\.txt){0,1}$/.txt/; }
	if ($config_output_format eq 'tex') { $outputfile =~ s/(\.tex){0,1}$/.tex/; }
	if ($config_output_format eq 'dvi') { $outputfile =~ s/(\.dvi){0,1}$/.dvi/; }
	if ($config_output_format eq 'ps') { $outputfile =~ s/(\.ps){0,1}$/.ps/; }
	if ($config_output_format eq 'cddb') { $outputfile =~ s/(\.cddb){0,1}$/.cddb/; }
	warn "Output goes to \"$outputfile\"\n";
}

#######
# LBL #
#######
if ($config_output_format eq 'lbl')
{
	open OUT,">$outputfile";
        print OUT "cdlabelgen \\\n";
	printf OUT "-c \"%s\" \\\n", $cddb->artist;
	printf OUT "-s \"%s\" \\\n", $cddb->title;
	print OUT "-S 0.96 -e penguin.eps \\\n";
	print OUT "-i \"";
	while ($cddb->next_track)
	{
		printf OUT "%2d. %s  %02d:%02d%%\\\n", $cddb->current_track_number, $cddb->current_track_info, $cddb->current_track_time_in_seconds/60, $cddb->current_track_time_in_seconds%60;
	}
	printf OUT "%%CD length: %02d:%02d\"\n", $cddb->disc_length/60, $cddb->disc_length%60;
	close OUT;
}
#######
# TXT #
#######
elsif ($config_output_format eq 'txt')
{
	open OUT,">$outputfile";
	printf OUT "Artist: %s\n", $cddb->artist;
	printf OUT "Title:  %s\n", $cddb->title;
	while ($cddb->next_track)
	{
		if ($cddb->current_track_extended_info eq "")
		{
			printf OUT "%02d %s %02d:%02d %d\n", $cddb->current_track_number, $cddb->current_track_info, $cddb->current_track_time_in_seconds/60, $cddb->current_track_time_in_seconds%60, $cddb->current_track_offset;
		}
		else
		{
			printf OUT "%02d %s %s %02d:%02d %d\n", $cddb->current_track_number, $cddb->current_track_info, $cddb->current_track_extended_info, $cddb->current_track_time_in_seconds/60, $cddb->current_track_time_in_seconds%60, $cddb->current_track_offset;
		}
        }
	printf OUT "CD length: %02d:%02d %d\n",
          $cddb->disc_length/60, $cddb->disc_length%60, $cddb->disc_length*75;
	close OUT;
}
########
# CDDB #
########
elsif ($config_output_format eq 'cddb')
{
	open OUT,">$outputfile";
	print OUT $cddb->cddb_string();
	close OUT;
}
#######
# TEX #
#######
elsif ($config_output_format eq 'tex')
{
	open OUT,">$outputfile";
	print OUT print_whole_cover();
	close OUT;
}
#######
# PDF #
#######
elsif ($config_output_format eq 'pdf')
{
	run_latex("pdflatex");
	$flag_move_end_file = 1;
}
#######
# DVI #
#######
elsif ($config_output_format eq 'dvi')
{
	run_latex("latex");
	$flag_move_end_file = 1;
}
######
# PS #
######
elsif ($config_output_format eq 'ps')
{
	run_latex("latex");
	if (system ("(cd $config_tmp_dir ; dvips \"$config_tmp_dir/disc-cover_$process_number.dvi\" -o \"$config_tmp_dir/disc-cover_$process_number.ps\" 2> /dev/null)") > 0)
	{
		end_program("Something went wrong while running dvips.", "Run disc-cover with argument '-r' as argument, then check if a .dvi\nfile is produced in \"$config_tmp_dir\".");
	}
	$flag_move_end_file = 1;
}
###############################
# error: no valid format give #
###############################
else
{
	end_program("The type of format \"".$config_output_format."\" does not exist.", "Use \"-t <option>\" where <option> is one of:\n$config_all_available_output_types.");
}

if ($flag_move_end_file == 1)
{
	if (defined($outputfile) and $outputfile eq "-")
	{
		open OUT,"$config_tmp_dir/disc-cover_$process_number.$config_output_format" or end_program("Could not open the file \"$config_tmp_dir/disc-cover_$process_number.$config_output_format\".", "Run disc-cover with argument '-r', then\ncheck if a .$config_output_format file is produced in \"$config_tmp_dir\".");
		while (<OUT>)
		{
			print;
		};
		close OUT;
	}
	else
	{
		system ("mv -- \"$config_tmp_dir/disc-cover_$process_number.$config_output_format\" \"$outputfile\" 2> /dev/null") and end_program("Could not move the file \"$config_tmp_dir/disc-cover_$process_number.$config_output_format\"\nto \"$outputfile\".", "Check if the directory is writable.", "Run disc-cover with argument '-r', then\ncheck if a .$config_output_format file is produced in \"$config_tmp_dir\".");
	}
}
end_program();


#######################
# Clean exit function #
#######################


# DESC: primary function is to remove temporary files
#	secondary funtion is to report errors and give solutions
# NOTE: no args means clean exit (no errors reported)
# ARGS: 1 error string
#	2- solutions to error
sub end_program
{
	my ($error) = defined($_[0]) ? $_[0] : undef ;
	shift;
	my (@solutions) = defined(@_) ? @_ : undef;

	warn "Error: $error\n" if defined ($error);

	if (defined(@solutions))
	{
		if ($#solutions == 0)
		{
			warn "\nSolution: $solutions[0]\n" if ($solutions[0] ne "");
		}
		else
		{
			my ($j) = 1;
			foreach my $solution (@solutions)
			{
				warn "\nSolution $j: $solution\n" if ($solution ne "");
				$j++;
			}
		}
	}

	if ($flag_remove_temporary_files == 1)
	{
		`rm -f \"$config_tmp_dir/disc-cover_$process_number.ps\"`;
		`rm -f \"$config_tmp_dir/disc-cover_$process_number.log\"`;
		`rm -f \"$config_tmp_dir/disc-cover_$process_number.dvi\"`;
		`rm -f \"$config_tmp_dir/disc-cover_$process_number.aux\"`;
		`rm -f \"$config_tmp_dir/disc-cover_$process_number.tex\"`;
		`rm -f \"$config_tmp_dir/disc-cover_front-picture_$process_number.eps\"`;
		`rm -f \"$config_tmp_dir/disc-cover_front-picture_$process_number.pdf\"`;
	}
	exit;
}

######################
# Commandline parser #
######################

sub commandline
{
	my ($readnext) = 0;
	
	foreach my $i (@ARGV)
	{
		if ($readnext > 0)
		{
			if ($readnext == 1)
			{
				$bottomtextfront = $i;
			}
			elsif ($readnext == 2)
			{
				$outputfile = $i;
			}
			elsif ($readnext == 3)
			{
				 $config_device = $i;
			}
			elsif ($readnext == 4)
			{
				 $inputfile = $i;
			}
			elsif ($readnext == 5)
			{
				 $config_output_format = $i;
			}
			elsif ($readnext == 6)
			{
				 $config_cover_picture = $i;
			}
			elsif ($readnext == 7)
			{
				 $config_cover_picture_in_eps = $i;
			}
			else
			{
				end_program("Internal error while parsing commandline, \$readnext=\"$readnext\" not allowed.", "This is an internal error contact the author.");
			}

			$readnext = 0;
		}
		else
		{
			if ($i =~ /^-e$/)
			{
				$flag_with_extended_track_info = 1;
			}
			elsif ($i =~ /^-r$/)
			{
				$flag_remove_temporary_files = 0;
			}
			elsif ($i =~ /^-F$/)
			{
				$flag_force_cddb_lookup = 1;
			}
			elsif ($i =~ /^-a$/)
			{
				$readnext = 1;
			}
			elsif ($i =~ /^-o$/)
			{
				$readnext = 2;
			}
			elsif ($i =~ /^-D$/)
			{
				$readnext = 3;
			}
			elsif ($i =~ /^-f$/)
			{
				$readnext = 4;
			}
			elsif ($i =~ /^-t$/)
			{
				$readnext = 5;
			}
			elsif ($i =~ /^-p$/)
			{
				$readnext = 6;
			}
			elsif ($i =~ /^-eps$/)
			{
				$readnext = 7;
			}
			elsif ($i =~ /^-n$/)
			{
				$flag_create_new = 1;
			}
			elsif ($i =~ /-v$/)
			{
				print print_version_info();
				exit;
			}
			elsif (($i =~ /-h$/) or ($i =~ /--help/) or ($i =~ /-help/))
			{
				print print_help();
				exit;
			}
			else
			{
				end_program("Unknown commandline option \"$i\".", "Try \'disc-cover -h\' for quick reference of the options.", "Read the manual using 'perldoc disc-cover'.");
			}

		}
	}

	if ($readnext > 0)
	{
		end_program("Expected more on the commandline after last option.", "Try \'disc-cover -h\' for help or read the manual.");
	}
}

#################
# LaTeX filters #
#################

sub filter_input_for_latex_multiple_lines
{
# Changes allmost all the noughty characters in a string returning a string
# safely parsed by LaTeX.

	my ($return) = $_[0];

	# recode $ as $$$
	$return =~ s/\$/\$\$\$/mg;
	# recode \ as $\backslash$
	$return =~ s/\\\\/\$\\backslash\$/mg;
	# recode \n as \\\\
	$return =~ s/\\n/\\\\/mg;
	# now recode $$ as \$
	$return =~ s/\$\$\$/\\\$/mg;
	# recode every x in _#%^&{} as \x{}
	$return =~ s/([_#%&\^~{}])/\\$1\{\}/mg;
	# recode every x in <>| as $x$
	$return =~ s/([<>\|])/\$$1\$/mg;

	# remove any \\ in front of the first line
	$return =~ s/^\\+//g;

	# special characters
	$return =~ s//\${}^{\\circ}\$/mg;
	$return =~ s//\$\\mu\$/mg;
	$return =~ s//\${}^{\\textrm{a}}\$/mg;
	$return =~ s//\${}^{\\textrm{o}}\$/mg;
	$return =~ s//\$\\ll\$/mg;
	$return =~ s//\$\\gg\$/mg;
	$return =~ s//\$\\neg\$/mg;
	$return =~ s//--/mg;
	$return =~ s//\$\\bar{ }\$/mg;

	#FIXME Needs AMS: $return =~ s//\$\\yen\$/mg;
	#FIXME Needs AMS: $return =~ s//\$\\circledR\$/mg;
	#FIXME ?: $return =~ s//\$ \$/mg;
	#FIXME ?: $return =~ s//\$ \$/mg;
	#FIXME ?: $return =~ s//\$ \$/mg;

	return ($return);
}

sub filter_input_for_latex_one_line
{
# Changes all the noughty characters in a string returning a string
# safely parsed by LaTeX.

	my ($return) = $_[0];

	# only read _one_ line!
	($return) = split ("\n", $return);
	!defined ($return) ? return "" : undef;

	# recode $ as $$$
	$return =~ s/\$/\$\$\$/mg;
	# recode \ as $\backslash$
	$return =~ s/\\/\$\\backslash\$/mg;
	# now recode $$ as \$
	$return =~ s/\$\$\$/\\\$/mg;
	# recode every x in _#%^&{} as \x{}
	$return =~ s/([_#%&\^~{}])/\\$1\{\}/mg;
	# recode every x in <>| as $x$
	$return =~ s/([<>\|])/\$$1\$/mg;

	# special characters
	$return =~ s//\${}^{\\circ}\$/mg;
	$return =~ s//\$\\mu\$/mg;
	$return =~ s//\${}^{\\textrm{a}}\$/mg;
	$return =~ s//\${}^{\\textrm{o}}\$/mg;
	$return =~ s//\$\\ll\$/mg;
	$return =~ s//\$\\gg\$/mg;
	$return =~ s//\$\\neg\$/mg;
	$return =~ s//--/mg;
	$return =~ s//\$\\bar{ }\$/mg;

	#FIXME Needs AMS: $return =~ s//\$\\yen\$/mg;
	#FIXME Needs AMS: $return =~ s//\$\\circledR\$/mg;
	#FIXME ?: $return =~ s//\$ \$/mg;
	#FIXME ?: $return =~ s//\$ \$/mg;
	#FIXME ?: $return =~ s//\$ \$/mg;

	return ($return);
}

####################################
# Start of all the print functions #
####################################

sub print_cd_info_without_extended_track_info
{
# Prints latex code that declares the commands '\myartist \mytitle, \mylabel,
# and \mycontents to be used in the covers.

	my ($return) = '
%%%%%%%%%%%
% CD INFO %
%%%%%%%%%%%
';

	$return .= '\newcommand{\mytitle}{'.filter_input_for_latex_one_line($cddb->title).'}'."\n";

	$return .= '\newcommand{\myartist}{'.filter_input_for_latex_one_line($cddb->artist).'}'."\n";

	$return .= '\newcommand{\mylabel}{'.filter_input_for_latex_multiple_lines($bottomtextfront).'}'."\n";

	$return .= '\newcommand{\mycontents}'."\n";
	$return .= '{'."\n";
	if ($cddb->number_of_tracks <= 11)
	{

		$return .= '	\begin{center}\parbox{13cm}{'."\n";
		$return .= '	\begin{description}'."\n";
		while ($cddb->next_track)
		{
			$return .= sprintf "\\item[%2i\.\]{{\\sf %s ~\\dotfill %02i.%02i}}\n", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
		}
		$return .= sprintf "		\\item[]{\\sf \\hfill %02i.%02i}\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
		$return .= '	\end{description}}\end{center}'."\n";
	}
	elsif ($cddb->number_of_tracks <= 27)
	{
		if ($cddb->number_of_tracks >= 22)
		{
			$return .= '	{\footnotesize'."\n";
		}

		$return .= '	\begin{tabular}{rp{12.1cm}}'."\n";
		$return .= '		\\\\'."\n";
		while ($cddb->next_track)
		{
			$return .= sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}\\\\\n", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
		}
		$return .= sprintf "	\& \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
		$return .= '	\end{tabular}'."\n";

		if ($cddb->number_of_tracks >= 22)
		{
			$return .= '	}'."\n";
		}
	}
	elsif ($cddb->number_of_tracks <= 54)
	{
		$return .= '	{\footnotesize'."\n";
		
		$return .= '	\begin{tabular}{r@{\hspace{1em}}p{5.6cm}c@{}r@{\hspace{1em}}p{5.6cm}}'."\n";
		$return .= '		\\\\'."\n";
		for (my $i = 0; $i < $cddb->number_of_tracks/2; $i++)
		{
			$cddb->current_track_number($i + 1);
			my $t1 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}",
			$cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			
			my $t2 = "\&";
			if ($cddb->current_track_number($i + int($cddb->number_of_tracks/2) + 1 + ($cddb->number_of_tracks % 2)))
			{
				$t2 = sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}",
				$cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			}
			$return .= $t1.'& &'.$t2."\\\\\n";
		}
		$return .= sprintf "	\& \& \& \& \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
		$return .= '	\end{tabular}'."\n";
		$return .= '	}'."\n";
	}
	else
	{
		$return .= '	{\scriptsize'."\n";
		
		$return .= '	\begin{tabular}{@{}r@{\hspace{0pt}}p{3.8cm}@{\hspace{1em}}r@{\hspace{1pt}}p{3.8cm}@{\hspace{1em}}r@{\hspace{1pt}}p{3.8cm}@{}}'."\n";
		$return .= '		\\\\'."\n";
		for (my $i = 1; $i <= (int($cddb->number_of_tracks/3) + ($cddb->number_of_tracks%3 && 1)); $i++)
		{
			$cddb->current_track_number($i);
			my $t1 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			
			my $t2 = "\&";
			if ( $cddb->current_track_number($i + int($cddb->number_of_tracks/3) + ($cddb->number_of_tracks%3 && 1)) )
			{
				$t2 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			}
			
			my $t3 = "\&";
			if ( $cddb->current_track_number($i + int($cddb->number_of_tracks/3 + ($cddb->number_of_tracks%3 && 1)) + int($cddb->number_of_tracks/3 + ($cddb->number_of_tracks%3 && 1))) )
			{
				$t3 = sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			}
			

			$return .= $t1.' & '.$t2. ' & '.$t3."\\\\\n";
		}
		$return .= sprintf "	 \& \& \& \& \&  \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
		$return .= '	\end{tabular}'."\n";
		$return .= '	}'."\n";
	}

	$return .= '}
%%%%%%%
'."\n";

	return ($return);
}

sub print_cd_info_with_extended_track_info
{
# Prints latex code that declares the commands '\myartist \mytitle, \mylabel,
# and \mycontents to be used in the covers.


	my ($return) = '
%%%%%%%%%%%%%%%%%%%%%%
% CD INFO W/EXTENDED %
%%%%%%%%%%%%%%%%%%%%%%
';

	$return .= '\newcommand{\mytitle}{'.filter_input_for_latex_one_line($cddb->title).'}'."\n";

	$return .= '\newcommand{\myartist}{'.filter_input_for_latex_one_line($cddb->artist).'}'."\n";

	$return .= '\newcommand{\mylabel}{'.filter_input_for_latex_multiple_lines($bottomtextfront).'}'."\n";

	$return .= '\newcommand{\mycontents}'."\n";
	$return .= '{'."\n";
	if ($cddb->number_of_tracks <= 11)
	{
			$return .= '	\begin{tabular}{rp{12.1cm}}'."\n";
			$return .= '		\\\\'."\n";
			while ($cddb->next_track)
			{
				$return .= sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}\\\\\n", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
				$return .= sprintf "\&{{\\footnotesize\\em %s}}\\\\\n", filter_input_for_latex_one_line($cddb->current_track_extended_info);
			}
			$return .= sprintf "	\& \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
			$return .= '	\end{tabular}'."\n";
	}
	elsif ($cddb->number_of_tracks <= 14)
	{
			$return .= '	{\footnotesize'."\n";

			$return .= '	\begin{tabular}{rp{12.1cm}}'."\n";
			$return .= '		\\\\'."\n";
			while ($cddb->next_track)
			{
				$return .= sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}\\\\\n", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
				$return .= sprintf "\&{{\\scriptsize\\em %s}}\\\\\n", filter_input_for_latex_one_line($cddb->current_track_extended_info);
			}
			$return .= sprintf "	\& \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
			$return .= '	\end{tabular}'."\n";

			$return .= '	}'."\n";
	}
	elsif ($cddb->number_of_tracks <= 28)
	{
		$return .= '	{\footnotesize'."\n";
		
		$return .= '	\begin{tabular}{r@{\hspace{1em}}p{5.6cm}c@{}r@{\hspace{1em}}p{5.6cm}}'."\n";
		$return .= '		\\\\'."\n";
		for (my $i = 0; $i < $cddb->number_of_tracks/2; $i++)
		{
			$cddb->current_track_number($i + 1);
			my $t1 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}",
			$cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			my $e1 = sprintf "\&{{\\scriptsize\\em %s}}", filter_input_for_latex_one_line($cddb->current_track_extended_info);
			
			my $t2 = ' & \\\\'."\n";
			my $e2 = ' & \\\\'."\n";
			if ($cddb->current_track_number($i + $cddb->number_of_tracks/2 + 1 + ($cddb->number_of_tracks%2)))
			{
				$t2 = sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}\\\\\n",
				$cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
				$e2 = sprintf "\&{{\\scriptsize\\em %s}}\\\\\n", filter_input_for_latex_one_line($cddb->current_track_extended_info);
			}
			
			$return .= $t1.'& &'.$t2;
			$return .= $e1.'& &'.$e2;
		}
		$return .= sprintf "	\& \& \& \& \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
		$return .= '	\end{tabular}'."\n";
		$return .= '	}'."\n";
	}
	elsif ($cddb->number_of_tracks <= 52)
	{
		$return .= '	{\scriptsize'."\n";
		
		$return .= '	\begin{tabular}{@{}r@{\hspace{0pt}}p{3.8cm}@{\hspace{1em}}r@{\hspace{1pt}}p{3.8cm}@{\hspace{1em}}r@{\hspace{1pt}}p{3.8cm}@{}}'."\n";
		$return .= '		\\\\'."\n";
		for (my $i = 0; $i < $cddb->number_of_tracks/3; $i++)
		{
			$cddb->current_track_number($i + 1);
			my $t1 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			my $e1 = sprintf "\&{{\\tiny\\em %s}}", filter_input_for_latex_one_line($cddb->current_track_extended_info);

			my $t2 = my $e2 = "\&";
			if ($cddb->current_track_number($i + int($cddb->number_of_tracks/3) + 2))
			{
				$t2 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
				$e2 = sprintf "\&{{\\tiny\\em %s}}", filter_input_for_latex_one_line($cddb->current_track_extended_info);
			}

			my $t3 = my $e3 = "\&";
			if ($cddb->current_track_number($i + int(2*$cddb->number_of_tracks/3) + 2))
			{
				$t3 = sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
				$e3 = sprintf "\&{{\\tiny\\em %s}}", filter_input_for_latex_one_line($cddb->current_track_extended_info);
			}

			$return .= $t1.' & '.$t2. ' & '.$t3."\\\\\n";
			$return .= $e1.' & '.$e2. ' & '.$e3."\\\\\n";
		}
		$return .= sprintf "	 \& \& \& \& \&  \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
		$return .= '	\end{tabular}'."\n";
		$return .= '	}'."\n";
	}
	else
	{
		$return .= '	{\scriptsize'."\n";
		$return .= '	\begin{tabular}{@{}r@{\hspace{0pt}}p{3.8cm}@{\hspace{1em}}r@{\hspace{1pt}}p{3.8cm}@{\hspace{1em}}r@{\hspace{1pt}}p{3.8cm}@{}}'."\n";
		$return .= '		\\\\'."\n";
		for (my $i = 1; $i <= (int($cddb->number_of_tracks/3) + ($cddb->number_of_tracks%3 && 1)); $i++)
		{
			$cddb->current_track_number($i);
			my $t1 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			
			my $t2 = "\&";
			if ( $cddb->current_track_number($i + int($cddb->number_of_tracks/3) + ($cddb->number_of_tracks%3 && 1)) )
			{
				$t2 = sprintf "{\\bf %i.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			}
			
			my $t3 = "\&";
			if ( $cddb->current_track_number($i + int($cddb->number_of_tracks/3 + ($cddb->number_of_tracks%3 && 1)) + int($cddb->number_of_tracks/3 + ($cddb->number_of_tracks%3 && 1))) )
			{
				$t3 = sprintf "{\\bf %i\.}\&{{\\sf %s ~\\dotfill %02i.%02i}}", $cddb->current_track_number, filter_input_for_latex_one_line($cddb->current_track_info), ($cddb->current_track_time_in_seconds/60),($cddb->current_track_time_in_seconds %60);
			}

			$return .= $t1.' & '.$t2. ' & '.$t3."\\\\\n";
		}
		$return .= sprintf "	 \& \& \& \& \&  \\sf\\hfill %02i.%02i\\\\\n", ($cddb->disc_length/60), ($cddb->disc_length%60);
		$return .= '	\end{tabular}'."\n";
		$return .= '	}'."\n";
	}
	$return .= '}
%%%%%%%
'."\n";

	return ($return);
}

############################
# Help and version dialogs #
############################

sub print_version_info
{
	return '
Disc-Cover version '.$version.' Copyright (C) 1999 J.I. van Hemert
This piece of software comes with ABSOLUTELY NO WARRANTY
This is free software, and you are welcome to redistribute it
under certain conditions, see the file COPYING for details.
For more information read the documentation that comes with the
distribution.
';
}


sub print_help
{
	return print_version_info().'
Program switches:
 -a "<text>"     additonal text at the bottom of the front cover
 -D <device>     scan the cd in this device
 -e              enable extended track info
 -eps <filename> picture in EPS or PS on the front cover         
 -f <filename>   use this cddb file as input instead of a cddb connection 
 -F              force checking with the cddb server
 -h              this help
 -n              generate a new file without checking cddb or cache
 -o <filename>   output to this filename (extension is added accordingly)
 -p <filename>   picture (almost any format) to be put on the front cover
 -r              do not remove temporary files from '.$config_tmp_dir.' (for debugging)
 -t <type>       output format, possible values: '.$config_all_available_output_types.'
 -v              version and program information
';
}


#########################
# LaTeX print functions #
#########################

sub print_latex_head
{
	my ($return) = '\documentclass[]{article}';
	if ($config_output_format eq 'pdf')
	{
		$return = '\documentclass[pdftex]{article}';
	}

	$return .= '
\usepackage{'.$latex_global_packages.'}
\graphicspath{{'.$config_tmp_dir.'/}}
\renewcommand{\thepage}{}
\oddsidemargin '.$latex_global_oddsidemargin.'
\evensidemargin '.$latex_global_evenside_margin.'
\voffset '.$latex_global_voffset.'
\footskip '.$latex_global_footskip.'
\textheight '.$latex_global_textheight.'
\hyphenpenalty=10000
\def\dotfill{\leaders\hbox to 2mm{\hfil.\hfil}\hfill}

%\newcommand{\mydate}{\the\year/\the\month/\the\day}

';

	return ($return);
}

sub print_latex_body
{
	my ($picture) = "";
	if (defined($config_cover_picture_in_eps))
	{
		$picture = "\\parbox{10cm}{\\raggedleft\\framebox{\\includegraphics[height=6cm]{$config_cover_picture_in_eps}}}\\vfill";
	}
	elsif (defined($config_cover_picture))
	{
		if (-f "$config_cover_picture")
		{
			if ($config_output_format eq 'pdf')
			{
				end_program("Something went wrong trying to copy \"$config_cover_picture\" to \"$config_tmp_dir/disc-cover_front-picture_$process_number.pdf\".", "Check if the file is readable for you.") if (system ("cp -- \"$config_cover_picture\" $config_tmp_dir/disc-cover_front-picture_$process_number.pdf 2> /dev/null"));
				
			}
			else
			{
				end_program("Failed converting the cover picture \"$config_cover_picture\" to EPSI.", "Check if the program convert (comes with ImageMagick) is installed.", "Check if you can convert the cover picture to EPSI yourself.") if (system ("convert -geometry 200x200 \"$config_cover_picture\" EPSI:$config_tmp_dir/disc-cover_front-picture_$process_number.eps 2> /dev/null"));
				### TODO: NEXT STUFF DOES NOT WORK YET!
				#my ($magick) = new Image::Magick;
				#$magick->Read($config_cover_picture);
				#$magick->SetAttributes(sample=>"200x200");
				#$magick->Display();
				#$magick->Write("EPSI:$config_tmp_dir/disc-cover_front-picture_$process_number.eps");
				###

			}
		}
		else
		{
			end_program("Failed to open cover picture \"$config_cover_picture\".", "Check if the file exists and if it is readable.");
		}
		$picture = "\\parbox{10cm}{\\raggedleft\\framebox{\\includegraphics[height=6cm]{disc-cover_front-picture_$process_number}}}\\vfill";
	}
	
	return '\begin{document}

\newcommand{\myhead}[1]
{
\noindent
\begin{center}
{
\parbox{#1}{{\Large\mytitle}}

\rule{#1}{1pt}
\vspace{0.1cm}

\noindent
\parbox{#1}{{\hfill\large\emph{\myartist}}}
}
\end{center}
}

\noindent
\parbox{11cm}
{
{\small Printed with \emph{Disc-Cover} version '.$version.' on '.localtime(time()).'
For suggestions mail the author at {\tt jvhemert@cs.leidenuniv.nl} or for the
latest version check {\tt http://www.liacs.nl/\~{}jvhemert/disc-cover}}
}
\vspace{0.5cm}


%%%%%%%%%
% FRONT %
%%%%%%%%%

\noindent
\framebox{\parbox[c][12.0cm][t]{12.0cm}
{
\vspace{1cm}

\myhead{10cm}
\vfill
\begin{center}
'.$picture.'
\parbox{10cm}{{\footnotesize\sf\mylabel}}
\end{center}

}}

%%%%%%%%%


\vspace{1cm}


%%%%%%%%
% BACK %
%%%%%%%%


\newlength{\Test}
\settowidth{\Test}{\emph{\myartist}\hfill~{\mytitle}}
\ifthenelse{\lengthtest{\Test > 12.0cm}}
{
	\settowidth{\Test}{\small \emph{\myartist}\hfill~{\mytitle}}
	\ifthenelse{\lengthtest{\Test > 12.0cm}}
	{
		\settowidth{\Test}{\footnotesize \emph{\myartist}\hfill~{\mytitle}}
		\ifthenelse{\lengthtest{\Test > 12.0cm}}
		{
			\settowidth{\Test}{\scriptsize \emph{\myartist}\hfill~{\mytitle}}
			\ifthenelse{\lengthtest{\Test > 12.0cm}}
			{
				\newcommand{\sidetext}{\parbox{11.6cm}{\tiny \emph{\myartist}\hfill~{\mytitle}}}
			}
			{
				\newcommand{\sidetext}{\parbox{11.6cm}{\scriptsize \emph{\myartist}\hfill~{\mytitle}}}
			}
		}
		{
			\newcommand{\sidetext}{\parbox{11.6cm}{\footnotesize \emph{\myartist}\hfill~{\mytitle}}}
		}
	}
	{
		\newcommand{\sidetext}{\parbox{11.6cm}{\small \emph{\myartist}\hfill~{\mytitle}}}
	}
}
{
	\newcommand{\sidetext}{\parbox{11.6cm}{\emph{\myartist}\hfill~{\mytitle}}}
}

\noindent
\framebox{\parbox[c][11.6cm][t]{3mm}
{
	\begin{turn}{90}\sidetext\end{turn}
}}\framebox{\parbox[c][11.6cm][t]{13.6cm}
{
	\vspace{-0.1cm}
	\myhead{13cm}
	\vspace{-0.2cm}
	\mycontents

}}\framebox{\parbox[c][11.6cm][t]{3mm}
{
	\begin{turn}{-90}\sidetext\end{turn}
}}

%%%%%%%%

\end{document}
';
}


sub print_whole_cover
{
	if ($flag_with_extended_track_info)
	{
		return (print_latex_head().print_cd_info_with_extended_track_info().print_latex_body());
	}
	else
	{
		return (print_latex_head().print_cd_info_without_extended_track_info().print_latex_body());
	}
}

sub run_latex
{
	my ($latex_command) = $_[0];

	open OUT,">$config_tmp_dir/disc-cover_$process_number.tex";
	print OUT print_whole_cover() ;
	close OUT;

	if (system ("(cd $config_tmp_dir ; echo q | $latex_command \"disc-cover_$process_number.tex\" > /dev/null)") > 0)
	{
		end_program("Something went wrong while running LaTeX.", "Check if the necessary LaTeX packages are installed:\n$latex_global_packages.", "Run disc-cover with the option \'-t tex\' and run LaTeX on the\noutput file.");
	}
}


###############
# MANUAL PAGE #
###############

=pod MANUAL PAGE

=head1 NAME

disc-cover - create front and back covers for audio CDs


=head1 SYNOPSIS

disc-cover  [-hnrqevF] [-a text] [-f filename] [-o filename] [-p filename] [-eps filename] [-t txt|dvi|tex|ps|pdf|cddb|lbl] [-D device]


=head1 DESCRIPTION

disc-cover creates front and back covers for audio CDs. The CD has to be
present in the CD-ROM drive. disc-cover searches the CDDB database for an entry
corresponding to the CD's CDDB ID. It starts by looking for a local CDDB entry
in ~/.cddb. If no local CDDB entry matches the CD, disc-cover continues to
search the online CDDB database at www.cddb.com. It then formats the CDDB entry
to produce a Latex, Dvi, Postscript or PDF file, which contains the front and
back covers on a single page. Other formats supported include a simple text
output, a CDDB compatible format and an output format that can be used with
cdlabel- gen (http://www.red-bean.com/~bwf/software/cdlabelgen/), another cover
builder.


=head1 LAYOUT

The front cover shows artist, album title and when available extended disc
info. In addition to those, the back cover lists the individual tracks,
preceded by a track number and followed by their running time. The total
running time of the CD is given at the bottom of the back cover. The sides of
the back cover contain the artist and CD title. Optionally a picture can be
added to the front cover.


=over 4

=head1 OPTIONS

=item B<-a> I<text>

Add text to the bottom of the front cover. Default is to put extended disc
information here.

=item B<-D> I<device>

Specify the CD-ROM device.

=item B<-e>

This flag enables extended track information. If it is available this extended
information will be added below the track names. It is mostly used in
compilation cds for artist information. Sometimes this extended track
information has been used for lyrics, needles to say this will not fit at the
back of one cd cover and will therefor destroy the layout. That is why is an
option instead of default behavior.

=item B<-eps> F<filename>

Include an Encapsulated PostScript picture on the front. This is essentially the
same option as B<-p> but no scaling or converting is performed. More responsibility
goes to the user this way. A normal PostScript file should work as well.

=item B<-f> F<filename>

Use filename as input instead of searching the local and online CDDB database.

=item B<-F>

Don't search the local CDDB database for the CD. Force online CDDB lookup.

=item B<-h>

Print help message and exit.

=item B<-n>

Generate a new file without using cddb servers or cache. This is useful for cds
that are not listed in the database especially for homebrewn cds. If called like
this 'disc-cover -n -t cddb -o newcd.cddb' this will give a template that can
be edited in any editor. Afterwards use disc-cover again to generate a cover:
'disc-cover -f newcd.cddb'.

=item B<-o> F<filename>

The -o switch allows to specify the name of the output file. By default the
filename will be Artist_Title.xxx, where xxx is txt, tex, dvi, ps or pdf
depending on the file format. See -t option for supported file formats. Using
"-o -" will send the output to standard out.

=item B<-p> F<filename>

Includes the picture F<filename> on the front cover in a framed box
right aligned with the artist name. The format of the picture has to be known to
the program convert that comes with ImageMagick. Also the graphics package for
LaTeX has to be available. The picture is scaled to 200x200 and converted into
Adobe Encapsulated PostScript Interchange format. Remember that output in tex,
dvi, txt, and labelgen are completely useless with pictures.

=item B<-r>

By default disc-cover deletes all temporary files it created before it exits. This behavior can be overwritten by specifying the -r option.

=item B<-t> I<txt|tex|dvi|ps|pdf|cddb|lbl>

The -t switch allows to specify the output format. By default disc-cover will
create a Postscript file. Other formats supported include ASCII text (txt),
LaTeX (tex), DVI (dvi), PDF (pdf), cddb database format (cddb) and a cdlabelgen
compatible format (lbl).

=item B<-v>

Print version and program information and exit.

=back

=head1 BUGS

=over 4

=item -

Whenever there is more than one file in the cddb cache directory disc-cover
will issue a warning and just use the first one it found.

=item -

In extended track information mode (option -e) the layout can be destroyed when
there are too many tracks or when there is too much information in the extended
information. There are more circumstances where the layout can be destroyed.

=item -

Using '-t pdf' and '-p <filename' will not work. One way to get pictures in a PDF
file is to first produce a postscript version and then convert it to PDF using
the utility I<ps2pdf>.

=head1 AUTHORS

disc-cover is written and maintained by J.I. van Hemert <jvhemert@cs.leidenuniv.nl>
You can find the latest version on http://www.liacs.nl/~jvhemert/disc-cover
The program is licensed under the GNU Public License.

=cut

# Eof disc-cover

