diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
index 64393669b3..c12fc21130 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs
+++ b/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);
}
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index 24059cddd3..6d34ca7708 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/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
///
/// Generates or gets the splashscreen.
///
- /// Optional. Supply the cache tag from the item object to receive strong caching headers.
+ /// Supply the cache tag from the item object to receive strong caching headers.
/// Determines the output format of the image - original,gif,jpg,png.
/// The maximum image width to return.
/// The maximum image height to return.
/// The fixed image width to return.
/// The fixed image height to return.
- /// Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases.
/// Width of box to fill.
/// Height of box to fill.
- /// Optional. Blur image.
- /// Optional. Apply a background color for transparent images.
- /// Optional. Apply a foreground layer on top of the image.
+ /// Blur image.
+ /// Apply a background color for transparent images.
+ /// Apply a foreground layer on top of the image.
+ /// Quality setting, from 0-100.
/// Splashscreen returned successfully.
/// The splashscreen.
[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("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(),
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase));
+ options,
+ cacheDuration,
+ ImmutableDictionary.Empty,
+ Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ .ConfigureAwait(false);
}
///
@@ -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);
diff --git a/Jellyfin.Drawing.Skia/DefaultImageGenerator.cs b/Jellyfin.Drawing.Skia/DefaultImageGenerator.cs
index 4d029d9069..e102b8f49a 100644
--- a/Jellyfin.Drawing.Skia/DefaultImageGenerator.cs
+++ b/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;
+
+///
+/// The default image generator.
+///
+public class DefaultImageGenerator : IImageGenerator
{
+ private readonly IImageEncoder _imageEncoder;
+ private readonly IItemRepository _itemRepository;
+ private readonly ILogger _logger;
+
///
- /// The default image generator.
+ /// Initializes a new instance of the class.
///
- public class DefaultImageGenerator : IImageGenerator
+ /// Instance of the interface.
+ /// Instance of the interface.
+ /// Instance of the interface.
+ public DefaultImageGenerator(
+ IImageEncoder imageEncoder,
+ IItemRepository itemRepository,
+ ILogger logger)
{
- private readonly IImageEncoder _imageEncoder;
- private readonly IItemRepository _itemRepository;
- private readonly ILogger _logger;
+ _imageEncoder = imageEncoder;
+ _itemRepository = itemRepository;
+ _logger = logger;
+ }
- ///
- /// Initializes a new instance of the class.
- ///
- /// Instance of the interface.
- /// Instance of the interface.
- /// Instance of the interface.
- public DefaultImageGenerator(
- IImageEncoder imageEncoder,
- IItemRepository itemRepository,
- ILogger logger)
- {
- _imageEncoder = imageEncoder;
- _itemRepository = itemRepository;
- _logger = logger;
- }
+ ///
+ public IReadOnlyList GetSupportedImages()
+ {
+ return new[] { GeneratedImageType.Splashscreen };
+ }
- ///
- public GeneratedImages[] GetSupportedImages()
+ ///
+ 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();
}
- ///
- 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 GetItemsWithImageType(ImageType imageType)
+ private IReadOnlyList 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[]
{
- CollapseBoxSetItems = false,
- Recursive = true,
- DtoOptions = new DtoOptions(false),
- ImageTypes = new ImageType[] { imageType },
- Limit = 30,
- // todo max parental rating configurable
- MaxParentalRating = 10,
- OrderBy = new ValueTuple[]
- {
- new ValueTuple(ItemSortBy.Random, SortOrder.Ascending)
- },
- IncludeItemTypes = new string[] { "Movie", "Series" }
- });
- }
+ new(ItemSortBy.Random, SortOrder.Ascending)
+ },
+ IncludeItemTypes = new[] { BaseItemKind.Movie, BaseItemKind.Series }
+ });
}
}
diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs
index ac7ab2dee0..b2f9a518a4 100644
--- a/Jellyfin.Server/CoreAppHost.cs
+++ b/Jellyfin.Server/CoreAppHost.cs
@@ -86,7 +86,7 @@ namespace Jellyfin.Server
serviceCollection.AddSingleton();
// TODO search plugins
- ServiceCollection.AddSingleton();
+ serviceCollection.AddSingleton();
// TODO search the assemblies instead of adding them manually?
serviceCollection.AddSingleton();
diff --git a/MediaBrowser.Controller/Drawing/GeneratedImageType.cs b/MediaBrowser.Controller/Drawing/GeneratedImageType.cs
new file mode 100644
index 0000000000..a8db86d4f6
--- /dev/null
+++ b/MediaBrowser.Controller/Drawing/GeneratedImageType.cs
@@ -0,0 +1,12 @@
+namespace MediaBrowser.Controller.Drawing;
+
+///
+/// Which generated image type the supports.
+///
+public enum GeneratedImageType
+{
+ ///
+ /// The splashscreen.
+ ///
+ Splashscreen = 0
+}
diff --git a/MediaBrowser.Controller/Drawing/GeneratedImages.cs b/MediaBrowser.Controller/Drawing/GeneratedImages.cs
deleted file mode 100644
index 47b60979b2..0000000000
--- a/MediaBrowser.Controller/Drawing/GeneratedImages.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace MediaBrowser.Controller.Drawing
-{
- ///
- /// Which generated images an supports.
- ///
- public enum GeneratedImages
- {
- ///
- /// The splashscreen.
- ///
- Splashscreen
- }
-}
diff --git a/MediaBrowser.Controller/Drawing/IImageGenerator.cs b/MediaBrowser.Controller/Drawing/IImageGenerator.cs
index f7e7f83b2e..773db02cb9 100644
--- a/MediaBrowser.Controller/Drawing/IImageGenerator.cs
+++ b/MediaBrowser.Controller/Drawing/IImageGenerator.cs
@@ -1,20 +1,22 @@
-namespace MediaBrowser.Controller.Drawing
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Drawing;
+
+///
+/// Interface for an image generator.
+///
+public interface IImageGenerator
{
///
- /// Interface for an image generator.
+ /// Gets the supported generated images of the image generator.
///
- public interface IImageGenerator
- {
- ///
- /// Gets the supported generated images of the image generator.
- ///
- /// The supported images.
- GeneratedImages[] GetSupportedImages();
+ /// The supported generated image types.
+ IReadOnlyList GetSupportedImages();
- ///
- /// Generates a splashscreen.
- ///
- /// The path where the splashscreen should be saved.
- void GenerateSplashscreen(string outputPath);
- }
+ ///
+ /// Generates a splashscreen.
+ ///
+ /// The image to generate.
+ /// The path where the splashscreen should be saved.
+ void Generate(GeneratedImageType imageTypeType, string outputPath);
}
diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs
index 56e5a87152..01db708856 100644
--- a/MediaBrowser.Model/Branding/BrandingOptions.cs
+++ b/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
+///
+/// The branding options.
+///
+public class BrandingOptions
{
- public class BrandingOptions
- {
- ///
- /// Gets or sets the login disclaimer.
- ///
- /// The login disclaimer.
- public string? LoginDisclaimer { get; set; }
+ ///
+ /// Gets or sets the login disclaimer.
+ ///
+ /// The login disclaimer.
+ public string? LoginDisclaimer { get; set; }
- ///
- /// Gets or sets the custom CSS.
- ///
- /// The custom CSS.
- public string? CustomCss { get; set; }
+ ///
+ /// Gets or sets the custom CSS.
+ ///
+ /// The custom CSS.
+ public string? CustomCss { get; set; }
- ///
- /// Gets or sets the splashscreen location on disk.
- ///
- ///
- /// Not served via the API.
- /// Only used to save the custom uploaded user splashscreen in the configuration file.
- ///
- [JsonIgnore]
- public string? SplashscreenLocation { get; set; }
+ ///
+ /// Gets or sets the splashscreen location on disk.
+ ///
+ ///
+ /// Not served via the API.
+ /// Only used to save the custom uploaded user splashscreen in the configuration file.
+ ///
+ [JsonIgnore]
+ public string? SplashscreenLocation { get; set; }
- ///
- /// Gets the splashscreen url.
- ///
- [XmlIgnore]
- public string? SplashscreenUrl => "/Branding/Splashscreen";
- }
+ ///
+ /// Gets the splashscreen url.
+ ///
+ [XmlIgnore]
+ public string SplashscreenUrl => "/Branding/Splashscreen";
}