[longomatch/stop] More work



commit 376ba2af0c2caf8b340d187d4d3edd08eef81d4b
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Sun Oct 11 16:30:22 2009 +0200

    More work

 CesarPlayer/Gui/PlayerBin.cs                    |   49 +++++--
 CesarPlayer/Handlers/Handlers.cs                |    1 +
 CesarPlayer/Player/GstPlayer.cs                 |    2 +
 CesarPlayer/gtk-gui/LongoMatch.Gui.PlayerBin.cs |   36 +++---
 LongoMatch/DB/DataBase.cs                       |    3 +-
 LongoMatch/Gui/Component/DrawingWidget.cs       |    4 +-
 LongoMatch/Gui/Component/TimeScale.cs           |   82 +++++++-----
 LongoMatch/Gui/Dialog/DrawingTool.cs            |    7 +-
 LongoMatch/Gui/MainWindow.cs                    |    4 +-
 LongoMatch/Gui/TreeView/PlaysTreeView.cs        |   40 +++++--
 LongoMatch/Handlers/EventsManager.cs            |    5 +-
 LongoMatch/Handlers/VideoDrawingsManager.cs     |  157 ++++++++++++++++-------
 LongoMatch/LongoMatch.mdp                       |    1 +
 LongoMatch/Main.cs                              |    7 +-
 LongoMatch/Time/Drawing.cs                      |   19 ++-
 LongoMatch/Time/MediaTimeNode.cs                |   53 +++-----
 LongoMatch/Time/PixbufTimeNode.cs               |   38 +++++-
 17 files changed, 330 insertions(+), 178 deletions(-)
---
diff --git a/CesarPlayer/Gui/PlayerBin.cs b/CesarPlayer/Gui/PlayerBin.cs
index 3bb942a..512427a 100644
--- a/CesarPlayer/Gui/PlayerBin.cs
+++ b/CesarPlayer/Gui/PlayerBin.cs
@@ -42,7 +42,7 @@ namespace LongoMatch.Gui
 		public event NextButtonClickedHandler Next;
 		public event PrevButtonClickedHandler Prev;
 		public event DrawFrameHandler DrawFrame;
-		public event EventHandler SeekEvent;
+		public event SeekEventHandler SeekEvent;
 			
 		private const int THUMBNAIL_WIDTH = 50;
 		private TickHandler tickHandler;
@@ -218,37 +218,46 @@ namespace LongoMatch.Gui
 		public void SeekTo(long time, bool accurate){
 			player.SeekTime(time,1,accurate);
 			if (SeekEvent != null)
-				SeekEvent(this,null);
+				SeekEvent(time);
 		}
 		
 		public void SeekInSegment(long pos){
 			player.SeekInSegment(pos, GetRateFromScale());
-			SeekEvent(this,null);
+			if (SeekEvent != null)
+				SeekEvent(pos);
 		}
 		
 		public void SeekToNextFrame(bool in_segment){
-			if (segmentStopTime==0 | player.CurrentTime < segmentStopTime){
+			int currentTime = (int)player.CurrentTime;
+			if (segmentStopTime==0 | currentTime < segmentStopTime){
 				player.SeekToNextFrame( GetRateFromScale(), in_segment);
-				SeekEvent(this,null);
+				if (SeekEvent != null)
+					SeekEvent(currentTime );
 			}
 			
 		}
 		
 		public void SeekToPreviousFrame(bool in_segment){
-			if (player.CurrentTime > segmentStartTime){
+			long currentTime = player.CurrentTime;
+			if (currentTime> segmentStartTime){
 				player.SeekToPreviousFrame( GetRateFromScale(),in_segment);
-				SeekEvent(this,null);
+				if (SeekEvent != null)
+					SeekEvent(currentTime);
 			}
 		}
 		
 		public void UpdateSegmentStartTime (long start){
 			segmentStartTime = start;
-			player.SegmentStartUpdate(start, GetRateFromScale());						
+			player.SegmentStartUpdate(start, GetRateFromScale());
+			if (SeekEvent != null)
+				SeekEvent(start);
 		}
 		
 		public void UpdateSegmentStopTime (long stop){
 			segmentStopTime = stop;
 			player.SegmentStopUpdate(stop, GetRateFromScale());	
+			if (SeekEvent != null)
+				SeekEvent(stop);
 		}
 		
 		public void SetStartStop(long start, long stop){
@@ -523,12 +532,26 @@ namespace LongoMatch.Gui
 		
 		protected virtual void OnDrawButtonClicked (object sender, System.EventArgs e)
 		{
-			if (DrawFrame != null)
-				DrawFrame(CurrentFrame,(int)AccurateCurrentTime);
+			int currentTime;
+			Pixbuf frame=null;
+			if (DrawFrame != null){
+				if (!InSegment())
+					DrawFrame(CurrentFrame,(int)AccurateCurrentTime);
+				else {
+					//We need an extra acurracy and we have to grant the frame 
+					//correspond to the instant we are assigning to this frame
+					//This process should be the same when when retrieving the 
+					//frame to paint over the drawings
+					currentTime = (int)AccurateCurrentTime;
+					Pause();
+					SeekInSegment(currentTime);
+					 //We have to wait untill the seek event is done to get a valid frame
+					while (frame == null)
+						frame = CurrentFrame;
+					DrawFrame(frame,currentTime);
+				}				
+			}				
 		}
-		
-
 #endregion	
 	}
-
 }
diff --git a/CesarPlayer/Handlers/Handlers.cs b/CesarPlayer/Handlers/Handlers.cs
index 48fe2d5..2460ff1 100644
--- a/CesarPlayer/Handlers/Handlers.cs
+++ b/CesarPlayer/Handlers/Handlers.cs
@@ -27,6 +27,7 @@ namespace LongoMatch.Video.Handlers
 	public delegate void PlayListSegmentDoneHandler ();
 	public delegate void SegmentClosedHandler();
 	public delegate void SegmentDoneHandler();
+	public delegate void SeekEventHandler(long pos);
 	public delegate void VolumeChangedHandler (double level);
 	public delegate void NextButtonClickedHandler ();
 	public delegate void PrevButtonClickedHandler ();
diff --git a/CesarPlayer/Player/GstPlayer.cs b/CesarPlayer/Player/GstPlayer.cs
index 1bb08e3..819064e 100644
--- a/CesarPlayer/Player/GstPlayer.cs
+++ b/CesarPlayer/Player/GstPlayer.cs
@@ -1140,6 +1140,8 @@ namespace LongoMatch.Video.Player {
 		public Gdk.Pixbuf GetCurrentFrame(int outwidth, int outheight) { 
 			IntPtr raw_ret = bacon_video_widget_get_current_frame(Handle);
 			Gdk.Pixbuf unmanaged = GLib.Object.GetObject(raw_ret) as Gdk.Pixbuf;
+			if (unmanaged == null)
+				return null;
 			Gdk.Pixbuf managed;
 			int h = unmanaged.Height;
 			int w = unmanaged.Width;
diff --git a/CesarPlayer/gtk-gui/LongoMatch.Gui.PlayerBin.cs b/CesarPlayer/gtk-gui/LongoMatch.Gui.PlayerBin.cs
index 7dd32e8..614fc41 100644
--- a/CesarPlayer/gtk-gui/LongoMatch.Gui.PlayerBin.cs
+++ b/CesarPlayer/gtk-gui/LongoMatch.Gui.PlayerBin.cs
@@ -106,14 +106,14 @@ namespace LongoMatch.Gui {
             this.drawbutton.UseUnderline = true;
             // Container child drawbutton.Gtk.Container+ContainerChild
             Gtk.Alignment w11 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            // Container child GtkAlignment1.Gtk.Container+ContainerChild
+            // Container child GtkAlignment.Gtk.Container+ContainerChild
             Gtk.HBox w12 = new Gtk.HBox();
             w12.Spacing = 2;
-            // Container child GtkHBox1.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Image w13 = new Gtk.Image();
             w13.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-select-color", Gtk.IconSize.Menu, 16);
             w12.Add(w13);
-            // Container child GtkHBox1.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Label w15 = new Gtk.Label();
             w12.Add(w15);
             w11.Add(w12);
@@ -131,14 +131,14 @@ namespace LongoMatch.Gui {
             this.playbutton.Relief = ((Gtk.ReliefStyle)(2));
             // Container child playbutton.Gtk.Container+ContainerChild
             Gtk.Alignment w20 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            // Container child GtkAlignment2.Gtk.Container+ContainerChild
+            // Container child GtkAlignment.Gtk.Container+ContainerChild
             Gtk.HBox w21 = new Gtk.HBox();
             w21.Spacing = 2;
-            // Container child GtkHBox2.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Image w22 = new Gtk.Image();
             w22.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-media-play", Gtk.IconSize.Button, 20);
             w21.Add(w22);
-            // Container child GtkHBox2.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Label w24 = new Gtk.Label();
             w21.Add(w24);
             w20.Add(w21);
@@ -156,14 +156,14 @@ namespace LongoMatch.Gui {
             this.pausebutton.Relief = ((Gtk.ReliefStyle)(2));
             // Container child pausebutton.Gtk.Container+ContainerChild
             Gtk.Alignment w29 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            // Container child GtkAlignment3.Gtk.Container+ContainerChild
+            // Container child GtkAlignment.Gtk.Container+ContainerChild
             Gtk.HBox w30 = new Gtk.HBox();
             w30.Spacing = 2;
-            // Container child GtkHBox3.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Image w31 = new Gtk.Image();
             w31.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-media-pause", Gtk.IconSize.Button, 20);
             w30.Add(w31);
-            // Container child GtkHBox3.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Label w33 = new Gtk.Label();
             w30.Add(w33);
             w29.Add(w30);
@@ -181,14 +181,14 @@ namespace LongoMatch.Gui {
             this.prevbutton.Relief = ((Gtk.ReliefStyle)(2));
             // Container child prevbutton.Gtk.Container+ContainerChild
             Gtk.Alignment w38 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            // Container child GtkAlignment4.Gtk.Container+ContainerChild
+            // Container child GtkAlignment.Gtk.Container+ContainerChild
             Gtk.HBox w39 = new Gtk.HBox();
             w39.Spacing = 2;
-            // Container child GtkHBox4.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Image w40 = new Gtk.Image();
             w40.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-media-previous", Gtk.IconSize.Button, 20);
             w39.Add(w40);
-            // Container child GtkHBox4.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Label w42 = new Gtk.Label();
             w39.Add(w42);
             w38.Add(w39);
@@ -207,14 +207,14 @@ namespace LongoMatch.Gui {
             this.nextbutton.Relief = ((Gtk.ReliefStyle)(2));
             // Container child nextbutton.Gtk.Container+ContainerChild
             Gtk.Alignment w47 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            // Container child GtkAlignment5.Gtk.Container+ContainerChild
+            // Container child GtkAlignment.Gtk.Container+ContainerChild
             Gtk.HBox w48 = new Gtk.HBox();
             w48.Spacing = 2;
-            // Container child GtkHBox5.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Image w49 = new Gtk.Image();
             w49.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-media-next", Gtk.IconSize.Button, 20);
             w48.Add(w49);
-            // Container child GtkHBox5.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Label w51 = new Gtk.Label();
             w48.Add(w51);
             w47.Add(w48);
@@ -267,14 +267,14 @@ namespace LongoMatch.Gui {
             this.volumebutton.Relief = ((Gtk.ReliefStyle)(2));
             // Container child volumebutton.Gtk.Container+ContainerChild
             Gtk.Alignment w60 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
-            // Container child GtkAlignment6.Gtk.Container+ContainerChild
+            // Container child GtkAlignment.Gtk.Container+ContainerChild
             Gtk.HBox w61 = new Gtk.HBox();
             w61.Spacing = 2;
-            // Container child GtkHBox6.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Image w62 = new Gtk.Image();
             w62.Pixbuf = Stetic.IconLoader.LoadIcon(this, "stock_volume", Gtk.IconSize.Button, 20);
             w61.Add(w62);
-            // Container child GtkHBox6.Gtk.Container+ContainerChild
+            // Container child GtkHBox.Gtk.Container+ContainerChild
             Gtk.Label w64 = new Gtk.Label();
             w61.Add(w64);
             w60.Add(w61);
diff --git a/LongoMatch/DB/DataBase.cs b/LongoMatch/DB/DataBase.cs
index e071359..5da1ab0 100644
--- a/LongoMatch/DB/DataBase.cs
+++ b/LongoMatch/DB/DataBase.cs
@@ -98,7 +98,7 @@ namespace LongoMatch.DB
 					IObjectSet result = query.Execute();
 					while (result.HasNext()){
 						allDB.Add(result.Next());					
-					}
+					}					
 					return allDB;					
 				}				
 				finally
@@ -224,6 +224,7 @@ namespace LongoMatch.DB
 			Db4oFactory.Configure().ObjectClass(typeof(HotKey)).CascadeOnDelete(true);
 			Db4oFactory.Configure().ObjectClass(typeof(TeamTemplate)).CascadeOnDelete(true);
 			Db4oFactory.Configure().ObjectClass(typeof(Drawing)).CascadeOnDelete(true);
+			Db4oFactory.Configure().ObjectClass(typeof(DrawingsList)).CascadeOnDelete(true);
 		}
 		
 		private bool Exists(string filename){
diff --git a/LongoMatch/Gui/Component/DrawingWidget.cs b/LongoMatch/Gui/Component/DrawingWidget.cs
index af37ae6..e611984 100644
--- a/LongoMatch/Gui/Component/DrawingWidget.cs
+++ b/LongoMatch/Gui/Component/DrawingWidget.cs
@@ -164,11 +164,11 @@ namespace LongoMatch.Gui.Component
 			Surface pngSurface = new ImageSurface (Format.ARGB32,sourceWidth,sourceHeight);
 			using (Context c = new Context(pngSurface)){
 				if (bSource){
-					c.SetSourceSurface(source,xOffset,yOffset);
+					c.SetSourceSurface(source,0,0);
 					c.Paint();
 				}
 				if (bDrawings){
-					c.SetSourceSurface(drawings,xOffset,yOffset);
+					c.SetSourceSurface(drawings,0,0);
 					c.PaintWithAlpha(transparency);
 				}
 			}
diff --git a/LongoMatch/Gui/Component/TimeScale.cs b/LongoMatch/Gui/Component/TimeScale.cs
index 35635a0..c1864ea 100644
--- a/LongoMatch/Gui/Component/TimeScale.cs
+++ b/LongoMatch/Gui/Component/TimeScale.cs
@@ -165,8 +165,8 @@ namespace LongoMatch.Gui.Component
 				using (Cairo.Context g = Gdk.CairoHelper.Create (win)){	
 					int height;
 					int width;	
-
-				
+					int keyframe;
+			
 					win.Resize((int)(frames/pixelRatio), Allocation.Height);
 					win.GetSize(out width, out height);				
 				
@@ -179,7 +179,7 @@ namespace LongoMatch.Gui.Component
 							g.Color = new Cairo.Color (color.R+0.1, color.G+0.1,color.B+0.1, 1);				
 							g.LineJoin = LineJoin.Round;
 							g.StrokePreserve();
-							g.Color = color;						
+							g.Color = color;							
 							g.Fill();
 						}
 						else {
@@ -189,6 +189,11 @@ namespace LongoMatch.Gui.Component
 					//Then we draw the selected TimeNode over the others
 					if (hasSelectedTimeNode){					
 						DrawRoundedRectangle(g,selected.StartFrame/pixelRatio,3,selected.TotalFrames/pixelRatio,height-6,SECTION_HEIGHT/7);					
+						if (selected.HasKeyFrame){
+							g.MoveTo(selected.KeyFrame/pixelRatio,3);
+							g.LineTo(selected.KeyFrame/pixelRatio,SECTION_HEIGHT-3);
+							g.StrokePreserve();
+						}
 						g.Color = new Cairo.Color (0, 0, 0, 1);		
 						g.LineWidth = 3;
 						g.LineJoin = LineJoin.Round;
@@ -224,8 +229,7 @@ namespace LongoMatch.Gui.Component
 			else {
 				win.DrawLine(Style.DarkGC(StateType.Normal),0,0,width,0);
 				win.DrawLine(Style.DarkGC(StateType.Normal),
-				             (int)(currentFrame/pixelRatio),
-				             0,
+				             (int)(currentFrame/pixelRatio),0,
 				             (int)(currentFrame/pixelRatio),height);
 			}
 		}	
@@ -236,7 +240,9 @@ namespace LongoMatch.Gui.Component
 				foreach (MediaTimeNode tn in list){	
 					layout.Width = Pango.Units.FromPixels((int)(tn.TotalFrames/pixelRatio));
 					layout.SetMarkup (tn.Name);
-					GdkWindow.DrawLayout(Style.TextGC(StateType.Normal),(int)(tn.StartFrame/pixelRatio)+2,2,layout);
+					GdkWindow.DrawLayout(Style.TextGC(StateType.Normal),
+					                     (int)(tn.StartFrame/pixelRatio)+2,
+					                     2,layout);
 				}
 			}
 		}
@@ -254,8 +260,7 @@ namespace LongoMatch.Gui.Component
 					del.Activated += new EventHandler(OnDelete);				
 					deleteMenu.Append(del);
 					dic.Add(del,tn);					
-				}
-				
+				}				
 			}	
 			menu.ShowAll();
 			menu.Popup();		
@@ -266,6 +271,7 @@ namespace LongoMatch.Gui.Component
 				candidateTN = null;
 				foreach (MediaTimeNode tn in list){	
 					int pos = (int) (evnt.X*pixelRatio);
+					//Moving from the right side
 					if (Math.Abs(pos-tn.StopFrame) < 3*pixelRatio){
 						candidateStart = false;
 						candidateTN = tn;
@@ -275,6 +281,7 @@ namespace LongoMatch.Gui.Component
 						ReDraw();
 						break;
 					}
+					//Moving from the left side
 					else if (Math.Abs(pos-tn.StartFrame) < 3*pixelRatio){
 						candidateStart =true;
 						candidateTN = tn;
@@ -323,42 +330,47 @@ namespace LongoMatch.Gui.Component
 		}
 		
 		protected override bool OnMotionNotifyEvent (EventMotion evnt)
-		{
-			uint pos = (uint) (evnt.X*pixelRatio);
-			
+		{	
+			int pos = (int) (evnt.X*pixelRatio);			
 			
-			if (movingLimit){				
-				
-				if (candidateStart && pos  > 0 && pos < candidateTN.StopFrame-10){
-					candidateTN.StartFrame = pos;					
-					if (TimeNodeChanged != null)
-						TimeNodeChanged(candidateTN,candidateTN.Start);
-				}
-				else if (!candidateStart && pos < frames && pos > candidateTN.StartFrame+10){
-					candidateTN.StopFrame = pos;					
-					if (TimeNodeChanged != null)
-						TimeNodeChanged(candidateTN,candidateTN.Stop);
-				}
-				
-				Gdk.Region region = GdkWindow.ClipRegion;
-				GdkWindow.InvalidateRegion(region,true);
-				GdkWindow.ProcessUpdates(true);			
-				
+			//If not moving don't do anything
+			if (!movingLimit);	
+			//Moving Start time 
+			else if (candidateStart){
+				Console.WriteLine(pos);
+				if (candidateTN.HasKeyFrame && pos > 0 && pos > candidateTN.KeyFrame-10)
+					candidateTN.StartFrame = candidateTN.KeyFrame-10;	
+				//Check not to go under start time nor 0
+				else if (pos  > 0 && pos < candidateTN.StopFrame-10)
+					candidateTN.StartFrame = (uint)pos;				
+				if (TimeNodeChanged != null)
+					TimeNodeChanged(candidateTN,candidateTN.Start);		
 			}
+			//Moving Stop time
+			else if(!candidateStart){
+				if (candidateTN.HasKeyFrame &&  pos < candidateTN.KeyFrame+10 )
+					candidateTN.StopFrame = candidateTN.KeyFrame+10;
+				//Check not to go under start time nor 0
+				else if (pos < frames && pos > candidateTN.StartFrame+10)
+					candidateTN.StopFrame = (uint) pos;				
+				if (TimeNodeChanged != null)
+					TimeNodeChanged(candidateTN,candidateTN.Stop);
+			}
+			
+			Gdk.Region region = GdkWindow.ClipRegion;
+			GdkWindow.InvalidateRegion(region,true);
+			GdkWindow.ProcessUpdates(true);			
+			
 			return base.OnMotionNotifyEvent (evnt);
 		}
 		
 		protected override bool OnButtonPressEvent (EventButton evnt)
 		{		
-			if (evnt.Button == 1){
-				ProcessButton1(evnt);	
-				
-				                                       
-			}
+			if (evnt.Button == 1)
+				ProcessButton1(evnt);
 			// On Right button pressed
-			else if (evnt.Button == 3){
+			else if (evnt.Button == 3)
 				ProcessButton3(evnt.X);
-			}
 			lastTime = evnt.Time;		
 			return base.OnButtonPressEvent (evnt);
 		}
diff --git a/LongoMatch/Gui/Dialog/DrawingTool.cs b/LongoMatch/Gui/Dialog/DrawingTool.cs
index af045a8..855bbac 100644
--- a/LongoMatch/Gui/Dialog/DrawingTool.cs
+++ b/LongoMatch/Gui/Dialog/DrawingTool.cs
@@ -46,7 +46,7 @@ namespace LongoMatch.Gui.Dialog
 		}
 		
 		public void SetPlay(MediaTimeNode play,int stopTime){
-			this.play = play;
+			this.play = play;	
 			this.stopTime = stopTime;
 			savetoprojectbutton.Visible = true;			
 		}
@@ -112,7 +112,10 @@ namespace LongoMatch.Gui.Dialog
 			string tempFile = System.IO.Path.GetTempFileName();
 			drawingwidget1.SaveDrawings(tempFile);
 			Pixbuf frame = new Pixbuf(tempFile);
-			play.AddDrawing(new Drawing(frame,new Time(stopTime)));
+			play.KeyFrameDrawing =new Drawing(frame,stopTime);
+			drawingwidget1.SaveAll(tempFile);
+			frame.Dispose();
+			play.Miniature = new Pixbuf(tempFile);
 		}
 	}
 }
diff --git a/LongoMatch/Gui/MainWindow.cs b/LongoMatch/Gui/MainWindow.cs
index 178a2e3..d838a02 100644
--- a/LongoMatch/Gui/MainWindow.cs
+++ b/LongoMatch/Gui/MainWindow.cs
@@ -36,6 +36,7 @@ using LongoMatch.Handlers;
 using System.Reflection;
 
 
+
 namespace LongoMatch.Gui
 {	
 	[System.ComponentModel.Category("LongoMatch")]
@@ -53,7 +54,7 @@ namespace LongoMatch.Gui
 #region Constructors
 		public MainWindow() : 
 				base("LongoMatch")
-		{			
+		{	
 			this.Build();
 			
 			/*Updater updater = new Updater();
@@ -96,6 +97,7 @@ namespace LongoMatch.Gui
 		
 #endregion
 
+
 		
 #region Private Methods
 		private void SetProject(Project project){	
diff --git a/LongoMatch/Gui/TreeView/PlaysTreeView.cs b/LongoMatch/Gui/TreeView/PlaysTreeView.cs
index 4f11d38..5b910dd 100644
--- a/LongoMatch/Gui/TreeView/PlaysTreeView.cs
+++ b/LongoMatch/Gui/TreeView/PlaysTreeView.cs
@@ -47,6 +47,7 @@ namespace LongoMatch.Gui.Component
 	    private	MenuItem visitor;
 		private MenuItem noTeam;
 		private MenuItem addPLN;
+		private MenuItem deleteKeyFrame;
 		private Gtk.CellRendererText nameCell;
 		private TreePath path;
 		private Gtk.TreeViewColumn nameColumn;
@@ -136,6 +137,7 @@ namespace LongoMatch.Gui.Component
 			MenuItem players = new MenuItem(Catalog.GetString("Tag player"));
 			players.Submenu = playersMenu;
 			MenuItem quit = new MenuItem(Catalog.GetString("Delete"));
+			deleteKeyFrame = new MenuItem(Catalog.GetString("Delete key frame"));
 			addPLN = new MenuItem(Catalog.GetString("Add to playlist"));
 			addPLN.Sensitive=false;
 			MenuItem snapshot = new MenuItem(Catalog.GetString("Export to PGN images"));
@@ -145,17 +147,19 @@ namespace LongoMatch.Gui.Component
 			menu.Append(players);
 			menu.Append(addPLN);
 			menu.Append(quit);
+			menu.Append(deleteKeyFrame);
 			menu.Append(snapshot);
 			 
-			name.Activated += new EventHandler(OnEdit);
-			local.Activated += new EventHandler(OnTeamSelection);
-			visitor.Activated += new EventHandler(OnTeamSelection);
-			noTeam.Activated += new EventHandler(OnTeamSelection);
-			localPlayers.Activated += new EventHandler(OnLocalPlayers);
-			visitorPlayers.Activated += new EventHandler (OnVisitorPlayers);
-			addPLN.Activated += new EventHandler(OnAdded);
-			quit.Activated += new EventHandler(OnDeleted);
-			snapshot.Activated += new EventHandler(OnSnapshot);
+			name.Activated += OnEdit;
+			local.Activated += OnTeamSelection;
+			visitor.Activated += OnTeamSelection;
+			noTeam.Activated += OnTeamSelection;
+			localPlayers.Activated += OnLocalPlayers;
+			visitorPlayers.Activated += OnVisitorPlayers;
+			addPLN.Activated += OnAdded;
+			quit.Activated += OnDeleted;
+			deleteKeyFrame.Activated += OnDeleteKeyFrame;
+			snapshot.Activated += OnSnapshot;
 			menu.ShowAll();		
 		}
 		
@@ -280,8 +284,10 @@ namespace LongoMatch.Gui.Component
 				if (path!=null){
 					this.Model.GetIter (out selectedIter,path); 
 					selectedTimeNode = (TimeNode)this.Model.GetValue (selectedIter, 0);
-					if (selectedTimeNode is MediaTimeNode )
+					if (selectedTimeNode is MediaTimeNode ){
+						deleteKeyFrame.Sensitive = (selectedTimeNode as MediaTimeNode).KeyFrameDrawing != null;
 					    menu.Popup();
+					}
 					else{
 						nameCell.Editable = true;
 						this.SetCursor(path,  nameColumn, true);
@@ -296,6 +302,20 @@ namespace LongoMatch.Gui.Component
 				TimeNodeDeleted((MediaTimeNode)selectedTimeNode,int.Parse(path.ToString().Split(':')[0]));
 		}
 		
+		protected void OnDeleteKeyFrame(object obj, EventArgs args){
+			MessageDialog md = new MessageDialog((Gtk.Window)Toplevel,
+			                                     DialogFlags.Modal,
+			                                     MessageType.Question,
+			                                     ButtonsType.YesNo,
+			                                     false,
+			                                     Catalog.GetString("Do you want to delete the key frame for this play?")
+			                                     );
+			if (md.Run() == (int)ResponseType.Yes)
+				//TODO also refresh the thumbnail
+				(selectedTimeNode as MediaTimeNode).KeyFrameDrawing = null;
+			md.Destroy();
+		}
+		
 		protected virtual void OnEdit(object obj, EventArgs args){
 			nameCell.Editable = true;
 			this.SetCursor(path,  nameColumn, true);
diff --git a/LongoMatch/Handlers/EventsManager.cs b/LongoMatch/Handlers/EventsManager.cs
index e28b700..21b2c93 100644
--- a/LongoMatch/Handlers/EventsManager.cs
+++ b/LongoMatch/Handlers/EventsManager.cs
@@ -192,8 +192,7 @@ namespace LongoMatch
 			player.SetStartStop(tNode.Start.MSeconds,tNode.Stop.MSeconds);		
 			notes.Visible = true;
 			notes.Play= tNode;
-			drawingManager.SetDrawings(tNode.DrawingsList,tNode.Start.MSeconds);
-			drawingManager.StartClock();
+			drawingManager.Drawing=tNode.KeyFrameDrawing;
 		}
 		
 		
@@ -264,7 +263,6 @@ namespace LongoMatch
 			selectedTimeNode = null;
 			timeline.SelectedTimeNode = null;
 			notes.Visible = false;
-			drawingManager.StopClock();
 		}
 		
 		protected virtual void OnSnapshotSeries(MediaTimeNode tNode){
@@ -333,6 +331,7 @@ namespace LongoMatch
 			if (selectedTimeNode != null)
 				dialog.SetPlay((selectedTimeNode as MediaTimeNode),
 				                time);
+			player.Pause();
 			dialog.Run();
 			dialog.Destroy();
 			pixbuf.Dispose();
diff --git a/LongoMatch/Handlers/VideoDrawingsManager.cs b/LongoMatch/Handlers/VideoDrawingsManager.cs
index 38184aa..6acd1ed 100644
--- a/LongoMatch/Handlers/VideoDrawingsManager.cs
+++ b/LongoMatch/Handlers/VideoDrawingsManager.cs
@@ -25,6 +25,7 @@ using LongoMatch.Video.Handlers;
 
 
 
+
 namespace LongoMatch.Handlers
 {
 	
@@ -33,84 +34,111 @@ namespace LongoMatch.Handlers
 	{
 		private PlayerBin player;
 		private uint timeout;
-		private SortedDictionary<int,Drawing> drawingsList;
-		private List<int> stopTimes;
-		private int nextStopTimeIndex;
-		//Monitorize the drawings list to recalculate the stop time;
-		private int previousDrawingsListSize; 
-		//False when the user is seeking using the scale
 		private bool canStop;
-		private object locker;
+		private bool inKeyFrame;
+		private Drawing drawing;
+		/*//Monitorize the drawings list to recalculate the stop time;
+		//private int previousDrawingsListSize; 
+		//False when the user is seeking using the scale
+		private DrawingsList drawingsList;
+		private int nextStopTimeIndex;
+		private object locker;*/		
 			
 		public VideoDrawingsManager(PlayerBin player)
 		{
 			this.player = player;
+			//False if the current play has no keyframe or if we are in 
+			//the middle of a seek
 			canStop = true;
 			timeout = 0;
-			locker = new Object();
-			stopTimes = new List<int>();
-			player.StateChanged += OnStateChanged;
-			player.SeekEvent += OnSeekEvent;
+			//locker = new Object();
 		}
 		
 		~ VideoDrawingsManager(){
 			StopClock();
 		}
 		
-		public void SetDrawings(SortedDictionary<int,Drawing> drawings,int startTime){
-			drawingsList = drawings;
+		/*public void SetDrawings(DrawingsList drawingsList,int startTime){
+			this.drawingsList = drawingsList;
 			previousDrawingsListSize = drawingsList.Count;
-			RebuildStopTimes(startTime);					
+			RecalculateNextStopTime(0);
+			StartClock();
+			ConnectSignals();
+		}*/
+		
+		public Drawing Drawing{
+			set{
+				drawing = value;
+				canStop = (drawing!=null);
+				if (canStop){
+					StartClock();
+					ConnectSignals();
+				}
+			}
 		}
 		
-		public void StartClock(){
-			timeout = GLib.Timeout.Add (20,CheckStopTime);
+		private void StartClock(){
+			if (timeout ==0)
+				timeout = GLib.Timeout.Add (20,CheckStopTime);
 		}
 		
-		public void StopClock(){
+		private void StopClock(){
 			if (timeout != 0){
 				GLib.Source.Remove(timeout);
 				timeout = 0;
 			}
 		}
 		
-		private void RebuildStopTimes(int currentTime){
-			stopTimes.Clear();
-			foreach(KeyValuePair<int,Drawing> pair in drawingsList){
-				stopTimes.Add(pair.Key);
-				Console.WriteLine("Added stoptime value:"+pair.Key);
-			}
-			RecalculateNextStopTime(currentTime);
-			previousDrawingsListSize=drawingsList.Count;
+		private void ConnectSignals(){
+			player.StateChanged += OnStateChanged;
+			player.SeekEvent += OnSeekEvent;
+			player.SegmentClosedEvent += OnSegmentCloseEvent;			
+		}
+		
+		private void DisconnectSignals(){
+			player.StateChanged -= OnStateChanged;
+			player.SeekEvent -= OnSeekEvent;
+			player.SegmentClosedEvent -= OnSegmentCloseEvent;			
 		}
 		
+		private int NextStopTime(){
+			//return drawingsList.GetStopTime(nextStopTimeIndex);
+			return drawing.StopTime;
+		}
+		/*
 		private void RecalculateNextStopTime (int currentTime){
+			if (drawingsList.Count == 0)
+				canStop = false;
+			else 
+				canStop = true;
 			nextStopTimeIndex = 0;
-			foreach (int time in stopTimes){
+			foreach (int time in drawingsList.StopTimes){
+				Console.WriteLine("Stop Time :"+time);				
 				if (time >= currentTime){
-					Console.WriteLine("Next Stop Time is :"+stopTimes[nextStopTimeIndex]);
+					Console.WriteLine("Next Stop Time is :"+NextStopTime());
 					return;
 				}
 				nextStopTimeIndex++;
 			}
-		}
+		}*/
 		
-		private void PrintDrawings(){
-			Pixbuf frame;
-			Drawing drawing;
-			int key = stopTimes[nextStopTimeIndex];			
+		private void PrintDrawing(){
+			Pixbuf frame = null;
+			//Drawing drawing;
 			
+			canStop=false;
 			player.Pause();
-			frame = player.CurrentFrame;
-			if (!drawingsList.TryGetValue(key,out drawing)){
-				return;
-			}
-			
+			player.SeekInSegment(drawing.StopTime);
+			while (frame == null)
+				frame = player.CurrentFrame;			
+			//drawing = drawingsList.GetStopDrawing(nextStopTimeIndex);
 			player.LogoPixbuf = frame;
 			frame.Dispose();
 			player.DrawingPixbuf = drawing.Pixbuf;
 			player.LogoMode = true;
-			player.DrawingMode = true;			
+			player.DrawingMode = true;
+			inKeyFrame = true;
+			Console.WriteLine("Seetting keyframe"+inKeyFrame);
 		}
 		
 		private void ResetPlayerWindow(){
@@ -121,35 +149,68 @@ namespace LongoMatch.Handlers
 		
 		private bool CheckStopTime(){
 			int currentTime = (int)player.AccurateCurrentTime;
+			/*
 			//If size has changed, we need to recalculate the
 			//the next stop time
 			if (drawingsList.Count != previousDrawingsListSize){
 				lock (locker){
-					RebuildStopTimes(currentTime);
+					Console.WriteLine("Added/Removed drawings");
+					RecalculateNextStopTime(currentTime);
+					previousDrawingsListSize = drawingsList.Count;
 				}
 			}
 			//If we are in middle of seek or we don't have any drawings don't draw anything
-			if (!canStop || stopTimes.Count == 0)
+		    if (!canStop || drawingsList.Count == 0)
+				return true;*/
+			if (!canStop || drawing == null)
 				return true;
-			if ((currentTime-10)>stopTimes[nextStopTimeIndex]){
+			if ((currentTime)>NextStopTime()){
 				StopClock();
-				PrintDrawings();
-				if (stopTimes.Count-1 != nextStopTimeIndex)
+				PrintDrawing();
+				/*if (drawingsList.Count-1 != nextStopTimeIndex){
 					nextStopTimeIndex++;
+					Console.WriteLine("Next Stop Time is :"+NextStopTime());
+				}
+				else {
+					Console.WriteLine("No more Drawings");
+					canStop = false;
+				}*/
 			}
 			return true;	
 		}
 		
 		protected virtual void OnStateChanged (object sender, StateChangeArgs args){
-			if (args.Playing)
+			//Check if we are currently paused displaying the key frame waiting for the user to
+			//go in to Play. If so we can stop
+			Console.WriteLine(inKeyFrame);
+			if (inKeyFrame){
 				ResetPlayerWindow();
+				inKeyFrame = false;
+				canStop=false;
+				StartClock();
+			}
 		}
 		
-		protected virtual void OnSeekEvent (object sender, EventArgs args){
-			ResetPlayerWindow();
-			lock (locker){
-				RecalculateNextStopTime ((int)player.AccurateCurrentTime);
+		protected virtual void OnSeekEvent (long time){
+			Console.WriteLine("Seek event.."+inKeyFrame);
+			if (drawing == null)
+				return;
+			if(inKeyFrame){
+				ResetPlayerWindow();
+				inKeyFrame = false;	
 			}
+			canStop = time < drawing.StopTime;
+			if (canStop)
+				StartClock();
+			/*lock (locker){
+				RecalculateNextStopTime ((int)player.AccurateCurrentTime);
+			}*/
+		}
+		
+		protected virtual void OnSegmentCloseEvent(){
+			ResetPlayerWindow();
+			DisconnectSignals();
+			StopClock();			
 		}
 		
 	}
diff --git a/LongoMatch/LongoMatch.mdp b/LongoMatch/LongoMatch.mdp
index 3140d2f..4433ad3 100644
--- a/LongoMatch/LongoMatch.mdp
+++ b/LongoMatch/LongoMatch.mdp
@@ -161,6 +161,7 @@
     <File name="gtk-gui/LongoMatch.Gui.Dialog.DrawingTool.cs" subtype="Code" buildaction="Compile" />
     <File name="Time/Drawing.cs" subtype="Code" buildaction="Compile" />
     <File name="Handlers/VideoDrawingsManager.cs" subtype="Code" buildaction="Compile" />
+    <File name="Time/DrawingsList.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Gac" localcopy="True" refto="Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
diff --git a/LongoMatch/Main.cs b/LongoMatch/Main.cs
index 7b61ebb..b1eb460 100644
--- a/LongoMatch/Main.cs
+++ b/LongoMatch/Main.cs
@@ -68,7 +68,10 @@ namespace LongoMatch
 				
 			//Comprobamos los archivos de inicio
 			CheckDirs();
-			CheckFiles();			
+			CheckFiles();		
+			
+			
+			
 			
 			//Iniciamos la base de datos
 			db = new DataBase(Path.Combine(DBDir(),"longomatch.db"));			
@@ -210,7 +213,7 @@ namespace LongoMatch
 			}		
 		}		
 			
-		private static void OnException(GLib.UnhandledExceptionArgs args){			
+		private static void OnException(GLib.UnhandledExceptionArgs args){
 			ProcessExecutionError((Exception)args.ExceptionObject);				
 		}
 		
diff --git a/LongoMatch/Time/Drawing.cs b/LongoMatch/Time/Drawing.cs
index bc72d74..a6a0aca 100644
--- a/LongoMatch/Time/Drawing.cs
+++ b/LongoMatch/Time/Drawing.cs
@@ -21,13 +21,17 @@ using Gdk;
 
 namespace LongoMatch.TimeNodes
 {
-	
+	[Serializable]
 	public class Drawing
 	{
 		private byte[] drawingBuf;
-		private Time stopTime;
+		private readonly int stopTime;
 		
-		public Drawing(Pixbuf drawing,Time stopTime)
+		
+		public Drawing(){
+		}
+		
+		public Drawing(Pixbuf drawing,int stopTime)
 		{
 			Pixbuf = drawing;
 			this.stopTime = stopTime;
@@ -40,12 +44,15 @@ namespace LongoMatch.TimeNodes
 				else return null;
 			}
 			set {
-				drawingBuf = value.SaveToBuffer("png");
+				if(value != null)
+					drawingBuf = value.SaveToBuffer("png");
+				else
+					drawingBuf = null;
 			}
 		}	
 		
-		public Time StopTime{
+		public int StopTime{
 			get{return stopTime;}
-		}
+		}		
 	}
 }
diff --git a/LongoMatch/Time/MediaTimeNode.cs b/LongoMatch/Time/MediaTimeNode.cs
index 579bf48..2aa0a11 100644
--- a/LongoMatch/Time/MediaTimeNode.cs
+++ b/LongoMatch/Time/MediaTimeNode.cs
@@ -57,7 +57,8 @@ namespace LongoMatch.TimeNodes
 											// We use the int index of the player in the template,		
 		private List<int> visitorPlayersList;// because it's the only unmutable variable
 		
-		private SortedDictionary<int,Drawing> drawingsList; 
+		private Drawing keyFrame;
+		
 
 		
 #region Constructors	
@@ -69,7 +70,6 @@ namespace LongoMatch.TimeNodes
 			this.stopFrame = (uint) this.Stop.MSeconds*fps/1000;
 			localPlayersList = new List<int>();
 			visitorPlayersList = new List<int>();
-			drawingsList = new SortedDictionary<int, Drawing>();
 		}
 		#endregion
 		
@@ -112,8 +112,16 @@ namespace LongoMatch.TimeNodes
 				this.stopFrame = value;
 				this.Stop = new Time((int)(1000*value/fps));
 			}
-		}		
+		}
 		
+		public uint KeyFrame{
+			get {
+				if (HasKeyFrame)
+					return (uint) KeyFrameDrawing.StopTime*fps/1000;
+				else return 0;
+			}
+		}
+	
 		public bool Selected {
 			get {return selected;}
 			set{this.selected = value;}			
@@ -129,18 +137,17 @@ namespace LongoMatch.TimeNodes
 			get{return visitorPlayersList;}
 		}
 		
-		public SortedDictionary<int,Drawing> DrawingsList{
-			set { drawingsList = value;}
-			get {
-				//Maintain compatibility with previous DB version where this list does not exists
-				if (drawingsList == null){                
-					drawingsList = new SortedDictionary<int, Drawing>();  
-				}
-				return drawingsList;
-			}
+		public Drawing KeyFrameDrawing{
+			set{keyFrame = value;}
+			get{return keyFrame;}
+		}
+		
+		public bool HasKeyFrame{
+			get{return keyFrame != null;}
 		}
 		
 		
+			
 		#endregion
 		
 		#region Public methods
@@ -164,25 +171,7 @@ namespace LongoMatch.TimeNodes
 		public void RemoveVisitorPlayer(int index){
 			visitorPlayersList.Remove(index);			
 		}
-		
-		public void AddDrawing (Drawing drawing){
-			//Maintain compatibility with previous DB version where this list does not exists
-			if (drawingsList == null){               
-				drawingsList = new SortedDictionary<int, Drawing>();  
-			}
-			if (drawingsList.ContainsKey(drawing.StopTime.MSeconds)){
-				drawingsList.Remove(drawing.StopTime.MSeconds);				
-			}
-			drawingsList.Add(drawing.StopTime.MSeconds,drawing);
-		}
-		
-		public void RemoveDrawing (Drawing drawing){
-			try{
-				drawingsList.Remove(drawing.StopTime.MSeconds);
-			}catch{}//Fallback sillently
-		}
-		
+	
 		#endregion
-	}
-		
+	}		
 }
diff --git a/LongoMatch/Time/PixbufTimeNode.cs b/LongoMatch/Time/PixbufTimeNode.cs
index 101804d..5d7945e 100644
--- a/LongoMatch/Time/PixbufTimeNode.cs
+++ b/LongoMatch/Time/PixbufTimeNode.cs
@@ -28,7 +28,8 @@ namespace LongoMatch.TimeNodes
 	public class PixbufTimeNode : TimeNode
 	{
 		private byte[] thumbnailBuf;
-		
+		private const int MAX_WIDTH=50;
+		private const int MAX_HEIGHT=50;
 		#region Contructors
 		public PixbufTimeNode(){
 		}	
@@ -50,10 +51,37 @@ namespace LongoMatch.TimeNodes
 				if (thumbnailBuf != null)
 					return new Pixbuf(thumbnailBuf);
 				else return null;
-			}
-		}		
-		
-		
+			}set{
+				if (value != null)
+					ScaleAndSave(value);
+				else thumbnailBuf = null;
+			}			
+		}			
+				
 		#endregion
+		
+		private void ScaleAndSave(Pixbuf pixbuf) {
+			int ow,oh,h,w;
+			 
+			h = ow = pixbuf.Height;
+			w = oh = pixbuf.Width;
+			ow = MAX_WIDTH;
+			oh = MAX_HEIGHT;
+			Console.WriteLine(w);
+			Console.WriteLine(h);
+			if (w>MAX_WIDTH || h>MAX_HEIGHT){
+				double rate = (double)w/(double)h;				
+				if (h>w){
+					ow= (int)(ow*rate);
+				}else{
+					oh = (int)(oh/rate);
+				}
+				Console.WriteLine(ow);
+				Console.WriteLine(oh);
+				thumbnailBuf = pixbuf.ScaleSimple(ow,oh,Gdk.InterpType.Bilinear).SaveToBuffer("png");
+				pixbuf.Dispose();
+			}	
+			else thumbnailBuf =  pixbuf.SaveToBuffer("png");
+		}
 	}
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]