diff options
Diffstat (limited to 'win/CS/HandBrake.ApplicationServices/Isolation')
3 files changed, 615 insertions, 0 deletions
diff --git a/win/CS/HandBrake.ApplicationServices/Isolation/BackgroundServiceConnector.cs b/win/CS/HandBrake.ApplicationServices/Isolation/BackgroundServiceConnector.cs new file mode 100644 index 000000000..4044e8a61 --- /dev/null +++ b/win/CS/HandBrake.ApplicationServices/Isolation/BackgroundServiceConnector.cs @@ -0,0 +1,214 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="BackgroundServiceConnector.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Background Service Connector.
+// HandBrake has the ability to connect to a service app that will control HandBrakeCLI or Libhb.
+// This acts as process isolation.
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrake.ApplicationServices.Isolation
+{
+ using System;
+ using System.Diagnostics;
+ using System.ServiceModel;
+ using System.Threading;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Exceptions;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+
+ /// <summary>
+ /// Background Service Connector.
+ /// HandBrake has the ability to connect to a service app that will control HandBrakeCLI or Libhb.
+ /// This acts as process isolation.
+ /// </summary>
+ public class BackgroundServiceConnector : IHbServiceCallback, IDisposable
+ {
+ #region Constants and Fields
+
+ /// <summary>
+ /// Gets or sets the pipe factory.
+ /// DuplexChannelFactory is necessary for Callbacks.
+ /// </summary>
+ private static DuplexChannelFactory<IServerService> pipeFactory;
+
+ /// <summary>
+ /// The background process.
+ /// </summary>
+ private static Process backgroundProcess;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets or sets a value indicating whether is connected.
+ /// </summary>
+ public bool IsConnected { get; set; }
+
+ /// <summary>
+ /// Gets or sets the service.
+ /// </summary>
+ public IServerService Service { get; set; }
+
+ #endregion
+
+ #region Public Server Management Methods
+
+ /// <summary>
+ /// The can connect.
+ /// </summary>
+ /// <returns>
+ /// The System.Boolean.
+ /// </returns>
+ public bool CanConnect()
+ {
+ return true;
+ }
+
+ /// <summary>
+ /// The connect.
+ /// </summary>
+ /// <param name="port">
+ /// The port.
+ /// </param>
+ public void Connect(string port)
+ {
+ if (backgroundProcess == null)
+ {
+ ProcessStartInfo processStartInfo = new ProcessStartInfo(
+ "HandBrake.Server.exe", port)
+ {
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ RedirectStandardOutput = true,
+ };
+
+ backgroundProcess = new Process { StartInfo = processStartInfo };
+ backgroundProcess.Start();
+ }
+
+ // When the process writes out a line, it's pipe server is ready and can be contacted for
+ // work. Reading line blocks until this happens.
+ backgroundProcess.StandardOutput.ReadLine();
+
+ ThreadPool.QueueUserWorkItem(delegate
+ {
+ try
+ {
+ pipeFactory = new DuplexChannelFactory<IServerService>(
+ new InstanceContext(this),
+ new NetTcpBinding(),
+ new EndpointAddress(string.Format("net.tcp://127.0.0.1:{0}/IHbService", port)));
+
+ // Connect and Subscribe to the Server
+ this.Service = pipeFactory.CreateChannel();
+ this.Service.Subscribe();
+ this.IsConnected = true;
+ }
+ catch (Exception exc)
+ {
+ throw new GeneralApplicationException("Unable to connect to background worker process", "Please restart HandBrake", exc);
+ }
+ });
+ }
+
+ /// <summary>
+ /// The disconnect.
+ /// </summary>
+ public void Shutdown()
+ {
+ try
+ {
+ if (backgroundProcess != null && !backgroundProcess.HasExited)
+ {
+ this.Service.Unsubscribe();
+ }
+ }
+ catch (Exception exc)
+ {
+ throw new GeneralApplicationException("Unable to disconnect to background worker process",
+ "It may have already close. Check for any left over HandBrake.Server.exe processes", exc);
+ }
+ }
+
+ #endregion
+
+ #region Implemented Interfaces
+
+ #region IDisposable
+
+ /// <summary>
+ /// The dispose.
+ /// </summary>
+ public void Dispose()
+ {
+ this.Service.Unsubscribe();
+ }
+
+ #endregion
+
+ #region IHbServiceCallback
+
+ /// <summary>
+ /// The scan completed.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event args.
+ /// </param>
+ public virtual void ScanCompletedCallback(ScanCompletedEventArgs eventArgs)
+ {
+ }
+
+ /// <summary>
+ /// The scan progress.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event args.
+ /// </param>
+ public virtual void ScanProgressCallback(ScanProgressEventArgs eventArgs)
+ {
+ }
+
+ /// <summary>
+ /// The scan started callback.
+ /// </summary>
+ public virtual void ScanStartedCallback()
+ {
+ }
+
+ /// <summary>
+ /// The encode progress callback.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event Args.
+ /// </param>
+ public virtual void EncodeProgressCallback(EncodeProgressEventArgs eventArgs)
+ {
+ }
+
+ /// <summary>
+ /// The encode completed callback.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event Args.
+ /// </param>
+ public virtual void EncodeCompletedCallback(EncodeCompletedEventArgs eventArgs)
+ {
+ }
+
+ /// <summary>
+ /// The encode started callback.
+ /// </summary>
+ public virtual void EncodeStartedCallback()
+ {
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
\ No newline at end of file diff --git a/win/CS/HandBrake.ApplicationServices/Isolation/IsolatedEncodeService.cs b/win/CS/HandBrake.ApplicationServices/Isolation/IsolatedEncodeService.cs new file mode 100644 index 000000000..6806e2844 --- /dev/null +++ b/win/CS/HandBrake.ApplicationServices/Isolation/IsolatedEncodeService.cs @@ -0,0 +1,185 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="IsolatedEncodeService.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Isolated Scan Service
+// This is an implementation of the IEncode implementation that runs scans on a seperate process
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrake.ApplicationServices.Isolation
+{
+ using System;
+ using System.Threading;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Exceptions;
+ using HandBrake.ApplicationServices.Model;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+
+ /// <summary>
+ /// Isolated Scan Service.
+ /// This is an implementation of the IEncode implementation that runs scans on a seperate process
+ /// </summary>
+ public class IsolatedEncodeService : BackgroundServiceConnector, IEncode
+ {
+ #region Constructors and Destructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="IsolatedEncodeService"/> class.
+ /// </summary>
+ /// <param name="port">
+ /// The port.
+ /// </param>
+ public IsolatedEncodeService(string port)
+ {
+ try
+ {
+ if (this.CanConnect())
+ {
+ this.Connect(port);
+ }
+ }
+ catch (Exception exception)
+ {
+ throw new GeneralApplicationException("Unable to connect to scan worker process.", "Try restarting HandBrake", exception);
+ }
+ }
+
+ #endregion
+
+ #region Events
+
+ /// <summary>
+ /// The encode completed.
+ /// </summary>
+ public event EncodeCompletedStatus EncodeCompleted;
+
+ /// <summary>
+ /// The encode started.
+ /// </summary>
+ public event EventHandler EncodeStarted;
+
+ /// <summary>
+ /// The encode status changed.
+ /// </summary>
+ public event EncodeProgessStatus EncodeStatusChanged;
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets ActivityLog.
+ /// </summary>
+ public string ActivityLog
+ {
+ get
+ {
+ return this.IsConnected ? this.Service.EncodeActivityLog : "Unable to connect to background worker service ...";
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether IsEncoding.
+ /// </summary>
+ public bool IsEncoding
+ {
+ get
+ {
+ return this.IsConnected && this.Service.IsEncoding;
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// The encode completed callback.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event args.
+ /// </param>
+ public override void EncodeCompletedCallback(EncodeCompletedEventArgs eventArgs)
+ {
+ if (this.EncodeCompleted != null)
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.EncodeCompleted(this, eventArgs); });
+ }
+
+ base.EncodeCompletedCallback(eventArgs);
+ }
+
+ /// <summary>
+ /// The encode progress callback.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event args.
+ /// </param>
+ public override void EncodeProgressCallback(EncodeProgressEventArgs eventArgs)
+ {
+ if (this.EncodeStatusChanged != null)
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.EncodeStatusChanged(this, eventArgs); });
+ }
+
+ base.EncodeProgressCallback(eventArgs);
+ }
+
+ #endregion
+
+ #region Implemented Interfaces
+
+ #region IEncode
+
+ /// <summary>
+ /// Copy the log file to the desired destinations
+ /// </summary>
+ /// <param name="destination">
+ /// The destination.
+ /// </param>
+ public void ProcessLogs(string destination)
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.Service.ProcessEncodeLogs(destination); });
+ }
+
+ /// <summary>
+ /// Attempt to Safely kill a DirectRun() CLI
+ /// NOTE: This will not work with a MinGW CLI
+ /// Note: http://www.cygwin.com/ml/cygwin/2006-03/msg00330.html
+ /// </summary>
+ public void SafelyStop()
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.Service.StopEncode(); });
+ }
+
+ /// <summary>
+ /// Start with a LibHb EncodeJob Object
+ /// </summary>
+ /// <param name="job">
+ /// The job.
+ /// </param>
+ /// <param name="enableLogging">
+ /// The enable Logging.
+ /// </param>
+ public void Start(QueueTask job, bool enableLogging)
+ {
+ ThreadPool.QueueUserWorkItem(
+ delegate { this.Service.StartEncode(job, enableLogging); });
+ }
+
+ /// <summary>
+ /// Kill the CLI process
+ /// </summary>
+ public void Stop()
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.Service.StopEncode(); });
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
\ No newline at end of file diff --git a/win/CS/HandBrake.ApplicationServices/Isolation/IsolatedScanService.cs b/win/CS/HandBrake.ApplicationServices/Isolation/IsolatedScanService.cs new file mode 100644 index 000000000..dcef0cc44 --- /dev/null +++ b/win/CS/HandBrake.ApplicationServices/Isolation/IsolatedScanService.cs @@ -0,0 +1,216 @@ +// --------------------------------------------------------------------------------------------------------------------
+// <copyright file="IsolatedScanService.cs" company="HandBrake Project (http://handbrake.fr)">
+// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
+// </copyright>
+// <summary>
+// Isolated Scan Service
+// This is an implementation of the IScan implementation that runs scans on a seperate process
+// </summary>
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace HandBrake.ApplicationServices.Isolation
+{
+ using System;
+ using System.Threading;
+
+ using HandBrake.ApplicationServices.EventArgs;
+ using HandBrake.ApplicationServices.Exceptions;
+ using HandBrake.ApplicationServices.Parsing;
+ using HandBrake.ApplicationServices.Services.Interfaces;
+
+ /// <summary>
+ /// Isolated Scan Service.
+ /// This is an implementation of the IScan implementation that runs scans on a seperate process
+ /// </summary>
+ public class IsolatedScanService : BackgroundServiceConnector, IScan
+ {
+ #region Constants and Fields
+
+ /// <summary>
+ /// The post action.
+ /// </summary>
+ private Action<bool> postScanAction;
+
+ #endregion
+
+ #region Events
+
+ /// <summary>
+ /// The scan completed.
+ /// </summary>
+ public event ScanCompletedStatus ScanCompleted;
+
+ /// <summary>
+ /// The scan stared.
+ /// </summary>
+ public event EventHandler ScanStared;
+
+ /// <summary>
+ /// The scan status changed.
+ /// </summary>
+ public event ScanProgessStatus ScanStatusChanged;
+
+ #endregion
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="IsolatedScanService"/> class.
+ /// </summary>
+ /// <param name="port">
+ /// The port.
+ /// </param>
+ public IsolatedScanService(string port)
+ {
+ try
+ {
+ if (this.CanConnect())
+ {
+ this.Connect(port);
+ }
+ }
+ catch (Exception exception)
+ {
+ throw new GeneralApplicationException("Unable to connect to scan worker process.", "Try restarting HandBrake", exception);
+ }
+ }
+
+ #region Properties
+
+ /// <summary>
+ /// Gets ActivityLog.
+ /// </summary>
+ public string ActivityLog
+ {
+ get
+ {
+ return this.Service.ScanActivityLog;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether IsScanning.
+ /// </summary>
+ public bool IsScanning
+ {
+ get
+ {
+ return this.Service.IsScanning;
+ }
+ }
+
+ /// <summary>
+ /// Gets the Souce Data.
+ /// </summary>
+ public Source SouceData
+ {
+ get
+ {
+ return this.Service.SouceData;
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ /// <summary>
+ /// The scan completed callback.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event args.
+ /// </param>
+ public override void ScanCompletedCallback(ScanCompletedEventArgs eventArgs)
+ {
+ if (this.postScanAction != null)
+ {
+ this.postScanAction(true);
+ }
+
+ if (this.ScanCompleted != null)
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.ScanCompleted(this, eventArgs); });
+ }
+
+ base.ScanCompletedCallback(eventArgs);
+ }
+
+ /// <summary>
+ /// The scan progress callback.
+ /// </summary>
+ /// <param name="eventArgs">
+ /// The event args.
+ /// </param>
+ public override void ScanProgressCallback(ScanProgressEventArgs eventArgs)
+ {
+ if (this.ScanStatusChanged != null)
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.ScanStatusChanged(this, eventArgs); });
+ }
+
+ base.ScanProgressCallback(eventArgs);
+ }
+
+ /// <summary>
+ /// The scan started callback.
+ /// </summary>
+ public override void ScanStartedCallback()
+ {
+ if (this.ScanStared != null)
+ {
+ ThreadPool.QueueUserWorkItem(delegate { this.ScanStared(this, EventArgs.Empty); });
+ }
+
+ base.ScanStartedCallback();
+ }
+
+ #endregion
+
+ #region Implemented Interfaces
+
+ #region IScan
+
+ /// <summary>
+ /// Take a Scan Log file, and process it as if it were from the CLI.
+ /// </summary>
+ /// <param name="path">
+ /// The path to the log file.
+ /// </param>
+ public void DebugScanLog(string path)
+ {
+ throw new NotImplementedException("Not available in process isolation mode!");
+ }
+
+ /// <summary>
+ /// Scan a Source Path.
+ /// Title 0: scan all
+ /// </summary>
+ /// <param name="sourcePath">
+ /// Path to the file to scan
+ /// </param>
+ /// <param name="title">
+ /// int title number. 0 for scan all
+ /// </param>
+ /// <param name="previewCount">
+ /// The preview Count.
+ /// </param>
+ /// <param name="postAction">
+ /// The post Action.
+ /// </param>
+ public void Scan(string sourcePath, int title, int previewCount, Action<bool> postAction)
+ {
+ this.postScanAction = postAction;
+ this.Service.ScanSource(sourcePath, title, previewCount);
+ }
+
+ /// <summary>
+ /// Kill the scan
+ /// </summary>
+ public void Stop()
+ {
+ this.Service.StopScan();
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
\ No newline at end of file |