The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

MP3::Mplib - Speedy access to id3v1 and id3v2 tags

SYNOPSIS

    use MP3::Mplib;

    my $mp3 = MP3::Mplib->new("/path/to/file.mp3");
    my $v1tag = $mp3->get_v1tag;
    my $v2tag = $mp3->get_v2tag;
    
    while (my ($key, $val) = each %$v1tag) {
        print "$key: $val\n";
    }
    
    while (my ($key, $val) = each %$v2tag) {
        ...
    }

    $mp3->add_to_v2tag( { TYER => 2002 } );

DESCRIPTION

MP3::Mplib is a wrapper around Stefan Podkowinski's mplib written in C. It combines the best of both worlds: C's speed and Perl's nice object-orientedness. Note that MP3::Mplib ships with its own version of mplib (currently 1.0.1).

There is no sophistaced class hierarchy. You simply create a MP3::Mplib object. Each method either returns a native Perl data-structure or takes one. Bang. That's it.

METHODS

new(file)

Constructor that takes a filename as only argument.

    my $mp3_object = MP3::Mplib->new("file.mp3");

Returns a hash-ref to the mpeg-header.

    my $mpeg_header = $mp3->header;
    print $mpeg_header->{bitrate}, "\n";
    ...

The hash-ref contains the following fields:

  • syncword (integer)

  • version (string)

  • layer (string)

  • protbit (boolean)

  • bitrate (string)

  • samplingfreq (string)

  • padbit (boolean)

  • privbit (boolean)

  • mode (string)

  • mode_ext (boolean)

  • copyright (boolean)

  • originalhome (boolean)

  • emphasis (boolean)

get_v1tag

Returns the id3v1 tag as a hash-ref.

    my $tag = $mp3->get_v1tag;
    print $tag->{title}, "\n";

The hash-ref contains the following fields:

  • artist

  • title

  • album

  • genre

  • track

  • year

  • comment

get_v2tag

Returns the id3v2 tag as a hash-ref.

    my $tag = $mp3->get_v2tag;
    print $tag->{TIT1}, "\n";

The hash-ref returned can contain up to 74 fields. All but the "COMM" and "WXXX" field have a single value if present.

The "COMM" field is the id3v2-equivalent of the 'comment' tag and contains three sub-categories:

  • text

    The actual comment as an arbitrarily long text.

  • short

    A short description of the comment.

  • lang

    The language of the comment as 3-byte string, e.g. "ENG" for English or "GER" for German.

The "WXXX" field looks like this:

  • url

    The URL that is referenced.

  • description

    An additional description.

Example:

    my $tag = $mp3->get_v2tag;
    if (exists $tag->{COMM}) {
        print "Language: $tag->{COMM}->{lang}\n";
        print "Short:    $tag->{COMM}->{short}\n";
        print "Text:     $tag->{COMM}->{text}\n";        
    }
get_v2header

Returns a hash-ref to the id3v2 header. This can contain the following fields:

  • ver_minor

    The 'x' as in 2.x.1

  • ver_revision

    The 'x' as in 2.3.x

  • unsync

  • experimental

  • footer

  • total_tag_size

  • extended_header

    A reference to the extended header if present.

The extended header has the following fields:

  • size

  • flag_bytes

  • no_flag_bytes

  • is_update

  • crc_data_present

  • crc_data_length

  • crc_data

  • restrictions

  • restrictions_data_length

  • restrictions_item_data

Since the extended header field only exists when the MP3 file has such a header, check for existance before accessing it:

    my $header = $mp3->get_v2header;
    if (exists $header->{extended_header}) {
        print $header->{extended_header}->{size}, "\n";
        ...
    }
set_v1tag(tag, [encoding])

Sets the id3v1-tag. If there was no such tag previously, it is created. An existing one is replaced.

It takes one obligatory argument, namely a reference to a hash. This hash has the keys described in get_v1tag().

'encoding' is an optional argument that determines the character encoding used for the data. It is either of the constants ISO_8859_1, UTF16, UTF16BE or UTF8. If none is given, ISO_8859_1 is used.

    $mp3->set_v1tag( { title     => 'Help',
                       artist    => 'The Beatles',
                       track     => 1,
                       year      => 1966,
                       genre     => 'Oldies',
                       comment   => 'A Beatles-song', }, &UTF16 );

Returns a true value on success, false otherwise. In this case, check $mp3->error.

add_to_v1tag(tag, [encoding])

Adds (or rather merges) 'tag' with the currently existing id3v1-tag. Existing fields are replaced. Use this to add a field to an already existing tag. 'tag' is meant to be a hash-reference:

    $mp3->add_to_v1tag( { TITLE => 'some title',
                          ALBUM => 'some album', } );

Returns a true value on success, false otherwise in which case you should check $mp3->error.

set_v2tag(tag, [encoding])

Sets the id3v2 tag. This has the same semantics as set_v1tag, so read its description first.

It differs in that id3v2 tags have different field names. They are always four ccharacter long uppercased strings. Since there are 74 of them, their explanation is not included in here. Please see the specifications at http://www.id3.org/.

A number of fields are special in that they don't just take one value. You can pass a hash-ref to them instead:

  • COMM [comment field]

    Possible fields are 'text', 'short' and 'lang'. 'lang' is always a three character upper-case string. When just an ordinary string is passed, this will become 'text'. 'short' will be left empty in this case and 'lang' is set to 'ENG'.

  • WXXX [used defined link frame]

    Possible fields are 'url' and 'description'. The content of 'url' has to be a ISO-8859-1 encoded string regardless of which 'encoding' you passed to set_v2tag. When just an ordinary string is passed, this will become 'url'. 'description' will remain empty in this case.

Further examples:

    my $tag = { TIT2 => 'Help',
                COMM => { lang  => 'ENG',
                          text  => 'Long comment ...',
                          short => 'short description', },
                WXXX => 'http://www.beatles.com',
                TEXT => 'Paul McCartney', # the text writer
                TPE1 => 'Paul McCartney', # the lead performer
                TPE2 => 'The Beatles',    # the band
                ..., };
    $mp3->set_v2header($tag);

In the above, the 'WXXX' could have also looked like this:

    WXXX => { url         => 'http://www.beatles.com',
              description => 'a webpage', },

or somesuch.

This method has the same return values as set_v1tag.

add_to_v2tag

The id3v2 equivalent to add_to_v1tag. It has the same semantics, both regarding the arguments it gets as well as its return value.

del_v1tag

Deletes the id3v2 tag from the file.

del_v2tag

Deletes the id3v2 tag. Correctly speaking, it deletes all id3v2 tags in the file. But since MP3::Mplib does not allow access to particular id3v2 tags this distinction should not matter.

clean_up

Some MP3s may have a very extensive id3v2-tag with some fields showing up several times. If you don't like that, use this method to wipe out all but the first frame of each type.

This method doesn't return anything meaningful since it never fails.

dump_structure

Mainly used as a debugging tool (or if you are just curious to peek at all the tags and fields present in an MP3), this method dumps the tag-structure of the MP3 to STDOUT.

This method doesn't return anything meaningful since it never fails.

error

As always, things can get wrong on certain operations. The statement that did not perform as expected always returns a false value in which case this functions returns a reference to a hash that you can inspect further. Keys of the hash are field names of an id3-tag while the corresponding values are set to an error-code (see "Error Codes" in MP3::Mplib).

There is a special key: mp_file relates to the file rather than to an individual tag-field. This might be set when you try to write a new tag on a read-only file.

Note that error can be called either as instance-method, class-method or function:

    my %err = $mp3->error;
    my %err = MP3::Mplib->error;
    my %err = MP3::Mplib::error();

It is not exported so you have to qualify it when calling it as function.

EXPORTS

Default exports

MP3::Mplib exports a couple of constants by default. If you don't want them, include the module in your scripts like this:

    use MP3::Mplib ();

Please note that each of these constants has to be called as subroutine, either with empty trailing paranteses or a leading ampersand:

    my $c = ISO_8859_1; # NOT OK!

    # instead:
    
    my $c = &ISO_8859_1; 
    # or
    my $c = ISO_8859_1();
Encodings
  • ISO_8859_1

  • UTF16

  • UTF16BE

  • UTF8

Error codes
  • MP_EERROR

    This is a non-specific error code that is - according to the mplib.h - returned under circumstances that cannot happen. :-)

  • MP_EFNF

    The specified field does not exist in the tag.

  • MP_EFCOMPR

    The value for this field has been compressed and can thus not be retrieved.

  • MP_EFENCR

    The value for this field has been encrypted and can thus not be retrieved.

  • MP_EVERSION

    Tag has a version set that is not supported by the library.

Optional exports

MP3::Mplib has a couple of tags you can import:

    use MP3::Mplib qw(:constants)
    use MP3::Mplib qw(:functions)
    use MP3::Mplib qw(:all)
:constants

This exports additional constants used for identifying id3v1 tag fields. These are integers so you cannot use them as hash-keys for set_v1header or get get_v1header!

  • MP_ARTIST

  • MP_TITLE

  • MP_ALBUM

  • MP_GENRE

  • MP_COMMENT

  • MP_YEAR

  • MP_TRACK

:functions

Seven functions are exported by this tag. Use those when you want the functional interface:

  • get_header

  • get_tag

  • get_id3v2_header

  • set_tag

  • delete_tags

  • clean_up

  • dump_structure

For a description see FUNCTIONS.

FUNCTIONS

When using the functional interface, you are using directly the functions defined through XS code. All of them have a prototype so that you can safely omit the parens when using them.

get_header $file

Returns a hash-ref to the mpeg-header. Fields are described under header in "METHODS".

get_tag $file, $version

Returns a hash-ref to the id3-tag for the given $file. $version must either be 1 or 2.

Returns undef if no tag of the specified $version has been found.

get_id3v2_header $file

Returns a hash-ref to the id3v2-header for the given $file. Fields are described under get_v2header in "METHODS".

set_tag $file, $version, $tag, [$enc]

Sets the tag of $version for $file to $tag which has to be a hash-reference. $enc is optional but if given has to be one of the constants described under "Encodings" in "EXPORTS". It defaults to ISO_8859_1.

Returns a true value on success, false otherwise. Check MP3::Mplib::error() in this case.

delete_tags $file, $version

Deletes all tags of $version in $file.

Returns a true value on success false otherwise. Currently MP3::Mplib::error() is not set when this functions fails.

clean_up $file

Cleans up the id3v2-tag of $file. See clean_up in "METHODS" for details.

dump_structure $file

Dumps the tag-structure of $file to STDOUT. See dump_structure in "METHODS" for details.

PLATFORMS

Operating systems

My development environment is a Debian box. In theory I should have access to some Solaris machines in my university but forgot my login. That means it's currently just tested under Linux.

I'd be grateful for anyone sending me remarks how well (or even at all) this module works on his/her machine. If someone is using ActiveState under Windows and did in fact install it succesfully I'd be even happier to hear about that. Perhaps this person would even be so kind to help me packing up a PPM package or even become the Windows-maintainer. Since I am lacking VisualC I am closed out here.

Perl versions and compilers

I've tested it with the following compilers and Perl versions:

  • gcc 2.95.4 / Perl 5.005_03

  • gcc 2.95.4 / Perl 5.6.1

  • gcc 3.0.4 / Perl 5.8.0

KNOWN BUGS

The underlying C library is incomplete with respect to parsing id3v2 tags. This is ok with simple tags, like all the Txxx frames. It is not so ok with more complicated ones, such as WXXX. I contacted mplib's author with a request for adding missing functionality. The mplib's author said that they might be added at some other time.

Currently, some missing functionality has been added by me (notably support for WXXX).

The current object-oriented interface could be considered a bug. There is only the MP3::Mplib object and no separate objects for id3v1- or id3v2-tags. Adding those, however, would require additions to the XS-portion of this module. Read: A lot of additional work.

TODO

Well, see "KNOWN BUGS".

Missing functionality from mplib

Some functionality from the mplib hasn't yet been incorporated into this library:

  • mp_convert_to_v1(id3_tag* tag)

    Converts an id3v2-tag into an id3v1-tag.

  • mp_convert_to_v2(id3_tag* tag)

    Vice versa.

  • mp_is_valid_v1_value(int field, char* value)

    Does some checks on an id3v1 field value. Oddly enough, there is no equivalent for id3v2 fields in the library.

Additional functionality

I would like to have support for the APIC frame (attached picture). Something like the following would be nice:

    $mp3->attach($file, $description);

Probably much more, but I am in modest-mode right now.

Error handling

Always an issue with me. Each object should have its own error reporting mechanism.

Tests

No tests yet for functional interface, nor for the header access.

VERSION

This document describes version 0.02.

AUTHOR AND COPYRIGHT

Tassilo v. Parseval <tassilo.von.parseval@rwth-aachen.de>

Copyright (c) 2002-2004 Tassilo von Parseval. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

http://www.id3.org/ for the id3 specifications.

http://mplib.sourceforge.net/ if you want to visit mplib's home.