Browse Source

Merge pull request #1453 from Bond-009/cleanup2

Improve main code flow
dkanada 6 years ago
parent
commit
b3b08fecb2

+ 2 - 4
Emby.Server.Implementations/IO/ManagedFileSystem.cs

@@ -20,16 +20,14 @@ namespace Emby.Server.Implementations.IO
         protected ILogger Logger;
 
         private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
-
         private readonly string _tempPath;
-
         private readonly bool _isEnvironmentCaseInsensitive;
 
         public ManagedFileSystem(
-            ILoggerFactory loggerFactory,
+            ILogger<ManagedFileSystem> logger,
             IApplicationPaths applicationPaths)
         {
-            Logger = loggerFactory.CreateLogger("FileSystem");
+            Logger = logger;
             _tempPath = applicationPaths.TempDirectory;
 
             _isEnvironmentCaseInsensitive = OperatingSystem.Id == OperatingSystemId.Windows;

+ 32 - 40
Jellyfin.Drawing.Skia/SkiaEncoder.cs

@@ -2,14 +2,11 @@ using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
-using System.Linq;
-using System.Reflection;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Extensions;
 using MediaBrowser.Model.Drawing;
 using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.IO;
 using Microsoft.Extensions.Logging;
 using SkiaSharp;
 
@@ -18,24 +15,28 @@ namespace Jellyfin.Drawing.Skia
     public class SkiaEncoder : IImageEncoder
     {
         private readonly ILogger _logger;
-        private static IApplicationPaths _appPaths;
-        private readonly IFileSystem _fileSystem;
-        private static ILocalizationManager _localizationManager;
+        private readonly IApplicationPaths _appPaths;
+        private readonly ILocalizationManager _localizationManager;
+
+        private static readonly HashSet<string> _transparentImageTypes
+            = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".png", ".gif", ".webp" };
 
         public SkiaEncoder(
-            ILoggerFactory loggerFactory,
+            ILogger<SkiaEncoder> logger,
             IApplicationPaths appPaths,
-            IFileSystem fileSystem,
             ILocalizationManager localizationManager)
         {
-            _logger = loggerFactory.CreateLogger("ImageEncoder");
+            _logger = logger;
             _appPaths = appPaths;
-            _fileSystem = fileSystem;
             _localizationManager = localizationManager;
-
-            LogVersion();
         }
 
+        public string Name => "Skia";
+
+        public bool SupportsImageCollageCreation => true;
+
+        public bool SupportsImageEncoding => true;
+
         public IReadOnlyCollection<string> SupportedInputFormats =>
             new HashSet<string>(StringComparer.OrdinalIgnoreCase)
             {
@@ -66,17 +67,15 @@ namespace Jellyfin.Drawing.Skia
         public IReadOnlyCollection<ImageFormat> SupportedOutputFormats
             => new HashSet<ImageFormat>() { ImageFormat.Webp, ImageFormat.Jpg, ImageFormat.Png };
 
-        private void LogVersion()
+        /// <summary>
+        /// Test to determine if the native lib is available
+        /// </summary>
+        public static void TestSkia()
         {
             // test an operation that requires the native library
             SKPMColor.PreMultiply(SKColors.Black);
-
-            _logger.LogInformation("SkiaSharp version: " + GetVersion());
         }
 
-        public static Version GetVersion()
-            => typeof(SKBitmap).GetTypeInfo().Assembly.GetName().Version;
-
         private static bool IsTransparent(SKColor color)
             => (color.Red == 255 && color.Green == 255 && color.Blue == 255) || color.Alpha == 0;
 
@@ -106,6 +105,7 @@ namespace Jellyfin.Drawing.Skia
                     return false;
                 }
             }
+
             return true;
         }
 
@@ -118,6 +118,7 @@ namespace Jellyfin.Drawing.Skia
                     return false;
                 }
             }
+
             return true;
         }
 
@@ -197,7 +198,7 @@ namespace Jellyfin.Drawing.Skia
         private static bool HasDiacritics(string text)
             => !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal);
 
-        private static bool RequiresSpecialCharacterHack(string path)
+        private bool RequiresSpecialCharacterHack(string path)
         {
             if (_localizationManager.HasUnicodeCategory(path, UnicodeCategory.OtherLetter))
             {
@@ -212,7 +213,7 @@ namespace Jellyfin.Drawing.Skia
             return false;
         }
 
-        private static string NormalizePath(string path, IFileSystem fileSystem)
+        private string NormalizePath(string path)
         {
             if (!RequiresSpecialCharacterHack(path))
             {
@@ -255,21 +256,18 @@ namespace Jellyfin.Drawing.Skia
             }
         }
 
-        private static readonly HashSet<string> TransparentImageTypes
-            = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".png", ".gif", ".webp" };
-
-        internal static SKBitmap Decode(string path, bool forceCleanBitmap, IFileSystem fileSystem, ImageOrientation? orientation, out SKEncodedOrigin origin)
+        internal SKBitmap Decode(string path, bool forceCleanBitmap, ImageOrientation? orientation, out SKEncodedOrigin origin)
         {
             if (!File.Exists(path))
             {
                 throw new FileNotFoundException("File not found", path);
             }
 
-            var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path));
+            var requiresTransparencyHack = _transparentImageTypes.Contains(Path.GetExtension(path));
 
             if (requiresTransparencyHack || forceCleanBitmap)
             {
-                using (var stream = new SKFileStream(NormalizePath(path, fileSystem)))
+                using (var stream = new SKFileStream(NormalizePath(path)))
                 using (var codec = SKCodec.Create(stream))
                 {
                     if (codec == null)
@@ -290,11 +288,11 @@ namespace Jellyfin.Drawing.Skia
                 }
             }
 
-            var resultBitmap = SKBitmap.Decode(NormalizePath(path, fileSystem));
+            var resultBitmap = SKBitmap.Decode(NormalizePath(path));
 
             if (resultBitmap == null)
             {
-                return Decode(path, true, fileSystem, orientation, out origin);
+                return Decode(path, true, orientation, out origin);
             }
 
             // If we have to resize these they often end up distorted
@@ -302,7 +300,7 @@ namespace Jellyfin.Drawing.Skia
             {
                 using (resultBitmap)
                 {
-                    return Decode(path, true, fileSystem, orientation, out origin);
+                    return Decode(path, true, orientation, out origin);
                 }
             }
 
@@ -314,13 +312,13 @@ namespace Jellyfin.Drawing.Skia
         {
             if (cropWhitespace)
             {
-                using (var bitmap = Decode(path, forceAnalyzeBitmap, _fileSystem, orientation, out origin))
+                using (var bitmap = Decode(path, forceAnalyzeBitmap, orientation, out origin))
                 {
                     return CropWhiteSpace(bitmap);
                 }
             }
 
-            return Decode(path, forceAnalyzeBitmap, _fileSystem, orientation, out origin);
+            return Decode(path, forceAnalyzeBitmap, orientation, out origin);
         }
 
         private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient, ImageOrientation? orientation)
@@ -607,16 +605,16 @@ namespace Jellyfin.Drawing.Skia
 
             if (ratio >= 1.4)
             {
-                new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
+                new StripCollageBuilder(this).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);
+                new StripCollageBuilder(this).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
             }
             else
             {
                 // TODO: Create Poster collage capability
-                new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
+                new StripCollageBuilder(this).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
             }
         }
 
@@ -645,11 +643,5 @@ namespace Jellyfin.Drawing.Skia
                 _logger.LogError(ex, "Error drawing indicator overlay");
             }
         }
-
-        public string Name => "Skia";
-
-        public bool SupportsImageCollageCreation => true;
-
-        public bool SupportsImageEncoding => true;
     }
 }

+ 23 - 25
Jellyfin.Drawing.Skia/StripCollageBuilder.cs

@@ -1,21 +1,17 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.IO;
 using SkiaSharp;
 
 namespace Jellyfin.Drawing.Skia
 {
     public class StripCollageBuilder
     {
-        private readonly IApplicationPaths _appPaths;
-        private readonly IFileSystem _fileSystem;
+        private readonly SkiaEncoder _skiaEncoder;
 
-        public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
+        public StripCollageBuilder(SkiaEncoder skiaEncoder)
         {
-            _appPaths = appPaths;
-            _fileSystem = fileSystem;
+            _skiaEncoder = skiaEncoder;
         }
 
         public static SKEncodedImageFormat GetEncodedFormat(string outputPath)
@@ -25,19 +21,28 @@ namespace Jellyfin.Drawing.Skia
                 throw new ArgumentNullException(nameof(outputPath));
             }
 
-            var ext = Path.GetExtension(outputPath).ToLowerInvariant();
+            var ext = Path.GetExtension(outputPath);
 
-            if (ext == ".jpg" || ext == ".jpeg")
+            if (string.Equals(ext, ".jpg", StringComparison.OrdinalIgnoreCase)
+                || string.Equals(ext, ".jpeg", StringComparison.OrdinalIgnoreCase))
+            {
                 return SKEncodedImageFormat.Jpeg;
+            }
 
-            if (ext == ".webp")
+            if (string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase))
+            {
                 return SKEncodedImageFormat.Webp;
+            }
 
-            if (ext == ".gif")
+            if (string.Equals(ext, ".gif", StringComparison.OrdinalIgnoreCase))
+            {
                 return SKEncodedImageFormat.Gif;
+            }
 
-            if (ext == ".bmp")
+            if (string.Equals(ext, ".bmp", StringComparison.OrdinalIgnoreCase))
+            {
                 return SKEncodedImageFormat.Bmp;
+            }
 
             // default to png
             return SKEncodedImageFormat.Png;
@@ -47,25 +52,19 @@ namespace Jellyfin.Drawing.Skia
         {
             using (var bitmap = BuildSquareCollageBitmap(paths, width, height))
             using (var outputStream = new SKFileWStream(outputPath))
+            using (var pixmap = new SKPixmap(new SKImageInfo(width, height), bitmap.GetPixels()))
             {
-                using (var pixmap = new SKPixmap(new SKImageInfo(width, height), bitmap.GetPixels()))
-                {
-                    pixmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
-                }
+                pixmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
             }
         }
 
         public void BuildThumbCollage(string[] paths, string outputPath, int width, int height)
         {
             using (var bitmap = BuildThumbCollageBitmap(paths, width, height))
+            using (var outputStream = new SKFileWStream(outputPath))
+            using (var pixmap = new SKPixmap(new SKImageInfo(width, height), bitmap.GetPixels()))
             {
-                using (var outputStream = new SKFileWStream(outputPath))
-                {
-                    using (var pixmap = new SKPixmap(new SKImageInfo(width, height), bitmap.GetPixels()))
-                    {
-                        pixmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
-                    }
-                }
+                pixmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
             }
         }
 
@@ -127,7 +126,7 @@ namespace Jellyfin.Drawing.Skia
                     currentIndex = 0;
                 }
 
-                bitmap = SkiaEncoder.Decode(paths[currentIndex], false, _fileSystem, null, out var origin);
+                bitmap = _skiaEncoder.Decode(paths[currentIndex], false, null, out var origin);
 
                 imagesTested[currentIndex] = 0;
 
@@ -156,7 +155,6 @@ namespace Jellyfin.Drawing.Skia
                 {
                     for (var y = 0; y < 2; y++)
                     {
-
                         using (var currentBitmap = GetNextValidImage(paths, imageIndex, out int newIndex))
                         {
                             imageIndex = newIndex;

+ 35 - 21
Jellyfin.Server/Program.cs

@@ -34,7 +34,6 @@ namespace Jellyfin.Server
         private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory();
         private static ILogger _logger;
         private static bool _restartOnShutdown;
-        private static IConfiguration appConfig;
 
         public static Task Main(string[] args)
         {
@@ -76,7 +75,7 @@ namespace Jellyfin.Server
             // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
             Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
 
-            appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false);
+            IConfiguration appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false);
 
             CreateLogger(appConfig, appPaths);
 
@@ -116,8 +115,6 @@ namespace Jellyfin.Server
 
             ApplicationHost.LogEnvironmentInfo(_logger, appPaths);
 
-            SQLitePCL.Batteries_V2.Init();
-
             // Increase the max http request limit
             // The default connection limit is 10 for ASP.NET hosted applications and 2 for all others.
             ServicePointManager.DefaultConnectionLimit = Math.Max(96, ServicePointManager.DefaultConnectionLimit);
@@ -129,20 +126,20 @@ namespace Jellyfin.Server
             ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
 #pragma warning restore CA5359
 
-            var fileSystem = new ManagedFileSystem(_loggerFactory, appPaths);
+            SQLitePCL.Batteries_V2.Init();
 
             using (var appHost = new CoreAppHost(
                 appPaths,
                 _loggerFactory,
                 options,
-                fileSystem,
+                new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
                 new NullImageEncoder(),
                 new NetworkManager(_loggerFactory),
                 appConfig))
             {
                 await appHost.InitAsync(new ServiceCollection()).ConfigureAwait(false);
 
-                appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager);
+                appHost.ImageProcessor.ImageEncoder = GetImageEncoder(appPaths, appHost.LocalizationManager);
 
                 await appHost.RunStartupTasksAsync().ConfigureAwait(false);
 
@@ -165,7 +162,7 @@ namespace Jellyfin.Server
 
         /// <summary>
         /// Create the data, config and log paths from the variety of inputs(command line args,
-        /// environment variables) or decide on what default to use.  For Windows it's %AppPath%
+        /// environment variables) or decide on what default to use. For Windows it's %AppPath%
         /// for everything else the XDG approach is followed:
         /// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
         /// </summary>
@@ -187,7 +184,9 @@ namespace Jellyfin.Server
                 if (string.IsNullOrEmpty(dataDir))
                 {
                     // LocalApplicationData follows the XDG spec on unix machines
-                    dataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "jellyfin");
+                    dataDir = Path.Combine(
+                        Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
+                        "jellyfin");
                 }
             }
 
@@ -206,20 +205,26 @@ namespace Jellyfin.Server
 
                 if (string.IsNullOrEmpty(configDir))
                 {
-                    if (options.DataDir != null || Directory.Exists(Path.Combine(dataDir, "config")) || RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+                    if (options.DataDir != null
+                        || Directory.Exists(Path.Combine(dataDir, "config"))
+                        || RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                     {
                         // Hang config folder off already set dataDir
                         configDir = Path.Combine(dataDir, "config");
                     }
                     else
                     {
-                        // $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored.
+                        // $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, a default equal to $HOME /.config should be used.
+                        // If $XDG_CONFIG_HOME is either not set or empty,
+                        // a default equal to $HOME /.config should be used.
                         if (string.IsNullOrEmpty(configDir))
                         {
-                            configDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config");
+                            configDir = Path.Combine(
+                                Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
+                                ".config");
                         }
 
                         configDir = Path.Combine(configDir, "jellyfin");
@@ -247,13 +252,17 @@ namespace Jellyfin.Server
                     }
                     else
                     {
-                        // $XDG_CACHE_HOME defines the base directory relative to which user specific non-essential data files should be stored.
+                        // $XDG_CACHE_HOME defines the base directory relative to which
+                        // user specific non-essential data files should be stored.
                         cacheDir = Environment.GetEnvironmentVariable("XDG_CACHE_HOME");
 
-                        // If $XDG_CACHE_HOME is either not set or empty, a default equal to $HOME/.cache should be used.
+                        // If $XDG_CACHE_HOME is either not set or empty,
+                        // a default equal to $HOME/.cache should be used.
                         if (string.IsNullOrEmpty(cacheDir))
                         {
-                            cacheDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cache");
+                            cacheDir = Path.Combine(
+                                Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
+                                ".cache");
                         }
 
                         cacheDir = Path.Combine(cacheDir, "jellyfin");
@@ -362,17 +371,22 @@ namespace Jellyfin.Server
         }
 
         private static IImageEncoder GetImageEncoder(
-            IFileSystem fileSystem,
             IApplicationPaths appPaths,
             ILocalizationManager localizationManager)
         {
             try
             {
-                return new SkiaEncoder(_loggerFactory, appPaths, fileSystem, localizationManager);
+                // Test if the native lib is available
+                SkiaEncoder.TestSkia();
+
+                return new SkiaEncoder(
+                    _loggerFactory.CreateLogger<SkiaEncoder>(),
+                    appPaths,
+                    localizationManager);
             }
             catch (Exception ex)
             {
-                _logger.LogInformation(ex, "Skia not available. Will fallback to NullIMageEncoder.");
+                _logger.LogWarning(ex, "Skia not available. Will fallback to NullIMageEncoder.");
             }
 
             return new NullImageEncoder();
@@ -386,7 +400,7 @@ namespace Jellyfin.Server
 
             if (string.IsNullOrWhiteSpace(module))
             {
-                module = Environment.GetCommandLineArgs().First();
+                module = Environment.GetCommandLineArgs()[0];
             }
 
             string commandLineArgsString;
@@ -398,7 +412,7 @@ namespace Jellyfin.Server
             else
             {
                 commandLineArgsString = string.Join(
-                    " ",
+                    ' ',
                     Environment.GetCommandLineArgs().Skip(1).Select(NormalizeCommandLineArgument));
             }