/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.frame.vorbis.type;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import com.ttProject.frame.vorbis.VorbisFrame;
import com.ttProject.nio.channels.IReadChannel;
import com.ttProject.unit.extra.BitLoader;
import com.ttProject.unit.extra.bit.Bit1;
import com.ttProject.unit.extra.bit.Bit32;
import com.ttProject.unit.extra.bit.Bit48;
import com.ttProject.unit.extra.bit.Bit8;
import com.ttProject.util.BufferUtil;
/**
* header frame for vorbis
* packetType: 1byte 0x03 comment header
* string: 6Byte "vorbis"
* venderLength: 4byte integer
* venderString: nbyte
* [repeat]
* iterateNum: 4byte integer
* length: 4byte integer
* string: nbyte (utf8?)
* [repeat end]
* framing flag 1bit(actually 1byte.)
*
* @see http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-620004.2.2
* @author taktod
*/
public class CommentHeaderFrame extends VorbisFrame {
/** logger */
@SuppressWarnings("unused")
private Logger logger = Logger.getLogger(CommentHeaderFrame.class);
private Bit8 packetType = new Bit8();
private Bit48 string = new Bit48();
private String venderName = null;
private Bit32 iterateNum = new Bit32();
private List<String> elementList = new ArrayList<String>();
private Bit1 lastFlag = new Bit1();
/**
* {@inheritDoc}
*/
@Override
public void minimumLoad(IReadChannel channel) throws Exception {
BitLoader loader = new BitLoader(channel);
loader.setLittleEndianFlg(true);
loader.load(packetType, string);
if(packetType.get() != 3) {
throw new Exception("unexpected packet type value.");
}
if(string.getLong() != 0x736962726F76L) {
throw new Exception("string value is unexpected.");
}
Bit32 size = new Bit32();
loader.load(size);
venderName = new String(BufferUtil.safeRead(channel, size.get()).array());
loader.load(iterateNum);
for(int i = 0;i < iterateNum.get();i ++) {
loader.load(size);
String data = new String(BufferUtil.safeRead(channel, size.get()).array());
elementList.add(data);
}
loader.load(lastFlag);
if(lastFlag.get() != 1) {
throw new Exception("end flag is unexpected.");
}
}
/**
* {@inheritDoc}
*/
@Override
public void load(IReadChannel channel) throws Exception {
super.update();
}
/**
* {@inheritDoc}
*/
@Override
protected void requestUpdate() throws Exception {
if(venderName == null) {
venderName = "myLib.vorbis.muxer";
}
int size = 1 + 6 + 4 + venderName.length() + 4 + 1;
for(String element : elementList) {
size += 4 + element.length();
}
ByteBuffer buffer = ByteBuffer.allocate(size);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put((byte)0x03);
buffer.put("vorbis".getBytes());
buffer.putInt(venderName.length());
buffer.put(venderName.getBytes());
buffer.putInt(elementList.size());
for(String element : elementList) {
buffer.putInt(element.length());
buffer.put(element.getBytes());
}
buffer.put((byte)0x01);
buffer.flip();
setSize(buffer.remaining());
setData(buffer);
}
/**
* {@inheritDoc}
*/
@Override
public ByteBuffer getPackBuffer() throws Exception {
return getData();
}
@Override
public int getSize() {
try {
getData();
} catch (Exception e) {
e.printStackTrace();
}
return super.getSize();
}
/**
* ref the minimum size buffer.
* @return
*/
public ByteBuffer getMinimumBuffer() {
ByteBuffer buffer = ByteBuffer.allocate(35);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.put((byte)0x03);
buffer.put("vorbis".getBytes());
String name = "myLib.vorbis.muxer";
buffer.putInt(name.length());
buffer.put(name.getBytes());
buffer.putInt(0);
buffer.put((byte)1);
buffer.flip();
return buffer;
}
}