diff --git a/DMX-2.0/SeqMidiUI.cs b/DMX-2.0/SeqMidiUI.cs index 339fed0..d6b7f0b 100644 --- a/DMX-2.0/SeqMidiUI.cs +++ b/DMX-2.0/SeqMidiUI.cs @@ -224,12 +224,47 @@ namespace DMX2 } ); + + item = new Gtk.SeparatorMenuItem (); + m.Add(item); + + item = new MenuItem("Connecter"); + item.Submenu = EnumMidiDevices (); + m.Add(item); + m.ShowAll(); m.Popup(); } + static public object PortKey = new object(); + + Gtk.Menu EnumMidiDevices(){ + + Gtk.Menu m = new Menu (); + + Gtk.MenuItem item; + + foreach (var dev in AlsaSeqLib.EnumClients ()) { + if(dev.Id== AlsaSeqLib.ClientId || dev.Id == 0 || dev.Id == 14 ) continue; + foreach(var port in dev.Ports){ + if((port.Caps & AlsaSeqLib.SND_SEQ_PORT_CAP_WRITE) == AlsaSeqLib.SND_SEQ_PORT_CAP_WRITE){ + string name = dev.Name+":"+port.Name; + + item = new MenuItem (name); + item.Data[PortKey] = port; + item.ButtonPressEvent+= ConnectMidiDevEvent; + m.Add (item); + + } + } + } + + return m; + } + + public override void Update (bool full) { if (fullUpdFlag || full) @@ -251,6 +286,13 @@ namespace DMX2 } } + void ConnectMidiDevEvent (object o, ButtonPressEventArgs args) + { + Gtk.MenuItem item = o as Gtk.MenuItem; + AlsaSeqLib.Port port = item.Data [PortKey] as AlsaSeqLib.Port; + sequenceur.Connect (port); + } + void SelectionneEffet (int index) { diff --git a/DMX-2.0/SequenceurMidi.cs b/DMX-2.0/SequenceurMidi.cs index 1530ab2..39f6578 100644 --- a/DMX-2.0/SequenceurMidi.cs +++ b/DMX-2.0/SequenceurMidi.cs @@ -24,14 +24,14 @@ using System.Threading; namespace DMX2 { - public class SequenceurMidi : Sequenceur + public class SequenceurMidi : Sequenceur , IDisposable { public class Ligne { public Ligne(){} string nom = string.Empty; TimeSpan top = TimeSpan.MinValue; - string commande =null; + string commande =string.Empty; public string Nom { get { @@ -104,6 +104,11 @@ namespace DMX2 bool paused=false; + int midiport=-1; + static int portnum=0; + + List mididests = new List(); + public bool Paused { get { return paused; @@ -113,6 +118,14 @@ namespace DMX2 } } + int midiCh=0; + + public int MidiCh { + get{ + return midiCh; + } + } + public SequenceurMidi () { @@ -134,8 +147,22 @@ namespace DMX2 return true; } ); + string portname = string.Format ("midi_seq_{0}", portnum++); + midiport = AlsaSeqLib.CreatePort (portname); } + bool disposed=false; + ~SequenceurMidi () + { + ((IDisposable)this).Dispose (); + } + + void IDisposable.Dispose (){ + if (disposed) + return; + disposed = true; + AlsaSeqLib.DeletePort (midiport); + } public int IndexLigneEnCours { @@ -145,6 +172,9 @@ namespace DMX2 } } + public void Connect (AlsaSeqLib.Port port){ + AlsaSeqLib.ConnectTo (midiport, port.ClientId, port.PortId); + } public int IndexLigneaSuivre { @@ -231,8 +261,19 @@ namespace DMX2 enCours = lignes[index]; // Gestion de la Reprise - // if(enCours.Circuits.ToLower().Equals("r") && ligneMaitre != null) - // enCours = ligneMaitre; + if (enCours.Commande.ToLower ().Equals ("r") && ligneMaitre != null) { + enCours = ligneMaitre; + } + + System.Text.RegularExpressions.Match m = regexGotoCmd.Match (enCours.Commande); + if (m.Success) { + int gtindex = int.Parse (m.Groups [2].Value)-1; + if (lignes.Count >= gtindex) { + timeStamp = TimeSpan.Zero; + enCours = lignes [gtindex]; + } + } + if(enCours.Nom.Length!=0) { @@ -264,10 +305,70 @@ namespace DMX2 } } + static System.Text.RegularExpressions.Regex regexMidiCmd = new System.Text.RegularExpressions.Regex( + @"(ch(\d+))|(CC(\d+),(\d+))|(PC(\d+))|(N(\d+)(\+|\-)(\d+)?)", + System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.IgnoreCase ); + + static System.Text.RegularExpressions.Regex regexGotoCmd = new System.Text.RegularExpressions.Regex( + @"(GT(\d+))", + System.Text.RegularExpressions.RegexOptions.Compiled | System.Text.RegularExpressions.RegexOptions.IgnoreCase ); + + void LanceCommandeMidi () { + Console.WriteLine (enCours.Commande); + + AlsaSeqLib.snd_seq_event_t ev; + var matches = regexMidiCmd.Matches (enCours.Commande); + + foreach (System.Text.RegularExpressions.Match match in matches) { + if (match.Groups [2].Success) { + midiCh = int.Parse (match.Groups [2].Value); + continue; + } + if (match.Groups [4].Success) { + ev = new AlsaSeqLib.snd_seq_event_t (); + ev.type = AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_CONTROLLER; + ev.data_ev_ctrl.channel = (byte)midiCh; + ev.data_ev_ctrl.param = uint.Parse (match.Groups [4].Value); + ev.data_ev_ctrl.value = int.Parse (match.Groups [5].Value); + ev.source.port = (byte)midiport; + AlsaSeqLib.SendEventToSubscribers (ev); + } + + if (match.Groups [7].Success) { + ev = new AlsaSeqLib.snd_seq_event_t (); + ev.type = AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_PGMCHANGE; + ev.data_ev_ctrl.channel = (byte)midiCh; + ev.data_ev_ctrl.value = int.Parse (match.Groups [7].Value); + ev.source.port = (byte)midiport; + AlsaSeqLib.SendEventToSubscribers (ev); + } + + if (match.Groups [9].Success) { + ev = new AlsaSeqLib.snd_seq_event_t (); + ev.data_ev_note.note = byte.Parse (match.Groups [9].Value); + ev.data_ev_note.channel = (byte)midiCh; + + if (match.Groups [10].Value.Equals ("+")) { + ev.type = AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_NOTEON; + if (match.Groups [11].Success) + ev.data_ev_note.velocity = byte.Parse (match.Groups [11].Value); + else + ev.data_ev_note.velocity = 127; + } else { + ev.type = AlsaSeqLib.snd_seq_event_type_t.SND_SEQ_EVENT_NOTEOFF; + if (match.Groups [11].Success) + ev.data_ev_note.off_velocity = byte.Parse (match.Groups [11].Value); + else + ev.data_ev_note.off_velocity = 0; + } + ev.source.port = (byte)midiport; + AlsaSeqLib.SendEventToSubscribers (ev); + } + } } diff --git a/DMX-2.0/gtk-gui/DMX2.SeqMidiUI.cs b/DMX-2.0/gtk-gui/DMX2.SeqMidiUI.cs index aa97bcd..a49fdd3 100644 --- a/DMX-2.0/gtk-gui/DMX2.SeqMidiUI.cs +++ b/DMX-2.0/gtk-gui/DMX2.SeqMidiUI.cs @@ -8,8 +8,6 @@ namespace DMX2 private global::Gtk.ToggleAction closeAction; - private global::Gtk.Action circuitsAction; - private global::Gtk.Action goForwardAction; private global::Gtk.Action goBackAction; @@ -66,8 +64,6 @@ namespace DMX2 this.closeAction = new global::Gtk.ToggleAction ("closeAction", " ", null, "gtk-close"); this.closeAction.ShortLabel = " "; w2.Add (this.closeAction, null); - this.circuitsAction = new global::Gtk.Action ("circuitsAction", null, "Association des circuits\nau sequenceur", "circuits"); - w2.Add (this.circuitsAction, null); this.goForwardAction = new global::Gtk.Action ("goForwardAction", null, null, "gtk-go-forward"); w2.Add (this.goForwardAction, null); this.goBackAction = new global::Gtk.Action ("goBackAction", null, null, "gtk-go-back"); diff --git a/DMX-2.0/gtk-gui/gui.stetic b/DMX-2.0/gtk-gui/gui.stetic index 9c852c5..676e6a0 100644 --- a/DMX-2.0/gtk-gui/gui.stetic +++ b/DMX-2.0/gtk-gui/gui.stetic @@ -2238,6 +2238,24 @@ au sequenceur True + + + + 0 + CC : Control Change (ex: CC12,100) +PC : Program Change (ex: PC5) +N : Note On/Off (ex: N64+127 ou N12-) +GT : Go To (ex: GT4) +r: loop + True + + + 2 + True + False + False + + @@ -4711,4 +4729,4 @@ trames DMX (ms) - + \ No newline at end of file