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 HandBrake.ApplicationServices.Model;
using HandBrake.ApplicationServices.Services.Interfaces;
using EventArgs = System.EventArgs;
///
/// The Queue Manager.
/// Thread Safe.
///
public class QueueManager : IQueueManager
{
/*
* TODO
* - Rewrite the batch script generator.
*/
#region Private Variables
///
/// A Lock object to maintain thread safety
///
static readonly object QueueLock = new object();
///
/// The Queue of Job objects
///
private readonly List queue = new List();
///
/// HandBrakes Queue file with a place holder for an extra string.
///
private readonly string queueFile;
///
/// The ID of the job last added
///
private int lastJobId;
///
/// The instance Id of this HandBrake instance.
///
private int instanceId;
#endregion
///
/// Initializes a new instance of the class.
///
///
/// The instance Id.
///
public QueueManager(int instanceId)
{
this.instanceId = instanceId;
// If this is the first instance, just use the main queue file, otherwise add the instance id to the filename.
this.queueFile = instanceId == 0 ? "hb_queue_recovery.xml" : string.Format("hb_queue_recovery{0}.xml", instanceId);
}
#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.Count;
}
}
///
/// Gets The current queue.
///
public ReadOnlyCollection Queue
{
get
{
return this.queue.AsReadOnly();
}
}
#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)
{
// Tag the job with an ID
job.Id = lastJobId++;
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)
{
// Tag the job with an ID
job.Id = lastJobId++;
queue.Add(job);
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[0];
this.LastProcessedJob = job;
this.Remove(job); // Remove the item which we are about to pass out.
return job;
}
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);
if (File.Exists(tempPath))
{
using (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write))
{
XmlSerializer serializer = new XmlSerializer(typeof(List));
serializer.Serialize(strm, queue);
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))
{
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 = serializer.Deserialize(strm) as List;
if (list != null)
foreach (QueueTask item in list)
this.queue.Add(item);
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 write batch script to file.
///
public bool WriteBatchScriptToFile(string file)
{
string queries = string.Empty;
foreach (QueueTask queueItem in this.queue)
{
string qItem = queueItem.Query;
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;
}
#endregion
}
}