// --------------------------------------------------------------------------------------------------------------------
//
// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License.
//
//
// Background Service Connector.
// HandBrake has the ability to connect to a service app that will control HandBrakeCLI or Libhb.
// This acts as process isolation.
//
// --------------------------------------------------------------------------------------------------------------------
namespace HandBrakeWPF.Isolation
{
using System;
using System.Diagnostics;
using System.ServiceModel;
using System.Threading;
using HandBrake.ApplicationServices.EventArgs;
using HandBrake.ApplicationServices.Services.Interfaces;
using HandBrakeWPF.Services.Interfaces;
///
/// Background Service Connector.
/// HandBrake has the ability to connect to a service app that will control HandBrakeCLI or Libhb.
/// This acts as process isolation.
///
public class BackgroundServiceConnector : IHbServiceCallback, IDisposable
{
#region Constants and Fields
///
/// The error service.
///
private readonly IErrorService errorService;
///
/// The user setting service.
///
private readonly IUserSettingService userSettingService;
///
/// Gets or sets the pipe factory.
/// DuplexChannelFactory is necessary for Callbacks.
///
private static DuplexChannelFactory pipeFactory;
///
/// The background process.
///
private static Process backgroundProcess;
#endregion
#region Properties
///
/// Initializes a new instance of the class.
///
///
/// The error service.
///
///
/// The user Setting Service.
///
public BackgroundServiceConnector(IErrorService errorService, IUserSettingService userSettingService)
{
this.errorService = errorService;
this.userSettingService = userSettingService;
}
///
/// Gets or sets a value indicating whether is connected.
///
public bool IsConnected { get; set; }
///
/// Gets or sets the service.
///
public IServerService Service { get; set; }
#endregion
#region Public Server Management Methods
///
/// The can connect.
///
///
/// The System.Boolean.
///
public bool CanConnect()
{
return true;
}
///
/// The connect.
///
public void Connect()
{
string port = this.userSettingService.GetUserSetting(UserSettingConstants.ServerPort);
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(
new InstanceContext(this),
new NetTcpBinding(),
new EndpointAddress(string.Format("net.tcp://127.0.0.1:{0}/IHbService", port)));
// Connect and Subscribe to the Server
Service = pipeFactory.CreateChannel();
Service.Subscribe();
IsConnected = true;
}
catch (Exception exc)
{
Caliburn.Micro.Execute.OnUIThread(() => this.errorService.ShowError("Unable to connect to background worker service", "Please restart HandBrake", exc));
}
});
}
///
/// The disconnect.
///
public void Disconnect()
{
try
{
if (backgroundProcess != null && !backgroundProcess.HasExited)
{
Service.Unsubscribe();
}
}
catch (Exception exc)
{
this.errorService.ShowError("Unable to disconnect from service", "It may have already close. Check for any left over HandBrake.Server.exe processes", exc);
}
}
#endregion
#region Public Service Methods
/////
///// The scan source.
/////
/////
///// The path.
/////
/////
///// The title.
/////
/////
///// The preview count.
/////
//public void ScanSource(string path, int title, int previewCount)
//{
// ThreadPool.QueueUserWorkItem(delegate { this.Service.ScanSource(path, title, previewCount); });
//}
/////
///// The stop scan.
/////
//public void StopScan()
//{
// ThreadPool.QueueUserWorkItem(delegate { this.Service.StopScan(); });
//}
/////
///// Start an Encode
/////
/////
///// The job.
/////
/////
///// The enable logging.
/////
//public void StartEncode(QueueTask job, bool enableLogging)
//{
// ThreadPool.QueueUserWorkItem(delegate { this.Service.StartEncode(job, enableLogging); });
//}
/////
///// Stop an Encode
/////
//public void StopEncode()
//{
// ThreadPool.QueueUserWorkItem(delegate { this.Service.StopEncode(); });
//}
#endregion
#region Implemented Interfaces
#region IDisposable
///
/// The dispose.
///
public void Dispose()
{
Service.Unsubscribe();
}
#endregion
#region IHbServiceCallback
///
/// The scan completed.
///
///
/// The event args.
///
public virtual void ScanCompletedCallback(ScanCompletedEventArgs eventArgs)
{
}
///
/// The scan progress.
///
///
/// The event args.
///
public virtual void ScanProgressCallback(ScanProgressEventArgs eventArgs)
{
}
///
/// The scan started callback.
///
public virtual void ScanStartedCallback()
{
}
///
/// The encode progress callback.
///
///
/// The event Args.
///
public virtual void EncodeProgressCallback(EncodeProgressEventArgs eventArgs)
{
}
///
/// The encode completed callback.
///
///
/// The event Args.
///
public virtual void EncodeCompletedCallback(EncodeCompletedEventArgs eventArgs)
{
}
///
/// The encode started callback.
///
public virtual void EncodeStartedCallback()
{
}
#endregion
#endregion
}
}