From ecb73168b34e3d58dff186b6d90fb4bdd192e24a Mon Sep 17 00:00:00 2001 From: Cody Robibero Date: Mon, 10 Jan 2022 08:25:46 -0700 Subject: [PATCH] Suggestions from review --- Emby.Drawing/NullImageEncoder.cs | 6 +++ .../Library/SplashscreenPostScanTask.cs | 51 +++++++++---------- .../Tasks/RefreshMediaLibraryTask.cs | 17 +------ Jellyfin.Api/Controllers/ImageController.cs | 21 ++++---- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 8 +++ Jellyfin.Drawing.Skia/SplashscreenBuilder.cs | 14 ++--- Jellyfin.Server/CoreAppHost.cs | 3 -- .../Drawing/IImageEncoder.cs | 7 +++ .../Drawing/IImageGenerator.cs | 22 -------- 9 files changed, 64 insertions(+), 85 deletions(-) rename Jellyfin.Drawing.Skia/DefaultImageGenerator.cs => Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs (66%) delete mode 100644 MediaBrowser.Controller/Drawing/IImageGenerator.cs diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index 1c05aa9161..d0a26b713b 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -43,6 +43,12 @@ namespace Emby.Drawing throw new NotImplementedException(); } + /// + public void CreateSplashscreen(IReadOnlyList posters, IReadOnlyList backdrops) + { + throw new NotImplementedException(); + } + /// public string GetImageBlurHash(int xComp, int yComp, string path) { diff --git a/Jellyfin.Drawing.Skia/DefaultImageGenerator.cs b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs similarity index 66% rename from Jellyfin.Drawing.Skia/DefaultImageGenerator.cs rename to Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs index e102b8f49a..65445d3aff 100644 --- a/Jellyfin.Drawing.Skia/DefaultImageGenerator.cs +++ b/Emby.Server.Implementations/Library/SplashscreenPostScanTask.cs @@ -1,68 +1,65 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using Microsoft.Extensions.Logging; -namespace Jellyfin.Drawing.Skia; +namespace Emby.Server.Implementations.Library; /// -/// The default image generator. +/// The splashscreen post scan task. /// -public class DefaultImageGenerator : IImageGenerator +public class SplashscreenPostScanTask : ILibraryPostScanTask { - private readonly IImageEncoder _imageEncoder; private readonly IItemRepository _itemRepository; - private readonly ILogger _logger; + private readonly IImageEncoder _imageEncoder; + private readonly ILogger _logger; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - public DefaultImageGenerator( - IImageEncoder imageEncoder, + /// Instance of the interface. + /// Instance of the interface. + public SplashscreenPostScanTask( IItemRepository itemRepository, - ILogger logger) + IImageEncoder imageEncoder, + ILogger logger) { - _imageEncoder = imageEncoder; _itemRepository = itemRepository; + _imageEncoder = imageEncoder; _logger = logger; } - /// - public IReadOnlyList GetSupportedImages() - { - return new[] { GeneratedImageType.Splashscreen }; - } - - /// - public void Generate(GeneratedImageType imageTypeType, string outputPath) + /// + public Task Run(IProgress progress, CancellationToken cancellationToken) { var posters = GetItemsWithImageType(ImageType.Primary).Select(x => x.GetImages(ImageType.Primary).First().Path).ToList(); - var landscape = GetItemsWithImageType(ImageType.Thumb).Select(x => x.GetImages(ImageType.Thumb).First().Path).ToList(); - if (landscape.Count == 0) + var backdrops = GetItemsWithImageType(ImageType.Thumb).Select(x => x.GetImages(ImageType.Thumb).First().Path).ToList(); + if (backdrops.Count == 0) { // Thumb images fit better because they include the title in the image but are not provided with TMDb. // Using backdrops as a fallback to generate an image at all _logger.LogDebug("No thumb images found. Using backdrops to generate splashscreen"); - landscape = GetItemsWithImageType(ImageType.Backdrop).Select(x => x.GetImages(ImageType.Backdrop).First().Path).ToList(); + backdrops = GetItemsWithImageType(ImageType.Backdrop).Select(x => x.GetImages(ImageType.Backdrop).First().Path).ToList(); } - var splashBuilder = new SplashscreenBuilder((SkiaEncoder)_imageEncoder); - splashBuilder.GenerateSplash(posters, landscape, outputPath); + _imageEncoder.CreateSplashscreen(posters, backdrops); + return Task.CompletedTask; } private IReadOnlyList GetItemsWithImageType(ImageType imageType) { - // todo make included libraries configurable + // TODO make included libraries configurable return _itemRepository.GetItemList(new InternalItemsQuery { CollapseBoxSetItems = false, @@ -70,7 +67,7 @@ public class DefaultImageGenerator : IImageGenerator DtoOptions = new DtoOptions(false), ImageTypes = new[] { imageType }, Limit = 30, - // todo max parental rating configurable + // TODO max parental rating configurable MaxParentalRating = 10, OrderBy = new ValueTuple[] { diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs index c12fc21130..7c27ae3844 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs @@ -2,12 +2,9 @@ using System; using System.Collections.Generic; -using System.IO; using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.Library; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Tasks; @@ -24,26 +21,16 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks /// private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; - private readonly IImageGenerator _imageGenerator; - private readonly IApplicationPaths _applicationPaths; /// /// Initializes a new instance of the class. /// /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. - /// Instance of the interface. - public RefreshMediaLibraryTask( - ILibraryManager libraryManager, - ILocalizationManager localization, - IImageGenerator imageGenerator, - IApplicationPaths applicationPaths) + public RefreshMediaLibraryTask(ILibraryManager libraryManager, ILocalizationManager localization) { _libraryManager = libraryManager; _localization = localization; - _imageGenerator = imageGenerator; - _applicationPaths = applicationPaths; } /// @@ -83,8 +70,6 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks progress.Report(0); - _imageGenerator.Generate(GeneratedImageType.Splashscreen, Path.Combine(_applicationPaths.DataPath, "splashscreen.webp")); - return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken); } } diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 6d34ca7708..b44a21d033 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -48,7 +48,7 @@ namespace Jellyfin.Api.Controllers private readonly ILogger _logger; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IApplicationPaths _appPaths; - private readonly IImageGenerator _imageGenerator; + private readonly IImageEncoder _imageEncoder; /// /// Initializes a new instance of the class. @@ -62,7 +62,7 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. + /// Instance of the interface. public ImageController( IUserManager userManager, ILibraryManager libraryManager, @@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers ILogger logger, IServerConfigurationManager serverConfigurationManager, IApplicationPaths appPaths, - IImageGenerator imageGenerator) + IImageEncoder imageEncoder) { _userManager = userManager; _libraryManager = libraryManager; @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers _logger = logger; _serverConfigurationManager = serverConfigurationManager; _appPaths = appPaths; - _imageGenerator = imageGenerator; + _imageEncoder = imageEncoder; } /// @@ -1737,19 +1737,20 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? foregroundLayer, [FromQuery, Range(0, 100)] int quality = 90) { - string splashscreenPath; var brandingOptions = _serverConfigurationManager.GetConfiguration("branding"); - if (!string.IsNullOrWhiteSpace(brandingOptions.SplashscreenLocation)) + string splashscreenPath; + + if (!string.IsNullOrWhiteSpace(brandingOptions.SplashscreenLocation) + && System.IO.File.Exists(brandingOptions.SplashscreenLocation)) { - splashscreenPath = brandingOptions.SplashscreenLocation!; + splashscreenPath = brandingOptions.SplashscreenLocation; } else { splashscreenPath = Path.Combine(_appPaths.DataPath, "splashscreen.webp"); - - if (!System.IO.File.Exists(splashscreenPath) && _imageGenerator.GetSupportedImages().Contains(GeneratedImageType.Splashscreen)) + if (!System.IO.File.Exists(splashscreenPath)) { - _imageGenerator.Generate(GeneratedImageType.Splashscreen, splashscreenPath); + return NotFound(); } } diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 6d0a5ac2b9..c40103f827 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -492,6 +492,14 @@ namespace Jellyfin.Drawing.Skia } } + /// + public void CreateSplashscreen(IReadOnlyList posters, IReadOnlyList backdrops) + { + var splashBuilder = new SplashscreenBuilder(this); + var outputPath = Path.Combine(_appPaths.DataPath, "splashscreen.webp"); + splashBuilder.GenerateSplash(posters, backdrops, outputPath); + } + private void DrawIndicator(SKCanvas canvas, int imageWidth, int imageHeight, ImageProcessingOptions options) { try diff --git a/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs b/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs index 9f801c3208..132c35e67c 100644 --- a/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs +++ b/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs @@ -32,12 +32,12 @@ namespace Jellyfin.Drawing.Skia /// Generate a splashscreen. /// /// The poster paths. - /// The landscape paths. + /// The landscape paths. /// The output path. - public void GenerateSplash(IReadOnlyList posters, IReadOnlyList backdrop, string outputPath) + public void GenerateSplash(IReadOnlyList posters, IReadOnlyList backdrops, string outputPath) { - var wall = GenerateCollage(posters, backdrop); - var transformed = Transform3D(wall); + using var wall = GenerateCollage(posters, backdrops); + using var transformed = Transform3D(wall); using var outputStream = new SKFileWStream(outputPath); using var pixmap = new SKPixmap(new SKImageInfo(FinalWidth, FinalHeight), transformed.GetPixels()); @@ -48,9 +48,9 @@ namespace Jellyfin.Drawing.Skia /// Generates a collage of posters and landscape pictures. /// /// The poster paths. - /// The landscape paths. + /// The landscape paths. /// The created collage as a bitmap. - private SKBitmap GenerateCollage(IReadOnlyList posters, IReadOnlyList backdrop) + private SKBitmap GenerateCollage(IReadOnlyList posters, IReadOnlyList backdrops) { var random = new Random(); @@ -82,7 +82,7 @@ namespace Jellyfin.Drawing.Skia posterIndex = newPosterIndex; break; default: - currentImage = SkiaHelper.GetNextValidImage(_skiaEncoder, backdrop, backdropIndex, out int newBackdropIndex); + currentImage = SkiaHelper.GetNextValidImage(_skiaEncoder, backdrops, backdropIndex, out int newBackdropIndex); backdropIndex = newBackdropIndex; break; } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b2f9a518a4..67e50b92d9 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -85,9 +85,6 @@ namespace Jellyfin.Server serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - // TODO search plugins - serviceCollection.AddSingleton(); - // TODO search the assemblies instead of adding them manually? serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/MediaBrowser.Controller/Drawing/IImageEncoder.cs b/MediaBrowser.Controller/Drawing/IImageEncoder.cs index 4e67cfee4f..e5c8ebfaf9 100644 --- a/MediaBrowser.Controller/Drawing/IImageEncoder.cs +++ b/MediaBrowser.Controller/Drawing/IImageEncoder.cs @@ -74,5 +74,12 @@ namespace MediaBrowser.Controller.Drawing /// The options to use when creating the collage. /// Optional. void CreateImageCollage(ImageCollageOptions options, string? libraryName); + + /// + /// Creates a new splashscreen image. + /// + /// The list of poster paths. + /// The list of backdrop paths. + void CreateSplashscreen(IReadOnlyList posters, IReadOnlyList backdrops); } } diff --git a/MediaBrowser.Controller/Drawing/IImageGenerator.cs b/MediaBrowser.Controller/Drawing/IImageGenerator.cs deleted file mode 100644 index 773db02cb9..0000000000 --- a/MediaBrowser.Controller/Drawing/IImageGenerator.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Drawing; - -/// -/// Interface for an image generator. -/// -public interface IImageGenerator -{ - /// - /// Gets the supported generated images of the image generator. - /// - /// The supported generated image types. - IReadOnlyList GetSupportedImages(); - - /// - /// Generates a splashscreen. - /// - /// The image to generate. - /// The path where the splashscreen should be saved. - void Generate(GeneratedImageType imageTypeType, string outputPath); -}