You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
293 lines
8.7 KiB
293 lines
8.7 KiB
|
6 years ago
|
#region licence/info
|
||
|
|
// OSC.NET - Open Sound Control for .NET
|
||
|
|
// http://luvtechno.net/
|
||
|
|
//
|
||
|
|
// Copyright (c) 2006, Yoshinori Kawasaki
|
||
|
|
// All rights reserved.
|
||
|
|
//
|
||
|
|
// Changes and improvements:
|
||
|
|
// Copyright (c) 2006-2014 Martin Kaltenbrunner <martin@tuio.org>
|
||
|
|
// As included with http://reactivision.sourceforge.net/
|
||
|
|
//
|
||
|
|
// Further implementations and specifications:
|
||
|
|
// Copyright (c) 2013 Marko Ritter <marko@intolight.de>
|
||
|
|
// As included with https://github.com/vvvv/vvvv-sdk///
|
||
|
|
//
|
||
|
|
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||
|
|
//
|
||
|
|
// * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||
|
|
// * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||
|
|
// * Neither the name of "luvtechno.net" nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||
|
|
//
|
||
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
|
||
|
|
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||
|
|
// AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
|
|
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||
|
|
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
|
||
|
|
// WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
#endregion licence/info
|
||
|
|
|
||
|
|
using System;
|
||
|
|
using System.Collections;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
using System.IO;
|
||
|
|
using System.Text;
|
||
|
|
using System.Drawing;
|
||
|
|
|
||
|
|
namespace OSC.NET
|
||
|
|
{
|
||
|
|
/// <summary>
|
||
|
|
/// OSCPacket
|
||
|
|
/// </summary>
|
||
|
|
abstract public class OSCPacket
|
||
|
|
{
|
||
|
|
public static readonly Encoding ASCIIEncoding8Bit;
|
||
|
|
public bool ExtendedVVVVMode { get; set; }
|
||
|
|
|
||
|
|
static OSCPacket()
|
||
|
|
{
|
||
|
|
ASCIIEncoding8Bit = Encoding.ASCII;//Encoding.GetEncoding(1252);
|
||
|
|
}
|
||
|
|
|
||
|
|
public OSCPacket(bool extendedMode = false)
|
||
|
|
{
|
||
|
|
this.ExtendedVVVVMode = extendedMode;
|
||
|
|
this.values = new ArrayList();
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static void addBytes(ArrayList data, byte[] bytes)
|
||
|
|
{
|
||
|
|
foreach(byte b in bytes)
|
||
|
|
{
|
||
|
|
data.Add(b);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static void padNull(ArrayList data)
|
||
|
|
{
|
||
|
|
byte zero = 0;
|
||
|
|
int pad = 4 - (data.Count % 4);
|
||
|
|
for (int i = 0; i < pad; i++)
|
||
|
|
{
|
||
|
|
data.Add(zero);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
internal static byte[] swapEndian(byte[] data)
|
||
|
|
{
|
||
|
|
byte[] swapped = new byte[data.Length];
|
||
|
|
for(int i = data.Length - 1, j = 0 ; i >= 0 ; i--, j++)
|
||
|
|
{
|
||
|
|
swapped[j] = data[i];
|
||
|
|
}
|
||
|
|
return swapped;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static byte[] packInt(int value)
|
||
|
|
{
|
||
|
|
byte[] data = BitConverter.GetBytes(value);
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static byte[] packLong(long value)
|
||
|
|
{
|
||
|
|
byte[] data = BitConverter.GetBytes(value);
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static byte[] packFloat(float value)
|
||
|
|
{
|
||
|
|
byte[] data = BitConverter.GetBytes(value);
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static byte[] packDouble(double value)
|
||
|
|
{
|
||
|
|
byte[] data = BitConverter.GetBytes(value);
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static byte[] packString(string value)
|
||
|
|
{
|
||
|
|
return ASCIIEncoding8Bit.GetBytes(value);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
protected static byte[] packChar(char value)
|
||
|
|
{
|
||
|
|
byte[] data = BitConverter.GetBytes(value);
|
||
|
|
if (BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
private static void Copy(Stream src, Stream dst, int bufferSize = 81920)
|
||
|
|
{
|
||
|
|
byte[] array = new byte[bufferSize];
|
||
|
|
int count;
|
||
|
|
while ((count = src.Read(array, 0, array.Length)) != 0)
|
||
|
|
{
|
||
|
|
dst.Write(array, 0, count);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
protected static byte[] packBlob(Stream value)
|
||
|
|
{
|
||
|
|
var mem = new MemoryStream();
|
||
|
|
value.Seek(0, SeekOrigin.Begin);
|
||
|
|
//value.CopyTo(mem);
|
||
|
|
Copy(value, mem);
|
||
|
|
byte[] valueData = mem.ToArray();
|
||
|
|
|
||
|
|
var lData = new ArrayList();
|
||
|
|
|
||
|
|
var length = packInt(valueData.Length);
|
||
|
|
|
||
|
|
lData.AddRange(length);
|
||
|
|
lData.AddRange(valueData);
|
||
|
|
|
||
|
|
return (byte[])lData.ToArray(typeof(byte));
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static byte[] packTimeTag(DateTime value)
|
||
|
|
{
|
||
|
|
var tag = new OscTimeTag();
|
||
|
|
tag.Set(value);
|
||
|
|
|
||
|
|
return tag.ToByteArray(); ;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static byte[] packColor(Color col)
|
||
|
|
{
|
||
|
|
byte[] data = {col.R, col.G, col.B, col.A};
|
||
|
|
if (BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
abstract protected void pack();
|
||
|
|
protected byte[] binaryData;
|
||
|
|
public byte[] BinaryData
|
||
|
|
{
|
||
|
|
get
|
||
|
|
{
|
||
|
|
pack();
|
||
|
|
return binaryData;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static int unpackInt(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
byte[] data = new byte[4];
|
||
|
|
for(int i = 0 ; i < 4 ; i++, start++) data[i] = bytes[start];
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return BitConverter.ToInt32(data, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static long unpackLong(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
byte[] data = new byte[8];
|
||
|
|
for(int i = 0 ; i < 8 ; i++, start++) data[i] = bytes[start];
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return BitConverter.ToInt64(data, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static float unpackFloat(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
byte[] data = new byte[4];
|
||
|
|
for(int i = 0 ; i < 4 ; i++, start++) data[i] = bytes[start];
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return BitConverter.ToSingle(data, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static double unpackDouble(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
byte[] data = new byte[8];
|
||
|
|
for(int i = 0 ; i < 8 ; i++, start++) data[i] = bytes[start];
|
||
|
|
if(BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
return BitConverter.ToDouble(data, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static string unpackString(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
int count= 0;
|
||
|
|
for(int index = start ; bytes[index] != 0 ; index++, count++) ;
|
||
|
|
string s = ASCIIEncoding8Bit.GetString(bytes, start, count);
|
||
|
|
start += count+1;
|
||
|
|
start = (start + 3) / 4 * 4;
|
||
|
|
return s;
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static char unpackChar(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
byte[] data = {bytes[start]};
|
||
|
|
return BitConverter.ToChar(data, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static Stream unpackBlob(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
int length = unpackInt(bytes, ref start);
|
||
|
|
|
||
|
|
byte[] buffer = new byte[length];
|
||
|
|
Array.Copy(bytes, start, buffer, 0, length);
|
||
|
|
|
||
|
|
start += length;
|
||
|
|
start = (start + 3) / 4 * 4;
|
||
|
|
return new MemoryStream(buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static Color unpackColor(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
byte[] data = new byte[4];
|
||
|
|
for (int i = 0; i < 4; i++, start++) data[i] = bytes[start];
|
||
|
|
if (BitConverter.IsLittleEndian) data = swapEndian(data);
|
||
|
|
|
||
|
|
return Color.FromArgb (data[3],data[0],data[1],data[2]);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected static DateTime unpackTimeTag(byte[] bytes, ref int start)
|
||
|
|
{
|
||
|
|
byte[] data = new byte[8];
|
||
|
|
for (int i = 0; i < 8; i++, start++) data[i] = bytes[start];
|
||
|
|
var tag = new OscTimeTag(data);
|
||
|
|
|
||
|
|
return tag.DateTime;
|
||
|
|
}
|
||
|
|
|
||
|
|
public static OSCPacket Unpack(byte[] bytes, bool extendedMode = false)
|
||
|
|
{
|
||
|
|
int start = 0;
|
||
|
|
return Unpack(bytes, ref start, bytes.Length, extendedMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
public static OSCPacket Unpack(byte[] bytes, ref int start, int end, bool extendedMode = false)
|
||
|
|
{
|
||
|
|
if(bytes[start] == '#') return OSCBundle.Unpack(bytes, ref start, end, extendedMode);
|
||
|
|
else return OSCMessage.Unpack(bytes, ref start, extendedMode);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
protected string address;
|
||
|
|
public string Address
|
||
|
|
{
|
||
|
|
get { return address; }
|
||
|
|
set
|
||
|
|
{
|
||
|
|
// TODO: validate
|
||
|
|
address = value;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
protected ArrayList values;
|
||
|
|
public ArrayList Values
|
||
|
|
{
|
||
|
|
get { return (ArrayList)values.Clone(); }
|
||
|
|
}
|
||
|
|
abstract public void Append(object value);
|
||
|
|
|
||
|
|
abstract public bool IsBundle();
|
||
|
|
}
|
||
|
|
}
|