1package MP3::Tag; 2 3################ 4# 5# provides a general interface for different modules, which can read tags 6# 7# at the moment MP3::Tag works with MP3::Tag::ID3v1 and MP3::Tag::ID3v2 8 9use strict; 10use MP3::Tag::ID3v1; 11use MP3::Tag::ID3v2; 12use MP3::Tag::File; 13use vars qw/$VERSION %config/; 14 15$VERSION="0.40"; 16 17=pod 18 19=head1 NAME 20 21MP3::Tag - Module for reading tags of MP3 audio files 22 23=head1 SYNOPSIS 24 25 use MP3::Tag; 26 27 $mp3 = MP3::Tag->new($filename); 28 29 # get some information about the file in the easiest way 30 ($song, $track, $artist, $album) = $mp3->autoinfo(); 31 32 # or have a closer look on the tags 33 34 # scan file for existing tags 35 $mp3->get_tags; 36 37 if (exists $mp3->{ID3v1}) { 38 # read some information from the tag 39 $id3v1 = $mp3->{ID3v1}; # $id3v1 is only a shortcut for $mp3->{ID3v1} 40 print $id3v1->song; 41 42 # change the tag contents 43 $id3v1->all("Song","Artist","Album",2001,"Comment",10,"Top 40"); 44 $id3v1->write_tag; 45 } 46 47 if (exists $mp3->{ID3v2}) { 48 # read some information from the tag 49 ($name, $info) = $mp3->{ID3v2}->get_frame("TIT2"); 50 # delete the tag completely from the file 51 $mp3->{ID3v2}->remove_tag; 52 } else { 53 # create a new tag 54 $mp3->new_tag("ID3v2"); 55 $mp3->{ID3v2}->add_frame("TALB", "Album title"); 56 $mp3->write_tag; 57 } 58 59 $mp3->close(); 60 61=head1 AUTHOR 62 63Thomas Geffert, thg@users.sourceforge.net 64 65=head1 DESCRIPTION 66 67Tag is a wrapper module to read different tags of mp3 files. 68It provides an easy way to access the functions of seperate moduls 69which do the handling of reading/writing the tags itself. 70 71At the moment MP3::Tag::ID3v1 and MP3::Tag::ID3v2 are supported. 72 73=over 4 74 75=item new() 76 77 $mp3 = MP3::Tag->new($filename); 78 79Creates a mp3-object, which can be used to retrieve/set 80different tags. 81 82=cut 83 84sub new { 85 my $class = shift; 86 my $filename = shift; 87 my $mp3data; 88 if (-f $filename) { 89 $mp3data = MP3::Tag::File->new($filename); 90 } 91 # later it should hopefully possible to support also http/ftp sources 92 # with a MP3::Tag::Net module or something like that 93 if ($mp3data) { 94 my $self={filename=>$mp3data}; 95 bless $self, $class; 96 return $self; 97 } 98 return undef; 99} 100 101=pod 102 103=item get_tags() 104 105 [old name: getTags() . The old name is still available, but its use is not advised] 106 107 @tags = $mp3->get_tags; 108 109Checks which tags can be found in the mp3-object. It returns 110a list @tags which contains strings identifying the found tags, like 111"ID3v1" or "ID3v2" . 112 113Each found tag can then be accessed with $mp3->{tagname} , where tagname is 114a sting returned by get_tags ; 115 116Use the information found in L<MP3::Tag::ID3v1> and L<MP3::Tag::ID3v2> 117to see what you can do with the tags. 118 119=cut 120 121################ tag subs 122 123sub get_tags { 124 my $self = shift; 125 my (@IDs, $ref); 126 if (exists $self->{gottags}) { 127 push @IDs, "ID3v1" if exists $self->{ID3v1}; 128 push @IDs, "ID3v2" if exists $self->{ID3v2}; 129 } elsif ($self->{filename}->open()) { 130 $self->{gottags}=1; 131 if (defined ($ref = MP3::Tag::ID3v2->new($self->{filename}))) { 132 $self->{ID3v2} = $ref; 133 push @IDs, "ID3v2"; 134 } 135 if(defined ($ref = MP3::Tag::ID3v1->new($self->{filename}))) { 136 $self->{ID3v1} = $ref; 137 push @IDs, "ID3v1"; 138 } 139 } 140 return @IDs; 141} 142 143# keep old name for a while 144*getTags = \&get_tags; 145 146=pod 147 148=item new_tag() 149 150 [old name: newTag() . The old name is still available, but its use is not advised] 151 152 $tag = $mp3->new_tag($tagname); 153 154Creates a new tag of the given type $tagname. You 155can access it then with $mp3->{$tagname}. At the 156moment ID3v1 and ID3v2 are supported as tagname. 157 158Returns an tag-object: $mp3->{$tagname}. 159 160=cut 161 162sub new_tag { 163 my $self = shift; 164 my $whichTag = shift; 165 if ($whichTag =~ /1/) { 166 $self->{ID3v1}= MP3::Tag::ID3v1->new($self->{filename},1); 167 return $self->{ID3v1}; 168 } elsif ($whichTag =~ /2/) { 169 $self->{ID3v2}= MP3::Tag::ID3v2->new($self->{filename},1); 170 return $self->{ID3v2}; 171 } 172} 173 174# keep old name for a while 175*newTag = \&new_tag; 176 177#only as a shortcut to {filename}->close to explicitly close a file 178 179=pod 180 181=item close() 182 183 $mp3->close; 184 185You can use close() to explicitly close a file. Normally this is done 186automatically by the module, so that you do not need to do this. 187 188=cut 189 190sub close { 191 my $self=shift; 192 $self->{filename}->close; 193} 194 195=pod 196 197=item genres() 198 199 $allgenres = $mp3->genres; 200 $genreName = $mp3->genres($genreID); 201 $genreID = $mp3->genres($genreName); 202 203Returns a list of all genres (reference to an array), or the according 204name or id to a given id or name. 205 206This function is only a shortcut to MP3::Tag::ID3v1->genres. 207 208This can be also called as MP3::Tag->genres; 209 210=cut 211 212sub genres { 213 # returns all genres, or if a parameter is given, the according genre 214 my $self=shift; 215 return MP3::Tag::ID3v1::genres(shift); 216} 217 218=pod 219 220=item autoinfo() 221 222 ($song, $track, $artist, $album) = $mp3->autoinfo(); 223 $info_hashref = $mp3->autoinfo(); 224 225autoinfo() returns information about the song name, song number, 226artist and album name. It can get this information from an 227ID3v1-tag, an ID3v2-tag and from the filename itself. 228 229It will as default first try to find a ID3v2-tag to get this 230information. If this cannot be found it tries to find a ID3v1-tag and 231if this is not present either, it will use the filename to retrieve 232the information. 233 234You can change the order of this with the config() command. 235 236autoinfo() returns an array with the information or a hashref. The hash 237has four keys 'song', 'track', 'artist' and 'album' where the information is 238stored. 239 240=cut 241 242sub autoinfo() { 243 my ($self) = shift; 244 245 my @order; 246 if (exists $config{autoinfo}) { 247 @order = @{$config{autoinfo}}; 248 } else { 249 @order = ("ID3v2","ID3v1","filename"); 250 } 251 252 $self->get_tags unless exists $self->{gottags}; 253 254 my ($song, $track, $artist, $album)=("","","",""); 255 foreach my $part (@order) { 256 if (exists $self->{$part}) { 257 #get the info 258 $song=$self->{$part}->song; 259 $track=$self->{$part}->track; 260 $artist=$self->{$part}->artist; 261 $album=$self->{$part}->album; 262 last; 263 } 264 } 265 return wantarray ? ($song, $track, $artist, $album) : 266 { song => $song, track => $track, artist => $artist, album => $album } ; 267} 268 269=pod 270 271=item config 272 273 MP3::Tag->config("item", options, ...); 274 275Possible items are: 276 277* autoinfo 278 279 Configure the order in which ID3v1-, ID3v2-tag and filename are used 280 by autoinfo. Options can be "ID3v1","ID3v2","filename". The order 281 in which they are given to config also sets the order how they are 282 used by autoinfo. If an option is not present, it will not be used 283 by auotinfo. 284 285 $mp3->config("autoinfo","ID3v1","ID3v2","filename"); 286 287 sets the order to check first ID3v1, then ID3v2 and at last the 288 Filename 289 290 $mp3->config("autoinfo","ID3v1","filename","ID3v2"); 291 292 sets the order to check first ID3v1, then the Filename and last 293 ID3v2. As the filename will be always present ID3v2 will here 294 never be checked. 295 296 $mp3->config("autoinfo","ID3v1","ID3v2"); 297 298 sets the order to check first ID3v1, then ID3v2. The filename will 299 never be used. 300 301* Later there will be probably more things to configure. 302 303=cut 304 305sub config() { 306 my ($self, $item, @options) = @_; 307 308 $item = lc $item; 309 310 if ($item ne "autoinfo") { 311 warn "MP3::Tag::config(): Unknown option '$item' found\n"; 312 return; 313 } 314 315 $config{$item}=\@options; 316} 317 318 319sub DESTROY { 320 my $self=shift; 321 if (exists $self->{filename} and defined $self->{filename}) { 322 $self->{filename}->close; 323 } 324} 325 3261; 327 328=pod 329 330=head1 SEE ALSO 331 332L<MP3::Tag::ID3v1>, L<MP3::Tag::ID3v2>, L<MP3::Tag::File> 333 334=cut 335