#!/usr/local/bin/perl -w
# $Id: filenametoid3,v 1.9 2003/12/12 06:30:10 ianb Exp $
# Ian Beckwith <ianb@nessie.mcc.ac.uk>
# v1 20030508
# v2 20031024 MP3::Archive support

use vars qw($me);
$me=($0=~/(?:.*\/)?(.*)/)[0];

use MP3::Tag;
use MP3::Archive;
use strict;

my $archive=new MP3::Archive;

use vars qw($ALBUM $TRACK $GUESS);

$ALBUM=$MP3::Archive::ALBUM;
$TRACK=$MP3::Archive::TRACK;
$GUESS=$MP3::Archive::GUESS;
my $tracktype=$GUESS;

my $justone=0;
my $justtwo=0;
my $verbose=0;
my $dryrun=0;
my $wipe=0;
my $emptyonly=0;
my $doneargs=0;
my ($dotracknum,$doartist,$doalbum,$dotrack)=(0,0,0,0);
my $doall=1;
my $donesomething=0;

while($_=shift)
{
	if(/^-/ && !$doneargs)
	{
		if   (/-1/) { $justone=1; $justtwo=0;  }
		elsif(/-2/) { $justone=0; $justtwo=1;  }
		elsif(/-v/) { $verbose=1;              }
		elsif(/-q/) { $verbose=0;              }
		elsif(/-d/) { $dryrun=1;               }
		elsif(/-w/) { $wipe=1;                 }
		elsif(/-e/) { $emptyonly=1;            }
		elsif(/-a/) { $tracktype=$ALBUM;       }
		elsif(/-t/) { $tracktype=$TRACK;       }
		elsif(/-g/) { $tracktype=$GUESS;       }
		elsif(/-N/) { $dotracknum=1; $doall=0; }
		elsif(/-A/) { $doartist=1;   $doall=0; }
		elsif(/-L/) { $doalbum=1;    $doall=0; }
		elsif(/-T/) { $dotrack=1;    $doall=0; }
		elsif(/--/) { $doneargs=1; }
		else { usage(); }
		next;
	}
	$donesomething=1;

	my $file=$_;
	unless(-e $file)
	{
		warn("$me: $file: not found\n");
		next;
	}
	
    my $isalbum=1; #default
	# No tracknumber or album unless its an album track
	if(($tracktype==$TRACK) ||
	   (($tracktype==$GUESS) &&
		($archive->isalbum($file)) ||
		($archive->config->get("format_default") =~/track/i)))
	{
		$isalbum=0;
	}
	my($fntracknum,$fnartist,$fnalbum,$fntrack);
	if($doartist || $doall)
	{
		$fnartist=$archive->artist($file,$tracktype);
		unless(defined($fnartist)) { warn("$me: $file: cannot extract artist\n"); next; }
	}
	if(($dotracknum || $doall) && $isalbum)
	{
		$fntracknum=$archive->tracknum($file,$tracktype);
		unless(defined($fntracknum)) { warn("$me: $file: cannot extract track number\n"); next; }
	}
	if(($doalbum || $doall) && $isalbum)
	{
		$fnalbum=$archive->album($file,$tracktype);
		unless(defined($fnalbum)) { warn("$me: $file: cannot extract album\n"); next; }
	}
	if($dotrack || $doall)
	{
		$fntrack=$archive->track($file,$tracktype);
		unless(defined($fntrack)) { warn("$me: $file: cannot extract track name\n"); next; }
	}

	my $mp3=MP3::Tag->new($file);
	unless($mp3)
	{
		warn("$me: cannot open $mp3: $!\n");
		next;
	}
	
	$mp3->get_tags;

	my($v1tracknum,$v1artist,$v1album,$v1track)=(undef,undef,undef,undef);
	my($v2tracknum,$v2artist,$v2album,$v2track)=(undef,undef,undef,undef);
	my($v1,$v2)=(undef,undef);
	
	# ID3v1
	unless($justtwo)
	{
		if(exists($mp3->{ID3v1}))
		{
			$v1=$mp3->{ID3v1};
			$v1tracknum=$v1->track;
			$v1artist  =$v1->artist;
			$v1album   =$v1->album;
			$v1track   =$v1->song;
			if($wipe && !$dryrun)
			{
				$v1->remove_tag;
			}
		}
	}

	#ID3v2
	unless($justone)
	{
		if(exists($mp3->{ID3v2}))
		{
			$v2=$mp3->{ID3v2};
			$v2tracknum=$v2->track;
			$v2artist  =$v2->artist;
			$v2album   =$v2->album;
			$v2track   =$v2->song;
			
			if($wipe && !$dryrun)
			{
				$v2->remove_tag;
				$mp3->close;
				$mp3=MP3::Tag->new($file);
				unless($mp3)
				{
					warn("$me: cannot reopen $mp3: $!\n");
					next;
				}
				$mp3->get_tags;
			}
		}
	}
	
	unless($justone)
	{
		unless((exists($mp3->{ID3v2}))||$dryrun)
		{
			$mp3->new_tag("ID3v2");
			$v2=$mp3->{ID3v2};
		}

		if(($dotracknum || $doall) && defined($fntracknum))
		{
			unless($emptyonly && isemptynum($v2tracknum))
			{
				print "$file:id3v2:Track number:$fntracknum\n" if ($verbose||$dryrun);
				unless($dryrun)
				{
					$v2->remove_frame("TRCK");
					$v2->add_frame("TRCK",$fntracknum) unless($dryrun);
				}
			}
		}
		if(($doartist || $doall) && defined($fnartist))
		{
			unless($emptyonly && isempty($v2artist))
			{
				print "$file:id3v2:Artist:$fnartist\n" if ($verbose||$dryrun);
				unless($dryrun)
				{
					$v2->remove_frame("TPE1");
					$v2->add_frame("TPE1",$fnartist);
				}
			}
		}
		if(($doalbum || $doall) && defined($fnalbum))
		{
			unless($emptyonly && isempty($v2album))
			{
				print "$file:id3v2:Album:$fnalbum\n" if ($verbose||$dryrun);
				unless($dryrun)
				{
					$v2->remove_frame("TALB");
					$v2->add_frame("TALB",$fnalbum);
				}
			}
		}
		if(($dotrack || $doall) && defined($fntrack))
		{
			unless($emptyonly && isempty($v2track))
			{
				print "$file:id3v2:Track:$fntrack\n" if ($verbose||$dryrun);
				unless($dryrun)
				{
					$v2->remove_frame("TIT2");
					$v2->add_frame("TIT2",$fntrack);
				}
			}
		}
		
		$v2->write_tag unless($dryrun);
	}

	unless($justtwo)
	{
		unless((exists($mp3->{ID3v1})) || $dryrun)
		{
			$mp3->new_tag("ID3v1");
			$v1=$mp3->{ID3v1};
		}
 		if(($dotracknum || $doall) && defined($fntracknum))
		{
			unless($emptyonly && isemptynum($v1tracknum))
			{
				print "$file:id3v1:Track number:$fntracknum\n" if ($verbose||$dryrun);
				$v1->track($fntracknum) unless($dryrun);
			}
		}
		if(($doartist || $doall) && defined($fnartist))
		{
			unless($emptyonly && isempty($v1artist))
			{
				print "$file:id3v1:Artist:$fnartist\n" if ($verbose||$dryrun);
				$v1->artist($fnartist) unless($dryrun);
			}
		}
		if(($doalbum || $doall) && defined($fnalbum))
		{
			unless($emptyonly && isempty($v1album))
			{
				print "$file:id3v1:Album:$fnalbum\n" if ($verbose||$dryrun);
				$mp3->{ID3v1}->album($fnalbum) unless($dryrun);
			}
		}
		if(($dotrack || $doall) && defined($fntrack))
		{
			unless($emptyonly && isempty($v1track))
			{
				print "$file:id3v1:Track:$fntrack\n" if ($verbose||$dryrun);
				$mp3->{ID3v1}->song($fntrack) unless($dryrun);
			}
		}
		$v1->write_tag unless($dryrun);
	}
	$mp3->close;
}

unless($donesomething)
{
	usage();
}

sub isempty
{
	my $it=shift;
	return 0 unless(defined($it));
	return 0 if($it=~/^\s*$/);
	return 1;
}

sub isemptynum
{
	my $it=shift;
	return 0 unless(defined($it));
	return 0 unless($it=~/^\d+$/);
	return 0 if($it == 0);
	return 1;
}


sub usage
{
	die("Usage: $me [-vqd12atgewNALTh] file.mp3..\n".
		" -v\tVerbose.\n".
		" -q\tQuiet (default).\n".
		" -d\tDry run.\n".
		" -1\tWrite ID3v1 tag only.\n".
		" -2\tWrite ID3v2 tag only.\n".
		" -a\tTreat as album tracks.\n".
		" -t\tTreat as non-album tracks.\n".
		" -g\tGuess track types from directory (default).\n".
		" -e\tOnly set tags if they are empty or not present.\n".
		" -w\tWipe existing tags first.\n".
		" -N\tSet trackNumber.\n".
		" -A\tSet Artist.\n".
		" -L\tSet aLbum.\n".
		" -T\tSet Track.\n".
		" -h\tThis help.\n".
		" --\tEnd of options.\n".
		"Default: set all four data types.\n");
}

		
__DATA__

=head1 NAME

filenametoid3 - set id3 metadata from filename

=head1 SYNOPSIS

B<filenametoid3> [I<-v>] [I<-q>] [I<-d>] [I<-1>] [I<-2>] [I<-a>] [I<-t>] [I<-g>] [I<-e>] [I<-w>] [I<-N>] [I<-A>] [I<-L>] [I<-T>] [I<-h>] [I<file.mp3>...]

=head1 DESCRIPTION

filenametoid3 parses given mp3 filenames and sets the id3 (v1 and v2)
metadata.

If none of the B<-N>/B<-A>/B<-L>/B<-T> options are set, it defaults to
updating all data.

For details on how to configure your style of filenames by configuring
F<.mp3archiverc>, see L<MP3::Archive::Config(3)>.

=head1 OPTIONS

=over 4

=item B<-v>

Verbose.

=item B<-q>

Quiet (no output). This is the default.

=item B<-d>

Dry run (just show what would be done).	

=item B<-1>

Write ID3V1 tag only

=item B<-2>

Write ID3V2 tag only

=item B<-a>

Treat files as album tracks.

=item B<-t>

Treat files as non-album tracks.

=item B<-g>

Guess whether to treat files as album tracks or not, based on the
current directory of the file.

=item B<-e>

Only set tags if they are empty, just whitespace, or not present.

=item B<-w>

Wipe existing id3 tags.

=item B<-N>

Only update the id3 tracknumber tags.

=item B<-A>

Only update the id3 artist tags.

=item B<-L>

Only update the id3 album tags.

=item B<-T>

Only update the id3 track (song title) tags.

=item B<-h>

Show a short help message.

=back

=head1 BUGS

None known. Please report any found to ianb@nessie.mcc.ac.uk	

=head1 SEE ALSO    

L<id3tofilename(1)>, L<MP3::Archive(3)>, L<MP3::Archive::Config(3)>,
L<mp3-archive-tools(1)>, L<mp3lint(1)>

=head1 AUTHOR

Ian Beckwith <ianb@nessie.mcc.ac.uk>

=head1 AVAILABILITY

filenametoid3 is part of the mp3-archive-tools package.

The latest version can be found at:

B<http://nessie.mcc.ac.uk/~ianb/projects/mp3-archive-tools/>

=head1 COPYRIGHT

Copyright 2003 Ian Beckwith <ianb@nessie.mcc.ac.uk>

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.

=cut


	
