// -------------------------------------------------------------------------------------------------------------------- // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // // // LibHB Implementation of IEncode // // -------------------------------------------------------------------------------------------------------------------- namespace HandBrake.ApplicationServices.Services { using System; using System.Diagnostics; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Services.Base; using HandBrake.ApplicationServices.Services.Interfaces; using HandBrake.ApplicationServices.Utilities; using HandBrake.Interop; using HandBrake.Interop.EventArgs; using HandBrake.Interop.Interfaces; using HandBrake.Interop.Model; using EncodeCompletedEventArgs = HandBrake.ApplicationServices.EventArgs.EncodeCompletedEventArgs; using EncodeProgressEventArgs = HandBrake.ApplicationServices.EventArgs.EncodeProgressEventArgs; /// /// LibHB Implementation of IEncode /// public class LibEncode : EncodeBase, IEncode { #region Private Variables /// /// Lock for the log file /// private static readonly object LogLock = new object(); /// /// The instance. /// private IHandBrakeInstance instance; /// /// The Start time of the current Encode; /// private DateTime startTime; /// /// A flag to indicate if logging is enabled or not. /// private bool loggingEnabled; /// /// The Current Task /// private QueueTask currentTask; #endregion /// /// Initializes a new instance of the class. /// public LibEncode() { HandBrakeUtils.MessageLogged += this.HandBrakeInstanceMessageLogged; HandBrakeUtils.ErrorLogged += this.HandBrakeInstanceErrorLogged; } /// /// Gets a value indicating whether can pause. /// public bool CanPause { get { return true; } } /// /// Gets a value indicating whether is pasued. /// public bool IsPasued { get; private set; } /// /// Start with a LibHb EncodeJob Object /// /// /// The job. /// public void Start(QueueTask job) { // Setup this.startTime = DateTime.Now; this.loggingEnabled = job.Configuration.IsLoggingEnabled; this.currentTask = job; // Create a new HandBrake instance // Setup the HandBrake Instance instance = new HandBrakeInstance(); instance.Initialize(1); instance.EncodeCompleted += this.InstanceEncodeCompleted; instance.EncodeProgress += this.InstanceEncodeProgress; try { // Sanity Checking and Setup if (this.IsEncoding) { throw new Exception("HandBrake is already encoding."); } this.IsEncoding = true; // Enable logging if required. if (job.Configuration.IsLoggingEnabled) { try { this.SetupLogging(job); } catch (Exception) { this.IsEncoding = false; throw; } } // Verify the Destination Path Exists, and if not, create it. this.VerifyEncodeDestinationPath(job); // We have to scan the source again but only the title so the HandBrake instance is initialised correctly. // Since the UI sends the crop params down, we don't have to do all the previews. instance.StartScan(job.Task.Source, job.Configuration.PreviewScanCount, job.Task.Title); instance.ScanCompleted += delegate { ScanCompleted(job, instance); }; } catch (Exception exc) { this.InvokeEncodeCompleted(new EncodeCompletedEventArgs(false, exc, "An Error has occured.", this.currentTask.Task.Destination)); } } /// /// Pause the currently running encode. /// public void Pause() { if (this.instance != null) { this.instance.PauseEncode(); this.IsPasued = true; } } /// /// Resume the currently running encode. /// public void Resume() { if (this.instance != null) { this.instance.ResumeEncode(); this.IsPasued = false; } } /// /// Kill the CLI process /// public override void Stop() { try { this.IsEncoding = false; this.instance.StopEncode(); } catch (Exception) { // Do Nothing. } } /// /// Shutdown the service. /// public void Shutdown() { // Nothing to do for this implementation. } /// /// The scan completed. /// /// /// The job. /// /// /// The instance. /// private void ScanCompleted(QueueTask job, IHandBrakeInstance instance) { // Get an EncodeJob object for the Interop Library EncodeJob encodeJob = InteropModelCreator.GetEncodeJob(job); // Start the Encode instance.StartEncode(encodeJob, job.Configuration.PreviewScanCount); // Fire the Encode Started Event this.InvokeEncodeStarted(EventArgs.Empty); // Set the Process Priority switch (job.Configuration.ProcessPriority) { case "Realtime": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime; break; case "High": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High; break; case "Above Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.AboveNormal; break; case "Normal": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Normal; break; case "Low": Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.Idle; break; default: Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal; break; } } #region HandBrakeInstance Event Handlers. /// /// Log a message /// /// /// The sender. /// /// /// The MessageLoggedEventArgs. /// private void HandBrakeInstanceErrorLogged(object sender, MessageLoggedEventArgs e) { if (this.loggingEnabled) { lock (LogLock) { this.ProcessLogMessage(e.Message); } } } /// /// Log a message /// /// /// The sender. /// /// /// The MessageLoggedEventArgs. /// private void HandBrakeInstanceMessageLogged(object sender, MessageLoggedEventArgs e) { if (this.loggingEnabled) { lock (LogLock) { this.ProcessLogMessage(e.Message); } } } /// /// Encode Progress Event Handler /// /// /// The sender. /// /// /// The Interop.EncodeProgressEventArgs. /// private void InstanceEncodeProgress(object sender, Interop.EventArgs.EncodeProgressEventArgs e) { EncodeProgressEventArgs args = new EncodeProgressEventArgs { AverageFrameRate = e.AverageFrameRate, CurrentFrameRate = e.CurrentFrameRate, EstimatedTimeLeft = e.EstimatedTimeLeft, PercentComplete = e.FractionComplete * 100, Task = e.Pass, ElapsedTime = DateTime.Now - this.startTime, }; this.InvokeEncodeStatusChanged(args); } /// /// Encode Completed Event Handler /// /// /// The sender. /// /// /// The e. /// private void InstanceEncodeCompleted(object sender, Interop.EventArgs.EncodeCompletedEventArgs e) { this.IsEncoding = false; this.InvokeEncodeCompleted( e.Error ? new EncodeCompletedEventArgs(false, null, string.Empty, this.currentTask.Task.Destination) : new EncodeCompletedEventArgs(true, null, string.Empty, this.currentTask.Task.Destination)); this.ShutdownFileWriter(); } #endregion } }