diff --git a/DMX-2.0/MidiEventProvider.cs b/DMX-2.0/MidiEventProvider.cs index 0c7ee91..5396cdd 100644 --- a/DMX-2.0/MidiEventProvider.cs +++ b/DMX-2.0/MidiEventProvider.cs @@ -282,7 +282,6 @@ namespace DMX2 if (!knowndevices.ContainsKey (dev.Name)) return; knowndevices.Remove (dev.Name); - // TODO: Deconnecter ici foreach (int connectedport in dev.ConnectedPorts) { int client = connectedport >> 8; @@ -557,8 +556,6 @@ namespace DMX2 ); continue; - - //TODO : Regarder si d'autres controles interessants. default: id = null; #if DEBUG @@ -622,8 +619,6 @@ namespace DMX2 } } - //TODO gerer pages et feeddback - static System.Text.RegularExpressions.Regex regexCtrlEventID = new System.Text.RegularExpressions.Regex ( @"MIDI-PAGE(?\d+)-CTRL-C(?\d+)P(?\d+)", System.Text.RegularExpressions.RegexOptions.Compiled); diff --git a/DMX-2.0/SeqSonUI.cs b/DMX-2.0/SeqSonUI.cs index 2600832..4cda866 100644 --- a/DMX-2.0/SeqSonUI.cs +++ b/DMX-2.0/SeqSonUI.cs @@ -22,14 +22,21 @@ using Gtk; namespace DMX2 { + + //TODO : Changement de nom + [System.ComponentModel.ToolboxItem(true)] public partial class SeqSonUI : SequenceurUI { - ListStore lsFiles = null; SequenceurSon sequenceur; + public bool updateflag=true; + + bool ff=false; + bool rw=false; + public void buildListFiles () { lsFiles = new ListStore(typeof(string)); @@ -87,7 +94,23 @@ namespace DMX2 #region implemented abstract members of DMX2.SequenceurUI public override void Update (bool full) { - //throw new System.NotImplementedException (); + if (full||updateflag ) { + listFiles.QueueDraw(); + SelectionneLigne(); + UpdListFiles(); + + } + updateflag=false; + sclVolume.Value = sequenceur.Volume; + posLabel.Text = string.Format("n°{0}",sequenceur.Index+1); + TimeSpan dur = sequenceur.Duration; + TimeSpan cur = sequenceur.PlayTime; + + if (ff) sequenceur.PlayTime += TimeSpan.FromSeconds(1); + if (rw) sequenceur.PlayTime += TimeSpan.FromSeconds(-1); + + timeLabel.LabelProp = string.Format ("elap.{0:mm\\:ss\\.fff}\nrem. {1:mm\\:ss\\.fff}",cur,dur-cur); + pbCur.Fraction = (dur == TimeSpan.Zero)?0:(cur.TotalMilliseconds/dur.TotalMilliseconds); } int IndexSelection() @@ -101,7 +124,7 @@ namespace DMX2 { FileChooserDialog fcd = new FileChooserDialog ("Ouvrir ...", this.Parent as Gtk.Window, FileChooserAction.Open, - "Annuler", ResponseType.Cancel, + "Annuler", ResponseType.Cancel, "Ouvrir", ResponseType.Accept); fcd.SelectMultiple = true; /*fcd.Filter = new FileFilter (); @@ -119,7 +142,11 @@ namespace DMX2 } fcd.Destroy (); UpdListFiles(); + } + void SelectionneLigne(){ + int index = sequenceur.Index; + listFiles.SetCursor( new TreePath( new int[1] {index }) ,null,false); } protected void OnActDelFileActivated (object sender, EventArgs e) @@ -134,6 +161,7 @@ namespace DMX2 { sequenceur.Index+=1; listFiles.QueueDraw(); + SelectionneLigne(); } @@ -156,30 +184,55 @@ namespace DMX2 { sequenceur.Index-=1; listFiles.QueueDraw(); + SelectionneLigne(); } protected void OnBtnRewindPressed (object sender, EventArgs e) { - Console.WriteLine("Rew Pressed"); + rw=true; } protected void OnBtnRewindReleased (object sender, EventArgs e) { - Console.WriteLine("Rew Released"); + rw=false; } protected void OnBtnForwardPressed (object sender, EventArgs e) { - Console.WriteLine("FF Pressed"); + ff=true; } protected void OnBtnForwardReleased (object sender, EventArgs e) { - Console.WriteLine("FF Released"); + ff=false; } protected void OnSclVolumeValueChanged (object sender, EventArgs e) { sequenceur.Volume = (uint)(sclVolume.Value); } + + protected void OnBtnGotoClicked (object sender, EventArgs e) + { + TimeSpan ts; + string[] formats = new string[]{ + @"m\:s\.f", + @"m\:s", + @"h\:m\:s", + @"h\:m\:s\.f" + }; + if(!TimeSpan.TryParseExact(txtGoto.Text,formats,null,out ts)) return; + sequenceur.PlayTime = ts; + } + + protected void OnListFilesCursorChanged (object sender, EventArgs e) + { + TreeViewColumn col; + TreePath path; + listFiles.GetCursor (out path, out col); + + if (listFiles.Columns [0] == col) { + sequenceur.Index = IndexSelection(); + } + } #endregion } diff --git a/DMX-2.0/Sequenceur.cs b/DMX-2.0/Sequenceur.cs index a65a301..b2d62b1 100644 --- a/DMX-2.0/Sequenceur.cs +++ b/DMX-2.0/Sequenceur.cs @@ -82,6 +82,8 @@ namespace DMX2 return SequenceurLineaire.Load(conduite, el); case "SequenceurMacro": return SequenceurMacro.Load(conduite,el); + case "SequenceurSon": + return SequenceurSon.Load(conduite,el); } return null; } diff --git a/DMX-2.0/SequenceurSon.cs b/DMX-2.0/SequenceurSon.cs index b492e5b..f997f89 100644 --- a/DMX-2.0/SequenceurSon.cs +++ b/DMX-2.0/SequenceurSon.cs @@ -21,11 +21,21 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading; +using System.Xml; namespace DMX2 { + + // TODO : Sauvegarde et chargement + public class SequenceurSon : Sequenceur { + ~SequenceurSon() + { + if(element!=null) + Stop(); + element=null; + } SeqSonUI ui=null; @@ -37,6 +47,15 @@ namespace DMX2 uint volume=100; + delegate void Task (); + + Queue taskQueue = new Queue(); + + TimeSpan fading=TimeSpan.Zero; + TimeSpan fadeLen; + int fadeVStart; + int fadeVEnd; + Gst.Element element = null; public ReadOnlyCollection Files { @@ -63,7 +82,7 @@ namespace DMX2 { lock (this) { files.Insert (pos, file); - //CommandAdd(pos); + CommandAdd(pos); return pos; } } @@ -77,33 +96,78 @@ namespace DMX2 } } + public TimeSpan PlayTime { + get{ + if(element==null) return TimeSpan.Zero; + Gst.Format format = Gst.Format.Time ; + long cur; + element.QueryPosition(ref format, out cur); + return TimeSpan.FromMilliseconds(cur/1000000); + } + set{ + if(element==null) return; + if(element.CurrentState != Gst.State.Paused && element.CurrentState != Gst.State.Playing){ + lock(taskQueue)taskQueue.Enqueue(delegate(){ + PlayTime = value; + }); + return; + } + long pos = (long)(value.TotalMilliseconds) * 1000000; + element.Seek (Gst.Format.Time,Gst.SeekFlags.Flush|Gst.SeekFlags.Accurate,pos); + } + } + + TimeSpan duration = TimeSpan.Zero; + + public TimeSpan Duration { + get { + if(element==null) return TimeSpan.Zero; + if(duration == TimeSpan.Zero) { + Gst.Format format = Gst.Format.Time ; + long dur; + element.QueryDuration(ref format, out dur); + duration = TimeSpan.FromMilliseconds(dur/1000000); + } + return duration; + } + } + public void DelFile (int pos) { lock (this) { files.RemoveAt (pos); - //CommandRemove(pos); + CommandRemove(pos); } } + + void LoadFile (int pos) { curfile = files[pos]; - if (element != null) { - element.SetState(Gst.State.Null); - element.Dispose(); - } + Stop(); + + duration = TimeSpan.Zero; Uri uri = new Uri(curfile); - element = Gst.ElementFactory.Make("playbin2"); + element = Gst.ElementFactory.Make("playbin"); element["uri"] = uri.AbsoluteUri; element.SetState(Gst.State.Paused); + element["volume"] = (double)volume / 100.0d ; } public void Play () { if(element == null)return; + if(element.CurrentState != Gst.State.Paused && element.CurrentState != Gst.State.Playing){ + lock(taskQueue)taskQueue.Enqueue(delegate(){ + Play(); + }); + return; + } + element.SetState(Gst.State.Playing); } public void Pause () @@ -117,10 +181,7 @@ namespace DMX2 element.SetState(Gst.State.Null); element.Dispose(); element=null; - } - - public void MoveTo(ulong pos){ - + taskQueue.Clear(); } static void GstInit () @@ -159,17 +220,201 @@ namespace DMX2 public override void Tick (TimeSpan time) { - //throw new System.NotImplementedException (); + if(element!=null && taskQueue.Count>0) + lock(taskQueue)taskQueue.Dequeue()(); + + if (fading != TimeSpan.Zero) { + fading-=time; + if(fading<=TimeSpan.Zero){ + Volume = (uint)fadeVEnd; + fading=TimeSpan.Zero; + } + else{ + Volume = (uint)( + fadeVEnd + + (fadeVStart-fadeVEnd) * + fading.TotalMilliseconds / fadeLen.TotalMilliseconds); + + } + } } public override void Save (System.Xml.XmlElement parent) { - //throw new System.NotImplementedException (); + System.Xml.XmlElement el = parent.OwnerDocument.CreateElement ("SequenceurSon"); + System.Xml.XmlElement xmlEl; + + parent.AppendChild (el); + el.SetAttribute ("id", ID.ToString ()); + el.SetAttribute ("name", Name); + + foreach (string file in files) { + el.AppendChild(xmlEl = parent.OwnerDocument.CreateElement ("File")); + xmlEl.SetAttribute("path",file); + } + } + public static new SequenceurSon Load (Conduite conduite, System.Xml.XmlElement el) + { + SequenceurSon seq = new SequenceurSon(); + seq.LoadSeq(conduite,el); + return seq; + } + + void LoadSeq (Conduite conduite, System.Xml.XmlElement el) + { + ID = int.Parse (el.GetAttribute ("id")); + Name = el.GetAttribute ("name"); + + XmlElement xmlE; + + foreach (var xf in el.GetElementsByTagName("File")) { + System.Xml.XmlElement xfil = xf as System.Xml.XmlElement; + string file = xfil.GetAttribute ("path"); + files.Add(file); + } + } + + + static System.Text.RegularExpressions.Regex regexCommand1 = new System.Text.RegularExpressions.Regex( + @"(?\d+)?(g(?[\d\.:]+))?(v(?\d+)(,(?\d+))?)?(?(ps|p|s))?", + System.Text.RegularExpressions.RegexOptions.Compiled); + + static System.Text.RegularExpressions.Regex regexCommand2 = new System.Text.RegularExpressions.Regex( + @"(?\d+)(?[gvp](.+)?)?", + System.Text.RegularExpressions.RegexOptions.Compiled); + + public override void Command (string command) { - //throw new System.NotImplementedException (); + lock (this) { + var cmd = regexCommand1.Match (command); + + if (cmd.Success) { + if (cmd.Groups ["file"].Success) { + int filen = int.Parse (cmd.Groups ["file"].Value) - 1; + + if (filen >= files.Count) + return; + + Index = filen; + if (ui != null) + ui.updateflag = true; + + } + + + if (cmd.Groups ["goto"].Success) { + string[] formats = new string[]{ + @"m\:s\.f", @"m\:s", @"h\:m\:s",@"h\:m\:s\.f" + }; + TimeSpan ts; + if(TimeSpan.TryParseExact( + cmd.Groups ["goto"].Value,formats,null,out ts)) { + PlayTime = ts; + } + } + + if (cmd.Groups ["volume"].Success) { + uint vol = uint.Parse (cmd.Groups ["volume"].Value); + if(vol>100) vol=100; + if(cmd.Groups ["fade"].Success) { + fadeLen = fading = TimeSpan.FromMilliseconds (100*int.Parse (cmd.Groups ["fade"].Value)); + fadeVStart = (int)volume; + fadeVEnd = (int)vol; + } + else{ + Volume = vol; + if (ui != null) + ui.updateflag = true; + } + } + + if (cmd.Groups ["play"].Success) { + switch(cmd.Groups ["play"].Value) + { + case "p": + Play(); + break; + case "ps": + Pause(); + break; + case "s": + Stop(); + break; + } + } + + + } + } + + } + + + + void CommandAdd (int index) + { + lock (Conduite.Courante.SequenceurMaitre) { + string[] commands = Conduite.Courante.SequenceurMaitre.GetCommands (this); + + for (int i = 0; i < commands.Length; i++) { + var cmd = regexCommand2.Match(commands[i]); + if(cmd.Success){ + int ef = int.Parse(cmd.Groups["file"].Value); + if (ef-1>index) { + ef++; + commands[i] = ef.ToString() + cmd.Groups["params"].Value; + } + } + } + Conduite.Courante.SequenceurMaitre.SetCommands(this,commands); + } + } + + void CommandRemove (int index) + { + lock (Conduite.Courante.SequenceurMaitre) { + string[] commands = Conduite.Courante.SequenceurMaitre.GetCommands (this); + + for (int i = 0; i < commands.Length; i++) { + var cmd = regexCommand2.Match(commands[i]); + if(cmd.Success){ + int ef = int.Parse(cmd.Groups["file"].Value); + if (ef-1 == index) + commands[i] = string.Empty; + else if (ef-1>index) { + ef--; + commands[i] = ef.ToString() + cmd.Groups["params"].Value; + } + } + } + Conduite.Courante.SequenceurMaitre.SetCommands(this,commands); + } + } + + void CommandSwap (int index) + { + lock (Conduite.Courante.SequenceurMaitre) { + string[] commands = Conduite.Courante.SequenceurMaitre.GetCommands (this); + + // numeros a swapper + int a = index+1; + int b = index+2; + + for (int i = 0; i < commands.Length; i++) { + var cmd = regexCommand2.Match(commands[i]); + if(cmd.Success){ + int ef = int.Parse(cmd.Groups["file"].Value); + if (ef == a) + commands[i] = b.ToString() + cmd.Groups["params"].Value; + if (ef == b) + commands[i] = a.ToString() + cmd.Groups["params"].Value; + } + } + Conduite.Courante.SequenceurMaitre.SetCommands(this,commands); + } } #endregion diff --git a/DMX-2.0/gtk-gui/DMX2.SeqSonUI.cs b/DMX-2.0/gtk-gui/DMX2.SeqSonUI.cs index 88ef958..5b9f07c 100644 --- a/DMX-2.0/gtk-gui/DMX2.SeqSonUI.cs +++ b/DMX-2.0/gtk-gui/DMX2.SeqSonUI.cs @@ -26,9 +26,9 @@ namespace DMX2 private global::Gtk.EventBox evBBox; private global::Gtk.HBox hbox2; private global::Gtk.Label posLabel; - private global::Gtk.Label actLabel; + private global::Gtk.Label titleLabel; private global::Gtk.Label timeLabel; - private global::Gtk.ProgressBar progressbar1; + private global::Gtk.ProgressBar pbCur; private global::Gtk.HBox hbox3; private global::Gtk.Button btnPlay; private global::Gtk.Button btnPause; @@ -37,8 +37,8 @@ namespace DMX2 private global::Gtk.Button btnRewind; private global::Gtk.Button btnForward; private global::Gtk.Button btnNext; - private global::Gtk.Entry entry1; - private global::Gtk.Button button133; + private global::Gtk.Entry txtGoto; + private global::Gtk.Button btnGoto; private global::Gtk.VScale sclVolume; private global::Gtk.Toolbar toolbar4; private global::Gtk.ScrolledWindow GtkScrolledWindow; @@ -122,12 +122,12 @@ namespace DMX2 w3.Expand = false; w3.Fill = false; // Container child hbox2.Gtk.Box+BoxChild - this.actLabel = new global::Gtk.Label (); - this.actLabel.Name = "actLabel"; - this.actLabel.UseMarkup = true; - this.actLabel.Wrap = true; - this.hbox2.Add (this.actLabel); - global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.actLabel])); + this.titleLabel = new global::Gtk.Label (); + this.titleLabel.Name = "titleLabel"; + this.titleLabel.UseMarkup = true; + this.titleLabel.Wrap = true; + this.hbox2.Add (this.titleLabel); + global::Gtk.Box.BoxChild w4 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.titleLabel])); w4.Position = 1; w4.Fill = false; // Container child hbox2.Gtk.Box+BoxChild @@ -135,8 +135,9 @@ namespace DMX2 this.timeLabel.HeightRequest = 33; this.timeLabel.Name = "timeLabel"; this.timeLabel.Xpad = 15; - this.timeLabel.LabelProp = "00.0"; + this.timeLabel.LabelProp = "00.0"; this.timeLabel.UseMarkup = true; + this.timeLabel.Justify = ((global::Gtk.Justification)(1)); this.hbox2.Add (this.timeLabel); global::Gtk.Box.BoxChild w5 = ((global::Gtk.Box.BoxChild)(this.hbox2 [this.timeLabel])); w5.PackType = ((global::Gtk.PackType)(1)); @@ -150,10 +151,10 @@ namespace DMX2 w7.Expand = false; w7.Fill = false; // Container child vbox3.Gtk.Box+BoxChild - this.progressbar1 = new global::Gtk.ProgressBar (); - this.progressbar1.Name = "progressbar1"; - this.vbox3.Add (this.progressbar1); - global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.progressbar1])); + this.pbCur = new global::Gtk.ProgressBar (); + this.pbCur.Name = "pbCur"; + this.vbox3.Add (this.pbCur); + global::Gtk.Box.BoxChild w8 = ((global::Gtk.Box.BoxChild)(this.vbox3 [this.pbCur])); w8.Position = 1; w8.Expand = false; w8.Fill = false; @@ -330,22 +331,22 @@ namespace DMX2 w71.Expand = false; w71.Fill = false; // Container child hbox3.Gtk.Box+BoxChild - this.entry1 = new global::Gtk.Entry (); - this.entry1.CanFocus = true; - this.entry1.Name = "entry1"; - this.entry1.IsEditable = true; - this.entry1.InvisibleChar = '•'; - this.hbox3.Add (this.entry1); - global::Gtk.Box.BoxChild w72 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.entry1])); + this.txtGoto = new global::Gtk.Entry (); + this.txtGoto.CanFocus = true; + this.txtGoto.Name = "txtGoto"; + this.txtGoto.IsEditable = true; + this.txtGoto.InvisibleChar = '•'; + this.hbox3.Add (this.txtGoto); + global::Gtk.Box.BoxChild w72 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.txtGoto])); w72.Position = 7; // Container child hbox3.Gtk.Box+BoxChild - this.button133 = new global::Gtk.Button (); - this.button133.CanFocus = true; - this.button133.Name = "button133"; - this.button133.UseUnderline = true; - this.button133.Label = "GoTo"; - this.hbox3.Add (this.button133); - global::Gtk.Box.BoxChild w73 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.button133])); + this.btnGoto = new global::Gtk.Button (); + this.btnGoto.CanFocus = true; + this.btnGoto.Name = "btnGoto"; + this.btnGoto.UseUnderline = true; + this.btnGoto.Label = "GoTo"; + this.hbox3.Add (this.btnGoto); + global::Gtk.Box.BoxChild w73 = ((global::Gtk.Box.BoxChild)(this.hbox3 [this.btnGoto])); w73.Position = 8; w73.Expand = false; w73.Fill = false; @@ -430,7 +431,9 @@ namespace DMX2 this.btnForward.Pressed += new global::System.EventHandler (this.OnBtnForwardPressed); this.btnForward.Released += new global::System.EventHandler (this.OnBtnForwardReleased); this.btnNext.Clicked += new global::System.EventHandler (this.OnBtnNextClicked); + this.btnGoto.Clicked += new global::System.EventHandler (this.OnBtnGotoClicked); this.sclVolume.ValueChanged += new global::System.EventHandler (this.OnSclVolumeValueChanged); + this.listFiles.CursorChanged += new global::System.EventHandler (this.OnListFilesCursorChanged); } } } diff --git a/DMX-2.0/gtk-gui/gui.stetic b/DMX-2.0/gtk-gui/gui.stetic index 18f35f8..49b9ba9 100644 --- a/DMX-2.0/gtk-gui/gui.stetic +++ b/DMX-2.0/gtk-gui/gui.stetic @@ -3651,7 +3651,7 @@ trames DMX (ms) - + True True @@ -3667,8 +3667,9 @@ trames DMX (ms) 33 15 - <big>00.0</big> + <small>00.0</small> True + Right End @@ -3689,7 +3690,7 @@ trames DMX (ms) - + @@ -3825,7 +3826,7 @@ trames DMX (ms) - + True True @@ -3837,12 +3838,13 @@ trames DMX (ms) - + True TextOnly GoTo True + 8 @@ -3925,6 +3927,7 @@ trames DMX (ms) True True True +