#!/usr/bin/perl
$version = "crip v3.5 (http://bach.dynet.com/crip)";
# Written to facilitate ripping & encoding CDs under Linux/UNIX
# by Charlton Harrison (charlton@dynet.com)
#
# This script is intended to rip, encode and tag Ogg Vorbis and/or FLAC
# digital music files from CD.  If you want to make MP3s instead go back
# to the past and use crip version 1.0.
#

# Defaults Section ------------------------------------------------------------
# Rather than edit these values here,  it is better to edit them in the
# ~/.criprc file,  which is read in later...

# encoders supported are "vorbis" and "flac"
$encodeto = "vorbis";

# Flags for oggenc (Ogg Vorbis encoder) command.  Only used only if
#  $encodeto is set to "vorbis".
# Default is "-q 4" which is a quality setting very roughly equal to
# about 128kbps.  Note that even "-q 3" is better than 128kbps MP3.
# Hint:  If you'd rather put these flags as a command-line option,
#  use:  -o " -q 4"  (with a space as the first character within the
#  quotes so as to not confuse the command-line parser)
$oggencflags = "-q 4";

# $flacflags:  Only used if $encodeto is set to "flac".
# Note: if you include --ogg as a flag and encode to an ogg-formatted
# flac file,  crip will try to use metaflac to write the tags and that
# seems to fail.  I'm not sure what the best way to handle this scenario is.
# If anyone out there wants to make flac files within the .ogg framework,
# please enlighten me as to 1) why,  and 2) what is one supposed to use to
# modify comments in this .ogg file,  vorbiscomment?!
$flacflags = "--best --replay-gain";

# Flags for cdparanoia (CD ripper) command.
# I like to use "-v -z" here.
# If you find the "-v" is too verbose and pointless,  feel free to take it
# out.  That would significantly reduce the size of your terminal output.
# I find that using "-z" is good because I like knowing that when the script
# finishes cdparanoia did not encounter anything that could lead to an
# audible defect.  However sometimes the script might hang indefinitely
# because of the "-z".  If you find that is the case,  you can now ctrl-C
# during the rip and set new options (say, to "-v --never-skip=40") so that
# you can at least go back and listen to see if there were any audible
# defects (most of the time there isn't even if the rip wasn't perfect).
$cdparanoiaflags="-v -z";

# The comment field in the tag-info will be the Disc ID followed by the
# string below.
$comment = "Produced using " . $version . " on ";
# The comment is followed by a date/time timestamp.

# Get the title information that goes into the tag either from the
# "filename" or the "cddb" info.
# Default is "filename",  because sometimes the CDDB info is wrong.
# Note that if you set this to "cddb" but there isn't any CDDB info,
# it'll just set it based on the filename anyway.
$settitle = "filename";

# editnames: "off" = Use the legacy command-line to edit filenames;
# "on" = use an editor;  and "both" = use the command-line to edit the
# filenames but also asks afterwards if you want to edit the filenames
# with the editor.   default = "on".
$editnames = "on";

# Your favorite editor for editing filenames and tag files
$editor = "vim";

# Default contact information (put YOUR e-mail address here!)
# Remember to escape the '@' (by putting a '\' before it).
# Example:  $contact = "nobody\@nowhere.com";
$contact = "";

# Normalization is not necessary with replaygain/vorbisgain tags, so
# turn off normalization by default.
# This option can either be "on" or "off".
$normalize = "off";
# Volume threshold - if peak vol > 1/$volthresh don't bother normalizing
# Default is 1.078.  If you set this value real high,  your songs probably
# won't be normalized but you'll still get the "not normalized, peak=X.XXX"
# in your comment (you won't get this in your comment if normalize is off,
# but you'll still have peak and group-peak info in your replaygain (vorbisgain)
# tags,  but these tags are not visible using xmms thru v1.2.7).
# If normalize = "off" then $volthresh is ignored.
$volthresh = 1.078;

# $trimsilence can either be "on" or "off",  depending on whether or not you
#  want to trim silence off the beginning & end of your track/group.
# Note that if both trimsilence and normalize are off,  you won't need
#  sox or wav_find_beginning or wav_find_end.
# I personally always set this to "on",  but I'm defaulting it to "off" so
# that the prerequisits aren't so tough.  It doesn't seem to make much
# difference in the final file size,  interestingly.
$trimsilence = "off";

# The type of media that the source comes from (default = "CD")
# this just gets put in a comment
$sourcemedia = "CD";

# Default genre to "classical" unless otherwise specified later.
$genre = "classical";

# Default device to rip from
$cddevice = "/dev/cdrom";

# Turn on/off deletion of wave and tag files.  "on" by default.
$delfiles = "on";

# Classical-style questioning defaults to "off" (because I'm assuming
# most people will be ripping 'pop-style' CDs most of the time),
$askclassical = "off";
# ...unless the genre winds-up being of the following,  then it defaults
#  to "on". (values will be compared in a case-insensitive way)
#@classicalgenres = ("classical","jazz");
@classicalgenres = ("classical");

# Skip the album abbreviation question?
# (turn this "on" if you never want to be asked for or have the album
#  abbreviation.  If you rip a bunch of classical CDs and don't want
#  to have to answer null to the album abbreviation question every
#  time it's asked,  but otherwise for non-classical CDs you want to
#  have the album abbreviation,  set to "classical".)
# "off", "on", or "classical" - default should be "off".
$skipalbumabv = "off";

# Turn this on to skip the ripping process and create empty .wav files.
# By turning this on you will automatically turn on $stopgap so that
# you will have a chance to substitute the empty .wav files with the
# .wav files that you presumably already have.
$skiprip = "off";

# Add a 'stop-gap' for allowing user to edit the .wav files before
# they are encoded?  This is done after the digital silence trimming.
$stopgap = "off";

# Eject CD when done with it.  "off" by default.
$ejectcd = "off";

# Funny characters to allow (in default filenames) (other than [A-Z,a-z,0-9])
# Edit this string with care.  Some chars have to be escaped ("\"),  some
#  apparently have to be double-escaped ("//") (such as "(",")","[", and "]")
#  and some don't need to be escaped at all (such as the ",","","", etc.)
$funnychars = "\-\'\",\\.\\[\\]\\(\\)";
# Map euro characters in the default filenames to American characters
# (turn "on" if you are an American imperialist)
$mapeurochars = "off";
# European characters to allow (if $mapeurochars is set to "off")
# (again, this is only for the computer-chosen default filenames,  which
#  are based on CDDB info.  The tag info will automatically allow European
#  characters from CDDB or user sources.)
$eurochars = "߼";

# Allow spaces in filenames
# I recommend leaving this off because it is bad form to have spaces in
# filenames regardless of whether you are on UNIX or Windows.  I have included
# the option because there are too many Windoze users out there who flooded
# the internet with sorry-ass MP3s made with bad encoders, no tag information,
# and inappropriate file naming conventions, and who are still too used to
# putting spaces in their filenames.  I figure having this feature will
# encourage them to use this script and make better quality files for
# everyone.  (no offense to the person who suggested me this feature)
# So if you absolutely must have spaces in your filenames,  turn
# this to "on" (default is "off").
$allowspaces = "off";

# This is the e-mail address used to submit new entries to the freedb
#  CDDB database
$cddbsubmitaddr = "freedb-submit\@freedb.org";
# Directory to write the cddb submit entry file (need to have write
#  permissions to this directory).
$cddbsubmitdir = "/tmp";

# Now look and see what is in the .criprc file...
open(CONFIG, "<" . $ENV{HOME} . "/.criprc");
while (<CONFIG>) {
	next if /^\#/;
	chomp;
	next unless $_; # skip empty lines
	s/\=/___EQ___/; # replace first equal sign
	($key, $val) = split /___EQ___/;
	$key =~ s/[\t ]//g;   # trim leading & trailing spaces
	$val = join " ", grep { $_ } split /[\t ]/, $val;
	${$key} = $val;
##print "Key: ",$key, "   Val: ", $val, "\n";
}
close CONFIG;

# Set the following variable to "" if you do not want to receive copies of
# the CDDB submissions that you make.
$cddbsubmitaddrCc = $contact;

# End of Defaults Section -----------------------------------------------------

# Allow the user to override the defaults from the command line...
#use Getopt::Std;
use Getopt::Long;
$Getopt::Long::ignorecase = 0;

$USAGE = "$0 [options]

Options:
  -h, --help        Print this help then exit
  -v, --version     Print version of crip then exit
  -e codec          Encode to vorbis or flac (default = $encodeto)
  -s media          Specify the source media (default = $sourcemedia)
  -g genre          Specify the music genre (default = $genre)
  -q [on/off]       Classical-style questioning (default = $askclassical)
  -m [on/off]       Map European to American-only chars (default = $mapeurochars)
  -t [on/off]       Trim leading/trailing silence (default = $trimsilence)
  -n [on/off]       Normalize the audio (default = $normalize)
  -V volthresh      Volume threshold for normalizing (default = $volthresh)
                       (only used when normalizing is enabled)
  -r [on/off]       Remove files after encoding (default = $delfiles)
  -E editor         Editor to use (default = $editor)
  -u [on/off/both]  Use editor to name the files (default = $editnames)
                       (as opposed to the command-line)
  -o \" flags\"       Flags to pass to oggenc (default = '$oggencflags')
  -f \" flags\"       Flags to pass to flac (default = '$flacflags')
  -c \" flags\"       Flags to pass to cdparanoia (default = '$cdparanoiaflags')
  -d device         CDrom device to read from (default = $cddevice)
  -w [on/off]       Skip the ripping (makes empty .wav files) (default = $skiprip)
                       (useful if you already have the .wav files to encode)
  -p [on/off]       Prompt to continue after ripping (default = $stopgap)
                       (useful pause to edit .wav files before encoding)
  -x [on/off]       Eject CD when done ripping (default = $ejectcd)

";

GetOptions("v","version","h","help","s=s","g=s","d=s","e=s","E=s","V=f","u:s","o:s","f:s","c:s","q:s","t:s","n:s","r:s","w:s","p:s","x:s") || die "$USAGE";

if ((defined $opt_h) || (defined $opt_help)) { print "$USAGE"; exit(); }
if ((defined $opt_v) || (defined $opt_version)) { print "$version\n"; exit(); }
$sourcemedia = $opt_s if (defined $opt_s);
$genre = $opt_g if (defined $opt_g);
$askclassicalflag = $opt_q if (defined $opt_q);
$mapeurochars = $opt_m if (defined $opt_m);
$editnames = $opt_u if (defined $opt_u);
$encodeto = $opt_e if (defined $opt_e);
$editor = $opt_E if (defined $opt_E);
$normalize = $opt_n if (defined $opt_n);
$volthresh = $opt_V if (defined $opt_V);
$trimsilence = $opt_t if (defined $opt_t);
$delfiles = $opt_r if (defined $opt_r);
$oggencflags = $opt_o if (defined $opt_o);
$flacflags = $opt_f if (defined $opt_f);
$cdparanoiaflags = $opt_c if (defined $opt_c);
$cddevice = $opt_d if (defined $opt_d);
$skiprip = $opt_w if (defined $opt_w);
$stopgap = $opt_p if (defined $opt_p);
$ejectcd = $opt_x if (defined $opt_x);

if ($normalize eq "") { $normalize = "on"; }
if (($normalize ne "on") && ($normalize ne "off")) {
	die "Unknown normalize (-n) setting ($normalize)!\n$USAGE";
}

if ($trimsilence eq "") { $trimsilence = "on"; }
if (($trimsilence ne "on") && ($trimsilence ne "off")) {
	die "Unknown trim silence (-t) setting ($trimsilence)!\n$USAGE";
}

if ($editnames eq "") { $editnames = "on"; }
if (($editnames ne "on") && ($editnames ne "off") && ($editnames ne "both")) {
	die "Unknown editnames (-f) setting ($editnames)!\n$USAGE";
}

if ($encodeto eq "") {
	print "Did not specify a codec to encode to.  Assuming \"vorbis\".\n";
	$encodeto = "vorbis";
}
if (($encodeto ne "vorbis") && ($encodeto ne "flac")) {
	die "Invalid/unsupported codec (-e) ($encodeto).\n$USAGE";
}

if ($mapeurochars eq "") { $mapeurochars = "on"; }
if (($mapeurochars ne "on") && ($mapeurochars ne "off")) {
	die "Unknown mapeurochars (-m) setting ($mapeurochars)!\n$USAGE";
}

if ($delfiles eq "") { $delfiles = "on"; }
if (($delfiles ne "on") && ($delfiles ne "off")) {
	die "Unknown delete (-r) setting ($delfiles)!\n$USAGE";
}

if ($skiprip eq "") { $skiprip = "on"; }
if (($skiprip ne "on") && ($skiprip ne "off")) {
	die "Unknown skiprip (-w) setting ($skiprip)!\n$USAGE";
}
if ($skiprip eq "on") { $stopgap = "on"; }

if ($stopgap eq "") { $stopgap = "on"; }
if (($stopgap ne "on") && ($stopgap ne "off")) {
	die "Unknown stopgap (-p) setting ($stopgap)!\n$USAGE";
}

if ($ejectcd eq "") { $ejectcd = "on"; }
if (($ejectcd ne "on") && ($ejectcd ne "off")) {
	die "Unknown eject (-x) setting ($ejectcd)!\n$USAGE";
}

if ((defined $opt_V) && ($normalize eq "off")) {
	print "You specified a volume threshold,\n";
	print "but you also have normalization turned off.\n\n";
	die "$USAGE";
}

if (defined $askclassicalflag) {
	if ($askclassicalflag eq "") { $askclassicalflag = "on"; }
	if (($askclassicalflag ne "on") && ($askclassicalflag ne "off")) {
		die "Unknown classical (-q) setting ($askclassicalflag)!\n$USAGE";
	}
}

if (! -e $cddevice) {
	die "No such device: $cddevice!\n$USAGE";
}
# End getopts section


# Print current version of crip
print $version, "\n";

# Print my feedback contact information
print "\n   Please report all bugs, feature requests, or\n";
print "   general difficulties to charlton\@dynet.com.\n\n";

# List options and what they're set to
print "Options currently set to:\n";
print "   contact = $contact\n";
print "   sourcemedia = $sourcemedia\n";
print "   encodeto = $encodeto\n";
print "   cddevice = $cddevice\n";
print "   settitle = $settitle\n";
print "   editnames = $editnames\n";
print "   editor = $editor\n";
print "   askclassical (default) = $askclassical\n";
if (defined $askclassicalflag) {
	print "   askclassicalflag = $askclassicalflag\n";
}
print "   skipalbumabv = $skipalbumabv\n";
print "   mapeurochars = $mapeurochars\n";
print "   normalize = $normalize\n";
if ($normalize eq "on") {
	print "    volthresh = $volthresh\n";
}
print "   trimsilence = $trimsilence\n";
print "   delfiles = $delfiles\n";
print "   skiprip = $skiprip\n";
print "   stopgap = $stopgap\n";
print "   ejectcd = $ejectcd\n";

print "\n";

# Print ripper info
$cdprelease = `cdparanoia --version 2>&1 | grep release`;
chop $cdprelease;

print "Ripper: ", $cdprelease, " ", $cdparanoiaflags, "\n";

if ((defined $opt_c) && ($cdparanoiaflags eq "")) {
	print "\nWARNING: Did not specify any flags for cdparanoia.\n";
	print "         Will run cdparanoia without any flags.\n\n";
}

if ((defined $opt_f) && ($flacflags eq "")) {
	if ($encodeto eq "flac") {
	    print "\nWARNING: Did not specify any flags for flac.\n";
		print "         Will run flac without any flags.\n\n";
	} else {
		print "\nWARNING: You specified the '-f' flag but you\n";
		print "         are not encoding to flac!\n\n";
	}
}


# Set the encoding field
if ($encodeto eq "vorbis") {
	$encoding = `oggenc --version`;  chop $encoding;
	$encoding = $encoding . " " . $oggencflags;
} else {
	$encoding = `flac --version`;  chop $encoding;
	$encoding = $encoding . " " . $flacflags;
}
print "Encoder: ", $encoding, "\n";

if ((defined $opt_o) && ($oggencflags eq "")) {
	if ($encodeto eq "vorbis") {
		print "\nWARNING: Did not specify any flags for oggenc.\n";
		print "         Will encode with no flags!\n";
	} else {
		print "\nWARNING: You specified the '-o' flag but you\n";
		print "         are not encoding to vorbis!\n\n";
	}
}

print "\n";
##exit();   # Used for testing command-line option behavior


# Now check to make sure all required components are available

# Check for the encoder and necessary tagging tools
if ($encodeto eq "vorbis") {
	$out = `which oggenc`;
	if ($out eq "") {
		die "Cannot find `oggenc` for encoding to Ogg Vorbis!\n";
	}
	$out = `which vorbiscomment`;
	if ($out eq "") {
		die "Cannot find `vorbiscomment` for tagging the Ogg Vorbis files!\n";
	}
} else {
	$out = `which flac`;
	if ($out eq "") {
		die "Cannot find `flac`!\n";
	}
	$out = `which metaflac`;
	if ($out eq "") {
		die "Cannot find `metaflac` for tagging the flac files!\n";
	}
}

# Unless normalize is on or not encoding to vorbis, check for vorbisgain
unless (($normalize eq "on") || ($encodeto ne "vorbis")) {
	# If vorbisgain is unavailable then deliver this warning.
	$out = `which vorbisgain`;
	if ($out eq "") {
		print "\nIt does not appear that vorbisgain is available on\n";
		print "this system.  Either get it (recommended) or turn on\n";
		print "normalization instead (not recommended).\n";
		print "Either ctrl-C now or press <enter> to continue: ";
		$inp = <stdin>;
	}
}

if ($editnames eq "on") {
	$out = `which $editor`;
	if ($out eq "") {
		print "\nYou have 'editnames' on,  and you have your editor set to '$editor',\n";
		print " but there is no $editor in your path.  You need to either install\n";
		print " this editor in your path,  change your editor to an available editor\n";
		print " in your path,  or turn 'editnames' off.\n";
		exit();
	}
}

if (($normalize eq "on") || ($trimsilence eq "on")) {
	$out = `which sox`;
	if ($out eq "") {
		print "\nsox needs to be installed.\n\n";
		print "Note: You can eliminate your dependency on sox by turning off\n";
		if (($normalize eq "on") && ($trimsilence eq "on")) {
			print " normalization and silence trimming.\n";
		} elsif ($trimsilence eq "on") {
			print " silence trimming.\n";
		} elsif ($normalize eq "on") {
			print " normalization.\n";
		}
		exit();
	} else {
		$out = `sox -h 2>&1 | grep Version`;  chop $out;
		if ($out ne "sox: Version 12.17") {
			print "Your sox needs to be version 12.17 (12.17.0).\n";
			print "The later versions of sox work differently (and in an undocumented way).\n";
			print "This script should have come with it.  It can also be downloaded from\n";
			print "ftp://bach.dynet.com/pub/crip/current\n\n";
			print "Note:  You can eliminate your dependency on sox by turning off\n";
			if (($normalize eq "on") && ($trimsilence eq "on")) {
				print " normalization and silence trimming.\n";
			} elsif ($trimsilence eq "on") {
				print " silence trimming.\n";
			} elsif ($normalize eq "on") {
				print " normalization.\n";
			}
			exit();
		}
	}
}

if ($trimsilence eq "on") {
	$out = `which wav_find_beginning`;
	if ($out eq "") {
		print "\nYou must have wav_find_beginning in your path.\n\n";
		print "Note:  You can eliminate this dependency by turning off\n";
		print " silence trimming.\n";
		exit();
	}
	$out = `which wav_find_end`;
	if ($out eq "") {
		print "\nYou must have wav_find_end in your path.\n\n";
		print "Note:  You can eliminate this dependency by turning off\n";
		print " silence trimming.\n";
		exit();
	}
}

# This will bomb with an error if not available:
use CDDB_get qw( get_cddb get_discids );

# Check for existing *.wav, *.tag, *.ogg, *.flac or filenames.txt files
$out = `ls *.wav *.ogg *.flac *.tag 2>/dev/null`;
if ($out ne "") {
	print "You currently have *.wav, *.ogg, *.flac, or *.tag files in the current\n";
	print "working directory.  These are subject to being overwritten.\n\n";
	print "Press <enter> to proceed (or ctrl-C to abort): ";
	$inp = <STDIN>;
}
if (-e "filenames.txt") {
	print "You currently have a filenames.txt file in the current working\n";
	print "working directory.  This will be deleted!\n\n";
	print "Press <enter> to proceed (or ctrl-C to abort): ";
	$inp = <STDIN>;
	# Go ahead and delete the file now so that if the script is stopped and
	#  restarted this question won't keep bugging the user.
	print "Deleting filenames.txt\n\n";
	`rm filenames.txt`;
}

# End of check components section.


# Main loop
while (1) {

$firstdate = 1;

# cddb query
print "Retrieving Disc Information...\n";
$ids = get_discids($cddevice);
$discid = sprintf "%08x", $ids->[0];
$totaltracks = $ids->[1];
$toc = $ids->[2];
print "Retrieving CDDB Information...\n";
# %cd = get_cddb();
eval { %cd = get_cddb(); };
if ($@) {
	print "error: $!\n\n";
	print "get_cddb() has failed for some reason.\n";
	print "Perhaps the network is down?\n";
}
print "\n";
print "DiscID:   ", $discid, "\n";
unless(defined $cd{title}) {
	print "No CDDB info found.\n";
} else {
	print "cddbID:   ", $cd{id}, "\n";
	print "artist:   ", $cd{artist}, "\n";
	print "title:    ", $cd{title}, "\n";
	print "category: ", $cd{cat}, "\n\n";
	$genre = $cd{cat};

	if ($cd{tno} != $totaltracks) {
		print "!!! WARNING !!!\n";
		print "Reported number of tracks different from actual.\n";
		print "Disc reports ", $totaltracks, ".\n";
		print "CDDB reports ", $cd{tno}, ".\n\n";
	}
}

print "total number of tracks: ", $totaltracks, "\n";
$tr=1;
foreach $trtitle ( @{cd->{track}} ) {
	$trname[$tr] = $trtitle;
	$from=$toc->[$tr-1]{frames};
	$to=$toc->[$tr]{frames} - 1;
	$dur=$to-$from;
	$min=int($dur/75/60);
	$sec=int($dur/75)-$min*60;
	$frm=($dur-$sec*75-$min*75*60)*100/75;
	$out=sprintf "track %2d: %8d - %8d  [%2d:%.2d.%.2d]: $trtitle\n",$tr,$from,$to,$min,$sec,$frm;
	print "$out";
	$tr++;
}
print "\n";


############################################################### CDDB test info
#foreach $tmp (0 .. ($totaltracks - 1)) {
#	print $tmp, " - ", $toc->[$tmp]{frames}, "\n";
#}
#$cddbduration = int($toc->[$totaltracks]{frames} / 75);
#print "Duration: ", $cddbduration, " seconds.\n";
#foreach $idx (@{cd->{raw}}) {
#	if ($idx =~ m/^#\s+Revision:\s*(\d+)/) { $revision = $1; }
#	print $idx;
#}
#print "\nRevision: ", $revision, "\n";
##############################################################################

##exit();


# Request normalization groupings

print "\n\nEnter the track numbers for each group (each group will be\n";
print "replaygained/vorbisgained/normalized,  trimmed,  and tagged\n";
print "as if it were one piece of music).\n\n";
print "Delimit the track numbers on each line by a space.\n";
print "Type \"end\" to go on to the next section.\n\n";
print "Note that only the tracks you specify will be ripped.\n";
print "Also note that if you list a track more than once, it will be\n";
print "unnecessarily ripped more than once (so don't do it).\n";
print "You can also enter \"all\" or \"each\" for grouping all tracks as\n";
print "one group, or each track as a separate group respectively.\n";
print "If input is \"all\" or \"each\" then the entire CD is ripped.\n";

$inp = "";  $listing = "";  $listnum = 0;
while ($inp ne "end") {
	print "\n> ";
	$inp = <STDIN>;
	chop $inp;

	if ($inp eq "all") {
		$i = 1;
		while ($i <= $totaltracks) {
			$list[$listnum][$i-1] = $i;
			$i++;
		}
		$listing = "all";
		$inp = "end";
	} elsif ($inp eq "each") {
		$i = 1;
		while ($i <= $totaltracks) {
			$list[$listnum][0] = $i;
			$listnum++;  $i++;
		}
		$listing = "each";
		$inp = "end";
	} elsif ($inp ne "end") {
		# Parse the list of numbers
		# If $inp is not a list of numbers then print "invalid"
		$valid = 0;  $i = 0;
		while ($inp =~ s/^(\d+)\s*//) {
			$list[$listnum][$i] = $1;
			$valid = 1;  $i++;
		}
		if ($valid) {
			$listnum++;
		} else {
		    print "Invalid Entry.\n\n";
		}
	}
}


# Reiterate the lists...
print "\n\nHere are the lists of tracks you picked:\n\n";
$listnum = 0;
while ($listnum <= $#list) {
	$index = 0;
	while ($index <= $#{$list[$listnum]}) {
		print $list[$listnum][$index], " ";
		$index++;
	}
	$listnum++;
	print "\n";
}
print "\n";

# Analyze picked tracks and display any warning messages if necessary
# 1) check to see if any of the tracks are listed more than once
$warning = 0;  $tmpindex = 0;  $listnum = 0;
while ($listnum <= $#list) {
	$index = 0;
	while ($index <= $#{$list[$listnum]}) {
		$tmptrack = $list[$listnum][$index];
		# Check if $tmptrack matches any from the array before it
		$chkindex = 0;
		while ($chkindex < $tmpindex) {
			if ($tmptrack == $tmptracks[$chkindex]) { $warning = 1; }
			$chkindex++;
		}
		# Add $tmptrack to the array
		$tmptracks[$tmpindex] = $tmptrack;
		$tmpindex++;
		$index++;
	}
	$listnum++;
}
if ($warning) { print "Warning:  Some track(s) in the list appear more than once.\n"; }
# 2) check to see if any of the tracks don't appear
$warning = 0;  $listnum = 0;
foreach $tmptrack (1 .. $totaltracks) {
	# Make sure each $tmptrack appears at least once
	$matched = 0;
	$listnum = 0;
	while ($listnum <= $#list) {
		$index = 0;
		while ($index <= $#{$list[$listnum]}) {
			if ($tmptrack == $list[$listnum][$index]) {
				$matched = 1;
			}
			$index++;
		}
		$listnum++;
	}
	if (!$matched) { $warning = 1;}
}
if ($warning) { print "Warning:  Some track(s) on the CD don't appear in your listed tracks.\n"; }
# 3) check to make sure all lists are in consecutive order
$warning = 0;  $listnum = 0;
while ($listnum <= $#list) {
	# Make sure each of these lists is in consecutive order
	$index = 0;  $lasttrack = 0;
	while ($index <= $#{$list[$listnum]}) {
		if ($lasttrack != 0) {
			if ($list[$listnum][$index] != ($lasttrack + 1)) { $warning = 1; }
		}
		$lasttrack = $list[$listnum][$index];
		$index++;
	}
	$listnum++;
}
if ($warning) { print "Warning:  Some list(s) are not in consecutive order.\n"; }
# 4) check to make sure all the tracks are within the bounds of the CD.
$warning = 0;  $listnum = 0;
while ($listnum <= $#list) {
	$index = 0;
	while ($index <= $#{$list[$listnum]}) {
		if (($list[$listnum][$index] < 1) || ($list[$listnum][$index] > $totaltracks)) {
			$warning = 1;
		}
		$index++;
	}
	$listnum++;
}
if ($warning) {
	print "Warning:  Some track(s) you listed are not on the CD (these won't be ripped).\n";
	print "FYI:  Total number of tracks disc reports: $totaltracks\n";
}
print "\n";



# Query section begins...
print "Please enter the genre for this album.\n";
print "Recommended genres are (from freedb.org):\n";
print "    blues       (self explanatory)\n";
print "    classical   (self explanatory)\n";
print "    country     (self explanatory)\n";
print "    folk        (self explanatory)\n";
print "    jazz        (self explanatory)\n";
print "    newage      (self explanatory)\n";
print "    reggae      (self explanatory)\n";
print "    rock        (including funk, soul, rap, pop, industrial, metal, etc.)\n";
print "    soundtrack  (movies, shows)\n";
print "    data        (ISO9660 and other data CDs)\n";
print "    misc        (others that do not fit in the above categories)\n";
print "Enter the genre for this album (single space = null): [", $genre, "]: ";
$inp = <STDIN>;  chop($inp);
if ($inp ne "") { $genre = $inp; }
if ($inp eq " ") { $genre = ""; }
if ($genre =~ m/new\.age/i) {
	print "\"$genre\" -> \"newage\"\n";
	$genre = "newage";
}

# If the '-q' flag was used,  override default
if (defined $askclassicalflag) {
	# We already know from above that $askclassicalflag must be "on" or "off"
	$askclassical = $askclassicalflag;
} else {
	# Set $askclassical if $genre is one of @classicalgenres
	foreach $classicalgenre (@classicalgenres) {
		if ($genre =~ m/^\s*$classicalgenre\s*$/i) {
			$askclassical = "on";
		}
	}
}

# Set $setlabels default
$setlabels = "cd";
$composer = "";  $complast = "";
if ($askclassical eq "on") {
	print "Since this is $genre, there should be a composer.\n";
	if ($#list >= 1) { # (more than one list)
		print "If the composer is different for each group/list, just set the\n";
		print "value to null and add the composer tag manually with each list.\n";
	}
	# Get $composer
	$composer = $cd{artist};
	print "Enter composer (single space = null): [", $composer, "]: ";
	$inp = <STDIN>;  chop($inp);
	if ($inp ne "") { $composer = $inp; }
	if ($inp eq " ") { $composer = ""; }
	# Now try to set $complast to the last name of the $composer
	if ($composer =~ m/^\s*(\S+)\s*,/) {
		$complast = $1;
	} elsif ($composer =~ m/\s+(\S+)\s*$/) {
		$complast = $1;
	} else {
		$complast = $composer;
	}

	# Since this is Classical-style questioning, default $setlabels to "list".
	# ($setlabels default will be reset if $listing eq "each" or "all")
	$setlabels = "list";
}

# Ask query to what $setlabels will actually be
# (this will determine whether to label once for the whole CD or
#  once for each list)
# But don't even bother if $listing is "each" or "all"
if (($listing ne "each") && ($listing ne "all")) {
	if ($#list >= 1) {
		print "Would you like to set the artist and miscellaneous labeling info for\n";
		print "the whole CD right now, or would you prefer to set it for each list?\n";
		print "(list/cd) [" . $setlabels . "]: ";
		$inp = <STDIN>;  chop($inp);
		if (($inp eq "list") || ($inp eq "LIST")) { $setlabels = "list"; }
		if (($inp eq "cd") || ($inp eq "CD")) { $setlabels = "cd"; }
	} else {   # Don't bother asking this question if the number of lists is just one.
		$setlabels = "cd";
	}
} else {
	# $listing is "each" or "all" so it's probably safe to assume that
	# the user doesn't want to label per list.
	$setlabels = "cd";
	# But if the user selected "each", print a message anyway just to
	# let the user know that if he wants to label each list,  he'll have
	# to start the script over and enter in each track as a separate list.
	if (($listing eq "each") && ($#list >= 1)) {
		print "Note:  Since you entered \"each\", I will assume that you will\n";
		print " want to enter all information just once rather than per list.\n";
	}
}

# Set default $artist now if $setlabels eq "cd"
$artist = $cd{artist};  $conductor = "";  $performer = "";  $ensemble = "";
if ($setlabels eq "cd") {   # Set the $artist now
	if ($askclassical eq "on") {
		print "Enter conductor.  If there isn't one, enter null.\n";
		print " (single space = null): [", $artist, "]: ";
		$inp = <STDIN>;  chop($inp);
		if ($inp eq "") { $conductor = $artist; } else { $conductor = $inp; }
		if ($inp eq " ") { $conductor = ""; }
		if ($conductor ne "") {
			print "You have entered a conductor so this will be your artist's name.\n";
			$artist = $conductor;
		} else {
			print "Since there is no conductor,  there's probably a (main) performer.\n";
			print "Enter this performer (single space = null): [", $artist, "]: ";
			$inp = <STDIN>;  chop($inp);
			if ($inp eq "") { $performer = $artist; } else { $performer = $inp; }
			if ($inp eq " ") { $performer = ""; }
			if ($performer ne "") {
				print "You have entered a performer so this will be your artist's name.\n";
				$artist = $performer;
			} else {
				print "Since there is no main performer or conductor,\n";
				print " the 'artist' is probably an ensemble.\n";
				print "If this is true,  enter the name of the ensemble (single space = null): [", $artist, "]: ";
				$inp = <STDIN>;  chop($inp);
				if ($inp eq "") { $ensemble = $artist; } else { $ensemble = $inp; }
				if ($inp eq " ") { $ensemble = ""; }
				if ($ensemble ne "") {
					print "You have entered an ensemble so this will be your 'artist'.\n";
					$artist = $ensemble;
				} else {
					print "Okay, just enter the artist then.\n";
					print "Enter artist (single space = null): [", $artist, "]: ";
					$inp = <STDIN>;  chop($inp);
					if ($inp ne "") { $artist = $inp; }
					if ($inp eq " ") { $artist = ""; }
				}
			}
		}
	} else {
		print "Enter artist (single space = null): [", $artist, "]: ";
		$inp = <STDIN>;  chop($inp);
		if ($inp ne "") { $artist = $inp; }
		if ($inp eq " ") { $artist = ""; }
	}
}

# Set $album (the album title)
$default = $cd{title};
$default =~ s/\r//g;   # Get rid of this common char that causes problems
print "Enter album name (single space = null): [", $default, "]: ";
$inp = <STDIN>;  chop($inp);
if ($inp eq "") { $album = $default; } else { $album = $inp; }
if ($inp eq " ") { $album = ""; }

# Set $albumabv (the album abbreviation).  This is only used to help
#  set the default track names.
if (($skipalbumabv eq "on") || (($skipalbumabv eq "classical") && ($askclassical eq "on"))) {
	# If classical, you probably don't want the default name to include
	#  an album abbreviation.  If you do, name the files manually.
	$albumabv = "";
} else {
	# Set $albumabv to the first four first-letters of the $album
	$albumabv = $album;  $albumabv =~ s/_/ /g;  $tmp = "";
	if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = substr($1, 0, 1); }
	if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = $tmp . substr($1, 0, 1); }
	if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = $tmp . substr($1, 0, 1); }
	if ($albumabv =~ s/([\w$eurochars]+)//) { $tmp = $tmp . substr($1, 0, 1); }
	$albumabv = $tmp;
	print "Enter album abbreviation (single space = null): [", $albumabv, "]: ";
	$inp = <STDIN>;  chop($inp);
	unless ($inp eq "") { $albumabv = $inp; }
	if ($inp eq " ") { $albumabv = ""; }
}

# Set the $label and $labelno
print "Enter label name (single space = null): []: ";
$inp = <STDIN>;  chop($inp);
if (($inp eq "") || ($inp eq " ")) { $label = ""; } else { $label = $inp; }
# Set $labelno
print "Enter label catalog number (single space = null): []: ";
$inp = <STDIN>;  chop($inp);
if (($inp eq "") || ($inp eq " ")) { $labelno = ""; } else { $labelno = $inp; }

# Set $recdate
# Incidently, the date of the recording is one of those things that I want
# to ask for every list,  even if $setlabels="cd".  But if the $listing is
# "all" or "each" then I'll just ask it once right now.
$recdate = "";
if (($listing eq "all") || ($listing eq "each")) {
	# Set $recdate for ALL the tracks here and now...
	if ($firstdate) {
		print "Enter the date of recording -\n";
		print "\n(formatting notes: no format is specifically required, but it is definitely\n";
		print " preferable to include all FOUR digits of the year,  and since it'll never\n";
		print " always be clear whether it's MM-DD or DD-MM, it is actually preferable\n";
		print " to spell out the month (at least the first 3 letters anyway) and then the day,\n";
		print " but if you really want to use a numeric format, chose the ISO-8601 standard\n";
		print " (YYYY-MM-DD),  however note that it may still be unclear to some which number\n";
		print " is the month and which is the day.  So it is recommended that you use dates\n";
		print " such as \"March 24, 1994\", \"March, 1994\", or \"1994\" (depending on how much\n";
		print " information you have),  and if all you have is the production (P) date,  put\n";
		print " \"(P)1994\".  The actual recording date is usually up to a year or two before\n";
		print " the production date.\n";
		$firstdate = 0;
	}
	print "Enter the date of recording (single space = null): [don't put one]: ";
	$inp = <STDIN>;  chop($inp);
	$recdate = $inp;
	if ($inp eq " ") { $recdate = ""; }
}

# If $setlabels ne "list",  set other tag fields here...
if ($setlabels ne "list") {
	print "\nType the name of a field tag that you'd like to add to\n";
	print " all these music files (or make up your own field tag name).\n";
	print "You can enter the fieldname then enter the data for that fieldname,\n";
	print "or you can enter fieldname=data all on one line.\n";
	# List some possible recommended tags
	print "\nPossible tag recommendations:\n";
	if ($askclassical eq "on") {
		if ($composer eq "") { print "  composer"; }
		if ($conductor eq "") { print "  conductor"; }
		if ($ensemble eq "") { print "  ensemble"; }
		print "  opus\n";
	}
	print "  location  performer  copyright  license\n\n";
	# Continue
	print "Just press <enter> (with nothing on the line) to finish:\n";
	$finished = 0;  $tagindex = 0;
	while (!$finished) {
		$inp = <STDIN>;  chop $inp;
		if (($inp ne "") && ($inp ne " ") && ($inp ne ".")) {
			# If there's an "=" assume the line is "fieldname=data"
			if ($inp =~ m/=/) {
				$tag[$tagindex] = $inp;
			} else {
				# There is no "=".  Assume the line is just the fieldname.
				$tagname = $inp;
				print "Set " . $tagname . "=";
				$inp = <STDIN>;  chop $inp;
				$tagdata = $inp;
				$tag[$tagindex] = $tagname . "=" . $tagdata;
			}
			$tagindex++;
		} else {
			$finished = 1;
		}
	}
}



# Filename Setting Section
print "\nTrack/filename labeling section...\n";

# Set all the default track names
$i = 1;
while ($i <= $totaltracks) {
	if ($i < 10) { $tmpindex = "0" . $i; } else { $tmpindex = $i; }
	$tn2 = $trname[$i];  $tocorigname = $tn2;
	# If there's no useful info in $tn2,  set it to "track_??"
	unless ($tn2 =~ m/\w/) { $tn2 = "track_" . $tmpindex; }
	if ($complast ne "") {
		$tn0 = $complast;
		$tn0 = $tn0 . "_-_";
	} elsif ($artist ne "") {
		$tn0 = $artist;
		$tn0 = $tn0 . "_-_";
	} else {
		$tn0 = "";
	}
	if ($albumabv eq "") {
		$tn1 = "";
	} else {
		$tn1 = $albumabv . $tmpindex . "_";
	}
	unless(defined $cd{title}) {
		if ($album eq "") {
			$album = "CDDB info not available";
		}
	}

	# Set default filename from its components
#	$tmpname = $artist . "_-_" . $albumabv . $tmpindex . "_" . $title;
	$tmpname = $tn0 . $tn1 . $tn2;

	# Process $tmpname
	$tmpname =~ s/\s+/_/g;  # Substitute white-space character blocks with "_"
	# Map special chars to other allowable chars
	$tmpname =~ s/[\/\\~]/-/g;    # Replace any of these chars with a "-"
	$tmpname =~ s/</(/g;  $tmpname =~ s/>/)/g;	# Substitute <> with ()
	$tmpname =~ s/{/[/g;  $tmpname =~ s/}/]/g;  # Substitute {} with []
	$tmpname =~ s/\&/_and_/g;	# Replace & with "and" (double-"_" will be taken out later)
	if ($mapeurochars eq "on") {
		# Map euro-characters to American characters
		$tmpname =~ s/[]/a/g;  $tmpname =~ s/[]/A/g;
		$tmpname =~ s/[]/e/g;  $tmpname =~ s/[]/E/g;
		$tmpname =~ s/[]/i/g;  $tmpname =~ s/[]/I/g;
		$tmpname =~ s/[]/o/g;  $tmpname =~ s/[]/O/g;
		$tmpname =~ s/[]/u/g;  $tmpname =~ s/[]/U/g;
		$tmpname =~ s/[]/n/g;  $tmpname =~ s/[]/N/g;
		$tmpname =~ s/[]/c/g;  $tmpname =~ s/[]/C/g;
		$tmpname =~ s/[]/s/g;  $tmpname =~ s/[]/S/g;
		$tmpname =~ s/[]/y/g;  $tmpname =~ s/[ݾ]/Y/g;
		$tmpname =~ s/[]/z/g;  $tmpname =~ s/[]/Z/g;
		$tmpname =~ s/[]/ae/g;  $tmpname =~ s/[]/AE/g;
		$tmpname =~ s/[]/oe/g;  $tmpname =~ s/[]/OE/g;
		$tmpname =~ s/[]/B/g;
	}
	# Now get rid of the rest (of the special chars)
	$tmpname =~ s/[^\w$funnychars$eurochars]//g;    # Only keep specified $funnychars and $eurochars
	$tmpname =~ s/__/_/g;   # Get rid of any double-blanks caused by the last line
	$tmpname =~ s/(,_|_,)/,/g;  $tmpname =~ s/(\._|_\.)/./g;    # Rid more extraneous "_"s
	if ($allowspaces eq "on") {
		# Replace all suggested "_" with " "
		# Easier doing this once at the end of the process than
		# making many exceptions from the beginning
		$tmpname =~ s/_/ /g;
	}
	# Done.  $tmpname will now be the default (computer-generated) filename

	$tocname[$tmpindex] = $tmpname;
	$tocorigname[$tmpindex] = $tocorigname;
	$i++;
}


# If $album is empty set it to $albumabv
unless ($album =~ m/\S+/) { $album = $albumabv; }

# User interaction begins for filename selection...
if ($editnames eq "on") {
	print "Here are the computer-chosen filenames for the tracks that you've picked:\n";
	# Create the filenames.txt file now
	open(NAMEFILE, ">filenames.txt");
	$listnum = 0;
	while ($listnum <= $#list) {
		$index = 0;
		while ($index <= $#{$list[$listnum]}) {
			print NAMEFILE "$tocname[$list[$listnum][$index]]\n";
			$index++;
		}
		print NAMEFILE "\n";
		$listnum++;
	}
	close(NAMEFILE);
	# Assume the computer-generated defaults aren't broken!
	$broken = 0;  $warning = 0;  $firstpass = 1;
	do {
		# Print out the filenames.txt file to the screen
		print "-------------------------------------------------------------------------------\n";
		open(NAMEFILE, "filenames.txt");
		while ($line = <NAMEFILE>) {
			# Process $line just like the filenames would be before showing them
			chop $line;  $line =~ s/^\s*//;  $line =~ s/\s*$//;
			print $line, "\n";
		}
		close(NAMEFILE);

		# Query
		$default = "no";
		if ($warning) {
			print $warningmsg;
			$default = "yes";
		}
		if ($broken) {
			print $reason;
			$default = "yes";
		}
		if ($firstpass) {
			$default = "yes";
		}
		print "Edit the above filenames? [" . $default . "]: ";
		$inp=<STDIN>;  chop($inp);
		if ($inp eq "") { $inp = $default; }
		$inp =~ s/\s//g;
		if ($inp =~ m/^\s*y/i) {
			system "$editor filenames.txt";
			$firstpass = 0;
		}
		# Process filenames.txt into $oname[][] and $name[][]
		$broken = 0;	# Will set this to 1 if the file is discovered to be broken
		$warning = 0;
		open(NAMEFILE, "filenames.txt");
		$listnum = 0;
		while ($listnum <= $#list) {
			$index = 0;
			while ($index <= $#{$list[$listnum]}) {
				$oname[$listnum][$index] = <NAMEFILE>;
				chop $oname[$listnum][$index];
				# Clear off any whitespace at the beginning or end of string
				$oname[$listnum][$index] =~ s/^\s*//;  $oname[$listnum][$index] =~ s/\s*$//;
				# But there are any spaces left set $broken
				if (($oname[$listnum][$index] =~ m/\s/) && ($allowspaces ne "on")) {
					$broken = 1;  $reason = "No spaces allowed in filenames.\n";
				}
				unless ($oname[$listnum][$index] =~ m/\w/) {
					$broken = 1;  $reason = "Invalid filename detected (no word characters).\n";
				}
				if ($oname[$listnum][$index] eq "") {
					$broken = 1;  $reason = "There must be one (and only one) empty line between each list.\n";
				}
				if ($oname[$listnum][$index] =~ m/\.(ogg|mp3|wav)$/i) {
					# Not broken,  but print a notice and set default to edit again.
					$warning = 1;
					$warningmsg = "Warning:  You are not supposed to end your filenames with an extension here.\n";
				}
				$name[$listnum][$index] = $oname[$listnum][$index];
				# Add escapes to the appropriate characters
				# Replace (, ), ', ` chars with \(, \), \', \`, etc.
				$name[$listnum][$index] =~ s/\(/\\(/g;  $name[$listnum][$index] =~ s/\)/\\)/g;
				$name[$listnum][$index] =~ s/'/\\'/g;  $name[$listnum][$index] =~ s/`/\\`/g;
				$name[$listnum][$index] =~ s/\"/\\\"/g;  $name[$listnum][$index] =~ s/ /\\ /g;
				$index++;
			}
			$emptyline = <NAMEFILE>;  chop $emptyline;  $emptyline =~ s/\s//g;
			if ($emptyline ne "") {
				$broken = 1;  $emptyline = "not_empty";
				$reason = "There cannot be empty lines within a list.\n";
			}
			$listnum++;
		}

		# If the names do not process go thru the loop again
	} until (($inp eq "no") && (!$broken));

} else {
	print "NOTE:  If you make a mistake during this section,  you can\n";
	print " enter a single space to go backwards in the list(s).  You\n";
	print " will then get a chance to redo the previous item(s).\n";
}
$listnum = 0;
while ($listnum <= $#list) {
	if ($editnames eq "on") {
		if (($setlabels eq "list") || (($listing ne "all") && ($listing ne "each"))) {
			print "\n\n-------------------------------------------------------------------------------\n";
			print "Enter information for the list:\n\n";
			# Print out the filenames in this list
			$index = 0;
			while ($index <= $#{$list[$listnum]}) {
				print "$oname[$listnum][$index]\n";
				$index++;
			}
			print "\n";
		}
	} else {
		print "\nNew List\n\n";
		$index = 0;
		while ($index <= $#{$list[$listnum]}) {
			print "Name for track ", $list[$listnum][$index], " - ";
			# $oname[][] will be the filename BEFORE inserting '\'s (for certain chars)
			$oname[$listnum][$index] = $tocname[$list[$listnum][$index]];
			$name[$listnum][$index] = $tocname[$list[$listnum][$index]];
			# Replace (, ), ', ` chars with \(, \), \', \`   *** - Might need to add on this later
			$name[$listnum][$index] =~ s/\(/\\(/g;  $name[$listnum][$index] =~ s/\)/\\)/g;
			$name[$listnum][$index] =~ s/'/\\'/g;  $name[$listnum][$index] =~ s/`/\\`/g;
			print "[", $oname[$listnum][$index], "]: ";
			$inp=<STDIN>;  chop($inp);
			unless (($inp eq "") || ($inp eq " ")) {
				print "Naming track ", $list[$listnum][$index], " to ", $inp, "\n";
				# Set $oname[][] to the name before putting in the '\'s.
				$oname[$listnum][$index] = $inp;
				# Add escapes to the appropriate characters
				# Replace (, ), ', ` chars with \(, \), \', \`, etc.
				$inp =~ s/\(/\\(/g;  $inp =~ s/\)/\\)/g;
				$inp =~ s/'/\\'/g;  $inp =~ s/`/\\`/g;
				$inp =~ s/\"/\\\"/g;  $inp =~ s/ /\\ /g;
				$name[$listnum][$index] = $inp;
			}
			$index++;
			if ($inp eq " ") {
				print "Going back...\n";
				$index--;  $index--;
				if ($index == -1) {
					$listnum--;  $index = 0;
					if ($listnum == -1) {
						$listnum = 0;
					} else {
						$index = $#{$list[$listnum]};
					}
				}
			}
		}
		print "-------------------------------------------------------------------------------\n";
	}

	# If $setlabels eq "list" set $artist[$listnum] now.
	if ($setlabels eq "list") {   # Set the $artist now
		if ($askclassical eq "on") {
			# If this is the first time around,  set $default = $artist
			if (($listnum < 1) && ($conductor eq "")) { $default = $artist; } else { $default = $conductor; }
			print "Enter conductor.  If there isn't one, enter null.\n";
			print " (single space = null): [", $default, "]: ";
			$inp = <STDIN>;  chop($inp); 
			if ($inp eq "") { $conductor = $default; } else { $conductor = $inp; }
			if ($inp eq " ") { $conductor = ""; }
			if ($conductor ne "") {
				print "You have entered a conductor so this will be your artist's name.\n";
				$artist = $conductor;
			} else {
				if (($listnum < 1) && ($performer eq "")) { $default = $artist; } else { $default = $performer; }
				print "Since there is no conductor,  there's probably a (main) performer.\n";
				print "If this is true,  enter this performer (single space = null): [", $default, "]: ";
				$inp = <STDIN>;  chop($inp); 
				if ($inp eq "") { $performer = $default; } else { $performer = $inp; }
				if ($inp eq " ") { $performer = ""; }
				if ($performer ne "") {
					print "You have entered a performer so this will be your artist's name.\n";
					$artist = $performer;
				} else {
					if (($listnum < 1) && ($ensemble eq "")) { $default = $artist; } else { $default = $ensemble; }
					print "Since there is no main performer or conductor,\n";
					print " the 'artist' is probably an ensemble.\n";
					print "If this is true,  enter the name of the ensemble (single space = null): [", $default, "]: ";
					$inp = <STDIN>;  chop($inp);
					if ($inp eq "") { $ensemble = $default; } else { $ensemble = $inp; }
					if ($inp eq " ") { $ensemble = ""; }
					if ($ensemble ne "") {
						print "You have entered an ensemble so this will be your 'artist'.\n";
						$artist = $ensemble;
					} else {
						print "Okay, just enter the artist then.\n";
						print "Enter artist (single space = null): [", $artist, "]: ";
						$inp = <STDIN>;  chop($inp);
						if ($inp ne "") { $artist = $inp; }
						if ($inp eq " ") { $artist = ""; }
					}
				}
			}
		} else {
			print "Enter artist (single space = null): [", $artist, "]: ";
			$inp = <STDIN>;  chop($inp);
			if ($inp ne "") { $artist = $inp; }
			if ($inp eq " ") { $artist = ""; }
		}
	}
	# Set these fields regardless if null or not
	#  because they are all labeled per list.
	$conductor[$listnum] = $conductor;
	$performer[$listnum] = $performer;
	$ensemble[$listnum] = $ensemble;
	$artist[$listnum] = $artist;


	if (($listing ne "all") && ($listing ne "each")) {
		# Set $recdate for the tracks in this list
		if ($firstdate) {
			print "Enter the date of recording -\n";
			print "\n(formatting notes: no format is specifically required, but it is definitely\n";
			print " preferable to include all FOUR digits of the year,  and since it'll never\n";
			print " always be clear whether it's MM-DD or DD-MM, it is actually preferable\n";
			print " to spell out the month (at least the first 3 letters anyway) and then the day,\n";
			print " but if you really want to use a numeric format, chose the ISO-8601 standard\n";
			print " (YYYY-MM-DD),  however note that it may still be unclear to some which number\n";
			print " is the month and which is the day.  So it is recommended that you use dates\n";
			print " such as \"March 24, 1994\", \"March, 1994\", or \"1994\" (depending on how much\n";
			print " information you have),  and if all you have is the production (P) date,  put\n";
			print " \"(P)1994\".  The actual recording date is usually up to a year or two before\n";
			print " the production date.\n";
			$firstdate = 0;
		}
		print "Enter the date of recording (single space = null): [";
		if ($recdate eq "") { print "don't put one"; }
		else { print $recdate; }
		print "]: ";
		$inp = <STDIN>;  chop $inp;
		if ($inp ne "") { $recdate = $inp; }
		if ($inp eq " ") { $recdate = ""; }
	}
	$recdate[$listnum] = $recdate;

	# If $setlabels eq "list",  set other tag fields here...
	if ($setlabels eq "list") {
		print "\nType the name of a field tag that you'd like to add to\n";
		print " all these music files (or make up your own field tag name).\n";
		print "You can enter the fieldname then enter the data for that fieldname,\n";
		print "or you can enter fieldname=data all on one line.\n";
		# List some possible recommended tags
		print "\nPossible tag recommendations:\n";
		if ($askclassical eq "on") {
			if ($composer eq "") { print "  composer"; }
			if ($conductor eq "") { print "  conductor"; }
			if ($ensemble eq "") { print "  ensemble"; }
			print "  opus\n";
		}
		print "  location  performer  copyright  license\n\n";
		# Continue
		print "Just press <enter> (with nothing on the line) to finish:\n";
		$finished = 0;  $tagindex = 0;
		while (!$finished) {
			$inp = <STDIN>;  chop $inp;
			if (($inp ne "") && ($inp ne " ") && ($inp ne ".")) {
				# If there's an "=" assume the line is "fieldname=data"
				if ($inp =~ m/=/) {
					$tag[$listnum][$tagindex] = $inp;
				} else {
					# There is no "=".  Assume the line is just the fieldname.
					$tagname = $inp;
					print "Set " . $tagname . "=";
					$inp = <STDIN>;  chop $inp;
					$tagdata = $inp;
					$tag[$listnum][$tagindex] = $tagname . "=" . $tagdata;
				}
				$tagindex++;
			} else {
				$finished = 1;
			}
		}
	}

	$listnum++;
}


# If editnames is "both",  here is the last chance to edit the filenames
# This is basically a reiteration of the above code.
if ($editnames eq "both") {
	print "\nHere are the filenames you put:\n";
	# Create the filenames.txt file now
	open(NAMEFILE, ">filenames.txt");
	$listnum = 0;
	while ($listnum <= $#list) {
		$index = 0;
		while ($index <= $#{$list[$listnum]}) {
			print NAMEFILE "$oname[$listnum][$index]\n";
			$index++;
		}
		print NAMEFILE "\n";
		$listnum++;
	}
	close(NAMEFILE);
	# Assume the computer-generated defaults aren't broken!
	$broken = 0;  $warning = 0;  $firstpass = 1;
	do {
		# Print out the filenames.txt file to the screen
		print "-------------------------------------------------------------------------------\n";
		open(NAMEFILE, "filenames.txt");
		while ($line = <NAMEFILE>) {
			# Process $line just like the filenames would be before showing them
			chop $line;  $line =~ s/^\s*//;  $line =~ s/\s*$//;
			print $line, "\n";
		}
		close(NAMEFILE);

		# Query
		$default = "no";
		if ($warning) {
			print $warningmsg;
			$default = "yes";
		}
		if ($broken) {
			print $reason;
			$default = "yes";
		}
		if ($firstpass) {
			$default = "yes";
		}
		print "Edit the above filenames? [" . $default . "]: ";
		$inp=<STDIN>;  chop($inp);
		if ($inp eq "") { $inp = $default; }
		$inp =~ s/\s//g;
		if ($inp =~ m/^\s*y/i) {
			system "$editor filenames.txt";
			$firstpass = 0;
		}
		# Process filenames.txt into $oname[][] and $name[][]
		$broken = 0;	# Will set this to 1 if the file is discovered to be broken
		$warning = 0;
		open(NAMEFILE, "filenames.txt");
		$listnum = 0;
		while ($listnum <= $#list) {
			$index = 0;
			while ($index <= $#{$list[$listnum]}) {
				$oname[$listnum][$index] = <NAMEFILE>;
				chop $oname[$listnum][$index];
				# Clear off any whitespace at the beginning or end of string
				$oname[$listnum][$index] =~ s/^\s*//;  $oname[$listnum][$index] =~ s/\s*$//;
				# But there are any spaces left set $broken
				if (($oname[$listnum][$index] =~ m/\s/) && ($allowspaces ne "on")) {
					$broken = 1;  $reason = "No spaces allowed in filenames.\n";
				}
				unless ($oname[$listnum][$index] =~ m/\w/) {
					$broken = 1;  $reason = "Invalid filename detected (no word characters).\n";
				}
				if ($oname[$listnum][$index] eq "") {
					$broken = 1;  $reason = "There must be one (and only one) empty line between each list.\n";
				}
				if ($oname[$listnum][$index] =~ m/\.(ogg|mp3|wav)$/i) {
					# Not broken,  but print a notice and set default to edit again.
					$warning = 1;
					$warningmsg = "Warning:  You are not supposed to end your filenames with an extension here.\n";
				}
				$name[$listnum][$index] = $oname[$listnum][$index];
				# Add escapes to the appropriate characters
				# Replace (, ), ', ` chars with \(, \), \', \`, etc.
				$name[$listnum][$index] =~ s/\(/\\(/g;  $name[$listnum][$index] =~ s/\)/\\)/g;
				$name[$listnum][$index] =~ s/'/\\'/g;  $name[$listnum][$index] =~ s/`/\\`/g;
				$name[$listnum][$index] =~ s/\"/\\\"/g;  $name[$listnum][$index] =~ s/ /\\ /g;
				$index++;
			}
			$emptyline = <NAMEFILE>;  chop $emptyline;  $emptyline =~ s/\s//g;
			if ($emptyline ne "") {
				$broken = 1;  $emptyline = "not_empty";
				$reason = "There cannot be empty lines within a list.\n";
			}
			$listnum++;
		}

		# If the names do not process go thru the loop again
	} until (($inp eq "no") && (!$broken));
}

print "\n\n";


# Note:  $oname[][] (original name) is the same as $name[][] with the
#  exception that $name includes an escape "\" on characters used to
#  specify the filename from the shell.  When specifying the filename
#  in perl (i.e. using print),  use $oname[][].  When specifying the
#  filename in a shell (i.e. using ``),  use $name[][].


# Start the .tag file for each file.
$listnum = 0;
while ($listnum <= $#list) {
	$index = 0;
	while ($index <= $#{$list[$listnum]}) {
		open(TAGFILE, ">$oname[$listnum][$index].tag");

		# Set tracknumber (left-pad with zeros to two digits)
		$tmptrnum = $list[$listnum][$index];
		if (length($tmptrnum) == 1) {
			if ($tmptrnum =~ /\d/) { $tmptrnum = "0" . $tmptrnum; }
			else { $tmptrnum = ""; }
		} elsif (length($tmptrnum) == 2) {
			unless ($tmptrnum =~ /\d\d/) { $tmptrnum = ""; }
		} else { $tmptrnum = ""; }

		# Set the title string ($titlestr)
		# If $settitle is "cddb" and there is CDDB info set the title to that,
		# otherwise set it from the filename.
		if (($settitle eq "cddb") && ($tocorigname[$list[$listnum][$index]] ne "")) {
			# Set from CDDB info
			$titlestr = $tocorigname[$list[$listnum][$index]];
			# Now change underscores back to spaces...
			$titlestr =~ s/_/ /g;
		} else {
			# Set from filename (after first "_-_")
			$titlestr = $oname[$listnum][$index];
			# Now strip off the artist name (everything before the first _-_)
			if ($titlestr =~ m/_-_(.+)/) { $titlestr = $1; }
			# Now check to see if $albumabv is in the title.
			if ($albumabv ne "") {
				if ($titlestr =~ m/^\.?$albumabv/) {
					$titlestr =~ s/^\.?$albumabv\.?\d?\d//;
				}
			}
			# Now change underscores back to spaces...
			$titlestr =~ s/_/ /g;
			# Trim off any spaces on the beginning or end
			$titlestr =~ s/^\s+//;
			$titlestr =~ s/\s+$//;
			# Make array of titles for possible CDDB submit
			$titlestr[$list[$listnum][$index]] = $titlestr;
		}

		# Tag the file
		if ($titlestr ne "") {
			print TAGFILE "title=$titlestr\n";
		}

		# Artist info
		if ($artist[$listnum] ne "") {
			print TAGFILE "artist=$artist[$listnum]\n";
		}
		# Composer should be mandatory for Classical,  but if it's not set
		#  it is still possible that it is being added as a user-specified tag.
		if ($composer ne "") {
			print TAGFILE "composer=$composer\n";
		}
		# Conductor and Performer may or may not be set.  If they have been set CD-wide,
		#  then the list-specific variable is set during the list query section.
		if ($conductor[$listnum] ne "") {
			print TAGFILE "conductor=$conductor[$listnum]\n";
		}
		if ($performer[$listnum] ne "") {
			print TAGFILE "performer=$performer[$listnum]\n";
		}
		if ($ensemble[$listnum] ne "") {
			print TAGFILE "ensemble=$ensemble[$listnum]\n";
		}
		# Date of recording - tends to immediately follow artist info
		if ($recdate[$listnum] ne "") {
			print TAGFILE "date=$recdate[$listnum]\n";
		}

		# User-added tags:  (presumably this is probably also artist-related)
		$tagindex = 0;
		if ($setlabels eq "list") {
			while ($tagindex <= $#{$tag[$listnum]}) {
				print TAGFILE "$tag[$listnum][$tagindex]\n";
				$tagindex++;
			}
		} else {
			while ($tagindex <= $#tag) {
				print TAGFILE "$tag[$tagindex]\n";
				$tagindex++;
			}
		}

		# Album info
		if ($album ne "") {
			print TAGFILE "album=$album\n";
		}
		if ($label ne "") {
			print TAGFILE "label=$label\n";
		}
		if ($labelno ne "") {
			print TAGFILE "labelno=$labelno\n";
		}
		# Track & part info
		print TAGFILE "tracknumber=$tmptrnum\n";
		# The part is just which place it is in its list.
		if ($#{$name[$listnum]} > 1) {
			$part = $index + 1;
			print TAGFILE "part=$part\n";
		}

		if ($genre ne "") {
			print TAGFILE "genre=$genre\n";
		}

		# Additional stuff
		if ($contact ne "") {
			print TAGFILE "contact=$contact\n";
		}
		close(TAGFILE);
		# Done creating the tag file for this particular file

		# Now print the track - filename, and the tag file.
		print $tmptrnum . ": " . $oname[$listnum][$index] . "\n";
		$out=`cat $name[$listnum][$index].tag`;  print $out, "\n";

		$index++;
	}
	print "\n";
	$listnum++;
}


# Prompt to see if user wants to edit any of the .tag files
print "\nLook at the above tags and make sure they are all okay.\n";
print "You can edit any of these tag files by entering the track number.\n";
print "You can also enter \"submit\" to submit this data to the freedb\n";
print "CDDB database or just press <enter> by itself to go directly to\n";
print "the ripping process!  (or press ctrl-C to abort everything).\n";

do {
	print "Enter track number, submit, or just press <enter> to Rip! : ";
	$inp = <stdin>;  chop $inp;
	if (($inp eq " ") || ($inp eq ".")) { $inp = ""; }
	if ($inp =~ m/\d+/) {
		$listnum = 0;
		while ($listnum <= $#list) {
			$index = 0;
			while ($index <= $#{$list[$listnum]}) {
				if ($inp == $list[$listnum][$index]) {
					system "$editor $name[$listnum][$index].tag";
				}
				$index++;
			}
			$listnum++;
		}
	}
} until (($inp eq "") || ($inp =~ m/submit/i));


# Submit to the freedb CDDB database if desired.
if ($inp =~ m/submit/i) {
	# First make sure $genre is one of the 11 freedb categories
	$cgy = $genre;
	while (($cgy ne "classical") && ($cgy ne "blues") && ($cgy ne "country") &&
		($cgy ne "data") && ($cgy ne "folk") && ($cgy ne "jazz") &&
		($cgy ne "newage") && ($cgy ne "reggae") && ($cgy ne "rock") &&
		($cgy ne "soundtrack") && ($cgy ne "misc")) {
		print "\nThe genre you've selected (\"$cgy\") is not a category that\n";
		print "freedb accepts.\n";
		print "Please enter one of the following categories for submission:\n";
		print "   classical   blues   country   data   folk   jazz   newage\n";
		print "   reggae   rock   soundtrack   misc\n> ";
		$cgy = <STDIN>;  chop $cgy;
		if ($cgy eq "data") {
			print "\"data\"?!   Are you sure?  [no]: ";
			$inp = <STDIN>;  chop $inp;
			unless ($inp =~ m/y/i) { $cgy = ""; }
		}
	}

	# Write the original raw CDDB info pulled from freedb
	$cddborig = "$cddbsubmitdir/cddb_orig_$discid";
	open(CDDBOR, ">$cddborig");
	foreach $tmp (@{cd->{raw}}) {
		# Now's the chance to pull the revision number
		if ($tmp =~ m/^#\s+Revision:\s*(\d+)/) { $revision = $1 + 1; }
		print CDDBOR $tmp;
	}
	close(CDDBOR);

	# Now create and write submission to file to be e-mailed
	$cddbfile = "$cddbsubmitdir/cddb_submit_$discid";
	open(CDDBFD, ">$cddbfile");
	print CDDBFD "# xmcd CD database file\n#\n# Track frame offsets:\n";
	foreach $tmp (0 .. ($totaltracks - 1)) {
		print CDDBFD "#       ", $toc->[$tmp]{frames}, "\n";
	}
	$cddbduration = int($toc->[$totaltracks]{frames} / 75);
	print CDDBFD "#\n# Disc length: ", $cddbduration, " seconds\n#\n";
	print CDDBFD "# Revision: ", $revision, "\n";
	print CDDBFD "# Submitted via: ", $version, "\n#\n";
	# End of header
	print CDDBFD "DISCID=$discid\n";
	if (($cgy eq "classical") && ($composer ne "")) {
		print CDDBFD "DTITLE=$composer / $album\n";
	} else {
		if (($artist ne "") && ($album ne "")) {
			print CDDBFD "DTITLE=$artist / $album\n";
		} elsif ($artist ne "") {
			print CDDBFD "DTITLE=$artist\n";
		} elsif ($album ne "") {
			print CDDBFD "DTITLE=$album\n";
		} else {
			# hmmm... this really shouldn't happen
			print "WARNING:  Both artist and album are NOT SET.\n";
			print CDDBFD "DTITLE=\n";
		}
	}
	$recdate[0] =~ m/(\d\d\d\d)/;  $year = $1;
	print CDDBFD "DYEAR=$year\n";
	print CDDBFD "DGENRE=$cgy\n";
	foreach $tnm (1 .. $totaltracks) {
		$tmp = $tnm - 1;
		print CDDBFD "TTITLE$tmp=$titlestr[$tnm]\n";
	}
	# Write EXTD and EXTT info
	if ($setlabels eq "list") {
		print CDDBFD "EXTD=\n";
		foreach $tnm (1 .. $totaltracks) {
			$tmp = $tnm - 1;
			# Find $listnum that track $tnm is in.
			$listnum = 0;  $index = -1;
			do {
				$index++;
				if ($index > $#{$list[$listnum]}) {
					$index = 0;  $listnum++;
				}
				if ($listnum > $#list) {   # This should never happen
					print "WTF?  Track $tnm isn't in any list!\n";
					break;
				}
			} until ($tnm == $list[$listnum][$index]);
			# Now write all user-specified tag info to each EXTT#
			# (hey, you gotta better idea?)
			$tagindex = 0;
			while ($tagindex <= $#{$tag[$listnum]}) {
				print CDDBFD "EXTT$tmp=$tag[$listnum][$tagindex]\n";
				$tagindex++;
			}
			if ($tagindex == 0) { print CDDBFD "EXTT$tmp=\n"; }
		}
	} else {
		$tagindex = 0;
		while ($tagindex <= $#tag) {
			print CDDBFD "EXTD=$tag[$tagindex]\n";
			$tagindex++;
		}
		if ($tagindex == 0) { print CDDBFD "EXTD=\n"; }
		foreach $tnm (1 .. $totaltracks) {
			$tmp = $tnm - 1;
			print CDDBFD "EXTT$tmp=\n";
		}
	}
	# End of EXTD and EXTT section
	print CDDBFD "PLAYORDER=\n";
	close(CDDBFD);

	# Verify with the user that the file is correct.
	do {
		# Print out original raw CDDB info
		print "\nORIGINAL CDDB RECORD:\n";
		$out = `cat $cddborig`;  print $out;
		# Print out the new CDDB submission data
		print "\nYOUR NEW SUBMISSION:\n";
		$out = `cat $cddbfile`;  print $out;
		print "\nPlease be absolutely sure that the above information is correct\n";
		print "and better than the original CDDB record before submitting it to\n";
		print "the CDDB database!";
		print "\nDoes it look good? (accept/edit/abort) [edit]: ";
		$inp = <STDIN>;  chop $inp;
		if (($inp eq "") || ($inp =~ m/edit/i)) {
			system "$editor $cddbfile";
		}
	} until (($inp =~ m/accept/i) || ($inp =~ m/abort/i));

	# Finally, mail off the file
	if ($inp =~ m/abort/i) {
		print "Aborted.\n\n";
	} else {
		print "\nmailing $cddbfile to $cddbsubmitaddr... ";
		`mail -s "cddb $cgy $discid" -c $cddbsubmitaddrCc $cddbsubmitaddr < $cddbfile`;
		print "Done.\n\n";
	}
}



# Now rip all of the tracks in each list
# cdparanoia command:

print "\n\nBeginning the rip...\n\n";
print "NOTE: You may press ctrl-C during the ripping process to abort\n";
print " the current rip and get the opportunity to rip with different\n";
print " cdparanoia command-line parameters.\n\n";

# Maintain a list of tracks that are possible flawed
#  (aborted and rerun without the "-z")
$posflawed = "";
$listnum = 0;
while ($listnum <= $#list) {
	$index = 0;
	while ($index <= $#{$list[$listnum]}) {
		if ($skiprip eq "on") {
			print "Creating empty file: $oname[$listnum][$index].wav\n";
			`cat /dev/null > $name[$listnum][$index].wav`;
		} else {
			$tmpcdflags = $cdparanoiaflags;
			$trackaborted = 0;
			do {
				print "\n---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n";
				print "Ripping track ", $list[$listnum][$index], "...\n\n";
				$cdpcmd="cdparanoia $tmpcdflags -d $cddevice $list[$listnum][$index]";
				print "Command: $cdpcmd\n";
				$cdpout = system "$cdpcmd";
				if ($cdpout != 0) {
					$trackaborted = 1;
					print "\n\nAborted.\n\n";
					print "Retry this track with different cdparanoia flags? (y/n) [y]: ";
					$inp = <STDIN>;  chop $inp;
					if ($inp =~ m/^\s*n/i) {   # If answer is no...
						# Just continue out of the loop.
						$cdpout = 0;
					} else {   # Presumably answer is yes... this is the safe path anyway.
						print "\nThe old cdparanoia flags are \"", $tmpcdflags, "\".\n";
						print "Enter the new flags to try for this track: [", $tmpcdflags, "]: ";
						$inp = <STDIN>;  chop $inp;
						if ($inp ne "") { $tmpcdflags = $inp; }
#						unless (($tmpcdflags =~ m/\b-z\b/) || ($trackposflawed)) {
# The \b-z\b part didn't work
#							# Track was aborted and reripped without the "-z" flag. Take note.
#							$posflawed = $posflawed . "   " . $list[$listnum][$index];
#							$posflawed = $posflawed . " - " . $oname[$listnum][$index] . "\n";
#							$trackposflawed = 1;   # Only take note once though.
#						}
					}
				} else {
					# Track successfully finished ripping
					# But if $tmpcdflags didn't have the '-z' flag in it then give a warning.
					if ($cdparanoiaflags =~ m/-z/) {
						unless ($tmpcdflags =~ m/-z/) {
							$posflawed = $posflawed . "   " . $list[$listnum][$index];
							$posflawed = $posflawed . " - " . $oname[$listnum][$index] . "\n";
						}
					}
				}
			} until ($cdpout == 0);
			# It would be nice to be able to get status/return codes from cdparanoia
			# to determine whether or not the rip is hanging, there's a skip ("V") in
			# the rip, or it otherwise failed or aborted WITHOUT having to get ctrl-C
			# signals from the user.  But until someone implements that in cdparanoia
			# I guess we'll just have to live with this glaring design flaw in cdparanoia.
			# I'd very-much like to implement something like this:
#			} else {
#				print "\n\n\n --- An Error Occurred in the ripping! ---\n\n\n";
#			}
			# ...but there is currently no way to do it!

			# Rename cdda.wav to $name[][].wav
			`mv -- cdda.wav $name[$listnum][$index].wav`;
		} # End if ($skiprip eq "on)

	    $index++;
	}
	$listnum++;
	print "\n";
}


print "Finished ripping.\n";
print "For the rest of this process crip will not need the CD.\n\n\n";
# Some of us will change CDs now and immediately start another instance
# of crip to rip another CD while this one is processing and encoding.
# I personally wait until the encoding starts so that all the major
# disk/IO is over with though.

# Eject CD if that option is turned on.
if ($ejectcd eq "on") {
	print "Attempting to eject CD...\n";
	$ejectcmd = "eject " . $cddevice;
	print "Running `$ejectcmd`\n";
	`$ejectcmd`;
	print "\n";
}


# Now's the time for a stop-gap prompt (i.e. if a user wants the chance
#  to edit the raw .wav files before the processing begins)...
if ($stopgap eq "on") {
	# The following line is just a stop-gap if needed.
	print "Ripping complete.\n";
	print "You may now edit the raw .wav files or whatever...\n";
	print "\nPress <enter> when ready to continue processing: ";
	$inp = <STDIN>; print "\n";
}


# Normalization and Trimming processing section
# If normalizing,  compute the $voladjust value for the list,  which
#  will be based off the list's highest peak-value.
if ($normalize eq "on") {
	print "Volume threshold is ", $volthresh, ".\n";
} else {
	print "Will not normalize.\n";
}
$listnum = 0;
while ($listnum <= $#list) {
	# Figure out what $volarg should be
	$volarg = "";
	if ($normalize eq "on") {
		print "\n\nFinding peak volume for list ", $listnum, "\n";
		$index = 0;  $voladjust = 999999;
		while ($index <= $#{$list[$listnum]}) {    # && ($voladjust >= $volthresh)) { # We want to get all the peaks anyway...
			$statout=`sox $name[$listnum][$index].wav -e stat -v 2>&1`;
			chop($statout);
			print "Volume adjust for ", $oname[$listnum][$index], ".wav: ", $statout, "\n";
			$origpeak[$list[$listnum][$index]] = 1.0 / $statout;
			if ($statout < $voladjust) { $voladjust = $statout; }
			$index++;
		}

		# Set the volume adjust argument for sox (or leave null)
		if ($voladjust >= $volthresh) {   # Add a volume adjust argument to sox.
			print "\n\nAdjusting volume of list ", $listnum, " to ", $voladjust, "\n";
			$normval[$listnum] = $voladjust;
			$volarg = "vol " . $voladjust;
		} else {
			print "\n\nNot adjusting volume of list ", $listnum, " to ", $voladjust, " (not worth it)\n";
			$normval[$listnum] = "";
		}
	}

	# Figure out what $trimarg should be and then (possibly)
	#  run the sox command for each track in the group.
	# Takes out any beginning or ending quiet time
	# (only take out quiet time if it's at the beginning or end of a group)
	# also normalize (if necessary) at the same time
	# Name of tracks should go from $name[][].wav to $name[][]
	$index = 0;
	while ($index <= $#{$list[$listnum]}) {

		$trimarg = "";
		if ($trimsilence eq "on") {
			# Adjust the volume & trim according to position in list
			if (($index == 0) && ($index == $#{$list[$listnum]})) {
				print "Finding digital silence at the beginning of $oname[$listnum][$index].wav ... ";
				$beg = `wav_find_beginning $name[$listnum][$index].wav`;  chop($beg);
				print "Done.\n";
				print "Finding digital silence at the end of $oname[$listnum][$index].wav ... ";
				$end = `wav_find_end $name[$listnum][$index].wav`;  chop($end);
				print "Done.\n";
				($f1,$f2,$f3,$f4,$f5,$f6,$f7,$endsamp,$f9,$f10,$f11,$f12,$f13) = stat "$oname[$listnum][$index].wav";
				$len = int(($end - $beg - 44)/176.400) + 1;
				$endsamp = $endsamp - $end;  $endsecs = ($endsamp / 176400);
				# Round $endsecs (down) to the thousandth of a second
				$endsecs = int($endsecs * 1000) / 1000;
				$begsamp = $beg;  $beg = int($beg / 176.400);  $begsecs = $beg / 1000;
				print "Trimming ", $begsamp, " samples (", $begsecs, " seconds) from the beginning\n";
				print " and ", $endsamp, " samples (", $endsecs, " seconds) from the end\n";
				print " (only the digital silence) from ", $oname[$listnum][$index], ".wav\n";
				if (($endsamp == 0) && ($beg == 0)) { $trimarg = ""; } else { $trimarg = "trim " . $beg . " " . $len; }
			} elsif ($index == 0) {
				print "Finding digital silence at the beginning of $oname[$listnum][$index].wav ... ";
				$beg = `wav_find_beginning $name[$listnum][$index].wav`;  chop($beg);
				print "Done.\n";
				$begsamp = $beg;  $beg = int($beg / 176.400);  $begsecs = $beg / 1000;
				print "Trimming ", $begsamp, " samples (", $begsecs, " seconds) from the beginning\n";
				print " (only the digital silence) from ", $oname[$listnum][$index], ".wav\n";
				if ($beg == 0) { $trimarg = ""; } else { $trimarg = "trim " . $beg; }
			} elsif ($index == $#{$list[$listnum]}) {
				print "Finding digital silence at the end of $oname[$listnum][$index].wav ... ";
				$end = `wav_find_end $name[$listnum][$index].wav`;  chop($end);
				print "Done.\n";
				($f1,$f2,$f3,$f4,$f5,$f6,$f7,$endsamp,$f9,$f10,$f11,$f12,$f13) = stat "$oname[$listnum][$index].wav";
				$len = int(($end - 44)/176.400) + 1;
				$endsamp = $endsamp - $end;  $endsecs = ($endsamp / 176400);
				# Round $endsecs (down) to the thousandth of a second
                $endsecs = int($endsecs * 1000) / 1000;
				print "Trimming ", $endsamp, " samples (", $endsecs, " seconds) from the end\n";
				print " (only the digital silence) from ", $oname[$listnum][$index], ".wav\n";
				if ($endsamp == 0) { $trimarg = ""; } else { $trimarg = "trim 0 " . $len; }
			}
		}
		# Now run the sox command.
		if (($volarg eq "") && ($trimarg eq "")) {
			print "Leaving $oname[$listnum][$index].wav alone.\n";
		} else {
			print "Moving $oname[$listnum][$index].wav to $oname[$listnum][$index].orig.wav\n";
			`mv -- $name[$listnum][$index].wav $name[$listnum][$index].orig.wav`;
			$soxcmd = "sox $name[$listnum][$index].orig.wav -t wav $name[$listnum][$index].wav $volarg $trimarg";
			print "Running sox command:\n $soxcmd\n";
			`$soxcmd`;
		}

		$index++;
	}

	$listnum++;
	print "\n";
}   # End while ($listnum <= $#list)


# Encoding section
if ($encodeto eq "vorbis") {
	$encodestr = "oggenc " . $oggencflags;
} else {
	$encodestr = "flac " . $flacflags;
}
print "\nEncoding with: ", $encodestr, "\n";
$listnum = 0;
while ($listnum <= $#list) {
	# With flac, must encode the whole list on one command line so that
	# the replaygain option (if there) gets all the files in the same 'album'.
	if ($encodeto eq "flac") {
		# Build a filelist and encode them all at once
		$index = 0;  $filelist = "";
		while ($index <= $#{$list[$listnum]}) {
			$filelist = $filelist . $name[$listnum][$index] . ".wav ";
			$index++;
		}
		# Now encode the whole filelist
		print "\nEncoding list $listnum:\n$encodestr $filelist\n\n";
		`$encodestr $filelist`;
	}

	$index = 0;
	while ($index <= $#{$list[$listnum]}) {

		# Encode (if flac,  encoding already done)
		unless ($encodeto eq "flac") {
			print "\nEncoding ", $oname[$listnum][$index], ".wav\n";
			`$encodestr $name[$listnum][$index].wav`;
		}
		# Tag
		# Set the final comment string ($commentstr)
		$commentstr = "";
		# I used to have DiscID-track in the comment field (from the days when
		# I used to make MP3s) but now it's more appropriate the have them in
		# their separate Ogg tags.  So I commented out the next two lines:
		#if ($tmptrnum eq "") { $commentstr = $discid . " "; }
		#else { $commentstr = $discid . "-" . $tmptrnum . " "; }
		if ($normalize eq "on") {
			if ($normval[$listnum] eq "") {
				$peak = $origpeak[$list[$listnum][$index]];
				# Convert $peak to X.XXX format
				$peak = $peak + "0.0004999999";  $peak = substr($peak, 0, 5);
				$commentstr = $commentstr . "not normalized, ";
				$commentstr = $commentstr . "peak=" . $peak . ", ";
			} else {
				$newpeak = $origpeak[$list[$listnum][$index]] * $normval[$listnum];
				# Convert $newpeak to X.XXX format
				$newpeak = $newpeak + "0.0004999999";  $newpeak = substr($newpeak, 0, 5);
				$commentstr = $commentstr . "normalized x" . $normval[$listnum] . ", ";
				$commentstr = $commentstr . "new peak=" . $newpeak . ", ";
			}
		}
		$commentstr = $commentstr . $comment;
		$timestamp = `date`;  chop $timestamp;
		$commentstr = $commentstr . $timestamp;

		open(TAGFILE, ">>$oname[$listnum][$index].tag");
		print TAGFILE "comment=$commentstr\n";
		print TAGFILE "sourcemedia=$sourcemedia\n";
		print TAGFILE "discid=$discid\n";
		print TAGFILE "encoding=$encoding\n";
		close(TAGFILE);

		# Okay finally, print what the .tag file finally looks like,
		# and then tag the file with the .tag file
		if ($encodeto eq "vorbis") {
			print "Tagging $oname[$listnum][$index].ogg:\n";
			$out=`cat $name[$listnum][$index].tag`;  print $out, "\n";
			`vorbiscomment -w -c $name[$listnum][$index].tag $name[$listnum][$index].ogg`;
		} else {
			if ($flacflags =~ m/--ogg/i) {
				print "Tagging $oname[$listnum][$index].ogg:\n";
				$out=`cat $name[$listnum][$index].tag`;  print $out, "\n";
				`metaflac --import-vc-from=$name[$listnum][$index].tag $name[$listnum][$index].ogg`;
			} else {
				print "Tagging $oname[$listnum][$index].flac:\n";
				$out=`cat $name[$listnum][$index].tag`;  print $out, "\n";
				`metaflac --import-vc-from=$name[$listnum][$index].tag $name[$listnum][$index].flac`;
			}
		}

		# Delete the tag file (if $delfiles is "on")
		if ($delfiles eq "on") {
			# Delete .wav file(s)
			print "\nDeleting ", $oname[$listnum][$index], ".wav\n";
			`rm -- $name[$listnum][$index].wav`;
			$tmpfilename = $oname[$listnum][$index] . ".orig.wav";
			if (-e $tmpfilename) {
				print "Deleting ", $oname[$listnum][$index], ".orig.wav\n";
				`rm -- $name[$listnum][$index].orig.wav`;
			}
			# Delete .tag file
			print "Deleting $oname[$listnum][$index].tag\n";
			`rm -- $name[$listnum][$index].tag`;
			if (-e "$oname[$listnum][$index].tag~") {
				print "Deleting $oname[$listnum][$index].tag~\n";
				`rm -- $name[$listnum][$index].tag~`;
			}
		}

		print "Done.\n\n";
		$index++;
	}

	# Add replaygain tags.
	# If normalize is on,  don't bother with replaygain
	# (only for non-flac files,  which were done during the encode)
	if (($normalize eq "off") && ($encodeto eq "vorbis")) {
		# Now run replaygain (vorbisgain) on all the tracks in the list.
		# First build the list of files in the list.
		$index = 0;  $filelist = "";
		while ($index <= $#{$list[$listnum]}) {
			$filelist = $filelist . $name[$listnum][$index] . ".ogg ";
			$index++;
		}
		# If there is more than one track in the list,  run in album mode
		if ($index > 1) {
			print "Running vorbisgain on group ", $listnum, "...\n";
			`vorbisgain -a $filelist`;
		} else {
			print "Running vorbisgain on track ", $filelist, "...\n";
			`vorbisgain $filelist`;
		}
	}

	# Increment the list and go on...
	$listnum++;
	print "\n\n";
}

# Delete the filenames.txt file
if ($delfiles eq "on") {
	print "Deleting filenames.txt\n";
	`rm filenames.txt`;
	if (-e "filenames.txt~") {
		print "Deleting filenames.txt~\n";
		`rm filenames.txt~`;
	}
}


# Before printing "Done!" list the $posflawed tracks.
if ($posflawed ne "") {
	print "\n\n";
	print "REMINDER: The following tracks were aborted and re-ripped\n";
	print "without the \"-z\" option (and could be flawed):\n\n";
	print $posflawed;
	print "\nSo listen to them just to make sure...\n";
}


# Wait for user to hit <return>,  then either end or start all over again...

print "Done!\n";
#print "   Change CDs and hit <return>.\n";
#print "   Ctrl-C to quit...\n\n> ";

#$inp = <STDIN>;

# To change the behavior so that the script restarts from the beginning,
# uncomment the next line and comment out the "exit;" below.
#reset;

# Just exit for now...
exit;

}


# End of script


