Cody Robibero 3 vuotta sitten
vanhempi
sitoutus
360fd70fc7

+ 1 - 1
Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs

@@ -83,7 +83,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 
             progress.Report(0);
 
-            _imageGenerator.GenerateSplashscreen(Path.Combine(_applicationPaths.DataPath, "splashscreen.webp"));
+            _imageGenerator.Generate(GeneratedImageType.Splashscreen, Path.Combine(_applicationPaths.DataPath, "splashscreen.webp"));
 
             return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
         }

+ 17 - 15
Jellyfin.Api/Controllers/ImageController.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Collections.Immutable;
 using System.ComponentModel.DataAnnotations;
 using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
@@ -1705,18 +1706,18 @@ namespace Jellyfin.Api.Controllers
         /// <summary>
         /// Generates or gets the splashscreen.
         /// </summary>
-        /// <param name="tag">Optional. Supply the cache tag from the item object to receive strong caching headers.</param>
+        /// <param name="tag">Supply the cache tag from the item object to receive strong caching headers.</param>
         /// <param name="format">Determines the output format of the image - original,gif,jpg,png.</param>
         /// <param name="maxWidth">The maximum image width to return.</param>
         /// <param name="maxHeight">The maximum image height to return.</param>
         /// <param name="width">The fixed image width to return.</param>
         /// <param name="height">The fixed image height to return.</param>
-        /// <param name="quality">Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.</param>
         /// <param name="fillWidth">Width of box to fill.</param>
         /// <param name="fillHeight">Height of box to fill.</param>
-        /// <param name="blur">Optional. Blur image.</param>
-        /// <param name="backgroundColor">Optional. Apply a background color for transparent images.</param>
-        /// <param name="foregroundLayer">Optional. Apply a foreground layer on top of the image.</param>
+        /// <param name="blur">Blur image.</param>
+        /// <param name="backgroundColor">Apply a background color for transparent images.</param>
+        /// <param name="foregroundLayer">Apply a foreground layer on top of the image.</param>
+        /// <param name="quality">Quality setting, from 0-100.</param>
         /// <response code="200">Splashscreen returned successfully.</response>
         /// <returns>The splashscreen.</returns>
         [HttpGet("Branding/Splashscreen")]
@@ -1729,12 +1730,12 @@ namespace Jellyfin.Api.Controllers
             [FromQuery] int? maxHeight,
             [FromQuery] int? width,
             [FromQuery] int? height,
-            [FromQuery] int? quality,
             [FromQuery] int? fillWidth,
             [FromQuery] int? fillHeight,
             [FromQuery] int? blur,
             [FromQuery] string? backgroundColor,
-            [FromQuery] string? foregroundLayer)
+            [FromQuery] string? foregroundLayer,
+            [FromQuery, Range(0, 100)] int quality = 90)
         {
             string splashscreenPath;
             var brandingOptions = _serverConfigurationManager.GetConfiguration<BrandingOptions>("branding");
@@ -1746,9 +1747,9 @@ namespace Jellyfin.Api.Controllers
             {
                 splashscreenPath = Path.Combine(_appPaths.DataPath, "splashscreen.webp");
 
-                if (!System.IO.File.Exists(splashscreenPath) && _imageGenerator.GetSupportedImages().Contains(GeneratedImages.Splashscreen))
+                if (!System.IO.File.Exists(splashscreenPath) && _imageGenerator.GetSupportedImages().Contains(GeneratedImageType.Splashscreen))
                 {
-                    _imageGenerator.GenerateSplashscreen(splashscreenPath);
+                    _imageGenerator.Generate(GeneratedImageType.Splashscreen, splashscreenPath);
                 }
             }
 
@@ -1771,18 +1772,20 @@ namespace Jellyfin.Api.Controllers
                 MaxWidth = maxWidth,
                 FillHeight = fillHeight,
                 FillWidth = fillWidth,
-                Quality = quality ?? 100,
+                Quality = quality,
                 Width = width,
                 Blur = blur,
                 BackgroundColor = backgroundColor,
                 ForegroundLayer = foregroundLayer,
                 SupportedOutputFormats = outputFormats
             };
+
             return await GetImageResult(
-                options,
-                cacheDuration,
-                new Dictionary<string, string>(),
-                Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase));
+                    options,
+                    cacheDuration,
+                    ImmutableDictionary<string, string>.Empty,
+                    Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+                .ConfigureAwait(false);
         }
 
         /// <summary>
@@ -1815,7 +1818,6 @@ namespace Jellyfin.Api.Controllers
             brandingOptions.SplashscreenLocation = filePath;
             _serverConfigurationManager.SaveConfiguration("branding", brandingOptions);
 
-            // use FileShare.None as this bypasses dotnet bug dotnet/runtime#42790 .
             await using (var fs = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous))
             {
                 await memoryStream.CopyToAsync(fs, CancellationToken.None).ConfigureAwait(false);

+ 56 - 57
Jellyfin.Drawing.Skia/DefaultImageGenerator.cs

@@ -10,74 +10,73 @@ using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Querying;
 using Microsoft.Extensions.Logging;
 
-namespace Jellyfin.Drawing.Skia
+namespace Jellyfin.Drawing.Skia;
+
+/// <summary>
+/// The default image generator.
+/// </summary>
+public class DefaultImageGenerator : IImageGenerator
 {
+    private readonly IImageEncoder _imageEncoder;
+    private readonly IItemRepository _itemRepository;
+    private readonly ILogger _logger;
+
     /// <summary>
-    /// The default image generator.
+    /// Initializes a new instance of the <see cref="DefaultImageGenerator"/> class.
     /// </summary>
-    public class DefaultImageGenerator : IImageGenerator
+    /// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param>
+    /// <param name="itemRepository">Instance of the <see cref="IItemRepository"/> interface.</param>
+    /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
+    public DefaultImageGenerator(
+        IImageEncoder imageEncoder,
+        IItemRepository itemRepository,
+        ILogger<DefaultImageGenerator> logger)
     {
-        private readonly IImageEncoder _imageEncoder;
-        private readonly IItemRepository _itemRepository;
-        private readonly ILogger _logger;
+        _imageEncoder = imageEncoder;
+        _itemRepository = itemRepository;
+        _logger = logger;
+    }
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="DefaultImageGenerator"/> class.
-        /// </summary>
-        /// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param>
-        /// <param name="itemRepository">Instance of the <see cref="IItemRepository"/> interface.</param>
-        /// <param name="logger">Instance of the <see cref="ILogger"/> interface.</param>
-        public DefaultImageGenerator(
-            IImageEncoder imageEncoder,
-            IItemRepository itemRepository,
-            ILogger<DefaultImageGenerator> logger)
-        {
-            _imageEncoder = imageEncoder;
-            _itemRepository = itemRepository;
-            _logger = logger;
-        }
+    /// <inheritdoc/>
+    public IReadOnlyList<GeneratedImageType> GetSupportedImages()
+    {
+        return new[] { GeneratedImageType.Splashscreen };
+    }
 
-        /// <inheritdoc/>
-        public GeneratedImages[] GetSupportedImages()
+    /// <inheritdoc/>
+    public void Generate(GeneratedImageType imageTypeType, string outputPath)
+    {
+        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)
         {
-            return new[] { GeneratedImages.Splashscreen };
+            // 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();
         }
 
-        /// <inheritdoc/>
-        public void GenerateSplashscreen(string outputPath)
-        {
-            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)
-            {
-                // 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();
-            }
-
-            var splashBuilder = new SplashscreenBuilder((SkiaEncoder)_imageEncoder);
-            splashBuilder.GenerateSplash(posters, landscape, outputPath);
-        }
+        var splashBuilder = new SplashscreenBuilder((SkiaEncoder)_imageEncoder);
+        splashBuilder.GenerateSplash(posters, landscape, outputPath);
+    }
 
-        private IReadOnlyList<BaseItem> GetItemsWithImageType(ImageType imageType)
+    private IReadOnlyList<BaseItem> GetItemsWithImageType(ImageType imageType)
+    {
+        // todo make included libraries configurable
+        return _itemRepository.GetItemList(new InternalItemsQuery
         {
-            // todo make included libraries configurable
-            return _itemRepository.GetItemList(new InternalItemsQuery
+            CollapseBoxSetItems = false,
+            Recursive = true,
+            DtoOptions = new DtoOptions(false),
+            ImageTypes = new[] { imageType },
+            Limit = 30,
+            // todo max parental rating configurable
+            MaxParentalRating = 10,
+            OrderBy = new ValueTuple<string, SortOrder>[]
             {
-                CollapseBoxSetItems = false,
-                Recursive = true,
-                DtoOptions = new DtoOptions(false),
-                ImageTypes = new ImageType[] { imageType },
-                Limit = 30,
-                // todo max parental rating configurable
-                MaxParentalRating = 10,
-                OrderBy = new ValueTuple<string, SortOrder>[]
-                {
-                    new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending)
-                },
-                IncludeItemTypes = new string[] { "Movie", "Series" }
-            });
-        }
+                new(ItemSortBy.Random, SortOrder.Ascending)
+            },
+            IncludeItemTypes = new[] { BaseItemKind.Movie, BaseItemKind.Series }
+        });
     }
 }

+ 1 - 1
Jellyfin.Server/CoreAppHost.cs

@@ -86,7 +86,7 @@ namespace Jellyfin.Server
             serviceCollection.AddSingleton<IDeviceManager, DeviceManager>();
 
             // TODO search plugins
-            ServiceCollection.AddSingleton<IImageGenerator, DefaultImageGenerator>();
+            serviceCollection.AddSingleton<IImageGenerator, DefaultImageGenerator>();
 
             // TODO search the assemblies instead of adding them manually?
             serviceCollection.AddSingleton<IWebSocketListener, SessionWebSocketListener>();

+ 12 - 0
MediaBrowser.Controller/Drawing/GeneratedImageType.cs

@@ -0,0 +1,12 @@
+namespace MediaBrowser.Controller.Drawing;
+
+/// <summary>
+/// Which generated image type the <see cref="IImageGenerator"/> supports.
+/// </summary>
+public enum GeneratedImageType
+{
+    /// <summary>
+    /// The splashscreen.
+    /// </summary>
+    Splashscreen = 0
+}

+ 0 - 13
MediaBrowser.Controller/Drawing/GeneratedImages.cs

@@ -1,13 +0,0 @@
-namespace MediaBrowser.Controller.Drawing
-{
-    /// <summary>
-    /// Which generated images an <see cref="IImageGenerator"/> supports.
-    /// </summary>
-    public enum GeneratedImages
-    {
-        /// <summary>
-        /// The splashscreen.
-        /// </summary>
-        Splashscreen
-    }
-}

+ 17 - 15
MediaBrowser.Controller/Drawing/IImageGenerator.cs

@@ -1,20 +1,22 @@
-namespace MediaBrowser.Controller.Drawing
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Drawing;
+
+/// <summary>
+/// Interface for an image generator.
+/// </summary>
+public interface IImageGenerator
 {
     /// <summary>
-    /// Interface for an image generator.
+    /// Gets the supported generated images of the image generator.
     /// </summary>
-    public interface IImageGenerator
-    {
-        /// <summary>
-        /// Gets the supported generated images of the image generator.
-        /// </summary>
-        /// <returns>The supported images.</returns>
-        GeneratedImages[] GetSupportedImages();
+    /// <returns>The supported generated image types.</returns>
+    IReadOnlyList<GeneratedImageType> GetSupportedImages();
 
-        /// <summary>
-        /// Generates a splashscreen.
-        /// </summary>
-        /// <param name="outputPath">The path where the splashscreen should be saved.</param>
-        void GenerateSplashscreen(string outputPath);
-    }
+    /// <summary>
+    /// Generates a splashscreen.
+    /// </summary>
+    /// <param name="imageTypeType">The image to generate.</param>
+    /// <param name="outputPath">The path where the splashscreen should be saved.</param>
+    void Generate(GeneratedImageType imageTypeType, string outputPath);
 }

+ 29 - 29
MediaBrowser.Model/Branding/BrandingOptions.cs

@@ -1,38 +1,38 @@
 using System.Text.Json.Serialization;
 using System.Xml.Serialization;
 
-#pragma warning disable CS1591
+namespace MediaBrowser.Model.Branding;
 
-namespace MediaBrowser.Model.Branding
+/// <summary>
+/// The branding options.
+/// </summary>
+public class BrandingOptions
 {
-    public class BrandingOptions
-    {
-        /// <summary>
-        /// Gets or sets the login disclaimer.
-        /// </summary>
-        /// <value>The login disclaimer.</value>
-        public string? LoginDisclaimer { get; set; }
+    /// <summary>
+    /// Gets or sets the login disclaimer.
+    /// </summary>
+    /// <value>The login disclaimer.</value>
+    public string? LoginDisclaimer { get; set; }
 
-        /// <summary>
-        /// Gets or sets the custom CSS.
-        /// </summary>
-        /// <value>The custom CSS.</value>
-        public string? CustomCss { get; set; }
+    /// <summary>
+    /// Gets or sets the custom CSS.
+    /// </summary>
+    /// <value>The custom CSS.</value>
+    public string? CustomCss { get; set; }
 
-        /// <summary>
-        /// Gets or sets the splashscreen location on disk.
-        /// </summary>
-        /// <remarks>
-        /// Not served via the API.
-        /// Only used to save the custom uploaded user splashscreen in the configuration file.
-        /// </remarks>
-        [JsonIgnore]
-        public string? SplashscreenLocation { get; set; }
+    /// <summary>
+    /// Gets or sets the splashscreen location on disk.
+    /// </summary>
+    /// <remarks>
+    /// Not served via the API.
+    /// Only used to save the custom uploaded user splashscreen in the configuration file.
+    /// </remarks>
+    [JsonIgnore]
+    public string? SplashscreenLocation { get; set; }
 
-        /// <summary>
-        /// Gets the splashscreen url.
-        /// </summary>
-        [XmlIgnore]
-        public string? SplashscreenUrl => "/Branding/Splashscreen";
-    }
+    /// <summary>
+    /// Gets the splashscreen url.
+    /// </summary>
+    [XmlIgnore]
+    public string SplashscreenUrl => "/Branding/Splashscreen";
 }