diff options
Diffstat (limited to 'MediaBrowser.Controller')
41 files changed, 384 insertions, 318 deletions
diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs deleted file mode 100644 index c049bb97e..000000000 --- a/MediaBrowser.Controller/Chapters/IChapterManager.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -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); - } -} 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/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 40cdd6c91..00b06dc79 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -64,7 +64,7 @@ namespace MediaBrowser.Controller.Entities return CreateResolveArgs(directoryService, true).FileSystemChildren; } - protected override List<BaseItem> LoadChildren() + protected override IReadOnlyList<BaseItem> LoadChildren() { lock (_childIdsLock) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index a0aae8769..f3873775b 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -21,6 +21,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// <summary> /// Class MusicAlbum. /// </summary> + [Common.RequiresSourceSerialisation] public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer { public MusicAlbum() diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 1ab6c9706..537550925 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -21,6 +21,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// <summary> /// Class MusicArtist. /// </summary> + [Common.RequiresSourceSerialisation] public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo<ArtistInfo> { [JsonIgnore] @@ -84,7 +85,7 @@ namespace MediaBrowser.Controller.Entities.Audio return !IsAccessedByName; } - public IList<BaseItem> GetTaggedItems(InternalItemsQuery query) + public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query) { if (query.IncludeItemTypes.Length == 0) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 7448d02ea..65669e680 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -14,6 +14,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// <summary> /// Class MusicGenre. /// </summary> + [Common.RequiresSourceSerialisation] public class MusicGenre : BaseItem, IItemByName { [JsonIgnore] @@ -64,7 +65,7 @@ namespace MediaBrowser.Controller.Entities.Audio return true; } - public IList<BaseItem> GetTaggedItems(InternalItemsQuery query) + public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query) { query.GenreIds = new[] { Id }; query.IncludeItemTypes = new[] { BaseItemKind.MusicVideo, BaseItemKind.Audio, BaseItemKind.MusicAlbum, BaseItemKind.MusicArtist }; diff --git a/MediaBrowser.Controller/Entities/AudioBook.cs b/MediaBrowser.Controller/Entities/AudioBook.cs index 782481fbc..666bf2a75 100644 --- a/MediaBrowser.Controller/Entities/AudioBook.cs +++ b/MediaBrowser.Controller/Entities/AudioBook.cs @@ -9,6 +9,7 @@ using MediaBrowser.Controller.Providers; namespace MediaBrowser.Controller.Entities { + [Common.RequiresSourceSerialisation] public class AudioBook : Audio.Audio, IHasSeries, IHasLookupInfo<SongInfo> { [JsonIgnore] diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index eb605f6c8..a6bc35a9f 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Globalization; using System.IO; using System.Linq; @@ -16,6 +17,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 +481,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; } @@ -1041,7 +1045,7 @@ namespace MediaBrowser.Controller.Entities return PlayAccess.Full; } - public virtual List<MediaStream> GetMediaStreams() + public virtual IReadOnlyList<MediaStream> GetMediaStreams() { return MediaSourceManager.GetMediaStreams(new MediaStreamQuery { @@ -1054,7 +1058,7 @@ namespace MediaBrowser.Controller.Entities return false; } - public virtual List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) + public virtual IReadOnlyList<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) { if (SourceType == SourceType.Channel) { @@ -1088,7 +1092,7 @@ namespace MediaBrowser.Controller.Entities return 1; }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) .ThenByDescending(i => i, new MediaSourceWidthComparator()) - .ToList(); + .ToArray(); } protected virtual IEnumerable<(BaseItem Item, MediaSourceType MediaSourceType)> GetAllItemsForMediaSources() @@ -1781,7 +1785,7 @@ namespace MediaBrowser.Controller.Entities } else { - Studios = [..current, name]; + Studios = [.. current, name]; } } } @@ -1803,7 +1807,7 @@ namespace MediaBrowser.Controller.Entities var genres = Genres; if (!genres.Contains(name, StringComparison.OrdinalIgnoreCase)) { - Genres = [..genres, name]; + Genres = [.. genres, name]; } } @@ -1821,7 +1825,10 @@ namespace MediaBrowser.Controller.Entities { ArgumentNullException.ThrowIfNull(user); - var data = UserDataManager.GetUserData(user, this); + var data = UserDataManager.GetUserData(user, this) ?? new UserItemData() + { + Key = GetUserDataKeys().First(), + }; if (datePlayed.HasValue) { @@ -1974,7 +1981,7 @@ namespace MediaBrowser.Controller.Entities public void AddImage(ItemImageInfo image) { - ImageInfos = [..ImageInfos, image]; + ImageInfos = [.. ImageInfos, image]; } public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken) @@ -2031,7 +2038,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 +2088,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) @@ -2524,7 +2531,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="children">Media children.</param> /// <returns><c>true</c> if the rating was updated; otherwise <c>false</c>.</returns> - public bool UpdateRatingToItems(IList<BaseItem> children) + public bool UpdateRatingToItems(IReadOnlyList<BaseItem> children) { var currentOfficialRating = OfficialRating; diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs index 66dea1084..518766937 100644 --- a/MediaBrowser.Controller/Entities/Book.cs +++ b/MediaBrowser.Controller/Entities/Book.cs @@ -10,6 +10,7 @@ using MediaBrowser.Controller.Providers; namespace MediaBrowser.Controller.Entities { + [Common.RequiresSourceSerialisation] public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries { public Book() diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 83c19a54e..a13f04614 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.IO; using System.Linq; using System.Security; @@ -11,6 +12,7 @@ using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Dataflow; +using J2N.Collections.Generic.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using Jellyfin.Extensions; @@ -247,7 +249,7 @@ namespace MediaBrowser.Controller.Entities /// We want this synchronous. /// </summary> /// <returns>Returns children.</returns> - protected virtual List<BaseItem> LoadChildren() + protected virtual IReadOnlyList<BaseItem> LoadChildren() { // logger.LogDebug("Loading children from {0} {1} {2}", GetType().Name, Id, Path); // just load our children from the repo - the library will be validated and maintained in other processes @@ -450,7 +452,7 @@ namespace MediaBrowser.Controller.Entities if (newItems.Count > 0) { - LibraryManager.CreateItems(newItems, this, cancellationToken); + LibraryManager.CreateOrUpdateItems(newItems, this, cancellationToken); } } else @@ -659,7 +661,7 @@ namespace MediaBrowser.Controller.Entities /// Get our children from the repo - stubbed for now. /// </summary> /// <returns>IEnumerable{BaseItem}.</returns> - protected List<BaseItem> GetCachedChildren() + protected IReadOnlyList<BaseItem> GetCachedChildren() { return ItemRepository.GetItemList(new InternalItemsQuery { @@ -1283,14 +1285,14 @@ namespace MediaBrowser.Controller.Entities return true; } - public List<BaseItem> GetChildren(User user, bool includeLinkedChildren) + public IReadOnlyList<BaseItem> GetChildren(User user, bool includeLinkedChildren) { ArgumentNullException.ThrowIfNull(user); return GetChildren(user, includeLinkedChildren, new InternalItemsQuery(user)); } - public virtual List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) + public virtual IReadOnlyList<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { ArgumentNullException.ThrowIfNull(user); @@ -1304,7 +1306,7 @@ namespace MediaBrowser.Controller.Entities AddChildren(user, includeLinkedChildren, result, false, query); - return result.Values.ToList(); + return result.Values.ToArray(); } protected virtual IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) @@ -1369,7 +1371,7 @@ namespace MediaBrowser.Controller.Entities } } - public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) + public virtual IReadOnlyList<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) { ArgumentNullException.ThrowIfNull(user); @@ -1377,35 +1379,35 @@ namespace MediaBrowser.Controller.Entities AddChildren(user, true, result, true, query); - return result.Values; + return result.Values.ToArray(); } /// <summary> /// Gets the recursive children. /// </summary> /// <returns>IList{BaseItem}.</returns> - public IList<BaseItem> GetRecursiveChildren() + public IReadOnlyList<BaseItem> GetRecursiveChildren() { return GetRecursiveChildren(true); } - public IList<BaseItem> GetRecursiveChildren(bool includeLinkedChildren) + public IReadOnlyList<BaseItem> GetRecursiveChildren(bool includeLinkedChildren) { return GetRecursiveChildren(i => true, includeLinkedChildren); } - public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter) + public IReadOnlyList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter) { return GetRecursiveChildren(filter, true); } - public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter, bool includeLinkedChildren) + public IReadOnlyList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter, bool includeLinkedChildren) { var result = new Dictionary<Guid, BaseItem>(); AddChildrenToList(result, includeLinkedChildren, true, filter); - return result.Values.ToList(); + return result.Values.ToArray(); } /// <summary> @@ -1556,11 +1558,12 @@ namespace MediaBrowser.Controller.Entities /// Gets the linked children. /// </summary> /// <returns>IEnumerable{BaseItem}.</returns> - public IEnumerable<Tuple<LinkedChild, BaseItem>> GetLinkedChildrenInfos() + public IReadOnlyList<Tuple<LinkedChild, BaseItem>> GetLinkedChildrenInfos() { return LinkedChildren .Select(i => new Tuple<LinkedChild, BaseItem>(i, GetLinkedChild(i))) - .Where(i => i.Item2 is not null); + .Where(i => i.Item2 is not null) + .ToArray(); } protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index ddf62dd4c..6ec78a270 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -14,6 +14,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Genre. /// </summary> + [Common.RequiresSourceSerialisation] public class Genre : BaseItem, IItemByName { /// <summary> @@ -61,7 +62,7 @@ namespace MediaBrowser.Controller.Entities return false; } - public IList<BaseItem> GetTaggedItems(InternalItemsQuery query) + public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query) { query.GenreIds = new[] { Id }; query.ExcludeItemTypes = new[] diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs index 90d9bdd2d..ad35494c2 100644 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -22,8 +22,8 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="enablePathSubstitution"><c>true</c> to enable path substitution, <c>false</c> to not.</param> /// <returns>A list of media sources.</returns> - List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution); + IReadOnlyList<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution); - List<MediaStream> GetMediaStreams(); + IReadOnlyList<MediaStream> GetMediaStreams(); } } diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs index cac8aa61a..4928bda7a 100644 --- a/MediaBrowser.Controller/Entities/IItemByName.cs +++ b/MediaBrowser.Controller/Entities/IItemByName.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> public interface IItemByName { - IList<BaseItem> GetTaggedItems(InternalItemsQuery query); + IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query); } public interface IHasDualAccess : IItemByName diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 1461a3680..43f02fb72 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -37,7 +37,6 @@ namespace MediaBrowser.Controller.Entities IncludeItemTypes = Array.Empty<BaseItemKind>(); ItemIds = Array.Empty<Guid>(); MediaTypes = Array.Empty<MediaType>(); - MinSimilarityScore = 20; OfficialRatings = Array.Empty<string>(); OrderBy = Array.Empty<(ItemSortBy, SortOrder)>(); PersonIds = Array.Empty<Guid>(); @@ -71,8 +70,6 @@ namespace MediaBrowser.Controller.Entities public User? User { get; set; } - public BaseItem? SimilarTo { get; set; } - public bool? IsFolder { get; set; } public bool? IsFavorite { get; set; } @@ -295,8 +292,6 @@ namespace MediaBrowser.Controller.Entities public DtoOptions DtoOptions { get; set; } - public int MinSimilarityScore { get; set; } - public string? HasNoAudioTrackWithLanguage { get; set; } public string? HasNoInternalSubtitleTrackWithLanguage { get; set; } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index a07187d2f..d0c9f049a 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Text.Json.Serialization; using Jellyfin.Data.Entities; @@ -91,7 +92,7 @@ namespace MediaBrowser.Controller.Entities.Movies return Enumerable.Empty<BaseItem>(); } - protected override List<BaseItem> LoadChildren() + protected override IReadOnlyList<BaseItem> LoadChildren() { if (IsLegacyBoxSet) { @@ -99,7 +100,7 @@ namespace MediaBrowser.Controller.Entities.Movies } // Save a trip to the database - return new List<BaseItem>(); + return []; } public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) @@ -127,16 +128,16 @@ namespace MediaBrowser.Controller.Entities.Movies return LibraryManager.Sort(items, user, new[] { sortBy }, SortOrder.Ascending); } - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) + public override IReadOnlyList<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { var children = base.GetChildren(user, includeLinkedChildren, query); - return Sort(children, user).ToList(); + return Sort(children, user).ToArray(); } - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) + public override IReadOnlyList<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) { var children = base.GetRecursiveChildren(user, query); - return Sort(children, user).ToList(); + return Sort(children, user).ToArray(); } public BoxSetInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs index 5292bd772..4141b1712 100644 --- a/MediaBrowser.Controller/Entities/PeopleHelper.cs +++ b/MediaBrowser.Controller/Entities/PeopleHelper.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Controller.Entities { public static class PeopleHelper { - public static void AddPerson(List<PersonInfo> people, PersonInfo person) + public static void AddPerson(ICollection<PersonInfo> people, PersonInfo person) { ArgumentNullException.ThrowIfNull(person); ArgumentException.ThrowIfNullOrEmpty(person.Name); diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 7f265084f..5cc4d322f 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -14,6 +14,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// This is the full Person object that can be retrieved with all of it's data. /// </summary> + [Common.RequiresSourceSerialisation] public class Person : BaseItem, IItemByName, IHasLookupInfo<PersonLookupInfo> { /// <summary> @@ -62,7 +63,7 @@ namespace MediaBrowser.Controller.Entities return value; } - public IList<BaseItem> GetTaggedItems(InternalItemsQuery query) + public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query) { query.PersonIds = new[] { Id }; diff --git a/MediaBrowser.Controller/Entities/PersonInfo.cs b/MediaBrowser.Controller/Entities/PersonInfo.cs index 3df0b0b78..0ed870bac 100644 --- a/MediaBrowser.Controller/Entities/PersonInfo.cs +++ b/MediaBrowser.Controller/Entities/PersonInfo.cs @@ -17,8 +17,14 @@ namespace MediaBrowser.Controller.Entities public PersonInfo() { ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); + Id = Guid.NewGuid(); } + /// <summary> + /// Gets or Sets the PersonId. + /// </summary> + public Guid Id { get; set; } + public Guid ItemId { get; set; } /// <summary> diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs index a7ecb9061..5b31b4f11 100644 --- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs +++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs @@ -4,6 +4,7 @@ using System.Text.Json.Serialization; namespace MediaBrowser.Controller.Entities { + [Common.RequiresSourceSerialisation] public class PhotoAlbum : Folder { [JsonIgnore] diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index a3736a4bf..9103b09a9 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -13,6 +13,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Studio. /// </summary> + [Common.RequiresSourceSerialisation] public class Studio : BaseItem, IItemByName { /// <summary> @@ -63,7 +64,7 @@ namespace MediaBrowser.Controller.Entities return true; } - public IList<BaseItem> GetTaggedItems(InternalItemsQuery query) + public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query) { query.StudioIds = new[] { Id }; diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 181b9be2b..8e9f5818d 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -10,6 +10,7 @@ using System.Text.Json.Serialization; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using Jellyfin.Extensions; +using MediaBrowser.Common; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Querying; @@ -19,6 +20,7 @@ namespace MediaBrowser.Controller.Entities.TV /// <summary> /// Class Season. /// </summary> + [RequiresSourceSerialisation] public class Season : Folder, IHasSeries, IHasLookupInfo<SeasonInfo> { [JsonIgnore] diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index a324f79ef..137d91f1c 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -189,12 +189,12 @@ namespace MediaBrowser.Controller.Entities.TV return list; } - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) + public override IReadOnlyList<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { return GetSeasons(user, new DtoOptions(true)); } - public List<BaseItem> GetSeasons(User user, DtoOptions options) + public IReadOnlyList<BaseItem> GetSeasons(User user, DtoOptions options) { var query = new InternalItemsQuery(user) { diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index a687adedd..7cf447fb8 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -52,7 +52,7 @@ namespace MediaBrowser.Controller.Entities } } - protected override List<BaseItem> LoadChildren() + protected override IReadOnlyList<BaseItem> LoadChildren() { lock (_childIdsLock) { diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index e4fb340f7..f5ca3737c 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -134,7 +134,7 @@ namespace MediaBrowser.Controller.Entities } /// <inheritdoc /> - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) + public override IReadOnlyList<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) { query.SetUser(user); query.Recursive = true; @@ -145,7 +145,7 @@ namespace MediaBrowser.Controller.Entities } /// <inheritdoc /> - protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) + protected override IReadOnlyList<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) { return GetChildren(user, false); } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 420349f35..4ec2e4c0a 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -236,7 +236,7 @@ namespace MediaBrowser.Controller.Entities return ConvertToResult(_libraryManager.GetItemList(query)); } - private QueryResult<BaseItem> ConvertToResult(List<BaseItem> items) + private QueryResult<BaseItem> ConvertToResult(IReadOnlyList<BaseItem> items) { return new QueryResult<BaseItem>(items); } diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index afdaf448b..37820296c 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -13,6 +13,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class Year. /// </summary> + [Common.RequiresSourceSerialisation] public class Year : BaseItem, IItemByName { [JsonIgnore] @@ -55,7 +56,7 @@ namespace MediaBrowser.Controller.Entities return true; } - public IList<BaseItem> GetTaggedItems(InternalItemsQuery query) + public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query) { if (!int.TryParse(Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year)) { diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index b802b7e6e..8fcd5f605 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -258,7 +258,7 @@ namespace MediaBrowser.Controller.Library /// <param name="items">Items to create.</param> /// <param name="parent">Parent of new items.</param> /// <param name="cancellationToken">CancellationToken to use for operation.</param> - void CreateItems(IReadOnlyList<BaseItem> items, BaseItem? parent, CancellationToken cancellationToken); + void CreateOrUpdateItems(IReadOnlyList<BaseItem> items, BaseItem? parent, CancellationToken cancellationToken); /// <summary> /// Updates the item. @@ -483,21 +483,21 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="item">The item.</param> /// <returns>List<PersonInfo>.</returns> - List<PersonInfo> GetPeople(BaseItem item); + IReadOnlyList<PersonInfo> GetPeople(BaseItem item); /// <summary> /// Gets the people. /// </summary> /// <param name="query">The query.</param> /// <returns>List<PersonInfo>.</returns> - List<PersonInfo> GetPeople(InternalPeopleQuery query); + IReadOnlyList<PersonInfo> GetPeople(InternalPeopleQuery query); /// <summary> /// Gets the people items. /// </summary> /// <param name="query">The query.</param> /// <returns>List<Person>.</returns> - List<Person> GetPeopleItems(InternalPeopleQuery query); + IReadOnlyList<Person> GetPeopleItems(InternalPeopleQuery query); /// <summary> /// Updates the people. @@ -513,21 +513,21 @@ namespace MediaBrowser.Controller.Library /// <param name="people">The people.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>The async task.</returns> - Task UpdatePeopleAsync(BaseItem item, List<PersonInfo> people, CancellationToken cancellationToken); + Task UpdatePeopleAsync(BaseItem item, IReadOnlyList<PersonInfo> people, CancellationToken cancellationToken); /// <summary> /// Gets the item ids. /// </summary> /// <param name="query">The query.</param> /// <returns>List<Guid>.</returns> - List<Guid> GetItemIds(InternalItemsQuery query); + IReadOnlyList<Guid> GetItemIds(InternalItemsQuery query); /// <summary> /// Gets the people names. /// </summary> /// <param name="query">The query.</param> /// <returns>List<System.String>.</returns> - List<string> GetPeopleNames(InternalPeopleQuery query); + IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery query); /// <summary> /// Queries the items. @@ -553,9 +553,9 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="query">The query.</param> /// <returns>QueryResult<BaseItem>.</returns> - List<BaseItem> GetItemList(InternalItemsQuery query); + IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query); - List<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent); + IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent); /// <summary> /// Gets the items. @@ -563,7 +563,7 @@ namespace MediaBrowser.Controller.Library /// <param name="query">The query to use.</param> /// <param name="parents">Items to use for query.</param> /// <returns>List of items.</returns> - List<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents); + IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents); /// <summary> /// Gets the items result. diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 44a1a85e3..729b385cf 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -29,28 +29,28 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="itemId">The item identifier.</param> /// <returns>IEnumerable<MediaStream>.</returns> - List<MediaStream> GetMediaStreams(Guid itemId); + IReadOnlyList<MediaStream> GetMediaStreams(Guid itemId); /// <summary> /// Gets the media streams. /// </summary> /// <param name="query">The query.</param> /// <returns>IEnumerable<MediaStream>.</returns> - List<MediaStream> GetMediaStreams(MediaStreamQuery query); + IReadOnlyList<MediaStream> GetMediaStreams(MediaStreamQuery query); /// <summary> /// Gets the media attachments. /// </summary> /// <param name="itemId">The item identifier.</param> /// <returns>IEnumerable<MediaAttachment>.</returns> - List<MediaAttachment> GetMediaAttachments(Guid itemId); + IReadOnlyList<MediaAttachment> GetMediaAttachments(Guid itemId); /// <summary> /// Gets the media attachments. /// </summary> /// <param name="query">The query.</param> /// <returns>IEnumerable<MediaAttachment>.</returns> - List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query); + IReadOnlyList<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query); /// <summary> /// Gets the playack media sources. @@ -61,7 +61,7 @@ namespace MediaBrowser.Controller.Library /// <param name="enablePathSubstitution">Option to enable path substitution.</param> /// <param name="cancellationToken">CancellationToken to use for operation.</param> /// <returns>List of media sources wrapped in an awaitable task.</returns> - Task<List<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken); + Task<IReadOnlyList<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken); /// <summary> /// Gets the static media sources. @@ -70,7 +70,7 @@ namespace MediaBrowser.Controller.Library /// <param name="enablePathSubstitution">Option to enable path substitution.</param> /// <param name="user">User to use for operation.</param> /// <returns>List of media sources.</returns> - List<MediaSourceInfo> GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null); + IReadOnlyList<MediaSourceInfo> GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null); /// <summary> /// Gets the static media source. @@ -123,7 +123,7 @@ namespace MediaBrowser.Controller.Library /// <param name="info">The <see cref="ActiveRecordingInfo"/>.</param> /// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param> /// <returns>A task containing the <see cref="MediaSourceInfo"/>'s for the recording.</returns> - Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(ActiveRecordingInfo info, CancellationToken cancellationToken); + Task<IReadOnlyList<MediaSourceInfo>> GetRecordingStreamMediaSources(ActiveRecordingInfo info, CancellationToken cancellationToken); /// <summary> /// Closes the media source. diff --git a/MediaBrowser.Controller/Library/IMusicManager.cs b/MediaBrowser.Controller/Library/IMusicManager.cs index 93073cc79..7ba8fc20c 100644 --- a/MediaBrowser.Controller/Library/IMusicManager.cs +++ b/MediaBrowser.Controller/Library/IMusicManager.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Library /// <param name="user">The user to use.</param> /// <param name="dtoOptions">The options to use.</param> /// <returns>List of items.</returns> - List<BaseItem> GetInstantMixFromItem(BaseItem item, User? user, DtoOptions dtoOptions); + IReadOnlyList<BaseItem> GetInstantMixFromItem(BaseItem item, User? user, DtoOptions dtoOptions); /// <summary> /// Gets the instant mix from artist. @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Library /// <param name="user">The user to use.</param> /// <param name="dtoOptions">The options to use.</param> /// <returns>List of items.</returns> - List<BaseItem> GetInstantMixFromArtist(MusicArtist artist, User? user, DtoOptions dtoOptions); + IReadOnlyList<BaseItem> GetInstantMixFromArtist(MusicArtist artist, User? user, DtoOptions dtoOptions); /// <summary> /// Gets the instant mix from genre. @@ -35,6 +35,6 @@ namespace MediaBrowser.Controller.Library /// <param name="user">The user to use.</param> /// <param name="dtoOptions">The options to use.</param> /// <returns>List of items.</returns> - List<BaseItem> GetInstantMixFromGenres(IEnumerable<string> genres, User? user, DtoOptions dtoOptions); + IReadOnlyList<BaseItem> GetInstantMixFromGenres(IEnumerable<string> genres, User? user, DtoOptions dtoOptions); } } diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index f36fd393f..5a2deda66 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Library /// <param name="user">User to use.</param> /// <param name="item">Item to use.</param> /// <returns>User data.</returns> - UserItemData GetUserData(User user, BaseItem item); + UserItemData? GetUserData(User user, BaseItem item); /// <summary> /// Gets the user data dto. @@ -52,7 +52,7 @@ namespace MediaBrowser.Controller.Library /// <param name="item">Item to use.</param> /// <param name="user">User to use.</param> /// <returns>User data dto.</returns> - UserItemDataDto GetUserDataDto(BaseItem item, User user); + UserItemDataDto? GetUserDataDto(BaseItem item, User user); /// <summary> /// Gets the user data dto. @@ -62,7 +62,7 @@ namespace MediaBrowser.Controller.Library /// <param name="user">User to use.</param> /// <param name="options">Dto options to use.</param> /// <returns>User data dto.</returns> - UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto? itemDto, User user, DtoOptions options); + UserItemDataDto? GetUserDataDto(BaseItem item, BaseItemDto? itemDto, User user, DtoOptions options); /// <summary> /// Updates playstate for an item and returns true or false indicating if it was played to completion. diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 3c2cf8e3d..b10e77e10 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Globalization; using System.Linq; using System.Text.Json.Serialization; @@ -119,13 +120,10 @@ namespace MediaBrowser.Controller.LiveTv return "TvChannel"; } - public IEnumerable<BaseItem> GetTaggedItems() - => Enumerable.Empty<BaseItem>(); + public IEnumerable<BaseItem> GetTaggedItems() => []; - public override List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) + public override IReadOnlyList<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) { - var list = new List<MediaSourceInfo>(); - var info = new MediaSourceInfo { Id = Id.ToString("N", CultureInfo.InvariantCulture), @@ -138,14 +136,12 @@ namespace MediaBrowser.Controller.LiveTv IsInfiniteStream = RunTimeTicks is null }; - list.Add(info); - - return list; + return [info]; } - public override List<MediaStream> GetMediaStreams() + public override IReadOnlyList<MediaStream> GetMediaStreams() { - return new List<MediaStream>(); + return []; } protected override string GetInternalMetadataPath(string basePath) diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 2ac6f9963..83944f741 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -18,6 +18,7 @@ using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.LiveTv { + [Common.RequiresSourceSerialisation] public class LiveTvProgram : BaseItem, IHasLookupInfo<ItemLookupInfo>, IHasStartDate, IHasProgramAttributes { private const string EmbyServiceName = "Emby"; diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 2c52b2b45..b27f156ef 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -7,157 +7,82 @@ using System.Collections.Generic; using System.Threading; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; -namespace MediaBrowser.Controller.Persistence +namespace MediaBrowser.Controller.Persistence; + +/// <summary> +/// Provides an interface to implement an Item repository. +/// </summary> +public interface IItemRepository : IDisposable { /// <summary> - /// Provides an interface to implement an Item repository. + /// Deletes the item. + /// </summary> + /// <param name="id">The identifier.</param> + void DeleteItem(Guid id); + + /// <summary> + /// Saves the items. + /// </summary> + /// <param name="items">The items.</param> + /// <param name="cancellationToken">The cancellation token.</param> + void SaveItems(IReadOnlyList<BaseItem> items, CancellationToken cancellationToken); + + void SaveImages(BaseItem item); + + /// <summary> + /// Retrieves the item. /// </summary> - public interface IItemRepository : IDisposable - { - /// <summary> - /// Deletes the item. - /// </summary> - /// <param name="id">The identifier.</param> - void DeleteItem(Guid id); - - /// <summary> - /// Saves the items. - /// </summary> - /// <param name="items">The items.</param> - /// <param name="cancellationToken">The cancellation token.</param> - void SaveItems(IReadOnlyList<BaseItem> items, CancellationToken cancellationToken); - - void SaveImages(BaseItem item); - - /// <summary> - /// Retrieves the item. - /// </summary> - /// <param name="id">The id.</param> - /// <returns>BaseItem.</returns> - BaseItem RetrieveItem(Guid id); - - /// <summary> - /// Gets chapters for an item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>The list of chapter info.</returns> - List<ChapterInfo> GetChapters(BaseItem item); - - /// <summary> - /// Gets a single chapter for an item. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="index">The chapter index.</param> - /// <returns>The chapter info at the specified index.</returns> - ChapterInfo GetChapter(BaseItem item, int index); - - /// <summary> - /// Saves the chapters. - /// </summary> - /// <param name="id">The item id.</param> - /// <param name="chapters">The list of chapters to save.</param> - void SaveChapters(Guid id, IReadOnlyList<ChapterInfo> chapters); - - /// <summary> - /// Gets the media streams. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>IEnumerable{MediaStream}.</returns> - List<MediaStream> GetMediaStreams(MediaStreamQuery query); - - /// <summary> - /// Saves the media streams. - /// </summary> - /// <param name="id">The identifier.</param> - /// <param name="streams">The streams.</param> - /// <param name="cancellationToken">The cancellation token.</param> - void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken); - - /// <summary> - /// Gets the media attachments. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>IEnumerable{MediaAttachment}.</returns> - List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query); - - /// <summary> - /// Saves the media attachments. - /// </summary> - /// <param name="id">The identifier.</param> - /// <param name="attachments">The attachments.</param> - /// <param name="cancellationToken">The cancellation token.</param> - void SaveMediaAttachments(Guid id, IReadOnlyList<MediaAttachment> attachments, CancellationToken cancellationToken); - - /// <summary> - /// Gets the items. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>QueryResult<BaseItem>.</returns> - QueryResult<BaseItem> GetItems(InternalItemsQuery query); - - /// <summary> - /// Gets the item ids list. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>List<Guid>.</returns> - List<Guid> GetItemIdsList(InternalItemsQuery query); - - /// <summary> - /// Gets the people. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>List<PersonInfo>.</returns> - List<PersonInfo> GetPeople(InternalPeopleQuery query); - - /// <summary> - /// Updates the people. - /// </summary> - /// <param name="itemId">The item identifier.</param> - /// <param name="people">The people.</param> - void UpdatePeople(Guid itemId, List<PersonInfo> people); - - /// <summary> - /// Gets the people names. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>List<System.String>.</returns> - List<string> GetPeopleNames(InternalPeopleQuery query); - - /// <summary> - /// Gets the item list. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>List<BaseItem>.</returns> - List<BaseItem> GetItemList(InternalItemsQuery query); - - /// <summary> - /// Updates the inherited values. - /// </summary> - void UpdateInheritedValues(); - - int GetCount(InternalItemsQuery query); - - QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query); - - QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query); - - QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query); - - QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query); - - QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query); - - QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query); - - List<string> GetMusicGenreNames(); - - List<string> GetStudioNames(); - - List<string> GetGenreNames(); - - List<string> GetAllArtistNames(); - } + /// <param name="id">The id.</param> + /// <returns>BaseItem.</returns> + BaseItem RetrieveItem(Guid id); + + /// <summary> + /// Gets the items. + /// </summary> + /// <param name="filter">The query.</param> + /// <returns>QueryResult<BaseItem>.</returns> + QueryResult<BaseItem> GetItems(InternalItemsQuery filter); + + /// <summary> + /// Gets the item ids list. + /// </summary> + /// <param name="filter">The query.</param> + /// <returns>List<Guid>.</returns> + IReadOnlyList<Guid> GetItemIdsList(InternalItemsQuery filter); + + /// <summary> + /// Gets the item list. + /// </summary> + /// <param name="filter">The query.</param> + /// <returns>List<BaseItem>.</returns> + IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery filter); + + /// <summary> + /// Updates the inherited values. + /// </summary> + void UpdateInheritedValues(); + + int GetCount(InternalItemsQuery filter); + + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery filter); + + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery filter); + + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery filter); + + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery filter); + + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery filter); + + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery filter); + + IReadOnlyList<string> GetMusicGenreNames(); + + IReadOnlyList<string> GetStudioNames(); + + IReadOnlyList<string> GetGenreNames(); + + IReadOnlyList<string> GetAllArtistNames(); } diff --git a/MediaBrowser.Controller/Persistence/IItemTypeLookup.cs b/MediaBrowser.Controller/Persistence/IItemTypeLookup.cs new file mode 100644 index 000000000..6699d3a4d --- /dev/null +++ b/MediaBrowser.Controller/Persistence/IItemTypeLookup.cs @@ -0,0 +1,22 @@ +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 serialisation target types for music related kinds. + /// </summary> + IReadOnlyList<string> MusicGenreTypes { get; } + + /// <summary> + /// Gets mapping for all BaseItemKinds and their expected serialization target. + /// </summary> + IReadOnlyDictionary<BaseItemKind, string> BaseItemKindNames { get; } +} diff --git a/MediaBrowser.Controller/Persistence/IMediaAttachmentRepository.cs b/MediaBrowser.Controller/Persistence/IMediaAttachmentRepository.cs new file mode 100644 index 000000000..4773f4058 --- /dev/null +++ b/MediaBrowser.Controller/Persistence/IMediaAttachmentRepository.cs @@ -0,0 +1,28 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using System.Threading; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Persistence; + +public interface IMediaAttachmentRepository +{ + /// <summary> + /// Gets the media attachments. + /// </summary> + /// <param name="filter">The query.</param> + /// <returns>IEnumerable{MediaAttachment}.</returns> + IReadOnlyList<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery filter); + + /// <summary> + /// Saves the media attachments. + /// </summary> + /// <param name="id">The identifier.</param> + /// <param name="attachments">The attachments.</param> + /// <param name="cancellationToken">The cancellation token.</param> + void SaveMediaAttachments(Guid id, IReadOnlyList<MediaAttachment> attachments, CancellationToken cancellationToken); +} diff --git a/MediaBrowser.Controller/Persistence/IMediaStreamRepository.cs b/MediaBrowser.Controller/Persistence/IMediaStreamRepository.cs new file mode 100644 index 000000000..665129eaf --- /dev/null +++ b/MediaBrowser.Controller/Persistence/IMediaStreamRepository.cs @@ -0,0 +1,31 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using System.Threading; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Persistence; + +/// <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> + IReadOnlyList<MediaStream> GetMediaStreams(MediaStreamQuery filter); + + /// <summary> + /// Saves the media streams. + /// </summary> + /// <param name="id">The identifier.</param> + /// <param name="streams">The streams.</param> + /// <param name="cancellationToken">The cancellation token.</param> + void SaveMediaStreams(Guid id, IReadOnlyList<MediaStream> streams, CancellationToken cancellationToken); +} diff --git a/MediaBrowser.Controller/Persistence/IPeopleRepository.cs b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs new file mode 100644 index 000000000..418289cb4 --- /dev/null +++ b/MediaBrowser.Controller/Persistence/IPeopleRepository.cs @@ -0,0 +1,33 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Persistence; + +public interface IPeopleRepository +{ + /// <summary> + /// Gets the people. + /// </summary> + /// <param name="filter">The query.</param> + /// <returns>The list of people matching the filter.</returns> + IReadOnlyList<PersonInfo> GetPeople(InternalPeopleQuery filter); + + /// <summary> + /// Updates the people. + /// </summary> + /// <param name="itemId">The item identifier.</param> + /// <param name="people">The people.</param> + void UpdatePeople(Guid itemId, IReadOnlyList<PersonInfo> people); + + /// <summary> + /// Gets the people names. + /// </summary> + /// <param name="filter">The query.</param> + /// <returns>The list of people names matching the filter.</returns> + IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery filter); +} diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs deleted file mode 100644 index f2fb2826a..000000000 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ /dev/null @@ -1,55 +0,0 @@ -#nullable disable - -using System; -using System.Collections.Generic; -using System.Threading; -using MediaBrowser.Controller.Entities; - -namespace MediaBrowser.Controller.Persistence -{ - /// <summary> - /// Provides an interface to implement a UserData repository. - /// </summary> - public interface IUserDataRepository : IDisposable - { - /// <summary> - /// Saves the user data. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="key">The key.</param> - /// <param name="userData">The user data.</param> - /// <param name="cancellationToken">The cancellation token.</param> - void SaveUserData(long userId, string key, UserItemData userData, CancellationToken cancellationToken); - - /// <summary> - /// Gets the user data. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="key">The key.</param> - /// <returns>The user data.</returns> - UserItemData GetUserData(long userId, string key); - - /// <summary> - /// Gets the user data. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="keys">The keys.</param> - /// <returns>The user data.</returns> - UserItemData GetUserData(long userId, List<string> keys); - - /// <summary> - /// Return all user data associated with the given user. - /// </summary> - /// <param name="userId">The user id.</param> - /// <returns>The list of user item data.</returns> - List<UserItemData> GetAllUserData(long userId); - - /// <summary> - /// Save all user data associated with the given user. - /// </summary> - /// <param name="userId">The user id.</param> - /// <param name="userData">The user item data.</param> - /// <param name="cancellationToken">The cancellation token.</param> - void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken); - } -} diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 45aefacf6..bf6871a74 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -137,27 +137,27 @@ namespace MediaBrowser.Controller.Playlists return Task.CompletedTask; } - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) + public override IReadOnlyList<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { return GetPlayableItems(user, query); } - protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) + protected override IReadOnlyList<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) { return []; } - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) + public override IReadOnlyList<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) { return GetPlayableItems(user, query); } - public IEnumerable<Tuple<LinkedChild, BaseItem>> GetManageableItems() + public IReadOnlyList<Tuple<LinkedChild, BaseItem>> GetManageableItems() { return GetLinkedChildrenInfos(); } - private List<BaseItem> GetPlayableItems(User user, InternalItemsQuery query) + private IReadOnlyList<BaseItem> GetPlayableItems(User user, InternalItemsQuery query) { query ??= new InternalItemsQuery(user); diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index cfff3eb14..ef69885fc 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -3,6 +3,7 @@ #pragma warning disable CA1002, CA2227, CS1591 using System.Collections.Generic; +using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; @@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Providers // Images aren't always used so the allocation is a waste a lot of the time private List<LocalImageInfo> _images; private List<(string Url, ImageType Type)> _remoteImages; + private List<PersonInfo> _people; public MetadataResult() { @@ -21,17 +23,21 @@ namespace MediaBrowser.Controller.Providers public List<LocalImageInfo> Images { - get => _images ??= new List<LocalImageInfo>(); + get => _images ??= []; set => _images = value; } public List<(string Url, ImageType Type)> RemoteImages { - get => _remoteImages ??= new List<(string Url, ImageType Type)>(); + get => _remoteImages ??= []; set => _remoteImages = value; } - public List<PersonInfo> People { get; set; } + public IReadOnlyList<PersonInfo> People + { + get => _people; + set => _people = value?.ToList(); + } public bool HasMetadata { get; set; } @@ -47,7 +53,7 @@ namespace MediaBrowser.Controller.Providers { People ??= new List<PersonInfo>(); - PeopleHelper.AddPerson(People, p); + PeopleHelper.AddPerson(_people, p); } /// <summary> @@ -61,7 +67,7 @@ namespace MediaBrowser.Controller.Providers } else { - People.Clear(); + _people.Clear(); } } } |
