de.sciss.net
Class OSCPacketCodec

java.lang.Object
  extended by de.sciss.net.OSCPacketCodec

public class OSCPacketCodec
extends Object

A packet codec defines how the translation between Java objects and OSC atoms is accomplished. For example, by default, when an OSC message is assembled for transmission, the encoder will translate ajava.lang.Integer argument into a four byte integer with typetag 'i'. Or when a received message is being decoded, finding an atom typetagged 'f', the decoder will create a java.lang.Float out of it.

This example sounds trivial, but the codec is also able to handle type conversions. For instance, in the strict OSC 1.0 specification, only 32bit numeric atoms are defined ('i' and 'f'). A codec with mode MODE_STRICT_V1 will reject a java.lang.Double in the encoding process and not be able to decode a typetag 'd'. A codec with mode MODE_MODEST automatically breaks down everything the 32bit, so a java.lang.Double gets encoded as 32bit 'f' and a received atom tagged 'd' becomes a java.lang.Float. Other configurations exist.

Another important function of the codec is to specify the charset encoding of strings, something that was overseen in the OSC 1.0 spec. By default, UTF-8 is used so all special characters can be safely encoded.

Last but not least, using the putDecoder and putEncoder methods, the codec can be extended to support additional Java classes or OSC typetags, without the need to subclass OSCPacketCodec.

Since:
NetUtil 0.35
Version:
0.36, 18-Feb-09
Author:
Hanns Holger Rutz

Nested Class Summary
static class OSCPacketCodec.Atom
          The Atom class represents a combination of an encoder and decoder of a Java respectively OSC atom.
 
Field Summary
protected  String charsetName
           
static int MODE_FAT_V1
          Support mode: like MODE_STRICT_V1, but with additional 64bit support, that is a mutual mapping between 'h' <--> java.lang.Long, and 'd' <--> java.lang.Double.
static int MODE_GRACEFUL
          Support mode: like MODE_MODEST, that is, it will downgrade to 32bit in the encoding process, but decoding leaves 64bit values intact, so 'h' becomes java.lang.Long, and 'd' into java.lang.Double.
static int MODE_MODEST
          Support mode: like MODE_STRICT_V1, but coder additionally encodes java.lang.Long as a 'i', java.lang.Double as a 'f', and de.sciss.net.OSCPacket as a blob 'b'.
static int MODE_READ_DOUBLE
           
static int MODE_READ_DOUBLE_AS_FLOAT
           
static int MODE_READ_LONG
           
static int MODE_READ_LONG_AS_INTEGER
           
static int MODE_READ_SYMBOL_AS_STRING
           
static int MODE_STRICT_V1
          Support mode: coder only accepts java.lang.Integer, java.lang.Float, java.lang.String, and byte[].
static int MODE_WRITE_DOUBLE
           
static int MODE_WRITE_DOUBLE_AS_FLOAT
           
static int MODE_WRITE_LONG
           
static int MODE_WRITE_LONG_AS_INTEGER
           
static int MODE_WRITE_PACKET_AS_BLOB
           
 
Constructor Summary
OSCPacketCodec()
          Creates a new codec with MODE_GRACEFUL and UTF-8 encoding.
OSCPacketCodec(int mode)
          Creates a new codec with a given support mode and UTF-8 encoding.
OSCPacketCodec(int mode, String charset)
          Creates a new codec with a given support mode and a given charset for string encoding.
 
Method Summary
 OSCPacket decode(ByteBuffer b)
          Creates a new packet decoded from the ByteBuffer.
protected  OSCBundle decodeBundle(ByteBuffer b)
           
protected  OSCMessage decodeMessage(String command, ByteBuffer b)
          Creates a new message with arguments decoded from the ByteBuffer.
 void encode(OSCPacket p, ByteBuffer b)
          Encodes the contents of this packet into the provided ByteBuffer, beginning at the buffer's current position.
protected  void encodeBundle(OSCBundle bndl, ByteBuffer b)
           
protected  void encodeMessage(OSCMessage msg, ByteBuffer b)
          Encodes the message onto the given ByteBuffer, beginning at the buffer's current position.
protected  int getBundleSize(OSCBundle bndl)
           
static OSCPacketCodec getDefaultCodec()
          Queries the standard codec which is used in all implicit client and server creations.
protected  int getMessageSize(OSCMessage msg)
          Calculates the byte size of the encoded message
 int getSize(OSCPacket p)
          Calculates and returns the packet's size in bytes
static void padToAlign(ByteBuffer b)
          Adds as many zero padding bytes as necessary to stop on a 4 byte alignment.
 void putDecoder(byte typeTag, OSCPacketCodec.Atom a)
          Registers an atomic decoder with the packet codec.
 void putEncoder(Class javaClass, OSCPacketCodec.Atom a)
          Registers an atomic encoder with the packet codec.
static String readString(ByteBuffer b)
          Reads a null terminated string from the current buffer position
 void setStringCharsetCodec(String charsetName)
          Specifies the charset to use in string coding and decoding.
 void setSupportMode(int mode)
          Adjusts the support mode for type tag handling.
static void skipToAlign(ByteBuffer b)
          Advances the current buffer position to an integer of four bytes.
static void skipToValues(ByteBuffer b)
          Advances in the buffer as long there are non-zero bytes, then advance to a four byte alignment.
static void terminateAndPadToAlign(ByteBuffer b)
          Adds as many zero padding bytes as necessary to stop on a 4 byte alignment.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

MODE_READ_DOUBLE

public static final int MODE_READ_DOUBLE
See Also:
Constant Field Values

MODE_READ_DOUBLE_AS_FLOAT

public static final int MODE_READ_DOUBLE_AS_FLOAT
See Also:
Constant Field Values

MODE_READ_LONG

public static final int MODE_READ_LONG
See Also:
Constant Field Values

MODE_READ_LONG_AS_INTEGER

public static final int MODE_READ_LONG_AS_INTEGER
See Also:
Constant Field Values

MODE_WRITE_DOUBLE

public static final int MODE_WRITE_DOUBLE
See Also:
Constant Field Values

MODE_WRITE_DOUBLE_AS_FLOAT

public static final int MODE_WRITE_DOUBLE_AS_FLOAT
See Also:
Constant Field Values

MODE_WRITE_LONG

public static final int MODE_WRITE_LONG
See Also:
Constant Field Values

MODE_WRITE_LONG_AS_INTEGER

public static final int MODE_WRITE_LONG_AS_INTEGER
See Also:
Constant Field Values

MODE_READ_SYMBOL_AS_STRING

public static final int MODE_READ_SYMBOL_AS_STRING
See Also:
Constant Field Values

MODE_WRITE_PACKET_AS_BLOB

public static final int MODE_WRITE_PACKET_AS_BLOB
See Also:
Constant Field Values

MODE_STRICT_V1

public static final int MODE_STRICT_V1
Support mode: coder only accepts java.lang.Integer, java.lang.Float, java.lang.String, and byte[]. Decoder only accepts 'i', 'f', 's', and 'b'. Note that byte[] is used to represents blobs ('b').

See Also:
Constant Field Values

MODE_MODEST

public static final int MODE_MODEST
Support mode: like MODE_STRICT_V1, but coder additionally encodes java.lang.Long as a 'i', java.lang.Double as a 'f', and de.sciss.net.OSCPacket as a blob 'b'. The decoder decodes 'h' into java.lang.Integer, 'd' into java.lang.Float, and 'S' (Symbol) into java.lang.String.

See Also:
Constant Field Values

MODE_GRACEFUL

public static final int MODE_GRACEFUL
Support mode: like MODE_MODEST, that is, it will downgrade to 32bit in the encoding process, but decoding leaves 64bit values intact, so 'h' becomes java.lang.Long, and 'd' into java.lang.Double.

See Also:
Constant Field Values

MODE_FAT_V1

public static final int MODE_FAT_V1
Support mode: like MODE_STRICT_V1, but with additional 64bit support, that is a mutual mapping between 'h' <--> java.lang.Long, and 'd' <--> java.lang.Double. Also, 'S' (Symbol) is decoded into java.lang.String, and de.sciss.net.OSCPacket is encoded as a blob 'b'.

See Also:
Constant Field Values

charsetName

protected String charsetName
Constructor Detail

OSCPacketCodec

public OSCPacketCodec()
Creates a new codec with MODE_GRACEFUL and UTF-8 encoding. Note that since a codec and be shared between OSCServer or OSCClient instances, usually you will just want to call getDefaultCodec!

See Also:
MODE_GRACEFUL, getDefaultCodec()

OSCPacketCodec

public OSCPacketCodec(int mode)
Creates a new codec with a given support mode and UTF-8 encoding.

Parameters:
mode - the support mode flag field to use

OSCPacketCodec

public OSCPacketCodec(int mode,
                      String charset)
Creates a new codec with a given support mode and a given charset for string encoding.

Parameters:
mode - the support mode flag mask to use
charset - the name of the charset to use for string coding and decoding, like "UTF-8", "ISO-8859-1" etc.
See Also:
Charset
Method Detail

getDefaultCodec

public static OSCPacketCodec getDefaultCodec()
Queries the standard codec which is used in all implicit client and server creations. This codec adheres to the MODE_GRACEFUL scheme and uses UTF-8 string encoding.

Note that although it is not recommended, it is possible to modify the returned codec. That means that upon your application launch, you could query the default codec and switch its behaviour, e.g. change the string charset, so all successive operations with the default codec will be subject to those customizations.

Returns:
the default codec
See Also:
MODE_GRACEFUL

setStringCharsetCodec

public void setStringCharsetCodec(String charsetName)
Specifies the charset to use in string coding and decoding.

Parameters:
charsetName - the name of the charset, e.g. "UTF-8", "ISO-8859-1" etc.
See Also:
Charset

putDecoder

public void putDecoder(byte typeTag,
                       OSCPacketCodec.Atom a)
Registers an atomic decoder with the packet codec. This decoder is called whenever an OSC message with the given typetag is encountered.

Parameters:
typeTag - the typetag which is to be decoded with the new Atom. typeTag must be in the ASCII value range 0 to 127.
a - the decoder to use
See Also:
OSCPacketCodec.Atom

putEncoder

public void putEncoder(Class javaClass,
                       OSCPacketCodec.Atom a)
Registers an atomic encoder with the packet codec. This encoder is called whenever an OSC message to be assembled contains an argument of the given Java class.

Parameters:
javaClass - the class for which the encoder is responsible
a - the encoder to use
See Also:
OSCPacketCodec.Atom

setSupportMode

public void setSupportMode(int mode)
Adjusts the support mode for type tag handling. Usually you specify the mode directly in the instantiation of OSCPacketCodec, but you can change it later using this method.

Parameters:
mode - the new mode to use. A flag field combination of MODE_READ_DOUBLE or MODE_READ_DOUBLE_AS_FLOAT etc., or a ready made combination such as MODE_FAT_V1.
See Also:
OSCPacketCodec( int )

decode

public OSCPacket decode(ByteBuffer b)
                 throws IOException
Creates a new packet decoded from the ByteBuffer. This method tries to read a null terminated string at the beginning of the provided buffer. If it equals the bundle identifier, the decode of OSCBundle is called (which may recursively decode nested bundles), otherwise the one from OSCMessage.

Parameters:
b - ByteBuffer pointing right at the beginning of the packet. the buffer's limited should be set appropriately to allow the complete packet to be read. when the method returns, the buffer's position is right after the end of the packet.
Returns:
new decoded OSC packet
Throws:
IOException - in case some of the reading or decoding procedures failed.
BufferUnderflowException - in case of a parsing error that causes the method to read past the buffer limit
IllegalArgumentException - occurs in some cases of buffer underflow

encode

public void encode(OSCPacket p,
                   ByteBuffer b)
            throws IOException
Encodes the contents of this packet into the provided ByteBuffer, beginning at the buffer's current position. To write the encoded packet, you will typically call flip() on the buffer, then write() on the channel.

Parameters:
b - ByteBuffer pointing right at the beginning of the osc packet. buffer position will be right after the end of the packet when the method returns.
Throws:
IOException - in case some of the writing procedures failed.

getSize

public int getSize(OSCPacket p)
            throws IOException
Calculates and returns the packet's size in bytes

Returns:
the size of the packet in bytes, including the initial osc command and aligned to 4-byte boundary. this is the amount of bytes written by the encode method.
Throws:
IOException - if an error occurs during the calculation

getBundleSize

protected int getBundleSize(OSCBundle bndl)
                     throws IOException
Throws:
IOException

getMessageSize

protected int getMessageSize(OSCMessage msg)
                      throws IOException
Calculates the byte size of the encoded message

Returns:
the size of the OSC message in bytes
Throws:
IOException - if the message contains invalid arguments

decodeBundle

protected OSCBundle decodeBundle(ByteBuffer b)
                          throws IOException
Throws:
IOException

decodeMessage

protected OSCMessage decodeMessage(String command,
                                   ByteBuffer b)
                            throws IOException
Creates a new message with arguments decoded from the ByteBuffer. Usually you call decode from the OSCPacket superclass which will invoke this method of it finds an OSC message.

Parameters:
b - ByteBuffer pointing right at the beginning of the type declaration section of the OSC message, i.e. the name was skipped before.
Returns:
new OSC message representing the received message described by the ByteBuffer.
Throws:
IOException - in case some of the reading or decoding procedures failed.
BufferUnderflowException - in case of a parsing error that causes the method to read past the buffer limit
IllegalArgumentException - occurs in some cases of buffer underflow

encodeBundle

protected void encodeBundle(OSCBundle bndl,
                            ByteBuffer b)
                     throws IOException
Throws:
IOException

encodeMessage

protected void encodeMessage(OSCMessage msg,
                             ByteBuffer b)
                      throws BufferOverflowException,
                             IOException
Encodes the message onto the given ByteBuffer, beginning at the buffer's current position. To write the encoded message, you will typically call flip() on the buffer, then write() on the channel.

Parameters:
b - ByteBuffer pointing right at the beginning of the osc packet. buffer position will be right after the end of the message when the method returns.
Throws:
IOException - in case some of the writing procedures failed (buffer overflow, illegal arguments).
BufferOverflowException

readString

public static String readString(ByteBuffer b)
Reads a null terminated string from the current buffer position

Parameters:
b - buffer to read from. position and limit must be set appropriately. new position will be right after the terminating zero byte when the method returns
Throws:
BufferUnderflowException - in case the string exceeds the provided buffer limit

terminateAndPadToAlign

public static void terminateAndPadToAlign(ByteBuffer b)
Adds as many zero padding bytes as necessary to stop on a 4 byte alignment. if the buffer position is already on a 4 byte alignment when calling this function, another 4 zero padding bytes are added. buffer position will be on the new aligned boundary when return from this method

Parameters:
b - the buffer to pad
Throws:
BufferOverflowException - in case the padding exceeds the provided buffer limit

padToAlign

public static void padToAlign(ByteBuffer b)
Adds as many zero padding bytes as necessary to stop on a 4 byte alignment. if the buffer position is already on a 4 byte alignment when calling this function, this method does nothing.

Parameters:
b - the buffer to align
Throws:
BufferOverflowException - in case the padding exceeds the provided buffer limit

skipToValues

public static void skipToValues(ByteBuffer b)
                         throws BufferUnderflowException
Advances in the buffer as long there are non-zero bytes, then advance to a four byte alignment.

Parameters:
b - the buffer to advance
Throws:
BufferUnderflowException - in case the reads exceed the provided buffer limit
IllegalArgumentException - in case the skipping exceeds the provided buffer limit

skipToAlign

public static void skipToAlign(ByteBuffer b)
Advances the current buffer position to an integer of four bytes. The position is not altered if it is already aligned to a four byte boundary.

Parameters:
b - the buffer to advance
Throws:
IllegalArgumentException - in case the skipping exceeds the provided buffer limit