/* Queue.cs $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Threading; using System.Windows.Forms; using System.Xml.Serialization; using Handbrake.Functions; namespace Handbrake.EncodeQueue { public class Queue : Encode { private static XmlSerializer serializer; private readonly List queue = new List(); private int NextJobId; /// /// Fires when a pause to the encode queue has been requested. /// public event EventHandler QueuePauseRequested; /// /// Fires when the entire encode queue has completed. /// public event EventHandler QueueCompleted; #region Queue /// /// Gets and removes the next job in the queue. /// /// The job that was removed from the queue. private Job GetNextJob() { Job job = queue[0]; LastEncode = job; Remove(0); // Remove the item which we are about to pass out. WriteQueueStateToFile("hb_queue_recovery.xml"); return job; } /// /// Gets the current state of the encode queue. /// public ReadOnlyCollection CurrentQueue { get { return queue.AsReadOnly(); } } /// /// Gets the number of items in the queue. /// public int Count { get { return queue.Count; } } /// /// Adds an item to the queue. /// /// The query that will be passed to the HandBrake CLI. /// The location of the source video. /// The location where the encoded video will be. /// Custom job /// The Scan public void Add(string query, string source, string destination, bool customJob) { Job newJob = new Job { Id = NextJobId++, Query = query, Source = source, Destination = destination, CustomQuery = customJob }; queue.Add(newJob); WriteQueueStateToFile("hb_queue_recovery.xml"); } /// /// Removes an item from the queue. /// /// The zero-based location of the job in the queue. public void Remove(int index) { queue.RemoveAt(index); WriteQueueStateToFile("hb_queue_recovery.xml"); } /// /// Retrieve a job from the queue /// /// /// public Job GetJob(int index) { if (queue.Count >= (index +1)) return queue[index]; return new Job(); } /// /// 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) { Job item = queue[index]; queue.RemoveAt(index); queue.Insert((index - 1), item); } WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file } /// /// 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 < queue.Count - 1) { Job item = queue[index]; queue.RemoveAt(index); queue.Insert((index + 1), item); } WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file } /// /// Writes the current state of the queue to a file. /// /// The location of the file to write the queue to. public void WriteQueueStateToFile(string file) { string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\hb_queue_recovery.xml"); string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : file; try { using (FileStream strm = new FileStream(tempPath, FileMode.Create, FileAccess.Write)) { if (serializer == null) serializer = new XmlSerializer(typeof(List)); serializer.Serialize(strm, queue); strm.Close(); strm.Dispose(); } } catch (Exception) { return; } } /// /// 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. public void WriteBatchScriptToFile(string file) { string queries = ""; foreach (Job queue_item in queue) { string q_item = queue_item.Query; string fullQuery = '"' + Application.StartupPath + "\\HandBrakeCLI.exe" + '"' + q_item; if (queries == string.Empty) queries = queries + fullQuery; else queries = queries + " && " + fullQuery; } string strCmdLine = queries; if (file != "") { 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); } MessageBox.Show("Your batch script has been sucessfully saved.", "Status", MessageBoxButtons.OK, MessageBoxIcon.Asterisk); } catch (Exception) { MessageBox.Show("Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand); } } } /// /// Reads a serialized XML file that represents a queue of encoding jobs. /// /// The location of the file to read the queue from. public void LoadQueueFromFile(string file) { string appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"HandBrake\hb_queue_recovery.xml"); string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : file; if (File.Exists(tempPath)) { using (FileStream strm = new FileStream(tempPath, FileMode.Open, FileAccess.Read)) { if (strm.Length != 0) { if (serializer == null) serializer = new XmlSerializer(typeof(List)); List list = serializer.Deserialize(strm) as List; if (list != null) foreach (Job item in list) queue.Add(item); if (file != "hb_queue_recovery.xml") WriteQueueStateToFile("hb_queue_recovery.xml"); } } } } /// /// 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 CheckForDestinationDuplicate(string destination) { foreach (Job checkItem in queue) { if (checkItem.Destination.Contains(destination.Replace("\\\\", "\\"))) return true; } return false; } #endregion #region Encoding /// /// Gets the last encode that was processed. /// /// public Job LastEncode { get; set; } /// /// Request Pause /// public Boolean PauseRequested { get; private set; } /// /// Starts encoding the first job in the queue and continues encoding until all jobs /// have been encoded. /// public void Start() { if (this.Count != 0) { if (PauseRequested) PauseRequested = false; else { PauseRequested = false; try { Thread theQueue = new Thread(StartQueue) { IsBackground = true }; theQueue.Start(); } catch (Exception exc) { MessageBox.Show(exc.ToString()); } } } } /// /// Requests a pause of the encode queue. /// public void Pause() { PauseRequested = true; if (QueuePauseRequested != null) QueuePauseRequested(this, new EventArgs()); } /// /// Run through all the jobs on the queue. /// /// private void StartQueue(object state) { // Run through each item on the queue while (this.Count != 0) { Job encJob = GetNextJob(); string query = encJob.Query; WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file Run(query); HbProcess.WaitForExit(); AddCLIQueryToLog(encJob); CopyLog(LastEncode.Destination); HbProcess.Close(); HbProcess.Dispose(); IsEncoding = false; //Growl if (Properties.Settings.Default.growlEncode) GrowlCommunicator.Notify("Encode Completed", "Put down that cocktail...\nyour Handbrake encode is done."); while (PauseRequested) // Need to find a better way of doing this. { Thread.Sleep(2000); } } LastEncode = new Job(); if (QueueCompleted != null) QueueCompleted(this, new EventArgs()); // After the encode is done, we may want to shutdown, suspend etc. Finish(); } #endregion } }