OSDN Git Service

WinGui:
[handbrake-jp/handbrake-jp-git.git] / win / C# / HandBrake.ApplicationServices / Services / Encode.cs
index 1731d48..4a6333d 100644 (file)
@@ -6,31 +6,26 @@
 namespace HandBrake.ApplicationServices.Services\r
 {\r
     using System;\r
+    using System.ComponentModel;\r
     using System.Diagnostics;\r
     using System.IO;\r
     using System.Text;\r
     using System.Threading;\r
     using System.Windows.Forms;\r
 \r
+    using HandBrake.ApplicationServices.EventArgs;\r
     using HandBrake.ApplicationServices.Functions;\r
     using HandBrake.ApplicationServices.Model;\r
     using HandBrake.ApplicationServices.Parsing;\r
-    using HandBrake.ApplicationServices.Properties;\r
     using HandBrake.ApplicationServices.Services.Interfaces;\r
-\r
-    using Timer = System.Threading.Timer;\r
+    using HandBrake.ApplicationServices.Utilities;\r
 \r
     /// <summary>\r
     /// Class which handles the CLI\r
     /// </summary>\r
     public class Encode : IEncode\r
     {\r
-        /* Private Variables */\r
-\r
-        /// <summary>\r
-        /// An Encode Job\r
-        /// </summary>\r
-        private Job job;\r
+        #region Private Variables\r
 \r
         /// <summary>\r
         /// The Log Buffer\r
@@ -38,14 +33,9 @@ namespace HandBrake.ApplicationServices.Services
         private StringBuilder logBuffer;\r
 \r
         /// <summary>\r
-        /// The line number thats been read to in the log file\r
+        /// The Log file writer\r
         /// </summary>\r
-        private int logFilePosition;\r
-\r
-        /// <summary>\r
-        /// A Timer for this window\r
-        /// </summary>\r
-        private Timer windowTimer;\r
+        private StreamWriter fileWriter;\r
 \r
         /// <summary>\r
         /// Gets The Process Handle\r
@@ -55,54 +45,48 @@ namespace HandBrake.ApplicationServices.Services
         /// <summary>\r
         /// Gets the Process ID\r
         /// </summary>\r
-        private int processID;\r
+        private int processId;\r
 \r
         /// <summary>\r
         /// Windows 7 API Pack wrapper\r
         /// </summary>\r
         private Win7 windowsSeven = new Win7();\r
 \r
-        /* Constructor */\r
+        /// <summary>\r
+        /// A Lock for the filewriter\r
+        /// </summary>\r
+        static readonly object fileWriterLock = new object();\r
+\r
+        #endregion\r
 \r
         /// <summary>\r
         /// Initializes a new instance of the <see cref="Encode"/> class.\r
         /// </summary>\r
         public Encode()\r
         {\r
-            this.EncodeStarted += Encode_EncodeStarted;\r
+            this.EncodeStarted += this.EncodeEncodeStarted;\r
+            GrowlCommunicator.Register();\r
         }\r
 \r
-        /* Delegates */\r
+        #region Delegates and Event Handlers\r
 \r
         /// <summary>\r
-        /// Encode Progess Status\r
-        /// </summary>\r
-        /// <param name="sender">\r
-        /// The sender.\r
-        /// </param>\r
-        /// <param name="e">\r
-        /// The EncodeProgressEventArgs.\r
-        /// </param>\r
-        public delegate void EncodeProgessStatus(object sender, EncodeProgressEventArgs e);\r
-\r
-        /* Event Handlers */\r
-\r
-        /// <summary>\r
-        /// Fires when a new CLI Job starts\r
+        /// Fires when a new CLI QueueTask starts\r
         /// </summary>\r
         public event EventHandler EncodeStarted;\r
 \r
         /// <summary>\r
-        /// Fires when a CLI job finishes.\r
+        /// Fires when a CLI QueueTask finishes.\r
         /// </summary>\r
-        public event EventHandler EncodeEnded;\r
+        public event EncodeCompletedStatus EncodeCompleted;\r
 \r
         /// <summary>\r
         /// Encode process has progressed\r
         /// </summary>\r
         public event EncodeProgessStatus EncodeStatusChanged;\r
+        #endregion\r
 \r
-        /* Properties */\r
+        #region Properties\r
 \r
         /// <summary>\r
         /// Gets or sets The HB Process\r
@@ -114,8 +98,6 @@ namespace HandBrake.ApplicationServices.Services
         /// </summary>\r
         public bool IsEncoding { get; private set; }\r
 \r
-        /* Public Methods */\r
-\r
         /// <summary>\r
         /// Gets ActivityLog.\r
         /// </summary>\r
@@ -123,307 +105,212 @@ namespace HandBrake.ApplicationServices.Services
         {\r
             get\r
             {\r
-                if (logBuffer == null)\r
+                if (this.IsEncoding == false)\r
                 {\r
-                    ResetLogReader();\r
-                    ReadFile(null);\r
+                    try\r
+                    {\r
+                        ReadFile(); // Read the last log file back in if it exists\r
+                    }\r
+                    catch (Exception exc)\r
+                    {\r
+                        return exc.ToString();\r
+                    }\r
                 }\r
 \r
-                return logBuffer != null ? logBuffer.ToString() : string.Empty;\r
+                return string.IsNullOrEmpty(this.logBuffer.ToString()) ? "No log data available..." : this.logBuffer.ToString();\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
-            this.Run(new Job { Query = query }, true);\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
-\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
+        #endregion\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
+        #region Public Methods\r
 \r
         /// <summary>\r
         /// Execute a HandBrakeCLI process.\r
         /// </summary>\r
-        /// <param name="encJob">\r
-        /// The enc Job.\r
+        /// <param name="encodeQueueTask">\r
+        /// The encodeQueueTask.\r
         /// </param>\r
-        /// <param name="requireStandardOuput">\r
-        /// Set to True to show no window and force standard output redirect\r
+        /// <param name="enableLogging">\r
+        /// Enable Logging. When Disabled we onlt parse Standard Ouput for progress info. Standard Error log data is ignored.\r
         /// </param>\r
-        protected void Run(Job encJob, bool requireStandardOuput)\r
+        public void Start(QueueTask encodeQueueTask, bool enableLogging)\r
         {\r
-            this.job = encJob;\r
             try\r
             {\r
-                if (Properties.Settings.Default.preventSleep)\r
+                QueueTask queueTask = encodeQueueTask;\r
+\r
+                if (queueTask == null)\r
                 {\r
-                    Win32.PreventSleep();\r
+                    throw new ArgumentNullException("QueueTask was null");\r
                 }\r
 \r
-                ResetLogReader();\r
-                IsEncoding = true;\r
-\r
-                string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");\r
-                string logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs", "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 || requireStandardOuput)\r
+                if (IsEncoding)\r
                 {\r
-                    cliStart.RedirectStandardOutput = true;\r
-                    cliStart.UseShellExecute = false;\r
-                    if (!Settings.Default.showCliForInGuiEncodeStatus || requireStandardOuput)\r
-                        cliStart.CreateNoWindow = true;\r
+                    throw new Exception("HandBrake is already encodeing.");\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
-                HbProcess = Process.Start(cliStart);\r
-                this.processID = Main.GetCliProcess(before);\r
-\r
-                this.processHandle = HbProcess.MainWindowHandle; // Set the process Handle\r
-\r
-                // Start the Log Monitor\r
-                windowTimer = new Timer(new TimerCallback(ReadFile), null, 1000, 1000);\r
+                IsEncoding = true;\r
 \r
-                // Set the process Priority\r
-                Process hbCliProcess = null;\r
-                if (this.processID != -1)\r
+                if (enableLogging)\r
                 {\r
-                    hbCliProcess = Process.GetProcessById(this.processID);\r
-                    hbCliProcess.EnableRaisingEvents = true;\r
-                    hbCliProcess.Exited += new EventHandler(HbProcess_Exited);\r
-                }\r
-\r
-                if (hbCliProcess != null)\r
-                    switch (Settings.Default.processPriority)\r
+                    try\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
+                        SetupLogging(queueTask);\r
                     }\r
+                    catch (Exception)\r
+                    {\r
+                        IsEncoding = false;\r
+                        throw;\r
+                    }\r
+                }\r
 \r
-                // Fire the Encode Started Event\r
-                if (this.EncodeStarted != null)\r
-                    this.EncodeStarted(this, new EventArgs());\r
-            }\r
-            catch (Exception exc)\r
-            {\r
-                Main.ShowExceptiowWindow("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()", exc.ToString());\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// The HandBrakeCLI process has exited.\r
-        /// </summary>\r
-        /// <param name="sender">\r
-        /// The sender.\r
-        /// </param>\r
-        /// <param name="e">\r
-        /// The EventArgs.\r
-        /// </param>\r
-        private void HbProcess_Exited(object sender, EventArgs e)\r
-        {\r
-            IsEncoding = false;\r
+                if (Init.PreventSleep)\r
+                {\r
+                    Win32.PreventSleep();\r
+                }\r
 \r
-            windowTimer.Dispose();\r
-            ReadFile(null);\r
+                string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe");\r
+                ProcessStartInfo cliStart = new ProcessStartInfo(handbrakeCLIPath, queueTask.Query)\r
+                {\r
+                    RedirectStandardOutput = true,\r
+                    RedirectStandardError = enableLogging ? true : false,\r
+                    UseShellExecute = false,\r
+                    CreateNoWindow = !Init.ShowCliForInGuiEncodeStatus ? true : false\r
+                };\r
 \r
-            if (this.EncodeEnded != null)\r
-                this.EncodeEnded(this, new EventArgs());\r
+                this.HbProcess = new Process { StartInfo = cliStart };\r
 \r
-            if (windowsSeven.IsWindowsSeven)\r
-            {\r
-                windowsSeven.SetTaskBarProgressToNoProgress();\r
-            }\r
+                this.HbProcess.Start();\r
 \r
-            if (Properties.Settings.Default.preventSleep)\r
-            {\r
-                Win32.AllowSleep();\r
-            }\r
-        }\r
+                if (enableLogging)\r
+                {\r
+                    this.HbProcess.ErrorDataReceived += HbProcErrorDataReceived;\r
+                    this.HbProcess.BeginErrorReadLine();\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
+                this.processId = HbProcess.Id;\r
+                this.processHandle = HbProcess.Handle;\r
 \r
-                IsEncoding = true;\r
+                // Set the process Priority\r
+                if (this.processId != -1)\r
+                {\r
+                    this.HbProcess.EnableRaisingEvents = true;\r
+                    this.HbProcess.Exited += this.HbProcessExited;\r
+                }\r
 \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
+                // Set the Process Priority\r
+                switch (Init.ProcessPriority)\r
                 {\r
                     case "Realtime":\r
-                        HbProcess.PriorityClass = ProcessPriorityClass.RealTime;\r
+                        this.HbProcess.PriorityClass = ProcessPriorityClass.RealTime;\r
                         break;\r
                     case "High":\r
-                        HbProcess.PriorityClass = ProcessPriorityClass.High;\r
+                        this.HbProcess.PriorityClass = ProcessPriorityClass.High;\r
                         break;\r
                     case "Above Normal":\r
-                        HbProcess.PriorityClass = ProcessPriorityClass.AboveNormal;\r
+                        this.HbProcess.PriorityClass = ProcessPriorityClass.AboveNormal;\r
                         break;\r
                     case "Normal":\r
-                        HbProcess.PriorityClass = ProcessPriorityClass.Normal;\r
+                        this.HbProcess.PriorityClass = ProcessPriorityClass.Normal;\r
                         break;\r
                     case "Low":\r
-                        HbProcess.PriorityClass = ProcessPriorityClass.Idle;\r
+                        this.HbProcess.PriorityClass = ProcessPriorityClass.Idle;\r
                         break;\r
                     default:\r
-                        HbProcess.PriorityClass = ProcessPriorityClass.BelowNormal;\r
+                        this.HbProcess.PriorityClass = ProcessPriorityClass.BelowNormal;\r
                         break;\r
                 }\r
 \r
-                // Set the class items\r
-                this.processID = HbProcess.Id;\r
-                this.processHandle = HbProcess.Handle;\r
+                // Fire the Encode Started Event\r
+                if (this.EncodeStarted != null)\r
+                    this.EncodeStarted(this, new EventArgs());\r
             }\r
             catch (Exception exc)\r
             {\r
-                Console.WriteLine(exc);\r
+                if (this.EncodeCompleted != null)\r
+                    this.EncodeCompleted(this, new EncodeCompletedEventArgs(false, exc, "An Error has occured in EncodeService.Run()"));\r
             }\r
         }\r
 \r
         /// <summary>\r
-        /// Add the CLI Query to the Log File.\r
+        /// Stop the Encode\r
         /// </summary>\r
-        /// <param name="encJob">\r
-        /// The Encode Job Object\r
+        public void Stop()\r
+        {\r
+            this.Stop(null);\r
+        }\r
+\r
+        /// <summary>\r
+        /// Kill the CLI process\r
+        /// </summary>\r
+        /// <param name="exc">\r
+        /// The Exception that has occured.\r
+        /// This will get bubbled up through the EncodeCompletedEventArgs\r
         /// </param>\r
-        protected void AddCLIQueryToLog(Job encJob)\r
+        public void Stop(Exception exc)\r
         {\r
             try\r
             {\r
-                string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) +\r
-                                "\\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
+                if (this.HbProcess != null && !this.HbProcess.HasExited)\r
+                {\r
+                    this.HbProcess.Kill();\r
+                }\r
+            }\r
+            catch (Exception)\r
+            {\r
+                // No need to report anything to the user. If it fails, it's probably already stopped.\r
+            }\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
+            if (exc == null)\r
+            {\r
+                if (this.EncodeCompleted != null)\r
+                    this.EncodeCompleted(this, new EncodeCompletedEventArgs(true, null, string.Empty));\r
             }\r
-            catch (Exception)\r
+            else\r
             {\r
-                return;\r
+                if (this.EncodeCompleted != null)\r
+                    this.EncodeCompleted(this, new EncodeCompletedEventArgs(false, exc, "An Error has occured."));\r
             }\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 SafelyStop()\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
+            /*/if (HbProcess != null)\r
+            //{\r
+            //    HbProcess.StandardInput.AutoFlush = true;\r
+            //    HbProcess.StandardInput.WriteLine("^c^z");\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
+        public void ProcessLogs(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
+                string tempLogFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", Init.InstanceId));\r
 \r
                 string encodeDestinationPath = Path.GetDirectoryName(destination);\r
                 string destinationFile = Path.GetFileName(destination);\r
@@ -438,113 +325,164 @@ namespace HandBrake.ApplicationServices.Services
                 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
+                if (Init.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
+                if (Directory.Exists(Init.SaveLogPath))\r
+                    if (Init.SaveLogPath != String.Empty && Init.SaveLogToSpecifiedPath)\r
+                        File.Copy(tempLogFile, Path.Combine(Init.SaveLogPath, encodeLogFile));\r
             }\r
             catch (Exception exc)\r
             {\r
-                Main.ShowExceptiowWindow("Unable to make a copy of the log file", exc.ToString());\r
+                // This exception doesn't warrent user interaction, but it should be logged (TODO)\r
             }\r
         }\r
 \r
+        #endregion\r
+\r
+        #region Private Helper Methods\r
+\r
         /// <summary>\r
-        /// Read the log file\r
+        /// The HandBrakeCLI process has exited.\r
         /// </summary>\r
-        /// <param name="n">\r
-        /// The object.\r
+        /// <param name="sender">\r
+        /// The sender.\r
         /// </param>\r
-        private void ReadFile(object n)\r
+        /// <param name="e">\r
+        /// The EventArgs.\r
+        /// </param>\r
+        private void HbProcessExited(object sender, EventArgs e)\r
+        {\r
+            IsEncoding = false;\r
+            if (windowsSeven.IsWindowsSeven)\r
+            {\r
+                windowsSeven.SetTaskBarProgressToNoProgress();\r
+            }\r
+\r
+            if (Init.PreventSleep)\r
+            {\r
+                Win32.AllowSleep();\r
+            }\r
+\r
+            try\r
+            {\r
+                lock (fileWriterLock)\r
+                {\r
+                    // This is just a quick hack to ensure that we are done processing the logging data.\r
+                    // Logging data comes in after the exit event has processed sometimes. We should really impliment ISyncronizingInvoke\r
+                    // and set the SyncObject on the process. I think this may resolve this properly.\r
+                    // For now, just wait 2.5 seconds to let any trailing log messages come in and be processed.\r
+                    Thread.Sleep(2500);\r
+\r
+                    this.HbProcess.CancelErrorRead();\r
+\r
+                    if (fileWriter != null)\r
+                    {\r
+                        fileWriter.Close();\r
+                        fileWriter.Dispose();\r
+                    }\r
+\r
+                    fileWriter = null;\r
+                }\r
+            }\r
+            catch (Exception exc)\r
+            {\r
+                // This exception doesn't warrent user interaction, but it should be logged (TODO)\r
+            }\r
+\r
+            if (this.EncodeCompleted != null)\r
+                this.EncodeCompleted(this, new EncodeCompletedEventArgs(true, null, string.Empty));\r
+        }\r
+\r
+        /// <summary>\r
+        /// Read the log file\r
+        /// </summary>\r
+        private void ReadFile()\r
         {\r
+            logBuffer = new StringBuilder();\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) +\r
-                                "\\HandBrake\\logs";\r
-                string logFile = Path.Combine(logDir, "last_encode_log.txt");\r
-                string logFile2 = Path.Combine(logDir, "tmp_appReadable_log.txt");\r
+                string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";\r
+                string logFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", Init.InstanceId));\r
+                string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", Init.InstanceId));\r
+                int logFilePosition = 0;\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 && job.Query != null)\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
+                    using (StreamReader sr = new StreamReader(logFile2))\r
                     {\r
-                        if (i > logFilePosition)\r
+                        string line;\r
+                        int i = 1;\r
+                        while ((line = sr.ReadLine()) != null)\r
                         {\r
-                            logBuffer.AppendLine(line);\r
-                            logFilePosition++;\r
+                            if (i > logFilePosition)\r
+                            {\r
+                                logBuffer.AppendLine(line);\r
+                                logFilePosition++;\r
+                            }\r
+                            i++;\r
                         }\r
-                        i++;\r
+                        sr.Close();\r
                     }\r
-                    sr.Close();\r
-                    sr.Dispose();\r
                 }\r
-                catch (Exception)\r
+                catch (Exception exc)\r
                 {\r
-                    ResetLogReader();\r
+                    logBuffer.Append(\r
+                        Environment.NewLine + "Unable to read Log file..." + Environment.NewLine + exc +\r
+                        Environment.NewLine);\r
                 }\r
             }\r
         }\r
 \r
         /// <summary>\r
-        /// Reset the Log Reader\r
+        /// Setup the logging.\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 name="encodeQueueTask">\r
+        /// The encode QueueTask.\r
         /// </param>\r
-        /// <param name="e">\r
-        /// DataReceived EventArgs\r
-        /// </param>\r
-        private void HbProcErrorDataReceived(object sender, DataReceivedEventArgs e)\r
+        private void SetupLogging(QueueTask encodeQueueTask)\r
         {\r
-            if (!String.IsNullOrEmpty(e.Data))\r
+            string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs";\r
+            string logFile = Path.Combine(logDir, string.Format("last_encode_log{0}.txt", Init.InstanceId));\r
+            string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", Init.InstanceId));\r
+\r
+            try\r
             {\r
-                lock (logBuffer)\r
-                    logBuffer.AppendLine(e.Data);\r
+                logBuffer = new StringBuilder();\r
+\r
+                // Clear the current Encode Logs\r
+                if (File.Exists(logFile)) File.Delete(logFile);\r
+                if (File.Exists(logFile2)) File.Delete(logFile2);\r
+\r
+                fileWriter = new StreamWriter(logFile) { AutoFlush = true };\r
+\r
+                fileWriter.WriteLine(UtilityService.CreateCliLogHeader(encodeQueueTask));\r
+                logBuffer.AppendLine(UtilityService.CreateCliLogHeader(encodeQueueTask));\r
+            }\r
+            catch (Exception)\r
+            {\r
+                if (fileWriter != null)\r
+                {\r
+                    fileWriter.Close();\r
+                    fileWriter.Dispose();\r
+                }\r
+                throw;\r
             }\r
         }\r
 \r
         /// <summary>\r
-        /// Standard Input Data Recieved from the CLI\r
+        /// Recieve the Standard Error information and process it\r
         /// </summary>\r
         /// <param name="sender">\r
         /// The Sender Object\r
@@ -552,12 +490,36 @@ namespace HandBrake.ApplicationServices.Services
         /// <param name="e">\r
         /// DataReceived EventArgs\r
         /// </param>\r
-        private void HbProcOutputDataReceived(object sender, DataReceivedEventArgs e)\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
+                try\r
+                {\r
+                    lock (logBuffer)\r
+                        logBuffer.AppendLine(e.Data);\r
+\r
+                    lock (fileWriterLock)\r
+                    {\r
+                        if (fileWriter != null && fileWriter.BaseStream.CanWrite)\r
+                        {\r
+                            fileWriter.WriteLine(e.Data);\r
+\r
+                            // If the logging grows past 100MB, kill the encode and stop.\r
+                            if (fileWriter.BaseStream.Length > 100000000)\r
+                            {\r
+                                this.Stop(\r
+                                    new Exception(\r
+                                        "The encode has been stopped. The log file has grown to over 100MB which indicates a serious problem has occured with the encode." +\r
+                                        "Please check the encode log for an indication of what the problem is."));\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+                catch (Exception exc)\r
+                {\r
+                    // Do Nothing.\r
+                }\r
             }\r
         }\r
 \r
@@ -570,14 +532,14 @@ namespace HandBrake.ApplicationServices.Services
         /// <param name="e">\r
         /// The EventArgs.\r
         /// </param>\r
-        private void Encode_EncodeStarted(object sender, EventArgs e)\r
+        private void EncodeEncodeStarted(object sender, EventArgs e)\r
         {\r
             Thread monitor = new Thread(EncodeMonitor);\r
             monitor.Start();\r
         }\r
 \r
         /// <summary>\r
-        /// Monitor the Job\r
+        /// Monitor the QueueTask\r
         /// </summary>\r
         private void EncodeMonitor()\r
         {\r
@@ -587,12 +549,10 @@ namespace HandBrake.ApplicationServices.Services
                 encode.OnEncodeProgress += EncodeOnEncodeProgress;\r
                 while (!encode.EndOfStream)\r
                     encode.ReadEncodeStatus();\r
-\r
-                // Main.ShowExceptiowWindow("Encode Monitor Stopped", "Stopped");\r
             }\r
             catch (Exception exc)\r
             {\r
-                Main.ShowExceptiowWindow("An Unknown Error has occured", exc.ToString());\r
+                EncodeOnEncodeProgress(null, 0, 0, 0, 0, 0, "Unknown, status not available..");\r
             }\r
         }\r
 \r
@@ -606,17 +566,17 @@ namespace HandBrake.ApplicationServices.Services
         /// <param name="currentFps">Current encode speed in fps</param>\r
         /// <param name="avg">Avg encode speed</param>\r
         /// <param name="timeRemaining">Time Left</param>\r
-        private void EncodeOnEncodeProgress(object sender, int currentTask, int taskCount, float percentComplete, float currentFps, float avg, TimeSpan timeRemaining)\r
+        private void EncodeOnEncodeProgress(object sender, int currentTask, int taskCount, float percentComplete, float currentFps, float avg, string timeRemaining)\r
         {\r
             EncodeProgressEventArgs eventArgs = new EncodeProgressEventArgs\r
-                {\r
-                    AverageFrameRate = avg,\r
-                    CurrentFrameRate = currentFps,\r
-                    EstimatedTimeLeft = timeRemaining,\r
-                    PercentComplete = percentComplete,\r
-                    Task = currentTask,\r
-                    TaskCount = taskCount\r
-                };\r
+            {\r
+                AverageFrameRate = avg,\r
+                CurrentFrameRate = currentFps,\r
+                EstimatedTimeLeft = Converters.EncodeToTimespan(timeRemaining),\r
+                PercentComplete = percentComplete,\r
+                Task = currentTask,\r
+                TaskCount = taskCount\r
+            };\r
 \r
             if (this.EncodeStatusChanged != null)\r
                 this.EncodeStatusChanged(this, eventArgs);\r
@@ -629,5 +589,7 @@ namespace HandBrake.ApplicationServices.Services
                 windowsSeven.SetTaskBarProgress(percent);\r
             }\r
         }\r
+\r
+        #endregion\r
     }\r
 }
\ No newline at end of file