#!/usr/bin/perl -w
use strict;
my $version  = "0.30";

my $driver = 0;
my $old = $^W; $^W = 0;
$driver++ if (shift eq "-driver");
$^W = $old;

my $bladeenc = "bladeenc -192 -DELETE";
my $paranoia = "cdparanoia -w";

print "\nRipEnc.pl v$version";
print "\n---------------\n\n";

my ($tag, @tocfo) = &toc;

print "\nDo you want to ID3 tag the MP3? (Y/n): ";
my $ans = <STDIN>;
chomp $ans;
unless (uc($ans) eq "N") {
  print 
    "\nThe following questions will determine what information is",
    "\nwritten as the ID3 Tag. If you don't know the answer, just",
    "\nleave it blank.\n";
  print "\nWhat year was this album published? ";
  $$tag{'year'} = <STDIN>;
  chomp $$tag{'year'};
  $$tag{'genre'} = &get_genre;
  my $files = &ripenc(@tocfo);
  tagmp3($files, $tag) unless ($ans eq "n");
} else {
  my $files = &ripenc(@tocfo);
}
  
  
sub toc {
  my %tag;

  print "[*] Looking up your CD in the CDDB.\n\n";
  system "cda on" unless $driver;
  my @toc;
  if ($driver) {
    @toc = split /\n/, `cat *=cddb.txt`;
  } else {
    @toc = split /\n/, `cda toc`;
  }
  # if cda jacks up
  if ($toc[0] =~ /Goodbye!/) {
    print("\n$0: Problem with 'cda' -- check error messages.\n");
    exit(-1);
  } else {
    if ($toc[0] eq "This command is not valid in the current state.") {
      print("\n$0: Problem with 'cda' -- check cdreader.\n");
      exit(-1);
    }
  }
  # if this is an unknown disc, alert and quit
  if ($toc[1] eq "(unknown disc title)") {
    print("\n$0: No entry in the CDDB!\n");
    system "cda off" unless $driver;
    exit(-1);
  }
  
  # set index pointer to where relevant cddb data begins
  my ($index, $idfound);
  for ($index = 0; $toc[$index] !~ /^Disc ID/; $index++) {
    if ($index > $#toc) {
      system "cda off" unless $driver;
      die(
	  "!!BaD ERROR!! Please report to brainsik\@theory.org.\n",
	  "Couldn't find \"Disc ID\" in `cda toc` output.\n",
	  "Here's what it sent back:\n",
	  @toc
	 );
    }
  }
  
  print "\n[*] Extracting artist and album names...\n\n";
  # artitst / title
  my ($artist, $album);
  print STDERR "$toc[$index + 1]\n";
  if ($toc[$index + 1] !~ m|/|) {
    # then this is a self-titled album
    $toc[$index + 1] =~ m:(.+):;
    $artist = $album = $1;
  } else {			
    $toc[$index + 1] =~ m:([^/]+) / (.+):;
    $artist = $1;
    $album = $2;
  }

  $artist =~ s|\s+$||;       # remove trailing whitespace
  $tag{'artist'} = $artist;
  $album =~ s|\s+$||;        # remove trailing whitespace
  $tag{'album'} = $album;
  PrepStr(\$artist);
  PrepStr(\$album);
			    
  print "[*] Writing CDDB table of contents to file $artist=$album=cddb.txt\n\n";
  (open TOCFILE, ">$artist=$album=cddb.txt") unless $driver;
  my $i;
  foreach $i (@toc) {
    print TOCFILE "$i\n" unless $driver;
  }
  close TOCFILE unless $driver;
  
  # track / song title
  print "[*] Extracting track number and song titles...\n\n";
  my (@song, $title, $track);
  for ($i = 3; $toc[$i+1] !~ /Total Time/; $i++) {
    print STDERR "$toc[$index + $i]\n";
    $toc[$index + $i] =~ m| (\d+) \d+:\d+  (.+)|;
    $track = $1;
    $title = $2;
    $title =~ s:\s+$::;   # remove trailing whitespace
    $title =~ s:[*]+$::;  # remove trailing asterick
    push @{$tag{'song'}}, $title;
    PrepStr(\$title);
    push @song, "$track=$title";
  }
  print STDERR "\n";
  
  system "cda off" unless $driver;
  return(\%tag,$artist,$album,@song);
}

sub ripenc {
  my ($artist, $album, @song) = @_;
  my @title;
  
  # rip all the songs to the disk
  print "\n[*] Ripping all songs from disc to disk...\n";
  for (my $i = 1; $i-1 <= $#song; $i++) {
    push @title, quotemeta "$artist=$album=$song[$i-1].wav";
    print "\nprogname: $paranoia $i $title[$i-1]\n";
    system "$paranoia $i $title[$i-1]" unless $driver;
  }
  # batch compress them
  print "\n[*] Compressing songs into MP3 format...\n";
  print "$0: $bladeenc @title\n";
  system "$bladeenc @title" unless $driver;

  return \@title;
}


sub tagmp3 {
  my ($files, $tag) = @_;
  my $input;
  
  my ($year, $comment, $genre);
  unless ($$tag{'year'} eq "") {
    $year = " -y " . $$tag{'year'};
  } else { $year = ""; }
  unless ($$tag{'genre'} eq "") {
    $genre = " -g " . $$tag{'genre'};
  } else { $genre = ""; }
  
  for (my $i = 0; $i <= $#$files; $i++) {
    $$files[$i] =~ s|wav$|mp3|;
    my $command = "mp3info" .
      ' -t "' . shift(@{$$tag{'song'}}) . '"' .
      ' -a "' . $$tag{'artist'}         . '"' .
      ' -l "' . $$tag{'album'}          . '"' .
	$year .
      ' -c "' . "Track " . ($i + 1)     . '"' .
       $genre .
        " "   . $$files[$i];
    print "\n[*] Writing MP3 ID3 Tag...\n\n";
    print "$0: $command\n";
    system $command;
  }
}


sub PrepStr {
  my $str = shift;
  $$str =~ s|=|--|;    # subst equal with double dash
  $$str =~ s| / |=|g;  # subst the slash with an equal
  $$str =~ s| |_|g;    # subst spaces with underscores
  $$str =~ s|/|\\|g;   # fix problem with filenames having '/'
}

sub get_genre {
  my @genre_list = (
		 "Blues",
		 "Classic Rock",
		 "Country",
		 "Dance",
		 "Disco",
		 "Funk",
		 "Grunge",
		 "Hip-Hop",
		 "Jazz",
		 "Metal",
		 "New Age",
		 "Oldies",
		 "Other",
		 "Pop",
		 "R&B",
		 "Rap",
		 "Reggae",
		 "Rock",
		 "Techno",
		 "Industrial",
		 "Alternative",
		 "Ska",
		 "Death Metal",
		 "Pranks",
		 "Soundtrack",
		 "Euro-Techno",
		 "Ambient",
		 "Trip-Hop",
		 "Vocal",
		 "Jazz+Funk",
		 "Fusion",
		 "Trance",
		 "Classical",
		 "Instrumental",
		 "Acid",
		 "House",
		 "Game",
		 "Sound Clip",
		 "Gospel",
		 "Noise",
		 "Alternative Rock",
		 "Bass",
		 "Soul",
		 "Punk",
		 "Space",
		 "Meditative",
		 "Instrumental Pop",
		 "Instrumental Rock",
		 "Ethnic",
		 "Gothic",
		 "Darkwave",
		 "Techno-Industrial",
		 "Electronic",
		 "Pop-Folk",
		 "Eurodance",
		 "Dream",
		 "Southern Rock",
		 "Comedy",
		 "Cult",
		 "Gangsta",
		 "Top 40",
		 "Christian Rap",
		 "Pop/Funk",
		 "Jungle",
		 "Native US",
		 "Cabaret",
		 "New Wave",
		 "Psychadelic",
		 "Rave",
		 "Showtunes",
		 "Trailer",
		 "Lo-Fi",
		 "Tribal",
		 "Acid Punk",
		 "Acid Jazz",
		 "Polka",
		 "Retro",
		 "Musical",
		 "Rock & Roll",
		 "Hard Rock",
		 "Folk",
		 "Folk-Rock",
		 "National Folk",
		 "Swing",
		 "Fast Fusion",
		 "Bebob",
		 "Latin",
		 "Revival",
		 "Celtic",
		 "Bluegrass",
		 "Avantgarde",
		 "Gothic Rock",
		 "Progressive Rock",
		 "Psychedelic Rock",
		 "Symphonic Rock",
		 "Slow Rock",
		 "Big Band",
		 "Chorus",
		 "Easy Listening",
		 "Acoustic",
		 "Humour",
		 "Speech",
		 "Chanson",
		 "Opera",
		 "Chamber Music",
		 "Sonata",
		 "Symphony",
		 "Booty Bass",
		 "Primus",
		 "Porn Groove",
		 "Satire",
		 "Slow Jam",
		 "Club",
		 "Tango",
		 "Samba",
		 "Folklore",
		 "Ballad",
		 "Power Ballad",
		 "Rhytmic Soul",
		 "Freestyle",
		 "Duet",
		 "Punk Rock",
		 "Drum Solo",
		 "Acapella",
		 "Euro-House",
		 "Dance Hall",
		 "Goa",
		 "Drum & Bass",
		 "Club-House",
		 "Hardcore",
		 "Terror",
		 "Indie",
		 "BritPop",
		 "Negerpunk",
		 "Polsk Punk",
		 "Beat",
		 "Christian Gangsta Rap",
		 "Heavy Metal",
		 "Black Metal",
		 "Crossover",
		 "Contemporary Christian",
		 "Christian Rock",
		 "Merengue",
		 "Salsa",
		 "Trash Metal",
		);
  
  my $input;
  while(1) {
    print "Album NUMERICAL genre (?=list): ";
    $input = <STDIN>;
    chomp $input;
    return($input) unless ($input eq "?");
    for (my $i = 0; $i <= $#genre_list; $i++) {
      print "[$i]: $genre_list[$i]\n";
    }
  }
}
