DirectOutputR1
DirectOutput framework R1 for virtual pinball cabinets.
Go to:
Overview 
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events Macros Pages
Engine.cs
Go to the documentation of this file.
1 using System;
2 using System.Net;
3 using System.Net.Sockets;
4 using System.Text;
5 using System.Timers;
6 
7 
8 namespace DirectOutput.Cab.Out.DMX.ArtnetEngine
9 {
14  public class Engine
15  {
16 
17  private static readonly Lazy<Engine> lazy = new Lazy<Engine>(() => new Engine());
18 
25  public static Engine Instance { get { return lazy.Value; } }
26 
27 
28 
29 
30 
31  #region "Public"
32 
37  private Engine()
38  {
39  ArtNetHeader = new byte[] { 0x41, 0x72, 0x74, 0x2d, 0x4e, 0x65, 0x74, 0 };
40  //ArtNetAddress = new byte[] { 0x7f, 0, 0, 1, Convert.ToByte(this.LoByte(0x1936)), Convert.ToByte(this.HiByte(0x1936)) };
41 
42  lock (UdpServerLocker)
43  {
44  try
45  {
46  UdpServer = new UdpClient(0x1936);
47  UdpServer.EnableBroadcast = true;
48  UdpServer.Client.SendTimeout = 100;
49  UdpServer.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
50  }
51  catch (Exception E)
52  {
53  Log.Exception("Could not initialize UdpServer for ArtNet (Port: 6454).", E);
54  UdpServer = null;
55  }
56  }
57  }
58 
62  ~Engine()
63  {
64  lock (UdpServerLocker)
65  {
66  if (UdpServer != null)
67  {
68  try
69  {
70  UdpServer.Close();
71  }
72  catch { }
73  UdpServer = null;
74  }
75  }
76  }
77 
78 
79  int SendExceptionCnt = 0;
87  public void SendDMX(string BroadcastAdress, short Universe, byte[] Data, int DataLength)
88  {
89  if (UdpServer != null)
90  {
91  byte[] packet = new byte[(0x11 + DataLength) + 1];
92  Buffer.BlockCopy(this.ArtNetHeader, 0, packet, 0, this.ArtNetHeader.Length);
93  packet[8] = Convert.ToByte(this.LoByte(0x5000));
94  packet[9] = Convert.ToByte(this.HiByte(0x5000));
95  packet[10] = 0; //ProtVerHi
96  packet[11] = 14; //ProtVerLo
97  packet[12] = 0; //Sequence
98  packet[13] = 0; //Physical
99  packet[14] = Convert.ToByte(this.LoByte(Universe));
100  packet[15] = Convert.ToByte(this.HiByte(Universe));
101  packet[0x10] = Convert.ToByte(this.HiByte(DataLength));
102  packet[0x11] = Convert.ToByte(this.LoByte(DataLength));
103 
104  try
105  {
106  Buffer.BlockCopy(Data, 0, packet, 0x12, DataLength);
107  }
108  catch (Exception exception1)
109  {
110  Log.Exception("A exception occured in the ArtNet Engine class.", exception1);
111  //Error(exception1, new EventArgs());
112  }
113 
114  lock (UdpServerLocker)
115  {
116  if (UdpServer != null)
117  {
118  try
119  {
120 
121  UdpServer.Send(packet, packet.Length, BroadcastAdress, 0x1936);
122  SendExceptionCnt = 0;
123  }
124  catch (Exception E)
125  {
126  SendExceptionCnt++;
127  if (SendExceptionCnt > 10)
128  {
129  try
130  {
131  Log.Exception("More than 10 consuecutive transmissions of ArtNet data have failed. ArtNet enigine will be disabled for the session.", E);
132  }
133  catch { }
134 
135  if (UdpServer != null)
136  {
137  try
138  {
139  UdpServer.Close();
140  }
141  catch { }
142  UdpServer = null;
143  }
144  }
145  else
146  {
147  Log.Exception("A exception has occured when sending ArtNet data.", E);
148  }
149 
150  }
151 
152  }
153  }
154  }
155  }
156 
157  #endregion
158 
159 
160 
161 
162  #region "Work Around"
163 
164 
165  private object LoByte(int wParam)
166  {
167  return (wParam & 0xffL);
168  }
169 
170  private object HiByte(int wParam)
171  {
172  return ((wParam / 0x100) & 0xffL);
173  }
174 
175 
176 
177  #endregion
178 
179 
180 
181  private object UdpServerLocker = new object();
182  private UdpClient UdpServer;
183 
184 
185  private byte[] ArtNetHeader;
186 
187 
188  }
189 }