loupiottes/DMX-2.0/OSCServer.cs
2014-12-04 15:37:16 +00:00

275 lines
4.9 KiB
C#

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections.Generic;
namespace DMX2
{
public class OSCServer : IDisposable
{
UdpClient udpCli=null;
Thread pollThread = null;
bool running=true;
enum OSCType {
Int32,
Float32,
String,
Blob
}
class OSCMessage {
public abstract class OSCArg{
protected OSCArg(){}
public abstract OSCType Type{ get; }
public virtual string GetString(){ throw new System.NotImplementedException (); }
public virtual float GetFloat (){throw new System.NotImplementedException (); }
public virtual int GetInt(){throw new System.NotImplementedException (); }
public virtual byte[] GetBlob(){throw new System.NotImplementedException (); }
}
private class OSCStringArg : OSCArg{
string _s;
public override OSCType Type {
get {
return OSCType.String;
}
}
public OSCStringArg(string s){
_s=s;
}
public override string GetString ()
{
return _s;
}
}
private class OSCIntArg : OSCArg{
int _i;
public override OSCType Type {
get {
return OSCType.Int32;
}
}
public OSCIntArg(int i){
_i=i;
}
public override int GetInt ()
{
return _i;
}
public override float GetFloat ()
{
return (float)_i;
}
public override string GetString ()
{
return _i.ToString();
}
}
private class OSCFloatArg : OSCArg{
float _f;
public override OSCType Type {
get {
return OSCType.Float32;
}
}
public OSCFloatArg(float f){
_f=f;
}
public override int GetInt ()
{
return (int)(_f);
}
public override float GetFloat ()
{
return _f;
}
public override string GetString ()
{
return _f.ToString();
}
}
private class OSCBlobArg : OSCArg{
byte[] _b;
public override OSCType Type {
get {
return OSCType.Blob;
}
}
public OSCBlobArg(byte[] b){
_b=b;
}
public override byte[] GetBlob ()
{
return _b;
}
}
static string DecodeString (byte[] b, ref int pos)
{
int end = Array.IndexOf<byte>(b,0,pos);
if(end==-1) end = b.Length;
string ret = System.Text.Encoding.ASCII.GetString(b,pos,end-pos);
pos = (end/4+1)*4;
return ret;
}
static float DecodeFloat (byte[] b, ref int pos)
{
if(BitConverter.IsLittleEndian)
Array.Reverse(b,pos,4);
float ret = BitConverter.ToSingle(b,pos);
pos+=4;
return ret;
}
static int DecodeInt (byte[] b, ref int pos)
{
if(BitConverter.IsLittleEndian)
Array.Reverse(b,pos,4);
int ret = BitConverter.ToInt32(b, pos);
pos+=4;
return ret;
}
public OSCMessage(byte[] bmsg){
int pos = 0;
Address = DecodeString(bmsg,ref pos);
string typestring = DecodeString(bmsg,ref pos);
args = new OSCArg[typestring.Length-1];
int idx=0;
foreach(char c in typestring){
switch(c){
case 'f':
args[idx++] = new OSCFloatArg(DecodeFloat(bmsg,ref pos));
break;
case 's':
args[idx++] = new OSCStringArg(DecodeString(bmsg,ref pos));
break;
case 'i':
args[idx++] = new OSCIntArg(DecodeInt(bmsg,ref pos));
break;
case 'b':
int len=DecodeInt(bmsg,ref pos)*4;
byte[] b = new byte[len];
bmsg.CopyTo(b,0);
pos+=len;
args[idx++] = new OSCBlobArg(b);
break;
}
}
}
public string Address{
get;
private set;
}
OSCArg[] args;
public OSCArg[] Args {
get {
return args;
}
}
}
public OSCServer ()
{
pollThread = new Thread(new ThreadStart(Loop));
pollThread.Start();
}
void Loop ()
{
udpCli = new UdpClient (7772);
byte[] recv;
IPEndPoint remep = new IPEndPoint (IPAddress.Any, 0);
try {
while (running) {
recv = udpCli.Receive (ref remep);
Console.WriteLine(remep);
OSCMessage msg = new OSCMessage(recv);
Console.WriteLine(msg.Address);
foreach(var arg in msg.Args)
Console.WriteLine(arg.GetString());
ProcessMessage(msg);
}
} catch (SocketException ex) {
}
finally {
}
}
/// <summary>
/// /master
/// /masterseq/
/// go
/// goback
/// goto
///
/// /seq/X/
/// go
/// goback
/// goto
/// master
/// circuit
///
/// /universe/X/
/// D/on
/// reset
///
///
///
/// </summary>
void ProcessMessage (OSCMessage msg)
{
}
#region IDisposable implementation
public void Dispose ()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose (bool disposing)
{
if (disposing) {
running=false;
if(udpCli!=null)
udpCli.Close();
if(pollThread!=null)
{
if(!pollThread.Join(100))
pollThread.Abort();
pollThread=null;
}
}
}
#endregion
}
}