-/* Queue.cs $\r
- This file is part of the HandBrake source code.\r
- Homepage: <http://handbrake.fr/>.\r
- It may be used under the terms of the GNU General Public License. */\r
-\r
-namespace HandBrake.ApplicationServices.Services\r
-{\r
- using System;\r
- using System.Collections.Generic;\r
- using System.Collections.ObjectModel;\r
- using System.Diagnostics;\r
- using System.IO;\r
- using System.Linq;\r
- using System.Threading;\r
- using System.Windows.Forms;\r
- using System.Xml.Serialization;\r
-\r
- using HandBrake.ApplicationServices.Functions;\r
- using HandBrake.ApplicationServices.Model;\r
- using HandBrake.ApplicationServices.Services.Interfaces;\r
-\r
- /// <summary>\r
- /// The HandBrake Queue\r
- /// </summary>\r
- public class Queue : Encode, IQueue\r
- {\r
- /// <summary>\r
- /// The Queue Job List\r
- /// </summary>\r
- private readonly List<QueueTask> queue = new List<QueueTask>();\r
-\r
- /// <summary>\r
- /// An XML Serializer\r
- /// </summary>\r
- private static XmlSerializer serializer;\r
-\r
- /// <summary>\r
- /// The Next Job ID\r
- /// </summary>\r
- private int nextJobId;\r
-\r
- #region Events\r
- /// <summary>\r
- /// Fires when the Queue has started\r
- /// </summary>\r
- public event EventHandler QueueStarted;\r
-\r
- /// <summary>\r
- /// Fires when a job is Added, Removed or Re-Ordered.\r
- /// Should be used for triggering an update of the Queue Window.\r
- /// </summary>\r
- public event EventHandler QueueListChanged;\r
-\r
- /// <summary>\r
- /// Fires when a pause to the encode queue has been requested.\r
- /// </summary>\r
- public event EventHandler QueuePauseRequested;\r
-\r
- /// <summary>\r
- /// Fires when the entire encode queue has completed.\r
- /// </summary>\r
- public event EventHandler QueueCompleted;\r
- #endregion\r
-\r
- #region Properties\r
- /// <summary>\r
- /// Gets or sets the last encode that was processed.\r
- /// </summary>\r
- /// <returns></returns> \r
- public QueueTask LastEncode { get; set; }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether Request Pause\r
- /// </summary>\r
- public bool Paused { get; private set; }\r
-\r
- /// <summary>\r
- /// Gets the current state of the encode queue.\r
- /// </summary>\r
- public ReadOnlyCollection<QueueTask> CurrentQueue\r
- {\r
- get { return this.queue.AsReadOnly(); }\r
- }\r
-\r
- /// <summary>\r
- /// Gets the number of items in the queue.\r
- /// </summary>\r
- public int Count\r
- {\r
- get { return this.queue.Count; }\r
- }\r
- #endregion\r
-\r
- #region Queue\r
-\r
- /// <summary>\r
- /// Gets and removes the next job in the queue.\r
- /// </summary>\r
- /// <returns>The job that was removed from the queue.</returns>\r
- private QueueTask GetNextJob()\r
- {\r
- QueueTask job = this.queue[0];\r
- this.LastEncode = job;\r
- this.Remove(0); // Remove the item which we are about to pass out.\r
-\r
- this.SaveQueue();\r
-\r
- return job;\r
- }\r
-\r
- /// <summary>\r
- /// Adds an item to the queue.\r
- /// </summary>\r
- /// <param name="query">\r
- /// The query that will be passed to the HandBrake CLI.\r
- /// </param>\r
- /// <param name="title">\r
- /// The title.\r
- /// </param>\r
- /// <param name="source">\r
- /// The location of the source video.\r
- /// </param>\r
- /// <param name="destination">\r
- /// The location where the encoded video will be.\r
- /// </param>\r
- /// <param name="customJob">\r
- /// Custom job\r
- /// </param>\r
- public void Add(string query, int title, string source, string destination, bool customJob)\r
- {\r
- QueueTask newJob = new QueueTask\r
- {\r
- Id = this.nextJobId++,\r
- Title = title,\r
- Query = query,\r
- Source = source,\r
- Destination = destination,\r
- CustomQuery = customJob\r
- };\r
-\r
- this.queue.Add(newJob);\r
- this.SaveQueue();\r
-\r
- if (this.QueueListChanged != null)\r
- this.QueueListChanged(this, new EventArgs());\r
- }\r
-\r
- /// <summary>\r
- /// Removes an item from the queue.\r
- /// </summary>\r
- /// <param name="index">The zero-based location of the job in the queue.</param>\r
- public void Remove(int index)\r
- {\r
- this.queue.RemoveAt(index);\r
- this.SaveQueue();\r
-\r
- if (this.QueueListChanged != null)\r
- this.QueueListChanged(this, new EventArgs());\r
- }\r
-\r
- /// <summary>\r
- /// Retrieve a job from the queue\r
- /// </summary>\r
- /// <param name="index">the job id</param>\r
- /// <returns>A job for the given index or blank job object</returns>\r
- public QueueTask GetJob(int index)\r
- {\r
- if (this.queue.Count >= (index + 1))\r
- return this.queue[index];\r
-\r
- return new QueueTask();\r
- }\r
-\r
- /// <summary>\r
- /// Moves an item up one position in the queue.\r
- /// </summary>\r
- /// <param name="index">The zero-based location of the job in the queue.</param>\r
- public void MoveUp(int index)\r
- {\r
- if (index > 0)\r
- {\r
- QueueTask item = queue[index];\r
-\r
- queue.RemoveAt(index);\r
- queue.Insert((index - 1), item);\r
- }\r
-\r
- this.SaveQueue(); // Update the queue recovery file\r
-\r
- if (this.QueueListChanged != null)\r
- this.QueueListChanged(this, new EventArgs());\r
- }\r
-\r
- /// <summary>\r
- /// Moves an item down one position in the queue.\r
- /// </summary>\r
- /// <param name="index">The zero-based location of the job in the queue.</param>\r
- public void MoveDown(int index)\r
- {\r
- if (index < this.queue.Count - 1)\r
- {\r
- QueueTask item = this.queue[index];\r
-\r
- this.queue.RemoveAt(index);\r
- this.queue.Insert((index + 1), item);\r
- }\r
-\r
- this.SaveQueue(); // Update the queue recovery file\r
-\r
- if (this.QueueListChanged != null)\r
- this.QueueListChanged(this, new EventArgs());\r
- }\r
- \r
- /// <summary>\r
- /// Save any updates to the main queue file.\r
- /// </summary>\r
- public void SaveQueue()\r
- {\r
- string file = Init.InstanceId == 0\r
- ? "hb_queue_recovery.xml"\r
- : string.Format("hb_queue_recovery{0}.xml", Init.InstanceId);\r
- this.WriteQueueStateToFile(file);\r
- }\r
-\r
- /// <summary>\r
- /// Writes the current state of the queue to a file.\r
- /// </summary>\r
- /// <param name="file">The location of the file to write the queue to.</param>\r
- public void WriteQueueStateToFile(string file)\r
- {\r
- string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");\r
- string tempPath = file.Contains("hb_queue_recovery") ? appDataPath + file : file;\r
-\r
- try\r
- {\r
- using (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write))\r
- {\r
- if (serializer == null)\r
- serializer = new XmlSerializer(typeof(List<QueueTask>));\r
- serializer.Serialize(strm, queue);\r
- strm.Close();\r
- strm.Dispose();\r
- }\r
- }\r
- catch (Exception)\r
- {\r
- return;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Writes the current state of the queue in the form of a batch (.bat) file.\r
- /// </summary>\r
- /// <param name="file">\r
- /// The location of the file to write the batch file to.\r
- /// </param>\r
- /// <returns>\r
- /// The write batch script to file.\r
- /// </returns>\r
- public bool WriteBatchScriptToFile(string file)\r
- {\r
- string queries = string.Empty;\r
- foreach (QueueTask queueItem in this.queue)\r
- {\r
- string qItem = queueItem.Query;\r
- string fullQuery = '"' + Application.StartupPath + "\\HandBrakeCLI.exe" + '"' + qItem;\r
-\r
- if (queries == string.Empty)\r
- queries = queries + fullQuery;\r
- else\r
- queries = queries + " && " + fullQuery;\r
- }\r
- string strCmdLine = queries;\r
-\r
- if (file != string.Empty)\r
- {\r
- try\r
- {\r
- // Create a StreamWriter and open the file, Write the batch file query to the file and \r
- // Close the stream\r
- using (StreamWriter line = new StreamWriter(file))\r
- {\r
- line.WriteLine(strCmdLine);\r
- }\r
-\r
- return true;\r
- }\r
- catch (Exception exc)\r
- {\r
- throw new Exception("Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", exc);\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- /// <summary>\r
- /// Reads a serialized XML file that represents a queue of encoding jobs.\r
- /// </summary>\r
- /// <param name="file">The location of the file to read the queue from.</param>\r
- public void LoadQueueFromFile(string file)\r
- {\r
- string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\");\r
- string tempPath = file.Contains("hb_queue_recovery") ? appDataPath + file : file;\r
-\r
- if (File.Exists(tempPath))\r
- {\r
- using (FileStream strm = new FileStream(tempPath, FileMode.Open, FileAccess.Read))\r
- {\r
- if (strm.Length != 0)\r
- {\r
- if (serializer == null)\r
- serializer = new XmlSerializer(typeof(List<QueueTask>));\r
-\r
- List<QueueTask> list = serializer.Deserialize(strm) as List<QueueTask>;\r
-\r
- if (list != null)\r
- foreach (QueueTask item in list)\r
- this.queue.Add(item);\r
-\r
- if (!file.Contains("hb_queue_recovery"))\r
- this.SaveQueue();\r
-\r
- if (this.QueueListChanged != null)\r
- this.QueueListChanged(this, new EventArgs());\r
- }\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Checks the current queue for an existing instance of the specified destination.\r
- /// </summary>\r
- /// <param name="destination">The destination of the encode.</param>\r
- /// <returns>Whether or not the supplied destination is already in the queue.</returns>\r
- public bool CheckForDestinationDuplicate(string destination)\r
- {\r
- return this.queue.Any(checkItem => checkItem.Destination.Contains(destination.Replace("\\\\", "\\")));\r
- }\r
-\r
- #endregion\r
-\r
- #region Encoding\r
-\r
- /// <summary>\r
- /// Starts encoding the first job in the queue and continues encoding until all jobs\r
- /// have been encoded.\r
- /// </summary>\r
- public void Start()\r
- {\r
- if (this.Count != 0)\r
- {\r
- if (this.Paused)\r
- this.Paused = false;\r
- else\r
- {\r
- this.Paused = false;\r
- try\r
- {\r
- Thread theQueue = new Thread(this.StartQueue) { IsBackground = true };\r
- theQueue.Start();\r
-\r
- if (this.QueueStarted != null)\r
- this.QueueStarted(this, new EventArgs());\r
- }\r
- catch (Exception exc)\r
- {\r
- throw new Exception("Unable to Start Queue", exc);\r
- }\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Requests a pause of the encode queue.\r
- /// </summary>\r
- public void Pause()\r
- {\r
- this.Paused = true;\r
-\r
- if (this.QueuePauseRequested != null)\r
- this.QueuePauseRequested(this, new EventArgs());\r
- }\r
-\r
- /// <summary>\r
- /// Run through all the jobs on the queue.\r
- /// </summary>\r
- /// <param name="state">Object State</param>\r
- private void StartQueue(object state)\r
- {\r
- // Run through each item on the queue\r
- while (this.Count != 0)\r
- {\r
- QueueTask encJob = this.GetNextJob();\r
- this.SaveQueue(); // Update the queue recovery file\r
-\r
- Start(encJob, true);\r
-\r
- if (HbProcess == null)\r
- {\r
- return;\r
- }\r
- HbProcess.WaitForExit();\r
-\r
- this.CopyLog(this.LastEncode.Destination);\r
-\r
- HbProcess.Close();\r
- HbProcess.Dispose();\r
-\r
- // Growl\r
- if (Init.GrowlEncode)\r
- GrowlCommunicator.Notify("Encode Completed",\r
- "Put down that cocktail...\nyour Handbrake encode is done.");\r
-\r
- while (this.Paused) // Need to find a better way of doing this.\r
- {\r
- Thread.Sleep(2000);\r
- }\r
- }\r
- this.LastEncode = new QueueTask();\r
-\r
- if (this.QueueCompleted != null)\r
- this.QueueCompleted(this, new EventArgs());\r
-\r
- // After the encode is done, we may want to shutdown, suspend etc.\r
- Finish();\r
- }\r
-\r
- /// <summary>\r
- /// Perform an action after an encode. e.g a shutdown, standby, restart etc.\r
- /// </summary>\r
- private void Finish()\r
- {\r
- // Growl\r
- if (Init.GrowlQueue)\r
- GrowlCommunicator.Notify("Queue Completed", "Put down that cocktail...\nyour Handbrake queue is done.");\r
-\r
- // Do something whent he encode ends.\r
- switch (Init.CompletionOption)\r
- {\r
- case "Shutdown":\r
- Process.Start("Shutdown", "-s -t 60");\r
- break;\r
- case "Log Off":\r
- Win32.ExitWindowsEx(0, 0);\r
- break;\r
- case "Suspend":\r
- Application.SetSuspendState(PowerState.Suspend, true, true);\r
- break;\r
- case "Hibernate":\r
- Application.SetSuspendState(PowerState.Hibernate, true, true);\r
- break;\r
- case "Lock System":\r
- Win32.LockWorkStation();\r
- break;\r
- case "Quit HandBrake":\r
- Application.Exit();\r
- break;\r
- default:\r
- break;\r
- }\r
- }\r
-\r
- #endregion\r
- }\r
-}
\ No newline at end of file