// --------------------------------------------------------------------------------------------------------------------
//
// 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
}
}