[longomatch] Add a new job's manager for rendering playlists



commit a0a8715333100015bf00ce13d7f34568d4d42c56
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date:   Tue Sep 20 01:33:43 2011 +0200

    Add a new job's manager for rendering playlists

 LongoMatch/Common/Enums.cs                         |    8 +
 LongoMatch/Gui/Component/PlayListWidget.cs         |   63 +-----
 LongoMatch/Gui/Component/RenderingStateBar.cs      |   74 ++++++
 LongoMatch/Gui/Dialog/RenderingJobsDialog.cs       |   98 ++++++++
 LongoMatch/Gui/MainWindow.cs                       |   20 ++-
 LongoMatch/Gui/TreeView/RenderingJobsTreeView.cs   |   83 +++++++
 LongoMatch/Handlers/EventsManager.cs               |   35 +---
 LongoMatch/Handlers/Handlers.cs                    |    3 +
 LongoMatch/LongoMatch.mdp                          |    9 +
 LongoMatch/Main.cs                                 |    1 +
 LongoMatch/Makefile.am                             |    8 +
 LongoMatch/Services/JobsManager/Job.cs             |   91 ++++++++
 .../Services/JobsManager/RenderingJobsManager.cs   |  235 ++++++++++++++++++++
 .../LongoMatch.Gui.Component.PlayListWidget.cs     |   35 +---
 .../LongoMatch.Gui.Component.RenderingStateBar.cs  |   72 ++++++
 .../LongoMatch.Gui.Dialog.RenderingJobsDialog.cs   |  172 ++++++++++++++
 LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs    |   19 +-
 ...ongoMatch.Gui.TreeView.RenderingJobsTreeView.cs |   19 ++
 LongoMatch/gtk-gui/gui.stetic                      |  209 +++++++++++++++--
 LongoMatch/gtk-gui/objects.xml                     |   20 ++-
 20 files changed, 1116 insertions(+), 158 deletions(-)
---
diff --git a/LongoMatch/Common/Enums.cs b/LongoMatch/Common/Enums.cs
index dd8b5e4..f7906b5 100644
--- a/LongoMatch/Common/Enums.cs
+++ b/LongoMatch/Common/Enums.cs
@@ -53,4 +53,12 @@ namespace LongoMatch.Common
 		LOCAL = 1,
 		VISITOR = 2,
 	}
+	
+	public enum JobState {
+		NotStarted,
+		Running,
+		Finished,
+		Cancelled,
+		Error,
+	}
 }
diff --git a/LongoMatch/Gui/Component/PlayListWidget.cs b/LongoMatch/Gui/Component/PlayListWidget.cs
index eed19b8..a647b1d 100644
--- a/LongoMatch/Gui/Component/PlayListWidget.cs
+++ b/LongoMatch/Gui/Component/PlayListWidget.cs
@@ -33,6 +33,7 @@ using LongoMatch.Video.Common;
 using LongoMatch.Gui;
 using LongoMatch.Gui.Dialog;
 using LongoMatch.Playlist;
+using LongoMatch.Services.JobsManager;
 
 
 
@@ -45,7 +46,7 @@ namespace LongoMatch.Gui.Component
 	{
 		public event PlayListNodeSelectedHandler PlayListNodeSelected;
 		public event ApplyCurrentRateHandler ApplyCurrentRate;
-		public event ProgressHandler Progress;
+		public event JobHandler NewRenderingJob;
 
 		private PlayerBin player;
 		private PlayListPlay plNode;
@@ -53,15 +54,11 @@ namespace LongoMatch.Gui.Component
 		private uint timeout;
 		private object lock_node;
 		private bool clock_started = false;
-		private IVideoEditor videoEditor;
-		private MultimediaFactory factory;
-
 
 		public PlayListWidget()
 		{
 			this.Build();
 			lock_node = new System.Object();
-			factory = new MultimediaFactory();
 			playlisttreeview1.Reorderable = true;
 			playlisttreeview1.RowActivated += OnPlaylisttreeview1RowActivated;
 			playlisttreeview1.ApplyCurrentRate += OnApplyRate;
@@ -71,12 +68,10 @@ namespace LongoMatch.Gui.Component
 			openbutton.CanFocus = false;
 			savebutton.CanFocus = false;
 			newvideobutton.CanFocus = false;
-			closebutton.CanFocus = false;
 		}
 
 		public void SetPlayer(PlayerBin player) {
 			this.player = player;
-			closebutton.Hide();
 			newvideobutton.Hide();
 		}
 
@@ -148,11 +143,6 @@ namespace LongoMatch.Gui.Component
 			}
 		}
 
-		public void StopEdition() {
-			if(videoEditor != null)
-				videoEditor.Cancel();
-		}
-
 		public void Stop() {
 			StopClock();
 		}
@@ -201,11 +191,6 @@ namespace LongoMatch.Gui.Component
 			}
 		}
 
-		private void LoadEditor() {
-			videoEditor = factory.getVideoEditor();
-			videoEditor.Progress += new ProgressHandler(OnProgress);
-		}
-
 		protected virtual void OnPlaylisttreeview1RowActivated(object o, Gtk.RowActivatedArgs args)
 		{
 			playlisttreeview1.LoadedPlay = SelectPlayListNode(args.Path);
@@ -274,48 +259,12 @@ namespace LongoMatch.Gui.Component
 				response=vep.Run();
 			}
 			if(response ==(int)ResponseType.Ok) {
-				//FIXME:Create a new instance of the video editor until we fix the audio swith enable/disabled
-				LoadEditor();
-				//videoEditor.ClearList();
-				foreach(PlayListPlay segment in playList) {
-					if(segment.Valid)
-						videoEditor.AddSegment(segment.MediaFile.FilePath,
-						                       segment.Start.MSeconds,
-						                       segment.Duration.MSeconds,
-						                       segment.Rate,
-						                       segment.Name,
-						                       segment.MediaFile.HasAudio);
-				}
-				try {
-					videoEditor.EncodingSettings = vep.EncodingSettings;
-					videoEditor.EnableTitle = vep.TitleOverlay;
-					videoEditor.EnableAudio = vep.EnableAudio;
-					videoEditor.Start();
-					closebutton.Show();
-					newvideobutton.Hide();
+				Job job = new Job(playList, vep.EncodingSettings, vep.EnableAudio, vep.TitleOverlay);
+				if (NewRenderingJob != null) {
+					NewRenderingJob(job);
 				}
-				catch(Exception ex) {
-					MessagePopup.PopupMessage(this, MessageType.Error, Catalog.GetString(ex.Message));
-				}
-				vep.Destroy();
-			}
-		}
-
-		protected virtual void OnClosebuttonClicked(object sender, System.EventArgs e)
-		{
-			videoEditor.Cancel();
-			closebutton.Hide();
-			newvideobutton.Show();
-		}
-
-		protected virtual void OnProgress(float progress) {
-			if(Progress!= null)
-				Progress(progress);
-
-			if(progress ==1) {
-				closebutton.Hide();
-				newvideobutton.Show();
 			}
+			vep.Destroy();
 		}
 
 		protected virtual void OnApplyRate(PlayListPlay plNode) {
diff --git a/LongoMatch/Gui/Component/RenderingStateBar.cs b/LongoMatch/Gui/Component/RenderingStateBar.cs
new file mode 100644
index 0000000..06db51d
--- /dev/null
+++ b/LongoMatch/Gui/Component/RenderingStateBar.cs
@@ -0,0 +1,74 @@
+// 
+//  Copyright (C) 2011 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+// 
+using System;
+namespace LongoMatch.Gui.Component
+{
+	[System.ComponentModel.ToolboxItem(true)]
+	public partial class RenderingStateBar : Gtk.Bin
+	{
+		public event EventHandler Cancel;
+		public event EventHandler ManageJobs;
+		
+		public RenderingStateBar ()
+		{
+			this.Build ();
+			progressbar.CanFocus = false;
+			cancellbutton.CanFocus = false;
+			statebutton.CanFocus = false;
+			
+			statebutton.Clicked += delegate(object sender, EventArgs e) {
+				if (ManageJobs != null)
+					ManageJobs(this, null);
+			};
+			
+			cancellbutton.Clicked += delegate(object sender, EventArgs e) {
+				if (Cancel != null)
+					Cancel(this, null);
+			};
+		}
+
+		public bool JobRunning {
+			set {
+				this.Visible = value;
+			}
+		}
+		
+		public string Text {
+			set {
+				statebutton.Label = value;
+			}
+		}
+		
+		public string ProgressText {
+			set {
+				progressbar.Text = value;
+			}
+		}
+		
+		public double Fraction {
+			set {
+				progressbar.Fraction = value;
+			}
+			get {
+				return progressbar.Fraction;
+			}
+			
+		}
+	}
+}
+
diff --git a/LongoMatch/Gui/Dialog/RenderingJobsDialog.cs b/LongoMatch/Gui/Dialog/RenderingJobsDialog.cs
new file mode 100644
index 0000000..ae413fb
--- /dev/null
+++ b/LongoMatch/Gui/Dialog/RenderingJobsDialog.cs
@@ -0,0 +1,98 @@
+// 
+//  Copyright (C) 2011 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+// 
+using System;
+using System.Collections.Generic;
+using Gtk;
+
+using LongoMatch.Common;
+
+using LongoMatch.Services.JobsManager;
+
+namespace LongoMatch.Gui.Dialog
+{
+	public partial class RenderingJobsDialog : Gtk.Dialog
+	{
+		RenderingJobsManager manager;
+		TreeStore model;
+		
+		public RenderingJobsDialog (RenderingJobsManager manager)
+		{
+			this.Build ();
+			this.manager = manager;
+			UpdateModel();
+			cancelbutton.Clicked += OnCancelbuttonClicked;
+			clearbutton.Clicked += OnClearbuttonClicked;
+			retrybutton.Clicked += OnRetrybuttonClicked;
+			renderingjobstreeview2.Selection.Changed += OnSelectionChanged;
+		}
+		
+		private void UpdateModel() {
+			model = manager.Model;
+			renderingjobstreeview2.Model = model;
+			QueueDraw();
+		}
+		
+		private void UpdateSelection() {
+			/* FIXME: Add support for multiple selection */
+			Job job;
+			List<Job> jobs = renderingjobstreeview2.SelectedJobs();
+			
+			cancelbutton.Visible = false;
+			retrybutton.Visible = false;
+			
+			if (jobs.Count == 0)
+				return;
+			
+			job = jobs[0];
+			
+			if (job.State == JobState.NotStarted ||
+			    job.State == JobState.Running)
+				cancelbutton.Visible = true;
+			
+			if (job.State == JobState.Error || job.State == JobState.Cancelled)
+				retrybutton.Visible = true;
+		}
+		
+		protected virtual void OnClearbuttonClicked (object sender, System.EventArgs e)
+		{
+			manager.ClearDoneJobs();
+			UpdateModel();
+			UpdateSelection();
+		}
+		
+		protected virtual void OnCancelbuttonClicked (object sender, System.EventArgs e)
+		{
+			manager.CancelJobs(renderingjobstreeview2.SelectedJobs());
+			UpdateSelection();
+			QueueDraw();
+		}
+		
+		protected virtual void OnRetrybuttonClicked (object sender, System.EventArgs e)
+		{
+			manager.RetryJobs(renderingjobstreeview2.SelectedJobs());
+			UpdateModel();
+			UpdateSelection();
+		}
+		
+		protected virtual void OnSelectionChanged (object sender, System.EventArgs e)
+		{
+			UpdateSelection();
+		}
+	}
+}
+
diff --git a/LongoMatch/Gui/MainWindow.cs b/LongoMatch/Gui/MainWindow.cs
index 5e59ac7..e21eab9 100644
--- a/LongoMatch/Gui/MainWindow.cs
+++ b/LongoMatch/Gui/MainWindow.cs
@@ -29,6 +29,7 @@ using LongoMatch.Gui.Dialog;
 using LongoMatch.Handlers;
 using LongoMatch.Store;
 using LongoMatch.Store.Templates;
+using LongoMatch.Services.JobsManager;
 using LongoMatch.Video.Capturer;
 using LongoMatch.Video.Common;
 using LongoMatch.Video.Utils;
@@ -49,6 +50,7 @@ namespace LongoMatch.Gui
 		private EventsManager eManager;
 		private HotKeysManager hkManager;
 		private KeyPressEventHandler hotkeysListener;
+		RenderingJobsManager videoRenderer;
 
 
 		#region Constructors
@@ -72,7 +74,6 @@ namespace LongoMatch.Gui
 			                             playlistwidget2,
 			                             playerbin1,
 			                             timelinewidget1,
-			                             videoprogressbar,
 			                             noteswidget1,
 			                             capturerBin);
 
@@ -85,6 +86,7 @@ namespace LongoMatch.Gui
 			DrawingManager dManager = new DrawingManager(drawingtoolbox1,playerbin1.VideoWidget);
 			//Forward Key and Button events to the Drawing Manager
 			KeyPressEvent += new KeyPressEventHandler(dManager.OnKeyPressEvent);
+			
 
 			playerbin1.SetLogo(System.IO.Path.Combine(MainClass.ImagesDir(),"background.png"));
 			playerbin1.LogoMode = true;
@@ -95,6 +97,12 @@ namespace LongoMatch.Gui
 				CloseCaptureProject();
 			};
 
+			videoRenderer = new RenderingJobsManager(renderingstatebar1);
+			renderingstatebar1.ManageJobs += OnManageJobs;
+			playlistwidget2.NewRenderingJob += delegate(Job job) {
+				videoRenderer.AddJob(job);
+			};
+			
 			buttonswidget1.Mode = TagMode.Predifined;
 
 			playlistwidget2.SetPlayer(playerbin1);
@@ -106,6 +114,8 @@ namespace LongoMatch.Gui
 		#endregion
 
 		#region Private Methods
+		
+		
 		private void SetProject(Project project, ProjectType projectType, CaptureSettings props)
 		{
 			bool isLive = false;
@@ -360,7 +370,6 @@ namespace LongoMatch.Gui
 		private void CloseAndQuit() {
 			if(!PromptCloseProject())
 				return;
-			playlistwidget2.StopEdition();
 			SaveProject();
 			playerbin1.Dispose();
 			Application.Quit();
@@ -596,6 +605,13 @@ namespace LongoMatch.Gui
 			if(!playlistwidget2.Visible)
 				rightvbox.Visible=false;
 		}
+		
+		protected virtual void OnManageJobs (object sender, EventArgs args) {
+			RenderingJobsDialog dialog = new RenderingJobsDialog(videoRenderer);
+			dialog.TransientFor = (Gtk.Window) Toplevel;
+			dialog.Run();
+			dialog.Destroy();
+		}
 
 		protected virtual void OnUpdate(Version version, string URL) {
 			LongoMatch.Gui.Dialog.UpdateDialog updater = new LongoMatch.Gui.Dialog.UpdateDialog();
diff --git a/LongoMatch/Gui/TreeView/RenderingJobsTreeView.cs b/LongoMatch/Gui/TreeView/RenderingJobsTreeView.cs
new file mode 100644
index 0000000..f08f009
--- /dev/null
+++ b/LongoMatch/Gui/TreeView/RenderingJobsTreeView.cs
@@ -0,0 +1,83 @@
+// 
+//  Copyright (C) 2011 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+// 
+using System;
+using System.Collections.Generic;
+using Gtk;
+using Stetic;
+using Mono.Unix;
+
+using LongoMatch.Services.JobsManager;
+
+namespace LongoMatch.Gui.Component
+{
+	[System.ComponentModel.ToolboxItem(true)]
+	public partial class RenderingJobsTreeView : Gtk.TreeView
+	{
+		public RenderingJobsTreeView ()
+		{
+			TreeViewColumn nameColumn = new TreeViewColumn();
+			nameColumn.Title = Catalog.GetString("Job name");
+			CellRendererText nameCell = new CellRendererText();
+			nameColumn.PackStart(nameCell, true);
+
+			TreeViewColumn stateColumn = new TreeViewColumn();
+			stateColumn.Title = Catalog.GetString("State");
+			CellRendererPixbuf stateCell = new CellRendererPixbuf();
+			stateColumn.PackStart(stateCell, true);
+
+			nameColumn.SetCellDataFunc(nameCell, new Gtk.TreeCellDataFunc(RenderName));
+			stateColumn.SetCellDataFunc(stateCell, new Gtk.TreeCellDataFunc(RenderState));
+
+			AppendColumn(nameColumn);
+			AppendColumn(stateColumn);
+		}
+		
+		public List<Job> SelectedJobs () {
+			/* FIXME: Only single selection is supported for now */
+			TreeIter iter;
+			List<Job> list;
+			TreePath[] pathArray;
+
+			list = new List<Job>();
+			pathArray = Selection.GetSelectedRows();
+
+			for(int i=0; i< pathArray.Length; i++) {
+				Model.GetIterFromString(out iter, pathArray[i].ToString());
+				list.Add((Job) Model.GetValue(iter, 0));
+			}
+			
+			return list;
+		}
+		
+		private void RenderName(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
+		{
+			Job job = (Job) model.GetValue(iter, 0);
+
+			(cell as Gtk.CellRendererText).Text = job.Name;
+		}
+
+
+		private void RenderState(Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter)
+		{
+			Job job = (Job) model.GetValue(iter, 0);
+
+			(cell as Gtk.CellRendererPixbuf).Pixbuf = IconLoader.LoadIcon(this, job.StateIconName, IconSize.Button);
+		}
+	}
+}
+
diff --git a/LongoMatch/Handlers/EventsManager.cs b/LongoMatch/Handlers/EventsManager.cs
index a07cc92..e04ef63 100644
--- a/LongoMatch/Handlers/EventsManager.cs
+++ b/LongoMatch/Handlers/EventsManager.cs
@@ -47,7 +47,6 @@ namespace LongoMatch
 		private PlayerBin player;
 		private CapturerBin capturer;
 		private TimeLineWidget timeline;
-		private ProgressBar videoprogressbar;
 		private NotesWidget notes;
 		private FramesSeriesCapturer fsc;
 		private FramesCaptureProgressDialog fcpd;
@@ -63,8 +62,7 @@ namespace LongoMatch
 		public EventsManager(PlaysListTreeWidget treewidget, PlayersListTreeWidget localPlayersList,
 		                     PlayersListTreeWidget visitorPlayersList, TagsTreeWidget tagsTreeWidget,
 		                     ButtonsWidget buttonswidget, PlayListWidget playlist, PlayerBin player,
-		                     TimeLineWidget timeline, ProgressBar videoprogressbar,NotesWidget notes,
-		                     CapturerBin capturer)
+		                     TimeLineWidget timeline, NotesWidget notes, CapturerBin capturer)
 		{
 			this.treewidget = treewidget;
 			this.localPlayersList = localPlayersList;
@@ -74,7 +72,6 @@ namespace LongoMatch
 			this.playlist = playlist;
 			this.player = player;
 			this.timeline = timeline;
-			this.videoprogressbar = videoprogressbar;
 			this.notes = notes;
 			this.capturer = capturer;
 			this.drawingManager = new VideoDrawingsManager(player);
@@ -123,7 +120,6 @@ namespace LongoMatch
 
 			/* Connect playlist events */
 			playlist.PlayListNodeSelected += OnPlayListNodeSelected;
-			playlist.Progress += OnProgress;
 			playlist.ApplyCurrentRate += OnApplyRate;
 
 			/* Connect PlayListNodeAdded events */
@@ -203,35 +199,6 @@ namespace LongoMatch
 			timeline.QueueDraw();
 		}
 
-		protected virtual void OnProgress(float progress) {
-
-			if(progress > (float)EditorState.START && progress <= (float)EditorState.FINISHED && progress > videoprogressbar.Fraction) {
-				videoprogressbar.Fraction = progress;
-			}
-
-			if(progress == (float)EditorState.CANCELED) {
-				videoprogressbar.Hide();
-			}
-
-			else if(progress == (float)EditorState.START) {
-				videoprogressbar.Show();
-				videoprogressbar.Fraction = 0;
-				videoprogressbar.Text = "Creating new video";
-			}
-
-			else if(progress == (float)EditorState.FINISHED) {
-				MessagePopup.PopupMessage(player, MessageType.Info,  Catalog.GetString("The video edition has finished successfully."));
-				videoprogressbar.Hide();
-			}
-
-			else if(progress == (float)EditorState.ERROR) {
-				MessagePopup.PopupMessage(player, MessageType.Error,
-				                          Catalog.GetString("An error has occurred in the video editor.")
-				                          +Catalog.GetString("Please, try again."));
-				videoprogressbar.Hide();
-			}
-		}
-
 		protected virtual void OnNewMarkAtFrame(Category category, int frame) {
 			Time pos = new Time { MSeconds = frame*1000/openedProject.Description.File.Fps};
 			player.CloseActualSegment();
diff --git a/LongoMatch/Handlers/Handlers.cs b/LongoMatch/Handlers/Handlers.cs
index ad9c565..5e6e3e6 100644
--- a/LongoMatch/Handlers/Handlers.cs
+++ b/LongoMatch/Handlers/Handlers.cs
@@ -25,6 +25,7 @@ using LongoMatch.DB;
 using LongoMatch.Interfaces;
 using LongoMatch.Store;
 using LongoMatch.Common;
+using LongoMatch.Services.JobsManager;
 
 namespace LongoMatch.Handlers
 {
@@ -93,4 +94,6 @@ namespace LongoMatch.Handlers
 	public delegate void PlayersPropertiesHandler(List<Player> players);
 	
 	public delegate void ProjectsSelectedHandler(List<ProjectDescription> projects);
+
+	public delegate void JobHandler(Job job);
 }
diff --git a/LongoMatch/LongoMatch.mdp b/LongoMatch/LongoMatch.mdp
index 2282c44..7c5bff2 100644
--- a/LongoMatch/LongoMatch.mdp
+++ b/LongoMatch/LongoMatch.mdp
@@ -192,6 +192,15 @@
     <File subtype="Code" buildaction="Compile" name="Common/Images.cs" />
     <File subtype="Code" buildaction="Compile" name="Gui/Component/CategoriesTemplateEditor.cs" />
     <File subtype="Code" buildaction="Compile" name="Gui/Component/TeamTemplateEditor.cs" />
+    <File subtype="Directory" buildaction="Compile" name="Services/JobsManager" />
+    <File subtype="Code" buildaction="Compile" name="Services/JobsManager/RenderingJobsManager.cs" />
+    <File subtype="Directory" buildaction="Compile" name="Services" />
+    <File subtype="Code" buildaction="Compile" name="Services/JobsManager/Job.cs" />
+    <File subtype="Code" buildaction="Compile" name="Gui/Component/RenderingStateBar.cs" />
+    <File subtype="Code" buildaction="Compile" name="gtk-gui/LongoMatch.Gui.Component.RenderingStateBar.cs" />
+    <File subtype="Code" buildaction="Compile" name="Gui/TreeView/RenderingJobsTreeView.cs" />
+    <File subtype="Code" buildaction="Compile" name="Gui/Dialog/RenderingJobsDialog.cs" />
+    <File subtype="Code" buildaction="Compile" name="gtk-gui/LongoMatch.Gui.Dialog.RenderingJobsDialog.cs" />
   </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 62c283f..3599269 100644
--- a/LongoMatch/Main.cs
+++ b/LongoMatch/Main.cs
@@ -28,6 +28,7 @@ using LongoMatch.Gui;
 using LongoMatch.IO;
 using LongoMatch.Store.Templates;
 using LongoMatch.Services;
+using LongoMatch.Services.JobsManager;
 using Mono.Unix;
 
 namespace LongoMatch
diff --git a/LongoMatch/Makefile.am b/LongoMatch/Makefile.am
index 0931b81..c3cf589 100644
--- a/LongoMatch/Makefile.am
+++ b/LongoMatch/Makefile.am
@@ -2,6 +2,7 @@ ASSEMBLY = LongoMatch
 TARGET = exe
 LINK = $(REF_DEP_LONGOMATCH)
 
+
 SOURCES = \
 	AssemblyInfo.cs \
 	Common/Cairo.cs \
@@ -27,6 +28,7 @@ SOURCES = \
 	gtk-gui/LongoMatch.Gui.Component.PlaysListTreeWidget.cs \
 	gtk-gui/LongoMatch.Gui.Component.ProjectDetailsWidget.cs \
 	gtk-gui/LongoMatch.Gui.Component.ProjectListWidget.cs \
+	gtk-gui/LongoMatch.Gui.Component.RenderingStateBar.cs \
 	gtk-gui/LongoMatch.Gui.Component.StringTaggerWidget.cs \
 	gtk-gui/LongoMatch.Gui.Component.TaggerWidget.cs \
 	gtk-gui/LongoMatch.Gui.Component.TagsTreeWidget.cs \
@@ -46,6 +48,7 @@ SOURCES = \
 	gtk-gui/LongoMatch.Gui.Dialog.PlayersSelectionDialog.cs \
 	gtk-gui/LongoMatch.Gui.Dialog.ProjectSelectionDialog.cs \
 	gtk-gui/LongoMatch.Gui.Dialog.ProjectsManager.cs \
+	gtk-gui/LongoMatch.Gui.Dialog.RenderingJobsDialog.cs \
 	gtk-gui/LongoMatch.Gui.Dialog.SnapshotsDialog.cs \
 	gtk-gui/LongoMatch.Gui.Dialog.SubCategoryTagsEditor.cs \
 	gtk-gui/LongoMatch.Gui.Dialog.TaggerDialog.cs \
@@ -64,6 +67,7 @@ SOURCES = \
 	Gui/Component/DrawingToolBox.cs \
 	Gui/Component/DrawingWidget.cs \
 	Gui/Component/NotesWidget.cs \
+	Gui/Component/RenderingStateBar.cs \
 	Gui/Component/PlayerProperties.cs \
 	Gui/Component/PlayersListTreeWidget.cs \
 	Gui/Component/PlayersTaggerWidget.cs \
@@ -93,6 +97,7 @@ SOURCES = \
 	Gui/Dialog/PlayersSelectionDialog.cs \
 	Gui/Dialog/ProjectSelectionDialog.cs \
 	Gui/Dialog/ProjectsManager.cs \
+	Gui/Dialog/RenderingJobsDialog.cs \
 	Gui/Dialog/SnapshotsDialog.cs \
 	Gui/Dialog/SubCategoryTagsEditor.cs \
 	Gui/Dialog/TaggerDialog.cs \
@@ -111,6 +116,7 @@ SOURCES = \
 	Gui/TreeView/PlayersTreeView.cs \
 	Gui/TreeView/PlayListTreeView.cs \
 	Gui/TreeView/PlaysTreeView.cs \
+	Gui/TreeView/RenderingJobsTreeView.cs \
 	Gui/TreeView/SubCategoriesTreeView.cs \
 	Gui/TreeView/TagsTreeView.cs \
 	Handlers/DrawingManager.cs \
@@ -127,6 +133,8 @@ SOURCES = \
 	Playlist/IPlayList.cs \
 	Playlist/PlayList.cs \
 	Services/DataBase.cs \
+	Services/JobsManager/Job.cs \
+	Services/JobsManager/RenderingJobsManager.cs \
 	Services/TemplatesService.cs \
 	Store/Category.cs \
 	Store/Drawing.cs \
diff --git a/LongoMatch/Services/JobsManager/Job.cs b/LongoMatch/Services/JobsManager/Job.cs
new file mode 100644
index 0000000..a6d2cf5
--- /dev/null
+++ b/LongoMatch/Services/JobsManager/Job.cs
@@ -0,0 +1,91 @@
+// 
+//  Copyright (C) 2011 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+// 
+using System;
+using Gdk;
+using Stetic;
+
+using LongoMatch.Common;
+using LongoMatch.Playlist;
+using LongoMatch.Video.Common;
+
+namespace LongoMatch.Services.JobsManager
+{
+	[Serializable]
+	public class Job
+	{
+		public Job (PlayList playlist, EncodingSettings encSettings,
+		            bool enableAudio, bool overlayTitle)
+		{
+			Playlist = Cloner.Clone(playlist);
+			EncodingSettings = encSettings;
+			EnableAudio = enableAudio;
+			OverlayTitle = overlayTitle;
+			State = JobState.NotStarted;
+		}
+		
+		public string Name {
+			get {
+				return System.IO.Path.GetFileName(EncodingSettings.OutputFile);
+			}
+		}
+		
+		public JobState State {
+			get;
+			set;
+		}
+		
+		public string StateIconName{
+			get{
+				switch (State) {
+				case JobState.Error:
+					return "gtk-dialog-error";
+				case JobState.Finished:
+					return "gtk-ok";
+				case JobState.Cancelled:
+					return "gtk-cancel";
+				case JobState.NotStarted:
+					return "gtk-execute";
+				case JobState.Running:
+					return "gtk-media-record";
+				}
+				return "";
+			}
+		}
+		
+		public PlayList Playlist{
+			get;
+			set;
+		}
+		
+		public EncodingSettings EncodingSettings {
+			get;
+			set;
+		}
+		
+		public bool EnableAudio {
+			get;
+			set;
+		}
+		
+		public bool OverlayTitle {
+			get;
+			set;
+		}
+	}
+}
+
diff --git a/LongoMatch/Services/JobsManager/RenderingJobsManager.cs b/LongoMatch/Services/JobsManager/RenderingJobsManager.cs
new file mode 100644
index 0000000..3f019b9
--- /dev/null
+++ b/LongoMatch/Services/JobsManager/RenderingJobsManager.cs
@@ -0,0 +1,235 @@
+// 
+//  Copyright (C) 2011 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+// 
+using System;
+using System.Collections.Generic;
+using Gtk;
+using Mono.Unix;
+
+using LongoMatch.Common;
+using LongoMatch.Gui;
+using LongoMatch.Gui.Component;
+using LongoMatch.Store;
+using LongoMatch.Video;
+using LongoMatch.Video.Editor;
+
+namespace LongoMatch.Services.JobsManager
+{
+	public class RenderingJobsManager
+	{
+		/* List of pending jobs */
+		List<Job> jobs, pendingJobs;
+		IVideoEditor videoEditor;
+		MultimediaFactory factory;
+		Job currentJob;
+		RenderingStateBar stateBar;
+		
+		public RenderingJobsManager (RenderingStateBar stateBar)
+		{
+			jobs = new List<Job>();
+			pendingJobs = new List<Job>();
+			factory = new MultimediaFactory();
+			this.stateBar = stateBar;
+			stateBar.Cancel += delegate(object sender, EventArgs e) {
+				CancelCurrentJob();
+			};
+		}
+		
+		public TreeStore Model {
+			get {
+				TreeStore model = new TreeStore(typeof(Job));
+				foreach (Job job in jobs)
+					model.AppendValues(job);
+				return model;
+			}
+		}
+		
+		public void AddJob(Job job) {
+			jobs.Add(job);
+			pendingJobs.Add(job);
+			UpdateJobsStatus();
+			if (pendingJobs.Count == 1)
+				StartNextJob();
+		}
+		
+		public void RetryJobs(List<Job> retryJobs) {
+			foreach (Job job in retryJobs) {
+				if (!jobs.Contains(job))
+					return;
+				if (!pendingJobs.Contains(job)) {
+					job.State = JobState.NotStarted;
+					jobs.Remove(job);
+					jobs.Add(job);
+					pendingJobs.Add(job);
+					UpdateJobsStatus();
+				}
+			}
+		}
+		
+		public void DeleteJob(Job job) {
+			job.State = JobState.Cancelled;
+			CancelJob(job);
+		}
+		
+		public void ClearDoneJobs() {
+			jobs.RemoveAll(j => j.State == JobState.Finished);
+		}
+		
+		public void CancelJobs(List<Job> cancelJobs) {
+			foreach (Job job in cancelJobs){
+				job.State = JobState.Cancelled;
+				pendingJobs.Remove(job);
+			}
+			
+			if (cancelJobs.Contains(currentJob))
+				CancelCurrentJob();
+		}
+		
+		public void CancelCurrentJob () {
+			CancelJob(currentJob);
+		}
+		
+		public void CancelJob(Job job) {
+			if (currentJob != job) 
+				return;
+			
+			videoEditor.Progress -= OnProgress;
+			videoEditor.Cancel();
+			job.State = JobState.Cancelled;
+			RemoveCurrentFromPending();
+			UpdateJobsStatus();
+			StartNextJob();
+		}
+		
+		public void CancelAllJobs() {
+			foreach (Job job in pendingJobs)
+				job.State = JobState.Cancelled;
+			pendingJobs.Clear();
+			CancelJob(currentJob);
+		}
+		
+		private void LoadJob(Job job) {
+			foreach(PlayListPlay segment in job.Playlist) {
+				if(segment.Valid)
+					videoEditor.AddSegment(segment.MediaFile.FilePath,
+					                       segment.Start.MSeconds,
+					                       segment.Duration.MSeconds,
+					                       segment.Rate,
+					                       segment.Name,
+					                       segment.MediaFile.HasAudio);
+			}
+		}
+		
+		private void CloseAndNext() {
+			RemoveCurrentFromPending();
+			UpdateJobsStatus();
+			StartNextJob();
+		}
+		
+		private void ResetGui() {
+			stateBar.ProgressText = "";
+			stateBar.JobRunning = false;
+		}
+		
+		private void StartNextJob() {
+			if (pendingJobs.Count == 0) {
+				ResetGui();
+				return;
+			}
+			
+			videoEditor = factory.getVideoEditor();
+			videoEditor.Progress += OnProgress;
+			currentJob = pendingJobs[0];
+			LoadJob(currentJob);
+			
+			try {
+				videoEditor.EncodingSettings = currentJob.EncodingSettings;
+				videoEditor.EnableTitle = currentJob.OverlayTitle;
+				videoEditor.EnableAudio = currentJob.EnableAudio;
+				videoEditor.Start();
+			}
+			catch(Exception ex) {
+				Log.Exception(ex);
+				Log.Error("Error redering job: ", currentJob.Playlist.Filename);
+				currentJob.State = JobState.Error;
+			}
+		}
+		
+		private void UpdateProgress(float progress) {
+			stateBar.Fraction = progress;
+			stateBar.ProgressText = String.Format("{0}... {1:0.0}%", Catalog.GetString("Rendering"),
+			                              progress * 100);
+		}
+		
+		private void UpdateJobsStatus() {
+			stateBar.Text = String.Format("{0} ({1} {2})", Catalog.GetString("Rendering queue"),
+			                              pendingJobs.Count, Catalog.GetString("Pending"));
+		}
+		
+		private void RemoveCurrentFromPending () {
+			try {
+				pendingJobs.Remove(currentJob);
+			} catch {}
+		}
+		
+		private void MainLoopOnProgress (float progress) {
+			if(progress > (float)EditorState.START && progress <= (float)EditorState.FINISHED
+			   && progress > stateBar.Fraction) {
+				UpdateProgress(progress);
+			}
+
+			if(progress == (float)EditorState.CANCELED) {
+				Log.Debug ("Job was cancelled");
+				currentJob.State = JobState.Cancelled;
+				CloseAndNext();
+			}
+
+			else if(progress == (float)EditorState.START) {
+				Log.Debug ("Job started");
+				currentJob.State = JobState.Running;
+				stateBar.JobRunning = true;
+				UpdateProgress(progress);
+			}
+
+			else if(progress == (float)EditorState.FINISHED) {
+				Log.Debug ("Job finished successfully");
+				videoEditor.Progress -= OnProgress;
+				UpdateProgress(progress);
+				currentJob.State = JobState.Finished;
+				CloseAndNext();
+			}
+
+			else if(progress == (float)EditorState.ERROR) {
+				Log.Debug ("Job finished with errors");
+				MessagePopup.PopupMessage(stateBar, MessageType.Error,
+				                          Catalog.GetString("An error has occurred in the video editor.")
+				                          +Catalog.GetString("Please, try again."));
+				currentJob.State = JobState.Error;
+				CloseAndNext();
+			}
+		}
+		
+		protected void OnProgress(float progress)
+		{
+			/* FIXME: Check if this is really sent from a gstreamer thread */
+			Application.Invoke(delegate {
+				MainLoopOnProgress (progress);
+			});
+		}
+	}
+}
+
diff --git a/LongoMatch/gtk-gui/LongoMatch.Gui.Component.PlayListWidget.cs b/LongoMatch/gtk-gui/LongoMatch.Gui.Component.PlayListWidget.cs
index d6c3001..a467a89 100644
--- a/LongoMatch/gtk-gui/LongoMatch.Gui.Component.PlayListWidget.cs
+++ b/LongoMatch/gtk-gui/LongoMatch.Gui.Component.PlayListWidget.cs
@@ -24,8 +24,6 @@ namespace LongoMatch.Gui.Component
 
 		private global::Gtk.Button newvideobutton;
 
-		private global::Gtk.Button closebutton;
-
 		protected virtual void Build ()
 		{
 			global::Stetic.Gui.Initialize (this);
@@ -168,46 +166,21 @@ namespace LongoMatch.Gui.Component
 			this.hbox2.Add (this.newvideobutton);
 			global::Gtk.Box.BoxChild w42 = ((global::Gtk.Box.BoxChild)(this.hbox2[this.newvideobutton]));
 			w42.Position = 3;
-			// Container child hbox2.Gtk.Box+BoxChild
-			this.closebutton = new global::Gtk.Button ();
-			this.closebutton.TooltipMarkup = "Cancel rendering";
-			this.closebutton.CanFocus = true;
-			this.closebutton.Name = "closebutton";
-			this.closebutton.UseUnderline = true;
-			// Container child closebutton.Gtk.Container+ContainerChild
-			global::Gtk.Alignment w43 = new global::Gtk.Alignment (0.5f, 0.5f, 0f, 0f);
-			// Container child GtkAlignment.Gtk.Container+ContainerChild
-			global::Gtk.HBox w44 = new global::Gtk.HBox ();
-			w44.Spacing = 2;
-			// Container child GtkHBox.Gtk.Container+ContainerChild
-			global::Gtk.Image w45 = new global::Gtk.Image ();
-			w45.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-close", global::Gtk.IconSize.Button);
-			w44.Add (w45);
-			// Container child GtkHBox.Gtk.Container+ContainerChild
-			global::Gtk.Label w47 = new global::Gtk.Label ();
-			w44.Add (w47);
-			w43.Add (w44);
-			this.closebutton.Add (w43);
-			this.hbox2.Add (this.closebutton);
-			global::Gtk.Box.BoxChild w51 = ((global::Gtk.Box.BoxChild)(this.hbox2[this.closebutton]));
-			w51.Position = 4;
 			this.vbox2.Add (this.hbox2);
-			global::Gtk.Box.BoxChild w52 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.hbox2]));
-			w52.Position = 1;
-			w52.Expand = false;
-			w52.Fill = false;
+			global::Gtk.Box.BoxChild w43 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.hbox2]));
+			w43.Position = 1;
+			w43.Expand = false;
+			w43.Fill = false;
 			this.Add (this.vbox2);
 			if ((this.Child != null)) {
 				this.Child.ShowAll ();
 			}
-			this.closebutton.Hide ();
 			this.Show ();
 			this.playlisttreeview1.DragEnd += new global::Gtk.DragEndHandler (this.OnPlaylisttreeview1DragEnd);
 			this.newbutton.Clicked += new global::System.EventHandler (this.OnNewbuttonClicked);
 			this.openbutton.Clicked += new global::System.EventHandler (this.OnOpenbuttonClicked);
 			this.savebutton.Clicked += new global::System.EventHandler (this.OnSavebuttonClicked);
 			this.newvideobutton.Clicked += new global::System.EventHandler (this.OnNewvideobuttonClicked);
-			this.closebutton.Clicked += new global::System.EventHandler (this.OnClosebuttonClicked);
 		}
 	}
 }
diff --git a/LongoMatch/gtk-gui/LongoMatch.Gui.Component.RenderingStateBar.cs b/LongoMatch/gtk-gui/LongoMatch.Gui.Component.RenderingStateBar.cs
new file mode 100644
index 0000000..ae5591b
--- /dev/null
+++ b/LongoMatch/gtk-gui/LongoMatch.Gui.Component.RenderingStateBar.cs
@@ -0,0 +1,72 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace LongoMatch.Gui.Component
+{
+	public partial class RenderingStateBar
+	{
+		private global::Gtk.HBox hbox1;
+
+		private global::Gtk.Button statebutton;
+
+		private global::Gtk.ProgressBar progressbar;
+
+		private global::Gtk.Button cancellbutton;
+
+		protected virtual void Build ()
+		{
+			global::Stetic.Gui.Initialize (this);
+			// Widget LongoMatch.Gui.Component.RenderingStateBar
+			global::Stetic.BinContainer.Attach (this);
+			this.Name = "LongoMatch.Gui.Component.RenderingStateBar";
+			// Container child LongoMatch.Gui.Component.RenderingStateBar.Gtk.Container+ContainerChild
+			this.hbox1 = new global::Gtk.HBox ();
+			this.hbox1.Name = "hbox1";
+			this.hbox1.Spacing = 6;
+			// Container child hbox1.Gtk.Box+BoxChild
+			this.statebutton = new global::Gtk.Button ();
+			this.statebutton.CanFocus = true;
+			this.statebutton.Name = "statebutton";
+			this.statebutton.UseUnderline = true;
+			this.statebutton.Label = "";
+			this.hbox1.Add (this.statebutton);
+			global::Gtk.Box.BoxChild w1 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.statebutton]));
+			w1.Position = 0;
+			// Container child hbox1.Gtk.Box+BoxChild
+			this.progressbar = new global::Gtk.ProgressBar ();
+			this.progressbar.Name = "progressbar";
+			this.hbox1.Add (this.progressbar);
+			global::Gtk.Box.BoxChild w2 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.progressbar]));
+			w2.Position = 1;
+			// Container child hbox1.Gtk.Box+BoxChild
+			this.cancellbutton = new global::Gtk.Button ();
+			this.cancellbutton.CanFocus = true;
+			this.cancellbutton.Name = "cancellbutton";
+			this.cancellbutton.UseUnderline = true;
+			// Container child cancellbutton.Gtk.Container+ContainerChild
+			global::Gtk.Alignment w3 = new global::Gtk.Alignment (0.5f, 0.5f, 0f, 0f);
+			// Container child GtkAlignment.Gtk.Container+ContainerChild
+			global::Gtk.HBox w4 = new global::Gtk.HBox ();
+			w4.Spacing = 2;
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Image w5 = new global::Gtk.Image ();
+			w5.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-cancel", global::Gtk.IconSize.Menu);
+			w4.Add (w5);
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Label w7 = new global::Gtk.Label ();
+			w4.Add (w7);
+			w3.Add (w4);
+			this.cancellbutton.Add (w3);
+			this.hbox1.Add (this.cancellbutton);
+			global::Gtk.Box.BoxChild w11 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.cancellbutton]));
+			w11.Position = 2;
+			w11.Expand = false;
+			w11.Fill = false;
+			this.Add (this.hbox1);
+			if ((this.Child != null)) {
+				this.Child.ShowAll ();
+			}
+			this.cancellbutton.Hide ();
+			this.Hide ();
+		}
+	}
+}
diff --git a/LongoMatch/gtk-gui/LongoMatch.Gui.Dialog.RenderingJobsDialog.cs b/LongoMatch/gtk-gui/LongoMatch.Gui.Dialog.RenderingJobsDialog.cs
new file mode 100644
index 0000000..0eb5887
--- /dev/null
+++ b/LongoMatch/gtk-gui/LongoMatch.Gui.Dialog.RenderingJobsDialog.cs
@@ -0,0 +1,172 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace LongoMatch.Gui.Dialog
+{
+	public partial class RenderingJobsDialog
+	{
+		private global::Gtk.HBox hbox1;
+
+		private global::Gtk.ScrolledWindow GtkScrolledWindow;
+
+		private global::LongoMatch.Gui.Component.RenderingJobsTreeView renderingjobstreeview2;
+
+		private global::Gtk.VBox vbox2;
+
+		private global::Gtk.Button clearbutton;
+
+		private global::Gtk.Button cancelbutton;
+
+		private global::Gtk.Button retrybutton;
+
+		private global::Gtk.Button buttonOk;
+
+		protected virtual void Build ()
+		{
+			global::Stetic.Gui.Initialize (this);
+			// Widget LongoMatch.Gui.Dialog.RenderingJobsDialog
+			this.Name = "LongoMatch.Gui.Dialog.RenderingJobsDialog";
+			this.Icon = global::Gdk.Pixbuf.LoadFromResource ("longomatch.png");
+			this.WindowPosition = ((global::Gtk.WindowPosition)(4));
+			this.Modal = true;
+			this.Gravity = ((global::Gdk.Gravity)(5));
+			this.SkipPagerHint = true;
+			this.SkipTaskbarHint = true;
+			// Internal child LongoMatch.Gui.Dialog.RenderingJobsDialog.VBox
+			global::Gtk.VBox w1 = this.VBox;
+			w1.Name = "dialog1_VBox";
+			w1.BorderWidth = ((uint)(2));
+			// Container child dialog1_VBox.Gtk.Box+BoxChild
+			this.hbox1 = new global::Gtk.HBox ();
+			this.hbox1.Name = "hbox1";
+			this.hbox1.Spacing = 6;
+			// Container child hbox1.Gtk.Box+BoxChild
+			this.GtkScrolledWindow = new global::Gtk.ScrolledWindow ();
+			this.GtkScrolledWindow.Name = "GtkScrolledWindow";
+			this.GtkScrolledWindow.ShadowType = ((global::Gtk.ShadowType)(1));
+			// Container child GtkScrolledWindow.Gtk.Container+ContainerChild
+			this.renderingjobstreeview2 = new global::LongoMatch.Gui.Component.RenderingJobsTreeView ();
+			this.renderingjobstreeview2.CanFocus = true;
+			this.renderingjobstreeview2.Name = "renderingjobstreeview2";
+			this.GtkScrolledWindow.Add (this.renderingjobstreeview2);
+			this.hbox1.Add (this.GtkScrolledWindow);
+			global::Gtk.Box.BoxChild w3 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.GtkScrolledWindow]));
+			w3.Position = 0;
+			// Container child hbox1.Gtk.Box+BoxChild
+			this.vbox2 = new global::Gtk.VBox ();
+			this.vbox2.Name = "vbox2";
+			this.vbox2.Spacing = 6;
+			// Container child vbox2.Gtk.Box+BoxChild
+			this.clearbutton = new global::Gtk.Button ();
+			this.clearbutton.CanFocus = true;
+			this.clearbutton.Name = "clearbutton";
+			this.clearbutton.UseUnderline = true;
+			// Container child clearbutton.Gtk.Container+ContainerChild
+			global::Gtk.Alignment w4 = new global::Gtk.Alignment (0.5f, 0.5f, 0f, 0f);
+			// Container child GtkAlignment.Gtk.Container+ContainerChild
+			global::Gtk.HBox w5 = new global::Gtk.HBox ();
+			w5.Spacing = 2;
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Image w6 = new global::Gtk.Image ();
+			w6.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-delete", global::Gtk.IconSize.Menu);
+			w5.Add (w6);
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Label w8 = new global::Gtk.Label ();
+			w8.LabelProp = global::Mono.Unix.Catalog.GetString ("C_lear finished jobs");
+			w8.UseUnderline = true;
+			w5.Add (w8);
+			w4.Add (w5);
+			this.clearbutton.Add (w4);
+			this.vbox2.Add (this.clearbutton);
+			global::Gtk.Box.BoxChild w12 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.clearbutton]));
+			w12.Position = 0;
+			w12.Expand = false;
+			w12.Fill = false;
+			// Container child vbox2.Gtk.Box+BoxChild
+			this.cancelbutton = new global::Gtk.Button ();
+			this.cancelbutton.CanFocus = true;
+			this.cancelbutton.Name = "cancelbutton";
+			this.cancelbutton.UseUnderline = true;
+			// Container child cancelbutton.Gtk.Container+ContainerChild
+			global::Gtk.Alignment w13 = new global::Gtk.Alignment (0.5f, 0.5f, 0f, 0f);
+			// Container child GtkAlignment.Gtk.Container+ContainerChild
+			global::Gtk.HBox w14 = new global::Gtk.HBox ();
+			w14.Spacing = 2;
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Image w15 = new global::Gtk.Image ();
+			w15.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-cancel", global::Gtk.IconSize.Menu);
+			w14.Add (w15);
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Label w17 = new global::Gtk.Label ();
+			w17.LabelProp = global::Mono.Unix.Catalog.GetString ("_Cancel job");
+			w17.UseUnderline = true;
+			w14.Add (w17);
+			w13.Add (w14);
+			this.cancelbutton.Add (w13);
+			this.vbox2.Add (this.cancelbutton);
+			global::Gtk.Box.BoxChild w21 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.cancelbutton]));
+			w21.Position = 1;
+			w21.Expand = false;
+			w21.Fill = false;
+			// Container child vbox2.Gtk.Box+BoxChild
+			this.retrybutton = new global::Gtk.Button ();
+			this.retrybutton.CanFocus = true;
+			this.retrybutton.Name = "retrybutton";
+			this.retrybutton.UseUnderline = true;
+			// Container child retrybutton.Gtk.Container+ContainerChild
+			global::Gtk.Alignment w22 = new global::Gtk.Alignment (0.5f, 0.5f, 0f, 0f);
+			// Container child GtkAlignment.Gtk.Container+ContainerChild
+			global::Gtk.HBox w23 = new global::Gtk.HBox ();
+			w23.Spacing = 2;
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Image w24 = new global::Gtk.Image ();
+			w24.Pixbuf = global::Stetic.IconLoader.LoadIcon (this, "gtk-refresh", global::Gtk.IconSize.Menu);
+			w23.Add (w24);
+			// Container child GtkHBox.Gtk.Container+ContainerChild
+			global::Gtk.Label w26 = new global::Gtk.Label ();
+			w26.LabelProp = global::Mono.Unix.Catalog.GetString ("Retry job");
+			w26.UseUnderline = true;
+			w23.Add (w26);
+			w22.Add (w23);
+			this.retrybutton.Add (w22);
+			this.vbox2.Add (this.retrybutton);
+			global::Gtk.Box.BoxChild w30 = ((global::Gtk.Box.BoxChild)(this.vbox2[this.retrybutton]));
+			w30.Position = 2;
+			w30.Expand = false;
+			w30.Fill = false;
+			this.hbox1.Add (this.vbox2);
+			global::Gtk.Box.BoxChild w31 = ((global::Gtk.Box.BoxChild)(this.hbox1[this.vbox2]));
+			w31.Position = 1;
+			w31.Expand = false;
+			w31.Fill = false;
+			w1.Add (this.hbox1);
+			global::Gtk.Box.BoxChild w32 = ((global::Gtk.Box.BoxChild)(w1[this.hbox1]));
+			w32.Position = 0;
+			// Internal child LongoMatch.Gui.Dialog.RenderingJobsDialog.ActionArea
+			global::Gtk.HButtonBox w33 = this.ActionArea;
+			w33.Name = "dialog1_ActionArea";
+			w33.Spacing = 10;
+			w33.BorderWidth = ((uint)(5));
+			w33.LayoutStyle = ((global::Gtk.ButtonBoxStyle)(4));
+			// Container child dialog1_ActionArea.Gtk.ButtonBox+ButtonBoxChild
+			this.buttonOk = new global::Gtk.Button ();
+			this.buttonOk.CanDefault = true;
+			this.buttonOk.CanFocus = true;
+			this.buttonOk.Name = "buttonOk";
+			this.buttonOk.UseStock = true;
+			this.buttonOk.UseUnderline = true;
+			this.buttonOk.Label = "gtk-ok";
+			this.AddActionWidget (this.buttonOk, -5);
+			global::Gtk.ButtonBox.ButtonBoxChild w34 = ((global::Gtk.ButtonBox.ButtonBoxChild)(w33[this.buttonOk]));
+			w34.Expand = false;
+			w34.Fill = false;
+			if ((this.Child != null)) {
+				this.Child.ShowAll ();
+			}
+			this.DefaultWidth = 400;
+			this.DefaultHeight = 212;
+			this.cancelbutton.Hide ();
+			this.retrybutton.Hide ();
+			this.Show ();
+		}
+	}
+}
diff --git a/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs b/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs
index 0d197d9..e1dda90 100644
--- a/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs
+++ b/LongoMatch/gtk-gui/LongoMatch.Gui.MainWindow.cs
@@ -104,7 +104,7 @@ namespace LongoMatch.Gui
 
 		private global::Gtk.Statusbar statusbar1;
 
-		private global::Gtk.ProgressBar videoprogressbar;
+		private global::LongoMatch.Gui.Component.RenderingStateBar renderingstatebar1;
 
 		protected virtual void Build ()
 		{
@@ -234,7 +234,7 @@ namespace LongoMatch.Gui
 			this.notebook1 = new global::Gtk.Notebook ();
 			this.notebook1.CanFocus = true;
 			this.notebook1.Name = "notebook1";
-			this.notebook1.CurrentPage = 0;
+			this.notebook1.CurrentPage = 3;
 			this.notebook1.TabPos = ((global::Gtk.PositionType)(3));
 			// Container child notebook1.Gtk.Notebook+NotebookChild
 			this.treewidget1 = new global::LongoMatch.Gui.Component.PlaysListTreeWidget ();
@@ -392,12 +392,13 @@ namespace LongoMatch.Gui
 			this.statusbar1.Name = "statusbar1";
 			this.statusbar1.Spacing = 6;
 			// Container child statusbar1.Gtk.Box+BoxChild
-			this.videoprogressbar = new global::Gtk.ProgressBar ();
-			this.videoprogressbar.Name = "videoprogressbar";
-			this.videoprogressbar.Text = global::Mono.Unix.Catalog.GetString ("Creating video...");
-			this.statusbar1.Add (this.videoprogressbar);
-			global::Gtk.Box.BoxChild w22 = ((global::Gtk.Box.BoxChild)(this.statusbar1[this.videoprogressbar]));
-			w22.Position = 3;
+			this.renderingstatebar1 = new global::LongoMatch.Gui.Component.RenderingStateBar ();
+			this.renderingstatebar1.Events = ((global::Gdk.EventMask)(256));
+			this.renderingstatebar1.Name = "renderingstatebar1";
+			this.renderingstatebar1.Fraction = 0;
+			this.statusbar1.Add (this.renderingstatebar1);
+			global::Gtk.Box.BoxChild w22 = ((global::Gtk.Box.BoxChild)(this.statusbar1[this.renderingstatebar1]));
+			w22.Position = 2;
 			w22.Expand = false;
 			w22.Fill = false;
 			this.vbox1.Add (this.statusbar1);
@@ -418,7 +419,7 @@ namespace LongoMatch.Gui
 			this.noteswidget1.Hide ();
 			this.playlistwidget2.Hide ();
 			this.rightvbox.Hide ();
-			this.videoprogressbar.Hide ();
+			this.renderingstatebar1.Hide ();
 			this.Show ();
 			this.NewPojectAction.Activated += new global::System.EventHandler (this.OnNewActivated);
 			this.OpenProjectAction.Activated += new global::System.EventHandler (this.OnOpenActivated);
diff --git a/LongoMatch/gtk-gui/LongoMatch.Gui.TreeView.RenderingJobsTreeView.cs b/LongoMatch/gtk-gui/LongoMatch.Gui.TreeView.RenderingJobsTreeView.cs
new file mode 100644
index 0000000..08d7b36
--- /dev/null
+++ b/LongoMatch/gtk-gui/LongoMatch.Gui.TreeView.RenderingJobsTreeView.cs
@@ -0,0 +1,19 @@
+
+// This file has been generated by the GUI designer. Do not modify.
+namespace LongoMatch.Gui.TreeView
+{
+	public partial class RenderingJobsTreeView
+	{
+		protected virtual void Build ()
+		{
+			global::Stetic.Gui.Initialize (this);
+			// Widget LongoMatch.Gui.TreeView.RenderingJobsTreeView
+			global::Stetic.BinContainer.Attach (this);
+			this.Name = "LongoMatch.Gui.TreeView.RenderingJobsTreeView";
+			if ((this.Child != null)) {
+				this.Child.ShowAll ();
+			}
+			this.Hide ();
+		}
+	}
+}
diff --git a/LongoMatch/gtk-gui/gui.stetic b/LongoMatch/gtk-gui/gui.stetic
index 869305e..6fa8b38 100644
--- a/LongoMatch/gtk-gui/gui.stetic
+++ b/LongoMatch/gtk-gui/gui.stetic
@@ -1823,7 +1823,7 @@
                   <widget class="Gtk.Notebook" id="notebook1">
                     <property name="MemberName" />
                     <property name="CanFocus">True</property>
-                    <property name="CurrentPage">0</property>
+                    <property name="CurrentPage">3</property>
                     <property name="TabPos">Bottom</property>
                     <child>
                       <widget class="LongoMatch.Gui.Component.PlaysListTreeWidget" id="treewidget1">
@@ -2051,16 +2051,14 @@
               <placeholder />
             </child>
             <child>
-              <placeholder />
-            </child>
-            <child>
-              <widget class="Gtk.ProgressBar" id="videoprogressbar">
+              <widget class="LongoMatch.Gui.Component.RenderingStateBar" id="renderingstatebar1">
                 <property name="MemberName" />
                 <property name="Visible">False</property>
-                <property name="Text" translatable="yes">Creating video...</property>
+                <property name="Events">ButtonPressMask</property>
+                <property name="Fraction">0</property>
               </widget>
               <packing>
-                <property name="Position">3</property>
+                <property name="Position">2</property>
                 <property name="AutoSize">False</property>
                 <property name="Expand">False</property>
                 <property name="Fill">False</property>
@@ -2760,23 +2758,6 @@ new one.</property>
                 <property name="AutoSize">False</property>
               </packing>
             </child>
-            <child>
-              <widget class="Gtk.Button" id="closebutton">
-                <property name="MemberName" />
-                <property name="Visible">False</property>
-                <property name="Tooltip" translatable="yes">Cancel rendering</property>
-                <property name="CanFocus">True</property>
-                <property name="Type">TextAndIcon</property>
-                <property name="Icon">stock:gtk-close Button</property>
-                <property name="Label" translatable="yes" />
-                <property name="UseUnderline">True</property>
-                <signal name="Clicked" handler="OnClosebuttonClicked" />
-              </widget>
-              <packing>
-                <property name="Position">4</property>
-                <property name="AutoSize">False</property>
-              </packing>
-            </child>
           </widget>
           <packing>
             <property name="Position">1</property>
@@ -6429,4 +6410,184 @@ You can continue with the current capture, cancel it or save your project.
       </widget>
     </child>
   </widget>
+  <widget class="Gtk.Bin" id="LongoMatch.Gui.Component.RenderingStateBar" design-size="204 28">
+    <property name="MemberName" />
+    <property name="Visible">False</property>
+    <child>
+      <widget class="Gtk.HBox" id="hbox1">
+        <property name="MemberName" />
+        <property name="Spacing">6</property>
+        <child>
+          <widget class="Gtk.Button" id="statebutton">
+            <property name="MemberName" />
+            <property name="CanFocus">True</property>
+            <property name="Type">TextOnly</property>
+            <property name="Label" translatable="yes" />
+            <property name="UseUnderline">True</property>
+          </widget>
+          <packing>
+            <property name="Position">0</property>
+            <property name="AutoSize">False</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="Gtk.ProgressBar" id="progressbar">
+            <property name="MemberName" />
+          </widget>
+          <packing>
+            <property name="Position">1</property>
+            <property name="AutoSize">True</property>
+          </packing>
+        </child>
+        <child>
+          <widget class="Gtk.Button" id="cancellbutton">
+            <property name="MemberName" />
+            <property name="Visible">False</property>
+            <property name="CanFocus">True</property>
+            <property name="Type">TextAndIcon</property>
+            <property name="Icon">stock:gtk-cancel Menu</property>
+            <property name="Label" translatable="yes" />
+            <property name="UseUnderline">True</property>
+          </widget>
+          <packing>
+            <property name="Position">2</property>
+            <property name="AutoSize">True</property>
+            <property name="Expand">False</property>
+            <property name="Fill">False</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
+  <widget class="Gtk.Dialog" id="LongoMatch.Gui.Dialog.RenderingJobsDialog" design-size="400 212">
+    <property name="MemberName" />
+    <property name="Icon">resource:longomatch.png</property>
+    <property name="WindowPosition">CenterOnParent</property>
+    <property name="Modal">True</property>
+    <property name="Gravity">Center</property>
+    <property name="SkipPagerHint">True</property>
+    <property name="SkipTaskbarHint">True</property>
+    <property name="Buttons">1</property>
+    <property name="HelpButton">False</property>
+    <child internal-child="VBox">
+      <widget class="Gtk.VBox" id="dialog1_VBox">
+        <property name="MemberName" />
+        <property name="BorderWidth">2</property>
+        <child>
+          <widget class="Gtk.HBox" id="hbox1">
+            <property name="MemberName" />
+            <property name="Spacing">6</property>
+            <child>
+              <widget class="Gtk.ScrolledWindow" id="GtkScrolledWindow">
+                <property name="MemberName" />
+                <property name="ShadowType">In</property>
+                <child>
+                  <widget class="LongoMatch.Gui.Component.RenderingJobsTreeView" id="renderingjobstreeview2">
+                    <property name="MemberName" />
+                    <property name="CanFocus">True</property>
+                    <property name="ShowScrollbars">True</property>
+                  </widget>
+                </child>
+              </widget>
+              <packing>
+                <property name="Position">0</property>
+                <property name="AutoSize">True</property>
+              </packing>
+            </child>
+            <child>
+              <widget class="Gtk.VBox" id="vbox2">
+                <property name="MemberName" />
+                <property name="Spacing">6</property>
+                <child>
+                  <widget class="Gtk.Button" id="clearbutton">
+                    <property name="MemberName" />
+                    <property name="CanFocus">True</property>
+                    <property name="Type">TextAndIcon</property>
+                    <property name="Icon">stock:gtk-delete Menu</property>
+                    <property name="Label" translatable="yes">C_lear finished jobs</property>
+                    <property name="UseUnderline">True</property>
+                  </widget>
+                  <packing>
+                    <property name="Position">0</property>
+                    <property name="AutoSize">True</property>
+                    <property name="Expand">False</property>
+                    <property name="Fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <widget class="Gtk.Button" id="cancelbutton">
+                    <property name="MemberName" />
+                    <property name="Visible">False</property>
+                    <property name="CanFocus">True</property>
+                    <property name="Type">TextAndIcon</property>
+                    <property name="Icon">stock:gtk-cancel Menu</property>
+                    <property name="Label" translatable="yes">_Cancel job</property>
+                    <property name="UseUnderline">True</property>
+                  </widget>
+                  <packing>
+                    <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="retrybutton">
+                    <property name="MemberName" />
+                    <property name="Visible">False</property>
+                    <property name="CanFocus">True</property>
+                    <property name="Type">TextAndIcon</property>
+                    <property name="Icon">stock:gtk-refresh Menu</property>
+                    <property name="Label" translatable="yes">Retry job</property>
+                    <property name="UseUnderline">True</property>
+                  </widget>
+                  <packing>
+                    <property name="Position">2</property>
+                    <property name="AutoSize">True</property>
+                    <property name="Expand">False</property>
+                    <property name="Fill">False</property>
+                  </packing>
+                </child>
+              </widget>
+              <packing>
+                <property name="Position">1</property>
+                <property name="AutoSize">False</property>
+                <property name="Expand">False</property>
+                <property name="Fill">False</property>
+              </packing>
+            </child>
+          </widget>
+          <packing>
+            <property name="Position">0</property>
+            <property name="AutoSize">False</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+    <child internal-child="ActionArea">
+      <widget class="Gtk.HButtonBox" id="dialog1_ActionArea">
+        <property name="MemberName" />
+        <property name="Spacing">10</property>
+        <property name="BorderWidth">5</property>
+        <property name="Size">1</property>
+        <property name="LayoutStyle">End</property>
+        <child>
+          <widget class="Gtk.Button" id="buttonOk">
+            <property name="MemberName" />
+            <property name="CanDefault">True</property>
+            <property name="CanFocus">True</property>
+            <property name="UseStock">True</property>
+            <property name="Type">StockItem</property>
+            <property name="StockId">gtk-ok</property>
+            <property name="ResponseId">-5</property>
+            <property name="label">gtk-ok</property>
+          </widget>
+          <packing>
+            <property name="Expand">False</property>
+            <property name="Fill">False</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </stetic-interface>
\ No newline at end of file
diff --git a/LongoMatch/gtk-gui/objects.xml b/LongoMatch/gtk-gui/objects.xml
index 237219b..273ebff 100644
--- a/LongoMatch/gtk-gui/objects.xml
+++ b/LongoMatch/gtk-gui/objects.xml
@@ -162,7 +162,7 @@
       <itemgroup label="PlayListWidget Signals">
         <signal name="PlayListNodeSelected" />
         <signal name="ApplyCurrentRate" />
-        <signal name="Progress" />
+        <signal name="NewRenderingJob" />
       </itemgroup>
     </signals>
   </object>
@@ -282,4 +282,22 @@
       </itemgroup>
     </signals>
   </object>
+  <object type="LongoMatch.Gui.Component.RenderingStateBar" palette-category="General" allow-children="false" base-type="Gtk.Bin">
+    <itemgroups>
+      <itemgroup label="RenderingStateBar Properties">
+        <property name="Fraction" />
+      </itemgroup>
+    </itemgroups>
+    <signals>
+      <itemgroup label="RenderingStateBar Signals">
+        <signal name="Cancel" />
+        <signal name="ManageJobs" />
+      </itemgroup>
+    </signals>
+  </object>
+  <object type="LongoMatch.Gui.Component.RenderingJobsTreeView" palette-category="General" allow-children="false" base-type="Gtk.TreeView">
+    <itemgroups />
+    <signals>
+    </signals>
+  </object>
 </objects>
\ No newline at end of file



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