/* Scan.cs $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ namespace HandBrake.ApplicationServices.Services { using System; using System.Diagnostics; using System.IO; using System.Text; using System.Threading; using System.Windows.Forms; using HandBrake.ApplicationServices.Functions; using HandBrake.ApplicationServices.Parsing; using HandBrake.ApplicationServices.Services.Interfaces; /// /// Scan a Source /// public class ScanService : IScan { /* Private Variables */ /// /// A Lock object /// private static readonly object locker = new object(); /// /// The CLI data parser /// private Parser readData; /// /// The Log Buffer /// private StringBuilder logBuffer; /// /// The line number thats been read to in the log file /// private int logFilePosition; /// /// The Process belonging to the CLI /// private Process hbProc; /* Event Handlers */ /// /// Scan has Started /// public event EventHandler ScanStared; /// /// Scan has completed /// public event EventHandler ScanCompleted; /// /// Scan process has changed to a new title /// public event EventHandler ScanStatusChanged; /* Properties */ /// /// Gets a value indicating whether IsScanning. /// public bool IsScanning { get; private set; } /// /// Gets the Scan Status. /// public string ScanStatus { get; private set; } /// /// Gets the Souce Data. /// public DVD SouceData { get; private set; } /// /// Gets ActivityLog. /// public string ActivityLog { get { if (IsScanning) return readData.Buffer.ToString(); if (logBuffer == null) { ResetLogReader(); ReadLastScanFile(); } return logBuffer != null ? logBuffer.ToString() : string.Empty; } } /* Public Methods */ /// /// Scan a Source Path. /// Title 0: scan all /// /// Path to the file to scan /// int title number. 0 for scan all public void Scan(string sourcePath, int title) { Thread t = new Thread(unused => this.ScanSource(sourcePath, title)); t.Start(); } /// /// Kill the scan /// public void Stop() { try { if (hbProc != null) hbProc.Kill(); } catch (Exception ex) { Main.ShowExceptiowWindow("Unable to kill HandBrakeCLI.exe \n" + "You may need to manually kill HandBrakeCLI.exe using the Windows Task Manager if it does not close automatically" + " within the next few minutes. ", ex.ToString()); } } /* Private Methods */ /// /// Start a scan for a given source path and title /// /// Path to the source file /// the title number to look at private void ScanSource(object sourcePath, int title) { try { IsScanning = true; if (this.ScanStared != null) this.ScanStared(this, new EventArgs()); ResetLogReader(); string handbrakeCLIPath = Path.Combine(Application.StartupPath, "HandBrakeCLI.exe"); string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; string dvdInfoPath = Path.Combine(logDir, string.Format("last_scan_log{0}.txt", Init.InstanceId)); // Make we don't pick up a stale last_encode_log.txt (and that we have rights to the file) if (File.Exists(dvdInfoPath)) File.Delete(dvdInfoPath); string extraArguments = string.Empty; if (Init.DisableDvdNav) extraArguments = " --no-dvdnav"; if (title > 0) extraArguments += " --scan "; this.hbProc = new Process { StartInfo = { FileName = handbrakeCLIPath, Arguments = String.Format(@" -i ""{0}"" -t{1} {2} -v ", sourcePath, title, extraArguments), RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true } }; // Start the Scan this.hbProc.Start(); this.readData = new Parser(this.hbProc.StandardError.BaseStream); this.readData.OnScanProgress += new ScanProgressEventHandler(this.OnScanProgress); this.SouceData = DVD.Parse(this.readData); // Write the Buffer out to file. StreamWriter scanLog = new StreamWriter(dvdInfoPath); scanLog.WriteLine(Logging.CreateCliLogHeader(null)); scanLog.Write(this.readData.Buffer); scanLog.Flush(); scanLog.Close(); logBuffer.AppendLine(this.readData.Buffer.ToString()); IsScanning = false; if (this.ScanCompleted != null) this.ScanCompleted(this, new EventArgs()); } catch (Exception exc) { Main.ShowExceptiowWindow("frmMain.cs - scanProcess() Error", exc.ToString()); } } /// /// Read the log file /// private void ReadLastScanFile() { lock (locker) { // 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), // we'll need to make a copy of it. string logDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\HandBrake\\logs"; string logFile = Path.Combine(logDir, string.Format("last_scan_log{0}.txt", Init.InstanceId)); string logFile2 = Path.Combine(logDir, string.Format("tmp_appReadable_log{0}.txt", Init.InstanceId)); try { // Make sure the application readable log file does not already exist. FileCopy fill fail if it does. if (File.Exists(logFile2)) File.Delete(logFile2); // Copy the log file. if (File.Exists(logFile)) File.Copy(logFile, logFile2, true); else { ResetLogReader(); return; } // Start the Reader // Only use text which continues on from the last read line StreamReader sr = new StreamReader(logFile2); string line; int i = 1; while ((line = sr.ReadLine()) != null) { if (i > logFilePosition) { logBuffer.AppendLine(line); logFilePosition++; } i++; } sr.Close(); sr.Dispose(); } catch (Exception exc) { Console.WriteLine(exc.ToString()); ResetLogReader(); } } } /// /// Reset the Log Reader /// private void ResetLogReader() { logFilePosition = 0; logBuffer = new StringBuilder(); logBuffer.AppendLine(Logging.CreateCliLogHeader(null)); } /// /// Fire an event when the scan process progresses /// /// the sender /// the current title being scanned /// the total number of titles private void OnScanProgress(object sender, int currentTitle, int titleCount) { this.ScanStatus = string.Format("Processing Title: {0} of {1}", currentTitle, titleCount); if (this.ScanStatusChanged != null) this.ScanStatusChanged(this, new EventArgs()); } } }