summaryrefslogtreecommitdiffstats
path: root/win/CS/HandBrakeWPF
diff options
context:
space:
mode:
authorsr55 <[email protected]>2015-03-01 18:03:28 +0000
committersr55 <[email protected]>2015-03-01 18:03:28 +0000
commit29c62be71227ae33e382199f323890ae3bfffa69 (patch)
treece95739341715439b97d7ca1b4baebd89474c6c9 /win/CS/HandBrakeWPF
parent5cce72f890bc7b6075a55aa4364b8817c22f11c0 (diff)
WinGui: Moving the Queue Code out to the UI level. The services library will be strictly a libhb warpper and service provider.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@6959 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'win/CS/HandBrakeWPF')
-rw-r--r--win/CS/HandBrakeWPF/EventArgs/QueueCompletedEventArgs.cs38
-rw-r--r--win/CS/HandBrakeWPF/EventArgs/QueueProgressEventArgs.cs37
-rw-r--r--win/CS/HandBrakeWPF/EventArgs/SettingChangedEventArgs.cs27
-rw-r--r--win/CS/HandBrakeWPF/HandBrakeWPF.csproj5
-rw-r--r--win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs2
-rw-r--r--win/CS/HandBrakeWPF/Services/Interfaces/IQueueProcessor.cs184
-rw-r--r--win/CS/HandBrakeWPF/Services/Interfaces/IUserSettingService.cs2
-rw-r--r--win/CS/HandBrakeWPF/Services/NotificationService.cs2
-rw-r--r--win/CS/HandBrakeWPF/Services/PrePostActionService.cs20
-rw-r--r--win/CS/HandBrakeWPF/Services/QueueProcessor.cs604
-rw-r--r--win/CS/HandBrakeWPF/Services/UserSettingService.cs3
-rw-r--r--win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs5
-rw-r--r--win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs7
-rw-r--r--win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs39
-rw-r--r--win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs2
-rw-r--r--win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs2
16 files changed, 941 insertions, 38 deletions
diff --git a/win/CS/HandBrakeWPF/EventArgs/QueueCompletedEventArgs.cs b/win/CS/HandBrakeWPF/EventArgs/QueueCompletedEventArgs.cs
new file mode 100644
index 000000000..e7e1fc813
--- /dev/null
+++ b/win/CS/HandBrakeWPF/EventArgs/QueueCompletedEventArgs.cs
@@ -0,0 +1,38 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="QueueCompletedEventArgs.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Queue Completed Event Args
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.EventArgs
+{
+ using System;
+ using System.Runtime.Serialization;
+
+ /// <summary>
+ /// Queue Completed Event Args
+ /// </summary>
+ [DataContract]
+ public class QueueCompletedEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueCompletedEventArgs"/> class.
+ /// </summary>
+ /// <param name="wasManuallyStopped">
+ /// The was Manually Stopped.
+ /// </param>
+ public QueueCompletedEventArgs(bool wasManuallyStopped)
+ {
+ this.WasManuallyStopped = wasManuallyStopped;
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the queue WasManuallyStopped.
+ /// </summary>
+ [DataMember]
+ public bool WasManuallyStopped { get; private set; }
+ }
+}
diff --git a/win/CS/HandBrakeWPF/EventArgs/QueueProgressEventArgs.cs b/win/CS/HandBrakeWPF/EventArgs/QueueProgressEventArgs.cs
new file mode 100644
index 000000000..3fa93fe7e
--- /dev/null
+++ b/win/CS/HandBrakeWPF/EventArgs/QueueProgressEventArgs.cs
@@ -0,0 +1,37 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="QueueProgressEventArgs.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Queue Progress Event Args
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.EventArgs
+{
+ using System;
+
+ using HandBrake.ApplicationServices.Model;
+
+ /// <summary>
+ /// Queue Progress Event Args
+ /// </summary>
+ public class QueueProgressEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueProgressEventArgs"/> class.
+ /// </summary>
+ /// <param name="newJob">
+ /// The new job.
+ /// </param>
+ public QueueProgressEventArgs(QueueTask newJob)
+ {
+ this.NewJob = newJob;
+ }
+
+ /// <summary>
+ /// Gets or sets the new job which is about to be processed.
+ /// </summary>
+ public QueueTask NewJob { get; set; }
+ }
+}
diff --git a/win/CS/HandBrakeWPF/EventArgs/SettingChangedEventArgs.cs b/win/CS/HandBrakeWPF/EventArgs/SettingChangedEventArgs.cs
new file mode 100644
index 000000000..edd27b11c
--- /dev/null
+++ b/win/CS/HandBrakeWPF/EventArgs/SettingChangedEventArgs.cs
@@ -0,0 +1,27 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="SettingChangedEventArgs.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// The setting changed event args.
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.EventArgs
+{
+ /// <summary>
+ /// The setting changed event args.
+ /// </summary>
+ public class SettingChangedEventArgs
+ {
+ /// <summary>
+ /// Gets or sets the key.
+ /// </summary>
+ public string Key { get; set; }
+
+ /// <summary>
+ /// Gets or sets the value.
+ /// </summary>
+ public object Value { get; set; }
+ }
+}
diff --git a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
index a5bde0f97..e44fd25d7 100644
--- a/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
+++ b/win/CS/HandBrakeWPF/HandBrakeWPF.csproj
@@ -140,12 +140,16 @@
<Compile Include="Converters\Subtitles\SubtitleBehaviourConverter.cs" />
<Compile Include="Converters\Video\VideoOptionsTooltipConverter.cs" />
<Compile Include="Converters\Video\ScalingConverter.cs" />
+ <Compile Include="EventArgs\QueueCompletedEventArgs.cs" />
+ <Compile Include="EventArgs\QueueProgressEventArgs.cs" />
+ <Compile Include="EventArgs\SettingChangedEventArgs.cs" />
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Model\Audio\AudioBehaviourModes.cs" />
<Compile Include="Model\Audio\AudioBehaviours.cs" />
<Compile Include="Model\Picture\PresetPictureSettingsMode.cs" />
<Compile Include="Model\Subtitles\SubtitleBehaviourModes.cs" />
<Compile Include="Model\Subtitles\SubtitleBehaviours.cs" />
+ <Compile Include="Services\Interfaces\IQueueProcessor.cs" />
<Compile Include="Services\Presets\Factories\PlistPresetFactory.cs" />
<Compile Include="Helpers\FileHelper.cs" />
<Compile Include="Services\Presets\Model\Preset.cs" />
@@ -155,6 +159,7 @@
<Compile Include="Services\Interfaces\IUserSettingService.cs" />
<Compile Include="Services\Presets\Model\PresetContainer.cs" />
<Compile Include="Services\Presets\PresetService.cs" />
+ <Compile Include="Services\QueueProcessor.cs" />
<Compile Include="Services\UserSettingService.cs" />
<Compile Include="Utilities\AppcastReader.cs" />
<Compile Include="Utilities\DelayedActionProcessor.cs" />
diff --git a/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs b/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs
index 53ab407e2..ceb8943b8 100644
--- a/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs
+++ b/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs
@@ -24,6 +24,8 @@ namespace HandBrakeWPF.Helpers
using HandBrakeWPF.Services.Interfaces;
+ using IQueueProcessor = HandBrakeWPF.Services.Interfaces.IQueueProcessor;
+
/// <summary>
/// Queue Recovery Helper
/// </summary>
diff --git a/win/CS/HandBrakeWPF/Services/Interfaces/IQueueProcessor.cs b/win/CS/HandBrakeWPF/Services/Interfaces/IQueueProcessor.cs
new file mode 100644
index 000000000..b04c825d9
--- /dev/null
+++ b/win/CS/HandBrakeWPF/Services/Interfaces/IQueueProcessor.cs
@@ -0,0 +1,184 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="IQueueProcessor.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// The Queue Processor
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services.Interfaces
+{
+ using System;
+ using System.ComponentModel;
+
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Services.Encode.Interfaces;
+
+ /// <summary>
+ /// The Queue Processor
+ /// </summary>
+ public interface IQueueProcessor
+ {
+ #region Events
+
+ /// <summary>
+ /// Fires when the Queue has started
+ /// </summary>
+ event QueueProcessor.QueueProgressStatus JobProcessingStarted;
+
+ /// <summary>
+ /// Fires when a job is Added, Removed or Re-Ordered.
+ /// Should be used for triggering an update of the Queue Window.
+ /// </summary>
+ event EventHandler QueueChanged;
+
+ /// <summary>
+ /// Fires when the entire encode queue has completed.
+ /// </summary>
+ event QueueProcessor.QueueCompletedEventDelegate QueueCompleted;
+
+ /// <summary>
+ /// Fires when a pause to the encode queue has been requested.
+ /// </summary>
+ event EventHandler QueuePaused;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets the number of jobs in the queue
+ /// </summary>
+ int Count { get; }
+
+ /// <summary>
+ /// Gets the IEncodeService instance.
+ /// </summary>
+ IEncode EncodeService { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether IsProcessing.
+ /// </summary>
+ bool IsProcessing { get; }
+
+ /// <summary>
+ /// Gets or sets Last Processed Job.
+ /// This is set when the job is poped of the queue by GetNextJobForProcessing();
+ /// </summary>
+ QueueTask LastProcessedJob { get; set; }
+
+ /// <summary>
+ /// Gets The current queue.
+ /// </summary>
+ BindingList<QueueTask> Queue { get; }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Add a job to the Queue.
+ /// This method is Thread Safe.
+ /// </summary>
+ /// <param name="job">
+ /// The encode Job object.
+ /// </param>
+ void Add(QueueTask job);
+
+ /// <summary>
+ /// Backup any changes to the queue file
+ /// </summary>
+ /// <param name="exportPath">
+ /// If this is not null or empty, this will be used instead of the standard backup location.
+ /// </param>
+ void BackupQueue(string exportPath);
+
+ /// <summary>
+ /// Checks the current queue for an existing instance of the specified destination.
+ /// </summary>
+ /// <param name="destination">
+ /// The destination of the encode.
+ /// </param>
+ /// <returns>
+ /// Whether or not the supplied destination is already in the queue.
+ /// </returns>
+ bool CheckForDestinationPathDuplicates(string destination);
+
+ /// <summary>
+ /// Clear down all Queue Items
+ /// </summary>
+ void Clear();
+
+ /// <summary>
+ /// Clear down the Queue�s completed items
+ /// </summary>
+ void ClearCompleted();
+
+ /// <summary>
+ /// Get the first job on the queue for processing.
+ /// This also removes the job from the Queue and sets the LastProcessedJob
+ /// </summary>
+ /// <returns>
+ /// An encode Job object.
+ /// </returns>
+ QueueTask GetNextJobForProcessing();
+
+ /// <summary>
+ /// Moves an item down one position in the queue.
+ /// </summary>
+ /// <param name="index">
+ /// The zero-based location of the job in the queue.
+ /// </param>
+ void MoveDown(int index);
+
+ /// <summary>
+ /// Moves an item up one position in the queue.
+ /// </summary>
+ /// <param name="index">
+ /// The zero-based location of the job in the queue.
+ /// </param>
+ void MoveUp(int index);
+
+ /// <summary>
+ /// Requests a pause of the encode queue.
+ /// </summary>
+ void Pause();
+
+ /// <summary>
+ /// Remove a job from the Queue.
+ /// This method is Thread Safe
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ void Remove(QueueTask job);
+
+ /// <summary>
+ /// Reset a Queued Item from Error or Completed to Waiting
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ void ResetJobStatusToWaiting(QueueTask job);
+
+ /// <summary>
+ /// Restore a Queue from file or from the queue backup file.
+ /// </summary>
+ /// <param name="importPath">
+ /// The import path. String.Empty or null will result in the default file being loaded.
+ /// </param>
+ void RestoreQueue(string importPath);
+
+ /// <summary>
+ /// Starts encoding the first job in the queue and continues encoding until all jobs
+ /// have been encoded.
+ /// </summary>
+ /// <param name="clearCompleted">
+ /// The clear Completed.
+ /// </param>
+ void Start(bool clearCompleted);
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrakeWPF/Services/Interfaces/IUserSettingService.cs b/win/CS/HandBrakeWPF/Services/Interfaces/IUserSettingService.cs
index d2f433bc1..c8b34b7cd 100644
--- a/win/CS/HandBrakeWPF/Services/Interfaces/IUserSettingService.cs
+++ b/win/CS/HandBrakeWPF/Services/Interfaces/IUserSettingService.cs
@@ -9,7 +9,7 @@
namespace HandBrakeWPF.Services.Interfaces
{
- using HandBrake.ApplicationServices.EventArgs;
+ using SettingChangedEventArgs = HandBrakeWPF.EventArgs.SettingChangedEventArgs;
/// <summary>
/// The setting event handler.
diff --git a/win/CS/HandBrakeWPF/Services/NotificationService.cs b/win/CS/HandBrakeWPF/Services/NotificationService.cs
index 1a647a970..0f387fec3 100644
--- a/win/CS/HandBrakeWPF/Services/NotificationService.cs
+++ b/win/CS/HandBrakeWPF/Services/NotificationService.cs
@@ -15,6 +15,8 @@ namespace HandBrakeWPF.Services
using HandBrakeWPF.Services.Interfaces;
+ using IQueueProcessor = HandBrakeWPF.Services.Interfaces.IQueueProcessor;
+
/// <summary>
/// The Notification Service (Growl Connector)
/// </summary>
diff --git a/win/CS/HandBrakeWPF/Services/PrePostActionService.cs b/win/CS/HandBrakeWPF/Services/PrePostActionService.cs
index c57935239..b8501b999 100644
--- a/win/CS/HandBrakeWPF/Services/PrePostActionService.cs
+++ b/win/CS/HandBrakeWPF/Services/PrePostActionService.cs
@@ -9,21 +9,19 @@
namespace HandBrakeWPF.Services
{
+ using System;
using System.Diagnostics;
using System.Windows.Forms;
using Caliburn.Micro;
- using HandBrake.ApplicationServices.EventArgs;
using HandBrake.ApplicationServices.Services.Encode.EventArgs;
- using HandBrake.ApplicationServices.Services.Interfaces;
using HandBrake.ApplicationServices.Utilities;
+ using HandBrakeWPF.EventArgs;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
- using Application = System.Windows.Application;
-
/// <summary>
/// The when done service.
/// </summary>
@@ -76,7 +74,7 @@ namespace HandBrakeWPF.Services
/// <param name="e">
/// The e.
/// </param>
- private void EncodeService_EncodeStarted(object sender, System.EventArgs e)
+ private void EncodeService_EncodeStarted(object sender, EventArgs e)
{
if (this.userSettingService.GetUserSetting<bool>(UserSettingConstants.PreventSleep))
{
@@ -134,7 +132,7 @@ namespace HandBrakeWPF.Services
// Give the user the ability to cancel the shutdown. Default 60 second timer.
ICountdownAlertViewModel titleSpecificView = IoC.Get<ICountdownAlertViewModel>();
- Caliburn.Micro.Execute.OnUIThread(
+ Execute.OnUIThread(
() =>
{
titleSpecificView.SetAction(this.userSettingService.GetUserSetting<string>(UserSettingConstants.WhenCompleteAction));
@@ -153,16 +151,16 @@ namespace HandBrakeWPF.Services
Win32.ExitWindowsEx(0, 0);
break;
case "Suspend":
- System.Windows.Forms.Application.SetSuspendState(PowerState.Suspend, true, true);
+ Application.SetSuspendState(PowerState.Suspend, true, true);
break;
case "Hibernate":
- System.Windows.Forms.Application.SetSuspendState(PowerState.Hibernate, true, true);
+ Application.SetSuspendState(PowerState.Hibernate, true, true);
break;
case "Lock System":
Win32.LockWorkStation();
break;
case "Quit HandBrake":
- Execute.OnUIThread(() => Application.Current.Shutdown());
+ Execute.OnUIThread(() => System.Windows.Application.Current.Shutdown());
break;
}
}
@@ -180,8 +178,8 @@ namespace HandBrakeWPF.Services
!string.IsNullOrEmpty(this.userSettingService.GetUserSetting<string>(UserSettingConstants.SendFileTo)))
{
string args = string.Format(
- "{0} \"{1}\"",
- this.userSettingService.GetUserSetting<string>(UserSettingConstants.SendFileToArgs),
+ "{0} \"{1}\"",
+ this.userSettingService.GetUserSetting<string>(UserSettingConstants.SendFileToArgs),
file);
var vlc =
new ProcessStartInfo(
diff --git a/win/CS/HandBrakeWPF/Services/QueueProcessor.cs b/win/CS/HandBrakeWPF/Services/QueueProcessor.cs
new file mode 100644
index 000000000..414113d2f
--- /dev/null
+++ b/win/CS/HandBrakeWPF/Services/QueueProcessor.cs
@@ -0,0 +1,604 @@
+// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="QueueProcessor.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// The HandBrake Queue
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrakeWPF.Services
+{
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.IO;
+ using System.Linq;
+ using System.Xml.Serialization;
+
+ using Caliburn.Micro;
+
+ using HandBrake.ApplicationServices.Exceptions;
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Services.Encode.EventArgs;
+ using HandBrake.ApplicationServices.Services.Encode.Interfaces;
+ using HandBrake.ApplicationServices.Utilities;
+
+ using IQueueProcessor = HandBrakeWPF.Services.Interfaces.IQueueProcessor;
+ using QueueCompletedEventArgs = HandBrakeWPF.EventArgs.QueueCompletedEventArgs;
+ using QueueProgressEventArgs = HandBrakeWPF.EventArgs.QueueProgressEventArgs;
+
+ /// <summary>
+ /// The HandBrake Queue
+ /// </summary>
+ public class QueueProcessor : IQueueProcessor
+ {
+ #region Constants and Fields
+
+ /// <summary>
+ /// A Lock object to maintain thread safety
+ /// </summary>
+ private static readonly object QueueLock = new object();
+
+ /// <summary>
+ /// The Queue of Job objects
+ /// </summary>
+ private readonly BindingList<QueueTask> queue = new BindingList<QueueTask>();
+
+ /// <summary>
+ /// HandBrakes Queue file with a place holder for an extra string.
+ /// </summary>
+ private readonly string queueFile;
+
+ /// <summary>
+ /// The clear completed.
+ /// </summary>
+ private bool clearCompleted;
+
+ #endregion
+
+ #region Constructors and Destructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueueProcessor"/> class.
+ /// </summary>
+ /// <param name="encodeService">
+ /// The encode Service.
+ /// </param>
+ /// <exception cref="ArgumentNullException">
+ /// Services are not setup
+ /// </exception>
+ public QueueProcessor(IEncode encodeService)
+ {
+ this.EncodeService = encodeService;
+
+ // If this is the first instance, just use the main queue file, otherwise add the instance id to the filename.
+ this.queueFile = string.Format("hb_queue_recovery{0}.xml", GeneralUtilities.ProcessId);
+ }
+
+ #endregion
+
+ #region Delegates
+
+ /// <summary>
+ /// Queue Progess Status
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The QueueProgressEventArgs.
+ /// </param>
+ public delegate void QueueProgressStatus(object sender, QueueProgressEventArgs e);
+
+ /// <summary>
+ /// The queue completed.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ public delegate void QueueCompletedEventDelegate(object sender, QueueCompletedEventArgs e);
+
+ #endregion
+
+ #region Events
+
+ /// <summary>
+ /// Fires when the Queue has started
+ /// </summary>
+ public event QueueProgressStatus JobProcessingStarted;
+
+ /// <summary>
+ /// Fires when a job is Added, Removed or Re-Ordered.
+ /// Should be used for triggering an update of the Queue Window.
+ /// </summary>
+ public event EventHandler QueueChanged;
+
+ /// <summary>
+ /// Fires when the entire encode queue has completed.
+ /// </summary>
+ public event QueueCompletedEventDelegate QueueCompleted;
+
+ /// <summary>
+ /// Fires when a pause to the encode queue has been requested.
+ /// </summary>
+ public event EventHandler QueuePaused;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets the number of jobs in the queue;
+ /// </summary>
+ public int Count
+ {
+ get
+ {
+ return this.queue.Count(item => item.Status == QueueItemStatus.Waiting);
+ }
+ }
+
+ /// <summary>
+ /// Gets the IEncodeService instance.
+ /// </summary>
+ public IEncode EncodeService { get; private set; }
+
+ /// <summary>
+ /// Gets a value indicating whether IsProcessing.
+ /// </summary>
+ public bool IsProcessing { get; private set; }
+
+ /// <summary>
+ /// Gets or sets Last Processed Job.
+ /// This is set when the job is poped of the queue by GetNextJobForProcessing();
+ /// </summary>
+ public QueueTask LastProcessedJob { get; set; }
+
+ /// <summary>
+ /// Gets The current queue.
+ /// </summary>
+ public BindingList<QueueTask> Queue
+ {
+ get
+ {
+ return this.queue;
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// Add a job to the Queue.
+ /// This method is Thread Safe.
+ /// </summary>
+ /// <param name="job">
+ /// The encode Job object.
+ /// </param>
+ public void Add(QueueTask job)
+ {
+ lock (QueueLock)
+ {
+ this.queue.Add(job);
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Backup any changes to the queue file
+ /// </summary>
+ /// <param name="exportPath">
+ /// If this is not null or empty, this will be used instead of the standard backup location.
+ /// </param>
+ public void BackupQueue(string exportPath)
+ {
+ string appDataPath = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
+ string tempPath = !string.IsNullOrEmpty(exportPath)
+ ? exportPath
+ : appDataPath + string.Format(this.queueFile, string.Empty);
+
+ using (var strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
+ {
+ List<QueueTask> tasks = this.queue.Where(item => item.Status != QueueItemStatus.Completed).ToList();
+ var serializer = new XmlSerializer(typeof(List<QueueTask>));
+ serializer.Serialize(strm, tasks);
+ strm.Close();
+ strm.Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Checks the current queue for an existing instance of the specified destination.
+ /// </summary>
+ /// <param name="destination">
+ /// The destination of the encode.
+ /// </param>
+ /// <returns>
+ /// Whether or not the supplied destination is already in the queue.
+ /// </returns>
+ public bool CheckForDestinationPathDuplicates(string destination)
+ {
+ return this.queue.Any(job => job.Task != null && job.Status == QueueItemStatus.Waiting && job.Task.Destination != null && job.Task.Destination.Contains(destination.Replace("\\\\", "\\")));
+ }
+
+ /// <summary>
+ /// Clear down all Queue Items
+ /// </summary>
+ public void Clear()
+ {
+ List<QueueTask> deleteList = this.queue.ToList();
+ foreach (QueueTask item in deleteList)
+ {
+ this.queue.Remove(item);
+ }
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Clear down the Queue´s completed items
+ /// </summary>
+ public void ClearCompleted()
+ {
+ Execute.OnUIThread(
+ () =>
+ {
+ List<QueueTask> deleteList =
+ this.queue.Where(task => task.Status == QueueItemStatus.Completed).ToList();
+ foreach (QueueTask item in deleteList)
+ {
+ this.queue.Remove(item);
+ }
+ this.InvokeQueueChanged(EventArgs.Empty);
+ });
+ }
+
+ /// <summary>
+ /// Get the first job on the queue for processing.
+ /// This also removes the job from the Queue and sets the LastProcessedJob
+ /// </summary>
+ /// <returns>
+ /// An encode Job object.
+ /// </returns>
+ public QueueTask GetNextJobForProcessing()
+ {
+ if (this.queue.Count > 0)
+ {
+ QueueTask job = this.queue.FirstOrDefault(q => q.Status == QueueItemStatus.Waiting);
+ if (job != null)
+ {
+ job.Status = QueueItemStatus.InProgress;
+ this.LastProcessedJob = job;
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+
+ this.BackupQueue(string.Empty);
+ return job;
+ }
+
+ this.BackupQueue(string.Empty);
+ return null;
+ }
+
+ /// <summary>
+ /// Moves an item down one position in the queue.
+ /// </summary>
+ /// <param name="index">
+ /// The zero-based location of the job in the queue.
+ /// </param>
+ public void MoveDown(int index)
+ {
+ if (index < this.queue.Count - 1)
+ {
+ QueueTask item = this.queue[index];
+
+ this.queue.RemoveAt(index);
+ this.queue.Insert((index + 1), item);
+ }
+
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Moves an item up one position in the queue.
+ /// </summary>
+ /// <param name="index">
+ /// The zero-based location of the job in the queue.
+ /// </param>
+ public void MoveUp(int index)
+ {
+ if (index > 0)
+ {
+ QueueTask item = this.queue[index];
+
+ this.queue.RemoveAt(index);
+ this.queue.Insert((index - 1), item);
+ }
+
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+
+ /// <summary>
+ /// Remove a job from the Queue.
+ /// This method is Thread Safe
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ public void Remove(QueueTask job)
+ {
+ lock (QueueLock)
+ {
+ this.queue.Remove(job);
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Reset a Queued Item from Error or Completed to Waiting
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ public void ResetJobStatusToWaiting(QueueTask job)
+ {
+ if (job.Status != QueueItemStatus.Error && job.Status != QueueItemStatus.Completed)
+ {
+ throw new GeneralApplicationException(
+ "Job Error", "Unable to reset job status as it is not in an Error or Completed state", null);
+ }
+
+ job.Status = QueueItemStatus.Waiting;
+ }
+
+ /// <summary>
+ /// Restore a Queue from file or from the queue backup file.
+ /// </summary>
+ /// <param name="importPath">
+ /// The import path. String.Empty or null will result in the default file being loaded.
+ /// </param>
+ public void RestoreQueue(string importPath)
+ {
+ string appDataPath = Path.Combine(
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");
+ string tempPath = !string.IsNullOrEmpty(importPath)
+ ? importPath
+ : (appDataPath + string.Format(this.queueFile, string.Empty));
+
+ if (File.Exists(tempPath))
+ {
+ bool invokeUpdate = false;
+ using (
+ var strm = new FileStream(
+ (!string.IsNullOrEmpty(importPath) ? importPath : tempPath), FileMode.Open, FileAccess.Read))
+ {
+ if (strm.Length != 0)
+ {
+ var serializer = new XmlSerializer(typeof(List<QueueTask>));
+
+ List<QueueTask> list;
+
+ try
+ {
+ list = serializer.Deserialize(strm) as List<QueueTask>;
+ }
+ catch (Exception exc)
+ {
+ throw new GeneralApplicationException(
+ "Unable to restore queue file.",
+ "The file may be corrupted or from an older incompatible version of HandBrake",
+ exc);
+ }
+
+ if (list != null)
+ {
+ foreach (QueueTask item in list)
+ {
+ if (item.Status != QueueItemStatus.Completed)
+ {
+ // Reset InProgress/Error to Waiting so it can be processed
+ if (item.Status == QueueItemStatus.InProgress)
+ {
+ item.Status = QueueItemStatus.Waiting;
+ }
+
+ this.queue.Add(item);
+ }
+ }
+ }
+
+ invokeUpdate = true;
+ }
+ }
+
+ if (invokeUpdate)
+ {
+ this.InvokeQueueChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Requests a pause of the encode queue.
+ /// </summary>
+ public void Pause()
+ {
+ this.InvokeQueuePaused(EventArgs.Empty);
+ this.IsProcessing = false;
+ }
+
+ /// <summary>
+ /// Starts encoding the first job in the queue and continues encoding until all jobs
+ /// have been encoded.
+ /// </summary>
+ /// <param name="isClearCompleted">
+ /// The is Clear Completed.
+ /// </param>
+ public void Start(bool isClearCompleted)
+ {
+ if (this.IsProcessing)
+ {
+ throw new Exception("Already Processing the Queue");
+ }
+
+ this.clearCompleted = isClearCompleted;
+
+ this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;
+ this.EncodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted;
+
+ if (this.EncodeService.CanPause && this.EncodeService.IsEncoding)
+ {
+ this.EncodeService.Resume();
+ }
+
+ if (!this.EncodeService.IsEncoding)
+ {
+ this.ProcessNextJob();
+ }
+
+ this.IsProcessing = true;
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// After an encode is complete, move onto the next job.
+ /// </summary>
+ /// <param name="sender">
+ /// The sender.
+ /// </param>
+ /// <param name="e">
+ /// The EncodeCompletedEventArgs.
+ /// </param>
+ private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e)
+ {
+ this.LastProcessedJob.Status = QueueItemStatus.Completed;
+
+ // Clear the completed item of the queue if the setting is set.
+ if (this.clearCompleted)
+ {
+ this.ClearCompleted();
+ }
+
+ if (!e.Successful)
+ {
+ this.LastProcessedJob.Status = QueueItemStatus.Error;
+ }
+
+ // Move onto the next job.
+ if (this.IsProcessing)
+ {
+ this.ProcessNextJob();
+ }
+ else
+ {
+ this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;
+ this.OnQueueCompleted(new QueueCompletedEventArgs(true));
+ this.BackupQueue(string.Empty);
+ }
+ }
+
+ /// <summary>
+ /// Invoke the JobProcessingStarted event
+ /// </summary>
+ /// <param name="e">
+ /// The QueueProgressEventArgs.
+ /// </param>
+ private void InvokeJobProcessingStarted(QueueProgressEventArgs e)
+ {
+ QueueProgressStatus handler = this.JobProcessingStarted;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ /// <summary>
+ /// Invoke the Queue Changed Event
+ /// </summary>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ private void InvokeQueueChanged(EventArgs e)
+ {
+ try
+ {
+ this.BackupQueue(string.Empty);
+ }
+ catch (Exception)
+ {
+ // Do Nothing.
+ }
+
+ EventHandler handler = this.QueueChanged;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ /// <summary>
+ /// Invoke the QueuePaused event
+ /// </summary>
+ /// <param name="e">
+ /// The EventArgs.
+ /// </param>
+ private void InvokeQueuePaused(EventArgs e)
+ {
+ this.IsProcessing = false;
+
+ EventHandler handler = this.QueuePaused;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+ }
+
+ /// <summary>
+ /// The on queue completed.
+ /// </summary>
+ /// <param name="e">
+ /// The e.
+ /// </param>
+ protected virtual void OnQueueCompleted(QueueCompletedEventArgs e)
+ {
+ QueueCompletedEventDelegate handler = this.QueueCompleted;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
+
+ this.IsProcessing = false;
+ }
+
+ /// <summary>
+ /// Run through all the jobs on the queue.
+ /// </summary>
+ private void ProcessNextJob()
+ {
+ QueueTask job = this.GetNextJobForProcessing();
+ if (job != null)
+ {
+ this.InvokeJobProcessingStarted(new QueueProgressEventArgs(job));
+ this.EncodeService.Start(job);
+ }
+ else
+ {
+ // No more jobs to process, so unsubscribe the event
+ this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted;
+
+ // Fire the event to tell connected services.
+ this.OnQueueCompleted(new QueueCompletedEventArgs(false));
+ }
+ }
+
+ #endregion
+ }
+} \ No newline at end of file
diff --git a/win/CS/HandBrakeWPF/Services/UserSettingService.cs b/win/CS/HandBrakeWPF/Services/UserSettingService.cs
index 6b7d87f1b..6c5c6629b 100644
--- a/win/CS/HandBrakeWPF/Services/UserSettingService.cs
+++ b/win/CS/HandBrakeWPF/Services/UserSettingService.cs
@@ -16,11 +16,12 @@ namespace HandBrakeWPF.Services
using System.Reflection;
using System.Xml.Serialization;
- using HandBrake.ApplicationServices.EventArgs;
using HandBrake.ApplicationServices.Exceptions;
using HandBrakeWPF.Services.Interfaces;
+ using SettingChangedEventArgs = HandBrakeWPF.EventArgs.SettingChangedEventArgs;
+
/// <summary>
/// The User Setting Serivce
/// </summary>
diff --git a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs
index c8b327cd3..617413bc8 100644
--- a/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs
+++ b/win/CS/HandBrakeWPF/Startup/CastleBootstrapper.cs
@@ -56,8 +56,8 @@ namespace HandBrakeWPF.Startup
this.windsorContainer.Register(Component.For<IEventAggregator>().ImplementedBy<EventAggregator>());
// Initialise the ApplicationServices IWindsorInstaller
- this.windsorContainer.Register(Component.For<IWindsorInstaller>().ImplementedBy<ServicesWindsorInstaller>());
- this.windsorContainer.Install(windsorContainer.ResolveAll<IWindsorInstaller>());
+ // this.windsorContainer.Register(Component.For<IWindsorInstaller>().ImplementedBy<ServicesWindsorInstaller>());
+ // this.windsorContainer.Install(windsorContainer.ResolveAll<IWindsorInstaller>());
// Services
this.windsorContainer.Register(Component.For<IUpdateService>().ImplementedBy<UpdateService>().LifeStyle.Is(LifestyleType.Singleton));
@@ -67,6 +67,7 @@ namespace HandBrakeWPF.Startup
this.windsorContainer.Register(Component.For<IPrePostActionService>().ImplementedBy<PrePostActionService>().LifeStyle.Is(LifestyleType.Singleton));
this.windsorContainer.Register(Component.For<IUserSettingService>().ImplementedBy<UserSettingService>());
this.windsorContainer.Register(Component.For<IPresetService>().ImplementedBy<PresetService>());
+ this.windsorContainer.Register(Component.For<IQueueProcessor>().ImplementedBy<QueueProcessor>());
// Commands
this.windsorContainer.Register(Component.For<IAdvancedEncoderOptionsCommand>().ImplementedBy<AdvancedEncoderOptionsCommand>().LifeStyle.Is(LifestyleType.Singleton));
diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs
index f204b084d..08662882c 100644
--- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs
+++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs
@@ -34,6 +34,7 @@ namespace HandBrakeWPF.ViewModels
using HandBrake.ApplicationServices.Interop;
using HandBrakeWPF.Commands;
+ using HandBrakeWPF.EventArgs;
using HandBrakeWPF.Factories;
using HandBrakeWPF.Helpers;
using HandBrakeWPF.Model;
@@ -52,6 +53,8 @@ namespace HandBrakeWPF.ViewModels
using Ookii.Dialogs.Wpf;
+ using IQueueProcessor = HandBrakeWPF.Services.Interfaces.IQueueProcessor;
+
/// <summary>
/// HandBrakes Main Window
/// </summary>
@@ -2104,7 +2107,7 @@ namespace HandBrakeWPF.ViewModels
/// <param name="e">
/// The e.
/// </param>
- void QueueProcessorJobProcessingStarted(object sender, HandBrake.ApplicationServices.EventArgs.QueueProgressEventArgs e)
+ void QueueProcessorJobProcessingStarted(object sender, QueueProgressEventArgs e)
{
Execute.OnUIThread(
() =>
@@ -2194,7 +2197,7 @@ namespace HandBrakeWPF.ViewModels
/// <param name="e">
/// The e.
/// </param>
- private void UserSettingServiceSettingChanged(object sender, HandBrake.ApplicationServices.EventArgs.SettingChangedEventArgs e)
+ private void UserSettingServiceSettingChanged(object sender, SettingChangedEventArgs e)
{
if (e.Key == UserSettingConstants.ShowAdvancedTab)
{
diff --git a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs
index 7f5ba9b00..7191ad9b5 100644
--- a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs
+++ b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs
@@ -15,12 +15,11 @@ namespace HandBrakeWPF.ViewModels
using Caliburn.Micro;
- using HandBrake.ApplicationServices.EventArgs;
using HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Services.Encode.EventArgs;
using HandBrake.ApplicationServices.Services.Encode.Model;
- using HandBrake.ApplicationServices.Services.Interfaces;
+ using HandBrakeWPF.EventArgs;
using HandBrakeWPF.Properties;
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
@@ -245,7 +244,7 @@ namespace HandBrakeWPF.ViewModels
this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count);
this.IsEncoding = false;
- MessageBox.Show("The Queue has been paused. The currently running job will run to completion and no further jobs will start.", "Queue",
+ MessageBox.Show("The Queue has been paused. The currently running job will run to completion and no further jobs will start.", "Queue",
MessageBoxButton.OK, MessageBoxImage.Information);
}
@@ -261,9 +260,9 @@ namespace HandBrakeWPF.ViewModels
{
MessageBoxResult result =
this.errorService.ShowMessageBox(
- "This encode is currently in progress. If you delete it, the encode will be stopped. Are you sure you wish to proceed?",
- Resources.Warning,
- MessageBoxButton.YesNo,
+ "This encode is currently in progress. If you delete it, the encode will be stopped. Are you sure you wish to proceed?",
+ Resources.Warning,
+ MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
@@ -317,9 +316,9 @@ namespace HandBrakeWPF.ViewModels
{
SaveFileDialog dialog = new SaveFileDialog
{
- Filter = "HandBrake Queue Files (*.hbq)|*.hbq",
- OverwritePrompt = true,
- DefaultExt = ".hbq",
+ Filter = "HandBrake Queue Files (*.hbq)|*.hbq",
+ OverwritePrompt = true,
+ DefaultExt = ".hbq",
AddExtension = true
};
if (dialog.ShowDialog() == true)
@@ -349,9 +348,9 @@ namespace HandBrakeWPF.ViewModels
public void EditJob(QueueTask task)
{
MessageBoxResult result = this.errorService.ShowMessageBox(
- "Are you sure you wish to edit this job? It will be removed from the queue and sent to the main window.",
- "Modify Job?",
- MessageBoxButton.YesNo,
+ "Are you sure you wish to edit this job? It will be removed from the queue and sent to the main window.",
+ "Modify Job?",
+ MessageBoxButton.YesNo,
MessageBoxImage.Question);
if (result != MessageBoxResult.Yes)
@@ -420,17 +419,17 @@ namespace HandBrakeWPF.ViewModels
/// </param>
private void EncodeService_EncodeStatusChanged(object sender, EncodeProgressEventArgs e)
{
- Caliburn.Micro.Execute.OnUIThread(() =>
+ Execute.OnUIThread(() =>
{
this.JobStatus =
string.Format(
- "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}",
- e.Task,
- e.TaskCount,
- e.PercentComplete,
- e.CurrentFrameRate,
- e.AverageFrameRate,
- e.EstimatedTimeLeft,
+ "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}",
+ e.Task,
+ e.TaskCount,
+ e.PercentComplete,
+ e.CurrentFrameRate,
+ e.AverageFrameRate,
+ e.EstimatedTimeLeft,
e.ElapsedTime);
});
}
diff --git a/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs
index e297db422..6d4fcc84a 100644
--- a/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs
+++ b/win/CS/HandBrakeWPF/ViewModels/ShellViewModel.cs
@@ -20,6 +20,8 @@ namespace HandBrakeWPF.ViewModels
using HandBrakeWPF.Services.Interfaces;
using HandBrakeWPF.ViewModels.Interfaces;
+ using IQueueProcessor = HandBrakeWPF.Services.Interfaces.IQueueProcessor;
+
/// <summary>
/// The Shell View Model
/// </summary>
diff --git a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs
index a975a8bcd..5f1193cc7 100644
--- a/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs
+++ b/win/CS/HandBrakeWPF/ViewModels/VideoViewModel.cs
@@ -17,7 +17,6 @@ namespace HandBrakeWPF.ViewModels
using Caliburn.Micro;
- using HandBrake.ApplicationServices.EventArgs;
using HandBrake.ApplicationServices.Services.Encode.Model;
using HandBrake.ApplicationServices.Services.Encode.Model.Models;
using HandBrake.ApplicationServices.Services.Encode.Model.Models.Video;
@@ -33,6 +32,7 @@ namespace HandBrakeWPF.ViewModels
using HandBrakeWPF.ViewModels.Interfaces;
using Clipboard = System.Windows.Clipboard;
+ using SettingChangedEventArgs = HandBrakeWPF.EventArgs.SettingChangedEventArgs;
/// <summary>
/// The Video View Model