/*
* Flazr <http://flazr.com> Copyright (C) 2009 Peter Thomas.
*
* This file is part of Flazr.
*
* Flazr 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 3 of the License, or
* (at your option) any later version.
*
* Flazr 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 Flazr. If not, see <http://www.gnu.org/licenses/>.
*/
package com.flazr.rtmp.message;
import com.flazr.rtmp.RtmpHeader;
import com.flazr.util.ValueToEnum;
import com.flazr.util.Utils;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Control extends AbstractMessage {
@SuppressWarnings("unused")
private static final Logger logger = LoggerFactory.getLogger(Control.class);
public static enum Type implements ValueToEnum.IntValue {
STREAM_BEGIN(0),
STREAM_EOF(1),
STREAM_DRY(2),
SET_BUFFER(3),
STREAM_IS_RECORDED(4),
PING_REQUEST(6),
PING_RESPONSE(7),
SWFV_REQUEST(26),
SWFV_RESPONSE(27),
BUFFER_EMPTY(31),
BUFFER_FULL(32);
private final int value;
private Type(int value) {
this.value = value;
}
@Override
public int intValue() {
return value;
}
private static final ValueToEnum<Type> converter = new ValueToEnum<Type>(Type.values());
public static Type valueToEnum(final int value) {
return converter.valueToEnum(value);
}
}
private Type type;
private int streamId;
private int bufferLength;
private int time;
private byte[] bytes;
public Control(RtmpHeader header, ChannelBuffer in) {
super(header, in);
}
private Control(Type type, int time) {
this.type = type;
this.time = time;
}
private Control(int streamId, Type type) {
this.streamId = streamId;
this.type = type;
}
@Override
public MessageType getMessageType() {
return MessageType.CONTROL;
}
public static Control setBuffer(int streamId, int bufferLength) {
Control control = new Control(Type.SET_BUFFER, 0);
control.bufferLength = bufferLength;
control.streamId = streamId;
return control;
}
public static Control pingRequest(int time) {
return new Control(Type.PING_REQUEST, time);
}
public static Control pingResponse(int time) {
return new Control(Type.PING_RESPONSE, time);
}
public static Control swfvResponse(byte[] bytes) {
Control control = new Control(Type.SWFV_RESPONSE, 0);
control.bytes = bytes;
return control;
}
public static Control streamBegin(int streamId) {
Control control = new Control(Type.STREAM_BEGIN, 0);
control.streamId = streamId;
return control;
}
public static Control streamIsRecorded(int streamId) {
return new Control(streamId, Type.STREAM_IS_RECORDED);
}
public static Control streamEof(int streamId) {
return new Control(streamId, Type.STREAM_EOF);
}
public static Control bufferEmpty(int streamId) {
return new Control(streamId, Type.BUFFER_EMPTY);
}
public static Control bufferFull(int streamId) {
return new Control(streamId, Type.BUFFER_FULL);
}
public Type getType() {
return type;
}
public int getTime() {
return time;
}
public int getBufferLength() {
return bufferLength;
}
@Override
public ChannelBuffer encode() {
final int size;
switch(type) {
case SWFV_RESPONSE: size = 44; break;
case SET_BUFFER: size = 10; break;
default: size = 6;
}
ChannelBuffer out = ChannelBuffers.buffer(size);
out.writeShort((short) type.value);
switch(type) {
case STREAM_BEGIN:
case STREAM_EOF:
case STREAM_DRY:
case STREAM_IS_RECORDED:
out.writeInt(streamId);
break;
case SET_BUFFER:
out.writeInt(streamId);
out.writeInt(bufferLength);
break;
case PING_REQUEST:
case PING_RESPONSE:
out.writeInt(time);
break;
case SWFV_REQUEST:
break;
case SWFV_RESPONSE:
out.writeBytes(bytes);
break;
case BUFFER_EMPTY:
case BUFFER_FULL:
out.writeInt(streamId);
break;
}
return out;
}
@Override
public void decode(ChannelBuffer in) {
type = Type.valueToEnum(in.readShort());
switch(type) {
case STREAM_BEGIN:
case STREAM_EOF:
case STREAM_DRY:
case STREAM_IS_RECORDED:
streamId = in.readInt();
break;
case SET_BUFFER:
streamId = in.readInt();
bufferLength = in.readInt();
break;
case PING_REQUEST:
case PING_RESPONSE:
time = in.readInt();
break;
case SWFV_REQUEST:
// only type (2 bytes)
break;
case SWFV_RESPONSE:
bytes = new byte[42];
in.readBytes(bytes);
break;
case BUFFER_EMPTY:
case BUFFER_FULL:
streamId = in.readInt();
break;
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(super.toString());
sb.append(type);
sb.append(" streamId: ").append(streamId);
switch(type) {
case SET_BUFFER:
sb.append(" bufferLength: ").append(bufferLength);
break;
case PING_REQUEST:
case PING_RESPONSE:
sb.append(" time: ").append(time);
break;
}
if(bytes != null) {
sb.append(" bytes: " + Utils.toHex(bytes));
}
return sb.toString();
}
public int getStreamId() {
return streamId;
}
}