// -------------------------------------------------------------------------------------------------------------------- // // 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.ServiceModel; using System.Threading; using HandBrake.ApplicationServices.Model; using HandBrake.ApplicationServices.Services.Encode; using HandBrake.ApplicationServices.Services.Encode.EventArgs; using HandBrake.ApplicationServices.Services.Encode.Interfaces; using HandBrake.ApplicationServices.Services.Interfaces; /// /// 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 host. /// private static ServiceHost host; /// /// The shutdown flag. /// private static ManualResetEvent shutdownFlag; #endregion #region Properties /// /// Gets the activity log. /// public string EncodeActivityLog { get; private set; } /// /// Gets a value indicating whether is encoding. /// public bool IsEncoding { get; private set; } /// /// Gets the activity log. /// public string ScanActivityLog { get; private set; } #endregion #region Implemented Interfaces #region IServerService /// /// The process encode logs. /// /// /// The destination. /// /// /// The configuration. /// public void ProcessEncodeLogs(string destination, HBConfiguration configuration) { encodeService.ProcessLogs(destination, configuration); } /// /// 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. encodeService = new LibEncode(); shutdownFlag = new ManualResetEvent(false); shutdownFlag.WaitOne(); } } /// /// Start and Encode /// /// /// The job. /// public void StartEncode(QueueTask job) { 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); } /// /// 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(); } /// /// 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 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 } }