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/HandBrake.Worker | |
parent | f34280f1c619dae0b4e1a1ea09cea5b39f17d695 (diff) |
WinGui: Further work on the isolated process articecture.
Diffstat (limited to 'win/CS/HandBrake.Worker')
-rw-r--r-- | win/CS/HandBrake.Worker/HandBrake.Worker.csproj | 7 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/HttpServer.cs | 8 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Logging/Interfaces/ILogHandler.cs | 2 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Logging/LogHandler.cs | 73 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Program.cs | 36 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Registration/ConnectionRegistrar.cs | 53 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Routing/ApiRouter.cs | 85 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Routing/Commands/EncodeCommand.cs | 20 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Routing/Commands/InitCommand.cs | 28 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Routing/Results/CommandResult.cs | 17 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Routing/Results/ConnectionResult.cs (renamed from win/CS/HandBrake.Worker/Registration/Model/ConnectionResult.cs) | 2 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Watcher/InstanceWatcher.cs | 51 |
12 files changed, 272 insertions, 110 deletions
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(); + } + } + } +} |