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