/*
* myLib - https://github.com/taktod/myLib
* Copyright (c) 2014 ttProject. All rights reserved.
*
* Licensed under The MIT license.
*/
package com.ttProject.frame.speex.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.speex.SpeexFrame;
import com.ttProject.nio.channels.ByteReadChannel;
import com.ttProject.nio.channels.IReadChannel;
import com.ttProject.util.BufferUtil;
/**
* comment Frame for speex.
* kind of metadata.
*
* 4byte int venderLength
* nbyte string venderName
* 4byte int elementNum
* 4byte elementLength
* nbyte elementString
* repeat as much as element has.
* @author taktod
* TODO こちらの動作ですが、解析途上の場合は、フラグで確認できるようにして、再度loadし直したら続きから処理できるようにしたいところ。
*/
public class CommentFrame extends SpeexFrame {
/** logger */
@SuppressWarnings("unused")
private Logger logger = Logger.getLogger(CommentFrame.class);
/** venderName */
private String venderName = null;
/** element size */
private Integer elementSize = null;
/** element list */
private List<String> elementList = new ArrayList<String>();
/** working buffer */
private ByteBuffer tmpBuffer = null;
/**
* constructor
*/
public CommentFrame() {
super.update();
}
/**
* {@inheritDoc}
*/
@Override
public void minimumLoad(IReadChannel channel) throws Exception {
super.update();
}
/**
* {@inheritDoc}
*/
@Override
public void load(IReadChannel channel) throws Exception {
IReadChannel targetChannel = null;
if(tmpBuffer != null) {
tmpBuffer = BufferUtil.connect(
tmpBuffer, BufferUtil.safeRead(channel, channel.size() - channel.position())
);
targetChannel = new ByteReadChannel(tmpBuffer);
tmpBuffer = null;
}
else {
targetChannel = channel;
}
if(venderName == null) {
venderName = readString(targetChannel);
if(venderName == null) {
return;
}
}
if(elementSize == null) {
Integer size = readInt(targetChannel);
if(size == null) {
return;
}
elementSize = size;
}
for(int i = 0;i < elementSize;i ++) {
String element = readString(targetChannel);
if(element == null) {
return;
}
elementList.add(element);
}
super.update();
}
/**
* try to read data.
* @param channel
* @return if need more data, return null.
*/
private String readString(IReadChannel channel) throws Exception {
Integer length = readInt(channel);
if(length == null) {
return null;
}
if(channel.size() - channel.position() < length) {
tmpBuffer = ByteBuffer.allocate(channel.size() - channel.position() + 4);
tmpBuffer.order(ByteOrder.LITTLE_ENDIAN);
tmpBuffer.putInt(length);
tmpBuffer.put(BufferUtil.safeRead(channel, channel.size() - channel.position()));
tmpBuffer.flip();
return null;
}
return new String(BufferUtil.safeRead(channel, length).array());
}
/**
* try to read int.
* @param channel
* @return if need more data, return null.
*/
private Integer readInt(IReadChannel channel) throws Exception {
if(channel.size() - channel.position() < 4) {
tmpBuffer = BufferUtil.safeRead(channel, channel.size() - channel.position());
return null;
}
ByteBuffer buffer = BufferUtil.safeRead(channel, 4);
buffer.order(ByteOrder.LITTLE_ENDIAN);
return buffer.getInt();
}
@Override
public int getSize() {
try {
getData();
}
catch(Exception e) {
}
return super.getSize();
}
/**
* {@inheritDoc}
*/
@Override
protected void requestUpdate() throws Exception {
if(venderName == null) {
venderName = "myLib.speex.muxer";
}
// venderLength
// venderData
// elementListSize
// elementDataLength
// elementData
// ...
int size = 4 + venderName.length() + 4;
for(String element : elementList) {
size += 4 + element.length();
}
ByteBuffer buffer = ByteBuffer.allocate(size);
buffer.order(ByteOrder.LITTLE_ENDIAN);
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.flip();
setSize(buffer.remaining());
setData(buffer);
}
/**
* {@inheritDoc}
*/
@Override
public ByteBuffer getPackBuffer() {
return null;
}
public void setVenderName(String name) {
this.venderName = name;
super.update();
}
public void addElement(String data) {
elementList.add(data);
super.update();
}
public void removeElement(String data) {
elementList.remove(data);
super.update();
}
/**
* check the data is complete.
*/
public boolean isComplete() {
return venderName != null && elementSize != null && elementSize == elementList.size();
}
}