From 2a18d05b52ea084b4bb968f3622872a8a08d83fa Mon Sep 17 00:00:00 2001 From: sr55 Date: Sat, 13 Oct 2012 17:52:14 +0000 Subject: WinGui: API Tidyup Part 3 of many. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5015 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- .../HandBrake.ApplicationServices.csproj | 2 - .../Services/Interfaces/IQueueManager.cs | 149 ------ .../Services/Interfaces/IQueueProcessor.cs | 144 +++++- .../Services/QueueManager.cs | 430 ---------------- .../Services/QueueProcessor.cs | 555 +++++++++++++++++---- .../ServicesWindsorInstaller.cs | 3 - win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs | 2 +- win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs | 14 +- win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs | 34 +- win/CS/HandBrakeWPF/Views/MainView.xaml | 1 - 10 files changed, 601 insertions(+), 733 deletions(-) delete mode 100644 win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs delete mode 100644 win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs (limited to 'win/CS') diff --git a/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj b/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj index 7039a22e3..af024c7e8 100644 --- a/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj +++ b/win/CS/HandBrake.ApplicationServices/HandBrake.ApplicationServices.csproj @@ -133,7 +133,6 @@ - @@ -141,7 +140,6 @@ - diff --git a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs deleted file mode 100644 index b52be1aef..000000000 --- a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueManager.cs +++ /dev/null @@ -1,149 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. -// -// -// The Queue Manager Interface -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrake.ApplicationServices.Services.Interfaces -{ - using System; - using System.Collections.ObjectModel; - - using HandBrake.ApplicationServices.Model; - - /// - /// The Queue Manager Interface - /// - public interface IQueueManager - { - /// - /// Fires when a job is Added, Removed or Re-Ordered. - /// Should be used for triggering an update of the Queue Window. - /// - event EventHandler QueueChanged; - - /// - /// Gets or sets Last Processed Job. - /// This is set when the job is poped of the queue by GetNextJobForProcessing(); - /// - QueueTask LastProcessedJob { get; set; } - - /// - /// Gets The current queue. - /// - ObservableCollection Queue { get; } - - /// - /// Gets the number of jobs in the queue - /// - int Count { get; } - - /// - /// Add a job to the Queue. - /// This method is Thread Safe. - /// - /// - /// The encode Job object. - /// - void Add(QueueTask job); - - /// - /// Remove a job from the Queue. - /// This method is Thread Safe - /// - /// - /// The job. - /// - void Remove(QueueTask job); - - /// - /// Reset a Queued Item from Error or Completed to Waiting - /// - /// - /// The job. - /// - void ResetJobStatusToWaiting(QueueTask job); - - /// - /// Clear down the Queue´s completed items - /// - void ClearCompleted(); - - /// - /// Clear down all Queue Items - /// - void Clear(); - - /// - /// Get the first job on the queue for processing. - /// This also removes the job from the Queue and sets the LastProcessedJob - /// - /// - /// An encode Job object. - /// - QueueTask GetNextJobForProcessing(); - - /// - /// Moves an item up one position in the queue. - /// - /// The zero-based location of the job in the queue. - void MoveUp(int index); - - /// - /// Moves an item down one position in the queue. - /// - /// The zero-based location of the job in the queue. - void MoveDown(int index); - - /// - /// Backup any changes to the queue file - /// - /// - /// If this is not null or empty, this will be used instead of the standard backup location. - /// - void BackupQueue(string exportPath); - - /// - /// Restore a Queue from file or from the queue backup file. - /// - /// - /// The import path. String.Empty or null will result in the default file being loaded. - /// - void RestoreQueue(string importPath); - - /// - /// Checks the current queue for an existing instance of the specified destination. - /// - /// The destination of the encode. - /// Whether or not the supplied destination is already in the queue. - bool CheckForDestinationPathDuplicates(string destination); - - /// - /// Create a batch script from the queue - /// - /// - /// The path to the location for the script to be saved. - /// - /// - /// The preview Scan Count. - /// - /// - /// The verbosity. - /// - /// - /// The disable Libdvdnav. - /// - /// - /// True if sucessful - /// - bool WriteBatchScriptToFile(string path, int previewScanCount, int verbosity, bool disableLibdvdnav); - - /// - /// Temp workaround until this can be fixed properly. - /// - void ResetInstanceId(); - } -} \ No newline at end of file diff --git a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs index dd5746387..c9285ebfe 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/Interfaces/IQueueProcessor.cs @@ -10,21 +10,27 @@ namespace HandBrake.ApplicationServices.Services.Interfaces { using System; + using System.Collections.ObjectModel; + + using HandBrake.ApplicationServices.Model; /// /// The Queue Processor /// public interface IQueueProcessor { + #region Events + /// /// Fires when the Queue has started /// event QueueProcessor.QueueProgressStatus JobProcessingStarted; /// - /// Fires when a pause to the encode queue has been requested. + /// Fires when a job is Added, Removed or Re-Ordered. + /// Should be used for triggering an update of the Queue Window. /// - event EventHandler QueuePaused; + event EventHandler QueueChanged; /// /// Fires when the entire encode queue has completed. @@ -32,14 +38,23 @@ namespace HandBrake.ApplicationServices.Services.Interfaces event EventHandler QueueCompleted; /// - /// Gets the IEncodeService instance. + /// Fires when a pause to the encode queue has been requested. /// - IEncodeServiceWrapper EncodeService { get; } + event EventHandler QueuePaused; + + #endregion + + #region Properties /// - /// Gets the IQueueManager instance. + /// Gets the number of jobs in the queue /// - IQueueManager QueueManager { get; } + int Count { get; } + + /// + /// Gets the IEncodeService instance. + /// + IEncodeServiceWrapper EncodeService { get; } /// /// Gets a value indicating whether IsProcessing. @@ -47,10 +62,82 @@ namespace HandBrake.ApplicationServices.Services.Interfaces bool IsProcessing { get; } /// - /// Starts encoding the first job in the queue and continues encoding until all jobs - /// have been encoded. + /// Gets or sets Last Processed Job. + /// This is set when the job is poped of the queue by GetNextJobForProcessing(); /// - void Start(); + QueueTask LastProcessedJob { get; set; } + + /// + /// Gets The current queue. + /// + ObservableCollection Queue { get; } + + #endregion + + #region Public Methods + + /// + /// Add a job to the Queue. + /// This method is Thread Safe. + /// + /// + /// The encode Job object. + /// + void Add(QueueTask job); + + /// + /// Backup any changes to the queue file + /// + /// + /// If this is not null or empty, this will be used instead of the standard backup location. + /// + void BackupQueue(string exportPath); + + /// + /// Checks the current queue for an existing instance of the specified destination. + /// + /// + /// The destination of the encode. + /// + /// + /// Whether or not the supplied destination is already in the queue. + /// + bool CheckForDestinationPathDuplicates(string destination); + + /// + /// Clear down all Queue Items + /// + void Clear(); + + /// + /// Clear down the Queue´s completed items + /// + void ClearCompleted(); + + /// + /// Get the first job on the queue for processing. + /// This also removes the job from the Queue and sets the LastProcessedJob + /// + /// + /// An encode Job object. + /// + QueueTask GetNextJobForProcessing(); + + /// + /// Moves an item down one position in the queue. + /// + /// + /// The zero-based location of the job in the queue. + /// + void MoveDown(int index); + + /// + /// Moves an item up one position in the queue. + /// + /// + /// The zero-based location of the job in the queue. + /// + void MoveUp(int index); /// /// Requests a pause of the encode queue. @@ -58,12 +145,41 @@ namespace HandBrake.ApplicationServices.Services.Interfaces void Pause(); /// - /// Swap encode service. - /// Temp method until Castle is hooked up. + /// Remove a job from the Queue. + /// This method is Thread Safe /// - /// - /// The service. + /// + /// The job. /// - void SwapEncodeService(IEncodeServiceWrapper service); + void Remove(QueueTask job); + + /// + /// Temp workaround until this can be fixed properly. + /// + void ResetInstanceId(); + + /// + /// Reset a Queued Item from Error or Completed to Waiting + /// + /// + /// The job. + /// + void ResetJobStatusToWaiting(QueueTask job); + + /// + /// Restore a Queue from file or from the queue backup file. + /// + /// + /// The import path. String.Empty or null will result in the default file being loaded. + /// + void RestoreQueue(string importPath); + + /// + /// Starts encoding the first job in the queue and continues encoding until all jobs + /// have been encoded. + /// + void Start(); + + #endregion } } \ No newline at end of file diff --git a/win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs b/win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs deleted file mode 100644 index 161653da0..000000000 --- a/win/CS/HandBrake.ApplicationServices/Services/QueueManager.cs +++ /dev/null @@ -1,430 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// -// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. -// -// -// The Queue Manager. -// Thread Safe. -// -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrake.ApplicationServices.Services -{ - using System; - using System.Collections.Generic; - using System.Collections.ObjectModel; - using System.IO; - using System.Linq; - using System.Windows.Forms; - using System.Xml.Serialization; - - using Caliburn.Micro; - - using HandBrake.ApplicationServices.Exceptions; - using HandBrake.ApplicationServices.Model; - using HandBrake.ApplicationServices.Services.Interfaces; - using HandBrake.ApplicationServices.Utilities; - - using EventArgs = System.EventArgs; - - /// - /// The Queue Manager. - /// Thread Safe. - /// - public class QueueManager : IQueueManager - { - /* - * TODO - * - Rewrite the batch script generator. - * - QueueTask, switch everything to use the Task property, which is a model of all settings. - */ - - #region Private Variables - - /// - /// A Lock object to maintain thread safety - /// - static readonly object QueueLock = new object(); - - /// - /// The Queue of Job objects - /// - private readonly ObservableCollection queue = new ObservableCollection(); - - /// - /// HandBrakes Queue file with a place holder for an extra string. - /// - private string queueFile; - - #endregion - - /// - /// Initializes a new instance of the class. - /// - public QueueManager() - { - // 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.GetInstanceCount); - } - - #region Events - - /// - /// Fires when a job is Added, Removed or Re-Ordered. - /// Should be used for triggering an update of the Queue Window. - /// - public event EventHandler QueueChanged; - - /// - /// Invoke the Queue Changed Event - /// - /// - /// The e. - /// - private void InvokeQueueChanged(EventArgs e) - { - try - { - this.BackupQueue(string.Empty); - } - catch (Exception) - { - // Do Nothing. - } - - EventHandler handler = this.QueueChanged; - if (handler != null) - { - handler(this, e); - } - } - - #endregion - - #region Public Properties - - /// - /// Gets or sets Last Processed Job. - /// This is set when the job is poped of the queue by GetNextJobForProcessing(); - /// - public QueueTask LastProcessedJob { get; set; } - - /// - /// Gets the number of jobs in the queue; - /// - public int Count - { - get - { - return this.queue.Where(item => item.Status == QueueItemStatus.Waiting).Count(); - } - } - - /// - /// Gets The current queue. - /// - public ObservableCollection Queue - { - get - { - return this.queue; - } - } - - #endregion - - #region Public Methods - - /// - /// Add a job to the Queue. - /// This method is Thread Safe. - /// - /// - /// The encode Job object. - /// - public void Add(QueueTask job) - { - lock (QueueLock) - { - queue.Add(job); - InvokeQueueChanged(EventArgs.Empty); - } - } - - /// - /// Remove a job from the Queue. - /// This method is Thread Safe - /// - /// - /// The job. - /// - public void Remove(QueueTask job) - { - lock (QueueLock) - { - queue.Remove(job); - InvokeQueueChanged(EventArgs.Empty); - } - } - - /// - /// Reset a Queued Item from Error or Completed to Waiting - /// - /// - /// The job. - /// - 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; - } - - /// - /// Clear down the Queue´s completed items - /// - public void ClearCompleted() - { - Execute.OnUIThread( - () => - { - List deleteList = this.queue.Where(task => task.Status == QueueItemStatus.Completed).ToList(); - foreach (QueueTask item in deleteList) - { - this.queue.Remove(item); - } - this.InvokeQueueChanged(EventArgs.Empty); - }); - } - - /// - /// Clear down all Queue Items - /// - public void Clear() - { - List deleteList = this.queue.ToList(); - foreach (QueueTask item in deleteList) - { - this.queue.Remove(item); - } - this.InvokeQueueChanged(EventArgs.Empty); - } - - /// - /// Get the first job on the queue for processing. - /// This also removes the job from the Queue and sets the LastProcessedJob - /// - /// - /// An encode Job object. - /// - 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; - InvokeQueueChanged(EventArgs.Empty); - } - - this.BackupQueue(string.Empty); - return job; - } - - this.BackupQueue(string.Empty); - return null; - } - - /// - /// Moves an item up one position in the queue. - /// - /// The zero-based location of the job in the queue. - public void MoveUp(int index) - { - if (index > 0) - { - QueueTask item = queue[index]; - - queue.RemoveAt(index); - queue.Insert((index - 1), item); - } - - this.InvokeQueueChanged(EventArgs.Empty); - } - - /// - /// Moves an item down one position in the queue. - /// - /// The zero-based location of the job in the queue. - 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); - } - - /// - /// Backup any changes to the queue file - /// - /// - /// If this is not null or empty, this will be used instead of the standard backup location. - /// - 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 (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write)) - { - List tasks = queue.Where(item => item.Status != QueueItemStatus.Completed).ToList(); - XmlSerializer serializer = new XmlSerializer(typeof(List)); - serializer.Serialize(strm, tasks); - strm.Close(); - strm.Dispose(); - } - } - - /// - /// Restore a Queue from file or from the queue backup file. - /// - /// - /// The import path. String.Empty or null will result in the default file being loaded. - /// - 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 (FileStream strm = new FileStream((!string.IsNullOrEmpty(importPath) ? importPath : tempPath), FileMode.Open, FileAccess.Read)) - { - if (strm.Length != 0) - { - XmlSerializer serializer = new XmlSerializer(typeof(List)); - - List list; - - try - { - list = serializer.Deserialize(strm) as List; - } - 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); - } - } - } - - /// - /// Checks the current queue for an existing instance of the specified destination. - /// - /// The destination of the encode. - /// Whether or not the supplied destination is already in the queue. - public bool CheckForDestinationPathDuplicates(string destination) - { - return this.queue.Any(checkItem => checkItem.Task.Destination.Contains(destination.Replace("\\\\", "\\"))); - } - - /// - /// Writes the current state of the queue in the form of a batch (.bat) file. - /// - /// - /// The location of the file to write the batch file to. - /// - /// - /// The preview Scan Count. - /// - /// - /// The verbosity. - /// - /// - /// The disable Libdvdnav. - /// - /// - /// The write batch script to file. - /// - public bool WriteBatchScriptToFile(string file, int previewScanCount, int verbosity, bool disableLibdvdnav) - { - string queries = string.Empty; - foreach (QueueTask queueItem in this.queue) - { - string qItem = QueryGeneratorUtility.GenerateQuery(new EncodeTask(queueItem.Task), previewScanCount, verbosity, disableLibdvdnav); - string fullQuery = '"' + Application.StartupPath + "\\HandBrakeCLI.exe" + '"' + qItem; - - if (queries == string.Empty) - queries = queries + fullQuery; - else - queries = queries + " && " + fullQuery; - } - string strCmdLine = queries; - - if (file != string.Empty) - { - try - { - // Create a StreamWriter and open the file, Write the batch file query to the file and - // Close the stream - using (StreamWriter line = new StreamWriter(file)) - { - line.WriteLine(strCmdLine); - } - - return true; - } - catch (Exception exc) - { - throw new Exception("Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", exc); - } - } - return false; - } - - /// - /// Temp workaround until this can be fixed properly. - /// - public void ResetInstanceId() - { - this.queueFile = string.Format("hb_queue_recovery{0}.xml", GeneralUtilities.GetInstanceCount); - } - - #endregion - } -} diff --git a/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs b/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs index 39f31a44c..0b3290839 100644 --- a/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs +++ b/win/CS/HandBrake.ApplicationServices/Services/QueueProcessor.cs @@ -10,10 +10,18 @@ namespace HandBrake.ApplicationServices.Services { using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Diagnostics; + using System.IO; + using System.Linq; using System.Windows.Forms; + using System.Xml.Serialization; + + using Caliburn.Micro; using HandBrake.ApplicationServices.EventArgs; + using HandBrake.ApplicationServices.Exceptions; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Services.Interfaces; using HandBrake.ApplicationServices.Utilities; @@ -23,17 +31,35 @@ namespace HandBrake.ApplicationServices.Services /// public class QueueProcessor : IQueueProcessor { + #region Constants and Fields + + /// + /// A Lock object to maintain thread safety + /// + private static readonly object QueueLock = new object(); + + /// + /// The Queue of Job objects + /// + private readonly ObservableCollection queue = new ObservableCollection(); + /// /// The User Setting Service /// private readonly IUserSettingService userSettingService; + /// + /// HandBrakes Queue file with a place holder for an extra string. + /// + private string queueFile; + + #endregion + + #region Constructors and Destructors + /// /// Initializes a new instance of the class. /// - /// - /// The queue manager. - /// /// /// The encode Service. /// @@ -43,24 +69,18 @@ namespace HandBrake.ApplicationServices.Services /// /// Services are not setup /// - public QueueProcessor(IQueueManager queueManager, IEncodeServiceWrapper encodeService, IUserSettingService userSettingService) + public QueueProcessor(IEncodeServiceWrapper encodeService, IUserSettingService userSettingService) { this.userSettingService = userSettingService; - this.QueueManager = queueManager; this.EncodeService = encodeService; - if (this.QueueManager == null) - { - throw new ArgumentNullException("queueManager"); - } - - if (this.QueueManager == null) - { - throw new ArgumentNullException("queueManager"); - } + // 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.GetInstanceCount); } - #region Events + #endregion + + #region Delegates /// /// Queue Progess Status @@ -73,15 +93,20 @@ namespace HandBrake.ApplicationServices.Services /// public delegate void QueueProgressStatus(object sender, QueueProgressEventArgs e); + #endregion + + #region Events + /// /// Fires when the Queue has started /// public event QueueProgressStatus JobProcessingStarted; /// - /// Fires when a pause to the encode queue has been requested. + /// Fires when a job is Added, Removed or Re-Ordered. + /// Should be used for triggering an update of the Queue Window. /// - public event EventHandler QueuePaused; + public event EventHandler QueueChanged; /// /// Fires when the entire encode queue has completed. @@ -89,87 +114,312 @@ namespace HandBrake.ApplicationServices.Services public event EventHandler QueueCompleted; /// - /// Invoke the JobProcessingStarted event + /// Fires when a pause to the encode queue has been requested. /// - /// - /// The QueueProgressEventArgs. + public event EventHandler QueuePaused; + + #endregion + + #region Properties + + /// + /// Gets the number of jobs in the queue; + /// + public int Count + { + get + { + return this.queue.Count(item => item.Status == QueueItemStatus.Waiting); + } + } + + /// + /// Gets the IEncodeService instance. + /// + public IEncodeServiceWrapper EncodeService { get; private set; } + + /// + /// Gets a value indicating whether IsProcessing. + /// + public bool IsProcessing { get; private set; } + + /// + /// Gets or sets Last Processed Job. + /// This is set when the job is poped of the queue by GetNextJobForProcessing(); + /// + public QueueTask LastProcessedJob { get; set; } + + /// + /// Gets The current queue. + /// + public ObservableCollection Queue + { + get + { + return this.queue; + } + } + + #endregion + + #region Public Methods + + /// + /// Add a job to the Queue. + /// This method is Thread Safe. + /// + /// + /// The encode Job object. /// - private void InvokeJobProcessingStarted(QueueProgressEventArgs e) + public void Add(QueueTask job) { - QueueProgressStatus handler = this.JobProcessingStarted; - if (handler != null) + lock (QueueLock) { - handler(this, e); + this.queue.Add(job); + this.InvokeQueueChanged(EventArgs.Empty); } } /// - /// Invoke the QueuePaused event + /// Backup any changes to the queue file /// - /// - /// The EventArgs. + /// + /// If this is not null or empty, this will be used instead of the standard backup location. /// - private void InvokeQueuePaused(EventArgs e) + public void BackupQueue(string exportPath) { - EventHandler handler = this.QueuePaused; - if (handler != null) + 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)) { - handler(this, e); + List tasks = this.queue.Where(item => item.Status != QueueItemStatus.Completed).ToList(); + var serializer = new XmlSerializer(typeof(List)); + serializer.Serialize(strm, tasks); + strm.Close(); + strm.Dispose(); } } /// - /// Invoke the QueueCompleted event. + /// Checks the current queue for an existing instance of the specified destination. /// - /// - /// The EventArgs. + /// + /// The destination of the encode. /// - private void InvokeQueueCompleted(EventArgs e) + /// + /// Whether or not the supplied destination is already in the queue. + /// + public bool CheckForDestinationPathDuplicates(string destination) { - this.IsProcessing = false; + return this.queue.Any(checkItem => checkItem.Task.Destination.Contains(destination.Replace("\\\\", "\\"))); + } - EventHandler handler = this.QueueCompleted; - if (handler != null) + /// + /// Clear down all Queue Items + /// + public void Clear() + { + List deleteList = this.queue.ToList(); + foreach (QueueTask item in deleteList) { - handler(this, e); + this.queue.Remove(item); } + this.InvokeQueueChanged(EventArgs.Empty); } - #endregion + /// + /// Clear down the Queue´s completed items + /// + public void ClearCompleted() + { + Execute.OnUIThread( + () => + { + List deleteList = + this.queue.Where(task => task.Status == QueueItemStatus.Completed).ToList(); + foreach (QueueTask item in deleteList) + { + this.queue.Remove(item); + } + this.InvokeQueueChanged(EventArgs.Empty); + }); + } - #region Properties + /// + /// Get the first job on the queue for processing. + /// This also removes the job from the Queue and sets the LastProcessedJob + /// + /// + /// An encode Job object. + /// + 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; + } /// - /// Gets a value indicating whether IsProcessing. + /// Moves an item down one position in the queue. /// - public bool IsProcessing { get; private set; } + /// + /// The zero-based location of the job in the queue. + /// + 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); + } /// - /// Gets the IEncodeService instance. + /// Moves an item up one position in the queue. /// - public IEncodeServiceWrapper EncodeService { get; private set; } + /// + /// The zero-based location of the job in the queue. + /// + 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); + } /// - /// Gets the IQueueManager instance. + /// Remove a job from the Queue. + /// This method is Thread Safe /// - public IQueueManager QueueManager { get; private set; } + /// + /// The job. + /// + public void Remove(QueueTask job) + { + lock (QueueLock) + { + this.queue.Remove(job); + this.InvokeQueueChanged(EventArgs.Empty); + } + } - #endregion + /// + /// Temp workaround until this can be fixed properly. + /// + public void ResetInstanceId() + { + this.queueFile = string.Format("hb_queue_recovery{0}.xml", GeneralUtilities.GetInstanceCount); + } /// - /// Starts encoding the first job in the queue and continues encoding until all jobs - /// have been encoded. + /// Reset a Queued Item from Error or Completed to Waiting /// - public void Start() + /// + /// The job. + /// + public void ResetJobStatusToWaiting(QueueTask job) { - if (IsProcessing) + if (job.Status != QueueItemStatus.Error && job.Status != QueueItemStatus.Completed) { - throw new Exception("Already Processing the Queue"); + throw new GeneralApplicationException( + "Job Error", "Unable to reset job status as it is not in an Error or Completed state", null); } - IsProcessing = true; - this.EncodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted; - this.ProcessNextJob(); + job.Status = QueueItemStatus.Waiting; + } + + /// + /// Restore a Queue from file or from the queue backup file. + /// + /// + /// The import path. String.Empty or null will result in the default file being loaded. + /// + 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)); + + List list; + + try + { + list = serializer.Deserialize(strm) as List; + } + 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); + } + } } /// @@ -182,17 +432,25 @@ namespace HandBrake.ApplicationServices.Services } /// - /// Swap encode service. - /// Temp method until Castle is hooked up. + /// Starts encoding the first job in the queue and continues encoding until all jobs + /// have been encoded. /// - /// - /// The service. - /// - public void SwapEncodeService(IEncodeServiceWrapper service) + public void Start() { - this.EncodeService = service; + if (this.IsProcessing) + { + throw new Exception("Already Processing the Queue"); + } + + this.IsProcessing = true; + this.EncodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted; + this.ProcessNextJob(); } + #endregion + + #region Methods + /// /// After an encode is complete, move onto the next job. /// @@ -204,39 +462,139 @@ namespace HandBrake.ApplicationServices.Services /// private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { - this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Completed; + this.LastProcessedJob.Status = QueueItemStatus.Completed; // Clear the completed item of the queue if the setting is set. - if (userSettingService.GetUserSetting(ASUserSettingConstants.ClearCompletedFromQueue)) + if (this.userSettingService.GetUserSetting(ASUserSettingConstants.ClearCompletedFromQueue)) { - this.QueueManager.ClearCompleted(); + this.ClearCompleted(); } if (!e.Successful) { - this.QueueManager.LastProcessedJob.Status = QueueItemStatus.Error; + this.LastProcessedJob.Status = QueueItemStatus.Error; this.Pause(); } // Handling Log Data - this.EncodeService.ProcessLogs(this.QueueManager.LastProcessedJob.Task.Destination); + this.EncodeService.ProcessLogs(this.LastProcessedJob.Task.Destination); // Post-Processing if (e.Successful) { - SendToApplication(this.QueueManager.LastProcessedJob.Task.Destination); + this.SendToApplication(this.LastProcessedJob.Task.Destination); } // Move onto the next job. if (this.IsProcessing) { this.ProcessNextJob(); - } - else + } + else { this.EncodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; this.InvokeQueueCompleted(EventArgs.Empty); - this.QueueManager.BackupQueue(string.Empty); + this.BackupQueue(string.Empty); + } + } + + /// + /// Perform an action after an encode. e.g a shutdown, standby, restart etc. + /// + private void Finish() + { + // Do something whent he encode ends. + switch (this.userSettingService.GetUserSetting(ASUserSettingConstants.WhenCompleteAction)) + { + case "Shutdown": + Process.Start("Shutdown", "-s -t 60"); + break; + case "Log off": + Win32.ExitWindowsEx(0, 0); + break; + case "Suspend": + Application.SetSuspendState(PowerState.Suspend, true, true); + break; + case "Hibernate": + Application.SetSuspendState(PowerState.Hibernate, true, true); + break; + case "Lock System": + Win32.LockWorkStation(); + break; + case "Quit HandBrake": + Application.Exit(); + break; + } + } + + /// + /// Invoke the JobProcessingStarted event + /// + /// + /// The QueueProgressEventArgs. + /// + private void InvokeJobProcessingStarted(QueueProgressEventArgs e) + { + QueueProgressStatus handler = this.JobProcessingStarted; + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Invoke the Queue Changed Event + /// + /// + /// The e. + /// + private void InvokeQueueChanged(EventArgs e) + { + try + { + this.BackupQueue(string.Empty); + } + catch (Exception) + { + // Do Nothing. + } + + EventHandler handler = this.QueueChanged; + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Invoke the QueueCompleted event. + /// + /// + /// The EventArgs. + /// + private void InvokeQueueCompleted(EventArgs e) + { + this.IsProcessing = false; + + EventHandler handler = this.QueueCompleted; + if (handler != null) + { + handler(this, e); + } + } + + /// + /// Invoke the QueuePaused event + /// + /// + /// The EventArgs. + /// + private void InvokeQueuePaused(EventArgs e) + { + EventHandler handler = this.QueuePaused; + if (handler != null) + { + handler(this, e); } } @@ -252,11 +610,11 @@ namespace HandBrake.ApplicationServices.Services return; } - QueueTask job = this.QueueManager.GetNextJobForProcessing(); + QueueTask job = this.GetNextJobForProcessing(); if (job != null) { this.InvokeJobProcessingStarted(new QueueProgressEventArgs(job)); - this.EncodeService.Start(job, true); + this.EncodeService.Start(job, true); } else { @@ -267,53 +625,32 @@ namespace HandBrake.ApplicationServices.Services this.InvokeQueueCompleted(EventArgs.Empty); // Run the After encode completeion work - Finish(); + this.Finish(); } } /// /// Send a file to a 3rd party application after encoding has completed. /// - /// The file path + /// + /// The file path + /// private void SendToApplication(string file) { - if (userSettingService.GetUserSetting(ASUserSettingConstants.SendFile) && !string.IsNullOrEmpty(userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo))) + if (this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFile) && + !string.IsNullOrEmpty(this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo))) { - string args = string.Format("{0} \"{1}\"", userSettingService.GetUserSetting(ASUserSettingConstants.SendFileToArgs), file); - ProcessStartInfo vlc = new ProcessStartInfo(userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo), args); + string args = string.Format( + "{0} \"{1}\"", + this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileToArgs), + file); + var vlc = + new ProcessStartInfo( + this.userSettingService.GetUserSetting(ASUserSettingConstants.SendFileTo), args); Process.Start(vlc); } } - /// - /// Perform an action after an encode. e.g a shutdown, standby, restart etc. - /// - private void Finish() - { - // Do something whent he encode ends. - switch (userSettingService.GetUserSetting(ASUserSettingConstants.WhenCompleteAction)) - { - case "Shutdown": - Process.Start("Shutdown", "-s -t 60"); - break; - case "Log off": - Win32.ExitWindowsEx(0, 0); - break; - case "Suspend": - Application.SetSuspendState(PowerState.Suspend, true, true); - break; - case "Hibernate": - Application.SetSuspendState(PowerState.Hibernate, true, true); - break; - case "Lock System": - Win32.LockWorkStation(); - break; - case "Quit HandBrake": - Application.Exit(); - break; - default: - break; - } - } + #endregion } } \ No newline at end of file diff --git a/win/CS/HandBrake.ApplicationServices/ServicesWindsorInstaller.cs b/win/CS/HandBrake.ApplicationServices/ServicesWindsorInstaller.cs index d2e0f0bb7..b787aa18b 100644 --- a/win/CS/HandBrake.ApplicationServices/ServicesWindsorInstaller.cs +++ b/win/CS/HandBrake.ApplicationServices/ServicesWindsorInstaller.cs @@ -30,11 +30,8 @@ namespace HandBrake.ApplicationServices public void Install(IWindsorContainer container, IConfigurationStore store) { container.Register(Component.For().ImplementedBy()); - container.Register(Component.For().ImplementedBy()); container.Register(Component.For().ImplementedBy()); container.Register(Component.For().ImplementedBy()); - // container.Register(Component.For().ImplementedBy()); - // container.Register(Component.For().ImplementedBy()); } #endregion diff --git a/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs b/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs index 32e999e7b..f37fae656 100644 --- a/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs +++ b/win/CS/HandBrakeWPF/Helpers/QueueRecoveryHelper.cs @@ -115,7 +115,7 @@ namespace HandBrakeWPF.Helpers { foreach (string file in queueFiles) { - encodeQueue.QueueManager.RestoreQueue(appDataPath + file); // Start Recovery + encodeQueue.RestoreQueue(appDataPath + file); // Start Recovery } } else diff --git a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs index e7c737b09..70f62c435 100644 --- a/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/MainViewModel.cs @@ -207,7 +207,7 @@ namespace HandBrakeWPF.ViewModels this.driveDetectService = driveDetectService; this.userSettingService = userSettingService; this.queueProcessor = IoC.Get(); - this.queueProcessor.QueueManager.ResetInstanceId(); + this.queueProcessor.ResetInstanceId(); // Setup Properties this.WindowTitle = "HandBrake"; @@ -960,9 +960,9 @@ namespace HandBrakeWPF.ViewModels } QueueTask task = new QueueTask { Task = new EncodeTask(this.CurrentTask) }; - if (!this.queueProcessor.QueueManager.CheckForDestinationPathDuplicates(task.Task.Destination)) + if (!this.queueProcessor.CheckForDestinationPathDuplicates(task.Task.Destination)) { - this.queueProcessor.QueueManager.Add(task); + this.queueProcessor.Add(task); } else { @@ -971,7 +971,7 @@ namespace HandBrakeWPF.ViewModels if (!this.IsEncoding) { - this.ProgramStatusLabel = string.Format("{0} Encodes Pending", this.queueProcessor.QueueManager.Count); + this.ProgramStatusLabel = string.Format("{0} Encodes Pending", this.queueProcessor.Count); } } @@ -1083,7 +1083,7 @@ namespace HandBrakeWPF.ViewModels } // Check if we already have jobs, and if we do, just start the queue. - if (this.queueProcessor.QueueManager.Count != 0) + if (this.queueProcessor.Count != 0) { this.queueProcessor.Start(); return; @@ -1117,7 +1117,7 @@ namespace HandBrakeWPF.ViewModels Task = new EncodeTask(this.CurrentTask), CustomQuery = false }; - this.queueProcessor.QueueManager.Add(task); + this.queueProcessor.Add(task); this.queueProcessor.Start(); this.IsEncoding = true; } @@ -1700,7 +1700,7 @@ namespace HandBrakeWPF.ViewModels e.AverageFrameRate, e.EstimatedTimeLeft, e.ElapsedTime, - this.queueProcessor.QueueManager.Count); + this.queueProcessor.Count); } }); } diff --git a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs index 82f3b30f4..80fe4372a 100644 --- a/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs +++ b/win/CS/HandBrakeWPF/ViewModels/QueueViewModel.cs @@ -158,7 +158,7 @@ namespace HandBrakeWPF.ViewModels { get { - return this.queueProcessor.QueueManager.Queue; + return this.queueProcessor.Queue; } } @@ -203,7 +203,7 @@ namespace HandBrakeWPF.ViewModels "Are you sure you wish to clear the queue?", "Confirm", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) { - this.queueProcessor.QueueManager.Clear(); + this.queueProcessor.Clear(); } } @@ -212,7 +212,7 @@ namespace HandBrakeWPF.ViewModels /// public void ClearCompleted() { - this.queueProcessor.QueueManager.ClearCompleted(); + this.queueProcessor.ClearCompleted(); } /// @@ -230,7 +230,7 @@ namespace HandBrakeWPF.ViewModels { // Setup the window to the correct state. this.IsEncoding = this.queueProcessor.EncodeService.IsEncoding; - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.QueueManager.Count); + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); base.OnLoad(); } @@ -263,15 +263,15 @@ namespace HandBrakeWPF.ViewModels if (result == MessageBoxResult.Yes) { this.queueProcessor.EncodeService.Stop(); - this.queueProcessor.QueueManager.Remove(task); + this.queueProcessor.Remove(task); } } else { - this.queueProcessor.QueueManager.Remove(task); + this.queueProcessor.Remove(task); } - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.QueueManager.Count); + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); } /// @@ -283,7 +283,7 @@ namespace HandBrakeWPF.ViewModels public void RetryJob(QueueTask task) { task.Status = QueueItemStatus.Waiting; - this.queueProcessor.QueueManager.BackupQueue(null); + this.queueProcessor.BackupQueue(null); } /// @@ -291,7 +291,7 @@ namespace HandBrakeWPF.ViewModels /// public void StartEncode() { - if (this.queueProcessor.QueueManager.Count == 0) + if (this.queueProcessor.Count == 0) { this.errorService.ShowMessageBox( "There are no pending jobs.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); @@ -315,7 +315,7 @@ namespace HandBrakeWPF.ViewModels }; dialog.ShowDialog(); - this.queueProcessor.QueueManager.BackupQueue(dialog.FileName); + this.queueProcessor.BackupQueue(dialog.FileName); } /// @@ -326,7 +326,7 @@ namespace HandBrakeWPF.ViewModels VistaOpenFileDialog dialog = new VistaOpenFileDialog { Filter = "HandBrake Queue Files (*.hbq)|*.hbq", CheckFileExists = true }; dialog.ShowDialog(); - this.queueProcessor.QueueManager.RestoreQueue(dialog.FileName); + this.queueProcessor.RestoreQueue(dialog.FileName); } /// @@ -372,7 +372,7 @@ namespace HandBrakeWPF.ViewModels this.queueProcessor.JobProcessingStarted += this.queueProcessor_JobProcessingStarted; this.queueProcessor.QueueCompleted += this.queueProcessor_QueueCompleted; this.queueProcessor.QueuePaused += this.queueProcessor_QueuePaused; - this.queueProcessor.QueueManager.QueueChanged += this.QueueManager_QueueChanged; + this.queueProcessor.QueueChanged += this.QueueManager_QueueChanged; this.queueProcessor.EncodeService.EncodeStatusChanged += this.EncodeService_EncodeStatusChanged; base.OnActivate(); @@ -389,7 +389,7 @@ namespace HandBrakeWPF.ViewModels this.queueProcessor.JobProcessingStarted -= this.queueProcessor_JobProcessingStarted; this.queueProcessor.QueueCompleted -= this.queueProcessor_QueueCompleted; this.queueProcessor.QueuePaused -= this.queueProcessor_QueuePaused; - this.queueProcessor.QueueManager.QueueChanged -= this.QueueManager_QueueChanged; + this.queueProcessor.QueueChanged -= this.QueueManager_QueueChanged; this.queueProcessor.EncodeService.EncodeStatusChanged -= this.EncodeService_EncodeStatusChanged; base.OnDeactivate(close); @@ -430,7 +430,7 @@ namespace HandBrakeWPF.ViewModels /// private void QueueManager_QueueChanged(object sender, EventArgs e) { - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.QueueManager.Count); + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); } /// @@ -446,7 +446,7 @@ namespace HandBrakeWPF.ViewModels object sender, QueueProgressEventArgs e) { this.JobStatus = "Queue Started"; - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.QueueManager.Count); + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); this.IsEncoding = true; } @@ -462,7 +462,7 @@ namespace HandBrakeWPF.ViewModels private void queueProcessor_QueueCompleted(object sender, EventArgs e) { this.JobStatus = "Queue Completed"; - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.QueueManager.Count); + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); this.IsEncoding = false; } @@ -478,7 +478,7 @@ namespace HandBrakeWPF.ViewModels private void queueProcessor_QueuePaused(object sender, EventArgs e) { this.JobStatus = "Queue Paused"; - this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.QueueManager.Count); + this.JobsPending = string.Format("{0} jobs pending", this.queueProcessor.Count); this.IsEncoding = false; } diff --git a/win/CS/HandBrakeWPF/Views/MainView.xaml b/win/CS/HandBrakeWPF/Views/MainView.xaml index ac4085146..c051786af 100644 --- a/win/CS/HandBrakeWPF/Views/MainView.xaml +++ b/win/CS/HandBrakeWPF/Views/MainView.xaml @@ -134,7 +134,6 @@ - -- cgit v1.2.3