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