/*
Copyright (C) Arnaud Houdelette 2012-2014
Copyright (C) Emmanuel Langlois 2012-2014
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
using System;
using System.Threading;
using System.IO.Ports;
using System.Xml;
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;
}
enum etatAutomate {
Deconnecte,
Transmission,
Erreur,
Reset,
Parametrage,
Fin
}
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;
public UniversDMX patch=null;
string portname = "";
SerialPort serial = null;
public DriverBoitierV1 (string serialport, string id): base(id)
{
portname = serialport;
Start();
//serial = serialport;
outputbuffer[0]=27;
outputbuffer[1]=68;
outputbuffer[4]=255;
}
void Start ()
{
if (loopthread == null) {
loopthread = new Thread(new ThreadStart(MainLoop));
loopthread.Start();
}
}
void Connection ()
{
#if DEBUG
Console.WriteLine ("DriverV1.Connection()");
#endif
if (serial != null) {
serial.Close();
serial.Dispose();
serial = null;
}
if (!System.IO.File.Exists (portname)) {
Thread.Sleep (200);
return;
}
serial = new SerialPort(portname, 460800,Parity.None,8,StopBits.One);
serial.DtrEnable = false;
serial.ReadTimeout = 15;
serial.WriteTimeout = 200;
serial.Open();
etat = etatAutomate.Transmission;
}
volatile etatAutomate etat = etatAutomate.Deconnecte;
DateTime finAttente = DateTime.Now;
void MainLoop()
{
while(!disposed && etat != etatAutomate.Fin)
{
switch (etat) {
case etatAutomate.Deconnecte:
Connection();
Attente(DateTime.Now.AddMilliseconds(200));
break;
case etatAutomate.Transmission:
finAttente = DateTime.Now.AddMilliseconds (22);
EnvoiTrame();
Reception();
Attente(finAttente);
break;
case etatAutomate.Erreur:
Deconnecte();
Attente(DateTime.Now.AddSeconds(2));
break;
// case etatAutomate.Parametrage:
// EnvoiParam();
// break;
// case etatAutomate.Reset:
// EnvoiReset();
// break;
}
}
Deconnecte();
}
void Attente (DateTime date)
{
int sleeptime = (int) (date - DateTime.Now).TotalMilliseconds;
if(sleeptime>2)
Thread.Sleep(sleeptime);
while (DateTime.Now\d+)?",
System.Text.RegularExpressions.RegexOptions.Compiled);
System.Collections.Concurrent.ConcurrentQueue eventsPending =
new System.Collections.Concurrent.ConcurrentQueue();
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;
evd.prev_value = (!bt.pressed)?(byte)0xFF:(byte)0x00;
callback(evd);
}
}
string IEventProvider.MenuName {
get {
return "Boitier V1";
}
}
IFeedbackInfo IEventProvider.GetFeedbackInfo (string eventId)
{
return null;
}
#endregion
#region implemented abstract members of DMX2.DriverDMX
public override void Save (System.Xml.XmlElement parent)
{
System.Xml.XmlElement el = parent.OwnerDocument.CreateElement ("DriverBoitierV1");
parent.AppendChild (el);
el.SetAttribute ("portname", portname.ToString ());
el.SetAttribute ("id", ID);
if(patch!=null) el.SetAttribute ("univers", patch.Nom);
}
#endregion
public static new DriverDMX Load(Conduite conduite, XmlElement el) {
//System.Xml.XmlElement xmlE;
string port = el.GetAttribute("portname");
if(! System.IO.File.Exists(port)) return null;
string id = el.GetAttribute("id");
DriverBoitierV1 drv = new DriverBoitierV1(port,id);
if(el.HasAttribute("univers"))
{
string univ = el.GetAttribute("univers");
foreach (UniversDMX u in conduite.Patches){
if(u.Nom== univ){
drv.patch = u;
break;
}
}
}
return drv;
}
}
}