mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 17:17:29 -05:00
250 lines
6.5 KiB
Java
250 lines
6.5 KiB
Java
/*******************************************************************************
|
|
* sdrtrunk
|
|
* Copyright (C) 2014-2016 Dennis Sheirer
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
******************************************************************************/
|
|
package audio.broadcast.shoutcast.v2.ultravox;
|
|
|
|
import bits.BinaryMessage;
|
|
import org.apache.commons.lang3.Validate;
|
|
|
|
import java.util.Arrays;
|
|
|
|
public abstract class UltravoxMessage
|
|
{
|
|
public static final String ULTRAVOX_VERSION = "2.1";
|
|
public static final String VALID_RESPONSE_PREFIX = "ACK";
|
|
public static final String VALID_RESPONSE_PAYLOAD_PREFIX = "ACK:";
|
|
public static final String ERROR_RESPONSE_PREFIX = "NAK:";
|
|
|
|
public static final int[] SYNC = {0,1,2,3,4,5,6,7};
|
|
public static final int[] RESERVED = {8,9,10,11};
|
|
public static final int REQUIRED_DELIVERY = 12;
|
|
public static final int[] SEND_QUEUE_PRIORITY = {13,14,15};
|
|
public static final int[] MESSAGE_CLASS = {16,17,18,19};
|
|
public static final int[] MESSAGE_CLASS_AND_TYPE = {16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31};
|
|
public static final int[] PAYLOAD_LENGTH = {32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47};
|
|
|
|
private BinaryMessage mMessage;
|
|
|
|
/**
|
|
* Constructs a ultravox from the byte array
|
|
*/
|
|
public UltravoxMessage(byte[] data)
|
|
{
|
|
mMessage = new BinaryMessage(data.length * 8);
|
|
|
|
int pointer = 0;
|
|
|
|
for(byte b: data)
|
|
{
|
|
mMessage.setByte(pointer, b);
|
|
pointer += 8;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructs an empty ultravox of the specified length
|
|
*
|
|
* @param ultravoxMessageType type of ultravox
|
|
*/
|
|
public UltravoxMessage(UltravoxMessageType ultravoxMessageType)
|
|
{
|
|
mMessage = new BinaryMessage(56);
|
|
|
|
setSync();
|
|
setMessageType(ultravoxMessageType);
|
|
}
|
|
|
|
/**
|
|
* Message byte array
|
|
*
|
|
* @return ultravox bytes
|
|
*/
|
|
public byte[] getMessage()
|
|
{
|
|
return mMessage.toByteArray();
|
|
}
|
|
|
|
public String toString()
|
|
{
|
|
return getMessageType().name();
|
|
}
|
|
|
|
/**
|
|
* Sets the ultravox sync bits to the predefined sync pattern: 01011010 (0x5A)
|
|
*/
|
|
private void setSync()
|
|
{
|
|
mMessage.setInt(0x5A, SYNC);
|
|
}
|
|
|
|
/**
|
|
* Ultravox ultravox class
|
|
*/
|
|
public UltravoxMessageClass getMessageClass()
|
|
{
|
|
return UltravoxMessageClass.fromValue(mMessage.getInt(MESSAGE_CLASS));
|
|
}
|
|
|
|
/**
|
|
* Ultravox ultravox type
|
|
* @return
|
|
*/
|
|
public UltravoxMessageType getMessageType()
|
|
{
|
|
return UltravoxMessageType.fromValue(mMessage.getInt(MESSAGE_CLASS_AND_TYPE));
|
|
}
|
|
|
|
/**
|
|
* Sets the ultravox bits according to the ultravox class and type
|
|
* @param messageType of ultravox ultravox
|
|
*/
|
|
private void setMessageType(UltravoxMessageType messageType)
|
|
{
|
|
mMessage.setInt(messageType.getValue(), MESSAGE_CLASS_AND_TYPE);
|
|
}
|
|
|
|
/**
|
|
* Indicates if this ultravox has the required delivery flag set
|
|
*/
|
|
public boolean isRequiredDelivery()
|
|
{
|
|
return mMessage.get(REQUIRED_DELIVERY);
|
|
}
|
|
|
|
/**
|
|
* Sets the required delivery flag according to the argument
|
|
*/
|
|
public void setRequiredDelivery(boolean required)
|
|
{
|
|
if(required)
|
|
{
|
|
mMessage.set(REQUIRED_DELIVERY);
|
|
}
|
|
else
|
|
{
|
|
mMessage.clear(REQUIRED_DELIVERY);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Send queue priority (0 - 7) for this ultravox
|
|
*/
|
|
public int getSendQueuePriority()
|
|
{
|
|
return mMessage.getInt(SEND_QUEUE_PRIORITY);
|
|
}
|
|
|
|
/**
|
|
* Sets send queue priority for this ultravox
|
|
* @param priority 0 - 7
|
|
*/
|
|
public void setSendQueuePriority(int priority)
|
|
{
|
|
Validate.isTrue(0 <= priority && priority <= 7);
|
|
|
|
mMessage.setInt(priority, SEND_QUEUE_PRIORITY);
|
|
}
|
|
|
|
/**
|
|
* Message payload
|
|
*/
|
|
public String getPayload()
|
|
{
|
|
int payloadLength = mMessage.getInt(PAYLOAD_LENGTH);
|
|
|
|
byte[] payload = new byte[payloadLength];
|
|
|
|
int payloadPointer = 48;
|
|
|
|
for(int x = 0; x < payloadLength; x++)
|
|
{
|
|
payload[x] = mMessage.getByte(payloadPointer);
|
|
payloadPointer += 8;
|
|
}
|
|
|
|
//Strip the trailing 0x00 null value from a server response
|
|
if(payload[payload.length - 1] == 0)
|
|
{
|
|
return new String(Arrays.copyOf(payload, payload.length - 1));
|
|
}
|
|
|
|
return new String(payload);
|
|
}
|
|
|
|
/**
|
|
* Sets the ultravox payload, updates the ultravox length field, and appends a trailing 0x00 byte after the payload.
|
|
*/
|
|
public void setPayload(String payload)
|
|
{
|
|
setPayload(payload.getBytes());
|
|
}
|
|
|
|
public void setPayload(byte[] payload)
|
|
{
|
|
int messageBitLength = (7 + payload.length) * 8;
|
|
|
|
mMessage.setSize(messageBitLength);
|
|
mMessage.setInt(payload.length, PAYLOAD_LENGTH);
|
|
|
|
int payloadPointer = 48;
|
|
|
|
for(byte payloadByte: payload)
|
|
{
|
|
mMessage.setByte(payloadPointer, payloadByte);
|
|
payloadPointer += 8;
|
|
}
|
|
|
|
mMessage.setByte(payloadPointer, (byte)0x00);
|
|
}
|
|
|
|
/**
|
|
* Indicates if the response is a valid (ie non-error) response
|
|
*/
|
|
public boolean isValidResponse()
|
|
{
|
|
String payload = getPayload();
|
|
|
|
return payload != null && payload.startsWith(VALID_RESPONSE_PREFIX);
|
|
}
|
|
|
|
/**
|
|
* Indicates if the response message contains an error message.
|
|
*/
|
|
public boolean isErrorResponse()
|
|
{
|
|
String payload = getPayload();
|
|
|
|
return payload != null && payload.startsWith(ERROR_RESPONSE_PREFIX);
|
|
}
|
|
|
|
/**
|
|
* Textual message available when the error response flag is set.
|
|
*/
|
|
public String getErrorMessage()
|
|
{
|
|
String payload = getPayload();
|
|
|
|
if(payload != null)
|
|
{
|
|
return payload.replace(ERROR_RESPONSE_PREFIX, "");
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|