[longomatch] New Feature: Support for store a drawings in a plays named Key Frame and redraw it when the player r



commit 7a5065548dddee1ab244940af7880f6cd9e3a6a3
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Wed Oct 14 20:57:51 2009 +0200

    New Feature: Support for store a drawings in a plays named Key Frame and redraw it when the player reaches this instant
    
    Conflicts:
    
    	libcesarplayer/src/bacon-video-widget-gst-0.10.c

 CesarPlayer/Gui/PlayerBin.cs                       |   69 +++++++--
 CesarPlayer/Handlers/Handlers.cs                   |    3 +-
 CesarPlayer/Player/GstPlayer.cs                    |   22 +++-
 CesarPlayer/Player/IPlayer.cs                      |   12 ++
 CesarPlayer/gtk-gui/objects.xml                    |    3 +-
 LongoMatch/DB/DataBase.cs                          |    3 +-
 LongoMatch/Gui/Component/DrawingWidget.cs          |    7 +-
 LongoMatch/Gui/Component/TimeScale.cs              |   81 ++++++-----
 LongoMatch/Gui/Dialog/DrawingTool.cs               |   24 +++-
 LongoMatch/Gui/MainWindow.cs                       |   11 ++-
 LongoMatch/Gui/TreeView/PlaysTreeView.cs           |   40 ++++--
 LongoMatch/Handlers/EventsManager.cs               |    9 +-
 LongoMatch/Handlers/VideoDrawingsManager.cs        |  156 ++++++++++++++++++++
 LongoMatch/LongoMatch.mdp                          |    3 +
 LongoMatch/Main.cs                                 |   21 +--
 LongoMatch/Makefile.am                             |    2 +
 LongoMatch/Time/Drawing.cs                         |   58 +++++++
 LongoMatch/Time/MediaTimeNode.cs                   |   28 +++-
 LongoMatch/Time/PixbufTimeNode.cs                  |   34 ++++-
 LongoMatch/Time/TimeNode.cs                        |    5 +-
 .../gtk-gui/LongoMatch.Gui.Dialog.DrawingTool.cs   |   93 +++++++++---
 LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs    |   11 +-
 LongoMatch/gtk-gui/gui.stetic                      |   41 ++++--
 libcesarplayer/src/bacon-video-widget-gst-0.10.c   |   68 +++++++--
 libcesarplayer/src/bacon-video-widget.h            |    8 +
 25 files changed, 661 insertions(+), 151 deletions(-)
---
diff --git a/CesarPlayer/Gui/PlayerBin.cs b/CesarPlayer/Gui/PlayerBin.cs
index bd3c1e4..512427a 100644
--- a/CesarPlayer/Gui/PlayerBin.cs
+++ b/CesarPlayer/Gui/PlayerBin.cs
@@ -38,10 +38,12 @@ namespace LongoMatch.Gui
 		public event SegmentClosedHandler SegmentClosedEvent;
 		public event TickHandler Tick;
 		public event ErrorHandler Error;
+		public event StateChangeHandler StateChanged;
 		public event NextButtonClickedHandler Next;
 		public event PrevButtonClickedHandler Prev;
 		public event DrawFrameHandler DrawFrame;
-		
+		public event SeekEventHandler SeekEvent;
+			
 		private const int THUMBNAIL_WIDTH = 50;
 		private TickHandler tickHandler;
 		private IPlayer player;
@@ -121,10 +123,21 @@ namespace LongoMatch.Gui
 			}
 		}
 		
-		public bool LogoMode {
-			get{return player.LogoMode;}
+		public Pixbuf LogoPixbuf{
+			set{player.LogoPixbuf = value;}
+		}
+		
+		public bool DrawingMode {
+			set{player.DrawingMode= value;}
+		}
+		
+		public Pixbuf DrawingPixbuf {
+			set{player.DrawingPixbuf=value;}
+		}
+		
+		public bool LogoMode{
 			set{player.LogoMode = value;}
-		}		
+		}
 		
 		public bool ExpandLogo {
 			get{return player.ExpandLogo;}
@@ -204,31 +217,47 @@ namespace LongoMatch.Gui
 		
 		public void SeekTo(long time, bool accurate){
 			player.SeekTime(time,1,accurate);
+			if (SeekEvent != null)
+				SeekEvent(time);
 		}
 		
 		public void SeekInSegment(long pos){
 			player.SeekInSegment(pos, GetRateFromScale());
+			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);
+				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);
+				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){
@@ -316,6 +345,8 @@ namespace LongoMatch.Gui
 				playbutton.Show();
 				pausebutton.Hide();
 			}
+			if (StateChanged != null)
+				StateChanged(this,args);
 		}
 		
 		protected void OnReadyToSeek(object o, EventArgs args){
@@ -501,12 +532,26 @@ namespace LongoMatch.Gui
 		
 		protected virtual void OnDrawButtonClicked (object sender, System.EventArgs e)
 		{
-			if (DrawFrame != null)
-				DrawFrame(CurrentFrame);
+			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 972c0e9..2460ff1 100644
--- a/CesarPlayer/Handlers/Handlers.cs
+++ b/CesarPlayer/Handlers/Handlers.cs
@@ -27,12 +27,13 @@ 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 ();
 	public delegate void ProgressHandler (float progress);
 	public delegate void FramesProgressHandler (int actual, int total,Pixbuf frame);
-	public delegate void DrawFrameHandler (Pixbuf frame);
+	public delegate void DrawFrameHandler (Pixbuf frame,int time);
 
 	
 	
diff --git a/CesarPlayer/Player/GstPlayer.cs b/CesarPlayer/Player/GstPlayer.cs
index 6d0d029..819064e 100644
--- a/CesarPlayer/Player/GstPlayer.cs
+++ b/CesarPlayer/Player/GstPlayer.cs
@@ -70,7 +70,7 @@ namespace LongoMatch.Video.Player {
 			set  {
 				bacon_video_widget_set_logo_mode(Handle, value);
 			}
-		}
+		}			
 		
 		[GLib.Property ("expand_logo")]
 		public bool ExpandLogo {
@@ -1074,6 +1074,24 @@ namespace LongoMatch.Video.Player {
 				bacon_video_widget_set_logo_pixbuf(Handle, value == null ? IntPtr.Zero : value.Handle);
 			}
 		}
+		
+		[DllImport("libcesarplayer.dll")]
+		static extern void bacon_video_widget_set_drawing_pixbuf(IntPtr raw, IntPtr drawing_mode);
+
+		public Gdk.Pixbuf DrawingPixbuf {
+			set  {
+				bacon_video_widget_set_drawing_pixbuf(Handle, value == null ? IntPtr.Zero : value.Handle);
+			}
+		}
+		
+		[DllImport("libcesarplayer.dll")]
+		static extern void bacon_video_widget_set_drawing_mode(IntPtr raw, bool drawing_mode);
+
+		public bool DrawingMode {
+			set  {
+				bacon_video_widget_set_drawing_mode(Handle, value);
+			}
+		}
 
 		/*[DllImport("libcesarplayer.dll")]
 		static extern void bacon_video_widget_set_visuals_quality(IntPtr raw, int quality);
@@ -1122,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/Player/IPlayer.cs b/CesarPlayer/Player/IPlayer.cs
index 2f1d6d8..1abf1b2 100644
--- a/CesarPlayer/Player/IPlayer.cs
+++ b/CesarPlayer/Player/IPlayer.cs
@@ -65,6 +65,14 @@ namespace LongoMatch.Video.Player
 			set;
 		}
 		
+		bool DrawingMode {
+			set;
+		}
+		
+		Pixbuf DrawingPixbuf {
+			set;
+		}
+		
 		bool ExpandLogo{
 			get;
 			set;
@@ -83,6 +91,10 @@ namespace LongoMatch.Video.Player
 			set;
 		}
 		
+		Pixbuf LogoPixbuf{
+			set;
+		}
+		
 		long AccurateCurrentTime{
 			get;
 		}
diff --git a/CesarPlayer/gtk-gui/objects.xml b/CesarPlayer/gtk-gui/objects.xml
index c75d338..13e8c72 100644
--- a/CesarPlayer/gtk-gui/objects.xml
+++ b/CesarPlayer/gtk-gui/objects.xml
@@ -7,7 +7,6 @@
     <itemgroups>
       <itemgroup label="PlayerBin Properties">
         <property name="Rate" />
-        <property name="LogoMode" />
         <property name="ExpandLogo" />
       </itemgroup>
     </itemgroups>
@@ -16,9 +15,11 @@
         <signal name="SegmentClosedEvent" />
         <signal name="Tick" />
         <signal name="Error" />
+        <signal name="StateChanged" />
         <signal name="Next" />
         <signal name="Prev" />
         <signal name="DrawFrame" />
+        <signal name="SeekEvent" />
       </itemgroup>
     </signals>
   </object>
diff --git a/LongoMatch/DB/DataBase.cs b/LongoMatch/DB/DataBase.cs
index 9bab21a..1c6446b 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(Player)).CascadeOnDelete(true);
 			Db4oFactory.Configure().ObjectClass(typeof(TeamTemplate)).CascadeOnDelete(true);
+			Db4oFactory.Configure().ObjectClass(typeof(Drawing)).CascadeOnDelete(true);
 		}
 		
 		private bool Exists(string filename){
diff --git a/LongoMatch/Gui/Component/DrawingWidget.cs b/LongoMatch/Gui/Component/DrawingWidget.cs
index 9c653b8..e611984 100644
--- a/LongoMatch/Gui/Component/DrawingWidget.cs
+++ b/LongoMatch/Gui/Component/DrawingWidget.cs
@@ -156,16 +156,19 @@ namespace LongoMatch.Gui.Component
 			Save(filename,true,true);
 		}
 		
+		public void SaveDrawings(string filename){
+			Save(filename,false,true);
+		}
 		
 		private void Save(string filename,bool bSource,bool bDrawings){
 			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..ff20a3f 100644
--- a/LongoMatch/Gui/Component/TimeScale.cs
+++ b/LongoMatch/Gui/Component/TimeScale.cs
@@ -165,8 +165,7 @@ namespace LongoMatch.Gui.Component
 				using (Cairo.Context g = Gdk.CairoHelper.Create (win)){	
 					int height;
 					int width;	
-
-				
+			
 					win.Resize((int)(frames/pixelRatio), Allocation.Height);
 					win.GetSize(out width, out height);				
 				
@@ -179,7 +178,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 +188,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 +228,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 +239,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 +259,7 @@ namespace LongoMatch.Gui.Component
 					del.Activated += new EventHandler(OnDelete);				
 					deleteMenu.Append(del);
 					dic.Add(del,tn);					
-				}
-				
+				}				
 			}	
 			menu.ShowAll();
 			menu.Popup();		
@@ -266,6 +270,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 +280,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 +329,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){
+				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 5480279..855bbac 100644
--- a/LongoMatch/Gui/Dialog/DrawingTool.cs
+++ b/LongoMatch/Gui/Dialog/DrawingTool.cs
@@ -21,6 +21,7 @@ using Gdk;
 using Gtk;
 using Mono.Unix;
 using LongoMatch.Gui.Component;
+using LongoMatch.TimeNodes;
 
 namespace LongoMatch.Gui.Dialog
 {
@@ -28,6 +29,8 @@ namespace LongoMatch.Gui.Dialog
 	
 	public partial class DrawingTool : Gtk.Dialog
 	{
+		private MediaTimeNode play;
+		private int stopTime;
 		
 		public DrawingTool()
 		{
@@ -39,9 +42,13 @@ namespace LongoMatch.Gui.Dialog
 		}
 		
 		public Pixbuf Image{
-			set{
-				drawingwidget1.SourceImage = value;			
-			}
+			set{drawingwidget1.SourceImage = value;}
+		}
+		
+		public void SetPlay(MediaTimeNode play,int stopTime){
+			this.play = play;	
+			this.stopTime = stopTime;
+			savetoprojectbutton.Visible = true;			
 		}
 
 		protected virtual void OnDrawingtoolbox1LineWidthChanged (int width)
@@ -99,5 +106,16 @@ namespace LongoMatch.Gui.Dialog
 			}
 			fChooser.Destroy();		
 		}
+
+		protected virtual void OnSavetoprojectbuttonClicked (object sender, System.EventArgs e)
+		{
+			string tempFile = System.IO.Path.GetTempFileName();
+			drawingwidget1.SaveDrawings(tempFile);
+			Pixbuf frame = new Pixbuf(tempFile);
+			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 d1b3c90..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){	
@@ -396,6 +398,13 @@ namespace LongoMatch.Gui
 					else
 						playerbin1.SeekToNextFrame(true);
 				}
+				if (key == Gdk.Key.q){
+					playerbin1.LogoMode=true;
+				}
+				if (key == Gdk.Key.r){
+					playerbin1.LogoMode=false;
+				}
+				
 			}
 			return base.OnKeyPressEvent (evnt);
 		}
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 6f48eb7..e9a6918 100644
--- a/LongoMatch/Handlers/EventsManager.cs
+++ b/LongoMatch/Handlers/EventsManager.cs
@@ -50,6 +50,7 @@ namespace LongoMatch
 		private NotesWidget notes;
 		private FramesSeriesCapturer fsc;
 		private FramesCaptureProgressDialog fcpd;
+		private VideoDrawingsManager drawingManager;
 		
 		// Current play loaded. null if no play is loaded
 		private TimeNode selectedTimeNode=null;
@@ -69,6 +70,7 @@ namespace LongoMatch
 			this.timeline = timeline;	
 			this.videoprogressbar = videoprogressbar;
 			this.notes = notes;
+			this.drawingManager = new VideoDrawingsManager(player);
 			
 			ConnectSignals();
 		}
@@ -190,6 +192,7 @@ namespace LongoMatch
 			player.SetStartStop(tNode.Start.MSeconds,tNode.Stop.MSeconds);		
 			notes.Visible = true;
 			notes.Play= tNode;
+			drawingManager.Play=tNode;
 		}
 		
 		
@@ -321,10 +324,14 @@ namespace LongoMatch
 			plNode.Rate = player.Rate;
 		}
 		
-		protected virtual void OnDrawFrame (Pixbuf pixbuf){
+		protected virtual void OnDrawFrame (Pixbuf pixbuf,int time){
 			DrawingTool dialog = new DrawingTool();
 			dialog.TransientFor = (Gtk.Window)player.Toplevel;
 			dialog.Image = pixbuf;
+			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
new file mode 100644
index 0000000..219b2fd
--- /dev/null
+++ b/LongoMatch/Handlers/VideoDrawingsManager.cs
@@ -0,0 +1,156 @@
+// 
+//  Copyright (C) 2009 Andoni Morales Alastruey
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//  
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// 
+
+using System;
+using System.Collections.Generic;
+using Gdk;
+using LongoMatch.TimeNodes;
+using LongoMatch.Gui;
+using LongoMatch.Video.Handlers;
+
+
+
+
+namespace LongoMatch.Handlers
+{
+	
+	
+	public class VideoDrawingsManager
+	{
+		private PlayerBin player;
+		private uint timeout;
+		private bool inKeyFrame;
+		private bool canStop;
+		private MediaTimeNode loadedPlay;
+					
+		public VideoDrawingsManager(PlayerBin player)
+		{
+			this.player = player;
+			timeout = 0;
+		}
+		
+		~ VideoDrawingsManager(){
+			StopClock();
+		}
+		
+		public MediaTimeNode Play{
+			set{
+				loadedPlay = value;
+				inKeyFrame = false;
+				canStop = true;
+				ResetPlayerWindow();
+				ConnectSignals();
+				StartClock();
+			}
+		}
+		
+		private Drawing Drawing{
+			get{ return loadedPlay.KeyFrameDrawing;}
+		}
+		
+		private void StartClock(){
+			if (timeout ==0)
+				timeout = GLib.Timeout.Add (20,CheckStopTime);
+		}
+		
+		private void StopClock(){
+			if (timeout != 0){
+				GLib.Source.Remove(timeout);
+				timeout = 0;
+			}
+		}
+		
+		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 Drawing.StopTime;
+		}
+				
+		private void PrintDrawing(){
+			Pixbuf frame = null;
+
+			player.Pause();
+			player.SeekInSegment(Drawing.StopTime);
+			while (frame == null)
+				frame = player.CurrentFrame;			
+			player.LogoPixbuf = frame;
+			frame.Dispose();
+			player.DrawingPixbuf = Drawing.Pixbuf;
+			player.LogoMode = true;
+			player.DrawingMode = true;
+			inKeyFrame = true;
+		}
+		
+		private void ResetPlayerWindow(){
+			player.LogoMode = false;
+			player.DrawingMode = false;
+			player.SetLogo(System.IO.Path.Combine(MainClass.ImagesDir(),"background.png"));
+		}
+		
+		private bool CheckStopTime(){
+			int currentTime = (int)player.AccurateCurrentTime;
+
+			if (Drawing == null || !canStop)
+				return true;
+			if ((currentTime)>NextStopTime()){
+				StopClock();
+				PrintDrawing();
+			}
+			return true;	
+		}
+		
+		protected virtual void OnStateChanged (object sender, StateChangeArgs args){
+			//Check if we are currently paused displaying the key frame waiting for the user to
+			//go in to Play. If so we can stop
+			if (inKeyFrame){
+				ResetPlayerWindow();
+				inKeyFrame = false;				
+			}
+		}
+		
+		protected virtual void OnSeekEvent (long time){
+			if (Drawing == null)
+				return;
+			if(inKeyFrame){
+				ResetPlayerWindow();
+				inKeyFrame = false;	
+			}
+			canStop = time < Drawing.StopTime;
+			if (canStop)
+				StartClock();
+			else StopClock();
+		}
+		
+		protected virtual void OnSegmentCloseEvent(){
+			ResetPlayerWindow();
+			DisconnectSignals();
+			StopClock();			
+		}
+		
+	}
+}
diff --git a/LongoMatch/LongoMatch.mdp b/LongoMatch/LongoMatch.mdp
index f84406d..4433ad3 100644
--- a/LongoMatch/LongoMatch.mdp
+++ b/LongoMatch/LongoMatch.mdp
@@ -159,6 +159,9 @@
     <File name="Gui/Component/DrawingWidget.cs" subtype="Code" buildaction="Compile" />
     <File name="Gui/Dialog/DrawingTool.cs" subtype="Code" buildaction="Compile" />
     <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 cc9b760..211f9ef 100644
--- a/LongoMatch/Main.cs
+++ b/LongoMatch/Main.cs
@@ -55,8 +55,7 @@ namespace LongoMatch
 			}
 					
 			//Iniciamos la internalización
-			Catalog.Init("longomatch",RelativeToPrefix("share/locale"));
-			
+			Catalog.Init("longomatch",RelativeToPrefix("share/locale"));			
 								
 			//Iniciamos la aplicación
 			Application.Init ();
@@ -64,15 +63,13 @@ namespace LongoMatch
 			GLib.ExceptionManager.UnhandledException += new GLib.UnhandledExceptionHandler(OnException);
 				
 			LongoMatch.Video.Player.GstPlayer.InitBackend("");
-			
-				
+							
 			//Comprobamos los archivos de inicio
 			CheckDirs();
 			CheckFiles();			
 			
 			//Iniciamos la base de datos
 			db = new DataBase(Path.Combine(DBDir(),"longomatch.db"));			
-		
 			
 			//Check for previous database
 			CheckOldFiles();
@@ -81,8 +78,7 @@ namespace LongoMatch
 				MainWindow win = new MainWindow ();
 				win.Show ();			
 				Application.Run ();
-			}
-			catch (Exception ex){
+			}catch (Exception ex){
 				ProcessExecutionError(ex);				
 			}			
 		}
@@ -93,8 +89,7 @@ namespace LongoMatch
 		
 		public static string HomeDir(){
 				return homeDirectory;	
-		}
-		
+		}		
 
 		public static string PlayListDir(){
 			return System.IO.Path.Combine (homeDirectory, "playlists");
@@ -183,12 +178,6 @@ namespace LongoMatch
 			get { return db;}
 		}
 		
-		/*private static void setGtkTheme(){
-			if (!System.IO.File.Exists(System.IO.Path.Combine(homeDirectory,"../../.gtkrc-2.0"))){
-			    System.IO.File.Copy(RelativeToPrefix("etc/gtk-2.0/gtkrc-2.0"),System.IO.Path.Combine(homeDirectory,"../../.gtkrc-2.0"),true);
-			}
-		}*/
-		
 		private static void SetUpWin32Config(){
 			Environment.SetEnvironmentVariable("GST_PLUGIN_PATH",RelativeToPrefix("lib\\gstreamer-0.10"));
 			baseDirectory = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory,"../");
@@ -210,7 +199,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/Makefile.am b/LongoMatch/Makefile.am
index 0871955..ab04f57 100644
--- a/LongoMatch/Makefile.am
+++ b/LongoMatch/Makefile.am
@@ -182,6 +182,7 @@ FILES = \
 	Handlers/EventsManager.cs \
 	Handlers/Handlers.cs \
 	Handlers/HotKeysManager.cs \
+	Handlers/VideoDrawingsManager.cs\
 	IO/CSVExport.cs \
 	IO/SectionsReader.cs \
 	IO/SectionsWriter.cs \
@@ -189,6 +190,7 @@ FILES = \
 	Main.cs \
 	Playlist/IPlayList.cs \
 	Playlist/PlayList.cs \
+	Time/Drawing.cs\
 	Time/HotKey.cs \
 	Time/MediaTimeNode.cs \
 	Time/PixbufTimeNode.cs \
diff --git a/LongoMatch/Time/Drawing.cs b/LongoMatch/Time/Drawing.cs
new file mode 100644
index 0000000..a6a0aca
--- /dev/null
+++ b/LongoMatch/Time/Drawing.cs
@@ -0,0 +1,58 @@
+// 
+//  Copyright (C) 2009 Andoni Morales Alastruey
+// 
+//  This program is free software; you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation; either version 2 of the License, or
+//  (at your option) any later version.
+// 
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+//  GNU General Public License for more details.
+//  
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// 
+
+using System;
+using Gdk;
+
+namespace LongoMatch.TimeNodes
+{
+	[Serializable]
+	public class Drawing
+	{
+		private byte[] drawingBuf;
+		private readonly int stopTime;
+		
+		
+		public Drawing(){
+		}
+		
+		public Drawing(Pixbuf drawing,int stopTime)
+		{
+			Pixbuf = drawing;
+			this.stopTime = stopTime;
+		}
+		
+		public Pixbuf Pixbuf{
+			get{ 
+				if (drawingBuf != null)
+					return new Pixbuf(drawingBuf);
+				else return null;
+			}
+			set {
+				if(value != null)
+					drawingBuf = value.SaveToBuffer("png");
+				else
+					drawingBuf = null;
+			}
+		}	
+		
+		public int StopTime{
+			get{return stopTime;}
+		}		
+	}
+}
diff --git a/LongoMatch/Time/MediaTimeNode.cs b/LongoMatch/Time/MediaTimeNode.cs
index eae13fc..2aa0a11 100644
--- a/LongoMatch/Time/MediaTimeNode.cs
+++ b/LongoMatch/Time/MediaTimeNode.cs
@@ -56,6 +56,9 @@ namespace LongoMatch.TimeNodes
 		private List<int> localPlayersList; //Used to multitag: one play and several players
 											// We use the int index of the player in the template,		
 		private List<int> visitorPlayersList;// because it's the only unmutable variable
+		
+		private Drawing keyFrame;
+		
 
 		
 #region Constructors	
@@ -109,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;}			
@@ -126,7 +137,17 @@ namespace LongoMatch.TimeNodes
 			get{return visitorPlayersList;}
 		}
 		
+		public Drawing KeyFrameDrawing{
+			set{keyFrame = value;}
+			get{return keyFrame;}
+		}
+		
+		public bool HasKeyFrame{
+			get{return keyFrame != null;}
+		}
+		
 		
+			
 		#endregion
 		
 		#region Public methods
@@ -150,8 +171,7 @@ namespace LongoMatch.TimeNodes
 		public void RemoveVisitorPlayer(int index){
 			visitorPlayersList.Remove(index);			
 		}
-		
+	
 		#endregion
-	}
-		
+	}		
 }
diff --git a/LongoMatch/Time/PixbufTimeNode.cs b/LongoMatch/Time/PixbufTimeNode.cs
index 101804d..aea8fad 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,33 @@ 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;
+
+			if (w>MAX_WIDTH || h>MAX_HEIGHT){
+				double rate = (double)w/(double)h;				
+				if (h>w)
+					ow = (int) (oh * rate);
+				else
+					oh = (int) (ow / rate);
+				thumbnailBuf = pixbuf.ScaleSimple(ow,oh,Gdk.InterpType.Bilinear).SaveToBuffer("png");
+				pixbuf.Dispose();
+			}	
+			else thumbnailBuf =  pixbuf.SaveToBuffer("png");
+		}
 	}
 }
diff --git a/LongoMatch/Time/TimeNode.cs b/LongoMatch/Time/TimeNode.cs
index 6b26f64..3139d3f 100644
--- a/LongoMatch/Time/TimeNode.cs
+++ b/LongoMatch/Time/TimeNode.cs
@@ -19,6 +19,8 @@
 //
 
 using System;
+using System.Collections.Generic;
+using LongoMatch.TimeNodes;
 
 namespace LongoMatch.TimeNodes
 {
@@ -35,8 +37,7 @@ namespace LongoMatch.TimeNodes
 		//Stores the stop time
 		private Time stop;
 		
-		
-		
+
 		public TimeNode(){
 		}
 		
diff --git a/LongoMatch/gtk-gui/LongoMatch.Gui.Dialog.DrawingTool.cs b/LongoMatch/gtk-gui/LongoMatch.Gui.Dialog.DrawingTool.cs
index 76e58b1..2db3cd7 100644
--- a/LongoMatch/gtk-gui/LongoMatch.Gui.Dialog.DrawingTool.cs
+++ b/LongoMatch/gtk-gui/LongoMatch.Gui.Dialog.DrawingTool.cs
@@ -19,6 +19,8 @@ namespace LongoMatch.Gui.Dialog {
         
         private LongoMatch.Gui.Component.DrawingToolBox drawingtoolbox1;
         
+        private Gtk.Button savetoprojectbutton;
+        
         private Gtk.Button savebutton;
         
         private LongoMatch.Gui.Component.DrawingWidget drawingwidget1;
@@ -59,39 +61,80 @@ namespace LongoMatch.Gui.Dialog {
             w2.Expand = false;
             w2.Fill = false;
             // Container child vbox2.Gtk.Box+BoxChild
+            this.savetoprojectbutton = new Gtk.Button();
+            this.savetoprojectbutton.CanFocus = true;
+            this.savetoprojectbutton.Name = "savetoprojectbutton";
+            this.savetoprojectbutton.UseUnderline = true;
+            // Container child savetoprojectbutton.Gtk.Container+ContainerChild
+            Gtk.Alignment w3 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
+            // Container child GtkAlignment2.Gtk.Container+ContainerChild
+            Gtk.HBox w4 = new Gtk.HBox();
+            w4.Spacing = 2;
+            // Container child GtkHBox3.Gtk.Container+ContainerChild
+            Gtk.Image w5 = new Gtk.Image();
+            w5.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-save", Gtk.IconSize.Menu, 16);
+            w4.Add(w5);
+            // Container child GtkHBox3.Gtk.Container+ContainerChild
+            Gtk.Label w7 = new Gtk.Label();
+            w7.LabelProp = Mono.Unix.Catalog.GetString("Save to Project");
+            w7.UseUnderline = true;
+            w4.Add(w7);
+            w3.Add(w4);
+            this.savetoprojectbutton.Add(w3);
+            this.vbox2.Add(this.savetoprojectbutton);
+            Gtk.Box.BoxChild w11 = ((Gtk.Box.BoxChild)(this.vbox2[this.savetoprojectbutton]));
+            w11.PackType = ((Gtk.PackType)(1));
+            w11.Position = 1;
+            w11.Expand = false;
+            w11.Fill = false;
+            // Container child vbox2.Gtk.Box+BoxChild
             this.savebutton = new Gtk.Button();
             this.savebutton.CanFocus = true;
             this.savebutton.Name = "savebutton";
-            this.savebutton.UseStock = true;
             this.savebutton.UseUnderline = true;
-            this.savebutton.Label = "gtk-save";
+            // Container child savebutton.Gtk.Container+ContainerChild
+            Gtk.Alignment w12 = new Gtk.Alignment(0.5F, 0.5F, 0F, 0F);
+            // Container child GtkAlignment1.Gtk.Container+ContainerChild
+            Gtk.HBox w13 = new Gtk.HBox();
+            w13.Spacing = 2;
+            // Container child GtkHBox2.Gtk.Container+ContainerChild
+            Gtk.Image w14 = new Gtk.Image();
+            w14.Pixbuf = Stetic.IconLoader.LoadIcon(this, "gtk-save", Gtk.IconSize.Menu, 16);
+            w13.Add(w14);
+            // Container child GtkHBox2.Gtk.Container+ContainerChild
+            Gtk.Label w16 = new Gtk.Label();
+            w16.LabelProp = Mono.Unix.Catalog.GetString("Save to File");
+            w16.UseUnderline = true;
+            w13.Add(w16);
+            w12.Add(w13);
+            this.savebutton.Add(w12);
             this.vbox2.Add(this.savebutton);
-            Gtk.Box.BoxChild w3 = ((Gtk.Box.BoxChild)(this.vbox2[this.savebutton]));
-            w3.PackType = ((Gtk.PackType)(1));
-            w3.Position = 1;
-            w3.Expand = false;
-            w3.Fill = false;
+            Gtk.Box.BoxChild w20 = ((Gtk.Box.BoxChild)(this.vbox2[this.savebutton]));
+            w20.PackType = ((Gtk.PackType)(1));
+            w20.Position = 2;
+            w20.Expand = false;
+            w20.Fill = false;
             this.hbox1.Add(this.vbox2);
-            Gtk.Box.BoxChild w4 = ((Gtk.Box.BoxChild)(this.hbox1[this.vbox2]));
-            w4.Position = 0;
-            w4.Expand = false;
-            w4.Fill = false;
+            Gtk.Box.BoxChild w21 = ((Gtk.Box.BoxChild)(this.hbox1[this.vbox2]));
+            w21.Position = 0;
+            w21.Expand = false;
+            w21.Fill = false;
             // Container child hbox1.Gtk.Box+BoxChild
             this.drawingwidget1 = new LongoMatch.Gui.Component.DrawingWidget();
             this.drawingwidget1.Events = ((Gdk.EventMask)(256));
             this.drawingwidget1.Name = "drawingwidget1";
             this.hbox1.Add(this.drawingwidget1);
-            Gtk.Box.BoxChild w5 = ((Gtk.Box.BoxChild)(this.hbox1[this.drawingwidget1]));
-            w5.Position = 1;
+            Gtk.Box.BoxChild w22 = ((Gtk.Box.BoxChild)(this.hbox1[this.drawingwidget1]));
+            w22.Position = 1;
             w1.Add(this.hbox1);
-            Gtk.Box.BoxChild w6 = ((Gtk.Box.BoxChild)(w1[this.hbox1]));
-            w6.Position = 0;
+            Gtk.Box.BoxChild w23 = ((Gtk.Box.BoxChild)(w1[this.hbox1]));
+            w23.Position = 0;
             // Internal child LongoMatch.Gui.Dialog.DrawingTool.ActionArea
-            Gtk.HButtonBox w7 = this.ActionArea;
-            w7.Name = "dialog1_ActionArea";
-            w7.Spacing = 6;
-            w7.BorderWidth = ((uint)(5));
-            w7.LayoutStyle = ((Gtk.ButtonBoxStyle)(4));
+            Gtk.HButtonBox w24 = this.ActionArea;
+            w24.Name = "dialog1_ActionArea";
+            w24.Spacing = 6;
+            w24.BorderWidth = ((uint)(5));
+            w24.LayoutStyle = ((Gtk.ButtonBoxStyle)(4));
             // Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
             this.button271 = new Gtk.Button();
             this.button271.CanFocus = true;
@@ -99,14 +142,15 @@ namespace LongoMatch.Gui.Dialog {
             this.button271.UseUnderline = true;
             this.button271.Label = Mono.Unix.Catalog.GetString("button271");
             this.AddActionWidget(this.button271, 0);
-            Gtk.ButtonBox.ButtonBoxChild w8 = ((Gtk.ButtonBox.ButtonBoxChild)(w7[this.button271]));
-            w8.Expand = false;
-            w8.Fill = false;
+            Gtk.ButtonBox.ButtonBoxChild w25 = ((Gtk.ButtonBox.ButtonBoxChild)(w24[this.button271]));
+            w25.Expand = false;
+            w25.Fill = false;
             if ((this.Child != null)) {
                 this.Child.ShowAll();
             }
             this.DefaultWidth = 600;
-            this.DefaultHeight = 521;
+            this.DefaultHeight = 549;
+            this.savetoprojectbutton.Hide();
             this.button271.Hide();
             this.Show();
             this.drawingtoolbox1.LineWidthChanged += new LongoMatch.Handlers.LineWidthChangedHandler(this.OnDrawingtoolbox1LineWidthChanged);
@@ -114,6 +158,7 @@ namespace LongoMatch.Gui.Dialog {
             this.drawingtoolbox1.VisibilityChanged += new LongoMatch.Handlers.VisibilityChangedHandler(this.OnDrawingtoolbox1VisibilityChanged);
             this.drawingtoolbox1.ClearDrawing += new LongoMatch.Handlers.ClearDrawingHandler(this.OnDrawingtoolbox1ClearDrawing);
             this.savebutton.Clicked += new System.EventHandler(this.OnSavebuttonClicked);
+            this.savetoprojectbutton.Clicked += new System.EventHandler(this.OnSavetoprojectbuttonClicked);
         }
     }
 }
diff --git a/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs b/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs
index f6ea97a..20f09b4 100644
--- a/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs
+++ b/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs
@@ -214,7 +214,7 @@ namespace LongoMatch.Gui {
             this.hpaned = new Gtk.HPaned();
             this.hpaned.CanFocus = true;
             this.hpaned.Name = "hpaned";
-            this.hpaned.Position = 318;
+            this.hpaned.Position = 295;
             // Container child hpaned.Gtk.Paned+PanedChild
             this.leftbox = new Gtk.VBox();
             this.leftbox.Name = "leftbox";
@@ -272,7 +272,7 @@ namespace LongoMatch.Gui {
             this.hpaned1 = new Gtk.HPaned();
             this.hpaned1.CanFocus = true;
             this.hpaned1.Name = "hpaned1";
-            this.hpaned1.Position = 760;
+            this.hpaned1.Position = 795;
             // Container child hpaned1.Gtk.Paned+PanedChild
             this.vbox5 = new Gtk.VBox();
             this.vbox5.Name = "vbox5";
@@ -294,9 +294,8 @@ namespace LongoMatch.Gui {
             this.playerbin1 = new LongoMatch.Gui.PlayerBin();
             this.playerbin1.Events = ((Gdk.EventMask)(256));
             this.playerbin1.Name = "playerbin1";
-            this.playerbin1.Rate = 0F;
-            this.playerbin1.LogoMode = false;
-            this.playerbin1.ExpandLogo = false;
+            this.playerbin1.Rate = 1F;
+            this.playerbin1.ExpandLogo = true;
             this.hbox1.Add(this.playerbin1);
             Gtk.Box.BoxChild w10 = ((Gtk.Box.BoxChild)(this.hbox1[this.playerbin1]));
             w10.Position = 1;
@@ -379,7 +378,7 @@ namespace LongoMatch.Gui {
                 this.Child.ShowAll();
             }
             this.DefaultWidth = 1259;
-            this.DefaultHeight = 590;
+            this.DefaultHeight = 761;
             this.leftbox.Hide();
             this.drawingtoolbox1.Hide();
             this.timelinewidget1.Hide();
diff --git a/LongoMatch/gtk-gui/gui.stetic b/LongoMatch/gtk-gui/gui.stetic
index f69ab6c..8701b21 100644
--- a/LongoMatch/gtk-gui/gui.stetic
+++ b/LongoMatch/gtk-gui/gui.stetic
@@ -1433,7 +1433,7 @@
       </widget>
     </child>
   </widget>
-  <widget class="Gtk.Window" id="LongoMatch.Gui.MainWindow" design-size="1259 590">
+  <widget class="Gtk.Window" id="LongoMatch.Gui.MainWindow" design-size="1259 761">
     <action-group name="Default">
       <action id="FileAction">
         <property name="Type">Action</property>
@@ -1656,7 +1656,7 @@
           <widget class="Gtk.HPaned" id="hpaned">
             <property name="MemberName" />
             <property name="CanFocus">True</property>
-            <property name="Position">318</property>
+            <property name="Position">295</property>
             <child>
               <widget class="Gtk.VBox" id="leftbox">
                 <property name="MemberName" />
@@ -1735,7 +1735,7 @@
               <widget class="Gtk.HPaned" id="hpaned1">
                 <property name="MemberName" />
                 <property name="CanFocus">True</property>
-                <property name="Position">760</property>
+                <property name="Position">795</property>
                 <child>
                   <widget class="Gtk.VBox" id="vbox5">
                     <property name="MemberName" />
@@ -1761,8 +1761,8 @@
                           <widget class="LongoMatch.Gui.PlayerBin" id="playerbin1">
                             <property name="MemberName" />
                             <property name="Events">ButtonPressMask</property>
-                            <property name="Rate">0</property>
-                            <property name="LogoMode">False</property>
+                            <property name="Rate">1</property>
+                            <property name="ExpandLogo">True</property>
                             <signal name="Error" handler="OnPlayerbin1Error" />
                             <signal name="SegmentClosedEvent" handler="OnSegmentClosedEvent" />
                           </widget>
@@ -4737,7 +4737,7 @@ Show-&gt;&lt;b&gt; S&lt;/b&gt;
       </widget>
     </child>
   </widget>
-  <widget class="Gtk.Dialog" id="LongoMatch.Gui.Dialog.DrawingTool" design-size="600 521">
+  <widget class="Gtk.Dialog" id="LongoMatch.Gui.Dialog.DrawingTool" design-size="600 549">
     <property name="MemberName" />
     <property name="Title" translatable="yes">Drawing Tool</property>
     <property name="Icon">resource:longomatch.png</property>
@@ -4778,18 +4778,37 @@ Show-&gt;&lt;b&gt; S&lt;/b&gt;
                   </packing>
                 </child>
                 <child>
+                  <widget class="Gtk.Button" id="savetoprojectbutton">
+                    <property name="MemberName" />
+                    <property name="Visible">False</property>
+                    <property name="CanFocus">True</property>
+                    <property name="Type">TextAndIcon</property>
+                    <property name="Icon">stock:gtk-save Menu</property>
+                    <property name="Label" translatable="yes">Save to Project</property>
+                    <property name="UseUnderline">True</property>
+                    <signal name="Clicked" handler="OnSavetoprojectbuttonClicked" />
+                  </widget>
+                  <packing>
+                    <property name="PackType">End</property>
+                    <property name="Position">1</property>
+                    <property name="AutoSize">True</property>
+                    <property name="Expand">False</property>
+                    <property name="Fill">False</property>
+                  </packing>
+                </child>
+                <child>
                   <widget class="Gtk.Button" id="savebutton">
                     <property name="MemberName" />
                     <property name="CanFocus">True</property>
-                    <property name="UseStock">True</property>
-                    <property name="Type">StockItem</property>
-                    <property name="StockId">gtk-save</property>
+                    <property name="Type">TextAndIcon</property>
+                    <property name="Icon">stock:gtk-save Menu</property>
+                    <property name="Label" translatable="yes">Save to File</property>
+                    <property name="UseUnderline">True</property>
                     <signal name="Clicked" handler="OnSavebuttonClicked" />
-                    <property name="label">gtk-save</property>
                   </widget>
                   <packing>
                     <property name="PackType">End</property>
-                    <property name="Position">1</property>
+                    <property name="Position">2</property>
                     <property name="AutoSize">True</property>
                     <property name="Expand">False</property>
                     <property name="Fill">False</property>
diff --git a/libcesarplayer/src/bacon-video-widget-gst-0.10.c b/libcesarplayer/src/bacon-video-widget-gst-0.10.c
index 9cc5433..7beb315 100644
--- a/libcesarplayer/src/bacon-video-widget-gst-0.10.c
+++ b/libcesarplayer/src/bacon-video-widget-gst-0.10.c
@@ -150,6 +150,7 @@ struct BaconVideoWidgetPrivate
   guint update_id;
 
   GdkPixbuf *logo_pixbuf;
+  GdkPixbuf *drawing_pixbuf;
 
   gboolean media_has_video;
   gboolean media_has_audio;
@@ -172,6 +173,7 @@ struct BaconVideoWidgetPrivate
 
   /* Other stuff */
   gboolean logo_mode;
+  gboolean drawing_mode;
   gboolean expand_logo;
   gboolean cursor_shown;
   gboolean fullscreen_mode;
@@ -484,8 +486,8 @@ get_media_size (BaconVideoWidget * bvw, gint * width, gint * height)
 	    }
 	  else if (!gst_video_calculate_display_ratio (&num, &den,
 						       bvw->priv->video_width,
-						       bvw->
-						       priv->video_height,
+						       bvw->priv->
+						       video_height,
 						       movie_par_n,
 						       movie_par_d,
 						       disp_par_n,
@@ -709,8 +711,8 @@ bacon_video_widget_expose_event (GtkWidget * widget, GdkEventExpose * event)
     {
 #ifdef WIN32
       gst_x_overlay_set_xwindow_id (bvw->priv->xoverlay,
-				    GDK_WINDOW_HWND (bvw->
-						     priv->video_window));
+				    GDK_WINDOW_HWND (bvw->priv->
+						     video_window));
 #else
       gst_x_overlay_set_xwindow_id (bvw->priv->xoverlay,
 				    GDK_WINDOW_XID (bvw->priv->video_window));
@@ -730,6 +732,7 @@ bacon_video_widget_expose_event (GtkWidget * widget, GdkEventExpose * event)
       if (bvw->priv->logo_pixbuf != NULL)
 	{
 	  GdkPixbuf *frame;
+	  GdkPixbuf *drawing;
 	  guchar *pixels;
 	  int rowstride;
 	  gint width, height, alloc_width, alloc_height, logo_x, logo_y;
@@ -761,7 +764,7 @@ bacon_video_widget_expose_event (GtkWidget * widget, GdkEventExpose * event)
 
 	  /* Drawing our frame */
 
-	  if (bvw->priv->expand_logo)
+	  if (bvw->priv->expand_logo && !bvw->priv->drawing_mode)
 	    {
 	      /* Scaling to available space */
 
@@ -810,11 +813,23 @@ bacon_video_widget_expose_event (GtkWidget * widget, GdkEventExpose * event)
 	      frame = gdk_pixbuf_scale_simple (bvw->priv->logo_pixbuf,
 					       width, height,
 					       GDK_INTERP_BILINEAR);
-
 	      gdk_draw_pixbuf (win, gtk_widget_get_style (widget)->fg_gc[0],
 			       frame, 0, 0, logo_x, logo_y, width, height,
 			       GDK_RGB_DITHER_NONE, 0, 0);
 
+	      if (bvw->priv->drawing_mode
+		  && bvw->priv->drawing_pixbuf != NULL)
+		{
+		  drawing =
+		    gdk_pixbuf_scale_simple (bvw->priv->drawing_pixbuf, width,
+					     height, GDK_INTERP_BILINEAR);
+		  gdk_draw_pixbuf (win,
+				   gtk_widget_get_style (widget)->fg_gc[0],
+				   drawing, 0, 0, logo_x, logo_y, width,
+				   height, GDK_RGB_DITHER_NONE, 0, 0);
+		  g_object_unref (drawing);
+		}
+
 	      g_object_unref (frame);
 	    }
 	}
@@ -1242,7 +1257,6 @@ bacon_video_widget_init (BaconVideoWidget * bvw)
   priv->audiotags = NULL;
   priv->videotags = NULL;
   priv->zoom = 1.0;
-  priv->expand_logo = TRUE;
   priv->lock = g_mutex_new ();
 
   bvw->priv->missing_plugins = NULL;
@@ -1865,12 +1879,11 @@ got_video_size (BaconVideoWidget * bvw)
   msg = gst_message_new_application (GST_OBJECT (bvw->priv->play),
 				     gst_structure_new ("video-size", "width",
 							G_TYPE_INT,
-							bvw->
-							priv->video_width,
-							"height", G_TYPE_INT,
-							bvw->
-							priv->video_height,
-							NULL));
+							bvw->priv->
+							video_width, "height",
+							G_TYPE_INT,
+							bvw->priv->
+							video_height, NULL));
   gst_element_post_message (bvw->priv->play, msg);
 }
 
@@ -4089,6 +4102,31 @@ bacon_video_widget_get_logo_mode (BaconVideoWidget * bvw)
   return bvw->priv->logo_mode;
 }
 
+void
+bacon_video_widget_set_drawing_pixbuf (BaconVideoWidget * bvw,
+				       GdkPixbuf * drawing)
+{
+  g_return_if_fail (bvw != NULL);
+  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
+  g_return_if_fail (drawing != NULL);
+
+  if (bvw->priv->drawing_pixbuf != NULL)
+    g_object_unref (bvw->priv->drawing_pixbuf);
+
+  g_object_ref (drawing);
+  bvw->priv->drawing_pixbuf = drawing;
+}
+
+void
+bacon_video_widget_set_drawing_mode (BaconVideoWidget * bvw,
+				     gboolean drawing_mode)
+{
+  g_return_if_fail (bvw != NULL);
+  g_return_if_fail (BACON_IS_VIDEO_WIDGET (bvw));
+
+  bvw->priv->drawing_mode = drawing_mode;
+}
+
 /**
  * bacon_video_widget_pause:
  * @bvw: a #BaconVideoWidget
@@ -5879,8 +5917,8 @@ bvw_element_msg_sync (GstBus * bus, GstMessage * msg, gpointer data)
 
 #ifdef WIN32
       gst_x_overlay_set_xwindow_id (bvw->priv->xoverlay,
-				    GDK_WINDOW_HWND (bvw->
-						     priv->video_window));
+				    GDK_WINDOW_HWND (bvw->priv->
+						     video_window));
 #else
       gst_x_overlay_set_xwindow_id (bvw->priv->xoverlay,
 				    GDK_WINDOW_XID (bvw->priv->video_window));
diff --git a/libcesarplayer/src/bacon-video-widget.h b/libcesarplayer/src/bacon-video-widget.h
index 4a9d5f0..859faf6 100644
--- a/libcesarplayer/src/bacon-video-widget.h
+++ b/libcesarplayer/src/bacon-video-widget.h
@@ -243,6 +243,14 @@ bacon_video_widget_error_quark (void)
 						double volume);
      EXPORT double bacon_video_widget_get_volume (BaconVideoWidget * bvw);
 
+/*Drawings Overlay*/
+     EXPORT void bacon_video_widget_set_drawing_pixbuf (BaconVideoWidget *
+							bvw,
+							GdkPixbuf * drawing);
+     EXPORT void bacon_video_widget_set_drawing_mode (BaconVideoWidget * bvw,
+						      gboolean drawing_mode);
+
+
 /* Properties */
      EXPORT void bacon_video_widget_set_logo (BaconVideoWidget * bvw,
 					      char *filename);



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