com.tffenterprises.music.tag
Class ID3v2

java.lang.Object
  extended by com.tffenterprises.music.tag.ID3v2
All Implemented Interfaces:
ID3Tag, FrameTypes, java.io.Serializable, java.lang.Cloneable

public final class ID3v2
extends java.lang.Object
implements ID3Tag, java.io.Serializable, java.lang.Cloneable, FrameTypes

ID3v2 is an implementation of the ID3v2 informal standard. An object can be constructed from a byte array, from another instance of an ID3 subclass, or from scratch. The ID3v2 object can output itself as a string or as a byte array ready to be written into a file. Writing the tag into a file at its proper location is not the responsibility of the ID3v2 class; it is the responsibility of its user. The com.tffenterprises.music.io.TaggedFile class is such a compliant user. Standard practice for ID3v2 tags is to insert the string "ID3" at the the beginning of a file, followed by a header and a variable-length number of bytes. The toBytes() instance method will output an array of bytes including the header, the data and the padding (used for future addition of information).

Version:
1.0d1 $Date: 2003/11/10 01:55:29 $
Author:
Guillaume Lessard, Daniel M. Zimmerman
See Also:
Serialized Form

Field Summary
private  boolean changed
          Whether this tag has been changed.
private  int fileLength
          How many bytes the tag occupies in the file, excluding the header and footer.
private  Flags flags
          The Flags object.
private  java.util.Hashtable frameTable
          A hashtable containing all the tag's information frames.
static int HEADER_LENGTH
          The byte length of an ID3v2 header.
private  int minimalLength
          The minimum number of bytes the tag can occupy in the file, excluding the header and footer.
private  int paddingLength
          How many bytes were skipped after the frame data.
static java.lang.String PREFIX
          The prefix to an ID3v2 tag.
 
Fields inherited from interface com.tffenterprises.music.tag.id3v2.frame.FrameTypes
ALBUM, ALBUM_TITLE, ARTIST, ATTACHED_PICTURE, AUDIO_ENCRYPTION, AUDIO_SIZE, AUTHOR, BAND, BEATS_PER_MINUTE, COMMENT, COMMERCIAL_FRAME, COMMERCIAL_INFORMATION, COMPOSER, CONDUCTOR, CONTENT_TYPE, COPYRIGHT, COPYRIGHT_INFORMATION, DATE, DURATION, ENCAPSULATED_OBJECT, ENCODED_BY, ENCODER_SETTINGS, ENCODER_USED, ENCRYPTION_METHOD, EQUALIZATION, FILE_OWNER, FILE_TYPE, GROUP_IDENTIFICATION, INITIAL_KEY, INTERNATIONAL_STANDARD_RECORDING_CODE, INTERNET_RADIO_STATION_NAME, INTERNET_RADIO_STATION_OWNER, INVOLVED_PEOPLE, ISRC, LANGUAGE_LIST, LEAD_PERFORMER, LEGAL_INFORMATION, LENGTH, LICENSEE, LINKED_INFORMATION, LYRICIST, MEDIA_TYPE, MODIFIED_BY, MPEG_LOCATION_LOOKUP_TABLE, MUSIC_CD_IDENTIFIER, OFFICIAL_ARTIST_PAGE, OFFICIAL_AUDIO_SOURCE_PAGE, OFFICIAL_FILE_PAGE, OFFICIAL_PUBLISHER_PAGE, OFFICIAL_RADIO_STATION_PAGE, ORCHESTRA, ORIGINAL_ALBUM, ORIGINAL_ARTIST, ORIGINAL_AUTHOR, ORIGINAL_FILENAME, ORIGINAL_LYRICIST, ORIGINAL_PERFORMER, ORIGINAL_RELEASE_YEAR, OWNERSHIP_FRAME, PART_OF_SET, PAYMENT, PLAY_COUNTER, PLAYLIST_DELAY, POPULARIMETER, POSITION_IN_SET, POSITION_SYNCHRONISATION_FRAME, PRIVATE_FRAME, PUBLISHER, RECOMMENDED_BUFFER_SIZE, RECORDING_DATES, RELATIVE_VOLUME_ADJUSTMENT, REMIX, REVERB, SET_TITLE, SIZE, SOLOIST, SUB_TITLE, SUPER_TITLE, SYNCHRONIZED_TEMPO_CODES, SYNCHRONIZED_TEXT, TERMS_OF_USE, textFrameTypes, TIME, TIME_MILLISECONDS, TIME_MINUTES_SECONDS, TIMING_CODES, TITLE, TRACK_NUMBER, UNIQUE_FILE_ID, UNSYNCHRONIZED_TEXT, urlFrameTypes, USER_DEFINED_TEXT, USER_DEFINED_URL, YEAR
 
Constructor Summary
ID3v2()
          Default constructor.
ID3v2(byte[] byteArray)
          Constructs an ID3v2 object from a byte array.
ID3v2(ID3Tag tag)
          Constructs an ID3v2 tag using the data contained in another Tag implementor.
ID3v2(java.io.InputStream in)
          Constructs an ID3v2 object from an InputStream.
ID3v2(short version)
          Constructs an ID3v2 tag using the version supplied as a parameter.
 
Method Summary
 Frame addFrame(Frame frame)
          Add a given frame to this ID3v2 tag.
static boolean CheckFileForTag(java.io.RandomAccessFile raFile)
          Checks for the presence of an ID3v2 tag in a file.
static byte[] CheckFileForTagVersion(java.io.RandomAccessFile raFile)
          Checks for the presence of an ID3v2 tag and returns its version.
 java.lang.Object clone()
          Returns a clone of this ID3v2 tag.
 boolean equals(java.lang.Object other)
          Compares this ID3v2 tag with another object.
 java.lang.String getAlbum()
          Returns the title of the album or set on which this track can be found.
 java.lang.String getArtist()
          Returnsthe name of the artist or performer featured on the track represented by this tag.
 byte[] getBytes()
          Returns a byte array equivalent to the tag's representation in a file, without the prefix.
 byte[] getBytes(int length)
          Returns a byte array equivalent to the tag's representation in a file, padded to the given length, but without the prefix.
 java.util.zip.Checksum getChecksum()
          Returns a Checksum of all this tag's data.
 java.lang.String getComment()
          Returns the comment attached to the track.
 int getFileLength()
          Returns the byte length occupied by this tag in its original file.
 Flags getFlags()
          Returns the Flags object for this ID3v2 tag.
 Frame getFrameOfType(java.lang.String theID)
          Returns a frame of an appropriate class to handle a frame with the given ID.
 java.lang.String getFrameTextForID(java.lang.String theID)
          Returns the text for the TextFrame with the ID passed as a parameter.
 byte getGenre()
          Returns a byte representing the genre of the track.
 Frame getKeyedFrameOfType(java.lang.String theID, java.lang.String theDescription)
           
 int getMinimalLength()
          Returns the minimal length that could be occupied by this tag in a file (including the prefix).
 Frame getNewFrameOfType(java.lang.String theID)
          Retruns a new frame of an appropriate class to handle the data for a given ID.
static int GetTagLength(java.io.RandomAccessFile raFile)
          Get the length of the ID3v2 tag, including header bytes, in the specified file.
static long GetTagOffset(java.io.RandomAccessFile raFile)
          Obtains the offset at which an ID3v2 tag would be located if there were one in the given file.
 java.lang.String getTitle()
          Returnsthe title of the track represented by this tag.
 byte getTrackNumber()
          Return the track's position out of its set, as an integer.
 short getVersion()
          Returns the version number of the format of this tag.
 short getYear()
          Returns the year during which the track was recorded.
 int hashCode()
          Returns a hash code for this ID3v2 tag.
 boolean isChanged()
          Returns true if the tag has been changed, false otherwise.
private  void parseFrames(AccountingInput acc, java.io.InputStream in, int len)
          Parse the frames.
private  void parseMetaFrame(MetaFrame meta)
          Obtain the frames that were embedded in a MetaFrame.
private  void parseStream(java.io.InputStream in)
          Parse the InputStream in which the ID3v2 information is embedded.
 Frame removeFrame(Frame frame)
          Removes the given frame from this tag, and returns the removed frame, or null if the referenced frame wasn't part of this tag.
 void setAlbum(java.lang.String album)
          Sets the title of the album or set on which this track can be found.
 void setArtist(java.lang.String artist)
          Sets the name of the artist or performer featured on the track represented by this tag.
 void setChanged(boolean changed)
          Sets or clears the "changed" bit.
 void setComment(java.lang.String comment)
          Attaches a comment to the track.
 void setComment(java.lang.String comment, java.lang.String description)
           
 void setFrameTextForID(java.lang.String theID, java.lang.String theText)
          Sets the text for the TextFrame frame with the ID passed as a parameter.
 void setGenre(byte genre)
          Sets the byte representing the genre of the track.
private  void setKeyedFrameText(java.lang.String theID, java.lang.String description, java.lang.String text)
          Sets the value text for a TXXX or COMM frame with an empty description.
 void setTitle(java.lang.String title)
          Sets the title of the track represented by this tag.
 void setTrackNumber(byte trackNumber)
          Sets the position of the track within its set.
 void setYear(short year)
          Sets the year during which the track was recorded or released.
 java.lang.String toString()
          Returns a String representation of this ID3v2 tag.
 void updateChecksum(DataOutputChecksum checksum)
          Updates a checksum with this tag's data
private  void writeFrameBytes(java.io.OutputStream os)
          Writes this tag's frames to the given OutputStream.
 void writeTo(java.io.OutputStream out)
          Writes a representation of tag to the given OutputStream.
 void writeTo(java.io.OutputStream out, int length)
          Writes a representation of this tag to the given OutputStream, padded to the given length.
 
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

PREFIX

public static final java.lang.String PREFIX
The prefix to an ID3v2 tag.

See Also:
Constant Field Values

HEADER_LENGTH

public static final int HEADER_LENGTH
The byte length of an ID3v2 header.

See Also:
Constant Field Values

frameTable

private java.util.Hashtable frameTable
A hashtable containing all the tag's information frames.


flags

private Flags flags
The Flags object. Its behaviour depends on ID3v2 version number. It's way cool.


fileLength

private transient int fileLength
How many bytes the tag occupies in the file, excluding the header and footer. If the tag was not read from a file, this field contains the minimal number of bytes necessary to hold the tag (lazily updated).


minimalLength

private transient int minimalLength
The minimum number of bytes the tag can occupy in the file, excluding the header and footer.


paddingLength

private transient int paddingLength
How many bytes were skipped after the frame data. This is there for debugging and trivia; it's really useless.


changed

private transient boolean changed
Whether this tag has been changed.

Constructor Detail

ID3v2

public ID3v2()
Default constructor. Constructs an ID3v2 tag with no information.


ID3v2

public ID3v2(short version)
      throws TagDataFormatException
Constructs an ID3v2 tag using the version supplied as a parameter.

Parameters:
version - The version of the ID3v2 specification to be used.
Throws:
TagDataFormatException - if the version can't be used.

ID3v2

public ID3v2(byte[] byteArray)
      throws TagDataFormatException,
             java.io.IOException,
             java.lang.IllegalArgumentException
Constructs an ID3v2 object from a byte array.

Parameters:
byteArray - The byte array.
Throws:
TagDataFormatException - if the byte array contains malformed data, in most cases.
java.io.IOException - if the byte array contains malformed data, in other cases.
java.lang.IllegalArgumentException - if the byte array does not contain a valid ID3v2 tag.

ID3v2

public ID3v2(java.io.InputStream in)
      throws TagDataFormatException,
             java.io.IOException,
             java.lang.IllegalArgumentException
Constructs an ID3v2 object from an InputStream.

Parameters:
in - The InputStream from which the ID3v2 information should be read.
Throws:
TagDataFormatException - if the byte array contains malformed data.
java.io.IOException - if such an error occurs on the input stream.
java.lang.IllegalArgumentException - if the byte array does not contain a valid ID3v2 tag.

ID3v2

public ID3v2(ID3Tag tag)
Constructs an ID3v2 tag using the data contained in another Tag implementor. The title, artist, album, comment, year, track number, and genre information are copied from the other Tag; no other data is copied.

Parameters:
tag - The tag which provides initial data for this ID3v2 tag.
Method Detail

CheckFileForTag

public static boolean CheckFileForTag(java.io.RandomAccessFile raFile)
                               throws java.io.IOException
Checks for the presence of an ID3v2 tag in a file.

Parameters:
raFile - the file to check for the presence of a tag.
Returns:
true if the file has an ID3v2 tag, false otherwise.
Throws:
java.io.IOException - if there is a problem reading from the file.

CheckFileForTagVersion

public static byte[] CheckFileForTagVersion(java.io.RandomAccessFile raFile)
                                     throws java.io.IOException
Checks for the presence of an ID3v2 tag and returns its version. If there is no ID3v2 tag, the method returns the null array.

Parameters:
raFile - the file to check for the presence of a tag.
Returns:
a 2-element byte array containing the 2 version numbers, or null if there is no ID3v2 tag.
Throws:
java.io.IOException - if there is a problem reading from the file.

GetTagOffset

public static long GetTagOffset(java.io.RandomAccessFile raFile)
                         throws java.io.IOException
Obtains the offset at which an ID3v2 tag would be located if there were one in the given file. Note that the offset of an ID3v2 tag is always 3 (after the 3-byte "ID3" string). This method is provided for consistency with other ID3 subclasses.

Parameters:
raFile - the file from which to extract the offset.
Returns:
the offset at which the ID3v2 information should be found.
Throws:
java.io.IOException - if there is a problem reading from the file. Since there is no file reading going on in this method yet, this should not happen.

GetTagLength

public static int GetTagLength(java.io.RandomAccessFile raFile)
                        throws java.io.IOException
Get the length of the ID3v2 tag, including header bytes, in the specified file. This method assumes that the file has already been checked for the presence of an ID3v2 tag. The file pointer will be moved by this operation.

Parameters:
raFile - the file for which to get the tag length.
Returns:
the length of the ID3v2 tag.
Throws:
java.io.IOException - if there is a problem reading from the file.

clone

public java.lang.Object clone()
Returns a clone of this ID3v2 tag.

Overrides:
clone in class java.lang.Object
Returns:
a clone of this ID3v2 tag.

updateChecksum

public void updateChecksum(DataOutputChecksum checksum)
Updates a checksum with this tag's data

Parameters:
checksum - the checksum to update

getChecksum

public final java.util.zip.Checksum getChecksum()
Returns a Checksum of all this tag's data.

Returns:
a Checksum of all of this tag's data.

hashCode

public final int hashCode()
Returns a hash code for this ID3v2 tag.

Overrides:
hashCode in class java.lang.Object
Returns:
a hash code for this ID3v2 tag.

equals

public boolean equals(java.lang.Object other)
Compares this ID3v2 tag with another object.

Overrides:
equals in class java.lang.Object
Parameters:
other - The other object.
Returns:
true if the two objects are equivalent, false otherwise.

toString

public java.lang.String toString()
Returns a String representation of this ID3v2 tag.

Specified by:
toString in interface ID3Tag
Overrides:
toString in class java.lang.Object
Returns:
a String representation of this ID3v2 tag.

getFrameTextForID

public java.lang.String getFrameTextForID(java.lang.String theID)
Returns the text for the TextFrame with the ID passed as a parameter. Note that if the ID does not point to a TextFrame instance, this will return the empty string. Users beware.

Parameters:
theID - the frame ID to be used to obtain the text.
Returns:
the text for the TextFrame with the ID passed as a parameter.

getFlags

public Flags getFlags()
Returns the Flags object for this ID3v2 tag.

Returns:
the Flags object for this ID3v2 tag.

setFrameTextForID

public void setFrameTextForID(java.lang.String theID,
                              java.lang.String theText)
Sets the text for the TextFrame frame with the ID passed as a parameter. Note that if the ID does not point to a TextFrame type, this does nothing.

Parameters:
theID - the frame ID to be used to find a frame and set its text.
theText - the frame text to use for the frame.

setKeyedFrameText

private void setKeyedFrameText(java.lang.String theID,
                               java.lang.String description,
                               java.lang.String text)
Sets the value text for a TXXX or COMM frame with an empty description. This is a really lame quick fix. This method should probably not exist in the first place.

Parameters:
theID - the frame ID to be used to find a frame and set its text.
theText - the frame text to use for the frame.

getFrameOfType

public Frame getFrameOfType(java.lang.String theID)
Returns a frame of an appropriate class to handle a frame with the given ID. If an appropriate frame does not already exist in the frame table, the null pointer will be returned.

Parameters:
theID - the frame id for which to find a frame.
Returns:
a frame of an appropriate class, or null.

getKeyedFrameOfType

public Frame getKeyedFrameOfType(java.lang.String theID,
                                 java.lang.String theDescription)

getNewFrameOfType

public Frame getNewFrameOfType(java.lang.String theID)
Retruns a new frame of an appropriate class to handle the data for a given ID. The frame will have the correct specification version. Note that the frame will *NOT* be added to the tag's frame list. If adding the frame is desirable, it should be done separately.

Parameters:
theID - the frame id for which to create a new frame.
Returns:
a frame of an appropriate class.

getTitle

public java.lang.String getTitle()
Returnsthe title of the track represented by this tag. If this information is not available, this method returns an empty string.

Specified by:
getTitle in interface ID3Tag
Returns:
the title of the track represented by this tag.

setTitle

public void setTitle(java.lang.String title)
Sets the title of the track represented by this tag.

Specified by:
setTitle in interface ID3Tag
Parameters:
title - the track title.

getArtist

public java.lang.String getArtist()
Returnsthe name of the artist or performer featured on the track represented by this tag. If this information is not available, this method returns an empty string.

Specified by:
getArtist in interface ID3Tag
Returns:
the name of the artist or performer featured on the track.

setArtist

public void setArtist(java.lang.String artist)
Sets the name of the artist or performer featured on the track represented by this tag.

Specified by:
setArtist in interface ID3Tag
Parameters:
artist - the artist/performer name.

getAlbum

public java.lang.String getAlbum()
Returns the title of the album or set on which this track can be found. If this information is not available, this method returns an empty string.

Specified by:
getAlbum in interface ID3Tag
Returns:
the title of the album or set on which this track can be found.

setAlbum

public void setAlbum(java.lang.String album)
Sets the title of the album or set on which this track can be found.

Specified by:
setAlbum in interface ID3Tag
Parameters:
album - the album/set title.

getComment

public java.lang.String getComment()
Returns the comment attached to the track. If there is no comment attached to the track, this method returns an empty string.

Specified by:
getComment in interface ID3Tag
Returns:
a comment attached to the track.

setComment

public void setComment(java.lang.String comment)
Attaches a comment to the track.

Specified by:
setComment in interface ID3Tag
Parameters:
comment - the comment.

setComment

public void setComment(java.lang.String comment,
                       java.lang.String description)

getTrackNumber

public byte getTrackNumber()
Return the track's position out of its set, as an integer. If this information is not available, this method returns -1.

Specified by:
getTrackNumber in interface ID3Tag
Returns:
the track's position out of its set, or -1.

setTrackNumber

public void setTrackNumber(byte trackNumber)
                    throws java.lang.IllegalArgumentException
Sets the position of the track within its set.

Specified by:
setTrackNumber in interface ID3Tag
Parameters:
trackNumber - the position of the track within its set.
Throws:
java.lang.IllegalArgumentException - if trackNumber <= 0.

getGenre

public byte getGenre()
Returns a byte representing the genre of the track. If this information is not available, this method returns -1.

Specified by:
getGenre in interface ID3Tag
Returns:
a byte representing the genre of the track, or -1.

setGenre

public void setGenre(byte genre)
              throws java.lang.IllegalArgumentException
Sets the byte representing the genre of the track. To set no genre, -1 should be passed to this method.

Specified by:
setGenre in interface ID3Tag
Parameters:
genre - the byte representing the genre of the track.
Throws:
java.lang.IllegalArgumentException - if genre < -1

getYear

public short getYear()
Returns the year during which the track was recorded. If this information is not available, this method returns -1.

Specified by:
getYear in interface ID3Tag
Returns:
the year during which the track was recorded.

setYear

public void setYear(short year)
Sets the year during which the track was recorded or released. To clear the year field, -1 should be passed to this method.

Specified by:
setYear in interface ID3Tag
Parameters:
year - during which the track was recorded or released.
Throws:
java.lang.IllegalArgumentException - if year < -1

isChanged

public boolean isChanged()
Returns true if the tag has been changed, false otherwise.

Specified by:
isChanged in interface ID3Tag
Returns:
true if the tag has been changed, false otherwise.

setChanged

public void setChanged(boolean changed)
Sets or clears the "changed" bit.

Specified by:
setChanged in interface ID3Tag
Parameters:
changed - true to set the changed bit, false to clear it.

getBytes

public byte[] getBytes()
Returns a byte array equivalent to the tag's representation in a file, without the prefix.

Specified by:
getBytes in interface ID3Tag
Returns:
a byte array equivalent to the tag's minimal-length representation in a file.

getBytes

public byte[] getBytes(int length)
Returns a byte array equivalent to the tag's representation in a file, padded to the given length, but without the prefix. If a byte array is returned by this method, it will always be of length length - PREFIX.length() if length is positive, or of the minimal tag length if length is non-positive. A null byte array will be returned if the tag cannot fit in the given length, or if there is a problem determining the representation of the tag.

Parameters:
length - The number of bytes to which the tag length should be padded. If this number is non-positive, the tag will not be padded.
Returns:
a byte array equivalent to the tag's representation in a file.

writeTo

public void writeTo(java.io.OutputStream out)
             throws java.io.IOException
Writes a representation of tag to the given OutputStream. This representation does not include the tag prefix.

Parameters:
out - OutputStream to which the tag should be written.
Throws:
java.io.IOException - if there is a problem with the OutputStream.

writeTo

public void writeTo(java.io.OutputStream out,
                    int length)
             throws java.io.IOException
Writes a representation of this tag to the given OutputStream, padded to the given length. This representation does not include the tag prefix.

Parameters:
out - OutputStream to which the tag should be written.
length - The desired length. If this is not positive, the tag will be written with minimal length.
Throws:
java.io.IOException - if there is a problem with the OutputStream.

writeFrameBytes

private void writeFrameBytes(java.io.OutputStream os)
                      throws java.io.IOException
Writes this tag's frames to the given OutputStream.

Parameters:
os - the OutputStream to which the tag's frames should be written.
Throws:
java.io.IOException - if there is a problem with the OutputStream.

getVersion

public short getVersion()
Returns the version number of the format of this tag.

Returns:
the version number of the format of this tag.

getFileLength

public int getFileLength()
Returns the byte length occupied by this tag in its original file. This length includes the tag prefix.

In an ideal world, this is the larger of the length of the tag in the file from which it was read and the minimal length of the tag. This length includes the prefix.

Returns:
the byte length occupied by this tag in a file.

getMinimalLength

public int getMinimalLength()
Returns the minimal length that could be occupied by this tag in a file (including the prefix).

Returns:
the minimal length that could be occupied by this tag in a file (including the prefix).

addFrame

public Frame addFrame(Frame frame)
Add a given frame to this ID3v2 tag.

Parameters:
frame - the frame to be added to the ID3v2 tag.
Returns:
a Frame that was replaced by frame, or null.

removeFrame

public Frame removeFrame(Frame frame)
Removes the given frame from this tag, and returns the removed frame, or null if the referenced frame wasn't part of this tag.

Parameters:
frame - the frame to be removed from this tag.
Returns:
the frame that was removed from this tag, or null if the referenced frame wasn't part of this tag.

parseStream

private void parseStream(java.io.InputStream in)
                  throws java.io.IOException,
                         java.lang.IllegalArgumentException,
                         TagDataFormatException
Parse the InputStream in which the ID3v2 information is embedded.

Parameters:
in - the InputStream in which the ID3v2 information is embedded.
Throws:
java.lang.IllegalArgumentException - if the stream does not contain a valid tag, or an ill-encoded tag.
java.io.IOException - if an I/O error occurs.
TagDataFormatException

parseFrames

private void parseFrames(AccountingInput acc,
                         java.io.InputStream in,
                         int len)
                  throws java.io.IOException,
                         PaddingException
Parse the frames. The parameters ins and acc are really ultimately referring to the same object, but to allow for some flexibility, it's passed separately with a different type declaration.

Parameters:
acc - an instance of AccountingInput
in - an InputStream.
len - the number of bytes to be converted to frames.
Throws:
java.io.IOException - if such an error occurs on the input stream.
PaddingException

parseMetaFrame

private void parseMetaFrame(MetaFrame meta)
Obtain the frames that were embedded in a MetaFrame.

Parameters:
meta - a MetaFrame that embeds other frames.