SplashscreenPostScanTask.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using Jellyfin.Data.Enums;
  7. using Jellyfin.Database.Implementations.Enums;
  8. using MediaBrowser.Controller.Drawing;
  9. using MediaBrowser.Controller.Dto;
  10. using MediaBrowser.Controller.Entities;
  11. using MediaBrowser.Controller.Library;
  12. using MediaBrowser.Controller.Persistence;
  13. using MediaBrowser.Model.Entities;
  14. using MediaBrowser.Model.Querying;
  15. using Microsoft.Extensions.Logging;
  16. namespace Emby.Server.Implementations.Library;
  17. /// <summary>
  18. /// The splashscreen post scan task.
  19. /// </summary>
  20. public class SplashscreenPostScanTask : ILibraryPostScanTask
  21. {
  22. private readonly IItemRepository _itemRepository;
  23. private readonly IImageEncoder _imageEncoder;
  24. private readonly ILogger<SplashscreenPostScanTask> _logger;
  25. /// <summary>
  26. /// Initializes a new instance of the <see cref="SplashscreenPostScanTask"/> class.
  27. /// </summary>
  28. /// <param name="itemRepository">Instance of the <see cref="IItemRepository"/> interface.</param>
  29. /// <param name="imageEncoder">Instance of the <see cref="IImageEncoder"/> interface.</param>
  30. /// <param name="logger">Instance of the <see cref="ILogger{SplashscreenPostScanTask}"/> interface.</param>
  31. public SplashscreenPostScanTask(
  32. IItemRepository itemRepository,
  33. IImageEncoder imageEncoder,
  34. ILogger<SplashscreenPostScanTask> logger)
  35. {
  36. _itemRepository = itemRepository;
  37. _imageEncoder = imageEncoder;
  38. _logger = logger;
  39. }
  40. /// <inheritdoc />
  41. public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
  42. {
  43. var posters = GetItemsWithImageType(ImageType.Primary)
  44. .Select(x => x.GetImages(ImageType.Primary).FirstOrDefault()?.Path)
  45. .Where(path => !string.IsNullOrEmpty(path))
  46. .Select(path => path!)
  47. .ToList();
  48. var backdrops = GetItemsWithImageType(ImageType.Thumb)
  49. .Select(x => x.GetImages(ImageType.Thumb).FirstOrDefault()?.Path)
  50. .Where(path => !string.IsNullOrEmpty(path))
  51. .Select(path => path!)
  52. .ToList();
  53. if (backdrops.Count == 0)
  54. {
  55. // Thumb images fit better because they include the title in the image but are not provided with TMDb.
  56. // Using backdrops as a fallback to generate an image at all
  57. _logger.LogDebug("No thumb images found. Using backdrops to generate splashscreen");
  58. backdrops = GetItemsWithImageType(ImageType.Backdrop)
  59. .Select(x => x.GetImages(ImageType.Backdrop).FirstOrDefault()?.Path)
  60. .Where(path => !string.IsNullOrEmpty(path))
  61. .Select(path => path!)
  62. .ToList();
  63. }
  64. _imageEncoder.CreateSplashscreen(posters, backdrops);
  65. return Task.CompletedTask;
  66. }
  67. private IReadOnlyList<BaseItem> GetItemsWithImageType(ImageType imageType)
  68. {
  69. // TODO make included libraries configurable
  70. return _itemRepository.GetItemList(new InternalItemsQuery
  71. {
  72. CollapseBoxSetItems = false,
  73. Recursive = true,
  74. DtoOptions = new DtoOptions(false),
  75. ImageTypes = new[] { imageType },
  76. Limit = 30,
  77. // TODO max parental rating configurable
  78. MaxParentalRating = 10,
  79. OrderBy = new[]
  80. {
  81. (ItemSortBy.Random, SortOrder.Ascending)
  82. },
  83. IncludeItemTypes = new[] { BaseItemKind.Movie, BaseItemKind.Series }
  84. });
  85. }
  86. }