Gestion des evenements Midi
This commit is contained in:
parent
55b06fe771
commit
3fc814731f
7 changed files with 298 additions and 36 deletions
|
|
@ -41,7 +41,7 @@ namespace DMX2
|
|||
Pause = false;
|
||||
|
||||
|
||||
midip = new MidiEventProvider();
|
||||
midip = new MidiEventProvider(eventManager);
|
||||
}
|
||||
|
||||
EventManager eventManager = new EventManager();
|
||||
|
|
@ -175,8 +175,6 @@ namespace DMX2
|
|||
TimeSpan deltaT = tickTime - dernierTick;
|
||||
dernierTick = tickTime;
|
||||
|
||||
midip.Process();
|
||||
|
||||
if (!Pause) {
|
||||
|
||||
/* if (deltaT > TimeSpan.FromMilliseconds (15))
|
||||
|
|
@ -212,6 +210,8 @@ namespace DMX2
|
|||
// Cette fonction retourne quasi immédiatement, même si il y'a beaucoup a faire sur l'affichage
|
||||
}
|
||||
|
||||
EventManager.ProcessEvents();
|
||||
|
||||
if(tickTime - derniereMaj > TimeSpan.FromMilliseconds(50)){
|
||||
MainWindow.Win.ScheduleUpdate();
|
||||
derniereMaj = DateTime.Now;
|
||||
|
|
|
|||
90
DMX-2.0/ContextMenuHelper.cs
Normal file
90
DMX-2.0/ContextMenuHelper.cs
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using Gdk;
|
||||
using GLib;
|
||||
using Gtk;
|
||||
|
||||
namespace DMX2
|
||||
{
|
||||
public class ContextMenuEventArgs : EventArgs
|
||||
{
|
||||
private Widget widget;
|
||||
|
||||
public Widget Widget { get { return widget; } }
|
||||
|
||||
private bool rightClick;
|
||||
|
||||
public bool RightClick { get { return rightClick; } }
|
||||
|
||||
public ContextMenuEventArgs (Widget widget, bool rightClick)
|
||||
{
|
||||
this.widget = widget;
|
||||
this.rightClick = rightClick;
|
||||
}
|
||||
}
|
||||
|
||||
public class ContextMenuHelper
|
||||
{
|
||||
public event EventHandler<ContextMenuEventArgs> ContextMenu;
|
||||
|
||||
public ContextMenuHelper ()
|
||||
{
|
||||
}
|
||||
|
||||
public ContextMenuHelper (Widget widget)
|
||||
{
|
||||
AttachToWidget (widget);
|
||||
}
|
||||
|
||||
public ContextMenuHelper (Widget widget, EventHandler<ContextMenuEventArgs> handler)
|
||||
{
|
||||
AttachToWidget (widget);
|
||||
ContextMenu += handler;
|
||||
}
|
||||
|
||||
public void AttachToWidget (Widget widget)
|
||||
{
|
||||
widget.PopupMenu += Widget_PopupMenu;
|
||||
widget.ButtonPressEvent += Widget_ButtonPressEvent;
|
||||
}
|
||||
|
||||
public void DetachFromWidget (Widget widget)
|
||||
{
|
||||
widget.PopupMenu -= Widget_PopupMenu;
|
||||
widget.ButtonPressEvent -= Widget_ButtonPressEvent;
|
||||
}
|
||||
|
||||
[GLib.ConnectBefore]
|
||||
private void Widget_PopupMenu (object o, PopupMenuArgs args)
|
||||
{
|
||||
RaiseContextMenuEvent (args, (Widget)o, false);
|
||||
}
|
||||
|
||||
[GLib.ConnectBefore]
|
||||
private void Widget_ButtonPressEvent (object o, ButtonPressEventArgs args)
|
||||
{
|
||||
if (args.Event.Button == 3 && args.Event.Type == EventType.ButtonPress) {
|
||||
RaiseContextMenuEvent (args, (Widget)o, true);
|
||||
}
|
||||
}
|
||||
|
||||
private bool propagating = false; //Prevent reentry
|
||||
|
||||
private void RaiseContextMenuEvent (SignalArgs signalArgs, Widget widget, bool rightClick)
|
||||
{
|
||||
if (!propagating) {
|
||||
//Propagate the event
|
||||
Event evnt = Gtk.Global.CurrentEvent;
|
||||
propagating = true;
|
||||
Gtk.Global.PropagateEvent (widget, evnt);
|
||||
propagating = false;
|
||||
signalArgs.RetVal = true; //The widget already processed the event in the propagation
|
||||
|
||||
//Raise the context menu event
|
||||
ContextMenuEventArgs args = new ContextMenuEventArgs (widget, rightClick);
|
||||
if (ContextMenu != null) {
|
||||
ContextMenu.Invoke (this, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -105,6 +105,7 @@
|
|||
<Compile Include="EventManager.cs" />
|
||||
<Compile Include="MidiEventProvider.cs" />
|
||||
<Compile Include="MidiEventProvider.PInvoke.cs" />
|
||||
<Compile Include="ContextMenuHelper.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<ProjectExtensions>
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@ namespace DMX2
|
|||
public interface IEventProvider
|
||||
{
|
||||
string MenuName{ get; }
|
||||
string[] GetEventList();
|
||||
ICollection<string> GetEventList();
|
||||
bool Bind (string eventId, IEventTarget target);
|
||||
void Unbind (string eventId, IEventTarget target);
|
||||
Gtk.Menu GetProviderSubMenu( Gtk.ButtonPressEventHandler handler );
|
||||
Gtk.Menu GetProviderSubMenu( EventManager.EventMenuData state, Gtk.ButtonPressEventHandler handler );
|
||||
void ProcessEvents();
|
||||
}
|
||||
|
||||
public interface IEventTarget
|
||||
|
|
@ -26,6 +27,9 @@ namespace DMX2
|
|||
|
||||
public class EventManager
|
||||
{
|
||||
static public object StateKey = new object();
|
||||
static public object EventIdKey = new object();
|
||||
|
||||
class eventBinding
|
||||
{
|
||||
private eventBinding(){}
|
||||
|
|
@ -51,28 +55,57 @@ namespace DMX2
|
|||
{
|
||||
providers.Add (prov);
|
||||
|
||||
List<string> evList = new List<string>(prov.GetEventList());
|
||||
//List<string> evList = new List<string>(prov.GetEventList());
|
||||
|
||||
foreach (eventBinding b in bindings) {
|
||||
if(b.provider == null && evList.Contains(b.id))
|
||||
if(b.provider == null)
|
||||
{
|
||||
prov.Bind(b.id,b.target);
|
||||
b.provider = prov;
|
||||
if(prov.Bind(b.id,b.target))
|
||||
b.provider = prov;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Gtk.Menu GetMenu ( Gtk.ButtonPressEventHandler handler )
|
||||
{
|
||||
Gtk.Menu menu = new Gtk.Menu();
|
||||
public delegate void EventMenuCallBack(object state, string eventId);
|
||||
public class EventMenuData {
|
||||
public EventMenuCallBack CallBack;
|
||||
public object state;
|
||||
}
|
||||
|
||||
public Gtk.Menu GetMenu (object state, EventMenuCallBack callback)
|
||||
{
|
||||
Gtk.Menu menu = new Gtk.Menu ();
|
||||
EventMenuData evd = new EventMenuData();
|
||||
evd.CallBack = callback;
|
||||
evd.state = state;
|
||||
|
||||
Gtk.ButtonPressEventHandler handler = new Gtk.ButtonPressEventHandler (HandleButtonPressEvent);
|
||||
|
||||
foreach (IEventProvider prov in providers) {
|
||||
Gtk.MenuItem provitem = new Gtk.MenuItem(prov.MenuName);
|
||||
provitem.Submenu = prov.GetProviderSubMenu(evd, handler);
|
||||
menu.Add(provitem);
|
||||
}
|
||||
|
||||
return menu;
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public void ProcessEvents ()
|
||||
{
|
||||
foreach (IEventProvider prov in providers) {
|
||||
prov.ProcessEvents();
|
||||
}
|
||||
}
|
||||
|
||||
public void UnregisterProvider (IEventProvider prov)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,36 +1,53 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DMX2
|
||||
{
|
||||
public partial class MidiEventProvider : IEventProvider, IDisposable
|
||||
{
|
||||
|
||||
IntPtr midi_seq_handle = IntPtr.Zero;
|
||||
int midiport;
|
||||
class internalEvent {
|
||||
public string internalName;
|
||||
public string description;
|
||||
List<IEventTarget> boundTargets=null;
|
||||
|
||||
public MidiEventProvider ()
|
||||
public internalEvent(string _id, string _desc)
|
||||
{
|
||||
internalName=_id;
|
||||
description=_desc;
|
||||
}
|
||||
public bool HasTargets {
|
||||
get {
|
||||
return boundTargets==null?false:boundTargets.Count>0;
|
||||
}
|
||||
}
|
||||
public List<IEventTarget> BoundTargets {
|
||||
get {
|
||||
if(boundTargets==null) boundTargets = new List<IEventTarget>();
|
||||
return boundTargets;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dictionary<string,internalEvent> eventlist = new Dictionary<string, internalEvent>();
|
||||
|
||||
|
||||
|
||||
IntPtr midi_seq_handle = IntPtr.Zero;
|
||||
|
||||
|
||||
public MidiEventProvider (EventManager manager)
|
||||
{
|
||||
snd_seq_open(out midi_seq_handle, "default",SND_SEQ_OPEN_DUPLEX,0);
|
||||
snd_seq_set_client_name(midi_seq_handle,"DMX2");
|
||||
midiport = snd_seq_create_simple_port(midi_seq_handle,"dmx_ctrl",
|
||||
snd_seq_create_simple_port(midi_seq_handle,"dmx_ctrl",
|
||||
SND_SEQ_PORT_CAP_WRITE + SND_SEQ_PORT_CAP_SUBS_WRITE,
|
||||
SND_SEQ_PORT_TYPE_APPLICATION);
|
||||
|
||||
Info.Publish(string.Format("Midi port {0}",midiport));
|
||||
manager.RegisterProvider(this);
|
||||
}
|
||||
|
||||
public void Process ()
|
||||
{
|
||||
int i; IntPtr ev;
|
||||
while ((i = snd_seq_event_input_pending(midi_seq_handle,1))>0) {
|
||||
//Console.WriteLine(i);
|
||||
i=snd_seq_event_input(midi_seq_handle, out ev);
|
||||
snd_seq_event_t evS =(snd_seq_event_t) Marshal.PtrToStructure(ev,typeof(snd_seq_event_t));
|
||||
Info.Publish(string.Format ("event {0} {1}", evS.type, evS.data_ev_ctrl.value) );
|
||||
snd_seq_free_event(ev);
|
||||
}
|
||||
}
|
||||
|
||||
#region IDisposable implementation
|
||||
public void Dispose ()
|
||||
|
|
@ -39,33 +56,113 @@ namespace DMX2
|
|||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region IEventProvider implementation
|
||||
string[] IEventProvider.GetEventList ()
|
||||
ICollection<string> IEventProvider.GetEventList ()
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
return eventlist.Keys;
|
||||
}
|
||||
|
||||
bool IEventProvider.Bind (string eventId, IEventTarget target)
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
if (!eventlist.ContainsKey (eventId)) {
|
||||
// TODO : check if non received yet midi event...
|
||||
return false;
|
||||
}
|
||||
eventlist[eventId].BoundTargets.Add(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
void IEventProvider.Unbind (string eventId, IEventTarget target)
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
if (!eventlist.ContainsKey (eventId)) return;
|
||||
eventlist[eventId].BoundTargets.Remove(target);
|
||||
return;
|
||||
}
|
||||
|
||||
Gtk.Menu IEventProvider.GetProviderSubMenu (Gtk.ButtonPressEventHandler handler)
|
||||
Gtk.Menu IEventProvider.GetProviderSubMenu (EventManager.EventMenuData state, Gtk.ButtonPressEventHandler handler)
|
||||
{
|
||||
throw new System.NotImplementedException ();
|
||||
Gtk.Menu retmenu = new Gtk.Menu ();
|
||||
//Gtk.MenuItem evmenuitem = new Gtk.MenuItem ("Events");
|
||||
//retmenu.Add (evmenuitem);
|
||||
Gtk.Menu evmenu = retmenu ;// new Gtk.Menu ();
|
||||
//evmenuitem.Submenu = evmenu;
|
||||
|
||||
List<string> sortedKeys = new List<string>(eventlist.Keys);
|
||||
sortedKeys.Sort();
|
||||
|
||||
foreach ( string key in sortedKeys ) {
|
||||
internalEvent evt= eventlist[key];
|
||||
Gtk.MenuItem item = new Gtk.MenuItem(evt.description);
|
||||
item.Data[EventManager.EventIdKey] = evt.internalName;
|
||||
item.Data[EventManager.StateKey] = state;
|
||||
item.ButtonPressEvent += handler;
|
||||
evmenu.Add (item);
|
||||
}
|
||||
|
||||
return retmenu;
|
||||
|
||||
}
|
||||
|
||||
void IEventProvider.ProcessEvents ()
|
||||
{
|
||||
int ret; IntPtr evPtr;
|
||||
while ((ret = snd_seq_event_input_pending(midi_seq_handle,1))>0) {
|
||||
ret=snd_seq_event_input(midi_seq_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);
|
||||
|
||||
string id=null, description=null; int value=0;
|
||||
|
||||
switch (evS.type) {
|
||||
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;
|
||||
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 );
|
||||
description = string.Format("Note {1} Ch {0}",evS.data_ev_note.channel, evS.data_ev_note.note );
|
||||
value = 255 ;
|
||||
break;
|
||||
case snd_seq_event_type_t.SND_SEQ_EVENT_NOTEOFF:
|
||||
id= string.Format("MIDI-NOTE-C{0}N{1}",evS.data_ev_note.channel, evS.data_ev_note.note );
|
||||
description = string.Format("Note {1} Ch {0}",evS.data_ev_note.channel, evS.data_ev_note.note );
|
||||
value = 0;
|
||||
break;
|
||||
|
||||
//TODO : Regarder si d'autres controles interessants.
|
||||
default:
|
||||
id= null;
|
||||
Info.Publish(string.Format ("event {0}", evS.type) );
|
||||
break;
|
||||
}
|
||||
|
||||
if(id!=null)
|
||||
{
|
||||
if(!eventlist.ContainsKey(id))
|
||||
eventlist.Add(id,new internalEvent(id,description));
|
||||
else{
|
||||
if(eventlist[id].HasTargets)
|
||||
{
|
||||
EventData evData = new EventData();
|
||||
evData.id = id;
|
||||
evData.value = (byte)value;
|
||||
foreach( IEventTarget t in eventlist[id].BoundTargets)
|
||||
t.FireEvent(evData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
string IEventProvider.MenuName {
|
||||
get {
|
||||
throw new System.NotImplementedException ();
|
||||
return "Midi";
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ namespace DMX2
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void OnRenameItemButtonPressed (object o, ButtonPressEventArgs args)
|
||||
{
|
||||
var dlg = new Dialog ("Nouveau Nom ?", GetAncestor(Gtk.Window.GType) as Gtk.Window , DialogFlags.Modal); var entry = new Entry (sequenceur.Name);
|
||||
|
|
@ -241,6 +243,21 @@ namespace DMX2
|
|||
return tirette;
|
||||
}
|
||||
|
||||
void TirettePopup (object sender, ContextMenuEventArgs e)
|
||||
{
|
||||
Circuit c = e.Widget.Data[circuitKey] as Circuit;
|
||||
Menu m = Conduite.Courante.EventManager.GetMenu(c,new EventManager.EventMenuCallBack(TirettePopupEnd));
|
||||
m.ShowAll();
|
||||
m.Popup();
|
||||
}
|
||||
|
||||
void TirettePopupEnd (object state, string eventId)
|
||||
{
|
||||
Circuit c = state as Circuit;
|
||||
sequenceur.BindEvent(c,eventId);
|
||||
Console.WriteLine("{0} bound to {1}", c, eventId );
|
||||
}
|
||||
|
||||
static Label NouveauLabel ()
|
||||
{
|
||||
Label l = new Label();
|
||||
|
|
@ -286,6 +303,7 @@ namespace DMX2
|
|||
tirette.Show();
|
||||
tirette.ValueChanged += TiretteActionee;
|
||||
tirette.Data.Add(circuitKey,c);
|
||||
new ContextMenuHelper(tirette, new EventHandler<ContextMenuEventArgs>(TirettePopup));
|
||||
tirette.TooltipText = c.Name;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -362,6 +362,29 @@ namespace DMX2
|
|||
}
|
||||
}
|
||||
|
||||
private class circEvTarget : IEventTarget{
|
||||
Circuit c; SequenceurLineaire seq;
|
||||
public circEvTarget(SequenceurLineaire _seq, Circuit _c){
|
||||
c=_c;
|
||||
seq=_seq;
|
||||
}
|
||||
#region IEventTarget implementation
|
||||
bool IEventTarget.FireEvent (EventData data)
|
||||
{
|
||||
seq.ChangeValeur(c,data.value);
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
public void BindEvent (Circuit c, string eventId)
|
||||
{
|
||||
// TODO : plein de trucs
|
||||
|
||||
Conduite.Courante.EventManager.Bind(eventId,new circEvTarget(this,c));
|
||||
}
|
||||
|
||||
public override void Save (System.Xml.XmlElement parent)
|
||||
{
|
||||
System.Xml.XmlElement el = parent.OwnerDocument.CreateElement ("SequenceurLineaire");
|
||||
|
|
|
|||
Loading…
Reference in a new issue