#region usings using System; using System.ComponentModel.Composition; using System.Collections.Generic; using System.Net; using System.Net.Sockets; using System.Threading; using System.Text; using VVVV.PluginInterfaces.V1; using VVVV.PluginInterfaces.V2; using VVVV.Utils.VColor; using VVVV.Utils.VMath; using VVVV.Core.Logging; #endregion usings // PCSocketInPC // V1.01 - Added incomplete output pin namespace VVVV.Nodes { #region PluginInfo [PluginInfo(Name = "SocketInPC", Category = "PC", Help = "Receives Point Cloud data via UDP", Tags = "")] #endregion PluginInfo public class PCSocketInPCNode : IPluginEvaluate { #region fields & pins [Input("Port", DefaultValue = 11000)] IDiffSpread FInput; // [Input("TimeType", IsSingle = true, DefaultValue = 0)] // IDiffSpread FTimeT; [Input("Enable", IsSingle = true, DefaultValue = 1)] IDiffSpread FEnable; [Output("Output")] ISpread FOutput; [Output("Got")] ISpread FGot; [Output("Frame")] ISpread FFrame; [Output("TimeStamp")] ISpread FTStamp; [Output("Incomplete")] ISpread FIncomplete; [Output("Dropped")] ISpread FDropped; [Import()] ILogger FLogger; #endregion fields & pins List outList = new List(); public bool messageReceived = false; public class UdpState { public UdpClient u; public IPEndPoint e; } UdpClient listener = null; IPEndPoint groupEP; bool FirstCall = true; const int BUFSIZE = 65000; public Byte[] Buffer = new Byte[BUFSIZE]; UInt32 framelast = 0; UInt32 timestamp; Int32 seqnext = 1; bool incomplete = false; bool dropped = false; uint datacnt = 0; private System.Object lockReader = new System.Object(); // used for locking data transfer to output pins public void ReceiveCallback(IAsyncResult ar) { UdpClient u = (UdpClient)((UdpState)(ar.AsyncState)).u; IPEndPoint e = (IPEndPoint)((UdpState)(ar.AsyncState)).e; try { Buffer = u.EndReceive(ar, ref e); } catch { // Socket must have been closed. Just exit. FLogger.Log(LogType.Debug, "SocketInPC: ReceiveCallback() exiting on dead socket."); return; } // Lock data access lock ( lockReader ) { UInt32 framenow; Int32 seqnow; bool endseq = false; int place = 0; if ( seqnext == 1 ) { // Clean finish on last, this must be new incomplete = false; dropped = false; } framenow = BitConverter.ToUInt32(Buffer, place); place += 4; //if ( FTimeT[0] ) //{ timestamp = BitConverter.ToUInt32(Buffer, place); place += 4; //} seqnow = BitConverter.ToInt32(Buffer, place); place += 4; // negative sequence means last one if ( seqnow < 0 ) { endseq = true; seqnow *= -1; } // See if we missed something if ( seqnow != seqnext ) { dropped = true; } // If in the middle of a frame and frame number changes, reset if ( seqnext > 1 && framenow != framelast ) { outList.Clear(); dropped = true; // Do more here? Output old data and save new? } datacnt = BitConverter.ToUInt32(Buffer, place); place += 4; //FLogger.Log(LogType.Debug, "SocketInPC: datacnt: {0}", datacnt); for ( int i = 0; i < datacnt; i++ ) { outList.Add((double)BitConverter.ToInt16(Buffer, place) / 1000.0); place += 2; } framelast = framenow; if ( endseq ) { seqnext = 1; messageReceived = true; } else { seqnext = seqnow + 1; u.BeginReceive(new AsyncCallback(ReceiveCallback), ar.AsyncState); } } // lockReader } UdpState s = new UdpState(); //called when data for any output pin is requested public void Evaluate(int SpreadMax) { FGot.SliceCount = 1; FGot[0] = false; FIncomplete.SliceCount = 1; FIncomplete[0] = false; FDropped.SliceCount = 1; FDropped[0] = false; FFrame.SliceCount = 1; int debug = 0; FOutput.SliceCount = 0; if ( !FEnable[0] ) { /* Crashes vvvv! try { if ( listener != null && listener.Client != null ) { listener.Close(); } } catch { // guess it wasn't open... listener = null; } */ FirstCall = true; return; } //bool done = false; if ( FirstCall || FInput.IsChanged ) { //FLogger.Log(LogType.Debug, "SocketInPC: Firstcall {0} Changed {1}", FirstCall, FInput.IsChanged); try { if ( listener != null && listener.Client != null ) { listener.Close(); } } catch ( Exception e ) { // guess it wasn't open... FLogger.Log(LogType.Debug, "SocketInPC: listener.Close() failed: {0}", e.ToString()); } try { FirstCall = false; debug = 1; groupEP = new IPEndPoint(IPAddress.Any, FInput[0]); debug = 2; listener = new UdpClient(groupEP); s.e = groupEP; s.u = listener; debug = 3; listener.BeginReceive(new AsyncCallback(ReceiveCallback), s); //ReceiveMessages(); FLogger.Log(LogType.Debug, "SocketInPC: Listening to port {0}", FInput[0]); } catch ( Exception e ) { FLogger.Log(LogType.Debug, "SocketInPC: Boink! debug = {0} msg: {1}", debug, e.ToString()); FirstCall = true; //listener.Close(); return; } } //string received_data; //byte[] receive_byte_array; lock ( lockReader ) { if ( messageReceived ) { //FLogger.Log(LogType.Debug, "SocketInPC: Got it: {0}", datacnt); messageReceived = false; FGot[0] = true; FIncomplete[0] = incomplete; FDropped[0] = dropped; FFrame[0] = (int)framelast; FTStamp[0] = (int)timestamp; FOutput.SliceCount = outList.Count; FOutput.AssignFrom(outList); outList.Clear(); listener.BeginReceive(new AsyncCallback(ReceiveCallback), s); } } } } }