OSDN Git Service

WinGui:
authorsr55 <sr55@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 27 Feb 2010 22:20:14 +0000 (22:20 +0000)
committersr55 <sr55@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Sat, 27 Feb 2010 22:20:14 +0000 (22:20 +0000)
- Checkin some missing files.

git-svn-id: svn://localhost/HandBrake/trunk@3145 b64f7644-9d1e-0410-96f1-a4d463321fa5

win/C#/Services/Encode.cs [new file with mode: 0644]
win/C#/Services/Queue.cs [new file with mode: 0644]
win/C#/Services/Scan.cs [new file with mode: 0644]

diff --git a/win/C#/Services/Encode.cs b/win/C#/Services/Encode.cs
new file mode 100644 (file)
index 0000000..d73a4a6
--- /dev/null
@@ -0,0 +1,537 @@
+/*  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
diff --git a/win/C#/Services/Queue.cs b/win/C#/Services/Queue.cs
new file mode 100644 (file)
index 0000000..59b1437
--- /dev/null
@@ -0,0 +1,387 @@
+/*  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
diff --git a/win/C#/Services/Scan.cs b/win/C#/Services/Scan.cs
new file mode 100644 (file)
index 0000000..aae87a0
--- /dev/null
@@ -0,0 +1,265 @@
+/*  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