📄 id3v24tag.java
字号:
copyPrimitives(copyObject);
copyFrames(copyObject);
}
/**
* Creates a new ID3v2_4 datatype based on another (non 2.4) tag
*
* @param mp3tag
*/
public ID3v24Tag(AbstractTag mp3tag)
{
logger.info("Creating tag from a tag of a different version");
frameMap = new LinkedHashMap();
if (mp3tag != null)
{
//Should use simpler copy constructor
if ((mp3tag instanceof ID3v24Tag == true))
{
throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument");
}
/* If we get a tag, we want to convert to id3v2_4
* both id3v1 and lyrics3 convert to this type
* id3v1 needs to convert to id3v2_4 before converting to lyrics3
*/
else if (mp3tag instanceof AbstractID3v2Tag)
{
copyPrimitives((AbstractID3v2Tag) mp3tag);
copyFrames((AbstractID3v2Tag) mp3tag);
}
//IDv1
else if (mp3tag instanceof ID3v1Tag)
{
// convert id3v1 tags.
ID3v1Tag id3tag = (ID3v1Tag) mp3tag;
ID3v24Frame newFrame;
AbstractID3v2FrameBody newBody;
if (id3tag.title.length() > 0)
{
newBody = new FrameBodyTIT2((byte) 0, id3tag.title);
newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_TITLE);
newFrame.setBody(newBody);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
if (id3tag.artist.length() > 0)
{
newBody = new FrameBodyTPE1((byte) 0, id3tag.artist);
newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_ARTIST);
newFrame.setBody(newBody);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
if (id3tag.album.length() > 0)
{
newBody = new FrameBodyTALB((byte) 0, id3tag.album);
newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_ALBUM);
newFrame.setBody(newBody);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
if (id3tag.year.length() > 0)
{
newBody = new FrameBodyTDRC((byte) 0, id3tag.year);
newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_YEAR);
newFrame.setBody(newBody);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
if (id3tag.comment.length() > 0)
{
newBody = new FrameBodyCOMM((byte) 0, "ENG", "", id3tag.comment);
newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_COMMENT);
newFrame.setBody(newBody);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
if (((id3tag.genre & ID3v1Tag.BYTE_TO_UNSIGNED) >= 0) && ((id3tag.genre & ID3v1Tag.BYTE_TO_UNSIGNED) != ID3v1Tag.BYTE_TO_UNSIGNED))
{
Integer genreId = id3tag.genre & ID3v1Tag.BYTE_TO_UNSIGNED;
String genre = "(" + genreId + ") " + GenreTypes.getInstanceOf().getValueForId(genreId);
newBody = new FrameBodyTCON((byte) 0, genre);
newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_GENRE);
newFrame.setBody(newBody);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
if (mp3tag instanceof ID3v11Tag)
{
ID3v11Tag id3tag2 = (ID3v11Tag) mp3tag;
if (id3tag2.track > 0)
{
newBody = new FrameBodyTRCK((byte) 0, Byte.toString(id3tag2.track));
newFrame = new ID3v24Frame(ID3v24Frames.FRAME_ID_TRACK);
newFrame.setBody(newBody);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
}
}
//Lyrics 3
else if (mp3tag instanceof AbstractLyrics3)
{
//Put the conversion stuff in the individual frame code.
Lyrics3v2 lyric;
if (mp3tag instanceof Lyrics3v2)
{
lyric = new Lyrics3v2((Lyrics3v2) mp3tag);
}
else
{
lyric = new Lyrics3v2(mp3tag);
}
Iterator iterator = lyric.iterator();
Lyrics3v2Field field;
ID3v24Frame newFrame;
while (iterator.hasNext())
{
try
{
field = (Lyrics3v2Field) iterator.next();
newFrame = new ID3v24Frame(field);
frameMap.put(newFrame.getIdentifier(), newFrame);
}
catch (InvalidTagException ex)
{
logger.warning("Unable to convert Lyrics3 to v24 Frame:Frame Identifier");
}
}
}
}
}
/**
* Creates a new ID3v2_4 datatype.
*
* @param buffer
* @param loggingFilename
* @throws TagException
*/
public ID3v24Tag(ByteBuffer buffer, String loggingFilename) throws TagException
{
frameMap = new LinkedHashMap();
setLoggingFilename(loggingFilename);
this.read(buffer);
}
/**
* Creates a new ID3v2_4 datatype.
*
* @param buffer
* @throws TagException
* @deprecated use {@link #ID3v24Tag(ByteBuffer,String)} instead
*/
public ID3v24Tag(ByteBuffer buffer) throws TagException
{
this(buffer, "");
}
/**
* @return identifier
*/
public String getIdentifier()
{
return "ID3v2.40";
}
/**
* Return tag size based upon the sizes of the frames rather than the physical
* no of bytes between start of ID3Tag and start of Audio Data.
*
* @return size
*/
public int getSize()
{
int size = TAG_HEADER_LENGTH;
if (extended)
{
size += this.TAG_EXT_HEADER_LENGTH;
if (updateTag)
{
size += this.TAG_EXT_HEADER_UPDATE_LENGTH;
}
if (crcDataFlag)
{
size += this.TAG_EXT_HEADER_CRC_LENGTH;
}
if (tagRestriction)
{
size += this.TAG_EXT_HEADER_RESTRICTION_LENGTH;
}
}
size += super.getSize();
logger.finer("Tag Size is" + size);
return size;
}
/**
* @param obj
* @return equality
*/
public boolean equals(Object obj)
{
if ((obj instanceof ID3v24Tag) == false)
{
return false;
}
ID3v24Tag object = (ID3v24Tag) obj;
if (this.footer != object.footer)
{
return false;
}
if (this.imageEncodingRestriction != object.imageEncodingRestriction)
{
return false;
}
if (this.imageSizeRestriction != object.imageSizeRestriction)
{
return false;
}
if (this.tagRestriction != object.tagRestriction)
{
return false;
}
if (this.tagSizeRestriction != object.tagSizeRestriction)
{
return false;
}
if (this.textEncodingRestriction != object.textEncodingRestriction)
{
return false;
}
if (this.textFieldSizeRestriction != object.textFieldSizeRestriction)
{
return false;
}
if (this.updateTag != object.updateTag)
{
return false;
}
return super.equals(obj);
}
/**
* Read Tag from Specified file.
* Read tag header, delegate reading of frames to readFrames()
*
* @param byteBuffer to read the tag from
* @throws TagException
* @throws TagNotFoundException
* @throws InvalidTagException
*/
public void read(ByteBuffer byteBuffer) throws TagException
{
int size;
byte[] buffer;
if (seek(byteBuffer) == false)
{
throw new TagNotFoundException(getLoggingFilename() + ":" + getIdentifier() + " tag not found");
}
//Flags
byte flags = byteBuffer.get();
unsynchronization = (flags & MASK_V24_UNSYNCHRONIZATION) != 0;
extended = (flags & MASK_V24_EXTENDED_HEADER) != 0;
experimental = (flags & MASK_V24_EXPERIMENTAL) != 0;
footer = (flags & MASK_V24_FOOTER_PRESENT) != 0;
if (isUnsynchronization())
{
logger.warning(getLoggingFilename() + ":" + "ID3v24 Tag is unsynchronized");
}
if (extended)
{
logger.warning(getLoggingFilename() + ":" + "ID3v24 Tag is extended");
}
if (experimental)
{
logger.warning(getLoggingFilename() + ":" + "ID3v24 Tag is experimental");
}
if (footer)
{
logger.warning(getLoggingFilename() + ":" + "ID3v24 Tag has footer");
}
// Read the size, this is size of tag apart from tag header
size = ID3SyncSafeInteger.bufferToValue(byteBuffer);
logger.info(getLoggingFilename() + ":" + "Reading tag from file size set in header is" + size);
if (extended)
{
// int is 4 bytes.
int extendedHeaderSize = byteBuffer.getInt();
// the extended header must be atleast 6 bytes
if (extendedHeaderSize <= TAG_EXT_HEADER_LENGTH)
{
throw new InvalidTagException(getLoggingFilename() + ":" + "Invalid Extended Header Size.");
}
//Number of bytes
byteBuffer.get();
// Read the extended flag bytes
byte extFlag = byteBuffer.get();
updateTag = (extFlag & MASK_V24_TAG_UPDATE) != 0;
crcDataFlag = (extFlag & MASK_V24_CRC_DATA_PRESENT) != 0;
tagRestriction = (extFlag & MASK_V24_TAG_RESTRICTIONS) != 0;
// read the length byte if the flag is set
// this tag should always be zero but just in case
// read this information.
if (updateTag == true)
{
byteBuffer.get();
}
if (crcDataFlag == true)
{
// the CRC has a variable length
byteBuffer.get();
buffer = new byte[TAG_EXT_HEADER_CRC_DATA_LENGTH];
byteBuffer.get(buffer, 0, TAG_EXT_HEADER_CRC_DATA_LENGTH);
crcData = 0;
for (int i = 0; i < TAG_EXT_HEADER_CRC_DATA_LENGTH; i++)
{
crcData <<= 8;
crcData += buffer[i];
}
}
if (tagRestriction == true)
{
byteBuffer.get();
buffer = new byte[1];
byteBuffer.get(buffer, 0, 1);
tagSizeRestriction = (byte) ((buffer[0] & MASK_V24_TAG_SIZE_RESTRICTIONS) >> 6);
textEncodingRestriction = (byte) ((buffer[0] & MASK_V24_TEXT_ENCODING_RESTRICTIONS) >> 5);
textFieldSizeRestriction = (byte) ((buffer[0] & MASK_V24_TEXT_FIELD_SIZE_RESTRICTIONS) >> 3);
imageEncodingRestriction = (byte) ((buffer[0] & MASK_V24_IMAGE_ENCODING) >> 2);
imageSizeRestriction = (byte) (buffer[0] & MASK_V24_IMAGE_SIZE_RESTRICTIONS);
}
}
//Note if there was an extended header the size value has padding taken
//off so we dont search it.
readFrames(byteBuffer, size);
}
/**
* Read frames from tag
*/
protected void readFrames(ByteBuffer byteBuffer, int size)
{
logger.finest(getLoggingFilename() + ":" + "Start of frame body at" + byteBuffer.position());
//Now start looking for frames
ID3v24Frame next;
frameMap = new LinkedHashMap();
//Read the size from the Tag Header
this.fileReadSize = size;
// Read the frames until got to upto the size as specified in header
logger.finest(getLoggingFilename() + ":" + "Start of frame body at:" + byteBuffer.position() + ",frames data size is:" + size);
while (byteBuffer.position() <= size)
{
String id;
try
{
//Read Frame
logger.finest(getLoggingFilename() + ":" + "looking for next frame at:" + byteBuffer.position());
next = new ID3v24Frame(byteBuffer, getLoggingFilename());
id = next.getIdentifier();
loadFrameIntoMap(id, next);
}
//Found Empty Frame
catch (EmptyFrameException ex)
{
logger.warning(getLoggingFilename() + ":" + "Empty Frame:" + ex.getMessage());
this.emptyFrameBytes += TAG_HEADER_LENGTH;
}
catch (InvalidFrameIdentifierException ifie)
{
logger.info(getLoggingFilename() + ":" + "Invalid Frame Identifier:" + ifie.getMessage());
this.invalidFrameBytes++;
//Dont try and find any more frames
break;
}
//Problem trying to find frame
catch (InvalidFrameException ife)
{
logger.warning(getLoggingFilename() + ":" + "Invalid Frame:" + ife.getMessage());
this.invalidFrameBytes++;
//Dont try and find any more frames
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -