diff options
-rw-r--r-- | win/CS/HandBrake.Worker/ApiRouter.cs | 87 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/App.config | 6 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/HandBrake.Worker.csproj | 66 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/HttpServer.cs | 107 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Program.cs | 89 | ||||
-rw-r--r-- | win/CS/HandBrake.Worker/Properties/AssemblyInfo.cs | 45 | ||||
-rw-r--r-- | win/CS/HandBrake.sln | 6 |
7 files changed, 406 insertions, 0 deletions
diff --git a/win/CS/HandBrake.Worker/ApiRouter.cs b/win/CS/HandBrake.Worker/ApiRouter.cs new file mode 100644 index 000000000..9b7b6a163 --- /dev/null +++ b/win/CS/HandBrake.Worker/ApiRouter.cs @@ -0,0 +1,87 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="ApiRouter.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> +// This is a service worker for the HandBrake app. It allows us to run encodes / scans in a seperate process easily. +// All API's expose the ApplicationServices models as JSON. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + + +namespace HandBrake.Worker +{ + using HandBrake.Interop.Interop; + using HandBrake.Interop.Utilities; + using Newtonsoft.Json; + using System; + using System.IO; + using System.Net; + + public class ApiRouter + { + private HandBrakeInstance handbrakeInstance; + + public string GetVersionInfo(HttpListenerRequest request) + { + return string.Format(JsonConvert.SerializeObject((object)VersionHelper.GetVersion(), Formatting.Indented, new JsonSerializerSettings() + { + NullValueHandling = NullValueHandling.Ignore + }), Array.Empty<object>()); + } + + public string StartEncode(HttpListenerRequest request) + { + if (this.handbrakeInstance == null) + this.handbrakeInstance = new HandBrakeInstance(); + string requestPostData = ApiRouter.GetRequestPostData(request); + this.handbrakeInstance.Initialize(1); + this.handbrakeInstance.StartEncode(requestPostData); + return (string)null; + } + + public string StopEncode(HttpListenerRequest request) + { + if (this.handbrakeInstance != null) + this.handbrakeInstance.StopEncode(); + return (string)null; + } + + public string PauseEncode(HttpListenerRequest request) + { + if (this.handbrakeInstance != null) + this.handbrakeInstance.PauseEncode(); + return (string)null; + } + + public string ResumeEncode(HttpListenerRequest request) + { + if (this.handbrakeInstance != null) + this.handbrakeInstance.ResumeEncode(); + return (string)null; + } + + public string PollEncodeProgress(HttpListenerRequest request) + { + if (this.handbrakeInstance == null) + ; + return (string)null; + } + + public string SetConfiguration(HttpListenerRequest request) + { + return (string)null; + } + + private static string GetRequestPostData(HttpListenerRequest request) + { + if (!request.HasEntityBody) + return (string)null; + using (Stream inputStream = request.InputStream) + { + using (StreamReader streamReader = new StreamReader(inputStream, request.ContentEncoding)) + return streamReader.ReadToEnd(); + } + } + } +} diff --git a/win/CS/HandBrake.Worker/App.config b/win/CS/HandBrake.Worker/App.config new file mode 100644 index 000000000..787dcbecc --- /dev/null +++ b/win/CS/HandBrake.Worker/App.config @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" ?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1" /> + </startup> +</configuration>
\ No newline at end of file diff --git a/win/CS/HandBrake.Worker/HandBrake.Worker.csproj b/win/CS/HandBrake.Worker/HandBrake.Worker.csproj new file mode 100644 index 000000000..e6e84b498 --- /dev/null +++ b/win/CS/HandBrake.Worker/HandBrake.Worker.csproj @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{F8370F37-B226-4830-AEE7-6D7AE403E3D2}</ProjectGuid> + <OutputType>Exe</OutputType> + <RootNamespace>HandBrake.Worker</RootNamespace> + <AssemblyName>HandBrake.Worker</AssemblyName> + <TargetFrameworkVersion>v4.7.1</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + <DebugSymbols>true</DebugSymbols> + <OutputPath>bin\x64\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <DebugType>full</DebugType> + <PlatformTarget>x64</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + <OutputPath>bin\x64\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <Optimize>true</Optimize> + <DebugType>pdbonly</DebugType> + <PlatformTarget>x64</PlatformTarget> + <ErrorReport>prompt</ErrorReport> + <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> + <Prefer32Bit>true</Prefer32Bit> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ApiRouter.cs" /> + <Compile Include="HttpServer.cs" /> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + </ItemGroup> + <ItemGroup> + <PackageReference Include="Newtonsoft.Json"> + <Version>11.0.2</Version> + </PackageReference> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\HandBrake.Interop\HandBrake.Interop.csproj"> + <Project>{087a2ba8-bac2-4577-a46f-07ff9d420016}</Project> + <Name>HandBrake.Interop</Name> + </ProjectReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/win/CS/HandBrake.Worker/HttpServer.cs b/win/CS/HandBrake.Worker/HttpServer.cs new file mode 100644 index 000000000..4f23fa190 --- /dev/null +++ b/win/CS/HandBrake.Worker/HttpServer.cs @@ -0,0 +1,107 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="HttpServer.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> +// This is a service worker for the HandBrake app. It allows us to run encodes / scans in a seperate process easily. +// All API's expose the ApplicationServices models as JSON. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Worker +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Net; + using System.Text; + using System.Threading; + + public class HttpServer + { + private readonly HttpListener httpListener = new HttpListener(); + private readonly Dictionary<string, Func<HttpListenerRequest, string>> apiHandlers; + + public HttpServer(Dictionary<string, Func<HttpListenerRequest, string>> apiCalls, int port) + { + if (!HttpListener.IsSupported) + { + throw new NotSupportedException("HttpListener not supported on this computer."); + } + + // Store the Handlers + this.apiHandlers = new Dictionary<string, Func<HttpListenerRequest, string>>(apiCalls); + + Console.WriteLine(Environment.NewLine + "Available APIs: "); + foreach (KeyValuePair<string, Func<HttpListenerRequest, string>> api in apiCalls) + { + string url = string.Format("http://localhost:{0}/{1}/", port, api.Key); + this.httpListener.Prefixes.Add(url); + Console.WriteLine(url); + } + + Console.WriteLine(Environment.NewLine); + + this.httpListener.Start(); + } + + public void Run() + { + ThreadPool.QueueUserWorkItem((o) => + { + try + { + while (this.httpListener.IsListening) + { + ThreadPool.QueueUserWorkItem( + (c) => + { + var context = c as HttpListenerContext; + try + { + string requestType = context.Request.HttpMethod; + string path = context.Request.RawUrl.TrimStart('/'); + + Func<HttpListenerRequest, string> actionToPerform; + if (apiHandlers.TryGetValue(path, out actionToPerform)) + { + string rstr = actionToPerform(context.Request); + byte[] buf = Encoding.UTF8.GetBytes(rstr); + context.Response.ContentLength64 = buf.Length; + context.Response.OutputStream.Write(buf, 0, buf.Length); + } + else + { + string rstr = "Error, There is a missing API handler."; + byte[] buf = Encoding.UTF8.GetBytes(rstr); + context.Response.ContentLength64 = buf.Length; + context.Response.OutputStream.Write(buf, 0, buf.Length); + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); + } + finally + { + // always close the stream + context?.Response.OutputStream.Close(); + } + }, + this.httpListener.GetContext()); + } + } + catch (Exception exc) + { + Debug.WriteLine(exc); + } + }); + } + + public void Stop() + { + this.httpListener.Stop(); + this.httpListener.Close(); + } + } +}
\ No newline at end of file diff --git a/win/CS/HandBrake.Worker/Program.cs b/win/CS/HandBrake.Worker/Program.cs new file mode 100644 index 000000000..09e9a8d4d --- /dev/null +++ b/win/CS/HandBrake.Worker/Program.cs @@ -0,0 +1,89 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="Program.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> +// Manage the HandBrake Worker Process Service. +// </summary> +// -------------------------------------------------------------------------------------------------------------------- + +namespace HandBrake.Worker +{ + using System; + using System.Collections.Generic; + using System.Net; + using HandBrake.Interop.Utilities; + using Newtonsoft.Json; + + public class Program + { + private static ApiRouter router; + + public static void Main(string[] args) + { + Console.WriteLine("Starting Web Server ..."); + router = new ApiRouter(); + + Dictionary<string, Func<HttpListenerRequest, string>> apiHandlers = RegisterApiHandlers(); + + int port = 8080; // Default Port; + + if (args.Length != 0) + { + foreach (string argument in args) + { + if (argument.StartsWith("--port")) + { + string portStr = argument.TrimStart("--port=".ToCharArray()); + if (int.TryParse(portStr, out var parsedPort)) + { + port = parsedPort; + } + } + } + } + + Console.WriteLine("Using Port: {0}", port); + + HttpServer webServer = new HttpServer(apiHandlers, port); + webServer.Run(); + + Console.WriteLine("Webserver Started"); + Console.WriteLine("Press any key to exit"); + + Console.ReadKey(); // Block from closing. + + webServer.Stop(); + } + + public static Dictionary<string, Func<HttpListenerRequest, string>> RegisterApiHandlers() + { + Dictionary<string, Func<HttpListenerRequest, string>> apiHandlers = + new Dictionary<string, Func<HttpListenerRequest, string>>(); + + 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 GetVersionInfo(HttpListenerRequest request) + { + string version = VersionHelper.GetVersion(); + JsonSerializerSettings settings = new JsonSerializerSettings + { + NullValueHandling = NullValueHandling.Ignore, + }; + + string versionJson = JsonConvert.SerializeObject(version, Formatting.Indented, settings); + + return string.Format(versionJson); + } + } +} + diff --git a/win/CS/HandBrake.Worker/Properties/AssemblyInfo.cs b/win/CS/HandBrake.Worker/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d834e2098 --- /dev/null +++ b/win/CS/HandBrake.Worker/Properties/AssemblyInfo.cs @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------------------------------------------------- +// <copyright file="AssemblyInfo.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> +// Assembly Info +// </summary> +// <auto-generated/> +// -------------------------------------------------------------------------------------------------------------------- + +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("HandBrake.Worker")] +[assembly: AssemblyDescription("HandBrake is a GPL-licensed, multiplatform, multithreaded video transcoder.")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("HandBrake Team")] +[assembly: AssemblyProduct("HandBrake.Worker")] +[assembly: AssemblyCopyright("Copyright © 2003-2018 HandBrake Team")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f8370f37-b226-4830-aee7-6d7ae403e3d2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.2.0.0")] +[assembly: AssemblyFileVersion("1.2.0.0")] diff --git a/win/CS/HandBrake.sln b/win/CS/HandBrake.sln index 7d9ad28ca..b4dac3f3f 100644 --- a/win/CS/HandBrake.sln +++ b/win/CS/HandBrake.sln @@ -16,6 +16,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrakeTools", "HandBrake EndProject
Project("{262852C6-CD72-467D-83FE-5EEB1973A190}") = "HandBrakeAppX", "HandBrakeAppX\HandBrakeAppX.jsproj", "{6E855245-E402-4C0F-BB0B-EEB63082F6AC}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HandBrake.Worker", "HandBrake.Worker\HandBrake.Worker.csproj", "{F8370F37-B226-4830-AEE7-6D7AE403E3D2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -40,6 +42,10 @@ Global {6E855245-E402-4C0F-BB0B-EEB63082F6AC}.Release|x64.ActiveCfg = Release|x64
{6E855245-E402-4C0F-BB0B-EEB63082F6AC}.Release|x64.Build.0 = Release|x64
{6E855245-E402-4C0F-BB0B-EEB63082F6AC}.Release|x64.Deploy.0 = Release|x64
+ {F8370F37-B226-4830-AEE7-6D7AE403E3D2}.Debug|x64.ActiveCfg = Debug|x64
+ {F8370F37-B226-4830-AEE7-6D7AE403E3D2}.Debug|x64.Build.0 = Debug|x64
+ {F8370F37-B226-4830-AEE7-6D7AE403E3D2}.Release|x64.ActiveCfg = Release|x64
+ {F8370F37-B226-4830-AEE7-6D7AE403E3D2}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
|