⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 id3v23frame.java

📁 YOYOPlayer MP3播放器 java+JMF实现
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *  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.FileConstants;
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 com.hadeslee.audiotag.tag.id3.framebody.ID3v23FrameBody;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;

/**
 * Represents an ID3v2.3 frame.
 * 
 * @author : Paul Taylor
 * @author : Eric Farng
 * @version $Id: ID3v23Frame.java,v 1.34 2007/11/29 12:05:26 paultaylor Exp $
 */
public class ID3v23Frame extends AbstractID3v2Frame
{
    Pattern validFrameIdentifier = Pattern.compile("[A-Z][0-9A-Z]{3}");

    protected static final int FRAME_ID_SIZE = 4;
    protected static final int FRAME_FLAGS_SIZE = 2;
    protected static final int FRAME_SIZE_SIZE = 4;
    protected static final int FRAME_COMPRESSION_UNCOMPRESSED_SIZE =4;
    protected static final int FRAME_ENCRYPTION_INDICATOR_SIZE =1;
    protected static final int FRAME_GROUPING_INDICATOR_SIZE =1;

    protected static final int FRAME_HEADER_SIZE = FRAME_ID_SIZE + FRAME_SIZE_SIZE + FRAME_FLAGS_SIZE;

    /**
     * Creates a new ID3v23 Frame
     */
    public ID3v23Frame()
    {
    }

    /**
     * Creates a new ID3v23 Frame of type identifier.
     *
     * <p>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 data.
     */
    public ID3v23Frame(String identifier)
    {
        super(identifier);
        statusFlags = new StatusFlags();
        encodingFlags = new EncodingFlags();
    }

    /**
     * Copy Constructor
     *
     * Creates a new v23 frame  based on another v23 frame
     */
    public ID3v23Frame(ID3v23Frame frame)
    {
        super(frame);
        statusFlags = new StatusFlags(frame.getStatusFlags().getOriginalFlags());
        encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags());
    }

    /**
     * Creates a new ID3v23Frame  based on another frame.
     *
     * @param frame
     */
    public ID3v23Frame(AbstractID3v2Frame frame) throws InvalidFrameException
    {
        logger.info("Creating frame from a frame of a different version");
        if ((frame instanceof ID3v23Frame == true) && (frame instanceof ID3v24Frame == false))
        {
            throw new UnsupportedOperationException("Copy Constructor not called. Please type cast the argument");
        }
        if (frame instanceof ID3v24Frame)
        {
            statusFlags = new StatusFlags((ID3v24Frame.StatusFlags) frame.getStatusFlags());
            encodingFlags = new EncodingFlags(frame.getEncodingFlags().getFlags());
        }

        if (frame instanceof ID3v24Frame)
        {
            if(ID3Tags.isID3v24FrameIdentifier(frame.getIdentifier()))
            {
                //Version between v4 and v3
                identifier = ID3Tags.convertFrameID24To23(frame.getIdentifier());
                if (identifier != null)
                {
                    logger.info("V4:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
                    this.frameBody = (AbstractID3v2FrameBody) ID3Tags.copyObject(frame.getBody());
                    this.frameBody.setHeader(this);
                    return;
                }
                else
                {
                    //Is it a known v4 frame which needs forcing to v3 frame e.g. TDRC - TYER,TDAT
                    identifier = ID3Tags.forceFrameID24To23(frame.getIdentifier());
                    if(identifier!=null)
                    {
                        logger.info("V4:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
                        this.frameBody = this.readBody(identifier, (AbstractID3v2FrameBody) frame.getBody());
                        this.frameBody.setHeader(this);
                        return;
                    }
                    //It is a v24 frame that is not known and cannot be forced in v23 e.g TDRL,in which case
                    //we convert to a framebody unsupported by writing contents as a byte array and feeding
                    //it into FrameBodyUnsupported
                    else
                    {
                        ByteArrayOutputStream baos = new  ByteArrayOutputStream();
                        ((AbstractID3v2FrameBody)frame.getBody()).write(baos);

                        identifier = frame.getIdentifier();
                        this.frameBody = new FrameBodyUnsupported(identifier,baos.toByteArray());
                        this.frameBody.setHeader(this);
                        logger.info("V4:Orig id is:" + frame.getIdentifier() + ":New Id Unsupported is:" + identifier);
                        return;
                    }
                }
            }
            //Unknown Frame e.g NCON
            else if(frame.getBody() instanceof FrameBodyUnsupported)
            {
                this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody());
                this.frameBody.setHeader(this);
                identifier = frame.getIdentifier();
                logger.info("UNKNOWN:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
                return;
            }
            // Deprecated frame for v24
            else if(frame.getBody() instanceof FrameBodyDeprecated)
            {
                //Was it valid for this tag version, if so try and reconstruct
                if(ID3Tags.isID3v23FrameIdentifier(frame.getIdentifier()))
                {
                      this.frameBody = ((FrameBodyDeprecated)frame.getBody()).getOriginalFrameBody();
                      this.frameBody.setHeader(this);
                      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());
                    this.frameBody.setHeader(this);
                    identifier = frame.getIdentifier();
                    logger.info("DEPRECATED:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
                    return;
                }
            }
            // Unable to find a suitable framebody, this shold not happen
            else
            {
                logger.severe("Orig id is:" + frame.getIdentifier() + "Unable to create Frame Body");
                throw new InvalidFrameException("Orig id is:" + frame.getIdentifier() + "Unable to create Frame Body");
            }
        }
        else if (frame instanceof ID3v22Frame)
        {
            if(ID3Tags.isID3v22FrameIdentifier(frame.getIdentifier()))
            {
                identifier = ID3Tags.convertFrameID22To23(frame.getIdentifier());
                if (identifier != null)
                {
                    logger.info("V3:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
                    this.frameBody = (AbstractID3v2FrameBody) ID3Tags.copyObject(frame.getBody());
                    this.frameBody.setHeader(this);
                    return;
                }
                //Is it a known v2 frame which needs forcing to v4 frame e.g PIC - APIC
                else if (ID3Tags.isID3v22FrameIdentifier(frame.getIdentifier()) == true)
                {
                    //Force v2 to v3
                    identifier = ID3Tags.forceFrameID22To23(frame.getIdentifier());
                    if(identifier!=null)
                    {
                        logger.info("V22Orig id is:" + frame.getIdentifier() + "New id is:" + identifier);
                        this.frameBody = this.readBody(identifier, (AbstractID3v2FrameBody) frame.getBody());
                        this.frameBody.setHeader(this);
                        return;
                    }
                    //No mechanism exists to convert it to a v23 frame
                    else
                    {
                        this.frameBody = new FrameBodyDeprecated((AbstractID3v2FrameBody)frame.getBody());
                        this.frameBody.setHeader(this);
                        identifier = frame.getIdentifier();
                        logger.info("Deprecated:V22:orig id id is:" + frame.getIdentifier() + ":New id is:" + identifier);
                        return;
                    }
                }
            }
            // Unknown Frame e.g NCON
            else
            {
                this.frameBody = new FrameBodyUnsupported((FrameBodyUnsupported) frame.getBody());
                this.frameBody.setHeader(this);
                identifier = frame.getIdentifier();
                logger.info("UNKNOWN:Orig id is:" + frame.getIdentifier() + ":New id is:" + identifier);
                return;
            }
        }

        logger.warning("Frame is unknown version");
    }

    /**
     * Creates a new ID3v23Frame datatype by reading from byteBuffer.
     *
     * @param byteBuffer to read from
     */
    public ID3v23Frame(ByteBuffer byteBuffer,String loggingFilename)
        throws InvalidFrameException
    {
       setLoggingFilename(loggingFilename);
       read(byteBuffer);
    }

    /**
     * Creates a new ID3v23Frame datatype by reading from byteBuffer.
     *
     * @param byteBuffer to read from
     *
     * @deprecated use {@link #ID3v23Frame(ByteBuffer,String)} instead
     */
    public ID3v23Frame(ByteBuffer byteBuffer)
        throws InvalidFrameException
    {
       this(byteBuffer,"");
    }

    /**
     * Return size of frame
     *
     * @return int frame size
     */
    public int getSize()
    {
        return frameBody.getSize() + ID3v23Frame.FRAME_HEADER_SIZE;
    }

    /**
     * Compare for equality
     * To be deemed equal obj must be a IDv23Frame with the same identifier
     * and the same flags.
     * containing the same body,datatype list ectera.
     * equals() method is made up from all the various components
     *
     * @param obj
     * @return if true if this object is equivalent to obj
     */
    public boolean equals(Object obj)
    {
        if ((obj instanceof ID3v23Frame) == false)
        {
            return false;
        }
        ID3v23Frame object = (ID3v23Frame) obj;
        if (this.statusFlags.getOriginalFlags() != object.statusFlags.getOriginalFlags())
        {
            return false;
        }
        if (this.encodingFlags.getFlags() != object.encodingFlags.getFlags())
        {
            return false;
        }
        return super.equals(obj);
    }

    /**
     * Read the frame from a bytebuffer
     *
     * @param byteBuffer buffer to read from
     */
    public void read(ByteBuffer byteBuffer)
        throws InvalidFrameException
    {
        logger.info(getLoggingFilename()+":Read Frame from byteBuffer");

        if(byteBuffer.position()+ FRAME_HEADER_SIZE >= byteBuffer.limit())
        {
            logger.warning(getLoggingFilename()+":No space to find another frame:");
            throw new InvalidFrameException(getLoggingFilename()+":No space to find another frame");
        }

        byte[] buffer = new byte[FRAME_ID_SIZE];

        // Read the Frame Identifier
        byteBuffer.get(buffer, 0, FRAME_ID_SIZE);
        identifier = new String(buffer);

        // Is this a valid identifier?
        if (isValidID3v2FrameIdentifier(identifier) == false)
        {
            logger.info(getLoggingFilename()+":Invalid identifier:" + identifier);
            byteBuffer.position(byteBuffer.position() - (FRAME_ID_SIZE - 1));
            throw new InvalidFrameIdentifierException(getLoggingFilename()+":"+identifier + "is not a valid ID3v2.30 frame");
        }
        //Read the size field (as Big Endian Int - byte buffers always initlised to Big endian order)
        frameSize = byteBuffer.getInt();
        if (frameSize < 0)
        {
            logger.warning(getLoggingFilename()+":Invalid Frame Size:" + identifier);
            throw new InvalidFrameException(identifier + " is invalid frame");
        }
        else if (frameSize == 0)
        {
            logger.warning(getLoggingFilename()+":Empty Frame Size:" + identifier);
            throw new EmptyFrameException(identifier + " is empty frame");
        }
        else if (frameSize > byteBuffer.remaining())
        {
            logger.warning(getLoggingFilename()+":Invalid Frame size larger than size before mp3 audio:" + identifier);
            throw new InvalidFrameException(identifier + " is invalid frame");
        }
        
       
        //Read the flag bytes
        statusFlags = new StatusFlags(byteBuffer.get());
        encodingFlags = new EncodingFlags(byteBuffer.get());
        String id;

        //If this identifier is a valid v24 identifier or easily converted to v24
        id = (String) ID3Tags.convertFrameID23To24(identifier);

        // Cant easily be converted to v23 but is it a valid v24 identifier
        if (id == null)
        {
            // It is a valid v23 identifier so should be able to find a
            //  frame body for it.
            if (ID3Tags.isID3v23FrameIdentifier(identifier) == true)
            {
                id = identifier;
            }
            // Unknown so will be created as FrameBodyUnsupported
            else
            {
                id = UNSUPPORTED_ID;
            }
        }
        logger.fine(getLoggingFilename()+":Identifier was:" + identifier + " reading using:" + id + "with frame size:"+frameSize);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -