\r
return queueFiles;\r
}\r
- catch (Exception)\r
+ catch (Exception exc)\r
{\r
return new List<string>(); // Keep quiet about the error.\r
}\r
<Compile Include="Model\General\UpdateCheckResult.cs" />\r
<Compile Include="Model\ModelBase.cs" />\r
<Compile Include="Model\Preset.cs" />\r
+ <Compile Include="Model\QueueItemStatus.cs" />\r
<Compile Include="Model\QueueTask.cs" />\r
<Compile Include="Model\Encoding\SubtitleType.cs" />\r
<Compile Include="Parsing\Audio.cs" />\r
--- /dev/null
+/* QueueItemStatus.cs $\r
+ This file is part of the HandBrake source code.\r
+ Homepage: <http://handbrake.fr>.\r
+ It may be used under the terms of the GNU General Public License. */\r
+\r
+namespace HandBrake.ApplicationServices.Model\r
+{\r
+ using System.ComponentModel;\r
+\r
+ using HandBrake.ApplicationServices.Converters;\r
+\r
+ /// <summary>\r
+ /// Queue Item Status\r
+ /// </summary>\r
+ [TypeConverter(typeof(EnumToDescConveter))]\r
+ public enum QueueItemStatus\r
+ {\r
+ [Description("Waiting")]\r
+ Waiting = 0,\r
+\r
+ [Description("In Progress")]\r
+ InProgress,\r
+\r
+ [Description("Completed")]\r
+ Completed,\r
+\r
+ [Description("Error")]\r
+ Error,\r
+ }\r
+}\r
\r
namespace HandBrake.ApplicationServices.Model\r
{\r
+ using System;\r
+\r
/// <summary>\r
/// The QueueTask.\r
/// </summary>\r
/// </summary>\r
public bool CustomQuery { get; set; }\r
\r
+ /// <summary>\r
+ /// Gets or sets Status.\r
+ /// </summary>\r
+ public QueueItemStatus Status { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets or sets StartTime.\r
+ /// </summary>\r
+ public DateTime StartTime { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets or sets ElaspedEncodeTime.\r
+ /// </summary>\r
+ public TimeSpan ElaspedEncodeTime { get; set; }\r
+\r
/// <summary>\r
/// Gets or sets the Encode Task.\r
/// </summary>\r
/// </summary>\r
private DateTime startTime;\r
\r
+ /// <summary>\r
+ /// The Current Task\r
+ /// </summary>\r
+ private QueueTask currentTask;\r
+\r
#endregion\r
\r
/// <summary>\r
{\r
try\r
{\r
- QueueTask queueTask = encodeQueueTask;\r
+ this.currentTask = encodeQueueTask;\r
\r
if (this.IsEncoding)\r
{\r
{\r
try\r
{\r
- this.SetupLogging(queueTask);\r
+ this.SetupLogging(currentTask);\r
}\r
catch (Exception)\r
{\r
}\r
\r
// Make sure the path exists, attempt to create it if it doesn't\r
- this.VerifyEncodeDestinationPath(queueTask);\r
+ this.VerifyEncodeDestinationPath(currentTask);\r
\r
string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");\r
- ProcessStartInfo cliStart = new ProcessStartInfo(handbrakeCLIPath, queueTask.Query)\r
+ ProcessStartInfo cliStart = new ProcessStartInfo(handbrakeCLIPath, currentTask.Query)\r
{\r
RedirectStandardOutput = true,\r
RedirectStandardError = enableLogging ? true : false,\r
}\r
catch (Exception exc)\r
{\r
- this.Invoke_encodeCompleted(new EncodeCompletedEventArgs(false, exc, "An Error occured when trying to encode this source. "));\r
+ TimeSpan time = DateTime.Now.Subtract(this.currentTask.StartTime);\r
+ this.Invoke_encodeCompleted(\r
+ new EncodeCompletedEventArgs(\r
+ false, exc, "An Error occured when trying to encode this source. "));\r
}\r
}\r
\r
// This exception doesn't warrent user interaction, but it should be logged (TODO)\r
}\r
\r
+ this.currentTask.Status = QueueItemStatus.Completed;\r
this.Invoke_encodeCompleted(new EncodeCompletedEventArgs(true, null, string.Empty));\r
}\r
\r
/// </param>\r
void Remove(QueueTask job);\r
\r
+ /// <summary>\r
+ /// Reset a Queued Item from Error or Completed to Waiting\r
+ /// </summary>\r
+ /// <param name="job">\r
+ /// The job.\r
+ /// </param>\r
+ void ResetJobStatusToWaiting(QueueTask job);\r
+\r
+ /// <summary>\r
+ /// Clear down the Queue´s completed items\r
+ /// </summary>\r
+ void ClearCompleted();\r
+\r
/// <summary>\r
/// Get the first job on the queue for processing.\r
/// This also removes the job from the Queue and sets the LastProcessedJob\r
using System.Windows.Forms;\r
using System.Xml.Serialization;\r
\r
+ using HandBrake.ApplicationServices.Exceptions;\r
using HandBrake.ApplicationServices.Model;\r
using HandBrake.ApplicationServices.Services.Interfaces;\r
\r
{\r
get\r
{\r
- return this.queue.Count;\r
+ return this.queue.Where(item => item.Status == QueueItemStatus.Waiting).Count();\r
}\r
}\r
\r
}\r
}\r
\r
+ /// <summary>\r
+ /// Reset a Queued Item from Error or Completed to Waiting\r
+ /// </summary>\r
+ /// <param name="job">\r
+ /// The job.\r
+ /// </param>\r
+ public void ResetJobStatusToWaiting(QueueTask job)\r
+ {\r
+ if (job.Status != QueueItemStatus.Error && job.Status != QueueItemStatus.Completed)\r
+ {\r
+ throw new GeneralApplicationException("Job Error", "Unable to reset job status as it is not in an Error or Completed state", null);\r
+ }\r
+\r
+ job.Status = QueueItemStatus.Waiting;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Clear down the Queue´s completed items\r
+ /// </summary>\r
+ public void ClearCompleted()\r
+ {\r
+ List<QueueTask> deleteList = this.queue.Where(task => task.Status == QueueItemStatus.Completed).ToList();\r
+ foreach (QueueTask item in deleteList)\r
+ {\r
+ this.queue.Remove(item);\r
+ }\r
+ this.InvokeQueueChanged(EventArgs.Empty);\r
+ }\r
+\r
/// <summary>\r
/// Get the first job on the queue for processing.\r
/// This also removes the job from the Queue and sets the LastProcessedJob\r
{\r
if (this.queue.Count > 0)\r
{\r
- QueueTask job = this.queue[0];\r
- this.LastProcessedJob = job;\r
- this.Remove(job); // Remove the item which we are about to pass out.\r
+ QueueTask job = this.queue.FirstOrDefault(q => q.Status == QueueItemStatus.Waiting);\r
+ if (job != null)\r
+ {\r
+ job.Status = QueueItemStatus.InProgress;\r
+ job.StartTime = DateTime.Now;\r
+ this.LastProcessedJob = job;\r
+ InvokeQueueChanged(EventArgs.Empty);\r
+ }\r
\r
return job;\r
}\r
string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");\r
string tempPath = !string.IsNullOrEmpty(exportPath) ? exportPath : appDataPath + string.Format(this.queueFile, string.Empty);\r
\r
+\r
using (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write))\r
{\r
+ List<QueueTask> tasks = queue.Where(item => item.Status != QueueItemStatus.Completed).ToList();\r
XmlSerializer serializer = new XmlSerializer(typeof(List<QueueTask>));\r
- serializer.Serialize(strm, queue);\r
+ serializer.Serialize(strm, tasks);\r
strm.Close();\r
strm.Dispose();\r
}\r
\r
if (list != null)\r
foreach (QueueTask item in list)\r
- this.queue.Add(item);\r
+ {\r
+ if (item.Status != QueueItemStatus.Completed)\r
+ {\r
+ // Reset InProgress/Error to Waiting so it can be processed\r
+ if (item.Status == QueueItemStatus.InProgress)\r
+ {\r
+ item.Status = QueueItemStatus.Waiting;\r
+ }\r
+\r
+ this.queue.Add(item);\r
+ }\r
+ }\r
\r
this.InvokeQueueChanged(EventArgs.Empty);\r
}\r
/// The encode Service.\r
/// </param>\r
/// <exception cref="ArgumentNullException">\r
+ /// Services are not setup\r
/// </exception>\r
public QueueProcessor(IQueueManager queueManager, IEncode encodeService)\r
{\r
/// </summary>\r
public void Pause()\r
{\r
- this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;\r
this.InvokeQueuePaused(EventArgs.Empty);\r
this.IsProcessing = false;\r
}\r
/// </param>\r
private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e)\r
{\r
+ this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Completed;\r
+\r
// Growl\r
if (Properties.Settings.Default.GrowlEncode)\r
GrowlCommunicator.Notify("Encode Completed",\r
\r
if (!e.Successful)\r
{\r
+ this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Error;\r
this.Pause();\r
throw new GeneralApplicationException(e.ErrorInformation, e.Exception.Message, e.Exception);\r
}\r
}\r
\r
// Move onto the next job.\r
- this.ProcessNextJob();\r
+ if (this.IsProcessing)\r
+ {\r
+ this.ProcessNextJob();\r
+ } \r
+ else \r
+ {\r
+ this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;\r
+ this.InvokeQueueCompleted(EventArgs.Empty);\r
+ this.QueueManager.BackupQueue(string.Empty);\r
+ }\r
}\r
\r
/// <summary>\r
this.toolStripButton1 = new System.Windows.Forms.ToolStripButton();\r
this.SaveFile = new System.Windows.Forms.SaveFileDialog();\r
this.list_queue = new System.Windows.Forms.ListView();\r
+ this.Status = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\r
this.Title = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\r
this.Chapters = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\r
this.Source = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));\r
this.mnu_edit = new System.Windows.Forms.ToolStripMenuItem();\r
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();\r
this.mnu_delete = new System.Windows.Forms.ToolStripMenuItem();\r
+ this.mnuClearCompleted = new System.Windows.Forms.ToolStripMenuItem();\r
this.statusStrip1 = new System.Windows.Forms.StatusStrip();\r
this.lbl_encodesPending = new System.Windows.Forms.ToolStripStatusLabel();\r
this.OpenFile = new System.Windows.Forms.OpenFileDialog();\r
this.panel3 = new System.Windows.Forms.Panel();\r
this.panel2 = new System.Windows.Forms.Panel();\r
this.panel1 = new System.Windows.Forms.Panel();\r
+ this.mnu_Retry = new System.Windows.Forms.ToolStripMenuItem();\r
this.toolStrip1.SuspendLayout();\r
this.mnu_queue.SuspendLayout();\r
this.statusStrip1.SuspendLayout();\r
// list_queue\r
// \r
this.list_queue.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {\r
+ this.Status,\r
this.Title,\r
this.Chapters,\r
this.Source,\r
this.list_queue.View = System.Windows.Forms.View.Details;\r
this.list_queue.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ListQueueDeleteKey);\r
// \r
+ // Status\r
+ // \r
+ this.Status.Text = "Job Status";\r
+ this.Status.Width = 80;\r
+ // \r
// Title\r
// \r
this.Title.Text = "Title";\r
this.mnu_Down,\r
this.toolStripSeparator3,\r
this.mnu_edit,\r
+ this.mnu_Retry,\r
this.toolStripSeparator4,\r
+ this.mnuClearCompleted,\r
this.mnu_delete});\r
this.mnu_queue.Name = "mnu_queue";\r
- this.mnu_queue.Size = new System.Drawing.Size(139, 104);\r
+ this.mnu_queue.Size = new System.Drawing.Size(164, 148);\r
// \r
// mnu_up\r
// \r
this.mnu_up.Name = "mnu_up";\r
- this.mnu_up.Size = new System.Drawing.Size(138, 22);\r
+ this.mnu_up.Size = new System.Drawing.Size(163, 22);\r
this.mnu_up.Text = "Move Up";\r
this.mnu_up.Click += new System.EventHandler(this.MnuUpClick);\r
// \r
// mnu_Down\r
// \r
this.mnu_Down.Name = "mnu_Down";\r
- this.mnu_Down.Size = new System.Drawing.Size(138, 22);\r
+ this.mnu_Down.Size = new System.Drawing.Size(163, 22);\r
this.mnu_Down.Text = "Move Down";\r
this.mnu_Down.Click += new System.EventHandler(this.MnuDownClick);\r
// \r
// toolStripSeparator3\r
// \r
this.toolStripSeparator3.Name = "toolStripSeparator3";\r
- this.toolStripSeparator3.Size = new System.Drawing.Size(135, 6);\r
+ this.toolStripSeparator3.Size = new System.Drawing.Size(160, 6);\r
// \r
// mnu_edit\r
// \r
this.mnu_edit.Name = "mnu_edit";\r
- this.mnu_edit.Size = new System.Drawing.Size(138, 22);\r
+ this.mnu_edit.Size = new System.Drawing.Size(163, 22);\r
this.mnu_edit.Text = "Edit";\r
this.mnu_edit.Click += new System.EventHandler(this.MnuEditClick);\r
// \r
// toolStripSeparator4\r
// \r
this.toolStripSeparator4.Name = "toolStripSeparator4";\r
- this.toolStripSeparator4.Size = new System.Drawing.Size(135, 6);\r
+ this.toolStripSeparator4.Size = new System.Drawing.Size(160, 6);\r
// \r
// mnu_delete\r
// \r
this.mnu_delete.Name = "mnu_delete";\r
- this.mnu_delete.Size = new System.Drawing.Size(138, 22);\r
+ this.mnu_delete.Size = new System.Drawing.Size(163, 22);\r
this.mnu_delete.Text = "Delete";\r
this.mnu_delete.Click += new System.EventHandler(this.MnuDeleteClick);\r
// \r
+ // mnuClearCompleted\r
+ // \r
+ this.mnuClearCompleted.Name = "mnuClearCompleted";\r
+ this.mnuClearCompleted.Size = new System.Drawing.Size(163, 22);\r
+ this.mnuClearCompleted.Text = "Clear Completed";\r
+ this.mnuClearCompleted.Click += new System.EventHandler(this.mnuClearCompleted_Click);\r
+ // \r
// statusStrip1\r
// \r
this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {\r
this.panel1.Size = new System.Drawing.Size(15, 214);\r
this.panel1.TabIndex = 0;\r
// \r
+ // mnu_Retry\r
+ // \r
+ this.mnu_Retry.Name = "mnu_Retry";\r
+ this.mnu_Retry.Size = new System.Drawing.Size(163, 22);\r
+ this.mnu_Retry.Text = "Retry Encode";\r
+ this.mnu_Retry.Click += new System.EventHandler(this.mnu_Retry_Click);\r
+ // \r
// frmQueue\r
// \r
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);\r
private System.Windows.Forms.ToolStripComboBox drp_completeOption;\r
private System.Windows.Forms.ToolStripButton toolStripButton1;\r
private System.Windows.Forms.Panel panel3;\r
+ private System.Windows.Forms.ColumnHeader Status;\r
+ private System.Windows.Forms.ToolStripMenuItem mnuClearCompleted;\r
+ private System.Windows.Forms.ToolStripMenuItem mnu_Retry;\r
}\r
}\r
/// </summary>\r
private readonly frmMain mainWindow;\r
\r
+ /// <summary>\r
+ /// The User setting service\r
+ /// </summary>\r
private readonly IUserSettingService userSettingService = new UserSettingService();\r
\r
/// <summary>\r
return;\r
}\r
\r
+ this.queue.QueueManager.LastProcessedJob.ElaspedEncodeTime = e.ElapsedTime;\r
+\r
lbl_encodeStatus.Text =\r
string.Format(\r
"Encoding: Pass {0} of {1}, {2:00.00}%, FPS: {3:000.0}, Avg FPS: {4:000.0}, Time Remaining: {5}, Elapsed: {6:hh\\:mm\\:ss}",\r
btn_pause.Visible = false;\r
btn_encode.Enabled = true;\r
\r
+ this.RedrawQueue();\r
ResetEncodeText();\r
}\r
\r
chapters = chapters + " - " + parsed.EndPoint;\r
}\r
\r
- ListViewItem item = new ListViewItem { Tag = queueItem, Text = title };\r
+ ListViewItem item = new ListViewItem\r
+ { Tag = queueItem, Text = EnumHelper<QueueItemStatus>.GetDescription(queueItem.Status) };\r
+ item.SubItems.Add(title);\r
item.SubItems.Add(chapters); // Chapters\r
item.SubItems.Add(queueItem.Source); // Source\r
item.SubItems.Add(queueItem.Destination); // Destination\r
UpdateStatusLabel();\r
}\r
\r
+ /// <summary>\r
+ /// Update the Display\r
+ /// </summary>\r
private void UpdateStatusLabel()\r
{\r
if (InvokeRequired)\r
return;\r
}\r
\r
- lbl_encodesPending.Text = string.Format("{0} encodes(s) pending", list_queue.Items.Count);\r
+ lbl_encodesPending.Text = string.Format("{0} encodes(s) pending", this.queue.QueueManager.Count);\r
}\r
\r
/// <summary>\r
{\r
userSettingService.SetUserSetting(UserSettingConstants.WhenCompleteAction, drp_completeOption.Text);\r
}\r
+\r
+ /// <summary>\r
+ /// Clear all completed items\r
+ /// </summary>\r
+ /// <param name="sender">\r
+ /// The sender.\r
+ /// </param>\r
+ /// <param name="e">\r
+ /// The e.\r
+ /// </param>\r
+ private void mnuClearCompleted_Click(object sender, EventArgs e)\r
+ {\r
+ this.queue.QueueManager.ClearCompleted();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Retry Job Menu Item\r
+ /// </summary>\r
+ /// <param name="sender">\r
+ /// The sender.\r
+ /// </param>\r
+ /// <param name="e">\r
+ /// The e.\r
+ /// </param>\r
+ private void mnu_Retry_Click(object sender, EventArgs e)\r
+ {\r
+ if (list_queue.SelectedIndices.Count != 0)\r
+ {\r
+ lock (queue)\r
+ {\r
+ lock (list_queue)\r
+ {\r
+ QueueTask index = list_queue.SelectedItems[0].Tag as QueueTask;\r
+\r
+ try\r
+ {\r
+ queue.QueueManager.ResetJobStatusToWaiting(index);\r
+ } \r
+ catch (Exception)\r
+ {\r
+ MessageBox.Show(\r
+ "Can only retry a job if it is in an Error or Completed state.",\r
+ "Notice",\r
+ MessageBoxButtons.OK,\r
+ MessageBoxIcon.Information);\r
+ }\r
+ RedrawQueue();\r
+ }\r
+ }\r
+ }\r
+ }\r
}\r
}
\ No newline at end of file