using System; using System.Runtime.InteropServices; using System.Collections.Generic; namespace DMX2 { public partial class MidiEventProvider : IEventProvider, IDisposable { class internalEvent { public string internalName; public string description; public internalEvent(string _id, string _desc) { internalName=_id; description=_desc; } } Dictionary eventlist = new Dictionary(); 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"); 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); manager.RegisterProvider(this); } #region IDisposable implementation public void Dispose () { snd_seq_close(midi_seq_handle); } #endregion #region IEventProvider implementation /*ICollection IEventProvider.GetEventList () { return eventlist.Keys; }*/ bool IEventProvider.Bind (string eventId) { // TODO : check if "MIDI ..." return true; } void IEventProvider.Unbind (string eventId) { return; } Gtk.Menu IEventProvider.GetProviderSubMenu (EventManager.EventMenuData state, Gtk.ButtonPressEventHandler handler) { Gtk.Menu retmenu = new Gtk.Menu (); if (levent != null) { Gtk.MenuItem lmenuitem = new Gtk.MenuItem ("Dernier"); retmenu.Add (lmenuitem); Gtk.Menu lmenu = new Gtk.Menu (); lmenuitem.Submenu = lmenu; Gtk.MenuItem item = new Gtk.MenuItem(levent.description); item.Data[EventManager.EventIdKey] = levent.internalName; item.Data[EventManager.StateKey] = state; item.ButtonPressEvent += handler; lmenu.Add (item); } Gtk.MenuItem evmenuitem = new Gtk.MenuItem ("Events"); retmenu.Add (evmenuitem); Gtk.Menu evmenu = new Gtk.Menu (); evmenuitem.Submenu = evmenu; List sortedKeys = new List(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; } EventData last; internalEvent levent=null; void IEventProvider.ProcessEvents (EventManagerCallback callback) { IntPtr evPtr; while ((snd_seq_event_input_pending(midi_seq_handle,1))>0) { 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; case snd_seq_event_type_t.SND_SEQ_EVENT_CLOCK: case snd_seq_event_type_t.SND_SEQ_EVENT_SENSING: continue; //TODO : Regarder si d'autres controles interessants. default: id= null; Info.Publish(string.Format ("event {0}", evS.type) ); continue; } if(id!=null) { if(!eventlist.ContainsKey(id)) eventlist.Add(id,new internalEvent(id,description)); levent= eventlist[id]; EventData evData = new EventData(); evData.id = id; evData.value = (byte)value; if(evData.Equals(last)) continue; callback(evData); last = evData; } } } string IEventProvider.MenuName { get { return "Midi"; } } #endregion } }