loupiottes/DMX-2.0/DriverBoitierV1.cs

242 lines
4.8 KiB
C#

using System;
using System.Threading;
using System.IO.Ports;
namespace DMX2
{
public class DriverBoitierV1 : DriverDMX, IEventProvider
{
struct buttonState {
public buttonState(byte _button, bool _pressed){
button=_button; pressed=_pressed;
}
public byte button;
public bool pressed;
}
bool[] buttons = new bool[8];
bool[] watchButtons = new bool[8];
// tampons Entrée/Sortie
byte[] inputbuffer = new byte[1];
byte[] outputbuffer = new byte[260];
//Thread de boucle
Thread loopthread=null;
volatile bool running=true;
UniversDMX patch=null;
string portname = "/dev/ttyUSB0";
SerialPort serial = null;
public DriverBoitierV1 (string serialport, string id): base(id)
{
//patch = Conduite.Courante.Patches[0];
//Start();
//serial = serialport;
outputbuffer[0]=27;
outputbuffer[1]=68;
outputbuffer[4]=255;
}
void Start ()
{
OpenPort();
if (loopthread == null) {
loopthread = new Thread(new ThreadStart(MainLoop));
loopthread.Start();
}
}
void OpenPort ()
{
if (serial != null) {
serial.Close();
}
serial = new SerialPort(portname, 460800,Parity.None,8,StopBits.One);
serial.DtrEnable = false;
serial.ReadTimeout = 15;
serial.WriteTimeout = 200;
serial.Open();
}
bool CheckPortStatus ()
{
if(serial.IsOpen) return true;
OpenPort();
return false;
}
void MainLoop ()
{
DateTime prochainEnvoi= DateTime.Now;
TimeSpan sleeptime;
while (running) {
lock(Conduite.Courante)
{
patch.CalculUnivers(outputbuffer,5,255);
}
if(!CheckPortStatus())
{
Thread.Sleep(1000);
continue;
}
sleeptime = prochainEnvoi - DateTime.Now;
if(sleeptime.TotalMilliseconds>1)
Thread.Sleep(sleeptime);
prochainEnvoi = DateTime.Now.AddMilliseconds(22);
Envoi();
Reception();
}
}
void Envoi ()
{
try {
if(!serial.IsOpen) return;
serial.Write(outputbuffer,0,outputbuffer.Length);
} catch (TimeoutException ex) {
serial.Close();
}
}
void Reception ()
{
try {
if(!serial.IsOpen) return;
serial.Read(inputbuffer,0,inputbuffer.Length);
//Console.WriteLine(inputbuffer[0]);
ProcessInput();
} catch (TimeoutException ex) {
serial.Close();
}
}
void ProcessInput ()
{
byte b = 1; bool pressed;
for (byte i = 0; i<8; i++) {
if(!watchButtons[i]) continue;
pressed = (inputbuffer[0] & b) != 0;
if(buttons[i]^pressed)
{
eventsPending.Enqueue(new buttonState(i,pressed));
buttons[i] = pressed;
}
b <<= 1;
}
}
public override void Dispose ()
{
disposed = true;
running = false;
if (loopthread != null) {
loopthread.Join ();
loopthread = null;
}
//TODO : Close Port
if(serial != null)
serial.Close();
}
#region implemented abstract members of DMX2.DriverDMX
public override Gtk.Widget GetUI ()
{
return new DriverBoitierV1UI(this);
}
#endregion
#region IEventProvider implementation
static System.Text.RegularExpressions.Regex regexEventID = new System.Text.RegularExpressions.Regex(
@"BV1-B(?<button>\d+)?",
System.Text.RegularExpressions.RegexOptions.Compiled);
System.Collections.Concurrent.ConcurrentQueue<buttonState> eventsPending =
new System.Collections.Concurrent.ConcurrentQueue<buttonState>();
bool IEventProvider.Bind (string eventId)
{
var res = regexEventID.Match (eventId);
if (res.Success) {
int bt = int.Parse (res.Groups ["button"].Value);
if(bt<0||bt>7) return false;
watchButtons[bt] = true;
return true;
}
return false;
}
void IEventProvider.Unbind (string eventId)
{
var res = regexEventID.Match (eventId);
if (res.Success) {
int bt = int.Parse (res.Groups ["button"].Value);
if(bt<0||bt>7) return ;
watchButtons[bt] = false;
}
return;
}
Gtk.Menu IEventProvider.GetProviderSubMenu (EventManager.EventMenuData state, Gtk.ButtonPressEventHandler handler)
{
Gtk.Menu retmenu = new Gtk.Menu ();
Gtk.MenuItem evmenuitem = new Gtk.MenuItem ("Boutons");
retmenu.Add (evmenuitem);
Gtk.Menu evmenu = new Gtk.Menu ();
evmenuitem.Submenu = evmenu;
for (int i= 0; i<8;i++ ) {
Gtk.MenuItem item = new Gtk.MenuItem(string.Format("Bouton {0}",i+1));
item.Data[EventManager.EventIdKey] = string.Format("BV1-B{0}",i);
item.Data[EventManager.StateKey] = state;
item.ButtonPressEvent += handler;
evmenu.Add (item);
}
return retmenu;
}
void IEventProvider.ProcessEvents (EventManagerCallback callback)
{
buttonState bt;
EventData evd;
while (eventsPending.TryDequeue(out bt)) {
evd.id= string.Format("BV1-B{0}",bt.button );
evd.value = bt.pressed?(byte)0xFF:(byte)0x00;
callback(evd);
}
}
string IEventProvider.MenuName {
get {
return "Boitier V1";
}
}
#endregion
}
}