| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | =head1 NAME | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  | AudioFile::Info - Perl extension to get info from audio files. | 
| 4 |  |  |  |  |  |  |  | 
| 5 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | use AudioFile::Info; | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | my $song = AudioFile::Info->new($some_mp3_or_ogg_vorbis_file); | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | print 'Title:  ', $song->title, "\n", | 
| 12 |  |  |  |  |  |  | 'Artist: ', $song->artist, "\n". | 
| 13 |  |  |  |  |  |  | 'Album:  ', $song->album, "\n", | 
| 14 |  |  |  |  |  |  | 'Track:  ', $song->track, "\n"; | 
| 15 |  |  |  |  |  |  | 'Year:   ', $song->year, "\n", | 
| 16 |  |  |  |  |  |  | 'Genre:  ', $song->genre, "\n"; | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | $song->title('something else'); # Changes the title | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =head1 ABSTRACT | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | AudioFile::Info is a simple way to get track information out of an audio | 
| 23 |  |  |  |  |  |  | file. It gives a unified interface for extracting information from both | 
| 24 |  |  |  |  |  |  | MP3 and Ogg Vorbis files. | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | Some AudioFile::Info plugins also have the ability to write data back | 
| 27 |  |  |  |  |  |  | to the file. | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | =head2 What is AudioFile::Info | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | I rip all of my audio files into Ogg Vorbis files. But some of my older | 
| 34 |  |  |  |  |  |  | rips are in MP3 format. If I'm writing a program to access information | 
| 35 |  |  |  |  |  |  | from my audio files it's annoying when I have to handle MP3 and Ogg | 
| 36 |  |  |  |  |  |  | Vorbis files completely separately. | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | AudioFile::Info is my solution to that problem. It works on both MP3 | 
| 39 |  |  |  |  |  |  | and Ogg Vorbis files and gives an identical interface for dealing with | 
| 40 |  |  |  |  |  |  | both of them. | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | =head2 Using AudioFile::Info | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | To use AudioFile::Info in your programs you simply load the module | 
| 45 |  |  |  |  |  |  | as normal. | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | use AudioFile::Info; | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | You then create an object using the C method and passing it the | 
| 50 |  |  |  |  |  |  | pathname of an audio file. | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | my $song = AudioFile::Info->new($some_mp3_or_ogg_vorbis_file); | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | The module works out whether the file is in MP3 or Ogg Vorbis format and | 
| 55 |  |  |  |  |  |  | creates an object which can extract the information from the correct | 
| 56 |  |  |  |  |  |  | type of file. You can then use this object to access the various pieces | 
| 57 |  |  |  |  |  |  | of information about the file. | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | print 'Title:  ', $song->title, "\n", | 
| 60 |  |  |  |  |  |  | 'Artist: ', $song->artist, "\n". | 
| 61 |  |  |  |  |  |  | 'Album:  ', $song->album, "\n", | 
| 62 |  |  |  |  |  |  | 'Track:  ', $song->track, "\n"; | 
| 63 |  |  |  |  |  |  | 'Year:   ', $song->year, "\n", | 
| 64 |  |  |  |  |  |  | 'Genre:  ', $song->genre, "\n"; | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | Currently you can access the title, artist, album, track number, year | 
| 67 |  |  |  |  |  |  | and genre of the file. | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | With certain plugins (see below for a description of plugins) you can | 
| 70 |  |  |  |  |  |  | now write data back to the file. This is as simple as passing a new string | 
| 71 |  |  |  |  |  |  | to the accessor function. | 
| 72 |  |  |  |  |  |  |  | 
| 73 |  |  |  |  |  |  | $song->title('something new'); | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | =head2 AudioFile::Info Plugins | 
| 76 |  |  |  |  |  |  |  | 
| 77 |  |  |  |  |  |  | AudioFile::Info is simply a wrapper around various other modules which | 
| 78 |  |  |  |  |  |  | read and write MP3 and Ogg Vorbis files. It makes use of these modules | 
| 79 |  |  |  |  |  |  | by using plugin modules which act as an interface between | 
| 80 |  |  |  |  |  |  | AudioFile::Info and the other modules. AudioFile::Info is pretty much | 
| 81 |  |  |  |  |  |  | useless without at least one these plugins installed. | 
| 82 |  |  |  |  |  |  |  | 
| 83 |  |  |  |  |  |  | Each time you install a plugin, AudioFile::Info notes how it compares | 
| 84 |  |  |  |  |  |  | with other installed plugins. It then works out how which of your | 
| 85 |  |  |  |  |  |  | installed plugins is best for handling the various types of audio | 
| 86 |  |  |  |  |  |  | files. When you use the module to read a file it will use the | 
| 87 |  |  |  |  |  |  | "best" plugin for the file type. | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | You can override this behaviour and tell it to use a particular | 
| 90 |  |  |  |  |  |  | plugin by using an extended version of the C method. | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | C takes an optional argument which is a reference to a hash | 
| 93 |  |  |  |  |  |  | that contains details of which plugin to use for each file type. | 
| 94 |  |  |  |  |  |  | You use it like this. | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | my $song = AudioFile::Info->new($file, | 
| 97 |  |  |  |  |  |  | { mp3 => 'AudioFile::Info::MP3::Info' }); | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | In this case, if C<$file> is the name of an MP3 file then | 
| 100 |  |  |  |  |  |  | AudioFile::Info will use C to handle it | 
| 101 |  |  |  |  |  |  | rather than the default MP3 plugin. If C<$file> contains the name | 
| 102 |  |  |  |  |  |  | of an Ogg Vorbis file then the default Ogg Vorbis plugin will still | 
| 103 |  |  |  |  |  |  | be used. You can change the Ogg Vorbis plugin by using the C | 
| 104 |  |  |  |  |  |  | key in the optional hash. | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  | Currently plugins are available for the following modules. | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | =over 4 | 
| 109 |  |  |  |  |  |  |  | 
| 110 |  |  |  |  |  |  | =item * | 
| 111 |  |  |  |  |  |  |  | 
| 112 |  |  |  |  |  |  | MP3::ID3Lib | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  | =item * | 
| 115 |  |  |  |  |  |  |  | 
| 116 |  |  |  |  |  |  | MP3::Info | 
| 117 |  |  |  |  |  |  |  | 
| 118 |  |  |  |  |  |  | =item * | 
| 119 |  |  |  |  |  |  |  | 
| 120 |  |  |  |  |  |  | MP3::Tag | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  | =item * | 
| 123 |  |  |  |  |  |  |  | 
| 124 |  |  |  |  |  |  | Ogg::Vorbis::Header | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | =item * | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | Ogg::Vorbis::Header::PurePerl | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | =back | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | Plugins for other modules may appear in the future. Let me know if you | 
| 133 |  |  |  |  |  |  | want a plugin that doesn't already exist. | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | =cut | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | package AudioFile::Info; | 
| 138 |  |  |  |  |  |  |  | 
| 139 | 1 |  |  | 1 |  | 70303 | use 5.006; | 
|  | 1 |  |  |  |  | 3 |  | 
| 140 | 1 |  |  | 1 |  | 5 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 20 |  | 
| 141 | 1 |  |  | 1 |  | 5 | use warnings; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 22 |  | 
| 142 | 1 |  |  | 1 |  | 5 | use Carp; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 70 |  | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 1 |  |  | 1 |  | 499 | use YAML 'LoadFile'; | 
|  | 1 |  |  |  |  | 9516 |  | 
|  | 1 |  |  |  |  | 277 |  | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | our $VERSION = '2.0.2'; | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | =head1 METHODS | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | =head2 AudioFile::Info->new(FILE, [\%OPTIONS]) | 
| 151 |  |  |  |  |  |  |  | 
| 152 |  |  |  |  |  |  | Constructor method which returns a new Audio::File::Info object. Well, | 
| 153 |  |  |  |  |  |  | actually it returns an instance of one of the AudioFile::Info plugin | 
| 154 |  |  |  |  |  |  | objects, but for the average user the difference is largely academic. | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | Takes one mandatory argument, which is a full local path to an audio | 
| 157 |  |  |  |  |  |  | file, and an optional reference to a hash containing options. | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | Currently the only options the method understands are 'mp3' or 'ogg'. | 
| 160 |  |  |  |  |  |  | The corresponding values for these keys is the name of a plugin module | 
| 161 |  |  |  |  |  |  | to use to process files of that type. This will override the default | 
| 162 |  |  |  |  |  |  | plugin which AudioFile::Info will choose for itself from the installed | 
| 163 |  |  |  |  |  |  | plugins. | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | =cut | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | sub new { | 
| 168 | 4 |  |  | 4 | 1 | 682 | my $class = shift; | 
| 169 | 4 | 100 |  |  |  | 22 | my $file = shift or die "No music file given."; | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 3 |  | 100 |  |  | 15 | my $param = shift || {}; | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 3 |  |  |  |  | 7 | my $path = $INC{'AudioFile/Info.pm'}; | 
| 174 |  |  |  |  |  |  |  | 
| 175 | 3 |  |  |  |  | 21 | $path =~ s/Info.pm$/plugins.yaml/; | 
| 176 |  |  |  |  |  |  |  | 
| 177 | 3 |  |  |  |  | 12 | my ($ext) = $file =~ /\.(\w+)$/; | 
| 178 | 3 | 100 |  |  |  | 13 | die "Can't work out the type of the file $file\n" | 
| 179 |  |  |  |  |  |  | unless defined $ext; | 
| 180 |  |  |  |  |  |  |  | 
| 181 | 2 |  |  |  |  | 6 | $ext = lc $ext; | 
| 182 |  |  |  |  |  |  |  | 
| 183 | 2 |  |  |  |  | 5 | my $pkg = $param->{$ext}; | 
| 184 |  |  |  |  |  |  |  | 
| 185 | 2 | 100 |  |  |  | 5 | unless (defined $pkg) { | 
| 186 | 1 |  |  |  |  | 6 | my $config = LoadFile($path); | 
| 187 |  |  |  |  |  |  |  | 
| 188 |  |  |  |  |  |  | die "No default $ext file handler\n" | 
| 189 | 0 | 0 |  |  |  | 0 | unless exists $config->{default}{$ext}; | 
| 190 |  |  |  |  |  |  |  | 
| 191 | 0 |  |  |  |  | 0 | $pkg = $config->{default}{$ext}{name}; | 
| 192 |  |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  |  | 
| 194 | 1 |  |  |  |  | 47 | eval "require $pkg"; | 
| 195 | 1 |  |  |  |  | 14 | $pkg->import; | 
| 196 |  |  |  |  |  |  |  | 
| 197 | 1 |  |  |  |  | 4 | return $pkg->new($file); | 
| 198 |  |  |  |  |  |  | } | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | 1; | 
| 202 |  |  |  |  |  |  | __END__ |