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

📄 id3v23tag.java

📁 java+eclipse做的TTPlayer
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
            logger.warning(getLoggingFilename()+":"+"ID3v23 Tag is extended");
        }

        if(experimental)
        {
            logger.warning(getLoggingFilename()+":"+"ID3v23 Tag is experimental");
        }

        // Read the size, this is size of tag not including  the tag header
        size = ID3SyncSafeInteger.bufferToValue(buffer);
        logger.info(getLoggingFilename()+":Tag size is:"+size+" according to header (does not include header size, add 10)");

        //Extended Header
        if (extended == true)
        {
            // Int is 4 bytes.
            int extendedHeaderSize = buffer.getInt();
            // Extended header without CRC Data
            if (extendedHeaderSize == TAG_EXT_HEADER_DATA_LENGTH)
            {
                //Flag
                byte extFlag = buffer.get();
                crcDataFlag = (extFlag & MASK_V23_CRC_DATA_PRESENT) != 0;
                if (crcDataFlag == true)
                {
                    throw new InvalidTagException(getLoggingFilename()+":CRC Data flag not set correctly.");
                }
                //Flag Byte (not used)
                buffer.get();
                //Take padding and ext header size off size to be read
                size = size - (buffer.getInt() + TAG_EXT_HEADER_LENGTH);
            }
            else if (extendedHeaderSize == TAG_EXT_HEADER_DATA_LENGTH + TAG_EXT_HEADER_CRC_LENGTH)
            {
                //Flag
                byte extFlag = buffer.get();
                crcDataFlag = (extFlag & MASK_V23_CRC_DATA_PRESENT) != 0;
                if (crcDataFlag == false)
                {
                    throw new InvalidTagException(getLoggingFilename()+":CRC Data flag not set correctly.");
                }
                //Flag Byte (not used)
                buffer.get();
                //Take padding size of size to be read
                size = size - (buffer.getInt() + TAG_EXT_HEADER_LENGTH + TAG_EXT_HEADER_CRC_LENGTH);
                //CRC Data
                crcData = buffer.getInt();
            }
            else
            {
                throw new InvalidTagException("Invalid Extended Header Size.");
            }
            logger.info(getLoggingFilename()+":has Extended Header so adjusted Tag size is:"+size);

        }

        //Slice Buffer, so position markers tally with size (i.e do not include tagheader)
        ByteBuffer bufferWithoutHeader = buffer.slice();
        //We need to synchronize the buffer
        if(isUnsynchronization() ==true)
        {
             bufferWithoutHeader=ID3Unsynchronization.synchronize(bufferWithoutHeader);
        }

        readFrames(bufferWithoutHeader,size);
        logger.info(getLoggingFilename()+":Loaded Frames,there are:" + frameMap.keySet().size());

    }

    /**
     * Read the frames
     *
     * Read from byteBuffer upto size
     *
     * @param byteBuffer
     * @param size
     */
    protected void readFrames(ByteBuffer byteBuffer, int size)
    {
        //Now start looking for frames
        ID3v23Frame next;
        frameMap = new LinkedHashMap();

        //Read the size from the Tag Header
        this.fileReadSize = size;
        logger.finest(getLoggingFilename()+":Start of frame body at:" + byteBuffer.position() + ",frames data size is:" + size);

        // Read the frames until got to upto the size as specified in header or until
        // we hit an invalid frame identifier
        while (byteBuffer.position()<size)
        {
            String id;
            try
            {
                //Read Frame
                logger.finest(getLoggingFilename()+":Looking for next frame at:" + byteBuffer.position());
                next = new ID3v23Frame(byteBuffer,getLoggingFilename());
                id = next.getIdentifier();
                loadFrameIntoMap(id, next);
            }
            //Found Empty Frame
            catch (EmptyFrameException ex)
            {
                logger.warning(getLoggingFilename()+":Empty Frame:"+ex.getMessage());
                this.emptyFrameBytes += ID3v23Frame.FRAME_HEADER_SIZE;
            }
            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, often just occurs because frameheader includes padding
            //and we have reached padding
            catch (InvalidFrameException ife)
            {
                logger.warning(getLoggingFilename()+":Invalid Frame:"+ife.getMessage());
                this.invalidFrameBytes++;
                //Dont try and find any more frames
                break;
            }
            ;
        }
    }

    /**
     * Write the ID3 header to the ByteBuffer.
     *
     *  TODO Calculate the CYC Data Check
     *  TODO Reintroduce Extended Header
     *
     * @param padding is the size of the padding portion of the tag
     * @param size is the size of the body data
     *
     * @return ByteBuffer
     * @throws IOException
     */
    private ByteBuffer writeHeaderToBuffer(int padding,int size) throws IOException
    {
        // 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;
        crcDataFlag  = false;

        // Create Header Buffer,allocate maximum possible size for the header
        ByteBuffer headerBuffer = ByteBuffer.
            allocate(TAG_HEADER_LENGTH + TAG_EXT_HEADER_LENGTH + TAG_EXT_HEADER_CRC_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_V23_UNSYNCHRONIZATION;
        }
        if (extended == true)
        {
            flagsByte |= MASK_V23_EXTENDED_HEADER;
        }
        if (experimental == true)
        {
            flagsByte |= MASK_V23_EXPERIMENTAL;
        }
        headerBuffer.put(flagsByte);

        //Additional Header Size,(for completeness we never actually write the extended header)
        int additionalHeaderSize =0;
        if (extended)
        {
            additionalHeaderSize += this.TAG_EXT_HEADER_LENGTH;
            if (crcDataFlag)
            {
                additionalHeaderSize += this.TAG_EXT_HEADER_CRC_LENGTH;
            }
        }

        //Size As Recorded in Header, don't include the main header length
        headerBuffer.put(ID3SyncSafeInteger.valueToBuffer(padding + size + additionalHeaderSize));
        
        //Write Extended Header
        if (extended == true)
        {
            byte extFlagsByte1 = 0;
            byte extFlagsByte2 = 0;

            //Contains CRCData
            if (crcDataFlag == true)
            {
                headerBuffer.putInt(TAG_EXT_HEADER_DATA_LENGTH + TAG_EXT_HEADER_CRC_LENGTH);
                extFlagsByte1 |= MASK_V23_CRC_DATA_PRESENT;
                headerBuffer.put(extFlagsByte1);
                headerBuffer.put(extFlagsByte2);
                headerBuffer.putInt(paddingSize);
                headerBuffer.putInt(crcData);
            }
            //Just extended Header
            else
            {
                headerBuffer.putInt(TAG_EXT_HEADER_DATA_LENGTH);
                headerBuffer.put(extFlagsByte1);
                headerBuffer.put(extFlagsByte2);
                //Newly Calculated Padding As Recorded in Extended Header
                headerBuffer.putInt(padding);
            }
        }

        headerBuffer.flip();
        return headerBuffer;
    }


    /**
     * Write tag to file
     *
     * TODO:we currently never write the Extended header , but if we did the size calculation in this
     * method would be slightly incorrect
     *
     * @param file The file to write to
     * @throws IOException 
     */
    public void write(File file, long audioStartLocation)
        throws IOException
    {
        logger.info(getLoggingFilename()+":Writing tag to file");

        //Write Body Buffer
        byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray();
        logger.info(getLoggingFilename()+":bodybytebuffer:sizebeforeunsynchronisation:"+bodyByteBuffer.length);

        // Unsynchronize if option enabled and unsync required
        if(TagOptionSingleton.getInstance().isUnsyncTags())
        {
            unsynchronization = ID3Unsynchronization.requiresUnsynchronization(bodyByteBuffer);
        }
        else
        {
            unsynchronization=false;
        }
        if(isUnsynchronization())
        {
            bodyByteBuffer=ID3Unsynchronization.unsynchronize(bodyByteBuffer);
            logger.info(getLoggingFilename()+":bodybytebuffer:sizeafterunsynchronisation:"+bodyByteBuffer.length);
        }

        int sizeIncPadding = calculateTagSize(bodyByteBuffer.length + TAG_HEADER_LENGTH, (int) audioStartLocation);
        int padding = sizeIncPadding - (bodyByteBuffer.length + TAG_HEADER_LENGTH) ;
        logger.info(getLoggingFilename()+":Current audiostart:"+audioStartLocation);
        logger.info(getLoggingFilename()+":Size including padding:"+sizeIncPadding);
        logger.info(getLoggingFilename()+":Padding:"+padding);

        ByteBuffer headerBuffer = writeHeaderToBuffer(padding,bodyByteBuffer.length);

        //We need to adjust location of audio File
        if (sizeIncPadding > audioStartLocation)
        {
            logger.info(getLoggingFilename()+":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(getLoggingFilename()+":Writing tag to channel");
  
        byte[] bodyByteBuffer = writeFramesToBuffer().toByteArray();
        logger.info(getLoggingFilename()+":bodybytebuffer:sizebeforeunsynchronisation:"+bodyByteBuffer.length);

        // Unsynchronize if option enabled and unsync required
        if(TagOptionSingleton.getInstance().isUnsyncTags())
        {
            unsynchronization = ID3Unsynchronization.requiresUnsynchronization(bodyByteBuffer);
        }
        else
        {
            unsynchronization=false;
        }
        if(isUnsynchronization())
        {
            bodyByteBuffer=ID3Unsynchronization.unsynchronize(bodyByteBuffer);
            logger.info(getLoggingFilename()+":bodybytebuffer:sizeafterunsynchronisation:"+bodyByteBuffer.length);
        }
        ByteBuffer headerBuffer = writeHeaderToBuffer(0,bodyByteBuffer.length);
    
        channel.write(headerBuffer);
        channel.write(ByteBuffer.wrap(bodyByteBuffer));
    }

    /**
     * For representing the MP3File in an XML Format
     *
     */
    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_EXTENDED, this.extended);
        MP3File.getStructureFormatter().addElement(TYPE_EXPERIMENTAL, this.experimental);
        MP3File.getStructureFormatter().addElement(TYPE_CRCDATA, this.crcData);
        MP3File.getStructureFormatter().addElement(TYPE_PADDINGSIZE, this.paddingSize);
        MP3File.getStructureFormatter().closeHeadingElement(TYPE_HEADER);
        //Body
        super.createStructureBody();
        MP3File.getStructureFormatter().closeHeadingElement(TYPE_TAG);
    }

    /**
    *
    * @return is tag unsynchronized
    */
    public boolean isUnsynchronization()
    {
       return unsynchronization;
    }

    protected String getArtistId()
    {
        return ID3v23Frames.FRAME_ID_V3_ARTIST;
    }

     protected String getAlbumId()
    {
        return ID3v23Frames.FRAME_ID_V3_ALBUM;
    }

    protected String getTitleId()
    {
        return ID3v23Frames.FRAME_ID_V3_TITLE;
    }

    protected String getTrackId()
    {
        return ID3v23Frames.FRAME_ID_V3_TRACK;
    }

    protected String getYearId()
    {
       return ID3v23Frames.FRAME_ID_V3_TYER;
    }

    protected String getCommentId()
    {
        return ID3v23Frames.FRAME_ID_V3_COMMENT;
    }

    protected String getGenreId()
    {
        return ID3v23Frames.FRAME_ID_V3_GENRE;
    }

    public ID3v23Frame createFrame(String id)
   {
        return new ID3v23Frame(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(ID3v23FieldKey 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 id3v23key
     *
     * @param id3v23FieldKey
     * @return
     */
    public String getFirst(ID3v23FieldKey id3v23FieldKey) throws KeyNotFoundException
    {
        if (id3v23FieldKey == null)
        {
            throw new KeyNotFoundException();
        }
        return super.doGetFirst(new FrameAndSubId(id3v23FieldKey.getFrameId(),id3v23FieldKey.getSubId()));
    }

    /**
     * Delete fields with this id3v23FieldKey
     *
     * @param id3v23FieldKey
     */
    public void deleteTagField
            (ID3v23FieldKey
                    id3v23FieldKey) throws KeyNotFoundException
    {
        if (id3v23FieldKey == null)
        {
            throw new KeyNotFoundException();
        }
        super.doDeleteTagField(new FrameAndSubId(id3v23FieldKey.getFrameId(),id3v23FieldKey.getSubId()));
    }


    protected FrameAndSubId getFrameAndSubIdFromGenericKey(TagFieldKey genericKey)
    {
        ID3v23FieldKey id3v23FieldKey = ID3v23Frames.getInstanceOf().getId3KeyFromGenericKey(genericKey);
        if (id3v23FieldKey == null)
        {
            throw new KeyNotFoundException();
        }
        return new FrameAndSubId(id3v23FieldKey.getFrameId(),id3v23FieldKey.getSubId());
    }

     protected ID3Frames getID3Frames()
    {
        return ID3v23Frames.getInstanceOf();
    }
}

⌨️ 快捷键说明

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