.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "MP3::Tag::ID3v2 3pm" .TH MP3::Tag::ID3v2 3pm "2022-12-30" "perl v5.36.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" MP3::Tag::ID3v2 \- Read / Write ID3v2.x.y tags from mp3 audio files .SH "SYNOPSIS" .IX Header "SYNOPSIS" MP3::Tag::ID3v2 supports * Reading of ID3v2.2.0 and ID3v2.3.0 tags (some ID3v2.4.0 frames too) * Writing of ID3v2.3.0 tags .PP MP3::Tag::ID3v2 is designed to be called from the MP3::Tag module. If you want to make calls from user code, please consider using highest-level wrapper code in MP3::Tag, such as \fBupdate_tags()\fR and \&\fBselect_id3v2_frame_by_descr()\fR. .PP Low-level creation code: .PP .Vb 2 \& use MP3::Tag; \& $mp3 = MP3::Tag\->new($filename); \& \& # read an existing tag \& $mp3\->get_tags(); \& $id3v2 = $mp3\->{ID3v2} if exists $mp3\->{ID3v2}; \& \& # or create a new tag \& $id3v2 = $mp3\->new_tag("ID3v2"); .Ve .PP See MP3::Tag for information on the above used functions. .PP * Reading a tag, very low-level: .PP .Vb 1 \& $frameIDs_hash = $id3v2\->get_frame_ids(\*(Aqtruename\*(Aq); \& \& foreach my $frame (keys %$frameIDs_hash) { \& my ($name, @info) = $id3v2\->get_frames($frame); \& for my $info (@info) { \& if (ref $info) { \& print "$name ($frame):\en"; \& while(my ($key,$val)=each %$info) { \& print " * $key => $val\en"; \& } \& } else { \& print "$name: $info\en"; \& } \& } \& } .Ve .PP * Adding / Changing / Removing a frame in memory (higher-level) .PP .Vb 1 \& $t = $id3v2\->frame_select("TIT2", undef, undef); # Very flexible \& \& $c = $id3v2\->frame_select_by_descr("COMM(fre,fra,eng,#0)[]"); \& $t = $id3v2\->frame_select_by_descr("TIT2"); \& $id3v2\->frame_select_by_descr("TIT2", "MyT"); # Set/Change \& $id3v2\->frame_select_by_descr("RBUF", $n1, $n2, $n3); # Set/Change \& $id3v2\->frame_select_by_descr("RBUF", "$n1;$n2;$n3"); # Set/Change \& $id3v2\->frame_select_by_descr("TIT2", undef); # Remove .Ve .PP * Adding / Changing / Removing a frame in memory (low-level) .PP .Vb 3 \& $id3v2\->add_frame("TIT2", "Title of the audio"); \& $id3v2\->change_frame("TALB","Greatest Album"); \& $id3v2\->remove_frame("TLAN"); .Ve .PP * Output the modified-in-memory version of the tag: .PP .Vb 1 \& $id3v2\->write_tag(); .Ve .PP * Removing the whole tag from the file .PP .Vb 1 \& $id3v2\->remove_tag(); .Ve .PP * Get information about supported frames .PP .Vb 5 \& %tags = $id3v2\->supported_frames(); \& while (($fname, $longname) = each %tags) { \& print "$fname $longname: ", \& join(", ", @{$id3v2\->what_data($fname)}), "\en"; \& } .Ve .SH "AUTHOR" .IX Header "AUTHOR" Thomas Geffert, thg@users.sourceforge.net Ilya Zakharevich, ilyaz@cpan.org .SH "DESCRIPTION" .IX Header "DESCRIPTION" .IP "\fBget_frame_ids()\fR" 4 .IX Item "get_frame_ids()" .Vb 2 \& $frameIDs = $tag\->get_frame_ids; \& $frameIDs = $tag\->get_frame_ids(\*(Aqtruename\*(Aq); \& \& [old name: getFrameIDs() . The old name is still available, but you should use the new name] .Ve .Sp get_frame_ids loops through all frames, which exist in the tag. It returns a hash reference with a list of all available Frame IDs. The keys of the returned hash are 4\-character\-codes (short names), the internal names of the frames, the according value is the english (long) name of the frame. .Sp You can use this list to iterate over all frames to get their data, or to check if a specific frame is included in the tag. .Sp If there are multiple occurences of a frame in one tag, the first frame is returned with its normal short name, following frames of this type get a \&'01', '02', '03', ... appended to this name. These names can then used with \f(CW\*(C`get_frame\*(C'\fR to get the information of these frames. These fake frames are not returned if \f(CW\*(Aqtruename\*(Aq\fR argument is set; one can still use \f(CW\*(C`get_frames()\*(C'\fR to extract the info for all of the frames with the given short name. .IP "\fBget_frame()\fR" 4 .IX Item "get_frame()" .Vb 2 \& ($info, $name, @rest) = $tag\->get_frame($ID); \& ($info, $name, @rest) = $tag\->get_frame($ID, \*(Aqraw\*(Aq); \& \& [old name: getFrame() . The old name is still available, but you should use the new name] .Ve .Sp get_frame gets the contents of a specific frame, which must be specified by the 4\-character\-ID (aka short name). You can use \f(CW\*(C`get_frame_ids\*(C'\fR to get the IDs of the tag, or use IDs which you hope to find in the tag. If the \s-1ID\s0 is not found, \&\f(CW\*(C`get_frame\*(C'\fR returns empty list, so \f(CW$info\fR and \f(CW$name\fR become undefined. .Sp Otherwise it extracts the contents of the frame. Frames in ID3v2 tags can be very small, or complex and huge. That is the reason, that \f(CW\*(C`get_frame\*(C'\fR returns the frame data in two ways, depending on the tag. .Sp If it is a simple tag, with only one piece of data, these data is returned directly as ($info, \f(CW$name\fR), where \f(CW$info\fR is the text string, and \f(CW$name\fR is the long (english) name of the frame. .Sp If the frame consist of different pieces of data, \f(CW$info\fR is a hash reference, \&\f(CW$name\fR is again the long name of the frame. .Sp The hash, to which \f(CW$info\fR points, contains key/value pairs, where the key is always the name of the data, and the value is the data itself. .Sp If the name starts with a underscore (as eg '_code'), the data is probably binary data and not printable. If the name starts without an underscore, it should be a text string and printable. .Sp If the second parameter is given as \f(CW\*(Aqraw\*(Aq\fR, the whole frame data is returned, but not the frame header. If the second parameter is \f(CW\*(Aqintact\*(Aq\fR, no mangling of embedded \f(CW"\e0"\fR and trailing spaces is performed. If the second parameter is \f(CW\*(Aqhash\*(Aq\fR, then, additionally, the result is always in the hash format; likewise, if it is \f(CW\*(Aqarray\*(Aq\fR, the result is an array reference (with \f(CW\*(C`key => value\*(C'\fR pairs same as with \f(CW\*(Aqhash\*(Aq\fR, but ordered as in the frame). If it is \f(CW\*(Aqarray_nokey\*(Aq\fR, only the \*(L"value\*(R" parts are returned (in particular, the result is suitable to give to \fBadd_frame()\fR, \fBchange_frame()\fR); in addition, if it is \f(CW\*(Aqarray_nodecode\*(Aq\fR, then keys are not returned, and the setting of \&\f(CW\*(C`decode_encoding_v2\*(C'\fR is ignored. (The \*(L"return array\*(R" flavors don't massage the fields for better consumption by humans, so the fields should be in format suitable for \fBframe_add()\fR.) .Sp If the data was stored compressed, it is uncompressed before it is returned (even in raw mode). Then \f(CW$info\fR contains a string with all data (which might be binary), and \f(CW$name\fR the long frame name. .Sp See also MP3::Tag::ID3v2_Data for a list of all supported frames, and some other explanations of the returned data structure. .Sp If more than one frame with name \f(CW$ID\fR is present, \f(CW@rest\fR contains \f(CW$info\fR fields for all consequent frames with the same name. Note that after removal of frames there may be holes in the list of frame names (as in \&\f(CW\*(C`FRAM FRAM01 FRAM02\*(C'\fR) in the case when multiple frames of the given type were present; the removed frames are returned as \f(CW\*(C`undef\*(C'\fR. .Sp ! Encrypted frames are not supported yet ! .Sp ! Some frames are not supported yet, but the most common ones are supported ! .IP "\fBget_frame_descr()\fR" 4 .IX Item "get_frame_descr()" .Vb 1 \& $long_name = $self\->get_frame_descr($fname); .Ve .Sp returns a \*(L"long name\*(R" for the frame (such as \f(CW\*(C`COMM(eng)[lyricist birthdate]\*(C'\fR), appropriate for interpolation, or for \fBframe_select_by_descr()\fR. .IP "\fBget_frame_descriptors()\fR" 4 .IX Item "get_frame_descriptors()" .Vb 1 \& @long_names = $self\->get_frame_descriptors(); .Ve .Sp return \*(L"long names\*(R" for the frames in the tag (see \f(CW\*(C`get_frame_descr\*(C'\fR). .IP "\fBget_frame_option()\fR" 4 .IX Item "get_frame_option()" .Vb 1 \& $options = get_frame_option($ID); \& \& Option is a hash reference, the hash contains all possible options. \& The value for each option is 0 or 1. \& \& groupid \-\- not supported yet \& encryption \-\- not supported yet \& compression \-\- Compresses frame before writing tag; \& compression/uncompression is done automatically \& read_only \-\- Ignored by this library, should be obeyed by application \& file_preserv \-\- Ignored by this library, should be obeyed by application \& tag_preserv \-\- Ignored by this library, should be obeyed by application .Ve .IP "\fBset_frame_option()\fR" 4 .IX Item "set_frame_option()" .Vb 1 \& $options = set_frame_option($ID, $option, $value); \& \& Set $option to $value (0 or 1). If successfull the new set of \& options is returned, undef otherwise. \& \& groupid \-\- not supported yet \& encryption \-\- not supported yet \& compression \-\- Compresses frame before writing tag; \& compression/uncompression is done automatically \& read_only \-\- Ignored by this library, should be obeyed by application \& file_preserv \-\- Ignored by this library, should be obeyed by application \& tag_preserv \-\- Ignored by this library, should be obeyed by application .Ve .IP "\fBget_frames()\fR" 4 .IX Item "get_frames()" .Vb 2 \& ($name, @info) = get_frames($ID); \& ($name, @info) = get_frames($ID, \*(Aqraw\*(Aq); .Ve .Sp Same as \fBget_frame()\fR with different order of the returned values. \&\f(CW$name\fR and elements of the array \f(CW@info\fR have the same semantic as for \&\fBget_frame()\fR; each frame with id \f(CW$ID\fR produces one elements of array \f(CW@info\fR. .IP "\fBas_bin()\fR" 4 .IX Item "as_bin()" .Vb 1 \& $tag2 = $id3v2\->as_bin($ignore_error, $update_file, $raw_ok); .Ve .Sp Returns the the current content of the ID3v2 tag as a string good to write to a file; it contains all the necessary footers and headers. .Sp If \f(CW$ignore_error\fR is \s-1TRUE,\s0 the frames the module does not know how to write are skipped; otherwise it is an error to have such a frame. Returns undef on error. .Sp If the optional argument \f(CW$update_file\fR is \s-1TRUE,\s0 an additional action is performed: if the audio file does not contain an ID3v2 tag, or the tag in the file is smaller than the built ID3v2 tag, the necessary 0\-padding is inserted before the audio content of the file so that it is able to accommodate the build tag (and the \f(CW\*(C`tagsize\*(C'\fR field of \&\f(CW$id3v2\fR is updated correspondingly); in any case the header length of \&\f(CW$tag2\fR is set to reflect the space in the beginning of the audio file. .Sp Unless \f(CW$update_file\fR has \f(CW\*(Aqpadding\*(Aq\fR as a substring, the actual length of the string \f(CW$tag2\fR is not modified, so if it is smaller than the reserved space in the file, one needs to add some 0 padding at the end. Note that if the size of reserved space can shrink (as with \f(CW\*(C`id3v2_shrink\*(C'\fR configuration option), then without this option it would be hard to calculate necessary padding by hand. .Sp If \f(CW$raw_ok\fR option is given, but not \f(CW$update_file\fR, the original contents is returned for unmodified tags. .IP "\fBas_bin_raw()\fR" 4 .IX Item "as_bin_raw()" .Vb 1 \& $tag2 = $id3v2\->as_bin_raw($ignore_error, $update_file); .Ve .Sp same as \fBas_bin()\fR with \f(CW$raw_ok\fR flag. .IP "\fBwrite_tag()\fR" 4 .IX Item "write_tag()" .Vb 1 \& $id3v2\->write_tag($ignore_error); .Ve .Sp Saves all frames to the file. It tries to update the file in place, when the space of the old tag is big enough for the new tag. Otherwise it creates a temp file with a new tag (i.e. copies the whole mp3 file) and renames/moves it to the original file name. .Sp An extended header with \s-1CRC\s0 checksum is not supported yet. .Sp Encryption of frames and group ids are not supported. If \f(CW$ignore_error\fR is set, these options are ignored and the frames are saved without these options. If \f(CW$ignore_error\fR is not set and a tag with an unsupported option should be save, the tag is not written and a 0 is returned. .Sp If a tag with an encrypted frame is read, and the frame is not changed it can be saved encrypted again. .Sp ID3v2.2 tags are converted automatically to ID3v2.3 tags during writing. If a frame cannot be converted automatically (\s-1PIC\s0; \s-1CMR\s0), writing aborts and returns a 0. If \f(CW$ignore_error\fR is true, only not convertable frames are ignored and not written, but the rest of the tag is saved as ID3v2.3. .Sp At the moment the tag is automatically unsynchronized. .Sp If the tag is written successfully, 1 is returned. .IP "\fBremove_tag()\fR" 4 .IX Item "remove_tag()" .Vb 1 \& $id3v2\->remove_tag(); .Ve .Sp Removes the whole tag from the file by copying the whole mp3\-file to a temp-file and renaming/moving that to the original filename. .Sp Do not use \fBremove_tag()\fR if you only want to change a header, as otherwise the file is copied unnecessarily. Use \fBwrite_tag()\fR directly, which will override an old tag. .IP "\fBadd_frame()\fR" 4 .IX Item "add_frame()" .Vb 1 \& $fn = $id3v2\->add_frame($fname, @data); .Ve .Sp Add a new frame, identified by the short name \f(CW$fname\fR. The number of elements of array \f(CW@data\fR should be as described in the ID3v2.3 standard. (See also MP3::Tag::ID3v2_Data.) There are two exceptions: if \f(CW@data\fR is empty, it is filled with necessary number of \&\f(CW""\fR); if one of required elements is \f(CW\*(C`encoding\*(C'\fR, it may be omitted or be \f(CW\*(C`undef\*(C'\fR, meaning the arguments are in \*(L"Plain Perl (=ISOLatin\-1 or Unicode) encoding\*(R". .Sp It returns the the short name \f(CW$fn\fR (which can differ from \&\f(CW$fname\fR, when an \f(CW$fname\fR frame already exists). If no other frame of this kind is allowed, an empty string is returned. Otherwise the name of the newly created frame is returned (which can have a 01 or 02 or ... appended). .Sp You have to call \fBwrite_tag()\fR to save the changes to the file. .Sp Examples (with \f(CW\*(C`$id3v2\->\*(C'\fR omitted): .Sp .Vb 2 \& $f = add_frame(\*(AqTIT2\*(Aq, 0, \*(AqAbba\*(Aq); # $f=\*(AqTIT2\*(Aq \& $f = add_frame(\*(AqTIT2\*(Aq, \*(AqAbba\*(Aq); # $f=\*(AqTIT201\*(Aq, encoding=0 implicit \& \& $f = add_frame(\*(AqCOMM\*(Aq, \*(AqENG\*(Aq, \*(AqShort text\*(Aq, \*(AqThis is a comment\*(Aq); \& \& $f = add_frame(\*(AqCOMM\*(Aq); # creates an empty frame \& \& $f = add_frame(\*(AqCOMM\*(Aq, \*(AqENG\*(Aq); # ! wrong ! $f=undef, becaues number \& # of arguments is wrong \& \& $f = add_frame(\*(AqRBUF\*(Aq, $n1, $n2, $n3); \& $f = add_frame(\*(AqRBUF\*(Aq, $n1, $n2); # last field of RBUF is optional .Ve .Sp If a frame has optional fields \fIand\fR \f(CW\*(C`encoding\*(C'\fR (only \f(CW\*(C`COMR\*(C'\fR frame as of ID3v2.4), there may be an ambiguity which fields are omitted. It is resolved this way: the \f(CW\*(C`encoding\*(C'\fR field can be omitted only if all other optional frames are omitted too (set it to \f(CW\*(C`undef\*(C'\fR instead). .IP "\fBadd_frame_split()\fR" 4 .IX Item "add_frame_split()" The same as \fBadd_frame()\fR, but if the number of arguments is unsufficient, would \fBsplit()\fR the last argument on \f(CW\*(C`;\*(C'\fR to obtain the needed number of arguments. Should be avoided unless it is known that the fields do not contain \f(CW\*(C`;\*(C'\fR (except for \f(CW\*(C`POPM RBUF RVRB SYTC\*(C'\fR, where splitting may be done non-ambiguously). .Sp .Vb 2 \& # No ambiguity, since numbers do not contain ";": \& $f = add_frame_split(\*(AqRBUF\*(Aq, "$n1;$n2;$n3"); .Ve .Sp For \f(CW\*(C`COMR\*(C'\fR frame, in case when the fields are \f(CW\*(C`join()\*(C'\fRed by \f(CW\*(Aq;\*(Aq\fR, \&\f(CW\*(C`encoding\*(C'\fR field may be present only if all the other fields are present. .IP "\fBchange_frame()\fR" 4 .IX Item "change_frame()" .Vb 1 \& $id3v2\->change_frame($fname, @data); .Ve .Sp Change an existing frame, which is identified by its short name \f(CW$fname\fR eg as returned by \fBget_frame_ids()\fR. \&\f(CW@data\fR must be same as in \fBadd_frame()\fR. .Sp If the frame \f(CW$fname\fR does not exist, undef is returned. .Sp You have to call \fBwrite_tag()\fR to save the changes to the file. .IP "\fBremove_frame()\fR" 4 .IX Item "remove_frame()" .Vb 1 \& $id3v2\->remove_frame($fname); .Ve .Sp Remove an existing frame. \f(CW$fname\fR is the short name of a frame, eg as returned by \fBget_frame_ids()\fR. .Sp You have to call \fBwrite_tag()\fR to save the changes to the file. .ie n .IP "copy_frames($from, $to, $overwrite, [$keep_flags, $f_ids])" 4 .el .IP "copy_frames($from, \f(CW$to\fR, \f(CW$overwrite\fR, [$keep_flags, \f(CW$f_ids\fR])" 4 .IX Item "copy_frames($from, $to, $overwrite, [$keep_flags, $f_ids])" Copies specified frames between \f(CW\*(C`MP3::Tag::ID3v2\*(C'\fR objects \f(CW$from\fR, \f(CW$to\fR. Unless \&\f(CW$keep_flags\fR, the copied frames have their flags cleared. If the array reference \f(CW$f_ids\fR is not specified, all the frames (but \f(CW\*(C`GRID\*(C'\fR and \f(CW\*(C`TLEN\*(C'\fR) are considered (subject to \f(CW$overwrite\fR), otherwise \f(CW$f_ids\fR should contain short frame ids to consider. Group \s-1ID\s0 flag is always cleared. .Sp If \f(CW$overwrite\fR is \f(CW\*(Aqdelete\*(Aq\fR, frames with the same descriptors (as returned by \fBget_frame_descr()\fR) in \f(CW$to\fR are deleted first, then all the specified frames are copied. If \f(CW$overwrite\fR is \s-1FALSE,\s0 only frames with descriptors not present in \f(CW$to\fR are copied. (If one of these two conditions is not met, the result may be not conformant to standards.) .Sp Returns count of copied frames. .IP "\fBis_modified()\fR" 4 .IX Item "is_modified()" .Vb 1 \& $id3v2\->is_modified; .Ve .Sp Returns true if the tag was modified after it was created. .IP "\fBsupported_frames()\fR" 4 .IX Item "supported_frames()" .Vb 1 \& $frames = $id3v2\->supported_frames(); .Ve .Sp Returns a hash reference with all supported frames. The keys of the hash are the short names of the supported frames, the according values are the long (english) names of the frames. .IP "\fBwhat_data()\fR" 4 .IX Item "what_data()" .Vb 1 \& ($data, $res_inp, $data_map) = $id3v2\->what_data($fname); .Ve .Sp Returns an array reference with the needed data fields for a given frame. At this moment only the internal field names are returned, without any additional information about the data format of this field. Names beginning with an underscore (normally '_data') can contain binary data. (The \f(CW\*(C`_encoding\*(C'\fR field is skipped in this list, since it is usually auto-deduced by this module.) .Sp \&\f(CW$resp_inp\fR is a reference to a hash (keyed by the field name) describing restrictions for the content of the data field. If the entry is undef, no restriction exists. Otherwise it is a hash. The keys of the hash are the allowed input, the correspodending value is the value which is actually stored in this field. If the value is undef then the key itself is valid for saving. If the hash contains an entry with \*(L"_FREE\*(R", the hash contains only suggestions for the input, but other input is also allowed. .Sp \&\f(CW$data_map\fR contains values of \f(CW$resp_inp\fR in the order of fields of a frame (including \f(CW\*(C`_encoding\*(C'\fR). .Sp Example for picture types of the \s-1APIC\s0 frame: .Sp .Vb 4 \& {"Other" => "\ex00", \& "32x32 pixels \*(Aqfile icon\*(Aq (PNG only)" => "\ex01", \& "Other file icon" => "\ex02", \& ...} .Ve .IP "title( [@new_title] )" 4 .IX Item "title( [@new_title] )" Returns the title composed of the tags configured via \f(CW\*(C`MP3::Tag\->config(\*(Aqv2title\*(Aq)\*(C'\fR call (with default 'Title/Songname/Content description' (\s-1TIT2\s0)) from the tag. (For backward compatibility may be called by deprecated name \fBsong()\fR as well.) .Sp Sets \s-1TIT2\s0 frame if given the optional arguments \f(CW@new_title\fR. If this is an empty string, the frame is removed. .IP "_comment([$language])" 4 .IX Item "_comment([$language])" Returns the file comment (\s-1COMM\s0 with an empty 'Description') from the tag, or \&\*(L"Subtitle/Description refinement\*(R" (\s-1TIT3\s0) frame (unless it is considered a part of the title). .IP "\fBcomment()\fR" 4 .IX Item "comment()" .Vb 2 \& $val = $id3v2\->comment(); \& $newframe = $id3v2\->comment(\*(AqJust a comment for freddy\*(Aq, \*(Aqpersonal\*(Aq, \*(Aqeng\*(Aq); .Ve .Sp Returns the file comment (\s-1COMM\s0 frame with the 'Description' field in \&\f(CW\*(C`default_descr_c\*(C'\fR configuration variable, defalting to \f(CW\*(Aq\*(Aq\fR) from the tag, or \*(L"Subtitle/Description refinement\*(R" (\s-1TIT3\s0) frame (unless it is considered a part of the title). .Sp If optional arguments ($comment, \f(CW$short\fR, \f(CW$language\fR) are present, sets the comment frame. If \f(CW$language\fR is omited, uses the \&\f(CW\*(C`default_language\*(C'\fR configuration variable (default is \f(CW\*(C`XXX\*(C'\fR). If not \&\f(CW\*(C`XXX\*(C'\fR, this should be lowercase 3\-letter abbreviation according to \&\s-1ISO\-639\-2\s0). .Sp If \f(CW$short\fR is not defined, uses the \f(CW\*(C`default_descr_c\*(C'\fR configuration variable. If \f(CW$comment\fR is an empty string, the frame is removed. .ie n .IP "frame_select($fname, $descrs, $languages [, $newval1, ...])" 4 .el .IP "frame_select($fname, \f(CW$descrs\fR, \f(CW$languages\fR [, \f(CW$newval1\fR, ...])" 4 .IX Item "frame_select($fname, $descrs, $languages [, $newval1, ...])" Used to get/set/delete frames which may be not necessarily unique in a tag. .Sp .Vb 8 \& # Select short\-description=\*(Aq\*(Aq, prefere language \*(Aqeng\*(Aq, then \*(Aqrus\*(Aq, then \& # the third COMM frame, then any (in this case, the first or the second) \& # COMM frame \& $val = $id3v2\->frame_select(\*(AqCOMM\*(Aq, \*(Aq\*(Aq, [\*(Aqeng\*(Aq, \*(Aqrus\*(Aq, \*(Aq#2\*(Aq, \*(Aq\*(Aq]); # Read \& $new = $id3v2\->frame_select(\*(AqCOMM\*(Aq, \*(Aq\*(Aq, [\*(Aqeng\*(Aq, \*(Aqrus\*(Aq, \*(Aq#2\*(Aq], # Write \& \*(AqComment with empty "Description" and "eng"\*(Aq); \& $new = $id3v2\->frame_select(\*(AqCOMM\*(Aq, \*(Aq\*(Aq, [\*(Aqeng\*(Aq, \*(Aqrus\*(Aq, \*(Aq#2\*(Aq], # Delete \& undef); .Ve .Sp Returns the contents of the first frame named \f(CW$fname\fR with a \&'Description' field in the specified array reference \f(CW$descrs\fR and the language in the list of specified languages \f(CW$languages\fR; empty return otherwise. If the frame is a \*(L"simple frame\*(R", the frame is returned as a string, otherwise as a hash reference; a \*(L"simple frame\*(R" should consist of one of Text/URL/_Data fields, with possible addition of Language and Description fields (if the corresponding arguments were defined). .Sp The lists \f(CW$descrs\fR and \f(CW$languages\fR of one element can be flattened to become this element (as with \f(CW\*(Aq\*(Aq\fR above). If the lists are not defined, no restriction is applied; to get the same effect with defined arguments, use \f(CW$languages\fR of \f(CW\*(Aq\*(Aq\fR, and/or \f(CW$descrs\fR a hash reference. Language of the form \f(CW\*(Aq#NUMBER\*(Aq\fR selects the \s-1NUMBER\s0's (0\-based) frame with frame name \f(CW$fname\fR. .Sp If optional arguments \f(CW\*(C`$newval1...\*(C'\fR are given, \fB\s-1ALL\s0\fR the found frames are removed; if only one such argument \f(CW\*(C`undef\*(C'\fR is given, this is the only action. Otherwise, a new frame is created afterwards (the first elements of \f(CW$descrs\fR and \f(CW$languages\fR are used as the short description and the language, defaulting to \f(CW\*(Aq\*(Aq\fR and the \f(CW\*(C`default_language\*(C'\fR configuration variable (which, in turn, defaults to \f(CW\*(C`XXX\*(C'\fR; if not \f(CW\*(C`XXX\*(C'\fR, this should be lowercase 3\-letter abbreviation according to \s-1ISO\-639\-2\s0). If new frame is created, the frame's name is returned; otherwise the count of removed frames is returned. .Sp As a generalization, \s-1APIC\s0 frames are handled too, using \f(CW\*(C`Picture Type\*(C'\fR instead of \f(CW\*(C`Language\*(C'\fR, and auto-calculating \f(CW\*(C`MIME type\*(C'\fR for (currently) \s-1TIFF/JPEG/GIF/PNG/BMP\s0 and octet-stream. Only frames with \&\f(CW\*(C`MIME type\*(C'\fR coinciding with the auto-calculated value are considered as \*(L"simple frames\*(R". One can use both the 1\-byte format for \f(CW\*(C`Picture Type\*(C'\fR, and the long names used in the ID3v2 documentation; the default value is \f(CW\*(AqCover (front)\*(Aq\fR. .Sp .Vb 9 \& # Choose APIC with empty description, picture_type=\*(AqLeaflet page\*(Aq \& my $data = $id3v2\->frame_select(\*(AqAPIC\*(Aq, \*(Aq\*(Aq, \*(AqLeaflet page\*(Aq) \& or die "no expected APIC frame found"; \& my $format = ( ref $data ? $data\->{\*(AqMIME type\*(Aq} \& : $id3v2\->_Data_to_MIME($data) ); \& # I know what to do with application/pdf only (sp?) and \*(Aqimage/gif\*(Aq \& die "Do not know what to do with this APIC format: \`$format\*(Aq" \& unless $format eq \*(Aqapplication/pdf\*(Aq or $format eq \*(Aqimage/gif\*(Aq; \& $data = $data\->{_Data} if ref $data; # handle non\-simple frame \& \& # Set APIC frame with empty description (front cover if no other present) \& # from content of file.gif \& my $data = do { open my $f, \*(Aq<\*(Aq, \*(Aqfile.gif\*(Aq and binmode $f or die; \& undef $/; <$f>}; \& my $new_frame = $id3v2\->frame_select(\*(AqAPIC\*(Aq, \*(Aq\*(Aq, undef, $data); .Ve .Sp Frames with multiple \*(L"content\*(R" fields may be set by providing multiple values to set. Alternatively, one can also \f(CW\*(C`join()\*(C'\fR the values with \&\f(CW\*(Aq;\*(Aq\fR if the splitting is not ambiguous, e.g., for \f(CW\*(C`POPM RBUF RVRB SYTC\*(C'\fR. (For frames \f(CW\*(C`GEOD\*(C'\fR and \f(CW\*(C`COMR\*(C'\fR, which have a \f(CW\*(C`Description\*(C'\fR field, it should be specified among these values.) .Sp .Vb 2 \& $id3v2\->frame_select("RBUF", undef, undef, $n1, $n2, $n3); \& $id3v2\->frame_select("RBUF", undef, undef, "$n1;$n2;$n3"); .Ve .Sp (By the way: consider using the method \fBselect_id3v2_frame()\fR on the \&\*(L"parent\*(R" MP3::Tag object instead [see \*(L"select_id3v2_frame\*(R" in MP3::Tag], or \fBframe_select_by_descr()\fR.) .IP "_Data_to_MIME" 4 .IX Item "_Data_to_MIME" Internal method to extract \s-1MIME\s0 type from a string the image file content. Returns \f(CW\*(C`application/octet\-stream\*(C'\fR for unrecognized data (unless extra \s-1TRUE\s0 argument is given). .Sp .Vb 1 \& $format = $id3v2\->_Data_to_MIME($data); .Ve .Sp Currently, only the first 4 bytes of the string are inspected. .IP "\fBframe_list()\fR" 4 .IX Item "frame_list()" Same as \fBframe_select()\fR, but returns the list of found frames, each an array reference \f(CW\*(C`[$N, $f]\*(C'\fR with \f(CW$N\fR the 0\-based ordinal (among frames with the given short name), and \f(CW$f\fR the contents of a frame. .IP "\fBframe_have()\fR" 4 .IX Item "frame_have()" Same as \fBframe_select()\fR, but returns the count of found frames. .IP "\fBframe_select_by_descr()\fR" 4 .IX Item "frame_select_by_descr()" .PD 0 .IP "\fBframe_have_by_descr()\fR" 4 .IX Item "frame_have_by_descr()" .IP "\fBframe_list_by_descr()\fR" 4 .IX Item "frame_list_by_descr()" .PD .Vb 6 \& $c = $id3v2\->frame_select_by_descr("COMM(fre,fra,eng,#0)[]"); \& $t = $id3v2\->frame_select_by_descr("TIT2"); \& $id3v2\->frame_select_by_descr("TIT2", "MyT"); # Set/Change \& $id3v2\->frame_select_by_descr("RBUF", $n1, $n2, $n3); # Set/Change \& $id3v2\->frame_select_by_descr("RBUF", "$n1;$n2;$n3"); # Set/Change \& $id3v2\->frame_select_by_descr("TIT2", undef); # Remove .Ve .Sp Same as \fBframe_select()\fR, \fBframe_have()\fR, \fBframe_list()\fR, but take one string argument instead of \f(CW$fname\fR, \f(CW$descrs\fR, \f(CW$languages\fR. The argument should be of the form .Sp .Vb 1 \& NAME(langs)[descr] .Ve .Sp Both \f(CW\*(C`(langs)\*(C'\fR and \f(CW\*(C`[descr]\*(C'\fR parts may be omitted; \fIlangs\fR should contain comma-separated list of needed languages; no protection by backslashes is needed in \fIdescr\fR. \fBframe_select_by_descr()\fR will return a hash if \f(CW\*(C`(lang)\*(C'\fR is omited, but the frame has a language field; likewise for \f(CW\*(C`[descr]\*(C'\fR; see below for alternatives. .Sp Remember that when \fBframe_select_by_descr()\fR is used for modification, \&\fB\s-1ALL\s0\fR found frames are deleted before a new one is added. .Sp (By the way: consider using the method \fBselect_id3v2_frame_by_descr()\fR on the \&\*(L"parent\*(R" MP3::Tag object instead; see \*(L"select_id3v2_frame_by_descr\*(R" in MP3::Tag.) .IP "\fBframe_select_by_descr_simple()\fR" 4 .IX Item "frame_select_by_descr_simple()" Same as \fBframe_select_by_descr()\fR, but if no language is given, will not consider the frame as \*(L"complicated\*(R" frame even if it contains a language field. .IP "\fBframe_select_by_descr_simpler()\fR" 4 .IX Item "frame_select_by_descr_simpler()" Same as \fBframe_select_by_descr_simple()\fR, but if no \f(CW\*(C`Description\*(C'\fR is given, will not consider the frame as \*(L"complicated\*(R" frame even if it contains a \f(CW\*(C`Description\*(C'\fR field. .IP "year( [@new_year] )" 4 .IX Item "year( [@new_year] )" Returns the year (\s-1TYER/TDRC\s0) from the tag. .Sp Sets \s-1TYER\s0 and \s-1TDRC\s0 frames if given the optional arguments \f(CW@new_year\fR. If this is an empty string, the frame is removed. .Sp The format is similar to timestamps of IDv2.4.0, but ranges can be separated by \f(CW\*(C`\-\*(C'\fR or \f(CW\*(C`\-\-\*(C'\fR, and non-contiguous dates are separated by \f(CW\*(C`,\*(C'\fR (comma). If periods need to be specified via duration, then one needs to use the \s-1ISO 8601\s0 \&\f(CW\*(C`/\*(C'\fR\-notation (e.g., see .Sp .Vb 1 \& http://www.mcs.vuw.ac.nz/technical/software/SGML/doc/iso8601/ISO8601.html .Ve .Sp ); the \f(CW\*(C`duration/end_timestamp\*(C'\fR is not supported. .Sp On output, ranges of timestamps are converted to \f(CW\*(C`\-\*(C'\fR or \f(CW\*(C`\-\-\*(C'\fR separated format depending on whether the timestamps are years, or have additional fields. .Sp If configuration variable \f(CW\*(C`year_is_timestamp\*(C'\fR is false, the return value is always the year only (of the first timestamp of a composite timestamp). .Sp Recall that ID3v2.4.0 timestamp has format yyyy\-MM\-ddTHH:mm:ss (year, \*(L"\-\*(R", month, \*(L"\-\*(R", day, \*(L"T\*(R", hour (out of 24), \*(L":\*(R", minutes, \*(L":\*(R", seconds), but the precision may be reduced by removing as many time indicators as wanted. Hence valid timestamps are yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy\-MM\-ddTHH:mm and yyyy\-MM\-ddTHH:mm:ss. All time stamps are \s-1UTC.\s0 For durations, use the slash character as described in 8601, and for multiple noncontiguous dates, use multiple strings, if allowed by the frame definition. .IP "track( [$new_track] )" 4 .IX Item "track( [$new_track] )" Returns the track number (\s-1TRCK\s0) from the tag. .Sp Sets \s-1TRCK\s0 frame if given the optional arguments \f(CW@new_track\fR. If this is an empty string or 0, the frame is removed. .ie n .IP "artist( [ $new_artist ] )" 4 .el .IP "artist( [ \f(CW$new_artist\fR ] )" 4 .IX Item "artist( [ $new_artist ] )" Returns the artist name; it is the first existing frame from the list of .Sp .Vb 5 \& TPE1 Lead artist/Lead performer/Soloist/Performing group \& TPE2 Band/Orchestra/Accompaniment \& TCOM Composer \& TPE3 Conductor \& TEXT Lyricist/Text writer .Ve .Sp Sets \s-1TPE1\s0 frame if given the optional arguments \f(CW@new_artist\fR. If this is an empty string, the frame is removed. .ie n .IP "album( [ $new_album ] )" 4 .el .IP "album( [ \f(CW$new_album\fR ] )" 4 .IX Item "album( [ $new_album ] )" Returns the album name (\s-1TALB\s0) from the tag. If none is found, returns the \*(L"Content group description\*(R" (\s-1TIT1\s0) frame (unless it is considered a part of the title). .Sp Sets \s-1TALB\s0 frame if given the optional arguments \f(CW@new_album\fR. If this is an empty string, the frame is removed. .ie n .IP "genre( [ $new_genre ] )" 4 .el .IP "genre( [ \f(CW$new_genre\fR ] )" 4 .IX Item "genre( [ $new_genre ] )" Returns the genre string from \s-1TCON\s0 frame of the tag. .Sp Sets \s-1TCON\s0 frame if given the optional arguments \f(CW@new_genre\fR. If this is an empty string, the frame is removed. .IP "\fBversion()\fR" 4 .IX Item "version()" .Vb 2 \& $version = $id3v2\->version(); \& ($major, $revision) = $id3v2\->version(); .Ve .Sp Returns the version of the ID3v2 tag. It returns a formatted string like \*(L"3.0\*(R" or an array containing the major part (eg. 3) and revision part (eg. 0) of the version number. .IP "\fBnew()\fR" 4 .IX Item "new()" .Vb 1 \& $tag = new($mp3fileobj); .Ve .Sp \&\f(CW\*(C`new()\*(C'\fR needs as parameter a mp3fileobj, as created by \f(CW\*(C`MP3::Tag::File\*(C'\fR. \&\f(CW\*(C`new\*(C'\fR tries to find a ID3v2 tag in the mp3fileobj. If it does not find a tag it returns undef. Otherwise it reads the tag header, as well as an extended header, if available. It reads the rest of the tag in a buffer, does unsynchronizing if necessary, and returns a ID3v2\-object. At this moment only ID3v2.3 is supported. Any extended header with \s-1CRC\s0 data is ignored, so no \s-1CRC\s0 check is done at the moment. The ID3v2\-object can be used to extract information from the tag. .Sp Please use .Sp .Vb 3 \& $mp3 = MP3::Tag\->new($filename); \& $mp3\->get_tags(); ## to find an existing tag, or \& $id3v2 = $mp3\->new_tag("ID3v2"); ## to create a new tag .Ve .Sp instead of using this function directly .SH "BUGS" .IX Header "BUGS" Writing \f(CW\*(C`v2.4\*(C'\fR\-layout tags is not supported. .PP Additionally, one should keep in mind that \f(CW\*(C`v2.3\*(C'\fR and \f(CW\*(C`v2.4\*(C'\fR have differences in two areas: .IP "\(bu" 4 layout of information in the byte stream (in other words, in a file considered as a string) is different; .IP "\(bu" 4 semantic of frames is extended in \f(CW\*(C`v2.4\*(C'\fR \- more frames are defined, and more frame flags are defined too. .PP MP3::Tag does not even try to \fIwrite\fR frames in \f(CW\*(C`v2.4\*(C'\fR\-layout. However, when \fIreading\fR the frames, MP3::Tag does not assume any restriction on the semantic of frames \- it allows all the semantical extensions defined in \f(CW\*(C`v2.4\*(C'\fR even for \f(CW\*(C`v2.3\*(C'\fR (and, probably, for \f(CW\*(C`v2.2\*(C'\fR) layout. .PP \&\f(CW\*(C`[*]\*(C'\fR (I expect, any sane program would do the same...) .PP Likewise, when writing frames, there is no restriction imposed on semantic. If user specifies a frame the meaning of which is defined only in \f(CW\*(C`v2.4\*(C'\fR, we would happily write it even when we use \f(CW\*(C`v2.3\*(C'\fR layout. Same for frame flags. (And given the assumption \f(CW\*(C`[*]\*(C'\fR, this is a correct thing to do...) .SH "SEE ALSO" .IX Header "SEE ALSO" MP3::Tag, MP3::Tag::ID3v1, MP3::Tag::ID3v2_Data .PP ID3v2 standard \- http://www.id3.org , , , , . .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2000\-2008 Thomas Geffert, Ilya Zakharevich. All rights reserved. .PP This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License, distributed with Perl.