aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs13
-rw-r--r--Emby.Server.Implementations/Data/ItemTypeLookup.cs139
-rw-r--r--Emby.Server.Implementations/MediaEncoder/EncodingManager.cs4
-rw-r--r--Jellyfin.Data/Entities/AncestorId.cs2
-rw-r--r--Jellyfin.Data/Entities/AttachmentStreamInfo.cs2
-rw-r--r--Jellyfin.Data/Entities/BaseItemEntity.cs (renamed from Jellyfin.Data/Entities/BaseItem.cs)3
-rw-r--r--Jellyfin.Data/Entities/BaseItemProvider.cs23
-rw-r--r--Jellyfin.Data/Entities/Chapter.cs2
-rw-r--r--Jellyfin.Data/Entities/ItemValue.cs23
-rw-r--r--Jellyfin.Data/Entities/MediaStreamInfo.cs2
-rw-r--r--Jellyfin.Data/Entities/People.cs34
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.cs (renamed from Jellyfin.Server.Implementations/Item/BaseItemManager.cs)394
-rw-r--r--Jellyfin.Server.Implementations/Item/ChapterRepository.cs (renamed from Jellyfin.Server.Implementations/Item/ChapterManager.cs)56
-rw-r--r--Jellyfin.Server.Implementations/Item/MediaAttachmentRepository.cs (renamed from Jellyfin.Server.Implementations/Item/MediaAttachmentManager.cs)2
-rw-r--r--Jellyfin.Server.Implementations/Item/MediaStreamRepository.cs (renamed from Jellyfin.Server.Implementations/Item/MediaStreamManager.cs)10
-rw-r--r--Jellyfin.Server.Implementations/Item/PeopleRepository.cs (renamed from Jellyfin.Server.Implementations/Item/PeopleManager.cs)7
-rw-r--r--Jellyfin.Server.Implementations/JellyfinDbContext.cs2
-rw-r--r--Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs4
-rw-r--r--Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs2
-rw-r--r--MediaBrowser.Controller/Chapters/ChapterManager.cs24
-rw-r--r--MediaBrowser.Controller/Chapters/IChapterManager.cs35
-rw-r--r--MediaBrowser.Controller/Chapters/IChapterRepository.cs49
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs25
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs7
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs1
-rw-r--r--MediaBrowser.Controller/Persistence/IItemTypeLookup.cs57
-rw-r--r--MediaBrowser.Controller/Persistence/IMediaAttachmentRepository.cs (renamed from MediaBrowser.Controller/Persistence/IMediaAttachmentManager.cs)3
-rw-r--r--MediaBrowser.Controller/Persistence/IMediaStreamRepository.cs (renamed from MediaBrowser.Controller/Persistence/IMediaStreamManager.cs)7
-rw-r--r--MediaBrowser.Controller/Persistence/IPeopleRepository.cs (renamed from MediaBrowser.Controller/Persistence/IPeopleManager.cs)3
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs4
-rw-r--r--MediaBrowser.Providers/MediaInfo/ProbeProvider.cs4
-rw-r--r--src/Jellyfin.Drawing/ImageProcessor.cs25
32 files changed, 601 insertions, 367 deletions
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index bdf013b5d..fbec4726f 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -40,6 +40,7 @@ using Jellyfin.MediaEncoding.Hls.Playlist;
using Jellyfin.Networking.Manager;
using Jellyfin.Networking.Udp;
using Jellyfin.Server.Implementations;
+using Jellyfin.Server.Implementations.Item;
using Jellyfin.Server.Implementations.MediaSegments;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
@@ -83,7 +84,6 @@ using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.System;
using MediaBrowser.Model.Tasks;
-using MediaBrowser.Providers.Chapters;
using MediaBrowser.Providers.Lyric;
using MediaBrowser.Providers.Manager;
using MediaBrowser.Providers.Plugins.Tmdb;
@@ -494,7 +494,12 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IUserDataManager, UserDataManager>();
- serviceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
+ serviceCollection.AddSingleton<IItemRepository, BaseItemRepository>();
+ serviceCollection.AddSingleton<IPeopleRepository, PeopleRepository>();
+ serviceCollection.AddSingleton<IChapterRepository, ChapterRepository>();
+ serviceCollection.AddSingleton<IMediaAttachmentRepository, MediaAttachmentRepository>();
+ serviceCollection.AddSingleton<IMediaStreamRepository, MediaStreamRepository>();
+ serviceCollection.AddSingleton<IItemTypeLookup, ItemTypeLookup>();
serviceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
serviceCollection.AddSingleton<EncodingHelper>();
@@ -539,8 +544,6 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IUserViewManager, UserViewManager>();
- serviceCollection.AddSingleton<IChapterManager, ChapterManager>();
-
serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
serviceCollection.AddSingleton<IAuthService, AuthService>();
@@ -578,8 +581,6 @@ namespace Emby.Server.Implementations
}
}
- ((SqliteItemRepository)Resolve<IItemRepository>()).Initialize();
-
var localizationManager = (LocalizationManager)Resolve<ILocalizationManager>();
await localizationManager.LoadAll().ConfigureAwait(false);
diff --git a/Emby.Server.Implementations/Data/ItemTypeLookup.cs b/Emby.Server.Implementations/Data/ItemTypeLookup.cs
new file mode 100644
index 000000000..14dc68a32
--- /dev/null
+++ b/Emby.Server.Implementations/Data/ItemTypeLookup.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Channels;
+using Emby.Server.Implementations.Playlists;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.LiveTv;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Playlists;
+using MediaBrowser.Model.Querying;
+
+namespace Jellyfin.Server.Implementations.Item;
+
+/// <summary>
+/// Provides static topic based lookups for the BaseItemKind.
+/// </summary>
+public class ItemTypeLookup : IItemTypeLookup
+{
+ /// <summary>
+ /// Gets all values of the ItemFields type.
+ /// </summary>
+ public IReadOnlyList<ItemFields> AllItemFields { get; } = Enum.GetValues<ItemFields>();
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered Programs.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ProgramTypes { get; } =
+ [
+ BaseItemKind.Program,
+ BaseItemKind.TvChannel,
+ BaseItemKind.LiveTvProgram,
+ BaseItemKind.LiveTvChannel
+ ];
+
+ /// <summary>
+ /// Gets all BaseItemKinds that should be excluded from parent lookup.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ProgramExcludeParentTypes { get; } =
+ [
+ BaseItemKind.Series,
+ BaseItemKind.Season,
+ BaseItemKind.MusicAlbum,
+ BaseItemKind.MusicArtist,
+ BaseItemKind.PhotoAlbum
+ ];
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered to be provided by services.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ServiceTypes { get; } =
+ [
+ BaseItemKind.TvChannel,
+ BaseItemKind.LiveTvChannel
+ ];
+
+ /// <summary>
+ /// Gets all BaseItemKinds that have a StartDate.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> StartDateTypes { get; } =
+ [
+ BaseItemKind.Program,
+ BaseItemKind.LiveTvProgram
+ ];
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered Series.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> SeriesTypes { get; } =
+ [
+ BaseItemKind.Book,
+ BaseItemKind.AudioBook,
+ BaseItemKind.Episode,
+ BaseItemKind.Season
+ ];
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are not to be evaluated for Artists.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ArtistExcludeParentTypes { get; } =
+ [
+ BaseItemKind.Series,
+ BaseItemKind.Season,
+ BaseItemKind.PhotoAlbum
+ ];
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered Artists.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ArtistsTypes { get; } =
+ [
+ BaseItemKind.Audio,
+ BaseItemKind.MusicAlbum,
+ BaseItemKind.MusicVideo,
+ BaseItemKind.AudioBook
+ ];
+
+ /// <summary>
+ /// Gets mapping for all BaseItemKinds and their expected serialisaition target.
+ /// </summary>
+ public IDictionary<BaseItemKind, string?> BaseItemKindNames { get; } = new Dictionary<BaseItemKind, string?>()
+ {
+ { BaseItemKind.AggregateFolder, typeof(AggregateFolder).FullName },
+ { BaseItemKind.Audio, typeof(Audio).FullName },
+ { BaseItemKind.AudioBook, typeof(AudioBook).FullName },
+ { BaseItemKind.BasePluginFolder, typeof(BasePluginFolder).FullName },
+ { BaseItemKind.Book, typeof(Book).FullName },
+ { BaseItemKind.BoxSet, typeof(BoxSet).FullName },
+ { BaseItemKind.Channel, typeof(Channel).FullName },
+ { BaseItemKind.CollectionFolder, typeof(CollectionFolder).FullName },
+ { BaseItemKind.Episode, typeof(Episode).FullName },
+ { BaseItemKind.Folder, typeof(Folder).FullName },
+ { BaseItemKind.Genre, typeof(Genre).FullName },
+ { BaseItemKind.Movie, typeof(Movie).FullName },
+ { BaseItemKind.LiveTvChannel, typeof(LiveTvChannel).FullName },
+ { BaseItemKind.LiveTvProgram, typeof(LiveTvProgram).FullName },
+ { BaseItemKind.MusicAlbum, typeof(MusicAlbum).FullName },
+ { BaseItemKind.MusicArtist, typeof(MusicArtist).FullName },
+ { BaseItemKind.MusicGenre, typeof(MusicGenre).FullName },
+ { BaseItemKind.MusicVideo, typeof(MusicVideo).FullName },
+ { BaseItemKind.Person, typeof(Person).FullName },
+ { BaseItemKind.Photo, typeof(Photo).FullName },
+ { BaseItemKind.PhotoAlbum, typeof(PhotoAlbum).FullName },
+ { BaseItemKind.Playlist, typeof(Playlist).FullName },
+ { BaseItemKind.PlaylistsFolder, typeof(PlaylistsFolder).FullName },
+ { BaseItemKind.Season, typeof(Season).FullName },
+ { BaseItemKind.Series, typeof(Series).FullName },
+ { BaseItemKind.Studio, typeof(Studio).FullName },
+ { BaseItemKind.Trailer, typeof(Trailer).FullName },
+ { BaseItemKind.TvChannel, typeof(LiveTvChannel).FullName },
+ { BaseItemKind.TvProgram, typeof(LiveTvProgram).FullName },
+ { BaseItemKind.UserRootFolder, typeof(UserRootFolder).FullName },
+ { BaseItemKind.UserView, typeof(UserView).FullName },
+ { BaseItemKind.Video, typeof(Video).FullName },
+ { BaseItemKind.Year, typeof(Year).FullName }
+ }.AsReadOnly();
+}
diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
index eb55e32c5..ea7896861 100644
--- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
+++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs
@@ -28,7 +28,7 @@ namespace Emby.Server.Implementations.MediaEncoder
private readonly IFileSystem _fileSystem;
private readonly ILogger<EncodingManager> _logger;
private readonly IMediaEncoder _encoder;
- private readonly IChapterManager _chapterManager;
+ private readonly IChapterRepository _chapterManager;
private readonly ILibraryManager _libraryManager;
/// <summary>
@@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.MediaEncoder
ILogger<EncodingManager> logger,
IFileSystem fileSystem,
IMediaEncoder encoder,
- IChapterManager chapterManager,
+ IChapterRepository chapterManager,
ILibraryManager libraryManager)
{
_logger = logger;
diff --git a/Jellyfin.Data/Entities/AncestorId.cs b/Jellyfin.Data/Entities/AncestorId.cs
index dc83b763e..3839b1ae4 100644
--- a/Jellyfin.Data/Entities/AncestorId.cs
+++ b/Jellyfin.Data/Entities/AncestorId.cs
@@ -13,7 +13,7 @@ public class AncestorId
public Guid ItemId { get; set; }
- public required BaseItem Item { get; set; }
+ public required BaseItemEntity Item { get; set; }
public string? AncestorIdText { get; set; }
}
diff --git a/Jellyfin.Data/Entities/AttachmentStreamInfo.cs b/Jellyfin.Data/Entities/AttachmentStreamInfo.cs
index 858465424..056d5b05e 100644
--- a/Jellyfin.Data/Entities/AttachmentStreamInfo.cs
+++ b/Jellyfin.Data/Entities/AttachmentStreamInfo.cs
@@ -7,7 +7,7 @@ public class AttachmentStreamInfo
{
public required Guid ItemId { get; set; }
- public required BaseItem Item { get; set; }
+ public required BaseItemEntity Item { get; set; }
public required int Index { get; set; }
diff --git a/Jellyfin.Data/Entities/BaseItem.cs b/Jellyfin.Data/Entities/BaseItemEntity.cs
index 0e67a7ca4..92b5caf05 100644
--- a/Jellyfin.Data/Entities/BaseItem.cs
+++ b/Jellyfin.Data/Entities/BaseItemEntity.cs
@@ -6,7 +6,7 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities;
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
-public class BaseItem
+public class BaseItemEntity
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -160,6 +160,7 @@ public class BaseItem
public long? Size { get; set; }
+#pragma warning disable CA2227 // Collection properties should be read only
public ICollection<People>? Peoples { get; set; }
public ICollection<UserData>? UserData { get; set; }
diff --git a/Jellyfin.Data/Entities/BaseItemProvider.cs b/Jellyfin.Data/Entities/BaseItemProvider.cs
index 6f8e1c39b..1fc721d6a 100644
--- a/Jellyfin.Data/Entities/BaseItemProvider.cs
+++ b/Jellyfin.Data/Entities/BaseItemProvider.cs
@@ -5,11 +5,28 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities;
+/// <summary>
+/// Represents an Key-Value relaten of an BaseItem's provider.
+/// </summary>
public class BaseItemProvider
{
+ /// <summary>
+ /// Gets or Sets the reference ItemId.
+ /// </summary>
public Guid ItemId { get; set; }
- public required BaseItem Item { get; set; }
- public string ProviderId { get; set; }
- public string ProviderValue { get; set; }
+ /// <summary>
+ /// Gets or Sets the reference BaseItem.
+ /// </summary>
+ public required BaseItemEntity Item { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the ProvidersId.
+ /// </summary>
+ public required string ProviderId { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the Providers Value.
+ /// </summary>
+ public required string ProviderValue { get; set; }
}
diff --git a/Jellyfin.Data/Entities/Chapter.cs b/Jellyfin.Data/Entities/Chapter.cs
index ad119d1c6..be353b5da 100644
--- a/Jellyfin.Data/Entities/Chapter.cs
+++ b/Jellyfin.Data/Entities/Chapter.cs
@@ -10,7 +10,7 @@ public class Chapter
{
public Guid ItemId { get; set; }
- public required BaseItem Item { get; set; }
+ public required BaseItemEntity Item { get; set; }
public required int ChapterIndex { get; set; }
diff --git a/Jellyfin.Data/Entities/ItemValue.cs b/Jellyfin.Data/Entities/ItemValue.cs
index a3c0908bb..1063aaa8b 100644
--- a/Jellyfin.Data/Entities/ItemValue.cs
+++ b/Jellyfin.Data/Entities/ItemValue.cs
@@ -5,12 +5,33 @@ using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities;
+/// <summary>
+/// Represents an ItemValue for a BaseItem.
+/// </summary>
public class ItemValue
{
+ /// <summary>
+ /// Gets or Sets the reference ItemId.
+ /// </summary>
public Guid ItemId { get; set; }
- public required BaseItem Item { get; set; }
+ /// <summary>
+ /// Gets or Sets the referenced BaseItem.
+ /// </summary>
+ public required BaseItemEntity Item { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the Type.
+ /// </summary>
public required int Type { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the Value.
+ /// </summary>
public required string Value { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the sanatised Value.
+ /// </summary>
public required string CleanValue { get; set; }
}
diff --git a/Jellyfin.Data/Entities/MediaStreamInfo.cs b/Jellyfin.Data/Entities/MediaStreamInfo.cs
index 3b89ca62f..992f33ecf 100644
--- a/Jellyfin.Data/Entities/MediaStreamInfo.cs
+++ b/Jellyfin.Data/Entities/MediaStreamInfo.cs
@@ -7,7 +7,7 @@ public class MediaStreamInfo
{
public Guid ItemId { get; set; }
- public required BaseItem Item { get; set; }
+ public required BaseItemEntity Item { get; set; }
public int StreamIndex { get; set; }
diff --git a/Jellyfin.Data/Entities/People.cs b/Jellyfin.Data/Entities/People.cs
index 014a0f1c9..8eb23f5e4 100644
--- a/Jellyfin.Data/Entities/People.cs
+++ b/Jellyfin.Data/Entities/People.cs
@@ -4,14 +4,44 @@ using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace Jellyfin.Data.Entities;
+
+/// <summary>
+/// People entity.
+/// </summary>
public class People
{
- public Guid ItemId { get; set; }
- public BaseItem Item { get; set; }
+ /// <summary>
+ /// Gets or Sets The ItemId.
+ /// </summary>
+ public required Guid ItemId { get; set; }
+
+ /// <summary>
+ /// Gets or Sets Reference Item.
+ /// </summary>
+ public required BaseItemEntity Item { get; set; }
+ /// <summary>
+ /// Gets or Sets the Persons Name.
+ /// </summary>
public required string Name { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the Role.
+ /// </summary>
public string? Role { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the Type.
+ /// </summary>
public string? PersonType { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the SortOrder.
+ /// </summary>
public int? SortOrder { get; set; }
+
+ /// <summary>
+ /// Gets or Sets the ListOrder.
+ /// </summary>
public int? ListOrder { get; set; }
}
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemManager.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
index 66cc765f3..a3e617a21 100644
--- a/Jellyfin.Server.Implementations/Item/BaseItemManager.cs
+++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
@@ -24,112 +24,23 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying;
using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Internal;
-using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using BaseItemDto = MediaBrowser.Controller.Entities.BaseItem;
-using BaseItemEntity = Jellyfin.Data.Entities.BaseItem;
+using BaseItemEntity = Jellyfin.Data.Entities.BaseItemEntity;
namespace Jellyfin.Server.Implementations.Item;
/// <summary>
/// Handles all storage logic for BaseItems.
/// </summary>
-public sealed class BaseItemManager : IItemRepository, IDisposable
+/// <remarks>
+/// Initializes a new instance of the <see cref="BaseItemRepository"/> class.
+/// </remarks>
+/// <param name="dbProvider">The db factory.</param>
+/// <param name="appHost">The Application host.</param>
+/// <param name="itemTypeLookup">The static type lookup.</param>
+public sealed class BaseItemRepository(IDbContextFactory<JellyfinDbContext> dbProvider, IServerApplicationHost appHost, IItemTypeLookup itemTypeLookup)
+ : IItemRepository, IDisposable
{
- private readonly IDbContextFactory<JellyfinDbContext> _dbProvider;
- private readonly IServerApplicationHost _appHost;
-
- private readonly ItemFields[] _allItemFields = Enum.GetValues<ItemFields>();
-
- private static readonly BaseItemKind[] _programTypes = new[]
- {
- BaseItemKind.Program,
- BaseItemKind.TvChannel,
- BaseItemKind.LiveTvProgram,
- BaseItemKind.LiveTvChannel
- };
-
- private static readonly BaseItemKind[] _programExcludeParentTypes = new[]
- {
- BaseItemKind.Series,
- BaseItemKind.Season,
- BaseItemKind.MusicAlbum,
- BaseItemKind.MusicArtist,
- BaseItemKind.PhotoAlbum
- };
-
- private static readonly BaseItemKind[] _serviceTypes = new[]
- {
- BaseItemKind.TvChannel,
- BaseItemKind.LiveTvChannel
- };
-
- private static readonly BaseItemKind[] _startDateTypes = new[]
- {
- BaseItemKind.Program,
- BaseItemKind.LiveTvProgram
- };
-
- private static readonly BaseItemKind[] _seriesTypes = new[]
- {
- BaseItemKind.Book,
- BaseItemKind.AudioBook,
- BaseItemKind.Episode,
- BaseItemKind.Season
- };
-
- private static readonly BaseItemKind[] _artistExcludeParentTypes = new[]
- {
- BaseItemKind.Series,
- BaseItemKind.Season,
- BaseItemKind.PhotoAlbum
- };
-
- private static readonly BaseItemKind[] _artistsTypes = new[]
- {
- BaseItemKind.Audio,
- BaseItemKind.MusicAlbum,
- BaseItemKind.MusicVideo,
- BaseItemKind.AudioBook
- };
-
- private static readonly Dictionary<BaseItemKind, string?> _baseItemKindNames = new()
- {
- { BaseItemKind.AggregateFolder, typeof(AggregateFolder).FullName },
- { BaseItemKind.Audio, typeof(Audio).FullName },
- { BaseItemKind.AudioBook, typeof(AudioBook).FullName },
- { BaseItemKind.BasePluginFolder, typeof(BasePluginFolder).FullName },
- { BaseItemKind.Book, typeof(Book).FullName },
- { BaseItemKind.BoxSet, typeof(BoxSet).FullName },
- { BaseItemKind.Channel, typeof(Channel).FullName },
- { BaseItemKind.CollectionFolder, typeof(CollectionFolder).FullName },
- { BaseItemKind.Episode, typeof(Episode).FullName },
- { BaseItemKind.Folder, typeof(Folder).FullName },
- { BaseItemKind.Genre, typeof(Genre).FullName },
- { BaseItemKind.Movie, typeof(Movie).FullName },
- { BaseItemKind.LiveTvChannel, typeof(LiveTvChannel).FullName },
- { BaseItemKind.LiveTvProgram, typeof(LiveTvProgram).FullName },
- { BaseItemKind.MusicAlbum, typeof(MusicAlbum).FullName },
- { BaseItemKind.MusicArtist, typeof(MusicArtist).FullName },
- { BaseItemKind.MusicGenre, typeof(MusicGenre).FullName },
- { BaseItemKind.MusicVideo, typeof(MusicVideo).FullName },
- { BaseItemKind.Person, typeof(Person).FullName },
- { BaseItemKind.Photo, typeof(Photo).FullName },
- { BaseItemKind.PhotoAlbum, typeof(PhotoAlbum).FullName },
- { BaseItemKind.Playlist, typeof(Playlist).FullName },
- { BaseItemKind.PlaylistsFolder, typeof(PlaylistsFolder).FullName },
- { BaseItemKind.Season, typeof(Season).FullName },
- { BaseItemKind.Series, typeof(Series).FullName },
- { BaseItemKind.Studio, typeof(Studio).FullName },
- { BaseItemKind.Trailer, typeof(Trailer).FullName },
- { BaseItemKind.TvChannel, typeof(LiveTvChannel).FullName },
- { BaseItemKind.TvProgram, typeof(LiveTvProgram).FullName },
- { BaseItemKind.UserRootFolder, typeof(UserRootFolder).FullName },
- { BaseItemKind.UserView, typeof(UserView).FullName },
- { BaseItemKind.Video, typeof(Video).FullName },
- { BaseItemKind.Year, typeof(Year).FullName }
- };
-
/// <summary>
/// This holds all the types in the running assemblies
/// so that we can de-serialize properly when we don't have strong types.
@@ -137,17 +48,6 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
private static readonly ConcurrentDictionary<string, Type?> _typeMap = new ConcurrentDictionary<string, Type?>();
private bool _disposed;
- /// <summary>
- /// Initializes a new instance of the <see cref="BaseItemManager"/> class.
- /// </summary>
- /// <param name="dbProvider">The db factory.</param>
- /// <param name="appHost">The Application host.</param>
- public BaseItemManager(IDbContextFactory<JellyfinDbContext> dbProvider, IServerApplicationHost appHost)
- {
- _dbProvider = dbProvider;
- _appHost = appHost;
- }
-
/// <inheritdoc/>
public void Dispose()
{
@@ -159,124 +59,12 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
_disposed = true;
}
- private QueryResult<(BaseItemDto Item, ItemCounts ItemCounts)> GetItemValues(InternalItemsQuery filter, int[] itemValueTypes, string returnType)
- {
- ArgumentNullException.ThrowIfNull(filter);
-
- if (!filter.Limit.HasValue)
- {
- filter.EnableTotalRecordCount = false;
- }
-
- using var context = _dbProvider.CreateDbContext();
-
- var innerQuery = new InternalItemsQuery(filter.User)
- {
- ExcludeItemTypes = filter.ExcludeItemTypes,
- IncludeItemTypes = filter.IncludeItemTypes,
- MediaTypes = filter.MediaTypes,
- AncestorIds = filter.AncestorIds,
- ItemIds = filter.ItemIds,
- TopParentIds = filter.TopParentIds,
- ParentId = filter.ParentId,
- IsAiring = filter.IsAiring,
- IsMovie = filter.IsMovie,
- IsSports = filter.IsSports,
- IsKids = filter.IsKids,
- IsNews = filter.IsNews,
- IsSeries = filter.IsSeries
- };
- var query = TranslateQuery(context.BaseItems, context, innerQuery);
-
- query = query.Where(e => e.Type == returnType && e.ItemValues!.Any(f => e.CleanName == f.CleanValue && itemValueTypes.Contains(f.Type)));
-
- var outerQuery = new InternalItemsQuery(filter.User)
- {
- IsPlayed = filter.IsPlayed,
- IsFavorite = filter.IsFavorite,
- IsFavoriteOrLiked = filter.IsFavoriteOrLiked,
- IsLiked = filter.IsLiked,
- IsLocked = filter.IsLocked,
- NameLessThan = filter.NameLessThan,
- NameStartsWith = filter.NameStartsWith,
- NameStartsWithOrGreater = filter.NameStartsWithOrGreater,
- Tags = filter.Tags,
- OfficialRatings = filter.OfficialRatings,
- StudioIds = filter.StudioIds,
- GenreIds = filter.GenreIds,
- Genres = filter.Genres,
- Years = filter.Years,
- NameContains = filter.NameContains,
- SearchTerm = filter.SearchTerm,
- SimilarTo = filter.SimilarTo,
- ExcludeItemIds = filter.ExcludeItemIds
- };
- query = TranslateQuery(query, context, outerQuery)
- .OrderBy(e => e.PresentationUniqueKey);
-
- if (filter.OrderBy.Count != 0
- || filter.SimilarTo is not null
- || !string.IsNullOrEmpty(filter.SearchTerm))
- {
- query = ApplyOrder(query, filter);
- }
- else
- {
- query = query.OrderBy(e => e.SortName);
- }
-
- if (filter.Limit.HasValue || filter.StartIndex.HasValue)
- {
- var offset = filter.StartIndex ?? 0;
-
- if (offset > 0)
- {
- query = query.Skip(offset);
- }
-
- if (filter.Limit.HasValue)
- {
- query.Take(filter.Limit.Value);
- }
- }
-
- var result = new QueryResult<(BaseItem, ItemCounts)>();
- string countText = string.Empty;
- if (filter.EnableTotalRecordCount)
- {
- result.TotalRecordCount = query.DistinctBy(e => e.PresentationUniqueKey).Count();
- }
-
- var resultQuery = query.Select(e => new
- {
- item = e,
- itemCount = new ItemCounts()
- {
- SeriesCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Series),
- EpisodeCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Episode),
- MovieCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Movie),
- AlbumCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.MusicAlbum),
- ArtistCount = e.ItemValues!.Count(e => e.Type == 0 || e.Type == 1),
- SongCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.MusicAlbum),
- TrailerCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Trailer),
- }
- });
-
- result.StartIndex = filter.StartIndex ?? 0;
- result.Items = resultQuery.ToImmutableArray().Select(e =>
- {
- return (DeserialiseBaseItem(e.item), e.itemCount);
- }).ToImmutableArray();
-
- return result;
- }
-
/// <inheritdoc />
public void DeleteItem(Guid id)
{
ArgumentNullException.ThrowIfNull(id.IsEmpty() ? null : id);
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
using var transaction = context.Database.BeginTransaction();
context.Peoples.Where(e => e.ItemId.Equals(id)).ExecuteDelete();
context.Chapters.Where(e => e.ItemId.Equals(id)).ExecuteDelete();
@@ -291,7 +79,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
/// <inheritdoc />
public void UpdateInheritedValues()
{
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
using var transaction = context.Database.BeginTransaction();
context.ItemValues.Where(e => e.Type == 6).ExecuteDelete();
@@ -324,7 +112,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
ArgumentNullException.ThrowIfNull(filter);
PrepareFilterQuery(filter);
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
var dbQuery = TranslateQuery(context.BaseItems.AsNoTracking(), context, filter)
.DistinctBy(e => e.Id);
@@ -352,56 +140,56 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
/// <inheritdoc />
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery filter)
{
- return GetItemValues(filter, new[] { 0, 1 }, typeof(MusicArtist).FullName!);
+ return GetItemValues(filter, [0, 1], typeof(MusicArtist).FullName!);
}
/// <inheritdoc />
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery filter)
{
- return GetItemValues(filter, new[] { 0 }, typeof(MusicArtist).FullName!);
+ return GetItemValues(filter, [0], typeof(MusicArtist).FullName!);
}
/// <inheritdoc />
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery filter)
{
- return GetItemValues(filter, new[] { 1 }, typeof(MusicArtist).FullName!);
+ return GetItemValues(filter, [1], typeof(MusicArtist).FullName!);
}
/// <inheritdoc />
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery filter)
{
- return GetItemValues(filter, new[] { 3 }, typeof(Studio).FullName!);
+ return GetItemValues(filter, [3], typeof(Studio).FullName!);
}
/// <inheritdoc />
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery filter)
{
- return GetItemValues(filter, new[] { 2 }, typeof(Genre).FullName!);
+ return GetItemValues(filter, [2], typeof(Genre).FullName!);
}
/// <inheritdoc />
public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery filter)
{
- return GetItemValues(filter, new[] { 2 }, typeof(MusicGenre).FullName!);
+ return GetItemValues(filter, [2], typeof(MusicGenre).FullName!);
}
/// <inheritdoc />
public IReadOnlyList<string> GetStudioNames()
{
- return GetItemValueNames(new[] { 3 }, Array.Empty<string>(), Array.Empty<string>());
+ return GetItemValueNames([3], Array.Empty<string>(), Array.Empty<string>());
}
/// <inheritdoc />
public IReadOnlyList<string> GetAllArtistNames()
{
- return GetItemValueNames(new[] { 0, 1 }, Array.Empty<string>(), Array.Empty<string>());
+ return GetItemValueNames([0, 1], Array.Empty<string>(), Array.Empty<string>());
}
/// <inheritdoc />
public IReadOnlyList<string> GetMusicGenreNames()
{
return GetItemValueNames(
- new[] { 2 },
+ [2],
new string[]
{
typeof(Audio).FullName!,
@@ -416,7 +204,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
public IReadOnlyList<string> GetGenreNames()
{
return GetItemValueNames(
- new[] { 2 },
+ [2],
Array.Empty<string>(),
new string[]
{
@@ -443,7 +231,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
PrepareFilterQuery(filter);
var result = new QueryResult<BaseItemDto>();
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
var dbQuery = TranslateQuery(context.BaseItems, context, filter)
.DistinctBy(e => e.Id);
if (filter.EnableTotalRecordCount)
@@ -477,7 +265,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
ArgumentNullException.ThrowIfNull(filter);
PrepareFilterQuery(filter);
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
var dbQuery = TranslateQuery(context.BaseItems, context, filter)
.DistinctBy(e => e.Id);
if (filter.Limit.HasValue || filter.StartIndex.HasValue)
@@ -505,7 +293,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
// Hack for right now since we currently don't support filtering out these duplicates within a query
PrepareFilterQuery(filter);
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
var dbQuery = TranslateQuery(context.BaseItems, context, filter);
return dbQuery.Count();
@@ -646,7 +434,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
var excludeTypes = filter.ExcludeItemTypes;
if (excludeTypes.Length == 1)
{
- if (_baseItemKindNames.TryGetValue(excludeTypes[0], out var excludeTypeName))
+ if (itemTypeLookup.BaseItemKindNames.TryGetValue(excludeTypes[0], out var excludeTypeName))
{
baseQuery = baseQuery.Where(e => e.Type != excludeTypeName);
}
@@ -656,7 +444,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
var excludeTypeName = new List<string>();
foreach (var excludeType in excludeTypes)
{
- if (_baseItemKindNames.TryGetValue(excludeType, out var baseItemKindName))
+ if (itemTypeLookup.BaseItemKindNames.TryGetValue(excludeType, out var baseItemKindName))
{
excludeTypeName.Add(baseItemKindName!);
}
@@ -667,7 +455,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
}
else if (includeTypes.Length == 1)
{
- if (_baseItemKindNames.TryGetValue(includeTypes[0], out var includeTypeName))
+ if (itemTypeLookup.BaseItemKindNames.TryGetValue(includeTypes[0], out var includeTypeName))
{
baseQuery = baseQuery.Where(e => e.Type == includeTypeName);
}
@@ -677,7 +465,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
var includeTypeName = new List<string>();
foreach (var includeType in includeTypes)
{
- if (_baseItemKindNames.TryGetValue(includeType, out var baseItemKindName))
+ if (itemTypeLookup.BaseItemKindNames.TryGetValue(includeType, out var baseItemKindName))
{
includeTypeName.Add(baseItemKindName!);
}
@@ -1421,7 +1209,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
ArgumentNullException.ThrowIfNull(item);
var images = SerializeImages(item.ImageInfos);
- using var db = _dbProvider.CreateDbContext();
+ using var db = dbProvider.CreateDbContext();
db.BaseItems
.Where(e => e.Id.Equals(item.Id))
@@ -1457,7 +1245,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
tuples[i] = (item, ancestorIds, topParent, userdataKey, inheritedTags);
}
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
foreach (var item in tuples)
{
var entity = Map(item.Item);
@@ -1501,7 +1289,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
throw new ArgumentException("Guid can't be empty", nameof(id));
}
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
var item = context.BaseItems.FirstOrDefault(e => e.Id.Equals(id));
if (item is null)
{
@@ -1832,7 +1620,7 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
private IReadOnlyList<string> GetItemValueNames(int[] itemValueTypes, IReadOnlyList<string> withItemTypes, IReadOnlyList<string> excludeItemTypes)
{
- using var context = _dbProvider.CreateDbContext();
+ using var context = dbProvider.CreateDbContext();
var query = context.ItemValues
.Where(e => itemValueTypes.Contains(e.Type));
@@ -1857,6 +1645,118 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
return Map(baseItemEntity, dto);
}
+ private QueryResult<(BaseItemDto Item, ItemCounts ItemCounts)> GetItemValues(InternalItemsQuery filter, int[] itemValueTypes, string returnType)
+ {
+ ArgumentNullException.ThrowIfNull(filter);
+
+ if (!filter.Limit.HasValue)
+ {
+ filter.EnableTotalRecordCount = false;
+ }
+
+ using var context = dbProvider.CreateDbContext();
+
+ var innerQuery = new InternalItemsQuery(filter.User)
+ {
+ ExcludeItemTypes = filter.ExcludeItemTypes,
+ IncludeItemTypes = filter.IncludeItemTypes,
+ MediaTypes = filter.MediaTypes,
+ AncestorIds = filter.AncestorIds,
+ ItemIds = filter.ItemIds,
+ TopParentIds = filter.TopParentIds,
+ ParentId = filter.ParentId,
+ IsAiring = filter.IsAiring,
+ IsMovie = filter.IsMovie,
+ IsSports = filter.IsSports,
+ IsKids = filter.IsKids,
+ IsNews = filter.IsNews,
+ IsSeries = filter.IsSeries
+ };
+ var query = TranslateQuery(context.BaseItems, context, innerQuery);
+
+ query = query.Where(e => e.Type == returnType && e.ItemValues!.Any(f => e.CleanName == f.CleanValue && itemValueTypes.Contains(f.Type)));
+
+ var outerQuery = new InternalItemsQuery(filter.User)
+ {
+ IsPlayed = filter.IsPlayed,
+ IsFavorite = filter.IsFavorite,
+ IsFavoriteOrLiked = filter.IsFavoriteOrLiked,
+ IsLiked = filter.IsLiked,
+ IsLocked = filter.IsLocked,
+ NameLessThan = filter.NameLessThan,
+ NameStartsWith = filter.NameStartsWith,
+ NameStartsWithOrGreater = filter.NameStartsWithOrGreater,
+ Tags = filter.Tags,
+ OfficialRatings = filter.OfficialRatings,
+ StudioIds = filter.StudioIds,
+ GenreIds = filter.GenreIds,
+ Genres = filter.Genres,
+ Years = filter.Years,
+ NameContains = filter.NameContains,
+ SearchTerm = filter.SearchTerm,
+ SimilarTo = filter.SimilarTo,
+ ExcludeItemIds = filter.ExcludeItemIds
+ };
+ query = TranslateQuery(query, context, outerQuery)
+ .OrderBy(e => e.PresentationUniqueKey);
+
+ if (filter.OrderBy.Count != 0
+ || filter.SimilarTo is not null
+ || !string.IsNullOrEmpty(filter.SearchTerm))
+ {
+ query = ApplyOrder(query, filter);
+ }
+ else
+ {
+ query = query.OrderBy(e => e.SortName);
+ }
+
+ if (filter.Limit.HasValue || filter.StartIndex.HasValue)
+ {
+ var offset = filter.StartIndex ?? 0;
+
+ if (offset > 0)
+ {
+ query = query.Skip(offset);
+ }
+
+ if (filter.Limit.HasValue)
+ {
+ query.Take(filter.Limit.Value);
+ }
+ }
+
+ var result = new QueryResult<(BaseItem, ItemCounts)>();
+ string countText = string.Empty;
+ if (filter.EnableTotalRecordCount)
+ {
+ result.TotalRecordCount = query.DistinctBy(e => e.PresentationUniqueKey).Count();
+ }
+
+ var resultQuery = query.Select(e => new
+ {
+ item = e,
+ itemCount = new ItemCounts()
+ {
+ SeriesCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Series),
+ EpisodeCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Episode),
+ MovieCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Movie),
+ AlbumCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.MusicAlbum),
+ ArtistCount = e.ItemValues!.Count(e => e.Type == 0 || e.Type == 1),
+ SongCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.MusicAlbum),
+ TrailerCount = e.ItemValues!.Count(e => e.Type == (int)BaseItemKind.Trailer),
+ }
+ });
+
+ result.StartIndex = filter.StartIndex ?? 0;
+ result.Items = resultQuery.ToImmutableArray().Select(e =>
+ {
+ return (DeserialiseBaseItem(e.item), e.itemCount);
+ }).ToImmutableArray();
+
+ return result;
+ }
+
private static void PrepareFilterQuery(InternalItemsQuery query)
{
if (query.Limit.HasValue && query.EnableGroupByMetadataKey)
@@ -2046,12 +1946,12 @@ public sealed class BaseItemManager : IItemRepository, IDisposable
return null;
}
- return _appHost.ReverseVirtualPath(path);
+ return appHost.ReverseVirtualPath(path);
}
private string RestorePath(string path)
{
- return _appHost.ExpandVirtualPath(path);
+ return appHost.ExpandVirtualPath(path);
}
internal ItemImageInfo? ItemImageInfoFromValueString(ReadOnlySpan<char> value)
diff --git a/Jellyfin.Server.Implementations/Item/ChapterManager.cs b/Jellyfin.Server.Implementations/Item/ChapterRepository.cs
index 7b0f98fde..d215a1d7a 100644
--- a/Jellyfin.Server.Implementations/Item/ChapterManager.cs
+++ b/Jellyfin.Server.Implementations/Item/ChapterRepository.cs
@@ -14,46 +14,69 @@ namespace Jellyfin.Server.Implementations.Item;
/// <summary>
/// The Chapter manager.
/// </summary>
-public class ChapterManager : IChapterManager
+public class ChapterRepository : IChapterRepository
{
private readonly IDbContextFactory<JellyfinDbContext> _dbProvider;
private readonly IImageProcessor _imageProcessor;
/// <summary>
- /// Initializes a new instance of the <see cref="ChapterManager"/> class.
+ /// Initializes a new instance of the <see cref="ChapterRepository"/> class.
/// </summary>
/// <param name="dbProvider">The EFCore provider.</param>
/// <param name="imageProcessor">The Image Processor.</param>
- public ChapterManager(IDbContextFactory<JellyfinDbContext> dbProvider, IImageProcessor imageProcessor)
+ public ChapterRepository(IDbContextFactory<JellyfinDbContext> dbProvider, IImageProcessor imageProcessor)
{
_dbProvider = dbProvider;
_imageProcessor = imageProcessor;
}
- /// <inheritdoc cref="IChapterManager"/>
+ /// <inheritdoc cref="IChapterRepository"/>
public ChapterInfo? GetChapter(BaseItemDto baseItem, int index)
{
+ return GetChapter(baseItem.Id, index);
+ }
+
+ /// <inheritdoc cref="IChapterRepository"/>
+ public IReadOnlyList<ChapterInfo> GetChapters(BaseItemDto baseItem)
+ {
+ return GetChapters(baseItem.Id);
+ }
+
+ /// <inheritdoc cref="IChapterRepository"/>
+ public ChapterInfo? GetChapter(Guid baseItemId, int index)
+ {
using var context = _dbProvider.CreateDbContext();
- var chapter = context.Chapters.FirstOrDefault(e => e.ItemId.Equals(baseItem.Id) && e.ChapterIndex == index);
+ var chapter = context.Chapters
+ .Select(e => new
+ {
+ chapter = e,
+ baseItemPath = e.Item.Path
+ })
+ .FirstOrDefault(e => e.chapter.ItemId.Equals(baseItemId) && e.chapter.ChapterIndex == index);
if (chapter is not null)
{
- return Map(chapter, baseItem);
+ return Map(chapter.chapter, chapter.baseItemPath!);
}
return null;
}
- /// <inheritdoc cref="IChapterManager"/>
- public IReadOnlyList<ChapterInfo> GetChapters(BaseItemDto baseItem)
+ /// <inheritdoc cref="IChapterRepository"/>
+ public IReadOnlyList<ChapterInfo> GetChapters(Guid baseItemId)
{
using var context = _dbProvider.CreateDbContext();
- return context.Chapters.Where(e => e.ItemId.Equals(baseItem.Id))
+ return context.Chapters.Where(e => e.ItemId.Equals(baseItemId))
+ .Select(e => new
+ {
+ chapter = e,
+ baseItemPath = e.Item.Path
+ })
.ToList()
- .Select(e => Map(e, baseItem))
+ .Select(e => Map(e.chapter, e.baseItemPath!))
.ToImmutableArray();
}
- /// <inheritdoc cref="IChapterManager"/>
+ /// <inheritdoc cref="IChapterRepository"/>
public void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters)
{
using var context = _dbProvider.CreateDbContext();
@@ -80,20 +103,21 @@ public class ChapterManager : IChapterManager
ImageDateModified = chapterInfo.ImageDateModified,
ImagePath = chapterInfo.ImagePath,
ItemId = itemId,
- Name = chapterInfo.Name
+ Name = chapterInfo.Name,
+ Item = null!
};
}
- private ChapterInfo Map(Chapter chapterInfo, BaseItemDto baseItem)
+ private ChapterInfo Map(Chapter chapterInfo, string baseItemPath)
{
- var info = new ChapterInfo()
+ var chapterEntity = new ChapterInfo()
{
StartPositionTicks = chapterInfo.StartPositionTicks,
ImageDateModified = chapterInfo.ImageDateModified.GetValueOrDefault(),
ImagePath = chapterInfo.ImagePath,
Name = chapterInfo.Name,
};
- info.ImageTag = _imageProcessor.GetImageCacheTag(baseItem, info);
- return info;
+ chapterEntity.ImageTag = _imageProcessor.GetImageCacheTag(baseItemPath, chapterEntity.ImageDateModified);
+ return chapterEntity;
}
}
diff --git a/Jellyfin.Server.Implementations/Item/MediaAttachmentManager.cs b/Jellyfin.Server.Implementations/Item/MediaAttachmentRepository.cs
index 288b1943e..70c5ff1e2 100644
--- a/Jellyfin.Server.Implementations/Item/MediaAttachmentManager.cs
+++ b/Jellyfin.Server.Implementations/Item/MediaAttachmentRepository.cs
@@ -14,7 +14,7 @@ namespace Jellyfin.Server.Implementations.Item;
/// Manager for handling Media Attachments.
/// </summary>
/// <param name="dbProvider">Efcore Factory.</param>
-public class MediaAttachmentManager(IDbContextFactory<JellyfinDbContext> dbProvider) : IMediaAttachmentManager
+public class MediaAttachmentRepository(IDbContextFactory<JellyfinDbContext> dbProvider) : IMediaAttachmentRepository
{
/// <inheritdoc />
public void SaveMediaAttachments(
diff --git a/Jellyfin.Server.Implementations/Item/MediaStreamManager.cs b/Jellyfin.Server.Implementations/Item/MediaStreamRepository.cs
index b7124283a..f7b714c29 100644
--- a/Jellyfin.Server.Implementations/Item/MediaStreamManager.cs
+++ b/Jellyfin.Server.Implementations/Item/MediaStreamRepository.cs
@@ -13,12 +13,12 @@ using Microsoft.EntityFrameworkCore;
namespace Jellyfin.Server.Implementations.Item;
/// <summary>
-/// Initializes a new instance of the <see cref="MediaStreamManager"/> class.
+/// Initializes a new instance of the <see cref="MediaStreamRepository"/> class.
/// </summary>
-/// <param name="dbProvider"></param>
-/// <param name="serverApplicationHost"></param>
-/// <param name="localization"></param>
-public class MediaStreamManager(IDbContextFactory<JellyfinDbContext> dbProvider, IServerApplicationHost serverApplicationHost, ILocalizationManager localization) : IMediaStreamManager
+/// <param name="dbProvider">The EFCore db factory.</param>
+/// <param name="serverApplicationHost">The Application host.</param>
+/// <param name="localization">The Localisation Provider.</param>
+public class MediaStreamRepository(IDbContextFactory<JellyfinDbContext> dbProvider, IServerApplicationHost serverApplicationHost, ILocalizationManager localization) : IMediaStreamRepository
{
/// <inheritdoc />
public void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken)
diff --git a/Jellyfin.Server.Implementations/Item/PeopleManager.cs b/Jellyfin.Server.Implementations/Item/PeopleRepository.cs
index d29d8b143..3ced6e24e 100644
--- a/Jellyfin.Server.Implementations/Item/PeopleManager.cs
+++ b/Jellyfin.Server.Implementations/Item/PeopleRepository.cs
@@ -16,13 +16,13 @@ namespace Jellyfin.Server.Implementations.Item;
/// </summary>
/// <param name="dbProvider">Efcore Factory.</param>
/// <remarks>
-/// Initializes a new instance of the <see cref="PeopleManager"/> class.
+/// Initializes a new instance of the <see cref="PeopleRepository"/> class.
/// </remarks>
-/// <param name="dbProvider">The EFCore Context factory.</param>
-public class PeopleManager(IDbContextFactory<JellyfinDbContext> dbProvider) : IPeopleManager
+public class PeopleRepository(IDbContextFactory<JellyfinDbContext> dbProvider) : IPeopleRepository
{
private readonly IDbContextFactory<JellyfinDbContext> _dbProvider = dbProvider;
+ /// <inheritdoc/>
public IReadOnlyList<PersonInfo> GetPeople(InternalPeopleQuery filter)
{
using var context = _dbProvider.CreateDbContext();
@@ -37,6 +37,7 @@ public class PeopleManager(IDbContextFactory<JellyfinDbContext> dbProvider) : IP
return dbQuery.ToList().Select(Map).ToImmutableArray();
}
+ /// <inheritdoc/>
public IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter)
{
using var context = _dbProvider.CreateDbContext();
diff --git a/Jellyfin.Server.Implementations/JellyfinDbContext.cs b/Jellyfin.Server.Implementations/JellyfinDbContext.cs
index fcc20a0d4..c1d6d58cd 100644
--- a/Jellyfin.Server.Implementations/JellyfinDbContext.cs
+++ b/Jellyfin.Server.Implementations/JellyfinDbContext.cs
@@ -106,7 +106,7 @@ public class JellyfinDbContext : DbContext
/// <summary>
/// Gets the <see cref="DbSet{TEntity}"/> containing the user data.
/// </summary>
- public DbSet<BaseItem> BaseItems => Set<BaseItem>();
+ public DbSet<BaseItemEntity> BaseItems => Set<BaseItemEntity>();
/// <summary>
/// Gets the <see cref="DbSet{TEntity}"/> containing the user data.
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs b/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs
index c0f09670d..4aba9d07e 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs
+++ b/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemConfiguration.cs
@@ -8,10 +8,10 @@ namespace Jellyfin.Server.Implementations.ModelConfiguration;
/// <summary>
/// Configuration for BaseItem.
/// </summary>
-public class BaseItemConfiguration : IEntityTypeConfiguration<BaseItem>
+public class BaseItemConfiguration : IEntityTypeConfiguration<BaseItemEntity>
{
/// <inheritdoc/>
- public void Configure(EntityTypeBuilder<BaseItem> builder)
+ public void Configure(EntityTypeBuilder<BaseItemEntity> builder)
{
builder.HasNoKey();
builder.HasIndex(e => e.Path);
diff --git a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs b/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
index f34837c57..d15049a1f 100644
--- a/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
+++ b/Jellyfin.Server.Implementations/ModelConfiguration/BaseItemProviderConfiguration.cs
@@ -13,7 +13,7 @@ public class BaseItemProviderConfiguration : IEntityTypeConfiguration<BaseItemPr
/// <inheritdoc/>
public void Configure(EntityTypeBuilder<BaseItemProvider> builder)
{
- builder.HasNoKey();
+ builder.HasKey(e => new { e.ItemId, e.ProviderId });
builder.HasOne(e => e.Item);
builder.HasIndex(e => new { e.ProviderId, e.ProviderValue, e.ItemId });
}
diff --git a/MediaBrowser.Controller/Chapters/ChapterManager.cs b/MediaBrowser.Controller/Chapters/ChapterManager.cs
deleted file mode 100644
index a9e11f603..000000000
--- a/MediaBrowser.Controller/Chapters/ChapterManager.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma warning disable CS1591
-
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Controller.Chapters;
-using MediaBrowser.Controller.Persistence;
-using MediaBrowser.Model.Entities;
-
-namespace MediaBrowser.Providers.Chapters
-{
- public class ChapterManager : IChapterManager
- {
- public ChapterManager(IDbContextFactory<JellyfinDbContext> dbProvider)
- {
- _itemRepo = itemRepo;
- }
-
- /// <inheritdoc />
- public void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters)
- {
- _itemRepo.SaveChapters(itemId, chapters);
- }
- }
-}
diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs
deleted file mode 100644
index 55762c7fc..000000000
--- a/MediaBrowser.Controller/Chapters/IChapterManager.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-
-namespace MediaBrowser.Controller.Chapters
-{
- /// <summary>
- /// Interface IChapterManager.
- /// </summary>
- public interface IChapterManager
- {
- /// <summary>
- /// Saves the chapters.
- /// </summary>
- /// <param name="itemId">The item.</param>
- /// <param name="chapters">The set of chapters.</param>
- void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters);
-
- /// <summary>
- /// Gets all chapters associated with the baseItem.
- /// </summary>
- /// <param name="baseItem">The baseitem.</param>
- /// <returns>A readonly list of chapter instances.</returns>
- IReadOnlyList<ChapterInfo> GetChapters(BaseItemDto baseItem);
-
- /// <summary>
- /// Gets a single chapter of a BaseItem on a specific index.
- /// </summary>
- /// <param name="baseItem">The baseitem.</param>
- /// <param name="index">The index of that chapter.</param>
- /// <returns>A chapter instance.</returns>
- ChapterInfo? GetChapter(BaseItemDto baseItem, int index);
- }
-}
diff --git a/MediaBrowser.Controller/Chapters/IChapterRepository.cs b/MediaBrowser.Controller/Chapters/IChapterRepository.cs
new file mode 100644
index 000000000..e22cb0f58
--- /dev/null
+++ b/MediaBrowser.Controller/Chapters/IChapterRepository.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Controller.Chapters;
+
+/// <summary>
+/// Interface IChapterManager.
+/// </summary>
+public interface IChapterRepository
+{
+ /// <summary>
+ /// Saves the chapters.
+ /// </summary>
+ /// <param name="itemId">The item.</param>
+ /// <param name="chapters">The set of chapters.</param>
+ void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters);
+
+ /// <summary>
+ /// Gets all chapters associated with the baseItem.
+ /// </summary>
+ /// <param name="baseItem">The baseitem.</param>
+ /// <returns>A readonly list of chapter instances.</returns>
+ IReadOnlyList<ChapterInfo> GetChapters(BaseItemDto baseItem);
+
+ /// <summary>
+ /// Gets a single chapter of a BaseItem on a specific index.
+ /// </summary>
+ /// <param name="baseItem">The baseitem.</param>
+ /// <param name="index">The index of that chapter.</param>
+ /// <returns>A chapter instance.</returns>
+ ChapterInfo? GetChapter(BaseItemDto baseItem, int index);
+
+ /// <summary>
+ /// Gets all chapters associated with the baseItem.
+ /// </summary>
+ /// <param name="baseItemId">The BaseItems id.</param>
+ /// <returns>A readonly list of chapter instances.</returns>
+ IReadOnlyList<ChapterInfo> GetChapters(Guid baseItemId);
+
+ /// <summary>
+ /// Gets a single chapter of a BaseItem on a specific index.
+ /// </summary>
+ /// <param name="baseItemId">The BaseItems id.</param>
+ /// <param name="index">The index of that chapter.</param>
+ /// <returns>A chapter instance.</returns>
+ ChapterInfo? GetChapter(Guid baseItemId, int index);
+}
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index 0d1e2a5a0..702ce39a2 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Drawing
@@ -60,11 +61,35 @@ namespace MediaBrowser.Controller.Drawing
/// <summary>
/// Gets the image cache tag.
/// </summary>
+ /// <param name="baseItemPath">The items basePath.</param>
+ /// <param name="imageDateModified">The image last modification date.</param>
+ /// <returns>Guid.</returns>
+ string? GetImageCacheTag(string baseItemPath, DateTime imageDateModified);
+
+ /// <summary>
+ /// Gets the image cache tag.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="image">The image.</param>
+ /// <returns>Guid.</returns>
+ string? GetImageCacheTag(BaseItemDto item, ChapterInfo image);
+
+ /// <summary>
+ /// Gets the image cache tag.
+ /// </summary>
/// <param name="item">The item.</param>
/// <param name="image">The image.</param>
/// <returns>Guid.</returns>
string GetImageCacheTag(BaseItem item, ItemImageInfo image);
+ /// <summary>
+ /// Gets the image cache tag.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="image">The image.</param>
+ /// <returns>Guid.</returns>
+ string GetImageCacheTag(BaseItemDto item, ItemImageInfo image);
+
string? GetImageCacheTag(BaseItem item, ChapterInfo chapter);
string? GetImageCacheTag(User user);
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index eb605f6c8..a4764dd33 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -16,6 +16,7 @@ using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
+using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities.Audio;
@@ -479,6 +480,8 @@ namespace MediaBrowser.Controller.Entities
public static IItemRepository ItemRepository { get; set; }
+ public static IChapterRepository ChapterRepository { get; set; }
+
public static IFileSystem FileSystem { get; set; }
public static IUserDataManager UserDataManager { get; set; }
@@ -2031,7 +2034,7 @@ namespace MediaBrowser.Controller.Entities
{
if (imageType == ImageType.Chapter)
{
- var chapter = ItemRepository.GetChapter(this, imageIndex);
+ var chapter = ChapterRepository.GetChapter(this.Id, imageIndex);
if (chapter is null)
{
@@ -2081,7 +2084,7 @@ namespace MediaBrowser.Controller.Entities
if (image.Type == ImageType.Chapter)
{
- var chapters = ItemRepository.GetChapters(this);
+ var chapters = ChapterRepository.GetChapters(this.Id);
for (var i = 0; i < chapters.Count; i++)
{
if (chapters[i].ImagePath == image.Path)
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 313b1459a..b27f156ef 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -52,7 +52,6 @@ public interface IItemRepository : IDisposable
/// <returns>List&lt;Guid&gt;.</returns>
IReadOnlyList<Guid> GetItemIdsList(InternalItemsQuery filter);
-
/// <summary>
/// Gets the item list.
/// </summary>
diff --git a/MediaBrowser.Controller/Persistence/IItemTypeLookup.cs b/MediaBrowser.Controller/Persistence/IItemTypeLookup.cs
new file mode 100644
index 000000000..1b2ca2acb
--- /dev/null
+++ b/MediaBrowser.Controller/Persistence/IItemTypeLookup.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Model.Querying;
+
+namespace MediaBrowser.Controller.Persistence;
+
+/// <summary>
+/// Provides static lookup data for <see cref="ItemFields"/> and <see cref="BaseItemKind"/> for the domain.
+/// </summary>
+public interface IItemTypeLookup
+{
+ /// <summary>
+ /// Gets all values of the ItemFields type.
+ /// </summary>
+ public IReadOnlyList<ItemFields> AllItemFields { get; }
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered Programs.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ProgramTypes { get; }
+
+ /// <summary>
+ /// Gets all BaseItemKinds that should be excluded from parent lookup.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ProgramExcludeParentTypes { get; }
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered to be provided by services.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ServiceTypes { get; }
+
+ /// <summary>
+ /// Gets all BaseItemKinds that have a StartDate.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> StartDateTypes { get; }
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered Series.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> SeriesTypes { get; }
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are not to be evaluated for Artists.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ArtistExcludeParentTypes { get; }
+
+ /// <summary>
+ /// Gets all BaseItemKinds that are considered Artists.
+ /// </summary>
+ public IReadOnlyList<BaseItemKind> ArtistsTypes { get; }
+
+ /// <summary>
+ /// Gets mapping for all BaseItemKinds and their expected serialisaition target.
+ /// </summary>
+ public IDictionary<BaseItemKind, string?> BaseItemKindNames { get; }
+}
diff --git a/MediaBrowser.Controller/Persistence/IMediaAttachmentManager.cs b/MediaBrowser.Controller/Persistence/IMediaAttachmentRepository.cs
index 210d80afa..4773f4058 100644
--- a/MediaBrowser.Controller/Persistence/IMediaAttachmentManager.cs
+++ b/MediaBrowser.Controller/Persistence/IMediaAttachmentRepository.cs
@@ -9,9 +9,8 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Persistence;
-public interface IMediaAttachmentManager
+public interface IMediaAttachmentRepository
{
-
/// <summary>
/// Gets the media attachments.
/// </summary>
diff --git a/MediaBrowser.Controller/Persistence/IMediaStreamManager.cs b/MediaBrowser.Controller/Persistence/IMediaStreamRepository.cs
index ec7c72935..665129eaf 100644
--- a/MediaBrowser.Controller/Persistence/IMediaStreamManager.cs
+++ b/MediaBrowser.Controller/Persistence/IMediaStreamRepository.cs
@@ -9,14 +9,17 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Persistence;
-public interface IMediaStreamManager
+/// <summary>
+/// Provides methods for accessing MediaStreams.
+/// </summary>
+public interface IMediaStreamRepository
{
/// <summary>
/// Gets the media streams.
/// </summary>
/// <param name="filter">The query.</param>
/// <returns>IEnumerable{MediaStream}.</returns>
- List<MediaStream> GetMediaStreams(MediaStreamQuery filter);
+ IReadOnlyList<MediaStream> GetMediaStreams(MediaStreamQuery filter);
/// <summary>
/// Saves the media streams.
diff --git a/MediaBrowser.Controller/Persistence/IPeopleManager.cs b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs
index 84e503fef..43a24703e 100644
--- a/MediaBrowser.Controller/Persistence/IPeopleManager.cs
+++ b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs
@@ -8,7 +8,7 @@ using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Persistence;
-public interface IPeopleManager
+public interface IPeopleRepository
{
/// <summary>
/// Gets the people.
@@ -30,5 +30,4 @@ public interface IPeopleManager
/// <param name="filter">The query.</param>
/// <returns>List&lt;System.String&gt;.</returns>
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter);
-
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 246ba2733..62c590944 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly IEncodingManager _encodingManager;
private readonly IServerConfigurationManager _config;
private readonly ISubtitleManager _subtitleManager;
- private readonly IChapterManager _chapterManager;
+ private readonly IChapterRepository _chapterManager;
private readonly ILibraryManager _libraryManager;
private readonly AudioResolver _audioResolver;
private readonly SubtitleResolver _subtitleResolver;
@@ -54,7 +54,7 @@ namespace MediaBrowser.Providers.MediaInfo
IEncodingManager encodingManager,
IServerConfigurationManager config,
ISubtitleManager subtitleManager,
- IChapterManager chapterManager,
+ IChapterRepository chapterManager,
ILibraryManager libraryManager,
AudioResolver audioResolver,
SubtitleResolver subtitleResolver)
diff --git a/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs
index 04da8fb88..f5e9dddcf 100644
--- a/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs
@@ -61,7 +61,7 @@ namespace MediaBrowser.Providers.MediaInfo
/// <param name="encodingManager">Instance of the <see cref="IEncodingManager"/> interface.</param>
/// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="subtitleManager">Instance of the <see cref="ISubtitleManager"/> interface.</param>
- /// <param name="chapterManager">Instance of the <see cref="IChapterManager"/> interface.</param>
+ /// <param name="chapterManager">Instance of the <see cref="IChapterRepository"/> interface.</param>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/>.</param>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
@@ -76,7 +76,7 @@ namespace MediaBrowser.Providers.MediaInfo
IEncodingManager encodingManager,
IServerConfigurationManager config,
ISubtitleManager subtitleManager,
- IChapterManager chapterManager,
+ IChapterRepository chapterManager,
ILibraryManager libraryManager,
IFileSystem fileSystem,
ILoggerFactory loggerFactory,
diff --git a/src/Jellyfin.Drawing/ImageProcessor.cs b/src/Jellyfin.Drawing/ImageProcessor.cs
index 5d4732234..b57f2753f 100644
--- a/src/Jellyfin.Drawing/ImageProcessor.cs
+++ b/src/Jellyfin.Drawing/ImageProcessor.cs
@@ -15,6 +15,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
@@ -404,10 +405,34 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
}
/// <inheritdoc />
+ public string GetImageCacheTag(string baseItemPath, DateTime imageDateModified)
+ => (baseItemPath + imageDateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+
+ /// <inheritdoc />
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
/// <inheritdoc />
+ public string GetImageCacheTag(BaseItemDto item, ItemImageInfo image)
+ => (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+
+ /// <inheritdoc />
+ public string? GetImageCacheTag(BaseItemDto item, ChapterInfo chapter)
+ {
+ if (chapter.ImagePath is null)
+ {
+ return null;
+ }
+
+ return GetImageCacheTag(item, new ItemImageInfo
+ {
+ Path = chapter.ImagePath,
+ Type = ImageType.Chapter,
+ DateModified = chapter.ImageDateModified
+ });
+ }
+
+ /// <inheritdoc />
public string? GetImageCacheTag(BaseItem item, ChapterInfo chapter)
{
if (chapter.ImagePath is null)