2 using System.Collections.Generic;
5 using System.Runtime.InteropServices;
7 using System.Xml.Serialization;
27 #region IOutputcontroller implementation
28 public override void Update()
33 PacDriveInstance.TriggerPacDriveUpdaterThread();
46 PacDriveInstance.Init(Cabinet);
47 Log.
Write(
"PacDrive initialized and updater thread started.");
57 PacDriveInstance.Finish();
58 PacDriveInstance.ShutdownLighting();
59 Log.
Write(
"PacDrive finished and updater thread stopped.");
73 private void AddOutputs()
75 for (
int i = 1; i <= 16; i++)
77 if (!Outputs.Any(x => x.Number == i))
79 Outputs.Add(
new Output() { Name =
"{0}.{1:00}".Build(Name, i), Number = i });
102 throw new Exception(
"The OutputValueChanged event handler for the PacDrive uni has been called by a sender which is not a OutputNumbered.");
106 if (!ON.
Number.IsBetween(1, 64))
108 throw new Exception(
"PacDrive output numbers must be in the range of 1-16. The supplied output number {0} is out of range.".Build(ON.
Number));
111 PacDriveInstance.UpdateValue(ON);
181 PacDriveInstance =
new PacDriveUnit();
203 #region Internal class for PacDrive output states and update methods
205 private static PacDriveUnit PacDriveInstance=null;
207 private class PacDriveUnit
213 private const int MaxUpdateFailCount = 5;
217 private ushort NewValue;
218 private ushort CurrentValue;
219 private bool UpdateRequired =
true;
221 private int Index = -1;
223 public object PacDriveUpdateLocker =
new object();
224 public object ValueChangeLocker =
new object();
226 public Thread PacDriveUpdater;
227 public bool KeepPacDriveUpdaterAlive =
false;
228 public object PacDriveUpdaterThreadLocker =
new object();
244 StartPacDriveUpdaterThread();
250 TerminatePacDriveUpdaterThread();
256 public void UpdateValue(IOutput Output)
259 if (!Output.Number.IsBetween(1, 16))
return;
261 int ZeroBasedOutputNumber = Output.Number - 1;
262 ushort Mask = (ushort)(1 << ZeroBasedOutputNumber);
263 lock (ValueChangeLocker)
265 if (Output.Value != 0)
271 NewValue &= (ushort)~Mask;
273 UpdateRequired =
true;
277 private void CopyNewToCurrent()
279 lock (ValueChangeLocker)
281 CurrentValue = NewValue;
286 public bool IsUpdaterThreadAlive
290 if (PacDriveUpdater != null)
292 return PacDriveUpdater.IsAlive;
298 public void StartPacDriveUpdaterThread()
300 lock (PacDriveUpdaterThreadLocker)
302 if (!IsUpdaterThreadAlive)
304 KeepPacDriveUpdaterAlive =
true;
305 PacDriveUpdater =
new Thread(PacDriveUpdaterDoIt);
306 PacDriveUpdater.Name =
"PacDrive updater thread";
307 PacDriveUpdater.Start();
311 public void TerminatePacDriveUpdaterThread()
313 lock (PacDriveUpdaterThreadLocker)
315 if (PacDriveUpdater != null)
319 KeepPacDriveUpdaterAlive =
false;
320 TriggerPacDriveUpdaterThread();
321 if (!PacDriveUpdater.Join(1000))
323 PacDriveUpdater.Abort();
329 Log.Exception(
"A error occurd during termination of {0}.".Build(PacDriveUpdater.Name), E);
330 throw new Exception(
"A error occurd during termination of {0}.".Build(PacDriveUpdater.Name), E);
332 PacDriveUpdater = null;
337 bool TriggerUpdate =
false;
338 public void TriggerPacDriveUpdaterThread()
340 if (!UpdateRequired)
return;
341 TriggerUpdate =
true;
342 UpdateRequired =
false;
343 lock (PacDriveUpdaterThreadLocker)
345 Monitor.Pulse(PacDriveUpdaterThreadLocker);
351 private void PacDriveUpdaterDoIt()
357 while (KeepPacDriveUpdaterAlive)
364 SendPacDriveUpdate();
371 Log.Exception(
"A error occured when updating PacDrive", E);
375 if (FailCnt > MaxUpdateFailCount)
377 Log.Exception(
"More than {0} consecutive updates failed for PacDrive. Updater thread will terminate.".Build(MaxUpdateFailCount));
378 KeepPacDriveUpdaterAlive =
false;
382 if (KeepPacDriveUpdaterAlive)
384 lock (PacDriveUpdaterThreadLocker)
386 while (!TriggerUpdate && KeepPacDriveUpdaterAlive)
388 Monitor.Wait(PacDriveUpdaterThreadLocker, 50);
395 TriggerUpdate =
false;
405 private bool ForceFullUpdate =
true;
406 private void SendPacDriveUpdate()
411 lock (PacDriveUpdateLocker)
413 lock (ValueChangeLocker)
415 if (NewValue == CurrentValue && !ForceFullUpdate)
return;
425 ForceFullUpdate =
false;
429 ForceFullUpdate =
true;
434 public void ShutdownLighting()
436 lock (PacDriveUpdateLocker)
438 lock (ValueChangeLocker)
450 private bool IsPresent
459 void Instance_OnPacRemoved(
int Index)
464 void Instance_OnPacAttached(
int Index)
468 TriggerPacDriveUpdaterThread();
471 private void InitUnit()
473 lock (ValueChangeLocker)
476 CurrentValue = 65535;
478 SendPacDriveUpdate();
482 public PacDriveUnit()
484 PDSingleton = PacDriveSingleton.
Instance;
485 PDSingleton.
OnPacAttached +=
new PacDriveSingleton.PacAttachedDelegate(Instance_OnPacAttached);
486 PDSingleton.
OnPacRemoved +=
new PacDriveSingleton.PacRemovedDelegate(Instance_OnPacRemoved);
487 this.Index = PacDriveSingleton.Instance.PacDriveGetIndex();
The Cabinet object describes the parts of a pinball cabinet (toys, outputcontrollers, outputs and more).
int Number
Gets or sets the number of the Output object.
Singleton version of the PacDrive class found in the PacDrive SDK.
override void Finish()
Finishes the PacDrive object. Finish does also terminate the workerthread.
static void Write(string Message)
Writes the specified message to the logfile.
A simple logger used to record important events and exceptions.
PacDrive()
Initializes a new instance of the PacDriveInstance class.
override void Init(Cabinet Cabinet)
Initializes the PacDrive object. This method does also start the workerthread which does the actual ...
PacRemovedDelegate OnPacRemoved
Common interface for outputs of any output controller. The Output class implements this interface and...
Abstract OutputController base class to be used for IOutputController implementations. Implements IOutputController.
The PacDrive is a simple output controller with 16 digital/on off outputs.
Common interface for all outputcontrollers. Only classes implementing this interface can be used as o...
bool PacDriveUHIDSetLEDStates(int Index, ushort Data)
PacAttachedDelegate OnPacAttached
int PacDriveGetIndex()
Gets the Ids of the first PacDrive controller which is connected to the system.
override void OnOutputValueChanged(IOutput Output)
This method is called whenever the value of a output in the Outputs property changes its value...
The namespace DirectOutput.General contains classes for general use.
static PacDriveSingleton Instance
Basic IOutput implementation.