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

📄 id3v23frame.java

📁 java+eclipse做的TTPlayer
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        //Read extra bits appended to frame header for various encodings
        //These are not included in header size but are included in frame size but wont be read when we actually
        //try to read the frame body data
        int extraHeaderBytesCount = 0;
        int decompressedFrameSize = -1;
        if(((EncodingFlags)encodingFlags).isCompression())
        {
            //Read the Decompressed Size
            decompressedFrameSize = byteBuffer.getInt();
            extraHeaderBytesCount = FRAME_COMPRESSION_UNCOMPRESSED_SIZE;
            logger.fine(getLoggingFilename()+":Decompressed frame size is:"+decompressedFrameSize);
        }

        if(((EncodingFlags)encodingFlags).isEncryption())
        {
            //Read the Encryption byte, but do nothing with it
            extraHeaderBytesCount += FRAME_ENCRYPTION_INDICATOR_SIZE;
            byteBuffer.get();
        }

        if(((EncodingFlags)encodingFlags).isGrouping())
        {
            //Read the Grouping byte, but do nothing with it
            extraHeaderBytesCount += FRAME_GROUPING_INDICATOR_SIZE;
            byteBuffer.get();
        }

        //Work out the real size of the framebody data
        int realFrameSize = frameSize - extraHeaderBytesCount;

        ByteBuffer frameBodyBuffer=null;

        //Uncompress the frame
        if(((EncodingFlags)encodingFlags).isCompression())
        {
            // Decompress the bytes into this buffer, size initialized from header field
            byte[] result = new byte[decompressedFrameSize];
            byte[] input = new byte[realFrameSize];

            //Store position ( just after frame header and any extra bits)
            //Read frame data into array, and then put buffer back to where it was
            int position = byteBuffer.position();
            byteBuffer.get(input,0,realFrameSize);
            byteBuffer.position(position);

            Inflater decompresser = new Inflater();
            decompresser.setInput(input);
            try
            {
                decompresser.inflate(result);
            }
            catch(DataFormatException dfe)
            {
                dfe.printStackTrace();
                //Update position of main buffer, so no attempt is made to reread these bytes
                byteBuffer.position(byteBuffer.position()+realFrameSize);
                throw new InvalidFrameException(getLoggingFilename()+"Unable to decompress this frame:"+identifier+":"+dfe.getMessage());
            }
            decompresser.end();
            frameBodyBuffer = ByteBuffer.wrap(result);
        }

        //Read the body data
        try
        {
            if(((EncodingFlags)encodingFlags).isCompression())
            {
               frameBody = readBody(id,frameBodyBuffer, decompressedFrameSize);
            }
            else
            {
                //Create Buffer that only contains the body of this frame rather than the remainder of tag
                frameBodyBuffer = byteBuffer.slice();
                frameBodyBuffer.limit(realFrameSize);
                frameBody = readBody(id,frameBodyBuffer, realFrameSize);
            }
            //TODO code seems to assume that if the frame created is not a v23FrameBody
            //it should be deprecated, but what about if somehow a V24Frame has been put into a V23 Tag, shouldnt
            //it then be created as FrameBodyUnsupported
            if(!(frameBody instanceof ID3v23FrameBody))
            {
                logger.info(getLoggingFilename()+":Converted frame body with:"+identifier+" to deprecated framebody");
                frameBody = new FrameBodyDeprecated((AbstractID3v2FrameBody)frameBody);
            }
        }
        finally
        {
            //Update position of main buffer, so no attempt is made to reread these bytes
            byteBuffer.position(byteBuffer.position()+realFrameSize);
        }
    }

    /**
     * Write the frame to bufferOutputStream
     *
     * @throws IOException
     */
    public void write(ByteArrayOutputStream tagBuffer)
    {
        logger.info("Writing frame to buffer:" + getIdentifier());
        //This is where we will write header, move position to where we can
        //write body
        ByteBuffer headerBuffer = ByteBuffer.allocate(FRAME_HEADER_SIZE);

        //Write Frame Body Data
        ByteArrayOutputStream bodyOutputStream = new ByteArrayOutputStream();
        ((AbstractID3v2FrameBody) frameBody).write(bodyOutputStream);
        //Write Frame Header write Frame ID
        if (getIdentifier().length() == 3)
        {
            identifier = identifier + ' ';
        }
        headerBuffer.put(Utils.getDefaultBytes(getIdentifier(),"ISO-8859-1"), 0, FRAME_ID_SIZE);
        //Write Frame Size
        int size = frameBody.getSize();
        logger.fine("Frame Size Is:" + size);
        headerBuffer.putInt(frameBody.getSize());

        //Write the Flags
        //Status Flags:leave as they were when we read
        headerBuffer.put(statusFlags.getWriteFlags());

        //Enclosing Flags, first reset
        encodingFlags.resetFlags();
        //Encoding we dont support any of flags so don't set any
        headerBuffer.put(encodingFlags.getFlags());

        try
        {
            //Add header to the Byte Array Output Stream
            tagBuffer.write(headerBuffer.array());

            //Add body to the Byte Array Output Stream
            tagBuffer.write(bodyOutputStream.toByteArray());
        }
        catch(IOException ioe)
        {
             //This could never happen coz not writing to file, so convert to RuntimeException
             throw new RuntimeException(ioe);
        }


    }

    protected AbstractID3v2Frame.StatusFlags getStatusFlags()
    {
        return statusFlags;
    }

    protected AbstractID3v2Frame.EncodingFlags getEncodingFlags()
    {
        return encodingFlags;
    }

    /**
     * This represents a frame headers Status Flags
     * Make adjustments if necessary based on frame type and specification.
     */
    class StatusFlags
        extends AbstractID3v2Frame.StatusFlags
    {
        public static final String TYPE_TAGALTERPRESERVATION = "typeTagAlterPreservation";
        public static final String TYPE_FILEALTERPRESERVATION = "typeFileAlterPreservation";
        public static final String TYPE_READONLY = "typeReadOnly";

        /**
         * Discard frame if tag altered
         */
        public static final int MASK_TAG_ALTER_PRESERVATION = FileConstants.BIT7;

        /**
         * Discard frame if audio file part  altered
         */
        public static final int MASK_FILE_ALTER_PRESERVATION = FileConstants.BIT6;

        /**
         * Frame tagged as read only
         */
        public static final int MASK_READ_ONLY = FileConstants.BIT5;

        public StatusFlags()
        {
            originalFlags = (byte) 0;
            writeFlags = (byte) 0;
        }

        StatusFlags(byte flags)
        {
            originalFlags = flags;
            writeFlags = flags;
            modifyFlags();
        }

        /**
         * Use this constructor when convert a v24 frame
         */
        StatusFlags(ID3v24Frame.StatusFlags statusFlags)
        {
            originalFlags = convertV4ToV3Flags(statusFlags.getOriginalFlags());
            writeFlags = originalFlags;
            modifyFlags();
        }

        private byte convertV4ToV3Flags(byte v4Flag)
        {
            byte v3Flag = (byte) 0;
            if ((v4Flag & ID3v24Frame.StatusFlags.MASK_FILE_ALTER_PRESERVATION) != 0)
            {
                v3Flag |= (byte) MASK_FILE_ALTER_PRESERVATION;
            }
            if ((v4Flag & ID3v24Frame.StatusFlags.MASK_TAG_ALTER_PRESERVATION) != 0)
            {
                v3Flag |= (byte) MASK_TAG_ALTER_PRESERVATION;
            }
            return v3Flag;
        }

        protected void modifyFlags()
        {
            String str = getIdentifier();
            if (ID3v23Frames.getInstanceOf().isDiscardIfFileAltered(str) == true)
            {
                writeFlags |= (byte) MASK_FILE_ALTER_PRESERVATION;
                writeFlags &= (byte) ~MASK_TAG_ALTER_PRESERVATION;
            }
            else
            {
                writeFlags &= (byte) ~MASK_FILE_ALTER_PRESERVATION;
                writeFlags &= (byte) ~MASK_TAG_ALTER_PRESERVATION;
            }
        }

        public void createStructure()
        {
            MP3File.getStructureFormatter().openHeadingElement(TYPE_FLAGS, "");
            MP3File.getStructureFormatter().addElement(TYPE_TAGALTERPRESERVATION, originalFlags & MASK_TAG_ALTER_PRESERVATION);
            MP3File.getStructureFormatter().addElement(TYPE_FILEALTERPRESERVATION, originalFlags & MASK_FILE_ALTER_PRESERVATION);
            MP3File.getStructureFormatter().addElement(TYPE_READONLY, originalFlags & MASK_READ_ONLY);
            MP3File.getStructureFormatter().closeHeadingElement(TYPE_FLAGS);
        }
    }

    /**
     * This represents a frame headers Encoding Flags
     */
    class EncodingFlags
        extends AbstractID3v2Frame.EncodingFlags
    {
        public static final String TYPE_COMPRESSION = "compression";
        public static final String TYPE_ENCRYPTION = "encryption";
        public static final String TYPE_GROUPIDENTITY = "groupidentity";

        /**
         * Frame is compressed
         */
        public static final int MASK_COMPRESSION = FileConstants.BIT7;

        /**
         * Frame is encrypted
         */
        public static final int MASK_ENCRYPTION = FileConstants.BIT6;

        /**
         * Frame is part of a group
         */
        public static final int MASK_GROUPING_IDENTITY = FileConstants.BIT5;

        public EncodingFlags()
        {
            super();
        }

        public EncodingFlags(byte flags)
        {
            super(flags);
            logEnabledFlags();
        }

        public void logEnabledFlags()
       {
           if (isCompression())
           {
               logger.warning(getLoggingFilename()+":"+identifier+" is compressed");
           }

           if (isEncryption())
           {
               logger.warning(getLoggingFilename()+":"+identifier+" is encrypted");
           }

           if (isGrouping())
           {
               logger.warning(getLoggingFilename()+":"+identifier+" is grouped");
           }
       }

        public boolean isCompression()
        {
            return (flags & MASK_COMPRESSION) >0;
        }

        public boolean isEncryption()
        {
            return (flags & MASK_ENCRYPTION) >0;
        }

        public boolean isGrouping()
        {
            return (flags & MASK_GROUPING_IDENTITY) >0;
        }



        public void createStructure()
        {
            MP3File.getStructureFormatter().openHeadingElement(TYPE_FLAGS, "");
            MP3File.getStructureFormatter().addElement(TYPE_COMPRESSION, flags & MASK_COMPRESSION);
            MP3File.getStructureFormatter().addElement(TYPE_ENCRYPTION, flags & MASK_ENCRYPTION);
            MP3File.getStructureFormatter().addElement(TYPE_GROUPIDENTITY, flags & MASK_GROUPING_IDENTITY);
            MP3File.getStructureFormatter().closeHeadingElement(TYPE_FLAGS);
        }
    }

    /**
     * Does the frame identifier meet the syntax for a idv3v2 frame identifier.
     * must start with a capital letter and only contain capital letters and numbers
     *
     * @param identifier to be checked
     * @return whether the identifier is valid
     */
    public boolean isValidID3v2FrameIdentifier(String identifier)
    {
        Matcher m = validFrameIdentifier.matcher(identifier);
        return m.matches();
    }

    /**
     * Return String Representation of body
     *
     */
    public void createStructure()
    {
        MP3File.getStructureFormatter().openHeadingElement(TYPE_FRAME, getIdentifier());
        MP3File.getStructureFormatter().addElement(TYPE_FRAME_SIZE, frameSize);
        statusFlags.createStructure();
        encodingFlags.createStructure();
        frameBody.createStructure();
        MP3File.getStructureFormatter().closeHeadingElement(TYPE_FRAME);
    }

      /**
     *
     * @return true if considered a common frame
     */
    public boolean isCommon()
    {
        return ID3v23Frames.getInstanceOf().isCommon(getId());
    }

     /**
     *
     * @return true if considered a common frame
     */
    public boolean isBinary()
    {
        return ID3v23Frames.getInstanceOf().isBinary(getId());
    }
}

⌨️ 快捷键说明

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