FileDocCategorySizeDatePackage
MetadataBlockHeader.javaAPI DocJaudiotagger 2.0.44408Fri Oct 28 12:41:04 BST 2011org.jaudiotagger.audio.flac.metadatablock

MetadataBlockHeader.java

/*
 * Entagged Audio Tag library
 * Copyright (c) 2003-2005 Raphaƫl Slinckx <raphael@slinckx.net>
 * 
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package org.jaudiotagger.audio.flac.metadatablock;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;

/**
 * Metadata Block Header
 */
public class MetadataBlockHeader
{
    public static final int BLOCK_TYPE_LENGTH   = 1;
    public static final int BLOCK_LENGTH        = 3;
    public static final int HEADER_LENGTH       = BLOCK_TYPE_LENGTH + BLOCK_LENGTH;

    private boolean isLastBlock;
    private int dataLength;
    private byte[] bytes;
    private BlockType blockType;

    /**
     * Create header by reading from file
     *
     * @param raf
     * @return
     * @throws IOException
     */
    public static MetadataBlockHeader readHeader(RandomAccessFile raf) throws IOException
    {
        ByteBuffer rawdata = ByteBuffer.allocate(HEADER_LENGTH);
        int bytesRead = raf.getChannel().read(rawdata);
        if (bytesRead < HEADER_LENGTH)
        {
            throw new IOException("Unable to read required number of databytes read:" + bytesRead + ":required:" + HEADER_LENGTH);
        }
        rawdata.rewind();
        return new MetadataBlockHeader(rawdata);
    }

    public String toString()
    {
        return "BlockType:"+blockType + " DataLength:"+dataLength + " isLastBlock:"+isLastBlock;
    }

    /**
     * Construct header by reading bytes
     *
     * @param rawdata
     */
    public MetadataBlockHeader(ByteBuffer rawdata)
    {
        isLastBlock = ((rawdata.get(0) & 0x80) >>> 7) == 1;

        int type = rawdata.get(0) & 0x7F;
        if (type < BlockType.values().length)
        {
            blockType = BlockType.values()[type];
        }


        dataLength = (u(rawdata.get(1)) << 16) + (u(rawdata.get(2)) << 8) + (u(rawdata.get(3)));

        bytes = new byte[HEADER_LENGTH];
        for (int i = 0; i < HEADER_LENGTH; i++)
        {
            bytes[i] = rawdata.get(i);
        }
        }

    /**
     * Construct a new header in order to write metadatablock to file
     *
     * @param isLastBlock
     * @param blockType
     * @param dataLength
     */
    public MetadataBlockHeader(boolean isLastBlock, BlockType blockType, int dataLength)
    {
        ByteBuffer rawdata = ByteBuffer.allocate(HEADER_LENGTH);
        this.blockType = blockType;
        this.isLastBlock = isLastBlock;
        this.dataLength = dataLength;

        byte type;
        if (isLastBlock)
        {
            type = (byte) (0x80 | blockType.getId());
        }
        else
        {
            type = (byte) blockType.getId();
        }
        rawdata.put(type);

        //Size is 3Byte BigEndian int
        rawdata.put((byte) ((dataLength & 0xFF0000) >>> 16));
        rawdata.put((byte) ((dataLength & 0xFF00) >>> 8));
        rawdata.put((byte) (dataLength & 0xFF));

        bytes = new byte[HEADER_LENGTH];
        for (int i = 0; i < HEADER_LENGTH; i++)
        {
            bytes[i] = rawdata.get(i);
        }
    }

    private int u(int i)
    {
        return i & 0xFF;
    }

    public int getDataLength()
    {
        return dataLength;
    }

    public BlockType getBlockType()
    {
        return blockType;
    }

    public boolean isLastBlock()
    {
        return isLastBlock;
    }

    public byte[] getBytesWithoutIsLastBlockFlag()
    {
        bytes[0] = (byte) (bytes[0] & 0x7F);
        return bytes;
    }

    public byte[] getBytes()
    {
        return bytes;
    }
}