📄 id3v24tag.java
字号:
break;
}
}
}
/**
* Write the ID3 header to the ByteBuffer.
* <p/>
* TODO Calculate the CYC Data Check
* TODO Reintroduce Extended Header
*
* @param padding is the size of the padding
* @param size is the size of the body data
* @return ByteBuffer
* @throws IOException
*/
private ByteBuffer writeHeaderToBuffer(int padding, int size) throws IOException
{
//This would only be set if every frame in tag has been unsynchronized, I only unsychronize frames
//that need it, in any case I have been advised not to set it even then.
unsynchronization = false;
// Flags,currently we never calculate the CRC
// and if we dont calculate them cant keep orig values. Tags are not
// experimental and we never create extended header to keep things simple.
extended = false;
experimental = false;
footer = false;
// Create Header Buffer,allocate maximum possible size for the header
ByteBuffer headerBuffer = ByteBuffer.allocate(TAG_HEADER_LENGTH);
//TAGID
headerBuffer.put(TAG_ID);
//Major Version
headerBuffer.put(getMajorVersion());
//Minor Version
headerBuffer.put(getRevision());
//Flags
byte flagsByte = 0;
if (isUnsynchronization() == true)
{
flagsByte |= MASK_V24_UNSYNCHRONIZATION;
}
if (extended == true)
{
flagsByte |= MASK_V24_EXTENDED_HEADER;
}
if (experimental == true)
{
flagsByte |= MASK_V24_EXPERIMENTAL;
}
if (footer == true)
{
flagsByte |= MASK_V24_FOOTER_PRESENT;
}
headerBuffer.put(flagsByte);
//Size As Recorded in Header, don't include the main header length
//Additional Header Size,(for completeness we never actually write the extended header, or footer)
int additionalHeaderSize = 0;
if (extended)
{
additionalHeaderSize += this.TAG_EXT_HEADER_LENGTH;
if (updateTag)
{
additionalHeaderSize += this.TAG_EXT_HEADER_UPDATE_LENGTH;
}
if (crcDataFlag)
{
additionalHeaderSize += this.TAG_EXT_HEADER_CRC_LENGTH;
}
if (tagRestriction)
{
additionalHeaderSize += this.TAG_EXT_HEADER_RESTRICTION_LENGTH;
}
}
//Size As Recorded in Header, don't include the main header length
headerBuffer.put(ID3SyncSafeInteger.valueToBuffer(padding + size + additionalHeaderSize));
//Write Extended Header
ByteBuffer extHeaderBuffer = null;
if (extended == true)
{
//Write Extended Header Size
int extendedSize = TAG_EXT_HEADER_LENGTH;
if (updateTag == true)
{
extendedSize += TAG_EXT_HEADER_UPDATE_LENGTH;
}
if (crcDataFlag == true)
{
extendedSize += TAG_EXT_HEADER_CRC_LENGTH;
}
if (tagRestriction == true)
{
extendedSize += TAG_EXT_HEADER_RESTRICTION_LENGTH;
}
extHeaderBuffer = ByteBuffer.allocate(extendedSize);
extHeaderBuffer.putInt(extendedSize);
//Write Number of flags Byte
extHeaderBuffer.put((byte) TAG_EXT_NUMBER_BYTES_DATA_LENGTH);
//Write Extended Flags
byte extFlag = 0;
if (updateTag)
{
extFlag |= MASK_V24_TAG_UPDATE;
}
if (crcDataFlag)
{
extFlag |= MASK_V24_CRC_DATA_PRESENT;
}
if (tagRestriction)
{
extFlag |= MASK_V24_TAG_RESTRICTIONS;
}
extHeaderBuffer.put(extFlag);
//Write Update Data
if (updateTag)
{
extHeaderBuffer.put((byte) 0);
}
//Write CRC Data
if (crcDataFlag)
{
extHeaderBuffer.put((byte) TAG_EXT_HEADER_CRC_DATA_LENGTH);
extHeaderBuffer.put((byte) 0);
extHeaderBuffer.putInt(crcData);
}
//Write Tag Restriction
if (tagRestriction)
{
extHeaderBuffer.put((byte) TAG_EXT_HEADER_RESTRICTION_DATA_LENGTH);
//todo not currently setting restrictions
extHeaderBuffer.put((byte) 0);
}
}
if (extHeaderBuffer != null)
{
extHeaderBuffer.flip();
headerBuffer.put(extHeaderBuffer);
}
headerBuffer.flip();
return headerBuffer;
}
/**
* Write this tag to file.
*
* @param file
* @throws IOException
*/
public void write(File file, long audioStartLocation) throws IOException
{
logger.info("Writing tag to file");
//Write Body Buffer
byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray();
//Calculate Tag Size including Padding
int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) audioStartLocation);
//Calculate padding bytes required
int padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH);
ByteBuffer headerBuffer = writeHeaderToBuffer(padding, bodyByteBuffer.length);
//We need to adjust location of audio File
if (sizeIncPadding > audioStartLocation)
{
logger.finest("Adjusting Padding");
adjustPadding(file, sizeIncPadding, audioStartLocation);
}
//Write changes to file
FileChannel fc = null;
try
{
fc = new RandomAccessFile(file, "rw").getChannel();
fc.write(headerBuffer);
fc.write(ByteBuffer.wrap(bodyByteBuffer));
fc.write(ByteBuffer.wrap(new byte[padding]));
}
finally
{
if (fc != null)
{
fc.close();
}
}
}
/**
* Write tag to channel
*
* @param channel
* @throws IOException
*/
public void write(WritableByteChannel channel) throws IOException
{
logger.info("Writing tag to channel");
byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray();
ByteBuffer headerBuffer = writeHeaderToBuffer(0, bodyByteBuffer.length);
channel.write(headerBuffer);
channel.write(ByteBuffer.wrap(bodyByteBuffer));
}
/**
* Display the tag in an XMLFormat
*/
public void createStructure()
{
MP3File.getStructureFormatter().openHeadingElement(TYPE_TAG, getIdentifier());
super.createStructureHeader();
//Header
MP3File.getStructureFormatter().openHeadingElement(TYPE_HEADER, "");
MP3File.getStructureFormatter().addElement(TYPE_UNSYNCHRONISATION, this.isUnsynchronization());
MP3File.getStructureFormatter().addElement(TYPE_CRCDATA, this.crcData);
MP3File.getStructureFormatter().addElement(TYPE_EXPERIMENTAL, this.experimental);
MP3File.getStructureFormatter().addElement(TYPE_EXTENDED, this.extended);
MP3File.getStructureFormatter().addElement(TYPE_PADDINGSIZE, this.paddingSize);
MP3File.getStructureFormatter().addElement(TYPE_FOOTER, this.footer);
MP3File.getStructureFormatter().addElement(TYPE_IMAGEENCODINGRESTRICTION, this.paddingSize);
MP3File.getStructureFormatter().addElement(TYPE_IMAGESIZERESTRICTION, (int) this.imageSizeRestriction);
MP3File.getStructureFormatter().addElement(TYPE_TAGRESTRICTION, this.tagRestriction);
MP3File.getStructureFormatter().addElement(TYPE_TAGSIZERESTRICTION, (int) this.tagSizeRestriction);
MP3File.getStructureFormatter().addElement(TYPE_TEXTFIELDSIZERESTRICTION, (int) this.textFieldSizeRestriction);
MP3File.getStructureFormatter().addElement(TYPE_TEXTENCODINGRESTRICTION, (int) this.textEncodingRestriction);
MP3File.getStructureFormatter().addElement(TYPE_UPDATETAG, this.updateTag);
MP3File.getStructureFormatter().closeHeadingElement(TYPE_HEADER);
//Body
super.createStructureBody();
MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG);
}
/**
* Are all frame swithin this tag unsynchronized
* <p/>
* <p>Because synchronization occurs at the frame level it is not normally desirable to unsynchronize all frames
* and hence this flag is not normally set.
*
* @return are all frames within the tag unsynchronized
*/
public boolean isUnsynchronization()
{
return unsynchronization;
}
protected String getArtistId()
{
return ID3v24Frames.FRAME_ID_ARTIST;
}
protected String getAlbumId()
{
return ID3v24Frames.FRAME_ID_ALBUM;
}
protected String getTitleId()
{
return ID3v24Frames.FRAME_ID_TITLE;
}
protected String getTrackId()
{
return ID3v24Frames.FRAME_ID_TRACK;
}
protected String getYearId()
{
return ID3v24Frames.FRAME_ID_YEAR;
}
protected String getCommentId()
{
return ID3v24Frames.FRAME_ID_COMMENT;
}
protected String getGenreId()
{
return ID3v24Frames.FRAME_ID_GENRE;
}
/**
* Create a new frame with the specified frameid
*
* @param id
* @return
*/
public ID3v24Frame createFrame(String id)
{
return new ID3v24Frame(id);
}
/**
* Create Frame for Id3 Key
* <p/>
* Only textual data supported at the moment, should only be used with frames that
* support a simple string argument.
*
* @param id3Key
* @param value
* @return
* @throws KeyNotFoundException
* @throws FieldDataInvalidException
*/
public TagField createTagField(ID3v24FieldKey id3Key, String value)
throws KeyNotFoundException, FieldDataInvalidException
{
if (id3Key == null)
{
throw new KeyNotFoundException();
}
return super.doCreateTagField(new FrameAndSubId(id3Key.getFrameId(),id3Key.getSubId()),value);
}
/**
* Retrieve the first value that exists for this id3v24key
*
* @param id3v24FieldKey
* @return
*/
public String getFirst(ID3v24FieldKey id3v24FieldKey) throws KeyNotFoundException
{
if (id3v24FieldKey == null)
{
throw new KeyNotFoundException();
}
return super.doGetFirst(new FrameAndSubId(id3v24FieldKey.getFrameId(),id3v24FieldKey.getSubId()));
}
/**
* Delete fields with this id3v24FieldKey
*
* @param id3v24FieldKey
*/
public void deleteTagField
(ID3v24FieldKey
id3v24FieldKey) throws KeyNotFoundException
{
if (id3v24FieldKey == null)
{
throw new KeyNotFoundException();
}
super.doDeleteTagField(new FrameAndSubId(id3v24FieldKey.getFrameId(),id3v24FieldKey.getSubId()));
}
protected FrameAndSubId getFrameAndSubIdFromGenericKey(TagFieldKey genericKey)
{
ID3v24FieldKey id3v24FieldKey = ID3v24Frames.getInstanceOf().getId3KeyFromGenericKey(genericKey);
if (id3v24FieldKey == null)
{
throw new KeyNotFoundException();
}
return new FrameAndSubId(id3v24FieldKey.getFrameId(),id3v24FieldKey.getSubId());
}
protected ID3Frames getID3Frames()
{
return ID3v24Frames.getInstanceOf();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -