#!/usr/bin/perl
#
# SmarTagger 0.1
# ==============
# I like my MP3 files tagged and named perfectly. 
# SmarTagger is a perl script that read a text file with 
# the album info and use it to write the MP3 tags and 
# rename the files according to a format string.
#
# the author
#    lafor@arrakis.es
#

%configuracion = (); 

### begin  configuration ###

# default config file name
#
$configuracion{FILE}="album.id3";

# default path of mp3 files
#
$configuracion{PATH}=".";

### end of configuration ###

if ($^O=~/win32/i)
{
	 $ls_command = "dir /b";
	 $sep = "\\";
	 $comilla = "\"";
}
else
{
	 $ls_command = "ls -1";
	 $sep = "/";
	 $comilla = "";
}

use MPEG::MP3Info;
$product_name = "SmarTagger";
$version = "0.1";
%tags = ();
if ($#ARGV==-1)
{
    help(0);
    exit(1);
}
foreach (@ARGV)
{
    if (/--file=(.+)/)
    {
	$configuracion{FILE}= $1;
    }
    if (/--path=(.+)/)
    {
	$configuracion{PATH}= $1;
    }
    if (/--config/)
    {
	$configuracion{CONFIGURACION}=1;
    }
    if (/--help/)
    {
	help(1);
	exit(1);
    }
    if (/--print/)
    {
	$configuracion{PRINT}=1;
    }
    if (/--verbose/)
    {
	$configuracion{VERBOSE}=1;
    }
    if (/--simulate/)
    {
	$configuracion{SIMULATE}=1;
    }
    if (/--tag/)
    {
	$configuracion{TAGGEAR}=1;
    }
    if (/--ren/)
    {
	$configuracion{RENOMBRAR}=1;
    }
}

if (verbose())
{
    print "Parametros leidos:\n";
    foreach (keys(%configuracion))
    {
	print "$_ => $configuracion{$_}\n";
    }
}

open(FH,"$configuracion{PATH}${sep}$configuracion{FILE}") or die( "Error abriendo fichero: $!\n");
@the_file = <FH>;
close(FH);
$c=0;

# contenido del fichero
foreach $linea (@the_file)
{
	 chomp $linea;
	 if (verbose())
	 {
		  print "$c: $linea\n";
	 } 
	 ($tag_name,$tag_value) = $linea =~ /\s*([^:]{3})[^:]+\s*:\s*(.+)\s*$/;
	 if ($tag_name ne "")
	 {
		  $tag_name =~ tr/[A-Z]/[a-z]/;
		  $tags{$tag_name} = $tag_value;
	 }
	 else
	 {
		  ($track,$dev_null,$song_name) =  $linea =~ /^(\d\d?)(\s*|\.)?([^.]*)$/;
		  if ( $track ne "" )
		  {
				if (length $track==1)
				{
					 $tags{"0${track}"} = $song_name;
				}
				else
				{
					 $tags{$track} = $song_name;
				}
		  }
	 }
	 $c++;
}

if (is_on("CONFIGURACION"))
{
	 print "Tags extracted from config file:\n";
	 foreach (keys(%tags))
	 {
		  print "$_ => $tags{$_}\n";
	 }
}

# tags exigidos: format
if ($tags{"for"} eq "" || !defined($tags{"for"}))
{
	 print "There is no format especified in $configuracion{FILE}\n";
	 exit(0);
}

# leer los nombres de ficheros con extension mp3
if (verbose())
{
	 print("comando para leer ficheros: $ls_command ${comilla}$configuracion{PATH}${sep}*.mp3${comilla}\n");
}
open( MP3, "$ls_command ${comilla}$configuracion{PATH}${sep}*.mp3${comilla} |") or die("Error listando ficheros ($!)\n");
@mp3_files = <MP3>;
close(MP3);
$c=0;
foreach $fich (@mp3_files)
{
	 chomp $fich;
	 ($track) = $fich =~ /(\d\d?)/;
	 $fich =~ s/^\.\///; # remove dot-slash on unix
	 if (length $track==1)
	 {
		  $cancion = $tags{"0${track}"};
	 }
	 else
	 {
		  $cancion = $tags{$track};
	 }
	 if (verbose())
	 {
		  print "cancion: $cancion\n";
	 }
	 if (is_on("PRINT"))
	 {
		  print_tags($fich, 'File: %f |  Artist: %A |  Album: %a |  Song: %s |  Genre: %g |  Year: %y |  Comment: %c');
	 }
	 if (is_on("TAGGEAR") && $cancion ne "")
	 {
		  if (verbose())
		  {
				print("$track => $configuracion{PATH}${sep}$fich | $cancion | $tags{art} | $tags{alb} | $tags{yea} | $tags{com} | $tags{gen}\n");
		  }
		  if (!is_on("SIMULATE"))
		  { 
				set_mp3tag("$configuracion{PATH}${sep}$fich", $cancion, $tags{art}, $tags{alb}, $tags{yea}, $tags{com}, $tags{gen});
		  }
		  else 
		  {
				print "set_mp3tag(\"$configuracion{PATH}${sep}$fich\", $cancion, $tags{art}, $tags{alb}, $tags{yea}, $tags{com}, $tags{gen});\n";
		  }
	 }
	 if (is_on("RENOMBRAR") && $cancion ne "")
	 {
		  $new_name = formatear($tags{for},$fich,$cancion,$tags{art},$tags{alb},$tags{yea},$tags{com},$tags{gen},$track),"\n";
		  if ($new_name eq "")
		  {
				print "There is some error with your configuration. Is the format string empty?\n";
				exit(1);
		  }
		  if (is_on("SIMULATE"))
		  {
				print "Renaming \"$configuracion{PATH}${sep}$fich\" => \"$configuracion{PATH}${sep}$new_name\.mp3\"\n";
		  }
		  else
		  {
				$ret_code = rename "$configuracion{PATH}${sep}$fich", "$configuracion{PATH}${sep}$new_name\.mp3";
				if ( $ret_code != 1 )
				{
					 print "Error renaming file: $!\n";
					 $cancion="";
				}
		  }
	 }
	 if (is_on("RENOMBRAR") || is_on("TAGGEAR"))
	 {
		  if ($cancion eq "")
		  {
				print "---Error: $fich\n";
				exit(1);
		  }
		  else 
		  {
				print "Ok: [$track] $cancion\n";
		  }
	 }
	 $c++;
}

sub print_tags
{
	 my ($fichero,$formato) = @_;
	 $tagref = get_mp3tag "$configuracion{PATH}${sep}$fichero";
	 ($xsongname, $xartist, $xalbum, $xyear, $xcomment, $xgenre) = ($tagref->{TITLE}, $tagref->{ARTIST}, $tagref->{ALBUM}, $tagref->{YEAR}, $tagref->{COMMENT}, $tagref->{GENRE});
	 $xsongname =~ s/\0//g if $xsongname;
	 $xartist =~ s/\0//g if $xartist;
	 $xalbum =~ s/\0//g if $xalbum;
	 $xyear =~ s/\0//g if $xyear;
	 $xcomment =~ s/\0//g if $xcomment;
	 $xgenre =~ s/\0//g if $xgenre;
	 
	 $foo = $^W;
	 $^W = 0;
	 print formatear($formato,$fich,$xsongname,$xartist,$xalbum,$xyear,$xcomment,$xgenre),"\n";
	 $^W = $foo;
}

sub formatear
{
	 my ($formato,$fich,$songname,$artist,$album,$year,$comment,$genre,$pista) = @_;
	 $formato =~ s/\%f/$fich/g;
	 $formato =~ s/\%s/$songname/g;
	 $formato =~ s/\%A/$artist/g;
	 $formato =~ s/\%a/$album/g;
	 $formato =~ s/\%y/$year/g;
	 $formato =~ s/\%c/$comment/g;
	 $formato =~ s/\%g/$genre/g;
	 $formato =~ s/\%t/$pista/g;
	 $formato =~ s/\|/\n/g;
	 if (verbose())
	 {
		  print "formateada: $formato\n";
	 }
	 return $formato;
}

sub verbose()
{
	 return is_on("VERBOSE");
}
sub is_on
{
	 my($opcion) = @_;
	 return $configuracion{$opcion}==1;
}
sub help
{
my ($long_output) = @_;
print <<"FIN_HELP";
	 
$product_name $version
		  
Usage: $0 --print --config --file=<configuration> --path=<path to mp3s files> --simulate --tag --ren --help

FIN_HELP

if ($long_output)
{
	 verbose_help();
}
}

sub verbose_help
{
	 print <<"FIN_HELP";

 --print         Print the current ID3 tags of each MP3 file. 
 --config        Parse the config file and writes it to standard output.
 --file=<config> File with ID3 info to tag the songs.
 --path=<path>   Path to MP3 files.
 --simulate      Show what will be done but modify nothing.
 --tag           Writes the tag info in the song.
 --ren           Rename the files.
 --help          Show this message.

ID3 tag file: See example.id3
The format string to rename files:
   %A -> Artist
   %a -> album
   %s -> Song
   %g -> Genre
   %y -> Year
   %c -> Comment
   %t -> Track number

Example: %t.(%A-%a) %s

The song list format is free but the most your format are near the mine, the best the result will be.
My format: TT.song title
TT are the track number in two digits format.
Example: 07.Semilla Negra

FIN_HELP
}
