All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.farng.mp3.id3.ID3v2_2Frame Maven / Gradle / Ivy

Go to download

This library reads song information, such as song title, artist, and album, from an MP3 file. It supports ID3v1, ID3v1.1, Lyrics3v1, Lyrics3v2, ID3v2.2, ID3v2.3, and ID3v2.4 tags. MP3 Frame Headers can also be read. There is a FilenameTag, a ID3v2.4 tag that is intelligently derived from the file name. It contains tag synchronization utilities, multiple save options, and easy tag conversion methods.

The newest version!
package org.farng.mp3.id3;

import org.farng.mp3.InvalidTagException;
import org.farng.mp3.TagUtility;

import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * 

The headers of the frames are similar in their construction. They consist of one three character * identifier (capital A-Z and 0-9) and one three byte size field, making a total of six bytes. The header is excluded * from the size. Identifiers beginning with "X", "Y" and "Z" are for experimental use and free for everyone to use. * Have in mind that someone else might have used the same identifier as you. All other identifiers are either used or * reserved for future use. This gives us 46656 combinations of frame identifiers.

*

*

The three character frame identifier is followed by a three byte size descriptor, making a total header * size of six bytes in every frame. The size is calculated as framesize excluding frame identifier and size descriptor * (frame size - 6).

*

*

The decision to have a 6 byte frame header was taken in an attempt to balance big frames against * little overhead. One might think that it's stupid to optimize away a few bytes when the entire MP3-file is soo huge. * On the other hand I thought it was really cool that most ID3v1 tags, when converted to ID3v2 was smaller than before. * Size does matter.

*

*

There is no fixed order of the frames' appearance in the tag, although it is desired that the frames are * arranged in order of significance concerning the recognition of the file. The reason for this is to make it faster * to search for a specific file by scanning the ID3v2 tags; an intelligent parser wouldn't have to keep reading the * entire tag after having found that the file isn't the one being looked for. An example of such order: UFI, MCI, TT2 ...

*

*

A tag must contain at least one frame. A frame must be at least 1 byte big, excluding the 6-byte header. *

*

*

If nothing else is said, a string is represented as ISO-8859-1 characters in the * range $20 - $FF. All unicode strings use 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2). All * numeric strings are always encoded as ISO-8859-1. Terminated strings are terminated with $00 * if encoded with ISO-8859-1 and $00 00 if encoded as unicode. If nothing else is said, newline * characters are forbidden. In ISO-8859-1, a new line is represented, when allowed, with $0A * only. Frames that allow different types of text encoding have a text encoding description byte directly after the * frame size. If ISO-8859-1 is used this byte should be $00, if unicode * is used it should be $01.

*

*

The three byte language field is used to describe the language of the frame's content, according to ISO-639-2.
ISO-639-1 is not used since its supported languages are just a subset of those * in ISO-639-2.

*

*

All URLs may be relative, e.g. "picture.png", "../doc.txt".

*

*

If a frame is longer than it should be, e.g. having more fields than specified in this document, that * indicates that additions to the frame have been made in a later version of the ID3 standard. This is reflected by the * revision number in the header of the tag.
This allows us to fix our mistakes as well as introducing new * features in the already existing frames.

* * @author Eric Farng * @version $Revision: 1.6 $ */ public class ID3v2_2Frame extends AbstractID3v2Frame { /** * Creates a new ID3v2_2Frame object. */ public ID3v2_2Frame() { // base empty constructor } /** * Creates a new ID3v2_2Frame object. */ public ID3v2_2Frame(final AbstractID3v2FrameBody body) { super(body); } /** * Creates a new ID3v2_2Frame object. */ public ID3v2_2Frame(final ID3v2_2Frame frame) { super(frame); } /** * Creates a new ID3v2_3Frame object. */ public ID3v2_2Frame(final AbstractID3v2Frame frame) { if (frame.getBody() == null) { // do nothing } else if (TagUtility.isID3v2_2FrameIdentifier(frame.getIdentifier())) { this.setBody((AbstractID3v2FrameBody) TagUtility.copyObject(frame.getBody())); // } else if (TagUtility.isID3v2_3FrameIdentifier(frame.getIdentifier())) { // // @todo correctly convert tags // this.setBody((AbstractID3v2FrameBody) TagUtility.copyObject(frame.getBody())); // } else if (TagUtility.isID3v2_4FrameIdentifier(frame.getIdentifier())) { // // @todo correctly convert tags // this.setBody((AbstractID3v2FrameBody) TagUtility.copyObject(frame.getBody())); } } /** * Creates a new ID3v2_2Frame object. */ public ID3v2_2Frame(final RandomAccessFile file) throws IOException, InvalidTagException { this.read(file); } public int getSize() { return this.getBody().getSize() + 3 + 3; } public void read(final RandomAccessFile file) throws IOException, InvalidTagException { final byte[] buffer = new byte[3]; // lets scan for a non-zero byte; long filePointer; byte b; do { filePointer = file.getFilePointer(); b = file.readByte(); org.farng.mp3.id3.AbstractID3v2.incrementPaddingCounter(); } while (b == 0); file.seek(filePointer); org.farng.mp3.id3.AbstractID3v2.decrementPaddingCounter(); // read the 3 chracter identifier file.read(buffer, 0, 3); final String identifier = new String(buffer, 0, 3); // is this a valid identifier? if (isValidID3v2FrameIdentifier(identifier) == false) { file.seek(file.getFilePointer() - 2); throw new InvalidTagException(identifier + " is not a valid ID3v2.20 frame"); } this.setBody(readBody(identifier, file)); } public void write(final RandomAccessFile file) throws IOException { final byte[] buffer = new byte[4]; final String str = TagUtility.truncate(getIdentifier(), 3); for (int i = 0; i < str.length(); i++) { buffer[i] = (byte) str.charAt(i); } file.write(buffer, 0, str.length()); this.getBody().write(file); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy