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(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 { } } /// /// /master /// /masterseq/ /// go /// goback /// goto /// /// /seq/X/ /// go /// goback /// goto /// master /// circuit /// /// /universe/X/ /// D/on /// reset /// /// /// /// 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 } }