diff --git a/DMX-2.0/DMX-2.0.csproj b/DMX-2.0/DMX-2.0.csproj index b599606..e7afef6 100644 --- a/DMX-2.0/DMX-2.0.csproj +++ b/DMX-2.0/DMX-2.0.csproj @@ -18,7 +18,6 @@ DEBUG; prompt 4 - false true fullscreen aguibtn @@ -28,7 +27,6 @@ bin\Release prompt 4 - x86 false diff --git a/DMX-2.0/EventManager.cs b/DMX-2.0/EventManager.cs index 4580d8f..9ad801a 100644 --- a/DMX-2.0/EventManager.cs +++ b/DMX-2.0/EventManager.cs @@ -4,39 +4,85 @@ using System.Linq; namespace DMX2 { - + /// + /// Event data : Objet passé aux cibles d'evenements + /// public struct EventData { public string id; public byte value; } - + /// + /// Interface pour les fournisseurs d'evenements + /// public interface IEventProvider { + /// + /// Renvoie le nom du sous menu associé au fournisseur d'evenements. + /// + /// + /// Le nom du menu. + /// string MenuName{ get; } - //ICollection GetEventList(); + + /// Demande au fournisseur de signaler l'evenement spécifié + /// L'id de l'evenement. + /// true si le fournisseur reconnais l'id bool Bind (string eventId); + + /// Signale au fournisseur que l'evenement n'est plus attendu + /// L'id de l'evenement. void Unbind (string eventId); + + /// Demande la construction du sous-menu evenement au fournisseur + /// Le sous menu + /// Un objet qui sera devra etre stocké dans Data[EventManager.StateKey] + /// La delegate qui devra etre associée aux ButtonClickedEvent Gtk.Menu GetProviderSubMenu( EventManager.EventMenuData state, Gtk.ButtonPressEventHandler handler ); + + /// Appelé par le Timer de la conduite + /// Fonction a appeler pour chaque evenement. void ProcessEvents(EventManagerCallback callback); } + /// + /// Interface pour les recepteurs d'evenements. + /// public interface IEventTarget { + /// Fonction appelée lors d'un evenement + /// Vrai si l'evenement est traité + /// Evenement bool FireEvent(EventData data); + + /// Indique a la cible qu'on lui associe un evenement + /// l'id de l'evenement void Bind(string id); + + /// Indique a la cible qu'on lui des associe un evenement + /// l'id de l'evenement void Unbind(string id); - IEnumerable IDs { get; } + } + /// + /// Callback sur evenement. + /// public delegate void EventManagerCallback(EventData data); + + + /// + /// Callback appele sur clic sur un bouton de menu de choix d'evenement + /// public delegate void EventManagerMenuCallBack(object state, string eventId); + /// + /// Cible generique d'evenement. + /// public class actionEventTarget : IEventTarget { public delegate bool EventAction (EventData data); EventAction action; - List eventIds = new List(); public actionEventTarget(EventAction _action) { action=_action; @@ -47,30 +93,17 @@ namespace DMX2 return action(data); } - void IEventTarget.Bind (string id) - { - if(!eventIds.Contains(id)) - eventIds.Add(id); - } + void IEventTarget.Bind (string id){} // Rien a faire ici + void IEventTarget.Unbind (string id){} - void IEventTarget.Unbind (string id) - { - eventIds.Remove(id); - } - - IEnumerable IEventTarget.IDs { - get { - return eventIds; - } - } #endregion } public class EventManager { - static public object StateKey = new object(); - static public object EventIdKey = new object(); + Dictionary bindings = new Dictionary(); + List providers = new List(); class eventBinding { @@ -91,9 +124,6 @@ namespace DMX2 } } - Dictionary bindings = new Dictionary(); - List providers = new List(); - public EventManager () { @@ -102,15 +132,20 @@ namespace DMX2 public void RegisterProvider (IEventProvider prov) { providers.Add (prov); - - } +#region Menus + // Cles pour association d'etat au elements de menu + static public object StateKey = new object(); + static public object EventIdKey = new object(); + + // Objet associe aux menus afin de pourvoir retransmettre les infos au createur du menu public class EventMenuData { public EventManagerMenuCallBack CallBack; public object state; } + /// Appelé par l'interface. L'objet 'state' sera retransmis tel quel lors de l'appel au callback public Gtk.Menu GetMenu (object state, EventManagerMenuCallBack callback) { Gtk.Menu menu = new Gtk.Menu (); @@ -126,6 +161,7 @@ namespace DMX2 if(provitem.Submenu!=null) menu.Add(provitem); } + // Creation de l'element 'Aucun' retournant un ID vide, pour permettre la desassociation Gtk.MenuItem itemNone = new Gtk.MenuItem("Aucun"); itemNone.Data[StateKey] = evd; itemNone.Data[EventIdKey] = ""; @@ -136,14 +172,17 @@ namespace DMX2 } + /// Traitement du clic sur les menus generes au dessus void HandleButtonPressEvent (object o, Gtk.ButtonPressEventArgs args) { Gtk.MenuItem item = o as Gtk.MenuItem; - EventMenuData evd = item.Data[EventManager.StateKey] as EventMenuData; - string id = item.Data[EventManager.EventIdKey] as string; - evd.CallBack(evd.state,id); + EventMenuData evd = item.Data[EventManager.StateKey] as EventMenuData; // On récupere l'objet d'etat et la fonction a rappeler + string id = item.Data[EventManager.EventIdKey] as string; // ainsi que l'id evenement + evd.CallBack(evd.state,id); // Appel de la fonction } +#endregion + /// Appelé par le Timer de la conduite ... appel le traitement pour l'ensemble des fournisseurs public void ProcessEvents () { foreach (IEventProvider prov in providers) { @@ -156,6 +195,7 @@ namespace DMX2 providers.Remove(prov); } + /// Enregistrement d'une association id => cible public bool Bind (string eventId, IEventTarget target) { if(!bindings.ContainsKey(eventId)) @@ -168,6 +208,7 @@ namespace DMX2 return false; } + /// Desenregistrement de toutes les associations d'une cible public void Unbind (IEventTarget target) { var q = from bind in bindings where bind.Value.Targets.Contains(target) select bind.Key; @@ -175,7 +216,7 @@ namespace DMX2 Unbind(id,target); } - + /// Desenregistrement d'une association id => cible public void Unbind (string eventId, IEventTarget target) { if (!bindings.ContainsKey (eventId)) return; @@ -190,6 +231,7 @@ namespace DMX2 target.Unbind(eventId); } + /// Fonction appelee sur evenement public void EventCallBack (EventData data) { Console.WriteLine("Event {0} => {1}",data.id,data.value); @@ -197,14 +239,18 @@ namespace DMX2 foreach (IEventTarget target in bindings[data.id].Targets) { target.FireEvent(data); } - } + } } - public static bool SaveBindings (System.Xml.XmlElement xmlParent, IEventTarget target) + public bool SaveBindings (System.Xml.XmlElement xmlParent, IEventTarget target) { bool ret=false; System.Xml.XmlElement xmlB; - foreach (string id in target.IDs) { + var q = from bind in bindings + where bind.Value.Targets.Contains(target) + select bind.Key; + + foreach (string id in q) { ret=true; xmlParent.AppendChild(xmlB = xmlParent.OwnerDocument.CreateElement("EventBinding")); xmlB.SetAttribute("id",id); diff --git a/DMX-2.0/MidiEventProvider.cs b/DMX-2.0/MidiEventProvider.cs index bb3a110..814d67f 100644 --- a/DMX-2.0/MidiEventProvider.cs +++ b/DMX-2.0/MidiEventProvider.cs @@ -7,6 +7,10 @@ namespace DMX2 { public partial class MidiEventProvider : IEventProvider { + + /// + /// Classe pour contenir et gérer un unique Handle d'acces au sequenceur midi Alsa. + /// public class MidiSeqHandle : IDisposable { static MidiSeqHandle singleton = new MidiSeqHandle(); @@ -18,7 +22,7 @@ namespace DMX2 } } - public MidiSeqHandle(){ + MidiSeqHandle(){ snd_seq_open(out midi_seq_handle, "default",SND_SEQ_OPEN_DUPLEX,0); snd_seq_set_client_name(midi_seq_handle,"DMX2"); snd_seq_create_simple_port(midi_seq_handle,"dmx_ctrl", @@ -27,13 +31,16 @@ namespace DMX2 } #region IDisposable implementation - public void Dispose () + void IDisposable.Dispose () { if(midi_seq_handle != IntPtr.Zero) snd_seq_close(midi_seq_handle); midi_seq_handle = IntPtr.Zero; } #endregion + ~MidiSeqHandle(){ + ((IDisposable)this).Dispose (); + } } @@ -47,8 +54,10 @@ namespace DMX2 } } - Dictionary eventlist = new Dictionary(); + EventData last; + internalEvent levent=null; + bool connected=false; public MidiEventProvider (EventManager manager) { @@ -56,27 +65,24 @@ namespace DMX2 } #region IEventProvider implementation - /*ICollection IEventProvider.GetEventList () - { - return eventlist.Keys; - }*/ bool IEventProvider.Bind (string eventId) { + // On indique a l'EventManager qu'on traite, si l'ID commence par 'MIDI-' return eventId.StartsWith("MIDI-"); } void IEventProvider.Unbind (string eventId) { - return; } Gtk.Menu IEventProvider.GetProviderSubMenu (EventManager.EventMenuData state, Gtk.ButtonPressEventHandler handler) { - if(!connected) return null; + if(!connected) return null; // Si pas encore recu d'evenements => pas de menu Gtk.Menu retmenu = new Gtk.Menu (); - if (levent != null) { + + if (levent != null) { // Creation du sous menu "Dernier" Gtk.MenuItem lmenuitem = new Gtk.MenuItem ("Dernier"); retmenu.Add (lmenuitem); Gtk.Menu lmenu = new Gtk.Menu (); @@ -87,13 +93,14 @@ namespace DMX2 item.ButtonPressEvent += handler; lmenu.Add (item); } - Gtk.MenuItem evmenuitem = new Gtk.MenuItem ("Events"); + + Gtk.MenuItem evmenuitem = new Gtk.MenuItem ("Events"); // Creation du sous menu "Events" retmenu.Add (evmenuitem); Gtk.Menu evmenu = new Gtk.Menu (); evmenuitem.Submenu = evmenu; - List sortedKeys = eventlist.Keys.ToList(); - sortedKeys.Sort(); + List sortedKeys = eventlist.Keys.ToList(); // On recupere des IDs + sortedKeys.Sort(); // et on les trie foreach ( string key in sortedKeys ) { internalEvent evt= eventlist[key]; @@ -108,27 +115,26 @@ namespace DMX2 } - EventData last; internalEvent levent=null; - bool connected=false; - void IEventProvider.ProcessEvents (EventManagerCallback callback) { - IntPtr evPtr; + IntPtr evPtr; // Pointeur vers la structure non managée alsa-seq + + // Tant qu'il y des evenements midi en attente while ((snd_seq_event_input_pending(MidiSeqHandle.Handle,1))>0) { - snd_seq_event_input(MidiSeqHandle.Handle, out evPtr); - snd_seq_event_t evS =(snd_seq_event_t) Marshal.PtrToStructure(evPtr,typeof(snd_seq_event_t)); - snd_seq_free_event(evPtr); + snd_seq_event_input(MidiSeqHandle.Handle, out evPtr); // Recup du pointeur vers l'ev + snd_seq_event_t evS =(snd_seq_event_t) Marshal.PtrToStructure(evPtr,typeof(snd_seq_event_t)); // Copie de la zone mémoire dans une structure managee + snd_seq_free_event(evPtr); // liberation du pointeur string id=null, description=null; int value=0; switch (evS.type) { - case snd_seq_event_type_t.SND_SEQ_EVENT_PORT_SUBSCRIBED: + case snd_seq_event_type_t.SND_SEQ_EVENT_PORT_SUBSCRIBED: // Connection d'un périph midi connected = true; continue; case snd_seq_event_type_t.SND_SEQ_EVENT_CONTROLLER: id= string.Format("MIDI-CTRL-C{0}P{1}",evS.data_ev_ctrl.channel,evS.data_ev_ctrl.param); description = string.Format("Controller Ch {0} Param {1}",evS.data_ev_ctrl.channel,evS.data_ev_ctrl.param); - value = 255 * evS.data_ev_ctrl.value / 127; + value = 255 * evS.data_ev_ctrl.value / 127; // Conversion {0,127} => {0,255} break; case snd_seq_event_type_t.SND_SEQ_EVENT_NOTEON: id= string.Format("MIDI-NOTE-C{0}N{1}",evS.data_ev_note.channel, evS.data_ev_note.note ); @@ -147,24 +153,28 @@ namespace DMX2 //TODO : Regarder si d'autres controles interessants. default: id= null; - Info.Publish(string.Format ("event {0}", evS.type) ); +#if DEBUG + Info.Publish(string.Format ("event {0}", evS.type) ); // On affiche les evenements inconnus +#endif continue; } + connected=true; + if(id!=null) { if(!eventlist.ContainsKey(id)) eventlist.Add(id,new internalEvent(id,description)); - levent= eventlist[id]; - EventData evData = new EventData(); + levent= eventlist[id]; //Dernier Evenement recu conserve pour menu + EventData evData = new EventData(); evData.id = id; evData.value = (byte)value; - if(evData.Equals(last)) continue; + + if(evData.Equals(last)) continue; // On ignore les evenements répétés à l'identique + callback(evData); last = evData; } - - } } @@ -175,9 +185,6 @@ namespace DMX2 } #endregion - - - } } diff --git a/DMX-2.0/Sequenceur.cs b/DMX-2.0/Sequenceur.cs index ef8334c..32f6c10 100644 --- a/DMX-2.0/Sequenceur.cs +++ b/DMX-2.0/Sequenceur.cs @@ -54,7 +54,9 @@ namespace DMX2 public abstract SequenceurUI GetUI(); public abstract int ValeurCircuit(Circuit c); + public abstract void Tick(TimeSpan time); + public static Sequenceur Load (Conduite conduite, XmlElement el) { switch (el.Name) { @@ -66,10 +68,6 @@ namespace DMX2 return null; } - /*public virtual void MajCircuitsSupprimes() - { - }*/ - public abstract void Save (XmlElement parent); public abstract void Command (string command); diff --git a/DMX-2.0/SequenceurLineaire.cs b/DMX-2.0/SequenceurLineaire.cs index 30d4890..a3b0a16 100644 --- a/DMX-2.0/SequenceurLineaire.cs +++ b/DMX-2.0/SequenceurLineaire.cs @@ -152,11 +152,11 @@ namespace DMX2 valeursrecues.Remove(id); } - IEnumerable IEventTarget.IDs { + /*IEnumerable IEventTarget.IDs { get { return valeursrecues.Keys; } - } + }*/ } @@ -531,20 +531,20 @@ namespace DMX2 el.AppendChild(xmlEl = parent.OwnerDocument.CreateElement ("Master")); xmlEl.SetAttribute("value",master.ToString()); - EventManager.SaveBindings(xmlEl,masterEventTarget); + Conduite.Courante.EventManager.SaveBindings(xmlEl,masterEventTarget); xmlEl = parent.OwnerDocument.CreateElement ("EffetSuivant"); - if(EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl); + if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl); xmlEl = parent.OwnerDocument.CreateElement ("EffetPrecedent"); - if(EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl); + if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl); foreach (Circuit c in circuitsSeq) { el.AppendChild(xmlEl = parent.OwnerDocument.CreateElement ("CircuitSeq")); xmlEl.SetAttribute("id",c.ID.ToString()); if(targets.ContainsKey(c)) - EventManager.SaveBindings(xmlEl,targets[c]); + Conduite.Courante.EventManager.SaveBindings(xmlEl,targets[c]); } diff --git a/DMX-2.0/SequenceurMacro.cs b/DMX-2.0/SequenceurMacro.cs index bb4ac4d..c436fb0 100644 --- a/DMX-2.0/SequenceurMacro.cs +++ b/DMX-2.0/SequenceurMacro.cs @@ -439,13 +439,13 @@ namespace DMX2 el.AppendChild(xmlEl = parent.OwnerDocument.CreateElement ("Master")); xmlEl.SetAttribute("value",master.ToString()); - EventManager.SaveBindings(xmlEl,masterEventTarget); + Conduite.Courante.EventManager.SaveBindings(xmlEl,masterEventTarget); xmlEl = parent.OwnerDocument.CreateElement ("EffetSuivant"); - if(EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl); + if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl); xmlEl = parent.OwnerDocument.CreateElement ("EffetPrecedent"); - if(EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl); + if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl); foreach (Circuit c in circuitsSeq) { el.AppendChild(xmlEl = parent.OwnerDocument.CreateElement ("CircuitSeq")); diff --git a/DMX-2.0/SequenceurMaitre.cs b/DMX-2.0/SequenceurMaitre.cs index e468420..c009e15 100644 --- a/DMX-2.0/SequenceurMaitre.cs +++ b/DMX-2.0/SequenceurMaitre.cs @@ -268,10 +268,10 @@ namespace DMX2 l.Save(el); XmlElement xmlEl = parent.OwnerDocument.CreateElement ("EffetSuivant"); - if(EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl); + if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goNextEventTarget )) el.AppendChild(xmlEl); xmlEl = parent.OwnerDocument.CreateElement ("EffetPrecedent"); - if(EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl); + if(Conduite.Courante.EventManager.SaveBindings(xmlEl,goBackEventTarget )) el.AppendChild(xmlEl); } diff --git a/DMX-2.0/UniversDMX.cs b/DMX-2.0/UniversDMX.cs index 6f85421..60ed20e 100644 --- a/DMX-2.0/UniversDMX.cs +++ b/DMX-2.0/UniversDMX.cs @@ -5,8 +5,20 @@ using System.Xml; namespace DMX2 { + /// + /// Univers DMX. + /// Chaque univers DMX représente un patch des circuits virtuels sur 512 dimmers DMX + /// public class UniversDMX { + /// structure indiquant le mode de calcul d'un octet sur la tramme DMX + public struct Dimmer { + public Circuit circuitAssocié; + public FTransfer fonctionTransfert; + public float param1; // Paramètres pour fonction de transfert + public float param2; + } + public static int maxid=1; @@ -32,6 +44,7 @@ namespace DMX2 return allumageForce; } } + public string Nom; public enum FTransfer { lineaire, @@ -39,13 +52,6 @@ namespace DMX2 exp } - public struct Dimmer { - public Circuit circuitAssocié; - public FTransfer fonctionTransfert; - public float param1; // Paramètres pour fonction de transfert - public float param2; - } - public Dimmer[] Dimmers { get { @@ -53,7 +59,10 @@ namespace DMX2 } } - + /// Calcule la trame DMX + /// tampon pour le stockage de la trame calculée + /// Offset de début de trame dans le tampon + /// Nombre d'octets a calculer public void CalculUnivers(byte[] valeurs, int offset, int count) { Dimmer g; @@ -72,8 +81,10 @@ namespace DMX2 valeurs[i+offset] = (byte)( g.circuitAssocié.ValeurCourante * g.param1 /100); break; case FTransfer.log: + // TODO : Ft Log break; case FTransfer.exp: + // TODO : Ft Exp break; default: throw new ArgumentOutOfRangeException ();