From 75efe9cf0a15b6871726a4c2e8802e2af88cf1d1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 1 Jan 2019 16:27:11 +0100 Subject: Rename and rework entry point --- Jellyfin.Server/Program.cs | 302 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 Jellyfin.Server/Program.cs (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs new file mode 100644 index 000000000..b768e1032 --- /dev/null +++ b/Jellyfin.Server/Program.cs @@ -0,0 +1,302 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Security; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Emby.Drawing; +using Emby.Drawing.ImageMagick; +using Emby.Drawing.Skia; +using Emby.Server.Implementations; +using Emby.Server.Implementations.EnvironmentInfo; +using Emby.Server.Implementations.IO; +using Emby.Server.Implementations.Networking; +using Jellyfin.Server.Native; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Net; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Logging; +using Serilog; +using Serilog.AspNetCore; +using ILogger = Microsoft.Extensions.Logging.ILogger; + +namespace Jellyfin.Server +{ + public static class Program + { + private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); + private static ILoggerFactory _loggerFactory; + private static ILogger _logger; + private static bool _restartOnShutdown; + + public static async Task Main(string[] args) + { + StartupOptions options = new StartupOptions(args); + + Assembly entryAssembly = Assembly.GetEntryAssembly(); + + if (options.ContainsOption("-v") || options.ContainsOption("--version")) + { + Console.WriteLine(entryAssembly.GetName().Version.ToString()); + return 0; + } + + string dataPath = options.GetOption("-programdata"); + string binPath = entryAssembly.Location; + ServerApplicationPaths appPaths = CreateApplicationPaths(binPath, dataPath); + + await createLogger(appPaths); + _loggerFactory = new SerilogLoggerFactory(); + _logger = _loggerFactory.CreateLogger("Main"); + + AppDomain.CurrentDomain.UnhandledException += (sender, e) + => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");; + + ApplicationHost.LogEnvironmentInfo(_logger, appPaths, true); + + SQLitePCL.Batteries_V2.Init(); + + // Allow all https requests + ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); + + EnvironmentInfo environmentInfo = getEnvironmentInfo(); + var fileSystem = new ManagedFileSystem(_loggerFactory.CreateLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, true); + + using (var appHost = new CoreAppHost( + appPaths, + _loggerFactory, + options, + fileSystem, + new PowerManagement(), + "embyserver-mono_{version}.zip", + environmentInfo, + new NullImageEncoder(), + new SystemEvents(_loggerFactory.CreateLogger("SystemEvents")), + new NetworkManager(_loggerFactory.CreateLogger("NetworkManager"), environmentInfo))) + { + appHost.Init(); + + appHost.ImageProcessor.ImageEncoder = GetImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); + + _logger.LogInformation("Running startup tasks"); + + await appHost.RunStartupTasks(); + + // TODO: read input for a stop command + // Block main thread until shutdown + await ApplicationTaskCompletionSource.Task; + + _logger.LogInformation("Disposing app host"); + } + + if (_restartOnShutdown) + { + StartNewInstance(options); + } + + return 0; + } + + private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, string programDataPath) + { + if (string.IsNullOrEmpty(programDataPath)) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + } + else + { + // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. + programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); + // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used. + if (string.IsNullOrEmpty(programDataPath)){ + programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + } + } + programDataPath = Path.Combine(programDataPath, "jellyfin"); + } + + string appFolderPath = Path.GetDirectoryName(applicationPath); + + return new ServerApplicationPaths(programDataPath, appFolderPath, appFolderPath); + } + + private static async Task createLogger(IApplicationPaths appPaths) + { + string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); + if (string.IsNullOrEmpty(logDir)){ + logDir = Path.Combine(appPaths.ProgramDataPath, "logs"); + Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); + } + try + { + string path = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json"); + + if (!File.Exists(path)) + { + // For some reason the csproj name is used instead of the assembly name + using (Stream rscstr = typeof(Program).Assembly + .GetManifestResourceStream("EmbyServer.Resources.Configuration.logging.json")) + using (Stream fstr = File.Open(path, FileMode.CreateNew)) + { + await rscstr.CopyToAsync(fstr); + } + } + var configuration = new ConfigurationBuilder() + .SetBasePath(appPaths.ConfigurationDirectoryPath) + .AddJsonFile("logging.json") + .AddEnvironmentVariables("JELLYFIN_") + .Build(); + + // Serilog.Log is used by SerilogLoggerFactory when no logger is specified + Serilog.Log.Logger = new LoggerConfiguration() + .ReadFrom.Configuration(configuration) + .Enrich.FromLogContext() + .CreateLogger(); + } + catch (Exception ex) + { + Serilog.Log.Logger = new LoggerConfiguration() + .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") + .WriteTo.File( + Path.Combine(logDir, "log_.log"), + rollingInterval: RollingInterval.Day, + outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") + .Enrich.FromLogContext() + .CreateLogger(); + + Serilog.Log.Logger.Fatal(ex, "Failed to create/read logger configuration"); + } + } + + public static IImageEncoder GetImageEncoder( + ILogger logger, + IFileSystem fileSystem, + StartupOptions startupOptions, + Func httpClient, + IApplicationPaths appPaths, + IEnvironmentInfo environment, + ILocalizationManager localizationManager) + { + if (!startupOptions.ContainsOption("-enablegdi")) + { + try + { + return new SkiaEncoder(logger, appPaths, httpClient, fileSystem, localizationManager); + } + catch (Exception ex) + { + logger.LogInformation("Skia not available. Will try next image processor. {0}", ex.Message); + } + + try + { + return new ImageMagickEncoder(logger, appPaths, httpClient, fileSystem, environment); + } + catch + { + logger.LogInformation("ImageMagick not available. Will try next image processor."); + } + } + + return new NullImageEncoder(); + } + + private static EnvironmentInfo getEnvironmentInfo() + => new EnvironmentInfo() + { + SystemArchitecture = RuntimeInformation.OSArchitecture, + OperatingSystem = getOperatingSystem() + }; + + private static MediaBrowser.Model.System.OperatingSystem getOperatingSystem() { + switch (Environment.OSVersion.Platform) + { + case PlatformID.MacOSX: + return MediaBrowser.Model.System.OperatingSystem.OSX; + case PlatformID.Win32NT: + return MediaBrowser.Model.System.OperatingSystem.Windows; + case PlatformID.Unix: + { + string osDescription = RuntimeInformation.OSDescription; + if (osDescription.Contains("linux", StringComparison.OrdinalIgnoreCase)) + { + return MediaBrowser.Model.System.OperatingSystem.Linux; + } + else if (osDescription.Contains("darwin", StringComparison.OrdinalIgnoreCase)) + { + return MediaBrowser.Model.System.OperatingSystem.OSX; + } + else if (osDescription.Contains("bsd", StringComparison.OrdinalIgnoreCase)) + { + return MediaBrowser.Model.System.OperatingSystem.BSD; + } + throw new Exception($"Can't resolve OS with description: {Environment.OSVersion.Platform}"); + } + default: throw new Exception($"Can't resolve OS with description: {Environment.OSVersion.Platform}"); + } + } + + public static void Shutdown() + { + ApplicationTaskCompletionSource.SetResult(true); + } + + public static void Restart() + { + _restartOnShutdown = true; + + Shutdown(); + } + + private static void StartNewInstance(StartupOptions startupOptions) + { + _logger.LogInformation("Starting new instance"); + + string module = startupOptions.GetOption("-restartpath"); + + if (string.IsNullOrWhiteSpace(module)) + { + module = Environment.GetCommandLineArgs().First(); + } + + string commandLineArgsString; + + if (startupOptions.ContainsOption("-restartargs")) + { + commandLineArgsString = startupOptions.GetOption("-restartargs") ?? string.Empty; + } + else + { + commandLineArgsString = string .Join(" ", + Environment.GetCommandLineArgs() + .Skip(1) + .Select(NormalizeCommandLineArgument) + ); + } + + _logger.LogInformation("Executable: {0}", module); + _logger.LogInformation("Arguments: {0}", commandLineArgsString); + + Process.Start(module, commandLineArgsString); + } + + private static string NormalizeCommandLineArgument(string arg) + { + if (!arg.Contains(" ", StringComparison.OrdinalIgnoreCase)) + { + return arg; + } + + return "\"" + arg + "\""; + } + } +} -- cgit v1.2.3 From a44936f97f8afc2817d3491615a7cfe1e31c251c Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 1 Jan 2019 18:41:02 +0100 Subject: Fix and improve logging --- Emby.Server.Implementations/ApplicationHost.cs | 62 +++++++--------------- .../EnvironmentInfo/EnvironmentInfo.cs | 10 +++- Jellyfin.Server/Jellyfin.Server.csproj | 4 ++ Jellyfin.Server/Program.cs | 8 +-- .../Resources/Configuration/logging.json | 19 +++++++ 5 files changed, 57 insertions(+), 46 deletions(-) create mode 100644 Jellyfin.Server/Resources/Configuration/logging.json (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 060898684..09179c15e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -799,27 +799,6 @@ namespace Emby.Server.Implementations JsonSerializer = CreateJsonSerializer(); - OnLoggerLoaded(true); - //LoggerFactory.LoggerLoaded += (s, e) => OnLoggerLoaded(false); - - DiscoverTypes(); - - SetHttpLimit(); - - RegisterResources(); - - FindParts(); - } - - protected virtual void OnLoggerLoaded(bool isFirstLoad) - { - Logger.LogInformation("Application version: {0}", ApplicationVersion); - - if (!isFirstLoad) - { - LogEnvironmentInfo(Logger, ApplicationPaths, false); - } - if (Plugins != null) { var pluginBuilder = new StringBuilder(); @@ -831,6 +810,14 @@ namespace Emby.Server.Implementations Logger.LogInformation("Plugins: {plugins}", pluginBuilder.ToString()); } + + DiscoverTypes(); + + SetHttpLimit(); + + RegisterResources(); + + FindParts(); } protected virtual IHttpClient CreateHttpClient() @@ -1073,36 +1060,27 @@ namespace Emby.Server.Implementations { get { - return "netframework"; + return "netcore"; } } - public static void LogEnvironmentInfo(ILogger Logger, IApplicationPaths appPaths, bool isStartup) - { - Logger.LogInformation("Jellyfin:\n{ex}", GetBaseExceptionMessage(appPaths).ToString()); - } - - protected static StringBuilder GetBaseExceptionMessage(IApplicationPaths appPaths) + public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths, EnvironmentInfo.EnvironmentInfo environmentInfo) { var builder = new StringBuilder(); // Distinct these to prevent users from reporting problems that aren't actually problems var commandLineArgs = Environment .GetCommandLineArgs() - .Distinct() - .ToArray(); - - builder.AppendLine(string.Format("Command line: {0}", string.Join(" ", commandLineArgs))); - - builder.AppendLine(string.Format("Operating system: {0}", Environment.OSVersion)); - builder.AppendLine(string.Format("64-Bit OS: {0}", Environment.Is64BitOperatingSystem)); - builder.AppendLine(string.Format("64-Bit Process: {0}", Environment.Is64BitProcess)); - builder.AppendLine(string.Format("User Interactive: {0}", Environment.UserInteractive)); - builder.AppendLine(string.Format("Processor count: {0}", Environment.ProcessorCount)); - builder.AppendLine(string.Format("Program data path: {0}", appPaths.ProgramDataPath)); - builder.AppendLine(string.Format("Application directory: {0}", appPaths.ProgramSystemPath)); - - return builder; + .Distinct(); + + logger.LogInformation("Arguments: {Args}", commandLineArgs); + logger.LogInformation("Operating system: {OS} {OSVersion}", environmentInfo.OperatingSystemName, environmentInfo.OperatingSystemVersion); + logger.LogInformation("Architecture: {Architecture}", environmentInfo.SystemArchitecture); + logger.LogInformation("64-Bit Process: {0}", Environment.Is64BitProcess); + logger.LogInformation("User Interactive: {0}", Environment.UserInteractive); + logger.LogInformation("Processor count: {0}", Environment.ProcessorCount); + logger.LogInformation("Program data path: {0}", appPaths.ProgramDataPath); + logger.LogInformation("Application directory: {0}", appPaths.ProgramSystemPath); } private void SetHttpLimit() diff --git a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs index ad941de55..5cff2dff0 100644 --- a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; namespace Emby.Server.Implementations.EnvironmentInfo { + // TODO: Rework @bond public class EnvironmentInfo : IEnvironmentInfo { private MediaBrowser.Model.System.OperatingSystem? _customOperatingSystem; @@ -40,7 +41,14 @@ namespace Emby.Server.Implementations.EnvironmentInfo { get { - return Environment.OSVersion.Platform.ToString(); + switch (OperatingSystem) { + case MediaBrowser.Model.System.OperatingSystem.Android: return "Android"; + case MediaBrowser.Model.System.OperatingSystem.BSD: return "BSD"; + case MediaBrowser.Model.System.OperatingSystem.Linux: return "Linux"; + case MediaBrowser.Model.System.OperatingSystem.OSX: return "macOS"; + case MediaBrowser.Model.System.OperatingSystem.Windows: return "Windows"; + default: throw new Exception($"Unknown OS {OperatingSystem}"); + } } } diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index cf8396785..09491d6a5 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -15,6 +15,10 @@ + + + + diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index b768e1032..dd5e427df 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -59,14 +59,16 @@ namespace Jellyfin.Server AppDomain.CurrentDomain.UnhandledException += (sender, e) => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");; - ApplicationHost.LogEnvironmentInfo(_logger, appPaths, true); + _logger.LogInformation("Jellyfin version: {Version}", entryAssembly.GetName().Version); + + EnvironmentInfo environmentInfo = getEnvironmentInfo(); + ApplicationHost.LogEnvironmentInfo(_logger, appPaths, environmentInfo); SQLitePCL.Batteries_V2.Init(); // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); - EnvironmentInfo environmentInfo = getEnvironmentInfo(); var fileSystem = new ManagedFileSystem(_loggerFactory.CreateLogger("FileSystem"), environmentInfo, null, appPaths.TempDirectory, true); using (var appHost = new CoreAppHost( @@ -144,7 +146,7 @@ namespace Jellyfin.Server { // For some reason the csproj name is used instead of the assembly name using (Stream rscstr = typeof(Program).Assembly - .GetManifestResourceStream("EmbyServer.Resources.Configuration.logging.json")) + .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json")) using (Stream fstr = File.Open(path, FileMode.CreateNew)) { await rscstr.CopyToAsync(fstr); diff --git a/Jellyfin.Server/Resources/Configuration/logging.json b/Jellyfin.Server/Resources/Configuration/logging.json new file mode 100644 index 000000000..78f99b2ad --- /dev/null +++ b/Jellyfin.Server/Resources/Configuration/logging.json @@ -0,0 +1,19 @@ +{ + "Serilog": { + "MinimumLevel": "Information", + "WriteTo": [ + { "Name": "Console", + "Args": { + "outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}" + } + }, + { "Name": "File", + "Args": { + "path": "%JELLYFIN_LOG_DIR%//log_.log", + "rollingInterval": "Day", + "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}" + } + } + ] + } +} -- cgit v1.2.3 From 95a5dd881076f6649f4b5dc5a1897df98dc3c008 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 1 Jan 2019 21:34:12 +0100 Subject: Fix log dir --- .../AppBase/BaseApplicationPaths.cs | 24 ++++++++-- .../ServerApplicationPaths.cs | 4 +- Jellyfin.Server/Program.cs | 51 ++++++++++++---------- MediaBrowser.Api/System/SystemService.cs | 10 ++--- 4 files changed, 54 insertions(+), 35 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs index 52e421374..76d0076a6 100644 --- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs +++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; using MediaBrowser.Common.Configuration; namespace Emby.Server.Implementations.AppBase @@ -13,10 +12,11 @@ namespace Emby.Server.Implementations.AppBase /// /// Initializes a new instance of the class. /// - protected BaseApplicationPaths(string programDataPath, string appFolderPath) + protected BaseApplicationPaths(string programDataPath, string appFolderPath, string logDirectoryPath) { ProgramDataPath = programDataPath; ProgramSystemPath = appFolderPath; + LogDirectoryPath = logDirectoryPath; } public string ProgramDataPath { get; private set; } @@ -106,6 +106,11 @@ namespace Emby.Server.Implementations.AppBase } } + /// + /// The _log directory + /// + private string _logDirectoryPath; + /// /// Gets the path to the log directory /// @@ -114,7 +119,18 @@ namespace Emby.Server.Implementations.AppBase { get { - return Path.Combine(ProgramDataPath, "logs"); + if (string.IsNullOrEmpty(_logDirectoryPath)) + { + _logDirectoryPath = Path.Combine(ProgramDataPath, "logs"); + + Directory.CreateDirectory(_logDirectoryPath); + } + + return _logDirectoryPath; + } + set + { + _logDirectoryPath = value; } } diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs index 1686a548b..f5986f943 100644 --- a/Emby.Server.Implementations/ServerApplicationPaths.cs +++ b/Emby.Server.Implementations/ServerApplicationPaths.cs @@ -13,8 +13,8 @@ namespace Emby.Server.Implementations /// /// Initializes a new instance of the class. /// - public ServerApplicationPaths(string programDataPath, string appFolderPath, string applicationResourcesPath) - : base(programDataPath, appFolderPath) + public ServerApplicationPaths(string programDataPath, string appFolderPath, string applicationResourcesPath, string logDirectoryPath = null) + : base(programDataPath, appFolderPath, logDirectoryPath) { ApplicationResourcesPath = applicationResourcesPath; } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index dd5e427df..aef22e020 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -39,27 +39,23 @@ namespace Jellyfin.Server public static async Task Main(string[] args) { StartupOptions options = new StartupOptions(args); - - Assembly entryAssembly = Assembly.GetEntryAssembly(); + Version version = Assembly.GetEntryAssembly().GetName().Version; if (options.ContainsOption("-v") || options.ContainsOption("--version")) { - Console.WriteLine(entryAssembly.GetName().Version.ToString()); + Console.WriteLine(version.ToString()); return 0; } - string dataPath = options.GetOption("-programdata"); - string binPath = entryAssembly.Location; - ServerApplicationPaths appPaths = CreateApplicationPaths(binPath, dataPath); - + ServerApplicationPaths appPaths = createApplicationPaths(options); await createLogger(appPaths); _loggerFactory = new SerilogLoggerFactory(); _logger = _loggerFactory.CreateLogger("Main"); AppDomain.CurrentDomain.UnhandledException += (sender, e) - => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception");; + => _logger.LogCritical((Exception)e.ExceptionObject, "Unhandled Exception"); - _logger.LogInformation("Jellyfin version: {Version}", entryAssembly.GetName().Version); + _logger.LogInformation("Jellyfin version: {Version}", version); EnvironmentInfo environmentInfo = getEnvironmentInfo(); ApplicationHost.LogEnvironmentInfo(_logger, appPaths, environmentInfo); @@ -106,9 +102,14 @@ namespace Jellyfin.Server return 0; } - private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, string programDataPath) + private static ServerApplicationPaths createApplicationPaths(StartupOptions options) { - if (string.IsNullOrEmpty(programDataPath)) + string programDataPath; + if (options.ContainsOption("-programdata")) + { + programDataPath = options.GetOption("-programdata"); + } + else { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { @@ -126,28 +127,30 @@ namespace Jellyfin.Server programDataPath = Path.Combine(programDataPath, "jellyfin"); } - string appFolderPath = Path.GetDirectoryName(applicationPath); + string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); + if (string.IsNullOrEmpty(logDir)){ + logDir = Path.Combine(programDataPath, "logs"); + // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager + Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); + } + + string appPath = Assembly.GetEntryAssembly().Location; - return new ServerApplicationPaths(programDataPath, appFolderPath, appFolderPath); + return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir); } private static async Task createLogger(IApplicationPaths appPaths) { - string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); - if (string.IsNullOrEmpty(logDir)){ - logDir = Path.Combine(appPaths.ProgramDataPath, "logs"); - Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); - } try { - string path = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json"); + string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json"); - if (!File.Exists(path)) + if (!File.Exists(configPath)) { // For some reason the csproj name is used instead of the assembly name using (Stream rscstr = typeof(Program).Assembly .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json")) - using (Stream fstr = File.Open(path, FileMode.CreateNew)) + using (Stream fstr = File.Open(configPath, FileMode.CreateNew)) { await rscstr.CopyToAsync(fstr); } @@ -169,7 +172,7 @@ namespace Jellyfin.Server Serilog.Log.Logger = new LoggerConfiguration() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") .WriteTo.File( - Path.Combine(logDir, "log_.log"), + Path.Combine(appPaths.LogDirectoryPath, "log_.log"), rollingInterval: RollingInterval.Day, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") .Enrich.FromLogContext() @@ -227,6 +230,7 @@ namespace Jellyfin.Server case PlatformID.Win32NT: return MediaBrowser.Model.System.OperatingSystem.Windows; case PlatformID.Unix: + default: { string osDescription = RuntimeInformation.OSDescription; if (osDescription.Contains("linux", StringComparison.OrdinalIgnoreCase)) @@ -241,9 +245,8 @@ namespace Jellyfin.Server { return MediaBrowser.Model.System.OperatingSystem.BSD; } - throw new Exception($"Can't resolve OS with description: {Environment.OSVersion.Platform}"); + throw new Exception($"Can't resolve OS with description: '{osDescription}'"); } - default: throw new Exception($"Can't resolve OS with description: {Environment.OSVersion.Platform}"); } } diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs index d2880f735..52e14dbcc 100644 --- a/MediaBrowser.Api/System/SystemService.cs +++ b/MediaBrowser.Api/System/SystemService.cs @@ -9,12 +9,11 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; - -using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; using MediaBrowser.Model.Services; using System.Threading; +using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.System { @@ -137,11 +136,12 @@ namespace MediaBrowser.Api.System try { - files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath, new[] { ".txt" }, true, false); + files = _fileSystem.GetFiles(_appPaths.LogDirectoryPath, new[] { ".txt", ".log" }, true, false); } - catch (IOException) + catch (IOException ex) { - files = new FileSystemMetadata[] { }; + Logger.LogError(ex, "Error getting logs"); + files = Enumerable.Empty(); } var result = files.Select(i => new LogFile -- cgit v1.2.3 From 9ccc259c99b11469cd93cb3e15ad2f69f54f0b46 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 1 Jan 2019 23:19:00 +0100 Subject: Fix errors and assembly name --- Jellyfin.Server/Jellyfin.Server.csproj | 1 + Jellyfin.Server/Program.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 09491d6a5..fa603a086 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -1,6 +1,7 @@  + jellyfin Exe netcoreapp2.1 false diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index aef22e020..73c7a0c7c 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -134,7 +134,7 @@ namespace Jellyfin.Server Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); } - string appPath = Assembly.GetEntryAssembly().Location; + string appPath = AppContext.BaseDirectory; return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir); } -- cgit v1.2.3 From 76d6b1fc2aa8d448803ecf874e7a37a9b6afef9e Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 1 Jan 2019 23:56:32 +0100 Subject: Ensure log dir exists --- Jellyfin.Server/Program.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 73c7a0c7c..6f3c8c317 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -130,6 +130,8 @@ namespace Jellyfin.Server string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); if (string.IsNullOrEmpty(logDir)){ logDir = Path.Combine(programDataPath, "logs"); + // Ensure logDir exists + Directory.CreateDirectory(logDir); // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); } -- cgit v1.2.3 From 5d855ee84c26ab4cdc3a8672433b168ba4cb8610 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 2 Jan 2019 00:10:26 +0100 Subject: Log when falling back on NullImageEncoder --- Jellyfin.Server/Program.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 6f3c8c317..a477d8b5a 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -81,7 +81,7 @@ namespace Jellyfin.Server { appHost.Init(); - appHost.ImageProcessor.ImageEncoder = GetImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); + appHost.ImageProcessor.ImageEncoder = getImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); _logger.LogInformation("Running startup tasks"); @@ -184,7 +184,7 @@ namespace Jellyfin.Server } } - public static IImageEncoder GetImageEncoder( + public static IImageEncoder getImageEncoder( ILogger logger, IFileSystem fileSystem, StartupOptions startupOptions, @@ -201,17 +201,18 @@ namespace Jellyfin.Server } catch (Exception ex) { - logger.LogInformation("Skia not available. Will try next image processor. {0}", ex.Message); + logger.LogInformation(ex, "Skia not available. Will try next image processor. {0}"); } try { return new ImageMagickEncoder(logger, appPaths, httpClient, fileSystem, environment); } - catch + catch (Exception ex) { - logger.LogInformation("ImageMagick not available. Will try next image processor."); + logger.LogInformation(ex, "ImageMagick not available. Will try next image processor."); } + _logger.LogInformation("Falling back on NullImageEncoder"); } return new NullImageEncoder(); -- cgit v1.2.3 From cf7e36561037e0e3c0d532b7a0c8d7d668c2373b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 2 Jan 2019 00:21:06 +0100 Subject: Fix inconsistent code style --- Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs | 3 ++- Jellyfin.Server/Program.cs | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs index 5cff2dff0..985eb71da 100644 --- a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -41,7 +41,8 @@ namespace Emby.Server.Implementations.EnvironmentInfo { get { - switch (OperatingSystem) { + switch (OperatingSystem) + { case MediaBrowser.Model.System.OperatingSystem.Android: return "Android"; case MediaBrowser.Model.System.OperatingSystem.BSD: return "BSD"; case MediaBrowser.Model.System.OperatingSystem.Linux: return "Linux"; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index a477d8b5a..f0907fd58 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -120,7 +120,8 @@ namespace Jellyfin.Server // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used. - if (string.IsNullOrEmpty(programDataPath)){ + if (string.IsNullOrEmpty(programDataPath)) + { programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); } } @@ -128,7 +129,8 @@ namespace Jellyfin.Server } string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); - if (string.IsNullOrEmpty(logDir)){ + if (string.IsNullOrEmpty(logDir)) + { logDir = Path.Combine(programDataPath, "logs"); // Ensure logDir exists Directory.CreateDirectory(logDir); -- cgit v1.2.3 From 6643ac3ea412ea62fc067ae6b24ddfe69fd18482 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 2 Jan 2019 00:41:47 +0100 Subject: Clean up EnvironmentInfo --- .../EnvironmentInfo/EnvironmentInfo.cs | 32 ++++------------------ Jellyfin.Server/Program.cs | 9 +----- 2 files changed, 6 insertions(+), 35 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs index 985eb71da..03e10e7ea 100644 --- a/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Server.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -8,35 +8,13 @@ namespace Emby.Server.Implementations.EnvironmentInfo // TODO: Rework @bond public class EnvironmentInfo : IEnvironmentInfo { - private MediaBrowser.Model.System.OperatingSystem? _customOperatingSystem; - - public virtual MediaBrowser.Model.System.OperatingSystem OperatingSystem + public EnvironmentInfo(MediaBrowser.Model.System.OperatingSystem operatingSystem) { - get - { - if (_customOperatingSystem.HasValue) - { - return _customOperatingSystem.Value; - } - - switch (Environment.OSVersion.Platform) - { - case PlatformID.MacOSX: - return MediaBrowser.Model.System.OperatingSystem.OSX; - case PlatformID.Win32NT: - return MediaBrowser.Model.System.OperatingSystem.Windows; - case PlatformID.Unix: - return MediaBrowser.Model.System.OperatingSystem.Linux; - } - - return MediaBrowser.Model.System.OperatingSystem.Windows; - } - set - { - _customOperatingSystem = value; - } + OperatingSystem = operatingSystem; } + public MediaBrowser.Model.System.OperatingSystem OperatingSystem { get; private set; } + public string OperatingSystemName { get @@ -69,7 +47,7 @@ namespace Emby.Server.Implementations.EnvironmentInfo } } - public Architecture SystemArchitecture { get; set; } + public Architecture SystemArchitecture { get { return RuntimeInformation.OSArchitecture; } } public string GetEnvironmentVariable(string name) { diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index f0907fd58..0150cd533 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -57,7 +57,7 @@ namespace Jellyfin.Server _logger.LogInformation("Jellyfin version: {Version}", version); - EnvironmentInfo environmentInfo = getEnvironmentInfo(); + EnvironmentInfo environmentInfo = new EnvironmentInfo(getOperatingSystem()); ApplicationHost.LogEnvironmentInfo(_logger, appPaths, environmentInfo); SQLitePCL.Batteries_V2.Init(); @@ -220,13 +220,6 @@ namespace Jellyfin.Server return new NullImageEncoder(); } - private static EnvironmentInfo getEnvironmentInfo() - => new EnvironmentInfo() - { - SystemArchitecture = RuntimeInformation.OSArchitecture, - OperatingSystem = getOperatingSystem() - }; - private static MediaBrowser.Model.System.OperatingSystem getOperatingSystem() { switch (Environment.OSVersion.Platform) { -- cgit v1.2.3 From 40563dc6cc30e45ace90db30a934478395d8c7c1 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 2 Jan 2019 17:09:40 +0100 Subject: Remove GitHub updater and don't trow exception in release --- Emby.Server.Implementations/ApplicationHost.cs | 49 +---- Jellyfin.Server/CoreAppHost.cs | 4 +- Jellyfin.Server/Program.cs | 1 - MediaBrowser.Common/Updates/GithubUpdater.cs | 274 ------------------------- 4 files changed, 7 insertions(+), 321 deletions(-) delete mode 100644 MediaBrowser.Common/Updates/GithubUpdater.cs (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index f1e1b4b2d..5853d20c8 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -368,7 +368,6 @@ namespace Emby.Server.Implementations protected IAuthService AuthService { get; private set; } public StartupOptions StartupOptions { get; private set; } - protected readonly string ReleaseAssetFilename; internal IPowerManagement PowerManagement { get; private set; } internal IImageEncoder ImageEncoder { get; private set; } @@ -393,7 +392,6 @@ namespace Emby.Server.Implementations StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, - string releaseAssetFilename, IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, ISystemEvents systemEvents, @@ -419,7 +417,6 @@ namespace Emby.Server.Implementations Logger = LoggerFactory.CreateLogger("App"); StartupOptions = options; - ReleaseAssetFilename = releaseAssetFilename; PowerManagement = powerManagement; ImageEncoder = imageEncoder; @@ -2292,48 +2289,12 @@ namespace Emby.Server.Implementations /// The cancellation token. /// The progress. /// Task{CheckForUpdateResult}. - public async Task CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress progress) + public Task CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress progress) { - var updateLevel = SystemUpdateLevel; - var cacheLength = updateLevel == PackageVersionClass.Release ? - TimeSpan.FromHours(12) : - TimeSpan.FromMinutes(5); - - try - { - var result = await new GithubUpdater(HttpClient, JsonSerializer).CheckForUpdateResult("MediaBrowser", - "Emby.Releases", - ApplicationVersion, - updateLevel, - ReleaseAssetFilename, - "MBServer", - UpdateTargetFileName, - cacheLength, - cancellationToken).ConfigureAwait(false); - - HasUpdateAvailable = result.IsUpdateAvailable; - - return result; - } - catch (HttpException ex) - { - // users are overreacting to this occasionally failing - if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.Forbidden) - { - HasUpdateAvailable = false; - return new CheckForUpdateResult - { - IsUpdateAvailable = false - }; - } - - throw; - } - } - - protected virtual string UpdateTargetFileName - { - get { return "Mbserver.zip"; } +#if DEBUG + throw new Exception("Unimplemented"); +#endif + return Task.FromResult(new CheckForUpdateResult()); } /// diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 2fb106b3c..b54634387 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,8 +11,8 @@ namespace Jellyfin.Server { public class CoreAppHost : ApplicationHost { - public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) - : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager) + public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) + : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, environmentInfo, imageEncoder, systemEvents, networkManager) { } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 0150cd533..9cc2fe103 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -73,7 +73,6 @@ namespace Jellyfin.Server options, fileSystem, new PowerManagement(), - "embyserver-mono_{version}.zip", environmentInfo, new NullImageEncoder(), new SystemEvents(_loggerFactory.CreateLogger("SystemEvents")), diff --git a/MediaBrowser.Common/Updates/GithubUpdater.cs b/MediaBrowser.Common/Updates/GithubUpdater.cs deleted file mode 100644 index 22ed788e0..000000000 --- a/MediaBrowser.Common/Updates/GithubUpdater.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Updates; - -namespace MediaBrowser.Common.Updates -{ - public class GithubUpdater - { - private readonly IHttpClient _httpClient; - private readonly IJsonSerializer _jsonSerializer; - - public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer) - { - _httpClient = httpClient; - _jsonSerializer = jsonSerializer; - } - - public async Task CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, TimeSpan cacheLength, CancellationToken cancellationToken) - { - var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository); - - var options = new HttpRequestOptions - { - Url = url, - EnableKeepAlive = false, - CancellationToken = cancellationToken, - UserAgent = "Emby/3.0", - BufferContent = false - }; - - if (cacheLength.Ticks > 0) - { - options.CacheMode = CacheMode.Unconditional; - options.CacheLength = cacheLength; - } - - using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false)) - using (var stream = response.Content) - { - var obj = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); - - return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename); - } - } - - private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename) - { - if (updateLevel == PackageVersionClass.Release) - { - // Technically all we need to do is check that it's not pre-release - // But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly. - obj = obj.Where(i => !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) && !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray(); - } - else if (updateLevel == PackageVersionClass.Beta) - { - obj = obj.Where(i => i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray(); - } - else if (updateLevel == PackageVersionClass.Dev) - { - obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray(); - } - - var availableUpdate = obj - .Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename)) - .Where(i => i != null) - .OrderByDescending(i => Version.Parse(i.AvailableVersion)) - .FirstOrDefault(); - - return availableUpdate ?? new CheckForUpdateResult - { - IsUpdateAvailable = false - }; - } - - private bool MatchesUpdateLevel(RootObject i, PackageVersionClass updateLevel) - { - if (updateLevel == PackageVersionClass.Beta) - { - return i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase); - } - if (updateLevel == PackageVersionClass.Dev) - { - return !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || - i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase); - } - - // Technically all we need to do is check that it's not pre-release - // But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly. - return !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) && - !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase); - } - - public async Task> GetLatestReleases(string organzation, string repository, string assetFilename, CancellationToken cancellationToken) - { - var list = new List(); - - var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository); - - var options = new HttpRequestOptions - { - Url = url, - EnableKeepAlive = false, - CancellationToken = cancellationToken, - UserAgent = "Emby/3.0", - BufferContent = false - }; - - using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false)) - using (var stream = response.Content) - { - var obj = await _jsonSerializer.DeserializeFromStreamAsync(stream).ConfigureAwait(false); - - obj = obj.Where(i => (i.assets ?? new List()).Any(a => IsAsset(a, assetFilename, i.tag_name))).ToArray(); - - list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Release)).OrderByDescending(GetVersion).Take(1)); - list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Beta)).OrderByDescending(GetVersion).Take(1)); - list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Dev)).OrderByDescending(GetVersion).Take(1)); - - return list; - } - } - - public Version GetVersion(RootObject obj) - { - Version version; - if (!Version.TryParse(obj.tag_name, out version)) - { - return new Version(1, 0); - } - - return version; - } - - private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename) - { - Version version; - var versionString = obj.tag_name; - if (!Version.TryParse(versionString, out version)) - { - return null; - } - - if (version < minVersion) - { - return null; - } - - var asset = (obj.assets ?? new List()).FirstOrDefault(i => IsAsset(i, assetFilename, versionString)); - - if (asset == null) - { - return null; - } - - return new CheckForUpdateResult - { - AvailableVersion = version.ToString(), - IsUpdateAvailable = version > minVersion, - Package = new PackageVersionInfo - { - classification = obj.prerelease ? - (obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) : - PackageVersionClass.Release, - name = packageName, - sourceUrl = asset.browser_download_url, - targetFilename = targetFilename, - versionStr = version.ToString(), - requiredVersionStr = "1.0.0", - description = obj.body, - infoUrl = obj.html_url - } - }; - } - - private bool IsAsset(Asset asset, string assetFilename, string version) - { - var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty; - - assetFilename = assetFilename.Replace("{version}", version); - - if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1) - { - return true; - } - - return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase); - } - - public class Uploader - { - public string login { get; set; } - public int id { get; set; } - public string avatar_url { get; set; } - public string gravatar_id { get; set; } - public string url { get; set; } - public string html_url { get; set; } - public string followers_url { get; set; } - public string following_url { get; set; } - public string gists_url { get; set; } - public string starred_url { get; set; } - public string subscriptions_url { get; set; } - public string organizations_url { get; set; } - public string repos_url { get; set; } - public string events_url { get; set; } - public string received_events_url { get; set; } - public string type { get; set; } - public bool site_admin { get; set; } - } - - public class Asset - { - public string url { get; set; } - public int id { get; set; } - public string name { get; set; } - public object label { get; set; } - public Uploader uploader { get; set; } - public string content_type { get; set; } - public string state { get; set; } - public int size { get; set; } - public int download_count { get; set; } - public string created_at { get; set; } - public string updated_at { get; set; } - public string browser_download_url { get; set; } - } - - public class Author - { - public string login { get; set; } - public int id { get; set; } - public string avatar_url { get; set; } - public string gravatar_id { get; set; } - public string url { get; set; } - public string html_url { get; set; } - public string followers_url { get; set; } - public string following_url { get; set; } - public string gists_url { get; set; } - public string starred_url { get; set; } - public string subscriptions_url { get; set; } - public string organizations_url { get; set; } - public string repos_url { get; set; } - public string events_url { get; set; } - public string received_events_url { get; set; } - public string type { get; set; } - public bool site_admin { get; set; } - } - - public class RootObject - { - public string url { get; set; } - public string assets_url { get; set; } - public string upload_url { get; set; } - public string html_url { get; set; } - public int id { get; set; } - public string tag_name { get; set; } - public string target_commitish { get; set; } - public string name { get; set; } - public bool draft { get; set; } - public Author author { get; set; } - public bool prerelease { get; set; } - public string created_at { get; set; } - public string published_at { get; set; } - public List assets { get; set; } - public string tarball_url { get; set; } - public string zipball_url { get; set; } - public string body { get; set; } - } - } -} -- cgit v1.2.3 From d15af6eb35c782b0f150fc67bf0f2b0566d86edc Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 3 Jan 2019 21:29:48 +0100 Subject: Removed all old and unused ImageEncoders. Remove solution platform cruft. --- .../Emby.Drawing.ImageMagick.csproj | 19 - Emby.Drawing.ImageMagick/ImageHelpers.cs | 43 --- Emby.Drawing.ImageMagick/ImageMagickEncoder.cs | 354 ----------------- Emby.Drawing.ImageMagick/PercentPlayedDrawer.cs | 40 -- Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs | 125 ------ .../Properties/AssemblyInfo.cs | 36 -- Emby.Drawing.ImageMagick/StripCollageBuilder.cs | 202 ---------- Emby.Drawing.ImageMagick/UnplayedCountIndicator.cs | 73 ---- Emby.Drawing.Net/DynamicImageHelpers.cs | 110 ------ Emby.Drawing.Net/Emby.Drawing.Net.csproj | 17 - Emby.Drawing.Net/GDIImageEncoder.cs | 282 -------------- Emby.Drawing.Net/ImageExtensions.cs | 217 ----------- Emby.Drawing.Net/ImageHelpers.cs | 43 --- Emby.Drawing.Net/PercentPlayedDrawer.cs | 34 -- Emby.Drawing.Net/PlayedIndicatorDrawer.cs | 32 -- Emby.Drawing.Net/Properties/AssemblyInfo.cs | 36 -- Emby.Drawing.Net/UnplayedCountIndicator.cs | 50 --- Emby.Drawing.Net/empty.png | Bin 68 -> 0 bytes Jellyfin.Server/Jellyfin.Server.csproj | 1 - Jellyfin.Server/Program.cs | 27 +- MediaBrowser.sln | 430 +-------------------- 21 files changed, 20 insertions(+), 2151 deletions(-) delete mode 100644 Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj delete mode 100644 Emby.Drawing.ImageMagick/ImageHelpers.cs delete mode 100644 Emby.Drawing.ImageMagick/ImageMagickEncoder.cs delete mode 100644 Emby.Drawing.ImageMagick/PercentPlayedDrawer.cs delete mode 100644 Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs delete mode 100644 Emby.Drawing.ImageMagick/Properties/AssemblyInfo.cs delete mode 100644 Emby.Drawing.ImageMagick/StripCollageBuilder.cs delete mode 100644 Emby.Drawing.ImageMagick/UnplayedCountIndicator.cs delete mode 100644 Emby.Drawing.Net/DynamicImageHelpers.cs delete mode 100644 Emby.Drawing.Net/Emby.Drawing.Net.csproj delete mode 100644 Emby.Drawing.Net/GDIImageEncoder.cs delete mode 100644 Emby.Drawing.Net/ImageExtensions.cs delete mode 100644 Emby.Drawing.Net/ImageHelpers.cs delete mode 100644 Emby.Drawing.Net/PercentPlayedDrawer.cs delete mode 100644 Emby.Drawing.Net/PlayedIndicatorDrawer.cs delete mode 100644 Emby.Drawing.Net/Properties/AssemblyInfo.cs delete mode 100644 Emby.Drawing.Net/UnplayedCountIndicator.cs delete mode 100644 Emby.Drawing.Net/empty.png (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj b/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj deleted file mode 100644 index 2c5c92367..000000000 --- a/Emby.Drawing.ImageMagick/Emby.Drawing.ImageMagick.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netstandard2.0 - false - - - - - - - - - - - - - - diff --git a/Emby.Drawing.ImageMagick/ImageHelpers.cs b/Emby.Drawing.ImageMagick/ImageHelpers.cs deleted file mode 100644 index 866693399..000000000 --- a/Emby.Drawing.ImageMagick/ImageHelpers.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Emby.Drawing.ImageMagick -{ - internal static class ImageHelpers - { - internal static List ProjectPaths(string[] paths, int count) - { - if (count <= 0) - { - throw new ArgumentOutOfRangeException("count"); - } - if (paths.Length == 0) - { - throw new ArgumentOutOfRangeException("paths"); - } - - var list = new List(); - - AddToList(list, paths, count); - - return list.Take(count).ToList(); - } - - private static void AddToList(List list, string[] paths, int count) - { - while (list.Count < count) - { - foreach (var path in paths) - { - list.Add(path); - - if (list.Count >= count) - { - return; - } - } - } - } - } -} diff --git a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs deleted file mode 100644 index 5de8ac383..000000000 --- a/Emby.Drawing.ImageMagick/ImageMagickEncoder.cs +++ /dev/null @@ -1,354 +0,0 @@ -using System.Threading.Tasks; -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.Drawing; -using Microsoft.Extensions.Logging; -using System; -using System.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.System; - -namespace Emby.Drawing.ImageMagick -{ - public class ImageMagickEncoder : IImageEncoder, IDisposable - { - private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; - private readonly Func _httpClientFactory; - private readonly IFileSystem _fileSystem; - private readonly IEnvironmentInfo _environment; - - public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, Func httpClientFactory, IFileSystem fileSystem, IEnvironmentInfo environment) - { - _logger = logger; - _appPaths = appPaths; - _httpClientFactory = httpClientFactory; - _fileSystem = fileSystem; - _environment = environment; - - LogVersion(); - } - - public string[] SupportedInputFormats - { - get - { - // Some common file name extensions for RAW picture files include: .cr2, .crw, .dng, .nef, .orf, .rw2, .pef, .arw, .sr2, .srf, and .tif. - return new[] - { - "tiff", - "tif", - "jpeg", - "jpg", - "png", - "aiff", - "cr2", - "crw", - "dng", - - // Remove until supported - //"nef", - "orf", - "pef", - "arw", - "webp", - "gif", - "bmp", - "erf", - "raf", - "rw2", - "nrw" - }; - } - } - - public ImageFormat[] SupportedOutputFormats - { - get - { - if (_webpAvailable) - { - return new[] { ImageFormat.Webp, ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png }; - } - return new[] { ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png }; - } - } - - private void LogVersion() - { - _logger.LogInformation("ImageMagick version: " + GetVersion()); - TestWebp(); - Wand.SetMagickThreadCount(1); - } - - public static string GetVersion() - { - return Wand.VersionString; - } - - private bool _webpAvailable = true; - private void TestWebp() - { - try - { - var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp"); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath)); - - using (var wand = new MagickWand(1, 1, new PixelWand("none", 1))) - { - wand.SaveImage(tmpPath); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error loading webp"); - _webpAvailable = false; - } - } - - public ImageSize GetImageSize(string path) - { - CheckDisposed(); - - using (var wand = new MagickWand()) - { - wand.PingImage(path); - var img = wand.CurrentImage; - - return new ImageSize - { - Width = img.Width, - Height = img.Height - }; - } - } - - private bool HasTransparency(string path) - { - var ext = Path.GetExtension(path); - - return string.Equals(ext, ".png", StringComparison.OrdinalIgnoreCase) || - string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase); - } - - public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) - { - // Even if the caller specified 100, don't use it because it takes forever - quality = Math.Min(quality, 99); - - if (string.IsNullOrEmpty(options.BackgroundColor) || !HasTransparency(inputPath)) - { - using (var originalImage = new MagickWand(inputPath)) - { - if (options.CropWhiteSpace) - { - originalImage.CurrentImage.TrimImage(10); - } - - var originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height); - - if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize) && !autoOrient) - { - // Just spit out the original file if all the options are default - return inputPath; - } - - var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize); - - var width = Convert.ToInt32(Math.Round(newImageSize.Width)); - var height = Convert.ToInt32(Math.Round(newImageSize.Height)); - - ScaleImage(originalImage, width, height, options.Blur ?? 0); - - if (autoOrient) - { - AutoOrientImage(originalImage); - } - - AddForegroundLayer(originalImage, options); - DrawIndicator(originalImage, width, height, options); - - originalImage.CurrentImage.CompressionQuality = quality; - originalImage.CurrentImage.StripImage(); - - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath)); - - originalImage.SaveImage(outputPath); - } - } - else - { - using (var originalImage = new MagickWand(inputPath)) - { - var originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height); - - var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize); - - var width = Convert.ToInt32(Math.Round(newImageSize.Width)); - var height = Convert.ToInt32(Math.Round(newImageSize.Height)); - - using (var wand = new MagickWand(width, height, options.BackgroundColor)) - { - ScaleImage(originalImage, width, height, options.Blur ?? 0); - - if (autoOrient) - { - AutoOrientImage(originalImage); - } - - wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); - - AddForegroundLayer(wand, options); - DrawIndicator(wand, width, height, options); - - wand.CurrentImage.CompressionQuality = quality; - wand.CurrentImage.StripImage(); - - wand.SaveImage(outputPath); - } - } - } - - return outputPath; - } - - private void AddForegroundLayer(MagickWand wand, ImageProcessingOptions options) - { - if (string.IsNullOrEmpty(options.ForegroundLayer)) - { - return; - } - - Double opacity; - if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4; - - using (var pixel = new PixelWand("#000", opacity)) - using (var overlay = new MagickWand(wand.CurrentImage.Width, wand.CurrentImage.Height, pixel)) - { - wand.CurrentImage.CompositeImage(overlay, CompositeOperator.OverCompositeOp, 0, 0); - } - } - - private void AutoOrientImage(MagickWand wand) - { - wand.CurrentImage.AutoOrientImage(); - } - - public static void RotateImage(MagickWand wand, float angle) - { - using (var pixelWand = new PixelWand("none", 1)) - { - wand.CurrentImage.RotateImage(pixelWand, angle); - } - } - - private void ScaleImage(MagickWand wand, int width, int height, int blur) - { - var useResize = blur > 1; - - if (useResize) - { - wand.CurrentImage.ResizeImage(width, height, FilterTypes.GaussianFilter, blur); - } - else - { - wand.CurrentImage.ScaleImage(width, height); - } - } - - /// - /// Draws the indicator. - /// - /// The wand. - /// Width of the image. - /// Height of the image. - /// The options. - private void DrawIndicator(MagickWand wand, int imageWidth, int imageHeight, ImageProcessingOptions options) - { - if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0)) - { - return; - } - - try - { - if (options.AddPlayedIndicator) - { - var currentImageSize = new ImageSize(imageWidth, imageHeight); - - var task = new PlayedIndicatorDrawer(_appPaths, _httpClientFactory(), _fileSystem).DrawPlayedIndicator(wand, currentImageSize); - Task.WaitAll(task); - } - else if (options.UnplayedCount.HasValue) - { - var currentImageSize = new ImageSize(imageWidth, imageHeight); - - new UnplayedCountIndicator(_appPaths, _fileSystem).DrawUnplayedCountIndicator(wand, currentImageSize, options.UnplayedCount.Value); - } - - if (options.PercentPlayed > 0) - { - new PercentPlayedDrawer().Process(wand, options.PercentPlayed); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error drawing indicator overlay"); - } - } - - public void CreateImageCollage(ImageCollageOptions options) - { - double ratio = options.Width; - ratio /= options.Height; - - if (ratio >= 1.4) - { - new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height); - } - else if (ratio >= .9) - { - new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height); - } - else - { - new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths, options.OutputPath, options.Width, options.Height); - } - } - - public string Name - { - get { return "ImageMagick"; } - } - - private bool _disposed; - public void Dispose() - { - _disposed = true; - Wand.CloseEnvironment(); - } - - private void CheckDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - } - - public bool SupportsImageCollageCreation - { - get - { - return true; - } - } - - public bool SupportsImageEncoding - { - get { return true; } - } - } -} diff --git a/Emby.Drawing.ImageMagick/PercentPlayedDrawer.cs b/Emby.Drawing.ImageMagick/PercentPlayedDrawer.cs deleted file mode 100644 index 90f9d5609..000000000 --- a/Emby.Drawing.ImageMagick/PercentPlayedDrawer.cs +++ /dev/null @@ -1,40 +0,0 @@ -using ImageMagickSharp; -using System; - -namespace Emby.Drawing.ImageMagick -{ - public class PercentPlayedDrawer - { - private const int IndicatorHeight = 8; - - public void Process(MagickWand wand, double percent) - { - var currentImage = wand.CurrentImage; - var height = currentImage.Height; - - using (var draw = new DrawingWand()) - { - using (PixelWand pixel = new PixelWand()) - { - var endX = currentImage.Width - 1; - var endY = height - 1; - - pixel.Color = "black"; - pixel.Opacity = 0.4; - draw.FillColor = pixel; - draw.DrawRectangle(0, endY - IndicatorHeight, endX, endY); - - double foregroundWidth = endX; - foregroundWidth *= percent; - foregroundWidth /= 100; - - pixel.Color = "#52B54B"; - pixel.Opacity = 0; - draw.FillColor = pixel; - draw.DrawRectangle(0, endY - IndicatorHeight, Convert.ToInt32(Math.Round(foregroundWidth)), endY); - wand.CurrentImage.DrawImage(draw); - } - } - } - } -} diff --git a/Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs b/Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs deleted file mode 100644 index 4dccca0c3..000000000 --- a/Emby.Drawing.ImageMagick/PlayedIndicatorDrawer.cs +++ /dev/null @@ -1,125 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Drawing; -using System; -using System.IO; -using System.Threading.Tasks; -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.ImageMagick -{ - public class PlayedIndicatorDrawer - { - private const int FontSize = 52; - private const int OffsetFromTopRightCorner = 38; - - private readonly IApplicationPaths _appPaths; - private readonly IHttpClient _iHttpClient; - private readonly IFileSystem _fileSystem; - - public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem) - { - _appPaths = appPaths; - _iHttpClient = iHttpClient; - _fileSystem = fileSystem; - } - - public async Task DrawPlayedIndicator(MagickWand wand, ImageSize imageSize) - { - var x = imageSize.Width - OffsetFromTopRightCorner; - - using (var draw = new DrawingWand()) - { - using (PixelWand pixel = new PixelWand()) - { - pixel.Color = "#52B54B"; - pixel.Opacity = 0.2; - draw.FillColor = pixel; - draw.DrawCircle(x, OffsetFromTopRightCorner, x - 20, OffsetFromTopRightCorner - 20); - - pixel.Opacity = 0; - pixel.Color = "white"; - draw.FillColor = pixel; - draw.Font = await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf", _appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false); - draw.FontSize = FontSize; - draw.FontStyle = FontStyleType.NormalStyle; - draw.TextAlignment = TextAlignType.CenterAlign; - draw.FontWeight = FontWeightType.RegularStyle; - draw.TextAntialias = true; - draw.DrawAnnotation(x + 4, OffsetFromTopRightCorner + 14, "a"); - - draw.FillColor = pixel; - wand.CurrentImage.DrawImage(draw); - } - } - } - - internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem) - { - var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); - - if (fileSystem.FileExists(filePath)) - { - return filePath; - } - - var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name; - var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf"); - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath)); - - using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath)) - { - using (var fileStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - stream.CopyTo(fileStream); - } - } - - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath)); - - try - { - fileSystem.CopyFile(tempPath, filePath, false); - } - catch (IOException) - { - - } - - return tempPath; - } - - internal static async Task DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem) - { - var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); - - if (fileSystem.FileExists(filePath)) - { - return filePath; - } - - var tempPath = await httpClient.GetTempFile(new HttpRequestOptions - { - Url = url, - Progress = new SimpleProgress() - - }).ConfigureAwait(false); - - fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath)); - - try - { - fileSystem.CopyFile(tempPath, filePath, false); - } - catch (IOException) - { - - } - - return tempPath; - } - } -} diff --git a/Emby.Drawing.ImageMagick/Properties/AssemblyInfo.cs b/Emby.Drawing.ImageMagick/Properties/AssemblyInfo.cs deleted file mode 100644 index 1089607d6..000000000 --- a/Emby.Drawing.ImageMagick/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -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("Emby.Drawing.ImageMagick")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Emby.Drawing.ImageMagick")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[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("6cfee013-6e7c-432b-ac37-cabf0880c69a")] - -// 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.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Emby.Drawing.ImageMagick/StripCollageBuilder.cs b/Emby.Drawing.ImageMagick/StripCollageBuilder.cs deleted file mode 100644 index 26c6c868d..000000000 --- a/Emby.Drawing.ImageMagick/StripCollageBuilder.cs +++ /dev/null @@ -1,202 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using System; -using System.Collections.Generic; - -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.ImageMagick -{ - public class StripCollageBuilder - { - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public void BuildPosterCollage(string[] paths, string outputPath, int width, int height) - { - using (var wand = BuildPosterCollageWand(paths, width, height)) - { - wand.SaveImage(outputPath); - } - } - - public void BuildSquareCollage(string[] paths, string outputPath, int width, int height) - { - using (var wand = BuildSquareCollageWand(paths, width, height)) - { - wand.SaveImage(outputPath); - } - } - - public void BuildThumbCollage(string[] paths, string outputPath, int width, int height) - { - using (var wand = BuildThumbCollageWand(paths, width, height)) - { - wand.SaveImage(outputPath); - } - } - - private MagickWand BuildPosterCollageWand(string[] paths, int width, int height) - { - var inputPaths = ImageHelpers.ProjectPaths(paths, 3); - using (var wandImages = new MagickWand(inputPaths.ToArray())) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - var iSlice = Convert.ToInt32(width * 0.3); - int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .65); - var horizontalImagePadding = Convert.ToInt32(width * 0.0366); - - foreach (var element in wandImages.ImageList) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); - element.Gravity = GravityType.CenterGravity; - element.BackgroundColor = blackPixelWand; - element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter); - int ix = (int)Math.Abs((iWidth - iSlice) / 2); - element.CropImage(iSlice, iHeight, ix, 0); - - element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0); - } - } - - wandImages.SetFirstIterator(); - using (var wandList = wandImages.AppendImages()) - { - wandList.CurrentImage.TrimImage(1); - using (var mwr = wandList.CloneMagickWand()) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - using (var greyPixelWand = new PixelWand(ColorName.Grey70)) - { - mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1); - mwr.CurrentImage.FlipImage(); - - mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel; - mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand); - - using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans)) - { - mwg.OpenImage("gradient:black-none"); - var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111); - mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing); - - wandList.AddImage(mwr); - int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2; - wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .05)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildThumbCollageWand(string[] paths, int width, int height) - { - var inputPaths = ImageHelpers.ProjectPaths(paths, 4); - using (var wandImages = new MagickWand(inputPaths.ToArray())) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - var iSlice = Convert.ToInt32(width * 0.24125); - int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .70); - var horizontalImagePadding = Convert.ToInt32(width * 0.0125); - - foreach (var element in wandImages.ImageList) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); - element.Gravity = GravityType.CenterGravity; - element.BackgroundColor = blackPixelWand; - element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter); - int ix = (int)Math.Abs((iWidth - iSlice) / 2); - element.CropImage(iSlice, iHeight, ix, 0); - - element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0); - } - } - - wandImages.SetFirstIterator(); - using (var wandList = wandImages.AppendImages()) - { - wandList.CurrentImage.TrimImage(1); - using (var mwr = wandList.CloneMagickWand()) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - using (var greyPixelWand = new PixelWand(ColorName.Grey70)) - { - mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1); - mwr.CurrentImage.FlipImage(); - - mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel; - mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand); - - using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans)) - { - mwg.OpenImage("gradient:black-none"); - var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111); - mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing); - - wandList.AddImage(mwr); - int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2; - wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .045)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildSquareCollageWand(string[] paths, int width, int height) - { - var inputPaths = ImageHelpers.ProjectPaths(paths, 4); - var outputWand = new MagickWand(width, height, new PixelWand("none", 1)); - var imageIndex = 0; - var cellWidth = width/2; - var cellHeight = height/2; - for (var x = 0; x < 2; x++) - { - for (var y = 0; y < 2; y++) - { - using (var temp = new MagickWand(inputPaths[imageIndex])) - { - temp.CurrentImage.ScaleImage(cellWidth, cellHeight); - // draw this image into the strip at the next position - var xPos = x*cellWidth; - var yPos = y*cellHeight; - outputWand.CurrentImage.CompositeImage(temp, CompositeOperator.OverCompositeOp, xPos, yPos); - } - imageIndex++; - } - } - - return outputWand; - } - } -} diff --git a/Emby.Drawing.ImageMagick/UnplayedCountIndicator.cs b/Emby.Drawing.ImageMagick/UnplayedCountIndicator.cs deleted file mode 100644 index ee685c3c5..000000000 --- a/Emby.Drawing.ImageMagick/UnplayedCountIndicator.cs +++ /dev/null @@ -1,73 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Drawing; -using System.Globalization; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.ImageMagick -{ - public class UnplayedCountIndicator - { - private const int OffsetFromTopRightCorner = 38; - - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public UnplayedCountIndicator(IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public void DrawUnplayedCountIndicator(MagickWand wand, ImageSize imageSize, int count) - { - var x = imageSize.Width - OffsetFromTopRightCorner; - var text = count.ToString(CultureInfo.InvariantCulture); - - using (var draw = new DrawingWand()) - { - using (PixelWand pixel = new PixelWand()) - { - pixel.Color = "#52B54B"; - pixel.Opacity = 0.2; - draw.FillColor = pixel; - draw.DrawCircle(x, OffsetFromTopRightCorner, x - 20, OffsetFromTopRightCorner - 20); - - pixel.Opacity = 0; - pixel.Color = "white"; - draw.FillColor = pixel; - draw.Font = PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem); - draw.FontStyle = FontStyleType.NormalStyle; - draw.TextAlignment = TextAlignType.CenterAlign; - draw.FontWeight = FontWeightType.RegularStyle; - draw.TextAntialias = true; - - var fontSize = 30; - var y = OffsetFromTopRightCorner + 11; - - if (text.Length == 1) - { - x += 1; - } - else if (text.Length == 2) - { - x += 1; - } - else if (text.Length >= 3) - { - //x += 1; - y -= 2; - fontSize = 24; - } - - draw.FontSize = fontSize; - draw.DrawAnnotation(x, y, text); - - draw.FillColor = pixel; - wand.CurrentImage.DrawImage(draw); - } - - } - } - } -} diff --git a/Emby.Drawing.Net/DynamicImageHelpers.cs b/Emby.Drawing.Net/DynamicImageHelpers.cs deleted file mode 100644 index 1910f7840..000000000 --- a/Emby.Drawing.Net/DynamicImageHelpers.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.Net -{ - public static class DynamicImageHelpers - { - public static void CreateThumbCollage(List files, - IFileSystem fileSystem, - string file, - int width, - int height) - { - const int numStrips = 4; - files = ImageHelpers.ProjectPaths(files, numStrips); - - const int rows = 1; - int cols = numStrips; - - int cellWidth = 2 * (width / 3); - int cellHeight = height; - var index = 0; - - using (var img = new Bitmap(width, height, PixelFormat.Format32bppPArgb)) - { - using (var graphics = Graphics.FromImage(img)) - { - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - - // SourceCopy causes the image to be blank in OSX - //graphics.CompositingMode = CompositingMode.SourceCopy; - - for (var row = 0; row < rows; row++) - { - for (var col = 0; col < cols; col++) - { - var x = col * (cellWidth / 2); - var y = row * cellHeight; - - if (files.Count > index) - { - using (var imgtemp = Image.FromFile(files[index])) - { - graphics.DrawImage(imgtemp, x, y, cellWidth, cellHeight); - } - } - - index++; - } - } - img.Save(file); - } - } - } - - public static void CreateSquareCollage(List files, - IFileSystem fileSystem, - string file, - int width, - int height) - { - files = ImageHelpers.ProjectPaths(files, 4); - - const int rows = 2; - const int cols = 2; - - int singleSize = width / 2; - var index = 0; - - using (var img = new Bitmap(width, height, PixelFormat.Format32bppPArgb)) - { - using (var graphics = Graphics.FromImage(img)) - { - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - - // SourceCopy causes the image to be blank in OSX - //graphics.CompositingMode = CompositingMode.SourceCopy; - - for (var row = 0; row < rows; row++) - { - for (var col = 0; col < cols; col++) - { - var x = col * singleSize; - var y = row * singleSize; - - using (var imgtemp = Image.FromFile(files[index])) - { - graphics.DrawImage(imgtemp, x, y, singleSize, singleSize); - } - index++; - } - } - img.Save(file); - } - } - } - } -} diff --git a/Emby.Drawing.Net/Emby.Drawing.Net.csproj b/Emby.Drawing.Net/Emby.Drawing.Net.csproj deleted file mode 100644 index dc9d35dca..000000000 --- a/Emby.Drawing.Net/Emby.Drawing.Net.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - netstandard2.0 - - - - - - - diff --git a/Emby.Drawing.Net/GDIImageEncoder.cs b/Emby.Drawing.Net/GDIImageEncoder.cs deleted file mode 100644 index 1639125d3..000000000 --- a/Emby.Drawing.Net/GDIImageEncoder.cs +++ /dev/null @@ -1,282 +0,0 @@ -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.Drawing; -using Microsoft.Extensions.Logging; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; -using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat; -using Emby.Drawing; - -namespace Emby.Drawing.Net -{ - public class GDIImageEncoder : IImageEncoder - { - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - - public GDIImageEncoder(IFileSystem fileSystem, ILogger logger) - { - _fileSystem = fileSystem; - _logger = logger; - - LogInfo(); - } - - private void LogInfo() - { - _logger.LogInformation("GDIImageEncoder starting"); - using (var stream = GetType().Assembly.GetManifestResourceStream(GetType().Namespace + ".empty.png")) - { - using (var img = Image.FromStream(stream)) - { - - } - } - _logger.LogInformation("GDIImageEncoder started"); - } - - public string[] SupportedInputFormats - { - get - { - return new[] - { - "png", - "jpeg", - "jpg", - "gif", - "bmp" - }; - } - } - - public ImageFormat[] SupportedOutputFormats - { - get - { - return new[] { ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png }; - } - } - - public ImageSize GetImageSize(string path) - { - using (var image = Image.FromFile(path)) - { - return new ImageSize - { - Width = image.Width, - Height = image.Height - }; - } - } - - private Image GetImage(string path, bool cropWhitespace) - { - if (cropWhitespace) - { - using (var originalImage = (Bitmap)Image.FromFile(path)) - { - return originalImage.CropWhitespace(); - } - } - - return Image.FromFile(path); - } - - public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) - { - using (var originalImage = GetImage(inputPath, options.CropWhiteSpace)) - { - if (options.CropWhiteSpace || !originalImageSize.HasValue) - { - originalImageSize = new ImageSize(originalImage.Width, originalImage.Height); - } - - var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize); - - var newWidth = Convert.ToInt32(Math.Round(newImageSize.Width)); - var newHeight = Convert.ToInt32(Math.Round(newImageSize.Height)); - - // Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here - // Also, Webp only supports Format32bppArgb and Format32bppRgb - var pixelFormat = selectedOutputFormat == ImageFormat.Webp - ? PixelFormat.Format32bppArgb - : PixelFormat.Format32bppPArgb; - - using (var thumbnail = new Bitmap(newWidth, newHeight, pixelFormat)) - { - // Mono throw an exeception if assign 0 to SetResolution - if (originalImage.HorizontalResolution > 0 && originalImage.VerticalResolution > 0) - { - // Preserve the original resolution - thumbnail.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution); - } - - using (var thumbnailGraph = Graphics.FromImage(thumbnail)) - { - thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality; - thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality; - thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic; - thumbnailGraph.PixelOffsetMode = PixelOffsetMode.HighQuality; - - // SourceCopy causes the image to be blank in OSX - //thumbnailGraph.CompositingMode = !hasPostProcessing ? - // CompositingMode.SourceCopy : - // CompositingMode.SourceOver; - - SetBackgroundColor(thumbnailGraph, options); - - thumbnailGraph.DrawImage(originalImage, 0, 0, newWidth, newHeight); - - DrawIndicator(thumbnailGraph, newWidth, newHeight, options); - - var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat); - - // Save to the cache location - using (var cacheFileStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false)) - { - // Save to the memory stream - thumbnail.Save(outputFormat, cacheFileStream, quality); - } - } - } - - } - } - - /// - /// Sets the color of the background. - /// - /// The graphics. - /// The options. - private void SetBackgroundColor(Graphics graphics, ImageProcessingOptions options) - { - var color = options.BackgroundColor; - - if (!string.IsNullOrEmpty(color)) - { - Color drawingColor; - - try - { - drawingColor = ColorTranslator.FromHtml(color); - } - catch - { - drawingColor = ColorTranslator.FromHtml("#" + color); - } - - graphics.Clear(drawingColor); - } - } - - /// - /// Draws the indicator. - /// - /// The graphics. - /// Width of the image. - /// Height of the image. - /// The options. - private void DrawIndicator(Graphics graphics, int imageWidth, int imageHeight, ImageProcessingOptions options) - { - if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0)) - { - return; - } - - try - { - if (options.AddPlayedIndicator) - { - var currentImageSize = new Size(imageWidth, imageHeight); - - new PlayedIndicatorDrawer().DrawPlayedIndicator(graphics, currentImageSize); - } - else if (options.UnplayedCount.HasValue) - { - var currentImageSize = new Size(imageWidth, imageHeight); - - new UnplayedCountIndicator().DrawUnplayedCountIndicator(graphics, currentImageSize, options.UnplayedCount.Value); - } - - if (options.PercentPlayed > 0) - { - var currentImageSize = new Size(imageWidth, imageHeight); - - new PercentPlayedDrawer().Process(graphics, currentImageSize, options.PercentPlayed); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error drawing indicator overlay"); - } - } - - /// - /// Gets the output format. - /// - /// The image. - /// The output format. - /// ImageFormat. - private System.Drawing.Imaging.ImageFormat GetOutputFormat(Image image, ImageFormat outputFormat) - { - switch (outputFormat) - { - case ImageFormat.Bmp: - return System.Drawing.Imaging.ImageFormat.Bmp; - case ImageFormat.Gif: - return System.Drawing.Imaging.ImageFormat.Gif; - case ImageFormat.Jpg: - return System.Drawing.Imaging.ImageFormat.Jpeg; - case ImageFormat.Png: - return System.Drawing.Imaging.ImageFormat.Png; - default: - return image.RawFormat; - } - } - - public void CreateImageCollage(ImageCollageOptions options) - { - double ratio = options.Width; - ratio /= options.Height; - - if (ratio >= 1.4) - { - DynamicImageHelpers.CreateThumbCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Height); - } - else if (ratio >= .9) - { - DynamicImageHelpers.CreateSquareCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Height); - } - else - { - DynamicImageHelpers.CreateSquareCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Width); - } - } - - public void Dispose() - { - } - - public string Name - { - get { return "GDI"; } - } - - public bool SupportsImageCollageCreation - { - get { return true; } - } - - public bool SupportsImageEncoding - { - get { return true; } - } - } -} diff --git a/Emby.Drawing.Net/ImageExtensions.cs b/Emby.Drawing.Net/ImageExtensions.cs deleted file mode 100644 index dec2613d0..000000000 --- a/Emby.Drawing.Net/ImageExtensions.cs +++ /dev/null @@ -1,217 +0,0 @@ -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; - -namespace Emby.Drawing.Net -{ - public static class ImageExtensions - { - /// - /// Saves the image. - /// - /// The output format. - /// The image. - /// To stream. - /// The quality. - public static void Save(this Image image, ImageFormat outputFormat, Stream toStream, int quality) - { - // Use special save methods for jpeg and png that will result in a much higher quality image - // All other formats use the generic Image.Save - if (ImageFormat.Jpeg.Equals(outputFormat)) - { - SaveAsJpeg(image, toStream, quality); - } - else if (ImageFormat.Png.Equals(outputFormat)) - { - image.Save(toStream, ImageFormat.Png); - } - else - { - image.Save(toStream, outputFormat); - } - } - - /// - /// Saves the JPEG. - /// - /// The image. - /// The target. - /// The quality. - public static void SaveAsJpeg(this Image image, Stream target, int quality) - { - using (var encoderParameters = new EncoderParameters(1)) - { - encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality); - image.Save(target, GetImageCodecInfo("image/jpeg"), encoderParameters); - } - } - - private static readonly ImageCodecInfo[] Encoders = ImageCodecInfo.GetImageEncoders(); - - /// - /// Gets the image codec info. - /// - /// Type of the MIME. - /// ImageCodecInfo. - private static ImageCodecInfo GetImageCodecInfo(string mimeType) - { - foreach (var encoder in Encoders) - { - if (string.Equals(encoder.MimeType, mimeType, StringComparison.OrdinalIgnoreCase)) - { - return encoder; - } - } - - return Encoders.Length == 0 ? null : Encoders[0]; - } - - /// - /// Crops an image by removing whitespace and transparency from the edges - /// - /// The BMP. - /// Bitmap. - /// - public static Bitmap CropWhitespace(this Bitmap bmp) - { - var width = bmp.Width; - var height = bmp.Height; - - var topmost = 0; - for (int row = 0; row < height; ++row) - { - if (IsAllWhiteRow(bmp, row, width)) - topmost = row; - else break; - } - - int bottommost = 0; - for (int row = height - 1; row >= 0; --row) - { - if (IsAllWhiteRow(bmp, row, width)) - bottommost = row; - else break; - } - - int leftmost = 0, rightmost = 0; - for (int col = 0; col < width; ++col) - { - if (IsAllWhiteColumn(bmp, col, height)) - leftmost = col; - else - break; - } - - for (int col = width - 1; col >= 0; --col) - { - if (IsAllWhiteColumn(bmp, col, height)) - rightmost = col; - else - break; - } - - if (rightmost == 0) rightmost = width; // As reached left - if (bottommost == 0) bottommost = height; // As reached top. - - var croppedWidth = rightmost - leftmost; - var croppedHeight = bottommost - topmost; - - if (croppedWidth == 0) // No border on left or right - { - leftmost = 0; - croppedWidth = width; - } - - if (croppedHeight == 0) // No border on top or bottom - { - topmost = 0; - croppedHeight = height; - } - - // Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here - var thumbnail = new Bitmap(croppedWidth, croppedHeight, PixelFormat.Format32bppPArgb); - - // Preserve the original resolution - TrySetResolution(thumbnail, bmp.HorizontalResolution, bmp.VerticalResolution); - - using (var thumbnailGraph = Graphics.FromImage(thumbnail)) - { - thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality; - thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality; - thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic; - thumbnailGraph.PixelOffsetMode = PixelOffsetMode.HighQuality; - thumbnailGraph.CompositingMode = CompositingMode.SourceCopy; - - thumbnailGraph.DrawImage(bmp, - new RectangleF(0, 0, croppedWidth, croppedHeight), - new RectangleF(leftmost, topmost, croppedWidth, croppedHeight), - GraphicsUnit.Pixel); - } - return thumbnail; - } - - /// - /// Tries the set resolution. - /// - /// The BMP. - /// The x. - /// The y. - private static void TrySetResolution(Bitmap bmp, float x, float y) - { - if (x > 0 && y > 0) - { - bmp.SetResolution(x, y); - } - } - - /// - /// Determines whether or not a row of pixels is all whitespace - /// - /// The BMP. - /// The row. - /// The width. - /// true if [is all white row] [the specified BMP]; otherwise, false. - private static bool IsAllWhiteRow(Bitmap bmp, int row, int width) - { - for (var i = 0; i < width; ++i) - { - if (!IsWhiteSpace(bmp.GetPixel(i, row))) - { - return false; - } - } - return true; - } - - /// - /// Determines whether or not a column of pixels is all whitespace - /// - /// The BMP. - /// The col. - /// The height. - /// true if [is all white column] [the specified BMP]; otherwise, false. - private static bool IsAllWhiteColumn(Bitmap bmp, int col, int height) - { - for (var i = 0; i < height; ++i) - { - if (!IsWhiteSpace(bmp.GetPixel(col, i))) - { - return false; - } - } - return true; - } - - /// - /// Determines if a color is whitespace - /// - /// The color. - /// true if [is white space] [the specified color]; otherwise, false. - private static bool IsWhiteSpace(Color color) - { - return (color.R == 255 && color.G == 255 && color.B == 255) || color.A == 0; - } - } -} diff --git a/Emby.Drawing.Net/ImageHelpers.cs b/Emby.Drawing.Net/ImageHelpers.cs deleted file mode 100644 index 1afc47cd0..000000000 --- a/Emby.Drawing.Net/ImageHelpers.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Emby.Drawing.Net -{ - internal static class ImageHelpers - { - internal static List ProjectPaths(List paths, int count) - { - if (count <= 0) - { - throw new ArgumentOutOfRangeException("count"); - } - if (paths.Count == 0) - { - throw new ArgumentOutOfRangeException("paths"); - } - - var list = new List(); - - AddToList(list, paths, count); - - return list.Take(count).ToList(); - } - - private static void AddToList(List list, List paths, int count) - { - while (list.Count < count) - { - foreach (var path in paths) - { - list.Add(path); - - if (list.Count >= count) - { - return; - } - } - } - } - } -} diff --git a/Emby.Drawing.Net/PercentPlayedDrawer.cs b/Emby.Drawing.Net/PercentPlayedDrawer.cs deleted file mode 100644 index fac15ba47..000000000 --- a/Emby.Drawing.Net/PercentPlayedDrawer.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Drawing; - -namespace Emby.Drawing.Net -{ - public class PercentPlayedDrawer - { - private const int IndicatorHeight = 8; - - public void Process(Graphics graphics, Size imageSize, double percent) - { - var y = imageSize.Height - IndicatorHeight; - - using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 0, 0, 0))) - { - const int innerX = 0; - var innerY = y; - var innerWidth = imageSize.Width; - var innerHeight = imageSize.Height; - - graphics.FillRectangle(backdroundBrush, innerX, innerY, innerWidth, innerHeight); - - using (var foregroundBrush = new SolidBrush(Color.FromArgb(82, 181, 75))) - { - double foregroundWidth = innerWidth; - foregroundWidth *= percent; - foregroundWidth /= 100; - - graphics.FillRectangle(foregroundBrush, innerX, innerY, Convert.ToInt32(Math.Round(foregroundWidth)), innerHeight); - } - } - } - } -} diff --git a/Emby.Drawing.Net/PlayedIndicatorDrawer.cs b/Emby.Drawing.Net/PlayedIndicatorDrawer.cs deleted file mode 100644 index 53683e6f4..000000000 --- a/Emby.Drawing.Net/PlayedIndicatorDrawer.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Drawing; - -namespace Emby.Drawing.Net -{ - public class PlayedIndicatorDrawer - { - private const int IndicatorHeight = 40; - public const int IndicatorWidth = 40; - private const int FontSize = 40; - private const int OffsetFromTopRightCorner = 10; - - public void DrawPlayedIndicator(Graphics graphics, Size imageSize) - { - var x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner; - - using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 82, 181, 75))) - { - graphics.FillEllipse(backdroundBrush, x, OffsetFromTopRightCorner, IndicatorWidth, IndicatorHeight); - - x = imageSize.Width - 45 - OffsetFromTopRightCorner; - - using (var font = new Font("Webdings", FontSize, FontStyle.Regular, GraphicsUnit.Pixel)) - { - using (var fontBrush = new SolidBrush(Color.White)) - { - graphics.DrawString("a", font, fontBrush, x, OffsetFromTopRightCorner - 2); - } - } - } - } - } -} diff --git a/Emby.Drawing.Net/Properties/AssemblyInfo.cs b/Emby.Drawing.Net/Properties/AssemblyInfo.cs deleted file mode 100644 index 321c3a297..000000000 --- a/Emby.Drawing.Net/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -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("Emby.Drawing.Net")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("Emby.Drawing.Net")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[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("c97a239e-a96c-4d64-a844-ccf8cc30aecb")] - -// 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.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Emby.Drawing.Net/UnplayedCountIndicator.cs b/Emby.Drawing.Net/UnplayedCountIndicator.cs deleted file mode 100644 index a38abeb32..000000000 --- a/Emby.Drawing.Net/UnplayedCountIndicator.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Drawing; - -namespace Emby.Drawing.Net -{ - public class UnplayedCountIndicator - { - private const int IndicatorHeight = 41; - public const int IndicatorWidth = 41; - private const int OffsetFromTopRightCorner = 10; - - public void DrawUnplayedCountIndicator(Graphics graphics, Size imageSize, int count) - { - var x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner; - - using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 82, 181, 75))) - { - graphics.FillEllipse(backdroundBrush, x, OffsetFromTopRightCorner, IndicatorWidth, IndicatorHeight); - - var text = count.ToString(); - - x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner; - var y = OffsetFromTopRightCorner + 6; - var fontSize = 24; - - if (text.Length == 1) - { - x += 10; - } - else if (text.Length == 2) - { - x += 3; - } - else if (text.Length == 3) - { - x += 1; - y += 1; - fontSize = 20; - } - - using (var font = new Font("Sans-Serif", fontSize, FontStyle.Regular, GraphicsUnit.Pixel)) - { - using (var fontBrush = new SolidBrush(Color.White)) - { - graphics.DrawString(text, font, fontBrush, x, y); - } - } - } - } - } -} diff --git a/Emby.Drawing.Net/empty.png b/Emby.Drawing.Net/empty.png deleted file mode 100644 index 34b25c436..000000000 Binary files a/Emby.Drawing.Net/empty.png and /dev/null differ diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index fa603a086..8ecae1b5b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -35,7 +35,6 @@ - diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 9cc2fe103..d5ed61936 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using System.IO; using System.Linq; @@ -194,26 +194,13 @@ namespace Jellyfin.Server IEnvironmentInfo environment, ILocalizationManager localizationManager) { - if (!startupOptions.ContainsOption("-enablegdi")) + try { - try - { - return new SkiaEncoder(logger, appPaths, httpClient, fileSystem, localizationManager); - } - catch (Exception ex) - { - logger.LogInformation(ex, "Skia not available. Will try next image processor. {0}"); - } - - try - { - return new ImageMagickEncoder(logger, appPaths, httpClient, fileSystem, environment); - } - catch (Exception ex) - { - logger.LogInformation(ex, "ImageMagick not available. Will try next image processor."); - } - _logger.LogInformation("Falling back on NullImageEncoder"); + return new SkiaEncoder(logger, appPaths, httpClient, fileSystem, localizationManager); + } + catch (Exception ex) + { + logger.LogInformation(ex, "Skia not available. Will fallback to NullIMageEncoder. {0}"); } return new NullImageEncoder(); diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 077bc6aee..6e9f240b0 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -3,13 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.26730.3 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{E60FB157-87E2-4A41-8B04-27EA49B63B4D}" - ProjectSection(SolutionItems) = preProject - .nuget\NuGet.Config = .nuget\NuGet.Config - .nuget\NuGet.exe = .nuget\NuGet.exe - .nuget\NuGet.targets = .nuget\NuGet.targets - EndProjectSection -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}" @@ -42,8 +35,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSSDP", "RSSDP\RSSDP.csproj EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.csproj", "{805844AB-E92F-45E6-9D99-4F6D48D129A5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Drawing.ImageMagick", "Emby.Drawing.ImageMagick\Emby.Drawing.ImageMagick.csproj", "{6CFEE013-6E7C-432B-AC37-CABF0880C69A}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Drawing.Skia", "Emby.Drawing.Skia\Emby.Drawing.Skia.csproj", "{2312DA6D-FF86-4597-9777-BCEEC32D96DD}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{CB7F2326-6497-4A3D-BA03-48513B17A7BE}" @@ -54,526 +45,131 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Notifications", "Emby. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Naming", "Emby.Naming\Emby.Naming.csproj", "{E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageMagickSharp", "ImageMagickSharp\ImageMagickSharp\ImageMagickSharp.csproj", "{124E0710-6572-497B-B2A5-696AA08AD8BB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "taglib-sharp", "ThirdParty\taglib-sharp\src\taglib-sharp.csproj", "{D45FC504-D06B-41A0-A220-C20B7E8F1304}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "taglib-sharp", "ThirdParty\taglib-sharp\src\taglib-sharp.csproj", "{D45FC504-D06B-41A0-A220-C20B7E8F1304}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.XmlTv", "Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj", "{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.XmlTv", "Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj", "{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IsoMounter", "Emby.IsoMounting\IsoMounter\IsoMounter.csproj", "{9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IsoMounter", "Emby.IsoMounting\IsoMounter\IsoMounter.csproj", "{9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{960295EE-4AF4-4440-A525-B4C295B01A61}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{960295EE-4AF4-4440-A525-B4C295B01A61}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{41093F42-C7CC-4D07-956B-6182CBEDE2EC}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Win32.ActiveCfg = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x64.ActiveCfg = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.ActiveCfg = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.Build.0 = Debug|Any CPU {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Win32.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x64.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Win32.ActiveCfg = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x64.ActiveCfg = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.ActiveCfg = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.Build.0 = Debug|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Win32.ActiveCfg = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x64.ActiveCfg = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.ActiveCfg = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.Build.0 = Release|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Win32.ActiveCfg = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x64.ActiveCfg = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.ActiveCfg = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.Build.0 = Debug|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.Build.0 = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Win32.ActiveCfg = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x64.ActiveCfg = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.ActiveCfg = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.Build.0 = Release|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Win32.ActiveCfg = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x64.ActiveCfg = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.ActiveCfg = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.Build.0 = Debug|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Win32.ActiveCfg = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x64.ActiveCfg = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.ActiveCfg = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.Build.0 = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Win32.ActiveCfg = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x64.ActiveCfg = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.ActiveCfg = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.Build.0 = Debug|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.ActiveCfg = Release|Any CPU {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.Build.0 = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Win32.ActiveCfg = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x64.ActiveCfg = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.ActiveCfg = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.Build.0 = Release|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Win32.ActiveCfg = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x64.ActiveCfg = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.ActiveCfg = Debug|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Win32.ActiveCfg = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x64.ActiveCfg = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Win32.ActiveCfg = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x64.ActiveCfg = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.ActiveCfg = Debug|Any CPU {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.Build.0 = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Win32.ActiveCfg = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x64.ActiveCfg = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.ActiveCfg = Release|Any CPU {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|Win32.ActiveCfg = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|x64.ActiveCfg = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.ActiveCfg = Debug|Any CPU {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|Win32.ActiveCfg = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|x64.ActiveCfg = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.ActiveCfg = Release|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Win32.ActiveCfg = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x64.ActiveCfg = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.ActiveCfg = Debug|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Win32.ActiveCfg = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x64.ActiveCfg = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.ActiveCfg = Release|Any CPU {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Win32.ActiveCfg = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x64.ActiveCfg = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x86.ActiveCfg = Debug|Any CPU {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.ActiveCfg = Release|Any CPU {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.Build.0 = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Win32.ActiveCfg = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x64.ActiveCfg = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x86.ActiveCfg = Release|Any CPU {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Win32.ActiveCfg = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Win32.Build.0 = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|x64.ActiveCfg = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|x64.Build.0 = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|x86.ActiveCfg = Debug|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|x86.Build.0 = Debug|Any CPU {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.ActiveCfg = Release|Any CPU {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.Build.0 = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Win32.ActiveCfg = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Win32.Build.0 = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|x64.ActiveCfg = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|x64.Build.0 = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|x86.ActiveCfg = Release|Any CPU - {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|x86.Build.0 = Release|Any CPU {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Win32.ActiveCfg = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Win32.Build.0 = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|x64.ActiveCfg = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|x64.Build.0 = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|x86.ActiveCfg = Debug|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|x86.Build.0 = Debug|Any CPU {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.ActiveCfg = Release|Any CPU {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.Build.0 = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Win32.ActiveCfg = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Win32.Build.0 = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|x64.ActiveCfg = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|x64.Build.0 = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|x86.ActiveCfg = Release|Any CPU - {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|x86.Build.0 = Release|Any CPU {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Win32.ActiveCfg = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Win32.Build.0 = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|x64.ActiveCfg = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|x64.Build.0 = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|x86.ActiveCfg = Debug|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|x86.Build.0 = Debug|Any CPU {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.ActiveCfg = Release|Any CPU {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.Build.0 = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Win32.ActiveCfg = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Win32.Build.0 = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|x64.ActiveCfg = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|x64.Build.0 = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|x86.ActiveCfg = Release|Any CPU - {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|x86.Build.0 = Release|Any CPU {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Win32.ActiveCfg = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Win32.Build.0 = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|x64.ActiveCfg = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|x64.Build.0 = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|x86.ActiveCfg = Debug|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|x86.Build.0 = Debug|Any CPU {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.ActiveCfg = Release|Any CPU {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.Build.0 = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Win32.ActiveCfg = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Win32.Build.0 = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|x64.ActiveCfg = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|x64.Build.0 = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|x86.ActiveCfg = Release|Any CPU - {E383961B-9356-4D5D-8233-9A1079D03055}.Release|x86.Build.0 = Release|Any CPU {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Win32.ActiveCfg = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Win32.Build.0 = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|x64.ActiveCfg = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|x64.Build.0 = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|x86.ActiveCfg = Debug|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|x86.Build.0 = Debug|Any CPU {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.ActiveCfg = Release|Any CPU {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.Build.0 = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Win32.ActiveCfg = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Win32.Build.0 = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|x64.ActiveCfg = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|x64.Build.0 = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|x86.ActiveCfg = Release|Any CPU - {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|x86.Build.0 = Release|Any CPU {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Win32.ActiveCfg = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Win32.Build.0 = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|x64.ActiveCfg = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|x64.Build.0 = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|x86.ActiveCfg = Debug|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|x86.Build.0 = Debug|Any CPU {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.ActiveCfg = Release|Any CPU {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.Build.0 = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Win32.ActiveCfg = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Win32.Build.0 = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|x64.ActiveCfg = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|x64.Build.0 = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|x86.ActiveCfg = Release|Any CPU - {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|x86.Build.0 = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Win32.ActiveCfg = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Win32.Build.0 = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x64.ActiveCfg = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x64.Build.0 = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x86.ActiveCfg = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x86.Build.0 = Debug|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Any CPU.Build.0 = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Win32.ActiveCfg = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Win32.Build.0 = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x64.ActiveCfg = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x64.Build.0 = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x86.ActiveCfg = Release|Any CPU - {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x86.Build.0 = Release|Any CPU {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|Win32.Build.0 = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x64.ActiveCfg = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x64.Build.0 = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Debug|x86.Build.0 = Debug|Any CPU {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Any CPU.Build.0 = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Win32.ActiveCfg = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|Win32.Build.0 = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x64.ActiveCfg = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x64.Build.0 = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x86.ActiveCfg = Release|Any CPU - {2312DA6D-FF86-4597-9777-BCEEC32D96DD}.Release|x86.Build.0 = Release|Any CPU {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Win32.ActiveCfg = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Win32.Build.0 = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|x64.ActiveCfg = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|x64.Build.0 = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|x86.ActiveCfg = Debug|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|x86.Build.0 = Debug|Any CPU {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.ActiveCfg = Release|Any CPU {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.Build.0 = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Win32.ActiveCfg = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Win32.Build.0 = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|x64.ActiveCfg = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|x64.Build.0 = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|x86.ActiveCfg = Release|Any CPU - {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|x86.Build.0 = Release|Any CPU {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Win32.ActiveCfg = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Win32.Build.0 = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|x64.ActiveCfg = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|x64.Build.0 = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|x86.ActiveCfg = Debug|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|x86.Build.0 = Debug|Any CPU {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Any CPU.ActiveCfg = Release|Any CPU {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Any CPU.Build.0 = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Win32.ActiveCfg = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Win32.Build.0 = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|x64.ActiveCfg = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|x64.Build.0 = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|x86.ActiveCfg = Release|Any CPU - {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|x86.Build.0 = Release|Any CPU {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Win32.Build.0 = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|x64.ActiveCfg = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|x64.Build.0 = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|x86.ActiveCfg = Debug|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|x86.Build.0 = Debug|Any CPU {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Any CPU.Build.0 = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Win32.ActiveCfg = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Win32.Build.0 = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|x64.ActiveCfg = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|x64.Build.0 = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|x86.ActiveCfg = Release|Any CPU - {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|x86.Build.0 = Release|Any CPU {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Win32.ActiveCfg = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Win32.Build.0 = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|x64.ActiveCfg = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|x64.Build.0 = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|x86.ActiveCfg = Debug|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|x86.Build.0 = Debug|Any CPU {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Any CPU.Build.0 = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Win32.ActiveCfg = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Win32.Build.0 = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|x64.ActiveCfg = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|x64.Build.0 = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|x86.ActiveCfg = Release|Any CPU - {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|x86.Build.0 = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|Win32.ActiveCfg = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|Win32.Build.0 = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|x64.ActiveCfg = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|x64.Build.0 = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|x86.ActiveCfg = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Debug|x86.Build.0 = Debug|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|Any CPU.Build.0 = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|Win32.ActiveCfg = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|Win32.Build.0 = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|x64.ActiveCfg = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|x64.Build.0 = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|x86.ActiveCfg = Release|Any CPU - {124E0710-6572-497B-B2A5-696AA08AD8BB}.Release|x86.Build.0 = Release|Any CPU + {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Release|Any CPU.Build.0 = Release|Any CPU {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Win32.ActiveCfg = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Win32.Build.0 = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|x64.ActiveCfg = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|x64.Build.0 = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|x86.ActiveCfg = Debug|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|x86.Build.0 = Debug|Any CPU {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.ActiveCfg = Release|Any CPU {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.Build.0 = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Win32.ActiveCfg = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Win32.Build.0 = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|x64.ActiveCfg = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|x64.Build.0 = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|x86.ActiveCfg = Release|Any CPU - {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|x86.Build.0 = Release|Any CPU {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Win32.ActiveCfg = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Win32.Build.0 = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|x64.ActiveCfg = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|x64.Build.0 = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|x86.ActiveCfg = Debug|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|x86.Build.0 = Debug|Any CPU {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.ActiveCfg = Release|Any CPU {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.Build.0 = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Win32.ActiveCfg = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Win32.Build.0 = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|x64.ActiveCfg = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|x64.Build.0 = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|x86.ActiveCfg = Release|Any CPU - {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|x86.Build.0 = Release|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.Build.0 = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Win32.ActiveCfg = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Win32.Build.0 = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|x64.ActiveCfg = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|x64.Build.0 = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|x86.ActiveCfg = Debug|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|x86.Build.0 = Debug|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.ActiveCfg = Release|Any CPU {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.Build.0 = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Win32.ActiveCfg = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Win32.Build.0 = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|x64.ActiveCfg = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|x64.Build.0 = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|x86.ActiveCfg = Release|Any CPU - {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|x86.Build.0 = Release|Any CPU {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Win32.ActiveCfg = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Win32.Build.0 = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x64.ActiveCfg = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x64.Build.0 = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x86.ActiveCfg = Debug|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|x86.Build.0 = Debug|Any CPU {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.ActiveCfg = Release|Any CPU {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.Build.0 = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Win32.ActiveCfg = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Win32.Build.0 = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x64.ActiveCfg = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x64.Build.0 = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x86.ActiveCfg = Release|Any CPU - {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|x86.Build.0 = Release|Any CPU - {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D45FC504-D06B-41A0-A220-C20B7E8F1304}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- cgit v1.2.3 From 22adb838e6364839647a60731c17b464e494538a Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 3 Jan 2019 21:35:08 +0100 Subject: Removed last using. --- Jellyfin.Server/Program.cs | 1 - 1 file changed, 1 deletion(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index d5ed61936..2dd4d9af6 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -8,7 +8,6 @@ using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; using Emby.Drawing; -using Emby.Drawing.ImageMagick; using Emby.Drawing.Skia; using Emby.Server.Implementations; using Emby.Server.Implementations.EnvironmentInfo; -- cgit v1.2.3 From 2850ff7b8afb2ab1a35c2797f88cef1bc0de8bd9 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 5 Jan 2019 19:12:05 +0100 Subject: Make config path configurable --- .../AppBase/BaseApplicationPaths.cs | 25 +++++++++++++++++-- .../ServerApplicationPaths.cs | 9 +++++-- Jellyfin.Server/Program.cs | 28 +++++++++++++++++++++- 3 files changed, 57 insertions(+), 5 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs index 76d0076a6..3e12bc0b6 100644 --- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs +++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs @@ -12,11 +12,16 @@ namespace Emby.Server.Implementations.AppBase /// /// Initializes a new instance of the class. /// - protected BaseApplicationPaths(string programDataPath, string appFolderPath, string logDirectoryPath) + protected BaseApplicationPaths( + string programDataPath, + string appFolderPath, + string logDirectoryPath = null, + string configurationDirectoryPath = null) { ProgramDataPath = programDataPath; ProgramSystemPath = appFolderPath; LogDirectoryPath = logDirectoryPath; + ConfigurationDirectoryPath = configurationDirectoryPath; } public string ProgramDataPath { get; private set; } @@ -134,6 +139,11 @@ namespace Emby.Server.Implementations.AppBase } } + /// + /// The _config directory + /// + private string _configurationDirectoryPath; + /// /// Gets the path to the application configuration root directory /// @@ -142,7 +152,18 @@ namespace Emby.Server.Implementations.AppBase { get { - return Path.Combine(ProgramDataPath, "config"); + if (string.IsNullOrEmpty(_configurationDirectoryPath)) + { + _configurationDirectoryPath = Path.Combine(ProgramDataPath, "config"); + + Directory.CreateDirectory(_configurationDirectoryPath); + } + + return _configurationDirectoryPath; + } + set + { + _configurationDirectoryPath = value; } } diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs index f5986f943..8a0f2671a 100644 --- a/Emby.Server.Implementations/ServerApplicationPaths.cs +++ b/Emby.Server.Implementations/ServerApplicationPaths.cs @@ -13,8 +13,13 @@ namespace Emby.Server.Implementations /// /// Initializes a new instance of the class. /// - public ServerApplicationPaths(string programDataPath, string appFolderPath, string applicationResourcesPath, string logDirectoryPath = null) - : base(programDataPath, appFolderPath, logDirectoryPath) + public ServerApplicationPaths( + string programDataPath, + string appFolderPath, + string applicationResourcesPath, + string logDirectoryPath = null, + string configurationDirectoryPath = null) + : base(programDataPath, appFolderPath, logDirectoryPath, configurationDirectoryPath) { ApplicationResourcesPath = applicationResourcesPath; } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 2dd4d9af6..d8a746304 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -124,6 +124,32 @@ namespace Jellyfin.Server } } programDataPath = Path.Combine(programDataPath, "jellyfin"); + Directory.CreateDirectory(programDataPath); + } + + string configPath; + if (options.ContainsOption("-configpath")) + { + configPath = options.GetOption("-configpath"); + } + else + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + configPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + } + else + { + // $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored. + configPath = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME"); + // If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config should be used. + if (string.IsNullOrEmpty(configPath)) + { + configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + } + } + configPath = Path.Combine(configPath, "jellyfin"); + Directory.CreateDirectory(configPath); } string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); @@ -138,7 +164,7 @@ namespace Jellyfin.Server string appPath = AppContext.BaseDirectory; - return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir); + return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir, configPath); } private static async Task createLogger(IApplicationPaths appPaths) -- cgit v1.2.3 From 23267bb08f7dcc319c81cdbdaa68efb0c6ea5bc7 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 5 Jan 2019 21:11:55 +0100 Subject: Use -logdir if env var isn't set --- Jellyfin.Server/Program.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index d8a746304..53eaacad0 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -124,13 +124,14 @@ namespace Jellyfin.Server } } programDataPath = Path.Combine(programDataPath, "jellyfin"); + // Ensure the dir exists Directory.CreateDirectory(programDataPath); } string configPath; - if (options.ContainsOption("-configpath")) + if (options.ContainsOption("-configdir")) { - configPath = options.GetOption("-configpath"); + configPath = options.GetOption("-configdir"); } else { @@ -149,15 +150,23 @@ namespace Jellyfin.Server } } configPath = Path.Combine(configPath, "jellyfin"); + // Ensure the dir exists Directory.CreateDirectory(configPath); } string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); if (string.IsNullOrEmpty(logDir)) { - logDir = Path.Combine(programDataPath, "logs"); - // Ensure logDir exists - Directory.CreateDirectory(logDir); + if (options.ContainsOption("-logdir")) + { + logDir = options.GetOption("-logdir"); + } + else + { + logDir = Path.Combine(programDataPath, "logs"); + // Ensure the dir exists + Directory.CreateDirectory(logDir); + } // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); } -- cgit v1.2.3 From f6d50c411f0008497f95e6e7e31eb7f04eb2c360 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 5 Jan 2019 21:16:47 +0100 Subject: Add env vars JELLYFIN_CONFIG_DIR and JELLYFIN_DATA_PATH --- Jellyfin.Server/Program.cs | 72 +++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 33 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 53eaacad0..eedc9f9ce 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -102,56 +102,62 @@ namespace Jellyfin.Server private static ServerApplicationPaths createApplicationPaths(StartupOptions options) { - string programDataPath; - if (options.ContainsOption("-programdata")) + string programDataPath = Environment.GetEnvironmentVariable("JELLYFIN_DATA_PATH"); + if (string.IsNullOrEmpty(programDataPath)) { - programDataPath = options.GetOption("-programdata"); - } - else - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (options.ContainsOption("-programdata")) { - programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + programDataPath = options.GetOption("-programdata"); } else { - // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. - programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); - // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used. - if (string.IsNullOrEmpty(programDataPath)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); } + else + { + // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. + programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); + // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used. + if (string.IsNullOrEmpty(programDataPath)) + { + programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + } + } + programDataPath = Path.Combine(programDataPath, "jellyfin"); + // Ensure the dir exists + Directory.CreateDirectory(programDataPath); } - programDataPath = Path.Combine(programDataPath, "jellyfin"); - // Ensure the dir exists - Directory.CreateDirectory(programDataPath); } - string configPath; - if (options.ContainsOption("-configdir")) + string configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR"); + if (string.IsNullOrEmpty(configDir)) { - configPath = options.GetOption("-configdir"); - } - else - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (options.ContainsOption("-configdir")) { - configPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + configDir = options.GetOption("-configdir"); } else { - // $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored. - configPath = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME"); - // If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config should be used. - if (string.IsNullOrEmpty(configPath)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + configDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); } + else + { + // $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored. + configDir = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME"); + // If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config should be used. + if (string.IsNullOrEmpty(configDir)) + { + configDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + } + } + configDir = Path.Combine(configDir, "jellyfin"); + // Ensure the dir exists + Directory.CreateDirectory(configDir); } - configPath = Path.Combine(configPath, "jellyfin"); - // Ensure the dir exists - Directory.CreateDirectory(configPath); } string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); @@ -173,7 +179,7 @@ namespace Jellyfin.Server string appPath = AppContext.BaseDirectory; - return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir, configPath); + return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir, configDir); } private static async Task createLogger(IApplicationPaths appPaths) -- cgit v1.2.3 From 7af3754a11ad5a4284f107997fb5419a010ce6f3 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 5 Jan 2019 23:08:22 +0100 Subject: Improve logging performance Perform logging to file on a background thread. This means logging won't be bottlenecked by IO. --- Jellyfin.Server/Jellyfin.Server.csproj | 1 + Jellyfin.Server/Program.cs | 4 ++-- Jellyfin.Server/Resources/Configuration/logging.json | 19 ++++++++++++++----- 3 files changed, 17 insertions(+), 7 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 8ecae1b5b..98c578e83 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -25,6 +25,7 @@ + diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 2dd4d9af6..950dea2c9 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -173,10 +173,10 @@ namespace Jellyfin.Server { Serilog.Log.Logger = new LoggerConfiguration() .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}") - .WriteTo.File( + .WriteTo.Async(x => x.File( Path.Combine(appPaths.LogDirectoryPath, "log_.log"), rollingInterval: RollingInterval.Day, - outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}") + outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}")) .Enrich.FromLogContext() .CreateLogger(); diff --git a/Jellyfin.Server/Resources/Configuration/logging.json b/Jellyfin.Server/Resources/Configuration/logging.json index 78f99b2ad..d16991277 100644 --- a/Jellyfin.Server/Resources/Configuration/logging.json +++ b/Jellyfin.Server/Resources/Configuration/logging.json @@ -2,16 +2,25 @@ "Serilog": { "MinimumLevel": "Information", "WriteTo": [ - { "Name": "Console", + { + "Name": "Console", "Args": { "outputTemplate": "[{Timestamp:HH:mm:ss}] [{Level:u3}] {Message:lj}{NewLine}{Exception}" } }, - { "Name": "File", + { + "Name": "Async", "Args": { - "path": "%JELLYFIN_LOG_DIR%//log_.log", - "rollingInterval": "Day", - "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}" + "configure": [ + { + "Name": "File", + "Args": { + "path": "%JELLYFIN_LOG_DIR%//log_.log", + "rollingInterval": "Day", + "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] {Message}{NewLine}{Exception}" + } + } + ] } } ] -- cgit v1.2.3 From c07d5a69635494e1bcd39890df8f929fb7353709 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 2 Jan 2019 15:57:48 +0100 Subject: Remove unused PowerManagement It isn't up to the application to prevent the system from going to sleep --- Emby.Server.Implementations/ApplicationHost.cs | 5 -- .../EntryPoints/KeepServerAwake.cs | 65 ---------------------- .../LiveTv/EmbyTV/EmbyTV.cs | 20 ++++++- .../LiveTv/EmbyTV/TimerManager.cs | 30 ++-------- Jellyfin.Server/CoreAppHost.cs | 4 +- Jellyfin.Server/PowerManagement.cs | 23 -------- Jellyfin.Server/Program.cs | 4 +- MediaBrowser.Model/System/IPowerManagement.cs | 11 ---- 8 files changed, 26 insertions(+), 136 deletions(-) delete mode 100644 Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs delete mode 100644 Jellyfin.Server/PowerManagement.cs delete mode 100644 MediaBrowser.Model/System/IPowerManagement.cs (limited to 'Jellyfin.Server/Program.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 9b9c6146f..950ae10c7 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -369,7 +369,6 @@ namespace Emby.Server.Implementations public StartupOptions StartupOptions { get; private set; } - internal IPowerManagement PowerManagement { get; private set; } internal IImageEncoder ImageEncoder { get; private set; } protected IProcessFactory ProcessFactory { get; private set; } @@ -391,7 +390,6 @@ namespace Emby.Server.Implementations ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, - IPowerManagement powerManagement, IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, ISystemEvents systemEvents, @@ -417,7 +415,6 @@ namespace Emby.Server.Implementations Logger = LoggerFactory.CreateLogger("App"); StartupOptions = options; - PowerManagement = powerManagement; ImageEncoder = imageEncoder; @@ -857,8 +854,6 @@ namespace Emby.Server.Implementations SocketFactory = new SocketFactory(LoggerFactory.CreateLogger("SocketFactory")); RegisterSingleInstance(SocketFactory); - RegisterSingleInstance(PowerManagement); - SecurityManager = new PluginSecurityManager(this, HttpClient, JsonSerializer, ApplicationPaths, LoggerFactory, FileSystemManager, CryptographyProvider); RegisterSingleInstance(SecurityManager); diff --git a/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs b/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs deleted file mode 100644 index a6dadcef0..000000000 --- a/Emby.Server.Implementations/EntryPoints/KeepServerAwake.cs +++ /dev/null @@ -1,65 +0,0 @@ -using MediaBrowser.Controller; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; -using Microsoft.Extensions.Logging; -using System; -using System.Linq; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Threading; - -namespace Emby.Server.Implementations.EntryPoints -{ - public class KeepServerAwake : IServerEntryPoint - { - private readonly ISessionManager _sessionManager; - private readonly ILogger _logger; - private ITimer _timer; - private readonly IServerApplicationHost _appHost; - private readonly ITimerFactory _timerFactory; - private readonly IPowerManagement _powerManagement; - - public KeepServerAwake(ISessionManager sessionManager, ILogger logger, IServerApplicationHost appHost, ITimerFactory timerFactory, IPowerManagement powerManagement) - { - _sessionManager = sessionManager; - _logger = logger; - _appHost = appHost; - _timerFactory = timerFactory; - _powerManagement = powerManagement; - } - - public void Run() - { - _timer = _timerFactory.Create(OnTimerCallback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); - } - - private void OnTimerCallback(object state) - { - var now = DateTime.UtcNow; - - try - { - if (_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 15)) - { - _powerManagement.PreventSystemStandby(); - } - else - { - _powerManagement.AllowSystemStandby(); - } - } - catch (Exception ex) - { - _logger.LogError(ex, "Error resetting system standby timer"); - } - } - - public void Dispose() - { - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } - } - } -} diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 59f9fe86f..81a47bfea 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -75,7 +75,23 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IStreamHelper _streamHelper; - public EmbyTV(IServerApplicationHost appHost, IStreamHelper streamHelper, IMediaSourceManager mediaSourceManager, IAssemblyInfo assemblyInfo, ILogger logger, IJsonSerializer jsonSerializer, IPowerManagement powerManagement, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IMediaEncoder mediaEncoder, ITimerFactory timerFactory, IProcessFactory processFactory, ISystemEvents systemEvents) + public EmbyTV(IServerApplicationHost appHost, + IStreamHelper streamHelper, + IMediaSourceManager mediaSourceManager, + IAssemblyInfo assemblyInfo, + ILogger logger, + IJsonSerializer jsonSerializer, + IHttpClient httpClient, + IServerConfigurationManager config, + ILiveTvManager liveTvManager, + IFileSystem fileSystem, + ILibraryManager libraryManager, + ILibraryMonitor libraryMonitor, + IProviderManager providerManager, + IMediaEncoder mediaEncoder, + ITimerFactory timerFactory, + IProcessFactory processFactory, + ISystemEvents systemEvents) { Current = this; @@ -97,7 +113,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _streamHelper = streamHelper; _seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); - _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger, timerFactory, powerManagement); + _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger, timerFactory); _timerProvider.TimerFired += _timerProvider_TimerFired; _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 76a044c02..e4ab34770 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -9,7 +9,6 @@ using MediaBrowser.Model.Serialization; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Threading; -using MediaBrowser.Model.System; namespace Emby.Server.Implementations.LiveTv.EmbyTV { @@ -20,14 +19,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public event EventHandler> TimerFired; private readonly ITimerFactory _timerFactory; - private readonly IPowerManagement _powerManagement; - public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1, ITimerFactory timerFactory, IPowerManagement powerManagement) + public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1, ITimerFactory timerFactory) : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) { _logger = logger1; _timerFactory = timerFactory; - _powerManagement = powerManagement; } public void RestartTimers() @@ -36,7 +33,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV foreach (var item in GetAll().ToList()) { - AddOrUpdateSystemTimer(item, false); + AddOrUpdateSystemTimer(item); } } @@ -59,7 +56,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public override void Update(TimerInfo item) { base.Update(item); - AddOrUpdateSystemTimer(item, false); + AddOrUpdateSystemTimer(item); } public void AddOrUpdate(TimerInfo item, bool resetTimer) @@ -90,7 +87,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } base.Add(item); - AddOrUpdateSystemTimer(item, true); + AddOrUpdateSystemTimer(item); } private bool ShouldStartTimer(TimerInfo item) @@ -104,7 +101,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return true; } - private void AddOrUpdateSystemTimer(TimerInfo item, bool scheduleSystemWakeTimer) + private void AddOrUpdateSystemTimer(TimerInfo item) { StopTimer(item); @@ -124,23 +121,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var dueTime = startDate - now; StartTimer(item, dueTime); - - if (scheduleSystemWakeTimer && dueTime >= TimeSpan.FromMinutes(15)) - { - ScheduleSystemWakeTimer(startDate, item.Name); - } - } - - private void ScheduleSystemWakeTimer(DateTime startDate, string displayName) - { - try - { - _powerManagement.ScheduleWake(startDate.AddMinutes(-5), displayName); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error scheduling wake timer"); - } } private void StartTimer(TimerInfo item, TimeSpan dueTime) diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b54634387..64e03f22e 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,8 +11,8 @@ namespace Jellyfin.Server { public class CoreAppHost : ApplicationHost { - public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) - : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, environmentInfo, imageEncoder, systemEvents, networkManager) + public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) + : base(applicationPaths, loggerFactory, options, fileSystem, environmentInfo, imageEncoder, systemEvents, networkManager) { } diff --git a/Jellyfin.Server/PowerManagement.cs b/Jellyfin.Server/PowerManagement.cs deleted file mode 100644 index c27c51893..000000000 --- a/Jellyfin.Server/PowerManagement.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using MediaBrowser.Model.System; - -namespace Jellyfin.Server.Native -{ - public class PowerManagement : IPowerManagement - { - public void PreventSystemStandby() - { - - } - - public void AllowSystemStandby() - { - - } - - public void ScheduleWake(DateTime wakeTimeUtc, string displayName) - { - - } - } -} diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 03fdacb26..e9f4708c8 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -13,7 +13,6 @@ using Emby.Server.Implementations; using Emby.Server.Implementations.EnvironmentInfo; using Emby.Server.Implementations.IO; using Emby.Server.Implementations.Networking; -using Jellyfin.Server.Native; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Drawing; @@ -71,7 +70,6 @@ namespace Jellyfin.Server _loggerFactory, options, fileSystem, - new PowerManagement(), environmentInfo, new NullImageEncoder(), new SystemEvents(_loggerFactory.CreateLogger("SystemEvents")), @@ -274,7 +272,7 @@ namespace Jellyfin.Server } } - public static void Shutdown() + public static void Shutdown() { ApplicationTaskCompletionSource.SetResult(true); } diff --git a/MediaBrowser.Model/System/IPowerManagement.cs b/MediaBrowser.Model/System/IPowerManagement.cs deleted file mode 100644 index 03907568c..000000000 --- a/MediaBrowser.Model/System/IPowerManagement.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace MediaBrowser.Model.System -{ - public interface IPowerManagement - { - void PreventSystemStandby(); - void AllowSystemStandby(); - void ScheduleWake(DateTime wakeTimeUtc, string displayName); - } -} -- cgit v1.2.3 From 5623d4b63217cf5d786f0c9ac5407d7b3e6d8831 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 6 Jan 2019 13:53:35 +0100 Subject: BaseApplicationPaths set up default config and log dir paths --- Jellyfin.Server/Program.cs | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) (limited to 'Jellyfin.Server/Program.cs') diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 03fdacb26..f1559e885 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -47,6 +47,8 @@ namespace Jellyfin.Server } ServerApplicationPaths appPaths = createApplicationPaths(options); + // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager + Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath); await createLogger(appPaths); _loggerFactory = new SerilogLoggerFactory(); _logger = _loggerFactory.CreateLogger("Main"); @@ -140,23 +142,8 @@ namespace Jellyfin.Server } else { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - configDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - } - else - { - // $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored. - configDir = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME"); - // If $XDG_CONFIG_HOME is either not set or empty, $HOME/.config should be used. - if (string.IsNullOrEmpty(configDir)) - { - configDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); - } - } - configDir = Path.Combine(configDir, "jellyfin"); - // Ensure the dir exists - Directory.CreateDirectory(configDir); + // Let BaseApplicationPaths set up the default value + configDir = null; } } @@ -169,12 +156,9 @@ namespace Jellyfin.Server } else { - logDir = Path.Combine(programDataPath, "logs"); - // Ensure the dir exists - Directory.CreateDirectory(logDir); + // Let BaseApplicationPaths set up the default value + logDir = null; } - // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager - Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", logDir); } string appPath = AppContext.BaseDirectory; -- cgit v1.2.3