// -------------------------------------------------------------------------------------------------------------------- // // This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. // // // HandBrake WCF Service // // -------------------------------------------------------------------------------------------------------------------- namespace HandBrake.ApplicationServices.Services { using System; using System.Collections.Generic; using System.Runtime.Serialization; using System.ServiceModel; using System.Threading; using System.Windows; using HandBrake.ApplicationServices.EventArgs; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Parsing; using HandBrake.ApplicationServices.Services.Interfaces; using HandBrake.Interop; using HandBrake.Interop.Interfaces; using EncodeCompletedEventArgs = HandBrake.ApplicationServices.EventArgs.EncodeCompletedEventArgs; using EncodeProgressEventArgs = HandBrake.ApplicationServices.EventArgs.EncodeProgressEventArgs; using ScanProgressEventArgs = HandBrake.ApplicationServices.EventArgs.ScanProgressEventArgs; /// /// HandBrake WCF Service /// [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, IncludeExceptionDetailInFaults = true, ConcurrencyMode = ConcurrencyMode.Single)] public class ServerService : IServerService { #region Constants and Fields /// /// List of connected Clients. For now, this should only be one. /// private static readonly List Subscribers = new List(); /// /// The encode service. /// private static IEncode encodeService; /// /// The scan service. /// private static IScan scanService; /// /// The host. /// private static ServiceHost host; /// /// The shutdown flag. /// private static ManualResetEvent shutdownFlag; #endregion #region Properties /// /// Gets the activity log. /// [DataMember] public string ActivityLog { get { return scanService.ActivityLog; } } /// /// Gets the activity log. /// public string EncodeActivityLog { get; private set; } /// /// Gets a value indicating whether is encoding. /// public bool IsEncoding { get; private set; } /// /// Gets a value indicating whether is scanning. /// [DataMember] public bool IsScanning { get { return scanService.IsScanning; } } /// /// Gets the activity log. /// public string ScanActivityLog { get; private set; } /// /// Gets the souce data. /// [DataMember] public Source SouceData { get { return scanService.SouceData; } } #endregion #region Implemented Interfaces #region IServerService /// /// The process encode logs. /// /// /// The destination. /// public void ProcessEncodeLogs(string destination) { encodeService.ProcessLogs(destination); } /// /// The scan source. /// /// /// The path. /// /// /// The title. /// /// /// The preview Count. /// public void ScanSource(string path, int title, int previewCount) { Console.WriteLine("Starting Source Scan for: " + path); scanService.ScanStared += this.ScanStaredHandler; scanService.ScanStatusChanged += this.ScanStatusChangedHandler; scanService.ScanCompleted += this.ScanCompletedHandler; scanService.Scan(path, title, previewCount, null); } /// /// Start the service /// /// /// The port. /// public void Start(string port) { using (host = new ServiceHost(typeof(ServerService), new Uri(string.Format("net.tcp://127.0.0.1:{0}", port)))) { // Setup a listener host.AddServiceEndpoint(typeof(IServerService), new NetTcpBinding(), "IHbService"); host.Open(); Console.WriteLine("::: HandBrake Isolation Server - Debug Console:::"); Console.WriteLine("Service Started. Waiting for Clients..."); // Setup the services we are going to use. IHandBrakeInstance instance = new HandBrakeInstance(); scanService = new LibScan(new UserSettingService(), instance); // TODO this needs wired up with castle encodeService = new LibEncode(new UserSettingService(), instance); shutdownFlag = new ManualResetEvent(false); shutdownFlag.WaitOne(); } } /// /// Start and Encode /// /// /// The job. /// /// /// The enable logging. /// public void StartEncode(QueueTask job, bool enableLogging) { Console.WriteLine("Starting Source Encode for: " + job.Task.Source); encodeService.EncodeCompleted += this.EncodeServiceEncodeCompleted; encodeService.EncodeStarted += this.encodeService_EncodeStarted; encodeService.EncodeStatusChanged += this.encodeService_EncodeStatusChanged; encodeService.Start(job, enableLogging); } /// /// Stop this service /// public void Stop() { if (host != null) { host.BeginClose(null, null); //host.Abort(); shutdownFlag.Set(); } } /// /// Stop and Encode /// public void StopEncode() { encodeService.Stop(); } /// /// Stop the scan. /// public void StopScan() { scanService.Stop(); } /// /// The subscribe. /// /// /// The System.Boolean. /// public bool Subscribe() { try { // Get the hashCode of the connecting app and store it as a connection var callback = OperationContext.Current.GetCallbackChannel(); if (!Subscribers.Contains(callback)) { Console.WriteLine("Client Connected"); Subscribers.Add(callback); } return true; } catch (Exception e) { Console.WriteLine(e.Message); return false; } } /// /// The unsubscribe. /// /// /// The System.Boolean. /// public bool Unsubscribe() { try { var callback = OperationContext.Current.GetCallbackChannel(); if (Subscribers.Contains(callback)) { Subscribers.Remove(callback); if (Subscribers.Count == 0) { Console.WriteLine("Client Disconnected, Shutting down..."); // Shutdown the service. We no longer have any clients to serve. // It is the responsibility of the UI to maintain a subscription while this service is in use. this.Stop(); } } return true; } catch { return false; } } #endregion #endregion #region Methods /// /// The scan service scan completed event handler /// /// /// The sender. /// /// /// The e. /// private void ScanCompletedHandler(object sender, ScanCompletedEventArgs e) { Subscribers.ForEach( delegate(IHbServiceCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { Console.WriteLine("Scan Completed Callback"); callback.ScanCompletedCallback(e); } else { Subscribers.Remove(callback); } }); scanService.ScanStared -= this.ScanStaredHandler; scanService.ScanStatusChanged -= this.ScanStatusChangedHandler; scanService.ScanCompleted -= this.ScanCompletedHandler; } /// /// The scan service scan stared. /// /// /// The sender. /// /// /// The e. /// private void ScanStaredHandler(object sender, EventArgs e) { Subscribers.ForEach( delegate(IHbServiceCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { Console.WriteLine("Scan Started Callback"); callback.ScanStartedCallback(); } else { Subscribers.Remove(callback); } }); } /// /// The scan service scan status changed event handler /// /// /// The sender. /// /// /// The e. /// private void ScanStatusChangedHandler(object sender, ScanProgressEventArgs e) { Subscribers.ForEach( delegate(IHbServiceCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { Console.WriteLine("Scan Changed Callback"); callback.ScanProgressCallback(e); } else { Subscribers.Remove(callback); } }); } /// /// The encode service_ encode completed. /// /// /// The sender. /// /// /// The e. /// private void EncodeServiceEncodeCompleted(object sender, EncodeCompletedEventArgs e) { encodeService.EncodeCompleted -= this.EncodeServiceEncodeCompleted; encodeService.EncodeStarted -= this.encodeService_EncodeStarted; encodeService.EncodeStatusChanged -= this.encodeService_EncodeStatusChanged; Subscribers.ForEach( delegate(IHbServiceCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { Console.WriteLine("Encode Completed Callback"); callback.EncodeCompletedCallback(e); } else { Subscribers.Remove(callback); } }); } /// /// The encode service_ encode started. /// /// /// The sender. /// /// /// The e. /// private void encodeService_EncodeStarted(object sender, EventArgs e) { Subscribers.ForEach( delegate(IHbServiceCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { Console.WriteLine("Encode Started Callback"); callback.EncodeStartedCallback(); } else { Subscribers.Remove(callback); } }); } /// /// The encode service_ encode status changed. /// /// /// The sender. /// /// /// The e. /// private void encodeService_EncodeStatusChanged(object sender, EncodeProgressEventArgs e) { Subscribers.ForEach( delegate(IHbServiceCallback callback) { if (((ICommunicationObject)callback).State == CommunicationState.Opened) { Console.WriteLine("Encode Status Callback"); callback.EncodeProgressCallback(e); } else { Subscribers.Remove(callback); } }); } #endregion } }