📄 id3v22frame.java
字号:
/*
* MusicTag Copyright (C)2003,2004
*
* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library; if not,
* you can get a copy from http://www.opensource.org/licenses/lgpl-license.php or write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.hadeslee.audiotag.tag.id3;
import com.hadeslee.audiotag.audio.mp3.MP3File;
import com.hadeslee.audiotag.audio.generic.Utils;
import com.hadeslee.audiotag.tag.EmptyFrameException;
import com.hadeslee.audiotag.tag.InvalidFrameException;
import com.hadeslee.audiotag.tag.InvalidFrameIdentifierException;
import com.hadeslee.audiotag.tag.id3.framebody.AbstractID3v2FrameBody;
import com.hadeslee.audiotag.tag.id3.framebody.FrameBodyDeprecated;
import com.hadeslee.audiotag.tag.id3.framebody.FrameBodyUnsupported;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Represents an ID3v2.2 frame.
*
* @author : Paul Taylor
* @author : Eric Farng
* @version $Id: ID3v22Frame.java,v 1.27 2007/11/29 12:05:26 paultaylor Exp $
*/
public class ID3v22Frame extends AbstractID3v2Frame
{
Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{2}");
protected static final int FRAME_ID_SIZE = 3;
protected static final int FRAME_SIZE_SIZE = 3;
protected static final int FRAME_HEADER_SIZE = FRAME_ID_SIZE + FRAME_SIZE_SIZE;
public ID3v22Frame()
{
}
/**
* Creates a new ID3v22 Frame with given body
*
* @param body New body and frame is based on this
*/
public ID3v22Frame(AbstractID3v2FrameBody body)
{
super(body);
}
/**
* Creates a new ID3v22 Frame of type identifier.
*
* An empty body of the correct type will be automatically created. This constructor should be used when wish to
* create a new frame from scratch using user values
*/
public ID3v22Frame(String identifier)
{
logger.info("Creating empty frame of type" + identifier);
String bodyIdentifier = identifier;
this.identifier = identifier;
//If dealing with v22 identifier (Note this constructor is used by all three tag versions)
if(ID3Tags.isID3v22FrameIdentifier(bodyIdentifier))
{
//Does it have its own framebody (PIC,CRM) or are we using v23/v24 body (the normal case)
if(ID3Tags.forceFrameID22To23(bodyIdentifier)!=null)
{
//Do not convert
}
//TODO Improve messy fix for datetime
//TODO need to check in case v22 body does exist before using V23 body(e.g PIC)
else if ((bodyIdentifier.equals(ID3v22Frames.FRAME_ID_V2_TYER)) || (bodyIdentifier.equals(ID3v22Frames.FRAME_ID_V2_TIME)))
{
bodyIdentifier = ID3v24Frames.FRAME_ID_YEAR;
}
// Have to check for v22 because most don't have own body they use v23 or v24
// body to hold the data, the frame is identified by its identifier, the body identifier
// is just to create a body suitable for writing the data to
else if (ID3Tags.isID3v22FrameIdentifier(bodyIdentifier))
{
bodyIdentifier = (String) ID3Tags.convertFrameID22To23(bodyIdentifier);
}
}
// Use reflection to map id to frame body, which makes things much easier
// to keep things up to date.
try
{
Class c = Class.forName("com.hadeslee.audiotag.tag.id3.framebody.FrameBody" + bodyIdentifier);
frameBody = (AbstractID3v2FrameBody) c.newInstance();
}
catch (ClassNotFoundException cnfe)
{
logger.log(Level.SEVERE, cnfe.getMessage(), cnfe);
frameBody = new FrameBodyUnsupported(identifier);
}
//Instantiate Interface/Abstract should not happen
catch (InstantiationException ie)
{
logger.log(Level.SEVERE, ie.getMessage(), ie);
throw new RuntimeException(ie);
}
//Private Constructor shouild not happen
catch (IllegalAccessException iae)
{
logger.log(Level.SEVERE, iae.getMessage(), iae);
throw new RuntimeException(iae);
}
frameBody.setHeader(this);
logger.info("Created empty frame of type" + this.identifier + "with frame body of" + bodyIdentifier);
}
/**
* Copy Constructor
*
* Creates a new v22 frame based on another v22 frame
*/
public ID3v22Frame(ID3v22Frame frame)
{
super(frame);
logger.info("Creating frame from a frame of same version");
}
private void createV22FrameFromV23Frame(ID3v23Frame frame)throws InvalidFrameException
{
identifier = ID3Tags.convertFrameID23To22(frame.getIdentifier());
if (identifier != null)
{
logger.info("V2:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
this.frameBody = (AbstractID3v2FrameBody) ID3Tags.copyObject(frame.getBody());
return;
}
// Is it a known v3 frame which needs forcing to v2 frame e.g. APIC - PIC
else if (ID3Tags.isID3v23FrameIdentifier(frame.getIdentifier()) == true)
{
identifier = ID3Tags.forceFrameID23To22(frame.getIdentifier());
if (identifier != null)
{
logger.info("V2:Force:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
this.frameBody = this.readBody(identifier, (AbstractID3v2FrameBody) frame.getBody());
return;
}
// No mechanism exists to convert it to a v22 frame
else
{
throw new InvalidFrameException("Unable to convert v23 frame:" + frame.getIdentifier() + " to a v22 frame");
}
}
//Deprecated frame for v23
else if (frame.getBody() instanceof FrameBodyDeprecated)
{
//Was it valid for this tag version, if so try and reconstruct
if (ID3Tags.isID3v22FrameIdentifier(frame.getIdentifier()))
{
this.frameBody = ((FrameBodyDeprecated) frame.getBody());
identifier = frame.getIdentifier();
logger.info("DEPRECATED:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
}
//or was it still deprecated, if so leave as is
else
{
this.frameBody = new FrameBodyDeprecated((FrameBodyDeprecated) frame.getBody());
identifier = frame.getIdentifier();
logger.info("DEPRECATED:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
return;
}
}
// Unknown Frame e.g NCON
else
{
this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody());
identifier = frame.getIdentifier();
logger.info("v2:UNKNOWN:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
return;
}
}
/**
* Creates a new ID3v22 Frame from another frame of a different tag version
*
* @param frame to construct the new frame from
*/
public ID3v22Frame(AbstractID3v2Frame frame) throws InvalidFrameException
{
logger.info("Creating frame from a frame of a different version");
if ((frame instanceof ID3v22Frame == true) && (frame instanceof ID3v23Frame == false))
{
throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument");
}
// If it is a v24 frame is it possible to convert it into a v23 frame, anmd then convert from that
if (frame instanceof ID3v24Frame)
{
ID3v23Frame v23Frame = new ID3v23Frame(frame);
createV22FrameFromV23Frame(v23Frame);
}
//If it is a v23 frame is it possible to convert it into a v22 frame
else if (frame instanceof ID3v23Frame)
{
createV22FrameFromV23Frame((ID3v23Frame)frame);
}
this.frameBody.setHeader(this);
logger.info("Created frame from a frame of a different version");
}
/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -