diff options
author | sr55 <[email protected]> | 2020-03-31 20:24:58 +0100 |
---|---|---|
committer | sr55 <[email protected]> | 2020-03-31 20:25:09 +0100 |
commit | 83dde24b82284b287dc784582ebce06e4dcbfd74 (patch) | |
tree | 6384324da7dd1ad16e45b960a951d5d17babdce6 /win/CS | |
parent | f34280f1c619dae0b4e1a1ea09cea5b39f17d695 (diff) |
WinGui: Further work on the isolated process articecture.
Diffstat (limited to 'win/CS')
18 files changed, 369 insertions, 240 deletions
diff --git a/win/CS/HandBrake.Interop/Interop/Interfaces/IEncodeInstance.cs b/win/CS/HandBrake.Interop/Interop/Interfaces/IEncodeInstance.cs index 104983b8f..5a0957cb9 100644 --- a/win/CS/HandBrake.Interop/Interop/Interfaces/IEncodeInstance.cs +++ b/win/CS/HandBrake.Interop/Interop/Interfaces/IEncodeInstance.cs @@ -33,6 +33,9 @@ namespace HandBrake.Interop.Interop.Interfaces /// <param name="verbosity"> /// The code for the logging verbosity to use. /// </param> + /// <param name="noHardware"> + /// Turn off Hardware Acceleration + /// </param> void Initialize(int verbosity, bool noHardware); /// <summary> diff --git a/win/CS/HandBrake.Worker/HandBrake.Worker.csproj b/win/CS/HandBrake.Worker/HandBrake.Worker.csproj index f075859c0..f0ca5786d 100644 --- a/win/CS/HandBrake.Worker/HandBrake.Worker.csproj +++ b/win/CS/HandBrake.Worker/HandBrake.Worker.csproj @@ -45,15 +45,18 @@ </ItemGroup> <ItemGroup> <Compile Include="Routing\ApiRouter.cs" /> - <Compile Include="Registration\ConnectionRegistrar.cs" /> <Compile Include="HttpServer.cs" /> <Compile Include="Logging\Interfaces\ILogHandler.cs" /> <Compile Include="Logging\LogHandler.cs" /> <Compile Include="Logging\Models\LogMessage.cs" /> <Compile Include="Program.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="Registration\Model\ConnectionResult.cs" /> + <Compile Include="Routing\Commands\EncodeCommand.cs" /> + <Compile Include="Routing\Results\CommandResult.cs" /> + <Compile Include="Routing\Results\ConnectionResult.cs" /> + <Compile Include="Routing\Commands\InitCommand.cs" /> <Compile Include="Utilities\HttpUtilities.cs" /> + <Compile Include="Watcher\InstanceWatcher.cs" /> </ItemGroup> <ItemGroup> <None Include="App.config" /> diff --git a/win/CS/HandBrake.Worker/HttpServer.cs b/win/CS/HandBrake.Worker/HttpServer.cs index a2495ba39..3c9a36b37 100644 --- a/win/CS/HandBrake.Worker/HttpServer.cs +++ b/win/CS/HandBrake.Worker/HttpServer.cs @@ -32,15 +32,15 @@ namespace HandBrake.Worker // Store the Handlers this.apiHandlers = new Dictionary<string, Func<HttpListenerRequest, string>>(apiCalls); - Console.WriteLine(Environment.NewLine + "Available APIs: "); + Debug.WriteLine(Environment.NewLine + "Available APIs: "); foreach (KeyValuePair<string, Func<HttpListenerRequest, string>> api in apiCalls) { string url = string.Format("http://127.0.0.1:{0}/{1}/", port, api.Key); this.httpListener.Prefixes.Add(url); - Console.WriteLine(url); + Debug.WriteLine(url); } - Console.WriteLine(Environment.NewLine); + Debug.WriteLine(Environment.NewLine); this.httpListener.Start(); } @@ -66,7 +66,7 @@ namespace HandBrake.Worker { string path = context.Request.RawUrl.TrimStart('/').TrimEnd('/'); - Console.WriteLine("Handling call to: " + path); + Debug.WriteLine("Handling call to: " + path); if (this.apiHandlers.TryGetValue(path, out var actionToPerform)) { diff --git a/win/CS/HandBrake.Worker/Logging/Interfaces/ILogHandler.cs b/win/CS/HandBrake.Worker/Logging/Interfaces/ILogHandler.cs index eaa527ed6..f9601d94e 100644 --- a/win/CS/HandBrake.Worker/Logging/Interfaces/ILogHandler.cs +++ b/win/CS/HandBrake.Worker/Logging/Interfaces/ILogHandler.cs @@ -30,5 +30,7 @@ namespace HandBrake.Worker.Logging.Interfaces /// Empty the log cache and reset the log handler to defaults. /// </summary> void Reset(); + + void ShutdownFileWriter(); } } diff --git a/win/CS/HandBrake.Worker/Logging/LogHandler.cs b/win/CS/HandBrake.Worker/Logging/LogHandler.cs index b0f11c1e7..6a1f7bb6f 100644 --- a/win/CS/HandBrake.Worker/Logging/LogHandler.cs +++ b/win/CS/HandBrake.Worker/Logging/LogHandler.cs @@ -10,7 +10,10 @@ namespace HandBrake.Worker.Logging { + using System; using System.Collections.Generic; + using System.Diagnostics; + using System.IO; using System.Linq; using System.Text; @@ -21,15 +24,32 @@ namespace HandBrake.Worker.Logging public class LogHandler : ILogHandler { + private readonly string logFile; + private readonly object lockObject = new object(); + private readonly object fileWriterLock = new object(); + private readonly StringBuilder logBuilder = new StringBuilder(); private readonly List<LogMessage> logMessages = new List<LogMessage>(); private bool isLoggingEnabled = true; + private bool isDiskLoggingEnabled = false; private int messageIndex; + private StreamWriter fileWriter; - public LogHandler() + public LogHandler(string logDirectory, string logFileName, bool enableDiskLogging) { + this.isDiskLoggingEnabled = enableDiskLogging; + + if (this.isDiskLoggingEnabled) + { + lock (this.fileWriterLock) + { + // Todo Handle no log directory. + this.fileWriter = new StreamWriter(logFileName) { AutoFlush = true }; + } + } + HandBrakeUtils.MessageLogged += this.HandBrakeUtils_MessageLogged; HandBrakeUtils.ErrorLogged += this.HandBrakeUtils_ErrorLogged; } @@ -78,17 +98,20 @@ namespace HandBrake.Worker.Logging public void LogMessage(string content) { + Console.WriteLine(content); + if (!this.isLoggingEnabled) { return; } + LogMessage msg = new LogMessage(content, this.messageIndex); lock (this.lockObject) { - LogMessage msg = new LogMessage(content, this.messageIndex); this.messageIndex = this.messageIndex + 1; this.logMessages.Add(msg); this.logBuilder.AppendLine(msg.Content); + this.LogMessageToDisk(msg); if (this.logMessages.Count > 50000) { @@ -96,6 +119,7 @@ namespace HandBrake.Worker.Logging msg = new LogMessage("Log Service Pausing. Too Many Log messages. This may indicate a problem with your encode.", this.messageIndex); this.logMessages.Add(msg); this.logBuilder.AppendLine(msg.Content); + this.LogMessageToDisk(msg); this.isLoggingEnabled = false; } @@ -112,6 +136,51 @@ namespace HandBrake.Worker.Logging } } + public void ShutdownFileWriter() + { + try + { + lock (this.fileWriterLock) + { + if (this.fileWriter != null) + { + this.fileWriter.Flush(); + this.fileWriter.Close(); + this.fileWriter.Dispose(); + } + + this.fileWriter = null; + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); // This exception doesn't warrant user interaction, but it should be logged + } + } + + private void LogMessageToDisk(LogMessage msg) + { + if (!this.isDiskLoggingEnabled) + { + return; + } + + try + { + lock (this.fileWriterLock) + { + if (this.fileWriter != null && this.fileWriter.BaseStream.CanWrite) + { + this.fileWriter.WriteLine(msg.Content); + } + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); // This exception doesn't warrant user interaction, but it should be logged + } + } + private void HandBrakeUtils_ErrorLogged(object sender, MessageLoggedEventArgs e) { if (e == null || string.IsNullOrEmpty(e.Message)) diff --git a/win/CS/HandBrake.Worker/Program.cs b/win/CS/HandBrake.Worker/Program.cs index 326643d13..74114bd9e 100644 --- a/win/CS/HandBrake.Worker/Program.cs +++ b/win/CS/HandBrake.Worker/Program.cs @@ -12,22 +12,20 @@ namespace HandBrake.Worker using System; using System.Collections.Generic; using System.Net; + using System.Runtime.CompilerServices; using System.Threading; - using HandBrake.Worker.Registration; using HandBrake.Worker.Routing; public class Program { private static ApiRouter router; private static ManualResetEvent manualResetEvent = new ManualResetEvent(false); - private static ConnectionRegistrar registrar = new ConnectionRegistrar(); public static void Main(string[] args) { int port = 8037; // Default Port; - int verbosity = 1; - + if (args.Length != 0) { foreach (string argument in args) @@ -40,21 +38,12 @@ namespace HandBrake.Worker port = parsedPort; } } - - if (argument.StartsWith("--verbosity")) - { - string value = argument.TrimStart("--port=".ToCharArray()); - if (int.TryParse(value, out var verbosityVal)) - { - verbosity = verbosityVal; - } - } } } Console.WriteLine("Starting HandBrake Engine ..."); router = new ApiRouter(); - router.Initialise(verbosity); + router.TerminationEvent += Router_TerminationEvent; Console.WriteLine("Starting Web Server ..."); Console.WriteLine("Using Port: {0}", port); @@ -63,21 +52,21 @@ namespace HandBrake.Worker webServer.Run(); Console.WriteLine("Web Server Started"); - + manualResetEvent.WaitOne(); webServer.Stop(); } - public static Dictionary<string, Func<HttpListenerRequest, string>> RegisterApiHandlers() + private static Dictionary<string, Func<HttpListenerRequest, string>> RegisterApiHandlers() { Dictionary<string, Func<HttpListenerRequest, string>> apiHandlers = new Dictionary<string, Func<HttpListenerRequest, string>>(); - // Worker APIs - apiHandlers.Add("Pair", registrar.Pair); - apiHandlers.Add("GetToken", registrar.GetToken); + // Process Handling apiHandlers.Add("Shutdown", ShutdownServer); + apiHandlers.Add("GetInstanceToken", router.GetInstanceToken); + apiHandlers.Add("Version", router.GetVersionInfo); // Logging apiHandlers.Add("GetAllLogMessages", router.GetAllLogMessages); @@ -85,18 +74,21 @@ namespace HandBrake.Worker apiHandlers.Add("ResetLogging", router.ResetLogging); // HandBrake APIs - apiHandlers.Add("Version", router.GetVersionInfo); apiHandlers.Add("StartEncode", router.StartEncode); apiHandlers.Add("PauseEncode", router.PauseEncode); apiHandlers.Add("ResumeEncode", router.ResumeEncode); apiHandlers.Add("StopEncode", router.StopEncode); apiHandlers.Add("PollEncodeProgress", router.PollEncodeProgress); - apiHandlers.Add("SetConfiguration", router.SetConfiguration); return apiHandlers; } - public static string ShutdownServer(HttpListenerRequest request) + private static void Router_TerminationEvent(object sender, EventArgs e) + { + ShutdownServer(null); + } + + private static string ShutdownServer(HttpListenerRequest request) { manualResetEvent.Set(); return "Server Terminated"; diff --git a/win/CS/HandBrake.Worker/Registration/ConnectionRegistrar.cs b/win/CS/HandBrake.Worker/Registration/ConnectionRegistrar.cs deleted file mode 100644 index 6dca9d950..000000000 --- a/win/CS/HandBrake.Worker/Registration/ConnectionRegistrar.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -------------------------------------------------------------------------------------------------------------------- -// <copyright file="ConnectionRegistrar.cs" company="HandBrake Project (http://handbrake.fr)"> -// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. -// </copyright> -// <summary> -// Defines the ConnectionRegistrar type. -// </summary> -// <remarks> -// To be clear, this is NOT a security service! -// This service simply allows the UI to verify which worker process it is connected to. -// </remarks> -// -------------------------------------------------------------------------------------------------------------------- - -namespace HandBrake.Worker.Registration -{ - using System; - using System.Net; - - using HandBrake.Worker.Registration.Model; - using HandBrake.Worker.Utilities; - - using Newtonsoft.Json; - - public class ConnectionRegistrar - { - private readonly JsonSerializerSettings jsonNetSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; - private string token; - - public ConnectionRegistrar() - { - } - - public string Pair(HttpListenerRequest request) - { - string tokenKey = HttpUtilities.GetRequestPostData(request); - - - if (!string.IsNullOrEmpty(token)) - { - return JsonConvert.SerializeObject(new ConnectionResult(false, null, "Already Paired"), Formatting.Indented, this.jsonNetSettings); - } - - this.token = tokenKey; - - return JsonConvert.SerializeObject(new ConnectionResult(true, tokenKey, null), Formatting.Indented, this.jsonNetSettings); - } - - public string GetToken(HttpListenerRequest request) - { - return this.token; - } - } -} diff --git a/win/CS/HandBrake.Worker/Routing/ApiRouter.cs b/win/CS/HandBrake.Worker/Routing/ApiRouter.cs index a98f7413d..81267acb9 100644 --- a/win/CS/HandBrake.Worker/Routing/ApiRouter.cs +++ b/win/CS/HandBrake.Worker/Routing/ApiRouter.cs @@ -20,32 +20,27 @@ namespace HandBrake.Worker.Routing using HandBrake.Worker.Logging; using HandBrake.Worker.Logging.Interfaces; using HandBrake.Worker.Logging.Models; + using HandBrake.Worker.Routing.Commands; + using HandBrake.Worker.Routing.Results; using HandBrake.Worker.Utilities; + using HandBrake.Worker.Watcher; using Newtonsoft.Json; public class ApiRouter { + private readonly string token = Guid.NewGuid().ToString(); + private readonly JsonSerializerSettings jsonNetSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; private HandBrakeInstance handbrakeInstance; private ILogHandler logHandler; - private bool isLoggingConfigured = false; + private InstanceWatcher instanceWatcher; - public string Initialise(int verbosity) - { - if (this.handbrakeInstance == null) - { - this.handbrakeInstance = new HandBrakeInstance(); - } + public event EventHandler TerminationEvent; - if (this.logHandler == null) - { - this.logHandler = new LogHandler(); - } - - this.handbrakeInstance.Initialize(verbosity, true); - - return null; + public string GetInstanceToken(HttpListenerRequest request) + { + return JsonConvert.SerializeObject(token, Formatting.Indented, this.jsonNetSettings); } public string GetVersionInfo(HttpListenerRequest request) @@ -59,10 +54,18 @@ namespace HandBrake.Worker.Routing { string requestPostData = HttpUtilities.GetRequestPostData(request); - Console.WriteLine(requestPostData); - this.handbrakeInstance.StartEncode(requestPostData); + if (!string.IsNullOrEmpty(requestPostData)) + { + EncodeCommand command = JsonConvert.DeserializeObject<EncodeCommand>(requestPostData); - return null; + this.Initialise(command.InitialiseCommand); + + this.handbrakeInstance.StartEncode(command.EncodeJob); + + return JsonConvert.SerializeObject(new CommandResult() { WasSuccessful = true }, Formatting.Indented, this.jsonNetSettings); + } + + return JsonConvert.SerializeObject(new CommandResult() { WasSuccessful = false, Error = "No POST data" }, Formatting.Indented, this.jsonNetSettings); } public string StopEncode(HttpListenerRequest request) @@ -99,12 +102,6 @@ namespace HandBrake.Worker.Routing return null; } - public string SetConfiguration(HttpListenerRequest request) - { - return null; - } - - /* Logging API */ // GET @@ -112,8 +109,7 @@ namespace HandBrake.Worker.Routing { return JsonConvert.SerializeObject(this.logHandler.GetLogMessages(), Formatting.Indented, this.jsonNetSettings); } - - + // POST public string GetLogMessagesFromIndex(HttpListenerRequest request) { @@ -133,5 +129,42 @@ namespace HandBrake.Worker.Routing return null; } + + public void OnTerminationEvent() + { + this.TerminationEvent?.Invoke(this, EventArgs.Empty); + } + + private void HandbrakeInstance_EncodeCompleted(object sender, Interop.Interop.EventArgs.EncodeCompletedEventArgs e) + { + this.logHandler.ShutdownFileWriter(); + } + + private void Initialise(InitCommand command) + { + if (this.handbrakeInstance == null) + { + this.handbrakeInstance = new HandBrakeInstance(); + } + + if (this.logHandler == null) + { + this.logHandler = new LogHandler(command.LogDirectory, command.LogFile, command.EnableDiskLogging); + } + + if (!command.AllowDisconnectedWorker) + { + this.instanceWatcher = new InstanceWatcher(this); + this.instanceWatcher.Start(5000); + } + + this.handbrakeInstance.Initialize(command.LogVerbosity, command.EnableHardwareAcceleration); + this.handbrakeInstance.EncodeCompleted += this.HandbrakeInstance_EncodeCompleted; + + if (command.DisableLibDvdNav) + { + HandBrakeUtils.SetDvdNav(true); // TODO check this is correct + } + } } } diff --git a/win/CS/HandBrake.Worker/Routing/Commands/EncodeCommand.cs b/win/CS/HandBrake.Worker/Routing/Commands/EncodeCommand.cs new file mode 100644 index 000000000..0960609a1 --- /dev/null +++ b/win/CS/HandBrake.Worker/Routing/Commands/EncodeCommand.cs @@ -0,0 +1,20 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="EncodeCommand.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Defines the EncodeCommand type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Worker.Routing.Commands +{ + using HandBrake.Interop.Interop.Json.Encode; + + public class EncodeCommand + { + public InitCommand InitialiseCommand { get; set; } + + public JsonEncodeObject EncodeJob { get; set; } + } +} diff --git a/win/CS/HandBrake.Worker/Routing/Commands/InitCommand.cs b/win/CS/HandBrake.Worker/Routing/Commands/InitCommand.cs new file mode 100644 index 000000000..c1814de61 --- /dev/null +++ b/win/CS/HandBrake.Worker/Routing/Commands/InitCommand.cs @@ -0,0 +1,28 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="InitCommand.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Defines the InitCommand type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Worker.Routing.Commands +{ + public class InitCommand + { + public int LogVerbosity { get; set; } + + public string LogDirectory { get; set; } + + public string LogFile { get; set; } + + public bool EnableDiskLogging { get; set; } + + public bool EnableHardwareAcceleration { get; set; } + + public bool DisableLibDvdNav { get; set; } + + public bool AllowDisconnectedWorker { get; set; } + } +} diff --git a/win/CS/HandBrake.Worker/Routing/Results/CommandResult.cs b/win/CS/HandBrake.Worker/Routing/Results/CommandResult.cs new file mode 100644 index 000000000..624ab9d3e --- /dev/null +++ b/win/CS/HandBrake.Worker/Routing/Results/CommandResult.cs @@ -0,0 +1,17 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="CommandResult.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Defines the CommandResult type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Worker.Routing.Results +{ + public class CommandResult + { + public bool WasSuccessful { get; set; } + public string Error { get; set; } + } +} diff --git a/win/CS/HandBrake.Worker/Registration/Model/ConnectionResult.cs b/win/CS/HandBrake.Worker/Routing/Results/ConnectionResult.cs index d11c12cec..65a26660b 100644 --- a/win/CS/HandBrake.Worker/Registration/Model/ConnectionResult.cs +++ b/win/CS/HandBrake.Worker/Routing/Results/ConnectionResult.cs @@ -7,7 +7,7 @@ // </summary> // -------------------------------------------------------------------------------------------------------------------- -namespace HandBrake.Worker.Registration.Model +namespace HandBrake.Worker.Routing.Results { public class ConnectionResult { diff --git a/win/CS/HandBrake.Worker/Watcher/InstanceWatcher.cs b/win/CS/HandBrake.Worker/Watcher/InstanceWatcher.cs new file mode 100644 index 000000000..f50ca6c4b --- /dev/null +++ b/win/CS/HandBrake.Worker/Watcher/InstanceWatcher.cs @@ -0,0 +1,51 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="InstanceWatcher.cs" company="HandBrake Project (http://handbrake.fr)"> +// This file is part of the HandBrake source code - It may be used under the terms of the GNU General Public License. +// </copyright> +// <summary> +// Defines the InstanceWatcher type. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Worker.Watcher +{ + using System.Diagnostics; + using System.Timers; + + using HandBrake.Worker.Routing; + + public class InstanceWatcher + { + private readonly ApiRouter routerInstance; + + private Timer timer; + + public InstanceWatcher(ApiRouter routerInstance) + { + this.routerInstance = routerInstance; + } + + public void Start(int ms) + { + if (this.timer != null) + { + this.timer.Stop(); + } + + this.timer = new Timer(ms) { AutoReset = true }; + this.timer.Start(); + this.timer.Elapsed += this.Timer_Elapsed; + } + + private void Timer_Elapsed(object sender, ElapsedEventArgs e) + { + // Check if we are still attached to a UI. If not, terminate. + Process[] uiProcesses = Process.GetProcessesByName("HandBrake"); + if (uiProcesses.Length == 0) + { + this.routerInstance.StopEncode(null); + this.routerInstance.OnTerminationEvent(); + } + } + } +} diff --git a/win/CS/HandBrakeWPF/Instance/HandBrakeInstanceManager.cs b/win/CS/HandBrakeWPF/Instance/HandBrakeInstanceManager.cs index 914d7916f..f24ae527b 100644 --- a/win/CS/HandBrakeWPF/Instance/HandBrakeInstanceManager.cs +++ b/win/CS/HandBrakeWPF/Instance/HandBrakeInstanceManager.cs @@ -12,11 +12,13 @@ namespace HandBrakeWPF.Instance using System; using System.Runtime.CompilerServices; + using HandBrake.Interop.Interop; using HandBrake.Interop.Interop.Interfaces; using HandBrake.Interop.Model; using HandBrakeWPF.Factories; + using HandBrakeWPF.Services.Logging.Interfaces; /// <summary> /// The HandBrake Instance manager. @@ -36,19 +38,7 @@ namespace HandBrakeWPF.Instance HandBrakeUtils.EnsureGlobalInit(noHardwareMode); } - /// <summary> - /// The get encode instance. - /// </summary> - /// <param name="verbosity"> - /// The verbosity. - /// </param> - /// <param name="configuration"> - /// The configuration. - /// </param> - /// <returns> - /// The <see cref="IHandBrakeInstance"/>. - /// </returns> - public static IEncodeInstance GetEncodeInstance(int verbosity, HBConfiguration configuration) + public static IEncodeInstance GetEncodeInstance(int verbosity, HBConfiguration configuration, ILog logService) { if (!HandBrakeUtils.IsInitialised()) { @@ -65,7 +55,7 @@ namespace HandBrakeWPF.Instance if (configuration.RemoteServiceEnabled) { - newInstance = new RemoteInstance(configuration.RemoteServicePort); + newInstance = new RemoteInstance(configuration, logService); } else { diff --git a/win/CS/HandBrakeWPF/Instance/RemoteInstance.cs b/win/CS/HandBrakeWPF/Instance/RemoteInstance.cs index 36221da4d..dc52d0885 100644 --- a/win/CS/HandBrakeWPF/Instance/RemoteInstance.cs +++ b/win/CS/HandBrakeWPF/Instance/RemoteInstance.cs @@ -11,22 +11,22 @@ namespace HandBrakeWPF.Instance { using System; - using System.Collections.Generic; using System.Diagnostics; - using System.Linq; - using System.Net.Http; - using System.Net.Http.Headers; - using System.Runtime.CompilerServices; - using System.Text; + using System.IO; using System.Threading.Tasks; using System.Timers; + using System.Windows.Media.Animation; + using HandBrake.Interop.Interop.EventArgs; using HandBrake.Interop.Interop.Interfaces; using HandBrake.Interop.Interop.Json.Encode; using HandBrake.Interop.Interop.Json.State; + using HandBrake.Interop.Model; + using HandBrake.Worker.Routing.Commands; using HandBrakeWPF.Instance.Model; + using HandBrakeWPF.Services.Logging.Interfaces; using HandBrakeWPF.Utilities; using Newtonsoft.Json; @@ -42,14 +42,21 @@ namespace HandBrakeWPF.Instance public class RemoteInstance : HttpRequestBase, IEncodeInstance, IDisposable { - private const double EncodePollIntervalMs = 1000; + private readonly HBConfiguration configuration; + + private readonly ILog logService; + + private const double EncodePollIntervalMs = 250; private Process workerProcess; private Timer encodePollTimer; + private int retryCount = 0; - public RemoteInstance(int port) + public RemoteInstance(HBConfiguration configuration, ILog logService) { - this.port = port; + this.configuration = configuration; + this.logService = logService; + this.port = configuration.RemoteServicePort; this.serverUrl = string.Format("http://127.0.0.1:{0}/", this.port); } @@ -71,8 +78,20 @@ namespace HandBrakeWPF.Instance public async void StartEncode(JsonEncodeObject jobToStart) { + InitCommand initCommand = new InitCommand + { + EnableDiskLogging = true, + AllowDisconnectedWorker = false, + DisableLibDvdNav = this.configuration.IsDvdNavDisabled, + EnableHardwareAcceleration = true, + LogDirectory = DirectoryUtilities.GetLogDirectory(), + LogVerbosity = configuration.Verbosity + }; + + initCommand.LogFile = Path.Combine(initCommand.LogDirectory, string.Format("activity_log.worker.{0}.txt", GeneralUtilities.ProcessId)); + JsonSerializerSettings settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; - string job = JsonConvert.SerializeObject(jobToStart, Formatting.None, settings); + string job = JsonConvert.SerializeObject(new EncodeCommand { InitialiseCommand = initCommand, EncodeJob = jobToStart }, Formatting.None, settings); await this.MakeHttpJsonPostRequest("StartEncode", job); @@ -82,7 +101,6 @@ namespace HandBrakeWPF.Instance public async void StopEncode() { await this.MakeHttpGetRequest("StopEncode"); - this.StopPollingProgress(); } public JsonState GetEncodeProgress() @@ -103,34 +121,49 @@ namespace HandBrakeWPF.Instance public void Initialize(int verbosityLvl, bool noHardwareMode) { - this.StartServer(verbosityLvl, noHardwareMode); + this.StartServer(); } public void Dispose() { this.client?.Dispose(); this.workerProcess?.Dispose(); - this.StopEncode(); - this.StopServer(); } - private void StartServer(int verbosityLvl, bool noHardwareMode) + private async void StartServer() { if (this.workerProcess == null || this.workerProcess.HasExited) { - this.workerProcess = new Process(); - this.workerProcess.StartInfo = - new ProcessStartInfo("HandBrake.Worker.exe", string.Format("--port={0} --verbosity={1}", this.port, verbosityLvl)) - { - WindowStyle = ProcessWindowStyle.Normal - }; - - this.workerProcess.Start(); - this.workerProcess.Exited += this.WorkerProcess_Exited; - Debug.WriteLine("Worker Process Started. PID = {0}", this.workerProcess.Id); + workerProcess = new Process + { + StartInfo = + { + FileName = "HandBrake.Worker.exe", + Arguments = string.Format(" --port={0}", this.port), + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + } + }; + workerProcess.Exited += this.WorkerProcess_Exited; + workerProcess.OutputDataReceived += this.WorkerProcess_OutputDataReceived; + workerProcess.ErrorDataReceived += this.WorkerProcess_OutputDataReceived; + + workerProcess.Start(); + workerProcess.BeginOutputReadLine(); + workerProcess.BeginErrorReadLine(); + + + this.logService.LogMessage(string.Format("Worker Process started with Process ID: {0}", this.workerProcess.Id)); } } + private void WorkerProcess_OutputDataReceived(object sender, DataReceivedEventArgs e) + { + this.logService.LogMessage(e.Data); + } + private void MonitorEncodeProgress() { this.encodePollTimer = new Timer(); @@ -152,13 +185,13 @@ namespace HandBrakeWPF.Instance private void StopPollingProgress() { - this.PollEncodeProgress(); // Get the final progress state. + this.PollEncodeProgress(); // Get the last progress state. this.encodePollTimer?.Stop(); } private void WorkerProcess_Exited(object sender, EventArgs e) { - Debug.WriteLine("Worker Process has exited"); + this.logService.LogMessage("Worker Process Existed!"); } private void StopServer() @@ -174,18 +207,29 @@ namespace HandBrakeWPF.Instance ServerResponse response = null; try { + if (this.retryCount > 5) + { + this.EncodeCompleted?.Invoke(sender: this, e: new EncodeCompletedEventArgs(true)); + + this.encodePollTimer?.Stop(); + + this.workerProcess?.Kill(); + + return; + } + response = await this.MakeHttpGetRequest("PollEncodeProgress"); + + this.retryCount = 0; // Reset } catch (Exception e) { - if (this.encodePollTimer != null) - { - this.encodePollTimer.Stop(); - } + retryCount = this.retryCount + 1; } if (response == null || !response.WasSuccessful) { + retryCount = this.retryCount + 1; return; } @@ -215,8 +259,15 @@ namespace HandBrakeWPF.Instance else if (taskState != null && taskState == TaskState.WorkDone) { this.encodePollTimer.Stop(); - + + this.EncodeCompleted?.Invoke(sender: this, e: new EncodeCompletedEventArgs(state.WorkDone.Error != 0)); + this.workerProcess?.Kill(); + } + else if (taskState == TaskState.Idle) + { + this.encodePollTimer.Stop(); this.EncodeCompleted?.Invoke(sender: this, e: new EncodeCompletedEventArgs(state.WorkDone.Error != 0)); + this.workerProcess?.Kill(); } } } diff --git a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs index 417d77855..481c8cebd 100644 --- a/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs +++ b/win/CS/HandBrakeWPF/Services/Encode/LibEncode.cs @@ -108,7 +108,7 @@ namespace HandBrakeWPF.Services.Encode this.TimedLogMessage(string.Format("base preset: {0}", basePresetName)); } - this.instance = task.IsPreviewEncode ? HandBrakeInstanceManager.GetPreviewInstance(configuration.Verbosity, configuration) : HandBrakeInstanceManager.GetEncodeInstance(configuration.Verbosity, configuration); + this.instance = task.IsPreviewEncode ? HandBrakeInstanceManager.GetPreviewInstance(configuration.Verbosity, configuration) : HandBrakeInstanceManager.GetEncodeInstance(configuration.Verbosity, configuration, this.log); this.instance.EncodeCompleted += this.InstanceEncodeCompleted; this.instance.EncodeProgress += this.InstanceEncodeProgress; diff --git a/win/CS/HandBrakeWPF/Services/Logging/LogService.cs b/win/CS/HandBrakeWPF/Services/Logging/LogService.cs index c11b764b0..738cb2b3a 100644 --- a/win/CS/HandBrakeWPF/Services/Logging/LogService.cs +++ b/win/CS/HandBrakeWPF/Services/Logging/LogService.cs @@ -22,8 +22,10 @@ namespace HandBrakeWPF.Services.Logging using HandBrake.Interop.Interop; using HandBrake.Interop.Interop.EventArgs; + using HandBrake.Worker.Logging.Interfaces; using HandBrake.Worker.Logging.Models; + using HandBrakeWPF.Instance; using HandBrakeWPF.Instance.Model; using HandBrakeWPF.Services.Interfaces; using HandBrakeWPF.Services.Logging.Model; @@ -34,7 +36,7 @@ namespace HandBrakeWPF.Services.Logging using ILog = Interfaces.ILog; using LogEventArgs = EventArgs.LogEventArgs; - public class LogService : HttpRequestBase, ILog + public class LogService : ILog { // TODO List. // Maybe make the event weak? @@ -52,23 +54,11 @@ namespace HandBrakeWPF.Services.Logging private bool isDiskLoggingEnabled; private StreamWriter fileWriter; private string logHeader; - private Timer remoteLogPollTimer; - private int remoteIndex = 0; - private bool isRemotePollingEnabled = false; public LogService(IUserSettingService userSettingService) { HandBrakeUtils.MessageLogged += this.HandBrakeUtils_MessageLogged; HandBrakeUtils.ErrorLogged += this.HandBrakeUtils_ErrorLogged; - - if (userSettingService.GetUserSetting<bool>(UserSettingConstants.RemoteServiceEnabled)) - { - this.ActivateRemoteLogPolling(); - this.isRemotePollingEnabled = true; - - this.port = userSettingService.GetUserSetting<int>(UserSettingConstants.RemoteServicePort); - this.serverUrl = string.Format("http://127.0.0.1:{0}/", this.port); - } } public event EventHandler<LogEventArgs> MessageLogged; @@ -175,21 +165,6 @@ namespace HandBrakeWPF.Services.Logging public async void Reset() { - //if (this.isRemotePollingEnabled) - //{ - // try - // { - // await this.MakeHttpGetRequest("ResetLogging"); - // } - // catch (Exception e) - // { - // if (this.remoteLogPollTimer != null) - // { - // this.remoteLogPollTimer.Stop(); - // } - // } - //} - lock (this.lockObject) { this.logMessages.Clear(); @@ -359,61 +334,9 @@ namespace HandBrakeWPF.Services.Logging this.LogMessage(e.Message); } - private void ActivateRemoteLogPolling() - { - this.remoteLogPollTimer = new Timer(); - this.remoteLogPollTimer.Interval = 1000; - - this.remoteLogPollTimer.Elapsed += (o, e) => - { - try - { - this.PollRemoteLog(); - } - catch (Exception exc) - { - Debug.WriteLine(exc); - } - }; - this.remoteLogPollTimer.Start(); - } - - private async void PollRemoteLog() + void ILogHandler.ShutdownFileWriter() { - ServerResponse response = null; - try - { - int nextIndex = this.remoteIndex + 1; - string json = JsonConvert.SerializeObject(nextIndex, Formatting.Indented, this.jsonNetSettings); - - response = await this.MakeHttpJsonPostRequest("GetLogMessagesFromIndex", json); - } - catch (Exception e) - { - Debug.WriteLine("No Endpoint"); - } - - if (response == null || !response.WasSuccessful) - { - return; - } - - string statusJson = response.JsonResponse; - - List<LogMessage> messages = null; - if (!string.IsNullOrEmpty(statusJson)) - { - messages = JsonConvert.DeserializeObject<List<LogMessage>>(statusJson, this.jsonNetSettings); - } - - if (messages != null) - { - foreach (var item in messages) - { - this.LogMessage(item.Content); - this.remoteIndex = item.MessageIndex; - } - } + throw new NotImplementedException(); } } } diff --git a/win/CS/HandBrakeWPF/Services/UserSettingService.cs b/win/CS/HandBrakeWPF/Services/UserSettingService.cs index 7e7b49e4a..4c181541a 100644 --- a/win/CS/HandBrakeWPF/Services/UserSettingService.cs +++ b/win/CS/HandBrakeWPF/Services/UserSettingService.cs @@ -305,7 +305,7 @@ namespace HandBrakeWPF.Services // Experimental
defaults.Add(UserSettingConstants.RemoteServiceEnabled, false);
- defaults.Add(UserSettingConstants.RemoteServicePort, true);
+ defaults.Add(UserSettingConstants.RemoteServicePort, 8037);
// Misc
defaults.Add(UserSettingConstants.ShowPresetPanel, false);
|