--- /dev/null
+/* Encode.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
+\r
+namespace Handbrake.Services\r
+{\r
+ using System;\r
+ using System.Diagnostics;\r
+ using System.IO;\r
+ using System.Text;\r
+ using System.Threading;\r
+ using System.Windows.Forms;\r
+ using Functions;\r
+ using Model;\r
+ using Properties;\r
+ using Timer = System.Threading.Timer;\r
+\r
+ /// <summary>\r
+ /// Class which handles the CLI\r
+ /// </summary>\r
+ public class Encode\r
+ {\r
+ /// <summary>\r
+ /// An Encode Job\r
+ /// </summary>\r
+ private Job job;\r
+\r
+ /// <summary>\r
+ /// The Log Buffer\r
+ /// </summary>\r
+ private StringBuilder logBuffer;\r
+\r
+ /// <summary>\r
+ /// The line number thats been read to in the log file\r
+ /// </summary>\r
+ private int logFilePosition;\r
+\r
+ /// <summary>\r
+ /// A Timer for this window\r
+ /// </summary>\r
+ private Timer windowTimer;\r
+\r
+ /// <summary>\r
+ /// Fires when a new CLI Job starts\r
+ /// </summary>\r
+ public event EventHandler EncodeStarted;\r
+\r
+ /// <summary>\r
+ /// Fires when a CLI job finishes.\r
+ /// </summary>\r
+ public event EventHandler EncodeEnded;\r
+\r
+ /// <summary>\r
+ /// Gets or sets The HB Process\r
+ /// </summary>\r
+ public Process HbProcess { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets or sets The Process Handle\r
+ /// </summary>\r
+ public IntPtr ProcessHandle { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets or sets a value indicating whether HandBrakeCLI.exe is running\r
+ /// </summary>\r
+ public bool IsEncoding { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets or sets the Process ID\r
+ /// </summary>\r
+ public int ProcessID { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets ActivityLog.\r
+ /// </summary>\r
+ public string ActivityLog\r
+ {\r
+ get\r
+ {\r
+ if (logBuffer != null)\r
+ return logBuffer.ToString();\r
+\r
+ return string.Empty;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Create a preview sample video\r
+ /// </summary>\r
+ /// <param name="query">\r
+ /// The CLI Query\r
+ /// </param>\r
+ public void CreatePreviewSample(string query)\r
+ {\r
+ Job job = new Job {Query = query};\r
+ this.Run(job);\r
+ }\r
+\r
+ /// <summary>\r
+ /// Kill the CLI process\r
+ /// </summary>\r
+ public void Stop()\r
+ {\r
+ if (this.HbProcess != null)\r
+ this.HbProcess.Kill();\r
+\r
+ Process[] list = Process.GetProcessesByName("HandBrakeCLI");\r
+ foreach (Process process in list)\r
+ process.Kill();\r
+\r
+ if (this.EncodeEnded != null)\r
+ this.EncodeEnded(this, new EventArgs());\r
+\r
+ IsEncoding = false;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Attempt to Safely kill a DirectRun() CLI\r
+ /// NOTE: This will not work with a MinGW CLI\r
+ /// Note: http://www.cygwin.com/ml/cygwin/2006-03/msg00330.html\r
+ /// </summary>\r
+ public void SafelyClose()\r
+ {\r
+ if ((int)this.ProcessHandle == 0)\r
+ return;\r
+\r
+ // Allow the CLI to exit cleanly\r
+ Win32.SetForegroundWindow((int)this.ProcessHandle);\r
+ SendKeys.Send("^C");\r
+ SendKeys.Flush();\r
+\r
+ // HbProcess.StandardInput.AutoFlush = true;\r
+ // HbProcess.StandardInput.WriteLine("^C");\r
+\r
+ IsEncoding = false;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Execute a HandBrakeCLI process.\r
+ /// </summary>\r
+ /// <param name="encJob">\r
+ /// The enc Job.\r
+ /// </param>\r
+ protected void Run(Job encJob)\r
+ {\r
+ this.job = encJob;\r
+ try\r
+ {\r
+ if (this.EncodeStarted != null)\r
+ this.EncodeStarted(this, new EventArgs());\r
+\r
+ IsEncoding = true;\r
+\r
+ ResetLogReader();\r
+\r
+ string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");\r
+ string logPath =\r
+ Path.Combine(\r
+ Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs",\r
+ "last_encode_log.txt");\r
+ string strCmdLine = String.Format(@" /C """"{0}"" {1} 2>""{2}"" """, handbrakeCLIPath, encJob.Query, logPath);\r
+ var cliStart = new ProcessStartInfo("CMD.exe", strCmdLine);\r
+\r
+ if (Settings.Default.enocdeStatusInGui)\r
+ {\r
+ cliStart.RedirectStandardOutput = true;\r
+ cliStart.UseShellExecute = false;\r
+ if (!Settings.Default.showCliForInGuiEncodeStatus)\r
+ cliStart.CreateNoWindow = true;\r
+ }\r
+ if (Settings.Default.cli_minimized)\r
+ cliStart.WindowStyle = ProcessWindowStyle.Minimized;\r
+\r
+ Process[] before = Process.GetProcesses(); // Get a list of running processes before starting.\r
+ this.HbProcess = Process.Start(cliStart);\r
+ this.ProcessID = Main.GetCliProcess(before);\r
+\r
+\r
+ if (this.HbProcess != null)\r
+ this.ProcessHandle = this.HbProcess.MainWindowHandle; // Set the process Handle\r
+\r
+ // Start the Log Monitor\r
+ windowTimer = new Timer(new TimerCallback(ReadFile), null, 1000, 1000);\r
+\r
+ // Set the process Priority\r
+ Process hbCliProcess = null;\r
+ if (this.ProcessID != -1)\r
+ hbCliProcess = Process.GetProcessById(this.ProcessID);\r
+\r
+ if (hbCliProcess != null)\r
+ switch (Settings.Default.processPriority)\r
+ {\r
+ case "Realtime":\r
+ hbCliProcess.PriorityClass = ProcessPriorityClass.RealTime;\r
+ break;\r
+ case "High":\r
+ hbCliProcess.PriorityClass = ProcessPriorityClass.High;\r
+ break;\r
+ case "Above Normal":\r
+ hbCliProcess.PriorityClass = ProcessPriorityClass.AboveNormal;\r
+ break;\r
+ case "Normal":\r
+ hbCliProcess.PriorityClass = ProcessPriorityClass.Normal;\r
+ break;\r
+ case "Low":\r
+ hbCliProcess.PriorityClass = ProcessPriorityClass.Idle;\r
+ break;\r
+ default:\r
+ hbCliProcess.PriorityClass = ProcessPriorityClass.BelowNormal;\r
+ break;\r
+ }\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ MessageBox.Show(\r
+ "It would appear that HandBrakeCLI has not started correctly. You should take a look at the Activity log as it may indicate the reason why.\n\nDetailed Error Information: error occured in runCli()\n\n" +\r
+ exc,\r
+ "Error",\r
+ MessageBoxButtons.OK,\r
+ MessageBoxIcon.Error);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Function to run the CLI directly rather than via CMD\r
+ /// TODO: Code to handle the Log data has yet to be written.\r
+ /// TODO: Code to handle the % / ETA info has to be written.\r
+ /// </summary>\r
+ /// <param name="query">\r
+ /// The query.\r
+ /// </param>\r
+ protected void DirectRun(string query)\r
+ {\r
+ try\r
+ {\r
+ if (this.EncodeStarted != null)\r
+ this.EncodeStarted(this, new EventArgs());\r
+\r
+ IsEncoding = true;\r
+ ResetLogReader();\r
+\r
+ // Setup the job\r
+ string handbrakeCLIPath = Path.Combine(Environment.CurrentDirectory, "HandBrakeCLI.exe");\r
+ HbProcess = new Process\r
+ {\r
+ StartInfo =\r
+ {\r
+ FileName = handbrakeCLIPath,\r
+ Arguments = query,\r
+ UseShellExecute = false,\r
+ RedirectStandardOutput = true,\r
+ RedirectStandardError = true,\r
+ RedirectStandardInput = true,\r
+ CreateNoWindow = false,\r
+ WindowStyle = ProcessWindowStyle.Minimized\r
+ }\r
+ };\r
+\r
+ // Setup event handlers for rediected data\r
+ HbProcess.ErrorDataReceived += new DataReceivedEventHandler(HbProcErrorDataReceived);\r
+ HbProcess.OutputDataReceived += new DataReceivedEventHandler(HbProcOutputDataReceived);\r
+\r
+ // Start the process\r
+ HbProcess.Start();\r
+\r
+ // Setup the asynchronous reading of stdin and stderr\r
+ HbProcess.BeginErrorReadLine();\r
+ HbProcess.BeginOutputReadLine();\r
+\r
+ // Set the Process Priority);\r
+ switch (Settings.Default.processPriority)\r
+ {\r
+ case "Realtime":\r
+ HbProcess.PriorityClass = ProcessPriorityClass.RealTime;\r
+ break;\r
+ case "High":\r
+ HbProcess.PriorityClass = ProcessPriorityClass.High;\r
+ break;\r
+ case "Above Normal":\r
+ HbProcess.PriorityClass = ProcessPriorityClass.AboveNormal;\r
+ break;\r
+ case "Normal":\r
+ HbProcess.PriorityClass = ProcessPriorityClass.Normal;\r
+ break;\r
+ case "Low":\r
+ HbProcess.PriorityClass = ProcessPriorityClass.Idle;\r
+ break;\r
+ default:\r
+ HbProcess.PriorityClass = ProcessPriorityClass.BelowNormal;\r
+ break;\r
+ }\r
+\r
+ // Set the class items\r
+ this.ProcessID = HbProcess.Id;\r
+ this.ProcessHandle = HbProcess.Handle;\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ Console.WriteLine(exc);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Perform an action after an encode. e.g a shutdown, standby, restart etc.\r
+ /// </summary>\r
+ protected void Finish()\r
+ {\r
+ if (this.EncodeEnded != null)\r
+ this.EncodeEnded(this, new EventArgs());\r
+\r
+ IsEncoding = false;\r
+\r
+ if (!IsEncoding)\r
+ {\r
+ windowTimer.Dispose();\r
+ ReadFile(null);\r
+ }\r
+\r
+ // Growl\r
+ if (Settings.Default.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 (Settings.Default.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
+ /// <summary>\r
+ /// Add the CLI Query to the Log File.\r
+ /// </summary>\r
+ /// <param name="encJob">\r
+ /// The Encode Job Object\r
+ /// </param>\r
+ protected void AddCLIQueryToLog(Job encJob)\r
+ {\r
+ try\r
+ {\r
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";\r
+ string logPath = Path.Combine(logDir, "last_encode_log.txt");\r
+\r
+ var reader = new StreamReader(File.Open(logPath, FileMode.Open, FileAccess.Read, FileShare.Read));\r
+ string log = reader.ReadToEnd();\r
+ reader.Close();\r
+\r
+ var writer = new StreamWriter(File.Create(logPath));\r
+\r
+ writer.WriteLine("### CLI Query: " + encJob.Query);\r
+ writer.WriteLine("### User Query: " + encJob.CustomQuery);\r
+ writer.WriteLine("#########################################");\r
+ writer.WriteLine(log);\r
+ writer.Flush();\r
+ writer.Close();\r
+ }\r
+ catch (Exception)\r
+ {\r
+ return;\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Save a copy of the log to the users desired location or a default location\r
+ /// if this feature is enabled in options.\r
+ /// </summary>\r
+ /// <param name="destination">\r
+ /// The Destination File Path\r
+ /// </param>\r
+ protected void CopyLog(string destination)\r
+ {\r
+ try\r
+ {\r
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +\r
+ "\\HandBrake\\logs";\r
+ string tempLogFile = Path.Combine(logDir, "last_encode_log.txt");\r
+\r
+ string encodeDestinationPath = Path.GetDirectoryName(destination);\r
+ string destinationFile = Path.GetFileName(destination);\r
+ string encodeLogFile = destinationFile + " " +\r
+ DateTime.Now.ToString().Replace("/", "-").Replace(":", "-") + ".txt";\r
+\r
+ // Make sure the log directory exists.\r
+ if (!Directory.Exists(logDir))\r
+ Directory.CreateDirectory(logDir);\r
+\r
+ // Copy the Log to HandBrakes log folder in the users applciation data folder.\r
+ File.Copy(tempLogFile, Path.Combine(logDir, encodeLogFile));\r
+\r
+ // Save a copy of the log file in the same location as the enocde.\r
+ if (Settings.Default.saveLogWithVideo)\r
+ File.Copy(tempLogFile, Path.Combine(encodeDestinationPath, encodeLogFile));\r
+\r
+ // Save a copy of the log file to a user specified location\r
+ if (Directory.Exists(Settings.Default.saveLogPath))\r
+ if (Settings.Default.saveLogPath != String.Empty && Settings.Default.saveLogToSpecifiedPath)\r
+ File.Copy(tempLogFile, Path.Combine(Settings.Default.saveLogPath, encodeLogFile));\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ MessageBox.Show(\r
+ "Something went a bit wrong trying to copy your log file.\nError Information:\n\n" + exc,\r
+ "Error",\r
+ MessageBoxButtons.OK,\r
+ MessageBoxIcon.Error);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Read the log file\r
+ /// </summary>\r
+ /// <param name="n">\r
+ /// The object.\r
+ /// </param>\r
+ private void ReadFile(object n)\r
+ {\r
+ lock (logBuffer)\r
+ {\r
+ // last_encode_log.txt is the primary log file. Since .NET can't read this file whilst the CLI is outputing to it (Not even in read only mode),\r
+ // we'll need to make a copy of it.\r
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";\r
+ string logFile = Path.Combine(logDir, "last_encode_log.txt");\r
+ string logFile2 = Path.Combine(logDir, "tmp_appReadable_log.txt");\r
+\r
+ try\r
+ {\r
+ // Make sure the application readable log file does not already exist. FileCopy fill fail if it does.\r
+ if (File.Exists(logFile2))\r
+ File.Delete(logFile2);\r
+\r
+ // Copy the log file.\r
+ if (File.Exists(logFile))\r
+ File.Copy(logFile, logFile2, true);\r
+ else\r
+ {\r
+ ResetLogReader();\r
+ return;\r
+ }\r
+\r
+ // Put the Query and User Generated Query Flag on the log.\r
+ if (logFilePosition == 0)\r
+ {\r
+ logBuffer.AppendLine("### CLI Query: " + job.Query);\r
+ logBuffer.AppendLine("### User Query: " + job.CustomQuery);\r
+ logBuffer.AppendLine("#########################################");\r
+ }\r
+\r
+ // Start the Reader\r
+ // Only use text which continues on from the last read line\r
+ StreamReader sr = new StreamReader(logFile2);\r
+ string line;\r
+ int i = 1;\r
+ while ((line = sr.ReadLine()) != null)\r
+ {\r
+ if (i > logFilePosition)\r
+ {\r
+ logBuffer.AppendLine(line);\r
+ logFilePosition++;\r
+ }\r
+ i++;\r
+ }\r
+ sr.Close();\r
+ sr.Dispose();\r
+ }\r
+ catch (Exception)\r
+ {\r
+ ResetLogReader();\r
+ }\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Reset the Log Reader\r
+ /// </summary>\r
+ private void ResetLogReader()\r
+ {\r
+ logFilePosition = 0;\r
+ logBuffer = new StringBuilder();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Recieve the Standard Error information and process it\r
+ /// </summary>\r
+ /// <param name="sender">\r
+ /// The Sender Object\r
+ /// </param>\r
+ /// <param name="e">\r
+ /// DataReceived EventArgs\r
+ /// </param>\r
+ private void HbProcErrorDataReceived(object sender, DataReceivedEventArgs e)\r
+ {\r
+ if (!String.IsNullOrEmpty(e.Data))\r
+ {\r
+ lock (logBuffer)\r
+ logBuffer.AppendLine(e.Data);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Standard Input Data Recieved from the CLI\r
+ /// </summary>\r
+ /// <param name="sender">\r
+ /// The Sender Object\r
+ /// </param>\r
+ /// <param name="e">\r
+ /// DataReceived EventArgs\r
+ /// </param>\r
+ private void HbProcOutputDataReceived(object sender, DataReceivedEventArgs e)\r
+ {\r
+ if (!String.IsNullOrEmpty(e.Data))\r
+ {\r
+ lock (logBuffer)\r
+ logBuffer.AppendLine(e.Data);\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* 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
+\r
+namespace Handbrake.Services\r
+{\r
+ using System;\r
+ using System.Collections.Generic;\r
+ using System.Collections.ObjectModel;\r
+ using System.IO;\r
+ using System.Threading;\r
+ using System.Windows.Forms;\r
+ using System.Xml.Serialization;\r
+ using Functions;\r
+ using Model;\r
+\r
+ /// <summary>\r
+ /// The HandBrake Queue\r
+ /// </summary>\r
+ public class Queue : Encode\r
+ {\r
+ /// <summary>\r
+ /// An XML Serializer\r
+ /// </summary>\r
+ private static XmlSerializer serializer;\r
+\r
+ /// <summary>\r
+ /// The Queue Job List\r
+ /// </summary>\r
+ private readonly List<Job> queue = new List<Job>();\r
+\r
+ /// <summary>\r
+ /// The Next Job ID\r
+ /// </summary>\r
+ private int nextJobId;\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
+\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 Job GetNextJob()\r
+ {\r
+ Job 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.WriteQueueStateToFile("hb_queue_recovery.xml");\r
+\r
+ return job;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Gets the current state of the encode queue.\r
+ /// </summary>\r
+ public ReadOnlyCollection<Job> 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
+\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="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, string source, string destination, bool customJob)\r
+ {\r
+ Job newJob = new Job\r
+ {\r
+ Id = this.nextJobId++, \r
+ Query = query, \r
+ Source = source, \r
+ Destination = destination, \r
+ CustomQuery = customJob\r
+ };\r
+\r
+ this.queue.Add(newJob);\r
+ this.WriteQueueStateToFile("hb_queue_recovery.xml");\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.WriteQueueStateToFile("hb_queue_recovery.xml");\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 Job GetJob(int index)\r
+ {\r
+ if (this.queue.Count >= (index + 1))\r
+ return this.queue[index];\r
+\r
+ return new Job();\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
+ Job item = queue[index];\r
+\r
+ queue.RemoveAt(index);\r
+ queue.Insert((index - 1), item);\r
+ }\r
+\r
+ WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\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
+ Job item = this.queue[index];\r
+\r
+ this.queue.RemoveAt(index);\r
+ this.queue.Insert((index + 1), item);\r
+ }\r
+\r
+ this.WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery 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), \r
+ @"HandBrake\hb_queue_recovery.xml");\r
+ string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : 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<Job>));\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">The location of the file to write the batch file to.</param>\r
+ public void WriteBatchScriptToFile(string file)\r
+ {\r
+ string queries = string.Empty;\r
+ foreach (Job 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
+ MessageBox.Show("Your batch script has been sucessfully saved.", "Status", MessageBoxButtons.OK, \r
+ MessageBoxIcon.Asterisk);\r
+ }\r
+ catch (Exception)\r
+ {\r
+ MessageBox.Show(\r
+ "Unable to write to the file. Please make sure that the location has the correct permissions for file writing.", \r
+ "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);\r
+ }\r
+ }\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), \r
+ @"HandBrake\hb_queue_recovery.xml");\r
+ string tempPath = file == "hb_queue_recovery.xml" ? appDataPath : 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<Job>));\r
+\r
+ List<Job> list = serializer.Deserialize(strm) as List<Job>;\r
+\r
+ if (list != null)\r
+ foreach (Job item in list)\r
+ this.queue.Add(item);\r
+\r
+ if (file != "hb_queue_recovery.xml")\r
+ this.WriteQueueStateToFile("hb_queue_recovery.xml");\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
+ foreach (Job checkItem in this.queue)\r
+ {\r
+ if (checkItem.Destination.Contains(destination.Replace("\\\\", "\\")))\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ #endregion\r
+\r
+ #region Encoding\r
+\r
+ /// <summary>\r
+ /// Gets or sets the last encode that was processed.\r
+ /// </summary>\r
+ /// <returns></returns> \r
+ public Job LastEncode { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets a value indicating whether Request Pause\r
+ /// </summary>\r
+ public bool PauseRequested { get; private set; }\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.PauseRequested)\r
+ this.PauseRequested = false;\r
+ else\r
+ {\r
+ this.PauseRequested = false;\r
+ try\r
+ {\r
+ Thread theQueue = new Thread(this.StartQueue) {IsBackground = true};\r
+ theQueue.Start();\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ MessageBox.Show(exc.ToString());\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Requests a pause of the encode queue.\r
+ /// </summary>\r
+ public void Pause()\r
+ {\r
+ this.PauseRequested = 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
+ Job encJob = this.GetNextJob();\r
+ this.WriteQueueStateToFile("hb_queue_recovery.xml"); // Update the queue recovery file\r
+\r
+ Run(encJob);\r
+\r
+ if (HbProcess == null)\r
+ {\r
+ return;\r
+ }\r
+ HbProcess.WaitForExit();\r
+\r
+ AddCLIQueryToLog(encJob);\r
+ this.CopyLog(this.LastEncode.Destination);\r
+\r
+ HbProcess.Close();\r
+ HbProcess.Dispose();\r
+\r
+ IsEncoding = false;\r
+\r
+ // Growl\r
+ if (Properties.Settings.Default.growlEncode)\r
+ GrowlCommunicator.Notify("Encode Completed", \r
+ "Put down that cocktail...\nyour Handbrake encode is done.");\r
+\r
+ while (this.PauseRequested) // Need to find a better way of doing this.\r
+ {\r
+ Thread.Sleep(2000);\r
+ }\r
+ }\r
+ this.LastEncode = new Job();\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
+ #endregion\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* Scan.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.Services\r
+{\r
+ using System;\r
+ using System.Diagnostics;\r
+ using System.IO;\r
+ using System.Text;\r
+ using System.Threading;\r
+ using System.Windows.Forms;\r
+ using Parsing;\r
+\r
+ /// <summary>\r
+ /// Scan a Source\r
+ /// </summary>\r
+ public class Scan\r
+ {\r
+ /// <summary>\r
+ /// The information for this source\r
+ /// </summary>\r
+ private DVD thisDvd;\r
+\r
+ /// <summary>\r
+ /// The CLI data parser\r
+ /// </summary>\r
+ private Parser readData;\r
+\r
+ /// <summary>\r
+ /// The Log Buffer\r
+ /// </summary>\r
+ private StringBuilder logBuffer;\r
+\r
+ static object locker = new object();\r
+\r
+ /// <summary>\r
+ /// The line number thats been read to in the log file\r
+ /// </summary>\r
+ private int logFilePosition;\r
+\r
+ /// <summary>\r
+ /// The Process belonging to the CLI\r
+ /// </summary>\r
+ private Process hbProc;\r
+\r
+ /// <summary>\r
+ /// The Progress of the scan\r
+ /// </summary>\r
+ private string scanProgress;\r
+\r
+ /// <summary>\r
+ /// Scan has Started\r
+ /// </summary>\r
+ public event EventHandler ScanStared;\r
+\r
+ /// <summary>\r
+ /// Scan has completed\r
+ /// </summary>\r
+ public event EventHandler ScanCompleted;\r
+\r
+ /// <summary>\r
+ /// Scan process has changed to a new title\r
+ /// </summary>\r
+ public event EventHandler ScanStatusChanged;\r
+\r
+ /// <summary>\r
+ /// Gets or sets a value indicating whether IsScanning.\r
+ /// </summary>\r
+ public bool IsScanning { get; set; }\r
+\r
+ /// <summary>\r
+ /// Gets ActivityLog.\r
+ /// </summary>\r
+ public string ActivityLog\r
+ {\r
+ get\r
+ {\r
+ if (IsScanning)\r
+ return readData.Buffer;\r
+\r
+ ReadFile();\r
+ return logBuffer.ToString();\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Scan a Source Path.\r
+ /// Title 0: scan all\r
+ /// </summary>\r
+ /// <param name="sourcePath">Path to the file to scan</param>\r
+ /// <param name="title">int title number. 0 for scan all</param>\r
+ public void ScanSource(string sourcePath, int title)\r
+ {\r
+ Thread t = new Thread(unused => this.RunScan(sourcePath, title));\r
+ t.Start();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Object containing the information parsed in the scan.\r
+ /// </summary>\r
+ /// <returns>The DVD object containing the scan information</returns>\r
+ public DVD SouceData()\r
+ {\r
+ return this.thisDvd;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Progress of the scan.\r
+ /// </summary>\r
+ /// <returns>The progress of the scan</returns>\r
+ public string ScanStatus()\r
+ {\r
+ return this.scanProgress;\r
+ }\r
+\r
+ /// <summary>\r
+ /// The Scan Process\r
+ /// </summary>\r
+ /// <returns>The CLI process</returns>\r
+ public Process ScanProcess()\r
+ {\r
+ return this.hbProc;\r
+ }\r
+\r
+ /// <summary>\r
+ /// Start a scan for a given source path and title\r
+ /// </summary>\r
+ /// <param name="sourcePath">Path to the source file</param>\r
+ /// <param name="title">the title number to look at</param>\r
+ private void RunScan(object sourcePath, int title)\r
+ {\r
+ try\r
+ {\r
+ IsScanning = true;\r
+ if (this.ScanStared != null)\r
+ this.ScanStared(this, new EventArgs());\r
+\r
+ ResetLogReader();\r
+\r
+ string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");\r
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";\r
+ string dvdInfoPath = Path.Combine(logDir, "last_scan_log.txt");\r
+\r
+ // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file)\r
+ if (File.Exists(dvdInfoPath))\r
+ File.Delete(dvdInfoPath);\r
+\r
+ string dvdnav = string.Empty;\r
+ if (Properties.Settings.Default.noDvdNav)\r
+ dvdnav = " --no-dvdnav";\r
+\r
+ this.hbProc = new Process\r
+ {\r
+ StartInfo =\r
+ {\r
+ FileName = handbrakeCLIPath,\r
+ Arguments =\r
+ String.Format(@" -i ""{0}"" -t{1} {2} -v ", sourcePath, title, dvdnav),\r
+ RedirectStandardOutput = true,\r
+ RedirectStandardError = true,\r
+ UseShellExecute = false,\r
+ CreateNoWindow = true\r
+ }\r
+ };\r
+\r
+ // Start the Scan\r
+ this.hbProc.Start();\r
+\r
+ this.readData = new Parser(this.hbProc.StandardError.BaseStream);\r
+ this.readData.OnScanProgress += new ScanProgressEventHandler(this.OnScanProgress);\r
+ this.thisDvd = DVD.Parse(this.readData);\r
+\r
+ // Write the Buffer out to file.\r
+ StreamWriter scanLog = new StreamWriter(dvdInfoPath);\r
+ scanLog.Write(this.readData.Buffer);\r
+ scanLog.Flush();\r
+ scanLog.Close();\r
+\r
+ if (this.ScanCompleted != null)\r
+ this.ScanCompleted(this, new EventArgs());\r
+ IsScanning = false;\r
+ }\r
+ catch (Exception exc)\r
+ {\r
+ Console.WriteLine("frmMain.cs - scanProcess() " + exc);\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Read the log file\r
+ /// </summary>\r
+ private void ReadFile()\r
+ {\r
+ lock (locker)\r
+ {\r
+ // last_encode_log.txt is the primary log file. Since .NET can't read this file whilst the CLI is outputing to it (Not even in read only mode),\r
+ // we'll need to make a copy of it.\r
+ string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";\r
+ string logFile = Path.Combine(logDir, "last_scan_log.txt");\r
+ string logFile2 = Path.Combine(logDir, "tmp_appReadable_log.txt");\r
+\r
+ try\r
+ {\r
+ // Make sure the application readable log file does not already exist. FileCopy fill fail if it does.\r
+ if (File.Exists(logFile2))\r
+ File.Delete(logFile2);\r
+\r
+ // Copy the log file.\r
+ if (File.Exists(logFile))\r
+ File.Copy(logFile, logFile2, true);\r
+ else\r
+ {\r
+ ResetLogReader();\r
+ return;\r
+ }\r
+\r
+ // Start the Reader\r
+ // Only use text which continues on from the last read line\r
+ StreamReader sr = new StreamReader(logFile2);\r
+ string line;\r
+ int i = 1;\r
+ while ((line = sr.ReadLine()) != null)\r
+ {\r
+ if (i > logFilePosition)\r
+ {\r
+ logBuffer.AppendLine(line);\r
+ logFilePosition++;\r
+ }\r
+ i++;\r
+ }\r
+ sr.Close();\r
+ sr.Dispose();\r
+ }\r
+ catch (Exception)\r
+ {\r
+ ResetLogReader();\r
+ }\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// Reset the Log Reader\r
+ /// </summary>\r
+ private void ResetLogReader()\r
+ {\r
+ logFilePosition = 0;\r
+ logBuffer = new StringBuilder();\r
+ }\r
+\r
+ /// <summary>\r
+ /// Fire an event when the scan process progresses\r
+ /// </summary>\r
+ /// <param name="sender">the sender</param>\r
+ /// <param name="currentTitle">the current title being scanned</param>\r
+ /// <param name="titleCount">the total number of titles</param>\r
+ private void OnScanProgress(object sender, int currentTitle, int titleCount)\r
+ {\r
+ this.scanProgress = string.Format("Processing Title: {0} of {1}", currentTitle, titleCount);\r
+ if (this.ScanStatusChanged != null)\r
+ this.ScanStatusChanged(this, new EventArgs());\r
+ }\r
+ }\r
+}
\ No newline at end of file