aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs2
-rw-r--r--MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs2
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs9
-rw-r--r--MediaBrowser.Controller/Chapters/IChapterManager.cs19
-rw-r--r--MediaBrowser.Controller/Chapters/IChapterRepository.cs49
-rw-r--r--MediaBrowser.Controller/Collections/ICollectionManager.cs2
-rw-r--r--MediaBrowser.Controller/Devices/IDeviceManager.cs8
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs27
-rw-r--r--MediaBrowser.Controller/Dto/IDtoService.cs2
-rw-r--r--MediaBrowser.Controller/Entities/AggregateFolder.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs5
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs19
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs3
-rw-r--r--MediaBrowser.Controller/Entities/AudioBook.cs1
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs77
-rw-r--r--MediaBrowser.Controller/Entities/Book.cs1
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs6
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs73
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs3
-rw-r--r--MediaBrowser.Controller/Entities/IHasMediaSources.cs4
-rw-r--r--MediaBrowser.Controller/Entities/IItemByName.cs2
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs9
-rw-r--r--MediaBrowser.Controller/Entities/InternalPeopleQuery.cs2
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs23
-rw-r--r--MediaBrowser.Controller/Entities/PeopleHelper.cs4
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs3
-rw-r--r--MediaBrowser.Controller/Entities/PersonInfo.cs6
-rw-r--r--MediaBrowser.Controller/Entities/PhotoAlbum.cs1
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs3
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs24
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs46
-rw-r--r--MediaBrowser.Controller/Entities/UserRootFolder.cs6
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs6
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs6
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs3
-rw-r--r--MediaBrowser.Controller/IDisplayPreferencesManager.cs2
-rw-r--r--MediaBrowser.Controller/IO/IPathManager.cs17
-rw-r--r--MediaBrowser.Controller/Library/IIntroProvider.cs3
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs42
-rw-r--r--MediaBrowser.Controller/Library/IMediaSourceManager.cs18
-rw-r--r--MediaBrowser.Controller/Library/IMusicManager.cs8
-rw-r--r--MediaBrowser.Controller/Library/IUserDataManager.cs8
-rw-r--r--MediaBrowser.Controller/Library/IUserManager.cs2
-rw-r--r--MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs2
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs2
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs16
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvProgram.cs1
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs101
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs2
-rw-r--r--MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs4
-rw-r--r--MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs (renamed from MediaBrowser.Controller/MediaSegements/IMediaSegmentManager.cs)16
-rw-r--r--MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs (renamed from MediaBrowser.Controller/MediaSegements/IMediaSegmentProvider.cs)0
-rw-r--r--MediaBrowser.Controller/Net/AuthorizationInfo.cs22
-rw-r--r--MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs2
-rw-r--r--MediaBrowser.Controller/Net/IWebSocketConnection.cs4
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs238
-rw-r--r--MediaBrowser.Controller/Persistence/IItemTypeLookup.cs22
-rw-r--r--MediaBrowser.Controller/Persistence/IMediaAttachmentRepository.cs28
-rw-r--r--MediaBrowser.Controller/Persistence/IMediaStreamRepository.cs31
-rw-r--r--MediaBrowser.Controller/Persistence/IPeopleRepository.cs33
-rw-r--r--MediaBrowser.Controller/Persistence/IUserDataRepository.cs55
-rw-r--r--MediaBrowser.Controller/Playlists/Playlist.cs18
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs5
-rw-r--r--MediaBrowser.Controller/Providers/IExternalId.cs6
-rw-r--r--MediaBrowser.Controller/Providers/MetadataResult.cs16
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs15
-rw-r--r--MediaBrowser.Controller/Session/SessionInfo.cs4
-rw-r--r--MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs5
-rw-r--r--MediaBrowser.Controller/Streaming/StreamState.cs2
-rw-r--r--MediaBrowser.Controller/Trickplay/ITrickplayManager.cs2
72 files changed, 709 insertions, 506 deletions
diff --git a/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs b/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs
index 81b532fda..976a667ac 100644
--- a/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs
+++ b/MediaBrowser.Controller/Authentication/IAuthenticationProvider.cs
@@ -1,7 +1,7 @@
#pragma warning disable CS1591
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Authentication
diff --git a/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs b/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs
index 8c9d1baf8..592ce9955 100644
--- a/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs
+++ b/MediaBrowser.Controller/Authentication/IPasswordResetProvider.cs
@@ -4,7 +4,7 @@
using System;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Authentication
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index f186523b9..199e22b3f 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -7,8 +7,9 @@ using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
-using Jellyfin.Data.Entities;
-using Jellyfin.Data.Enums;
+using Jellyfin.Data;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Querying;
@@ -22,7 +23,7 @@ namespace MediaBrowser.Controller.Channels
[JsonIgnore]
public override SourceType SourceType => SourceType.Channel;
- public override bool IsVisible(User user)
+ public override bool IsVisible(User user, bool skipAllowedTagsCheck = false)
{
var blockedChannelsPreference = user.GetPreferenceValues<Guid>(PreferenceKind.BlockedChannels);
if (blockedChannelsPreference.Length != 0)
@@ -41,7 +42,7 @@ namespace MediaBrowser.Controller.Channels
}
}
- return base.IsVisible(user);
+ return base.IsVisible(user, skipAllowedTagsCheck);
}
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
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/Collections/ICollectionManager.cs b/MediaBrowser.Controller/Collections/ICollectionManager.cs
index 38a78a67b..206b5ac42 100644
--- a/MediaBrowser.Controller/Collections/ICollectionManager.cs
+++ b/MediaBrowser.Controller/Collections/ICollectionManager.cs
@@ -3,7 +3,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
diff --git a/MediaBrowser.Controller/Devices/IDeviceManager.cs b/MediaBrowser.Controller/Devices/IDeviceManager.cs
index cade53d99..ea38950d3 100644
--- a/MediaBrowser.Controller/Devices/IDeviceManager.cs
+++ b/MediaBrowser.Controller/Devices/IDeviceManager.cs
@@ -1,10 +1,10 @@
using System;
using System.Threading.Tasks;
using Jellyfin.Data.Dtos;
-using Jellyfin.Data.Entities;
-using Jellyfin.Data.Entities.Security;
using Jellyfin.Data.Events;
using Jellyfin.Data.Queries;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Entities.Security;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -58,7 +58,7 @@ public interface IDeviceManager
QueryResult<Device> GetDevices(DeviceQuery query);
/// <summary>
- /// Gets device infromation based on the provided query.
+ /// Gets device information based on the provided query.
/// </summary>
/// <param name="query">The device query.</param>
/// <returns>A <see cref="Task{QueryResult}"/> representing the retrieval of the device information.</returns>
@@ -109,7 +109,7 @@ public interface IDeviceManager
DeviceOptionsDto? GetDeviceOptions(string deviceId);
/// <summary>
- /// Gets the dto for client capabilites.
+ /// Gets the dto for client capabilities.
/// </summary>
/// <param name="capabilities">The client capabilities.</param>
/// <returns><see cref="ClientCapabilitiesDto"/> of the device.</returns>
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index 0d1e2a5a0..4eeec99b0 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -3,9 +3,10 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.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/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index 22453f0f7..f1d507fcb 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -1,7 +1,7 @@
#pragma warning disable CA1002
using System.Collections.Generic;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index 40cdd6c91..a02802f41 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class AggregateFolder : Folder
{
- private readonly object _childIdsLock = new object();
+ private readonly Lock _childIdsLock = new();
/// <summary>
/// The _virtual children.
@@ -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/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
index 1625c748a..b085398c5 100644
--- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs
@@ -22,7 +22,7 @@ namespace MediaBrowser.Controller.Entities.Audio
IReadOnlyList<string> Artists { get; set; }
}
- public static class Extentions
+ public static class Extensions
{
public static IEnumerable<string> GetAllArtists<T>(this T item)
where T : IHasArtist, IHasAlbumArtist
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index a0aae8769..d016d8f62 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -8,8 +8,10 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
@@ -21,6 +23,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..58841e5b7 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -8,8 +8,10 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
@@ -21,6 +23,7 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// Class MusicArtist.
/// </summary>
+ [Common.RequiresSourceSerialisation]
public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo<ArtistInfo>
{
[JsonIgnore]
@@ -84,7 +87,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)
{
@@ -110,15 +113,15 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.IsSaveLocalMetadataEnabled();
}
- protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
+ protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, bool allowRemoveRoot, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
if (IsAccessedByName)
{
// Should never get in here anyway
- return Task.CompletedTask;
+ return;
}
- return base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, false, refreshOptions, directoryService, cancellationToken);
+ await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, false, refreshOptions, directoryService, cancellationToken).ConfigureAwait(false);
}
public override List<string> GetUserDataKeys()
@@ -137,11 +140,9 @@ namespace MediaBrowser.Controller.Entities.Audio
private static List<string> GetUserDataKeys(MusicArtist item)
{
var list = new List<string>();
- var id = item.GetProviderId(MetadataProvider.MusicBrainzArtist);
-
- if (!string.IsNullOrEmpty(id))
+ if (item.TryGetProviderId(MetadataProvider.MusicBrainzArtist, out var externalId))
{
- list.Add("Artist-Musicbrainz-" + id);
+ list.Add("Artist-Musicbrainz-" + externalId);
}
list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics());
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..53c832ff3 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;
@@ -11,14 +12,18 @@ using System.Text;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.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;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
@@ -479,6 +484,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; }
@@ -915,7 +922,7 @@ namespace MediaBrowser.Controller.Entities
// Remove from middle if surrounded by spaces
sortable = sortable.Replace(" " + search + " ", " ", StringComparison.Ordinal);
- // Remove from end if followed by a space
+ // Remove from end if preceeded by a space
if (sortable.EndsWith(" " + search, StringComparison.Ordinal))
{
sortable = sortable.Remove(sortable.Length - (search.Length + 1));
@@ -1041,7 +1048,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 +1061,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 +1095,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()
@@ -1299,7 +1306,7 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- if (GetParents().Any(i => !i.IsVisible(user)))
+ if (GetParents().Any(i => !i.IsVisible(user, true)))
{
return false;
}
@@ -1521,13 +1528,14 @@ namespace MediaBrowser.Controller.Entities
/// Determines if a given user has access to this item.
/// </summary>
/// <param name="user">The user.</param>
+ /// <param name="skipAllowedTagsCheck">Don't check for allowed tags.</param>
/// <returns><c>true</c> if [is parental allowed] [the specified user]; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentNullException">If user is null.</exception>
- public bool IsParentalAllowed(User user)
+ public bool IsParentalAllowed(User user, bool skipAllowedTagsCheck)
{
ArgumentNullException.ThrowIfNull(user);
- if (!IsVisibleViaTags(user))
+ if (!IsVisibleViaTags(user, skipAllowedTagsCheck))
{
return false;
}
@@ -1599,7 +1607,7 @@ namespace MediaBrowser.Controller.Entities
return list.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
}
- private bool IsVisibleViaTags(User user)
+ private bool IsVisibleViaTags(User user, bool skipAllowedTagsCheck)
{
var allTags = GetInheritedTags();
if (user.GetPreference(PreferenceKind.BlockedTags).Any(i => allTags.Contains(i, StringComparison.OrdinalIgnoreCase)))
@@ -1614,7 +1622,7 @@ namespace MediaBrowser.Controller.Entities
}
var allowedTagsPreference = user.GetPreference(PreferenceKind.AllowedTags);
- if (allowedTagsPreference.Length != 0 && !allowedTagsPreference.Any(i => allTags.Contains(i, StringComparison.OrdinalIgnoreCase)))
+ if (!skipAllowedTagsCheck && allowedTagsPreference.Length != 0 && !allowedTagsPreference.Any(i => allTags.Contains(i, StringComparison.OrdinalIgnoreCase)))
{
return false;
}
@@ -1654,13 +1662,14 @@ namespace MediaBrowser.Controller.Entities
/// Default is just parental allowed. Can be overridden for more functionality.
/// </summary>
/// <param name="user">The user.</param>
+ /// <param name="skipAllowedTagsCheck">Don't check for allowed tags.</param>
/// <returns><c>true</c> if the specified user is visible; otherwise, <c>false</c>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="user" /> is <c>null</c>.</exception>
- public virtual bool IsVisible(User user)
+ public virtual bool IsVisible(User user, bool skipAllowedTagsCheck = false)
{
ArgumentNullException.ThrowIfNull(user);
- return IsParentalAllowed(user);
+ return IsParentalAllowed(user, skipAllowedTagsCheck);
}
public virtual bool IsVisibleStandalone(User user)
@@ -1675,7 +1684,7 @@ namespace MediaBrowser.Controller.Entities
public virtual string GetClientTypeName()
{
- if (IsFolder && SourceType == SourceType.Channel && this is not Channel)
+ if (IsFolder && SourceType == SourceType.Channel && this is not Channel && this is not Season && this is not Series)
{
return "ChannelFolderItem";
}
@@ -1769,7 +1778,6 @@ namespace MediaBrowser.Controller.Entities
public void AddStudio(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
-
var current = Studios;
if (!current.Contains(name, StringComparison.OrdinalIgnoreCase))
@@ -1781,21 +1789,21 @@ namespace MediaBrowser.Controller.Entities
}
else
{
- Studios = [..current, name];
+ Studios = [.. current, name];
}
}
}
public void SetStudios(IEnumerable<string> names)
{
- Studios = names.Distinct().ToArray();
+ Studios = names.Trimmed().Distinct().ToArray();
}
/// <summary>
/// Adds a genre to the item.
/// </summary>
/// <param name="name">The name.</param>
- /// <exception cref="ArgumentNullException">Throwns if name is null.</exception>
+ /// <exception cref="ArgumentNullException">Throws if name is null.</exception>
public void AddGenre(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
@@ -1803,7 +1811,7 @@ namespace MediaBrowser.Controller.Entities
var genres = Genres;
if (!genres.Contains(name, StringComparison.OrdinalIgnoreCase))
{
- Genres = [..genres, name];
+ Genres = [.. genres, name];
}
}
@@ -1821,7 +1829,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,11 +1985,11 @@ namespace MediaBrowser.Controller.Entities
public void AddImage(ItemImageInfo image)
{
- ImageInfos = [..ImageInfos, image];
+ ImageInfos = [.. ImageInfos, image];
}
- public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken)
- => LibraryManager.UpdateItemAsync(this, GetParent(), updateReason, cancellationToken);
+ public virtual async Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken)
+ => await LibraryManager.UpdateItemAsync(this, GetParent(), updateReason, cancellationToken).ConfigureAwait(false);
/// <summary>
/// Validates that images within the item are still on the filesystem.
@@ -2031,7 +2042,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 +2092,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)
@@ -2367,7 +2378,7 @@ namespace MediaBrowser.Controller.Entities
}
}
- protected Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken)
+ protected async Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
var newOptions = new MetadataRefreshOptions(options)
{
@@ -2428,10 +2439,10 @@ namespace MediaBrowser.Controller.Entities
}
}
- return ownedItem.RefreshMetadata(newOptions, cancellationToken);
+ await ownedItem.RefreshMetadata(newOptions, cancellationToken).ConfigureAwait(false);
}
- protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken)
+ protected async Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken)
{
var newOptions = new MetadataRefreshOptions(options)
{
@@ -2441,9 +2452,7 @@ namespace MediaBrowser.Controller.Entities
var id = LibraryManager.GetNewItemId(path, typeof(Video));
// Try to retrieve it from the db. If we don't find it, use the resolved version
- var video = LibraryManager.GetItemById(id) as Video;
-
- if (video is null)
+ if (LibraryManager.GetItemById(id) is not Video video)
{
video = LibraryManager.ResolvePath(FileSystem.GetFileSystemInfo(path)) as Video;
@@ -2452,15 +2461,15 @@ namespace MediaBrowser.Controller.Entities
if (video is null)
{
- return Task.FromResult(true);
+ return;
}
if (video.OwnerId.IsEmpty())
{
- video.OwnerId = this.Id;
+ video.OwnerId = Id;
}
- return RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken);
+ await RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken).ConfigureAwait(false);
}
public string GetEtag(User user)
@@ -2524,7 +2533,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/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 4ead477f8..ca79e6245 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -11,8 +11,8 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
using Jellyfin.Extensions.Json;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
@@ -96,11 +96,11 @@ namespace MediaBrowser.Controller.Entities
return GetLibraryOptions(Path);
}
- public override bool IsVisible(User user)
+ public override bool IsVisible(User user, bool skipAllowedTagsCheck = false)
{
if (GetLibraryOptions().Enabled)
{
- return base.IsVisible(user);
+ return base.IsVisible(user, skipAllowedTagsCheck);
}
return false;
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index 83c19a54e..4da22854b 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,8 +12,11 @@ using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
-using Jellyfin.Data.Entities;
+using J2N.Collections.Generic.Extensions;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Collections;
@@ -217,7 +221,7 @@ namespace MediaBrowser.Controller.Entities
LibraryManager.CreateItem(item, this);
}
- public override bool IsVisible(User user)
+ public override bool IsVisible(User user, bool skipAllowedTagsCheck = false)
{
if (this is ICollectionFolder && this is not BasePluginFolder)
{
@@ -239,7 +243,7 @@ namespace MediaBrowser.Controller.Entities
}
}
- return base.IsVisible(user);
+ return base.IsVisible(user, skipAllowedTagsCheck);
}
/// <summary>
@@ -247,7 +251,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
@@ -528,13 +532,13 @@ namespace MediaBrowser.Controller.Entities
}
}
- private Task RefreshMetadataRecursive(IList<BaseItem> children, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
+ private async Task RefreshMetadataRecursive(IList<BaseItem> children, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken)
{
- return RunTasks(
+ await RunTasks(
(baseItem, innerProgress) => RefreshChildMetadata(baseItem, refreshOptions, recursive && baseItem.IsFolder, innerProgress, cancellationToken),
children,
progress,
- cancellationToken);
+ cancellationToken).ConfigureAwait(false);
}
private async Task RefreshAllMetadataForContainer(IMetadataContainer container, MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
@@ -575,13 +579,13 @@ namespace MediaBrowser.Controller.Entities
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- private Task ValidateSubFolders(IList<Folder> children, IDirectoryService directoryService, IProgress<double> progress, CancellationToken cancellationToken)
+ private async Task ValidateSubFolders(IList<Folder> children, IDirectoryService directoryService, IProgress<double> progress, CancellationToken cancellationToken)
{
- return RunTasks(
+ await RunTasks(
(folder, innerProgress) => folder.ValidateChildrenInternal(innerProgress, true, false, false, null, directoryService, cancellationToken),
children,
progress,
- cancellationToken);
+ cancellationToken).ConfigureAwait(false);
}
/// <summary>
@@ -659,7 +663,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
{
@@ -1060,11 +1064,6 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- if (queryParent is Series)
- {
- return false;
- }
-
if (queryParent is Season)
{
return false;
@@ -1084,12 +1083,15 @@ namespace MediaBrowser.Controller.Entities
if (!param.HasValue)
{
- if (user is not null && !configurationManager.Configuration.EnableGroupingIntoCollections)
+ if (user is not null && query.IncludeItemTypes.Any(type =>
+ (type == BaseItemKind.Movie && !configurationManager.Configuration.EnableGroupingMoviesIntoCollections) ||
+ (type == BaseItemKind.Series && !configurationManager.Configuration.EnableGroupingShowsIntoCollections)))
{
return false;
}
- if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains(BaseItemKind.Movie))
+ if (query.IncludeItemTypes.Length == 0
+ || query.IncludeItemTypes.Any(type => type == BaseItemKind.Movie || type == BaseItemKind.Series))
{
param = true;
}
@@ -1200,6 +1202,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
+ if (request.Is4K.HasValue)
+ {
+ return false;
+ }
+
if (request.IsHD.HasValue)
{
return false;
@@ -1240,11 +1247,6 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- if (request.GenreIds.Count > 0)
- {
- return false;
- }
-
if (request.VideoTypes.Length > 0)
{
return false;
@@ -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..5ce5fd4fa 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -3,8 +3,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Model.Entities;
@@ -37,7 +39,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 +72,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 +294,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/InternalPeopleQuery.cs b/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs
index 3e1d89274..203a16a66 100644
--- a/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs
@@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
namespace MediaBrowser.Controller.Entities
{
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index a07187d2f..d656fccb4 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -4,10 +4,13 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Linq;
using System.Text.Json.Serialization;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Querying;
@@ -91,7 +94,7 @@ namespace MediaBrowser.Controller.Entities.Movies
return Enumerable.Empty<BaseItem>();
}
- protected override List<BaseItem> LoadChildren()
+ protected override IReadOnlyList<BaseItem> LoadChildren()
{
if (IsLegacyBoxSet)
{
@@ -99,7 +102,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 +130,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()
@@ -144,14 +147,14 @@ namespace MediaBrowser.Controller.Entities.Movies
return GetItemLookupInfo<BoxSetInfo>();
}
- public override bool IsVisible(User user)
+ public override bool IsVisible(User user, bool skipAllowedTagsCheck = false)
{
if (IsLegacyBoxSet)
{
- return base.IsVisible(user);
+ return base.IsVisible(user, skipAllowedTagsCheck);
}
- if (base.IsVisible(user))
+ if (base.IsVisible(user, skipAllowedTagsCheck))
{
if (LinkedChildren.Length == 0)
{
diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs
index 5292bd772..24b1843ce 100644
--- a/MediaBrowser.Controller/Entities/PeopleHelper.cs
+++ b/MediaBrowser.Controller/Entities/PeopleHelper.cs
@@ -10,11 +10,13 @@ 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);
+ person.Name = person.Name.Trim();
+
// Normalize
if (string.Equals(person.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
{
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..408161b03 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -7,9 +7,11 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
-using Jellyfin.Data.Entities;
+using System.Threading;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
using Jellyfin.Extensions;
+using MediaBrowser.Common;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Querying;
@@ -19,6 +21,7 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Class Season.
/// </summary>
+ [RequiresSourceSerialisation]
public class Season : Folder, IHasSeries, IHasLookupInfo<SeasonInfo>
{
[JsonIgnore]
@@ -132,7 +135,7 @@ namespace MediaBrowser.Controller.Entities.TV
var series = Series;
if (series is not null)
{
- return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000", CultureInfo.InvariantCulture);
+ return series.PresentationUniqueKey + "-" + IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
}
}
@@ -150,6 +153,21 @@ namespace MediaBrowser.Controller.Entities.TV
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
{
+ if (SourceType == SourceType.Channel)
+ {
+ try
+ {
+ query.Parent = this;
+ query.ChannelIds = new[] { ChannelId };
+ return ChannelManager.GetChannelItemsInternal(query, new Progress<double>(), CancellationToken.None).GetAwaiter().GetResult();
+ }
+ catch
+ {
+ // Already logged at lower levels
+ return new QueryResult<BaseItem>();
+ }
+ }
+
if (query.User is null)
{
return base.GetItemsInternal(query);
@@ -255,7 +273,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{
- IndexNumber ??= LibraryManager.GetSeasonNumberFromPath(Path);
+ IndexNumber ??= LibraryManager.GetSeasonNumberFromPath(Path, ParentId);
// If a change was made record it
if (IndexNumber.HasValue)
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index a324f79ef..b4ad05921 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -9,12 +9,13 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Querying;
using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
@@ -23,7 +24,7 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Class Series.
/// </summary>
- public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IMetadataContainer
+ public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IMetadataContainer, ISupportsBoxSetGrouping
{
public Series()
{
@@ -189,12 +190,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)
{
@@ -225,6 +226,21 @@ namespace MediaBrowser.Controller.Entities.TV
{
var user = query.User;
+ if (SourceType == SourceType.Channel)
+ {
+ try
+ {
+ query.Parent = this;
+ query.ChannelIds = [ChannelId];
+ return ChannelManager.GetChannelItemsInternal(query, new Progress<double>(), CancellationToken.None).GetAwaiter().GetResult();
+ }
+ catch
+ {
+ // Already logged at lower levels
+ return new QueryResult<BaseItem>();
+ }
+ }
+
if (query.Recursive)
{
var seriesKey = GetUniqueSeriesKey(this);
@@ -371,7 +387,25 @@ namespace MediaBrowser.Controller.Entities.TV
query.IsMissing = false;
}
- var allItems = LibraryManager.GetItemList(query);
+ IReadOnlyList<BaseItem> allItems;
+ if (SourceType == SourceType.Channel)
+ {
+ try
+ {
+ query.Parent = parentSeason;
+ query.ChannelIds = [ChannelId];
+ allItems = [.. ChannelManager.GetChannelItemsInternal(query, new Progress<double>(), CancellationToken.None).GetAwaiter().GetResult().Items];
+ }
+ catch
+ {
+ // Already logged at lower levels
+ return [];
+ }
+ }
+ else
+ {
+ allItems = LibraryManager.GetItemList(query);
+ }
return GetSeasonEpisodes(parentSeason, user, allItems, options, shouldIncludeMissingEpisodes);
}
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index a687adedd..bc7e22d9a 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -8,7 +8,7 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
@@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class UserRootFolder : Folder
{
- private readonly object _childIdsLock = new object();
+ private readonly Lock _childIdsLock = new();
private List<Guid> _childrenIds = null;
/// <summary>
@@ -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..dfa31315c 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -8,8 +8,8 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.TV;
@@ -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..c2b4da32a 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -6,8 +6,10 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.TV;
@@ -236,7 +238,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/IDisplayPreferencesManager.cs b/MediaBrowser.Controller/IDisplayPreferencesManager.cs
index 10c0f56e0..a97096eae 100644
--- a/MediaBrowser.Controller/IDisplayPreferencesManager.cs
+++ b/MediaBrowser.Controller/IDisplayPreferencesManager.cs
@@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
namespace MediaBrowser.Controller
{
diff --git a/MediaBrowser.Controller/IO/IPathManager.cs b/MediaBrowser.Controller/IO/IPathManager.cs
new file mode 100644
index 000000000..036889810
--- /dev/null
+++ b/MediaBrowser.Controller/IO/IPathManager.cs
@@ -0,0 +1,17 @@
+using MediaBrowser.Controller.Entities;
+
+namespace MediaBrowser.Controller.IO;
+
+/// <summary>
+/// Interface ITrickplayManager.
+/// </summary>
+public interface IPathManager
+{
+ /// <summary>
+ /// Gets the path to the trickplay image base folder.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="saveWithMedia">Whether or not the tile should be saved next to the media file.</param>
+ /// <returns>The absolute path.</returns>
+ public string GetTrickplayDirectory(BaseItem item, bool saveWithMedia = false);
+}
diff --git a/MediaBrowser.Controller/Library/IIntroProvider.cs b/MediaBrowser.Controller/Library/IIntroProvider.cs
index 4a9721acb..860e948af 100644
--- a/MediaBrowser.Controller/Library/IIntroProvider.cs
+++ b/MediaBrowser.Controller/Library/IIntroProvider.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
@@ -23,6 +24,6 @@ namespace MediaBrowser.Controller.Library
/// <param name="item">The item.</param>
/// <param name="user">The user.</param>
/// <returns>IEnumerable{System.String}.</returns>
- Task<IEnumerable<IntroInfo>> GetIntros(BaseItem item, Jellyfin.Data.Entities.User user);
+ Task<IEnumerable<IntroInfo>> GetIntros(BaseItem item, User user);
}
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index b802b7e6e..df90f546c 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -4,8 +4,9 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -426,8 +427,9 @@ namespace MediaBrowser.Controller.Library
/// Gets the season number from path.
/// </summary>
/// <param name="path">The path.</param>
+ /// <param name="parentId">The parent id.</param>
/// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
- int? GetSeasonNumberFromPath(string path);
+ int? GetSeasonNumberFromPath(string path, Guid? parentId);
/// <summary>
/// Fills the missing episode numbers from path.
@@ -483,21 +485,21 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="item">The item.</param>
/// <returns>List&lt;PersonInfo&gt;.</returns>
- List<PersonInfo> GetPeople(BaseItem item);
+ IReadOnlyList<PersonInfo> GetPeople(BaseItem item);
/// <summary>
/// Gets the people.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;PersonInfo&gt;.</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&lt;Person&gt;.</returns>
- List<Person> GetPeopleItems(InternalPeopleQuery query);
+ IReadOnlyList<Person> GetPeopleItems(InternalPeopleQuery query);
/// <summary>
/// Updates the people.
@@ -513,21 +515,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&lt;Guid&gt;.</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&lt;System.String&gt;.</returns>
- List<string> GetPeopleNames(InternalPeopleQuery query);
+ IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery query);
/// <summary>
/// Queries the items.
@@ -553,9 +555,9 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</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 +565,25 @@ 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 TVShow/Album items for Latest api.
+ /// </summary>
+ /// <param name="query">The query to use.</param>
+ /// <param name="parents">Items to use for query.</param>
+ /// <param name="collectionType">Collection Type.</param>
+ /// <returns>List of items.</returns>
+ IReadOnlyList<BaseItem> GetLatestItemList(InternalItemsQuery query, IReadOnlyList<BaseItem> parents, CollectionType collectionType);
+
+ /// <summary>
+ /// Gets the list of series presentation keys for next up.
+ /// </summary>
+ /// <param name="query">The query to use.</param>
+ /// <param name="parents">Items to use for query.</param>
+ /// <param name="dateCutoff">The minimum date for a series to have been most recently watched.</param>
+ /// <returns>List of series presentation keys.</returns>
+ IReadOnlyList<string> GetNextUpSeriesKeys(InternalItemsQuery query, IReadOnlyCollection<BaseItem> parents, DateTime dateCutoff);
/// <summary>
/// Gets the items result.
diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
index 44a1a85e3..2b6781a19 100644
--- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs
+++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs
@@ -6,7 +6,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
@@ -29,31 +29,31 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <returns>IEnumerable&lt;MediaStream&gt;.</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&lt;MediaStream&gt;.</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&lt;MediaAttachment&gt;.</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&lt;MediaAttachment&gt;.</returns>
- List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query);
+ IReadOnlyList<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query);
/// <summary>
- /// Gets the playack media sources.
+ /// Gets the playback media sources.
/// </summary>
/// <param name="item">Item to use.</param>
/// <param name="user">User to use for operation.</param>
@@ -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..20764ec60 100644
--- a/MediaBrowser.Controller/Library/IMusicManager.cs
+++ b/MediaBrowser.Controller/Library/IMusicManager.cs
@@ -1,7 +1,7 @@
#pragma warning disable CA1002, CS1591
using System.Collections.Generic;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -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..eb46611dd 100644
--- a/MediaBrowser.Controller/Library/IUserDataManager.cs
+++ b/MediaBrowser.Controller/Library/IUserDataManager.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
@@ -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/Library/IUserManager.cs b/MediaBrowser.Controller/Library/IUserManager.cs
index 1c115be85..0109cf4b7 100644
--- a/MediaBrowser.Controller/Library/IUserManager.cs
+++ b/MediaBrowser.Controller/Library/IUserManager.cs
@@ -3,8 +3,8 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
using Jellyfin.Data.Events;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Users;
diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
index 76e9eb1f5..b0a6782c7 100644
--- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
+++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
@@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index c0e46ba24..8d59eef9f 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -6,8 +6,8 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
using Jellyfin.Data.Events;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
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/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index ba4a2a59c..d8aaf5ba0 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -18,6 +18,7 @@
</PropertyGroup>
<ItemGroup>
+ <PackageReference Include="BitFaster.Caching" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" />
<PackageReference Include="System.Threading.Tasks.Dataflow" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 7dea5f8eb..207bb40d9 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -13,7 +13,9 @@ using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Enums;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Extensions;
@@ -60,7 +62,7 @@ namespace MediaBrowser.Controller.MediaEncoding
private readonly Version _minFixedKernel60i915Hang = new Version(6, 0, 18);
private readonly Version _minKernelVersionAmdVkFmtModifier = new Version(5, 15);
- private readonly Version _minFFmpegImplictHwaccel = new Version(6, 0);
+ private readonly Version _minFFmpegImplicitHwaccel = new Version(6, 0);
private readonly Version _minFFmpegHwaUnsafeOutput = new Version(6, 0);
private readonly Version _minFFmpegOclCuTonemapMode = new Version(5, 1, 3);
private readonly Version _minFFmpegSvtAv1Params = new Version(5, 1);
@@ -309,7 +311,6 @@ namespace MediaBrowser.Controller.MediaEncoding
private bool IsSwTonemapAvailable(EncodingJobInfo state, EncodingOptions options)
{
if (state.VideoStream is null
- || !options.EnableTonemapping
|| GetVideoColorBitDepth(state) < 10
|| !_mediaEncoder.SupportsFilter("tonemapx"))
{
@@ -631,7 +632,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
if (string.IsNullOrWhiteSpace(container))
{
- // this may not work, but if the client is that broken we can not do anything better
+ // this may not work, but if the client is that broken we cannot do anything better
return "aac";
}
@@ -861,9 +862,9 @@ namespace MediaBrowser.Controller.MediaEncoding
&& _mediaEncoder.EncoderVersion >= _minFFmpegVaapiDeviceVendorId;
// Priority: 'renderNodePath' > 'vendorId' > 'kernelDriver'
- var driverOpts = string.IsNullOrEmpty(renderNodePath)
- ? (haveVendorId ? $",vendor_id={vendorId}" : (string.IsNullOrEmpty(kernelDriver) ? string.Empty : $",kernel_driver={kernelDriver}"))
- : renderNodePath;
+ var driverOpts = File.Exists(renderNodePath)
+ ? renderNodePath
+ : (haveVendorId ? $",vendor_id={vendorId}" : (string.IsNullOrEmpty(kernelDriver) ? string.Empty : $",kernel_driver={kernelDriver}"));
// 'driver' behaves similarly to env LIBVA_DRIVER_NAME
driverOpts += string.IsNullOrEmpty(driver) ? string.Empty : ",driver=" + driver;
@@ -2061,7 +2062,13 @@ namespace MediaBrowser.Controller.MediaEncoding
// libx265 only accept level option in -x265-params.
// level option may cause libx265 to fail.
// libx265 cannot adjust the given level, just throw an error.
- param += " -x265-params:0 subme=3:merange=25:rc-lookahead=10:me=star:ctu=32:max-tu-size=32:min-cu-size=16:rskip=2:rskip-edge-threshold=2:no-sao=1:no-strong-intra-smoothing=1:no-scenecut=1:no-open-gop=1:no-info=1";
+ param += " -x265-params:0 no-scenecut=1:no-open-gop=1:no-info=1";
+
+ if (encodingOptions.EncoderPreset < EncoderPreset.ultrafast)
+ {
+ // The following params are slower than the ultrafast preset, don't use when ultrafast is selected.
+ param += ":subme=3:merange=25:rc-lookahead=10:me=star:ctu=32:max-tu-size=32:min-cu-size=16:rskip=2:rskip-edge-threshold=2:no-sao=1:no-strong-intra-smoothing=1";
+ }
}
if (string.Equals(videoEncoder, "libsvtav1", StringComparison.OrdinalIgnoreCase)
@@ -2197,7 +2204,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var videoFrameRate = videoStream.ReferenceFrameRate;
// Add a little tolerance to the framerate check because some videos might record a framerate
- // that is slightly higher than the intended framerate, but the device can still play it correctly.
+ // that is slightly greater than the intended framerate, but the device can still play it correctly.
// 0.05 fps tolerance should be safe enough.
if (!videoFrameRate.HasValue || videoFrameRate.Value > requestedFramerate.Value + 0.05f)
{
@@ -3608,7 +3615,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return GetSwVidFilterChain(state, options, vidEncoder);
}
- // prefered nvdec/cuvid + cuda filters + nvenc pipeline
+ // preferred nvdec/cuvid + cuda filters + nvenc pipeline
return GetNvidiaVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
}
@@ -3649,8 +3656,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var subH = state.SubtitleStream?.Height;
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doCuTranspose = !string.IsNullOrEmpty(tranposeDir) && _mediaEncoder.SupportsFilter("transpose_cuda");
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doCuTranspose = !string.IsNullOrEmpty(transposeDir) && _mediaEncoder.SupportsFilter("transpose_cuda");
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isNvDecoder && doCuTranspose));
var swpInW = swapWAndH ? inH : inW;
var swpInH = swapWAndH ? inW : inH;
@@ -3696,7 +3703,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// hw transpose
if (doCuTranspose)
{
- mainFilters.Add($"transpose_cuda=dir={tranposeDir}");
+ mainFilters.Add($"transpose_cuda=dir={transposeDir}");
}
var isRext = IsVideoStreamHevcRext(state);
@@ -3816,7 +3823,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return GetSwVidFilterChain(state, options, vidEncoder);
}
- // prefered d3d11va + opencl filters + amf pipeline
+ // preferred d3d11va + opencl filters + amf pipeline
return GetAmdDx11VidFiltersPrefered(state, options, vidDecoder, vidEncoder);
}
@@ -3856,8 +3863,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var subH = state.SubtitleStream?.Height;
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doOclTranspose = !string.IsNullOrEmpty(tranposeDir)
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doOclTranspose = !string.IsNullOrEmpty(transposeDir)
&& _mediaEncoder.SupportsFilterWithOption(FilterOptionType.TransposeOpenclReversal);
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isD3d11vaDecoder && doOclTranspose));
var swpInW = swapWAndH ? inH : inW;
@@ -3901,12 +3908,12 @@ namespace MediaBrowser.Controller.MediaEncoding
// map from d3d11va to opencl via d3d11-opencl interop.
mainFilters.Add("hwmap=derive_device=opencl:mode=read");
- // hw deint <= TODO: finsh the 'yadif_opencl' filter
+ // hw deint <= TODO: finish the 'yadif_opencl' filter
// hw transpose
if (doOclTranspose)
{
- mainFilters.Add($"transpose_opencl=dir={tranposeDir}");
+ mainFilters.Add($"transpose_opencl=dir={transposeDir}");
}
var outFormat = doOclTonemap ? string.Empty : "nv12";
@@ -4042,13 +4049,13 @@ namespace MediaBrowser.Controller.MediaEncoding
return GetSwVidFilterChain(state, options, vidEncoder);
}
- // prefered qsv(vaapi) + opencl filters pipeline
+ // preferred qsv(vaapi) + opencl filters pipeline
if (isIntelVaapiOclSupported)
{
return GetIntelQsvVaapiVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
}
- // prefered qsv(d3d11) + opencl filters pipeline
+ // preferred qsv(d3d11) + opencl filters pipeline
if (isIntelDx11OclSupported)
{
return GetIntelQsvDx11VidFiltersPrefered(state, options, vidDecoder, vidEncoder);
@@ -4097,8 +4104,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var subH = state.SubtitleStream?.Height;
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doVppTranspose = !string.IsNullOrEmpty(tranposeDir);
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doVppTranspose = !string.IsNullOrEmpty(transposeDir);
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || ((isD3d11vaDecoder || isQsvDecoder) && doVppTranspose));
var swpInW = swapWAndH ? inH : inW;
var swpInH = swapWAndH ? inW : inH;
@@ -4191,7 +4198,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(hwScaleFilter) && doVppTranspose)
{
- hwScaleFilter += $":transpose={tranposeDir}";
+ hwScaleFilter += $":transpose={transposeDir}";
}
if (!string.IsNullOrEmpty(hwScaleFilter) && isMjpegEncoder)
@@ -4384,8 +4391,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var subH = state.SubtitleStream?.Height;
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doVppTranspose = !string.IsNullOrEmpty(tranposeDir);
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doVppTranspose = !string.IsNullOrEmpty(transposeDir);
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || ((isVaapiDecoder || isQsvDecoder) && doVppTranspose));
var swpInW = swapWAndH ? inH : inW;
var swpInH = swapWAndH ? inW : inH;
@@ -4445,7 +4452,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// hw transpose(vaapi vpp)
if (isVaapiDecoder && doVppTranspose)
{
- mainFilters.Add($"transpose_vaapi=dir={tranposeDir}");
+ mainFilters.Add($"transpose_vaapi=dir={transposeDir}");
}
var outFormat = doTonemap ? (((isQsvDecoder && doVppTranspose) || isRext) ? "p010" : string.Empty) : "nv12";
@@ -4455,7 +4462,7 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(hwScaleFilter) && isQsvDecoder && doVppTranspose)
{
- hwScaleFilter += $":transpose={tranposeDir}";
+ hwScaleFilter += $":transpose={transposeDir}";
}
if (!string.IsNullOrEmpty(hwScaleFilter) && isMjpegEncoder)
@@ -4656,14 +4663,14 @@ namespace MediaBrowser.Controller.MediaEncoding
return swFilterChain;
}
- // prefered vaapi + opencl filters pipeline
+ // preferred vaapi + opencl filters pipeline
if (_mediaEncoder.IsVaapiDeviceInteliHD)
{
// Intel iHD path, with extra vpp tonemap and overlay support.
return GetIntelVaapiFullVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
}
- // prefered vaapi + vulkan filters pipeline
+ // preferred vaapi + vulkan filters pipeline
if (_mediaEncoder.IsVaapiDeviceAmd
&& isVaapiVkSupported
&& _mediaEncoder.IsVaapiDeviceSupportVulkanDrmInterop
@@ -4715,8 +4722,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var subH = state.SubtitleStream?.Height;
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doVaVppTranspose = !string.IsNullOrEmpty(tranposeDir);
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doVaVppTranspose = !string.IsNullOrEmpty(transposeDir);
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isVaapiDecoder && doVaVppTranspose));
var swpInW = swapWAndH ? inH : inW;
var swpInH = swapWAndH ? inW : inH;
@@ -4771,7 +4778,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// hw transpose
if (doVaVppTranspose)
{
- mainFilters.Add($"transpose_vaapi=dir={tranposeDir}");
+ mainFilters.Add($"transpose_vaapi=dir={transposeDir}");
}
var outFormat = doTonemap ? (isRext ? "p010" : string.Empty) : "nv12";
@@ -4948,8 +4955,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|| string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase));
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doVkTranspose = isVaapiDecoder && !string.IsNullOrEmpty(tranposeDir);
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doVkTranspose = isVaapiDecoder && !string.IsNullOrEmpty(transposeDir);
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isVaapiDecoder && doVkTranspose));
var swpInW = swapWAndH ? inH : inW;
var swpInH = swapWAndH ? inW : inH;
@@ -5042,13 +5049,13 @@ namespace MediaBrowser.Controller.MediaEncoding
// vk transpose
if (doVkTranspose)
{
- if (string.Equals(tranposeDir, "reversal", StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(transposeDir, "reversal", StringComparison.OrdinalIgnoreCase))
{
mainFilters.Add("flip_vulkan");
}
else
{
- mainFilters.Add($"transpose_vulkan=dir={tranposeDir}");
+ mainFilters.Add($"transpose_vulkan=dir={transposeDir}");
}
}
@@ -5416,8 +5423,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var usingHwSurface = isVtDecoder && (_mediaEncoder.EncoderVersion >= _minFFmpegWorkingVtHwSurface);
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doVtTranspose = !string.IsNullOrEmpty(tranposeDir) && _mediaEncoder.SupportsFilter("transpose_vt");
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doVtTranspose = !string.IsNullOrEmpty(transposeDir) && _mediaEncoder.SupportsFilter("transpose_vt");
var swapWAndH = Math.Abs(rotation) == 90 && doVtTranspose;
var swpInW = swapWAndH ? inH : inW;
var swpInH = swapWAndH ? inW : inH;
@@ -5461,7 +5468,7 @@ namespace MediaBrowser.Controller.MediaEncoding
// hw transpose
if (doVtTranspose)
{
- mainFilters.Add($"transpose_vt=dir={tranposeDir}");
+ mainFilters.Add($"transpose_vt=dir={transposeDir}");
}
if (doVtTonemap)
@@ -5576,7 +5583,7 @@ namespace MediaBrowser.Controller.MediaEncoding
return GetSwVidFilterChain(state, options, vidEncoder);
}
- // prefered rkmpp + rkrga + opencl filters pipeline
+ // preferred rkmpp + rkrga + opencl filters pipeline
if (isRkmppOclSupported)
{
return GetRkmppVidFiltersPrefered(state, options, vidDecoder, vidEncoder);
@@ -5624,8 +5631,8 @@ namespace MediaBrowser.Controller.MediaEncoding
var subH = state.SubtitleStream?.Height;
var rotation = state.VideoStream?.Rotation ?? 0;
- var tranposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
- var doRkVppTranspose = !string.IsNullOrEmpty(tranposeDir);
+ var transposeDir = rotation == 0 ? string.Empty : GetVideoTransposeDirection(state);
+ var doRkVppTranspose = !string.IsNullOrEmpty(transposeDir);
var swapWAndH = Math.Abs(rotation) == 90 && (isSwDecoder || (isRkmppDecoder && doRkVppTranspose));
var swpInW = swapWAndH ? inH : inW;
var swpInH = swapWAndH ? inW : inH;
@@ -5690,13 +5697,17 @@ namespace MediaBrowser.Controller.MediaEncoding
if (!string.IsNullOrEmpty(doScaling)
&& !IsScaleRatioSupported(inW, inH, reqW, reqH, reqMaxW, reqMaxH, 8.0f))
{
- var hwScaleFilterFirstPass = $"scale_rkrga=w=iw/7.9:h=ih/7.9:format={outFormat}:afbc=1";
+ // Vendor provided BSP kernel has an RGA driver bug that causes the output to be corrupted for P010 format.
+ // Use NV15 instead of P010 to avoid the issue.
+ // SDR inputs are using BGRA formats already which is not affected.
+ var intermediateFormat = string.Equals(outFormat, "p010", StringComparison.OrdinalIgnoreCase) ? "nv15" : outFormat;
+ var hwScaleFilterFirstPass = $"scale_rkrga=w=iw/7.9:h=ih/7.9:format={intermediateFormat}:force_divisible_by=4:afbc=1";
mainFilters.Add(hwScaleFilterFirstPass);
}
if (!string.IsNullOrEmpty(hwScaleFilter) && doRkVppTranspose)
{
- hwScaleFilter += $":transpose={tranposeDir}";
+ hwScaleFilter += $":transpose={transposeDir}";
}
// try enabling AFBC to save DDR bandwidth
@@ -6170,7 +6181,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var ffmpegVersion = _mediaEncoder.EncoderVersion;
// Set the av1 codec explicitly to trigger hw accelerator, otherwise libdav1d will be used.
- var isAv1 = ffmpegVersion < _minFFmpegImplictHwaccel
+ var isAv1 = ffmpegVersion < _minFFmpegImplicitHwaccel
&& string.Equals(videoCodec, "av1", StringComparison.OrdinalIgnoreCase);
// Allow profile mismatch if decoding H.264 baseline with d3d11va and vaapi hwaccels.
@@ -7072,7 +7083,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
// DTS and TrueHD are not supported by HLS
// Keep them in the supported codecs list, but shift them to the end of the list so that if transcoding happens, another codec is used
- shiftAudioCodecs.Add("dca");
+ shiftAudioCodecs.Add("dts");
shiftAudioCodecs.Add("truehd");
}
else
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
index caa312987..7586ac902 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs
@@ -6,8 +6,8 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
-using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
diff --git a/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs b/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs
index fefa66cdb..56990d0b8 100644
--- a/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs
+++ b/MediaBrowser.Controller/MediaEncoding/TranscodingJob.cs
@@ -12,8 +12,8 @@ namespace MediaBrowser.Controller.MediaEncoding;
public sealed class TranscodingJob : IDisposable
{
private readonly ILogger<TranscodingJob> _logger;
- private readonly object _processLock = new();
- private readonly object _timerLock = new();
+ private readonly Lock _processLock = new();
+ private readonly Lock _timerLock = new();
private Timer? _killTimer;
diff --git a/MediaBrowser.Controller/MediaSegements/IMediaSegmentManager.cs b/MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs
index 672f27eca..456977b88 100644
--- a/MediaBrowser.Controller/MediaSegements/IMediaSegmentManager.cs
+++ b/MediaBrowser.Controller/MediaSegments/IMediaSegmentManager.cs
@@ -2,8 +2,8 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
-using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.MediaSegments;
@@ -46,20 +46,20 @@ public interface IMediaSegmentManager
Task DeleteSegmentAsync(Guid segmentId);
/// <summary>
- /// Obtains all segments accociated with the itemId.
+ /// Obtains all segments associated with the itemId.
/// </summary>
/// <param name="itemId">The id of the <see cref="BaseItem"/>.</param>
- /// <param name="typeFilter">filteres all media segments of the given type to be included. If null all types are included.</param>
- /// <param name="filterByProvider">When set filteres the segments to only return those that which providers are currently enabled on their library.</param>
+ /// <param name="typeFilter">filters all media segments of the given type to be included. If null all types are included.</param>
+ /// <param name="filterByProvider">When set filters the segments to only return those that which providers are currently enabled on their library.</param>
/// <returns>An enumerator of <see cref="MediaSegmentDto"/>'s.</returns>
Task<IEnumerable<MediaSegmentDto>> GetSegmentsAsync(Guid itemId, IEnumerable<MediaSegmentType>? typeFilter, bool filterByProvider = true);
/// <summary>
- /// Obtains all segments accociated with the itemId.
+ /// Obtains all segments associated with the itemId.
/// </summary>
/// <param name="item">The <see cref="BaseItem"/>.</param>
- /// <param name="typeFilter">filteres all media segments of the given type to be included. If null all types are included.</param>
- /// <param name="filterByProvider">When set filteres the segments to only return those that which providers are currently enabled on their library.</param>
+ /// <param name="typeFilter">filters all media segments of the given type to be included. If null all types are included.</param>
+ /// <param name="filterByProvider">When set filters the segments to only return those that which providers are currently enabled on their library.</param>
/// <returns>An enumerator of <see cref="MediaSegmentDto"/>'s.</returns>
Task<IEnumerable<MediaSegmentDto>> GetSegmentsAsync(BaseItem item, IEnumerable<MediaSegmentType>? typeFilter, bool filterByProvider = true);
diff --git a/MediaBrowser.Controller/MediaSegements/IMediaSegmentProvider.cs b/MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs
index 39bb58bef..39bb58bef 100644
--- a/MediaBrowser.Controller/MediaSegements/IMediaSegmentProvider.cs
+++ b/MediaBrowser.Controller/MediaSegments/IMediaSegmentProvider.cs
diff --git a/MediaBrowser.Controller/Net/AuthorizationInfo.cs b/MediaBrowser.Controller/Net/AuthorizationInfo.cs
index 2452b25ab..dd5eb9a01 100644
--- a/MediaBrowser.Controller/Net/AuthorizationInfo.cs
+++ b/MediaBrowser.Controller/Net/AuthorizationInfo.cs
@@ -1,7 +1,6 @@
-#nullable disable
-
using System;
-using Jellyfin.Data.Entities;
+using System.Diagnostics.CodeAnalysis;
+using Jellyfin.Database.Implementations.Entities;
namespace MediaBrowser.Controller.Net
{
@@ -20,31 +19,31 @@ namespace MediaBrowser.Controller.Net
/// Gets or sets the device identifier.
/// </summary>
/// <value>The device identifier.</value>
- public string DeviceId { get; set; }
+ public string? DeviceId { get; set; }
/// <summary>
/// Gets or sets the device.
/// </summary>
/// <value>The device.</value>
- public string Device { get; set; }
+ public string? Device { get; set; }
/// <summary>
/// Gets or sets the client.
/// </summary>
/// <value>The client.</value>
- public string Client { get; set; }
+ public string? Client { get; set; }
/// <summary>
/// Gets or sets the version.
/// </summary>
/// <value>The version.</value>
- public string Version { get; set; }
+ public string? Version { get; set; }
/// <summary>
/// Gets or sets the token.
/// </summary>
/// <value>The token.</value>
- public string Token { get; set; }
+ public string? Token { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the authorization is from an api key.
@@ -54,7 +53,7 @@ namespace MediaBrowser.Controller.Net
/// <summary>
/// Gets or sets the user making the request.
/// </summary>
- public User User { get; set; }
+ public User? User { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the token is authenticated.
@@ -62,8 +61,9 @@ namespace MediaBrowser.Controller.Net
public bool IsAuthenticated { get; set; }
/// <summary>
- /// Gets or sets a value indicating whether the request has a token.
+ /// Gets a value indicating whether the request has a token.
/// </summary>
- public bool HasToken { get; set; }
+ [MemberNotNullWhen(true, nameof(Token))]
+ public bool HasToken => !string.IsNullOrWhiteSpace(Token);
}
}
diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
index a47d2fa45..4757bfa30 100644
--- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
+++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
@@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Net
SingleWriter = false
});
- private readonly object _activeConnectionsLock = new();
+ private readonly Lock _activeConnectionsLock = new();
/// <summary>
/// The _active connections.
diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
index bba5a6b85..bdc0f9a10 100644
--- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
@@ -24,9 +24,9 @@ namespace MediaBrowser.Controller.Net
DateTime LastActivityDate { get; }
/// <summary>
- /// Gets or sets the date of last Keeplive received.
+ /// Gets or sets the date of last Keepalive received.
/// </summary>
- /// <value>The date of last Keeplive received.</value>
+ /// <value>The date of last Keepalive received.</value>
DateTime LastKeepAliveDate { get; set; }
/// <summary>
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 2c52b2b45..e185898bf 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -5,159 +5,101 @@
using System;
using System.Collections.Generic;
using System.Threading;
+using Jellyfin.Data.Enums;
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
{
/// <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&lt;BaseItem&gt;.</returns>
- QueryResult<BaseItem> GetItems(InternalItemsQuery query);
-
- /// <summary>
- /// Gets the item ids list.
- /// </summary>
- /// <param name="query">The query.</param>
- /// <returns>List&lt;Guid&gt;.</returns>
- List<Guid> GetItemIdsList(InternalItemsQuery query);
-
- /// <summary>
- /// Gets the people.
- /// </summary>
- /// <param name="query">The query.</param>
- /// <returns>List&lt;PersonInfo&gt;.</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&lt;System.String&gt;.</returns>
- List<string> GetPeopleNames(InternalPeopleQuery query);
-
- /// <summary>
- /// Gets the item list.
- /// </summary>
- /// <param name="query">The query.</param>
- /// <returns>List&lt;BaseItem&gt;.</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&lt;BaseItem&gt;.</returns>
+ QueryResult<BaseItem> GetItems(InternalItemsQuery filter);
+
+ /// <summary>
+ /// Gets the item ids list.
+ /// </summary>
+ /// <param name="filter">The query.</param>
+ /// <returns>List&lt;Guid&gt;.</returns>
+ IReadOnlyList<Guid> GetItemIdsList(InternalItemsQuery filter);
+
+ /// <summary>
+ /// Gets the item list.
+ /// </summary>
+ /// <param name="filter">The query.</param>
+ /// <returns>List&lt;BaseItem&gt;.</returns>
+ IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery filter);
+
+ /// <summary>
+ /// Gets the item list. Used mainly by the Latest api endpoint.
+ /// </summary>
+ /// <param name="filter">The query.</param>
+ /// <param name="collectionType">Collection Type.</param>
+ /// <returns>List&lt;BaseItem&gt;.</returns>
+ IReadOnlyList<BaseItem> GetLatestItemList(InternalItemsQuery filter, CollectionType collectionType);
+
+ /// <summary>
+ /// Gets the list of series presentation keys for next up.
+ /// </summary>
+ /// <param name="filter">The query.</param>
+ /// <param name="dateCutoff">The minimum date for a series to have been most recently watched.</param>
+ /// <returns>The list of keys.</returns>
+ IReadOnlyList<string> GetNextUpSeriesKeys(InternalItemsQuery filter, DateTime dateCutoff);
+
+ /// <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..1062399e3 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -9,8 +9,10 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Data;
using Jellyfin.Data.Enums;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@@ -137,27 +139,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);
@@ -227,11 +229,11 @@ namespace MediaBrowser.Controller.Playlists
return [item];
}
- public override bool IsVisible(User user)
+ public override bool IsVisible(User user, bool skipAllowedTagsCheck = false)
{
if (!IsSharedItem)
{
- return base.IsVisible(user);
+ return base.IsVisible(user, skipAllowedTagsCheck);
}
if (OpenAccess)
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index 474f09dc5..a1edfa3c9 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -10,14 +10,15 @@ namespace MediaBrowser.Controller.Providers
{
public class DirectoryService : IDirectoryService
{
- private readonly IFileSystem _fileSystem;
-
+ // TODO make static and switch to FastConcurrentLru.
private readonly ConcurrentDictionary<string, FileSystemMetadata[]> _cache = new(StringComparer.Ordinal);
private readonly ConcurrentDictionary<string, FileSystemMetadata> _fileCache = new(StringComparer.Ordinal);
private readonly ConcurrentDictionary<string, List<string>> _filePathCache = new(StringComparer.Ordinal);
+ private readonly IFileSystem _fileSystem;
+
public DirectoryService(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
diff --git a/MediaBrowser.Controller/Providers/IExternalId.cs b/MediaBrowser.Controller/Providers/IExternalId.cs
index f451eac6d..584c3297a 100644
--- a/MediaBrowser.Controller/Providers/IExternalId.cs
+++ b/MediaBrowser.Controller/Providers/IExternalId.cs
@@ -32,12 +32,6 @@ namespace MediaBrowser.Controller.Providers
ExternalIdMediaType? Type { get; }
/// <summary>
- /// Gets the URL format string for this id.
- /// </summary>
- [Obsolete("Obsolete in 10.10, to be removed in 10.11")]
- string? UrlFormatString { get; }
-
- /// <summary>
/// Determines whether this id supports a given item type.
/// </summary>
/// <param name="item">The item.</param>
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();
}
}
}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index 462a62455..47bcfdb6e 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -6,7 +6,8 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities.Security;
+using Jellyfin.Database.Implementations.Entities;
+using Jellyfin.Database.Implementations.Entities.Security;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
@@ -73,7 +74,7 @@ namespace MediaBrowser.Controller.Session
/// <param name="remoteEndPoint">The remote end point.</param>
/// <param name="user">The user.</param>
/// <returns>A task containing the session information.</returns>
- Task<SessionInfo> LogSessionActivity(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, Jellyfin.Data.Entities.User user);
+ Task<SessionInfo> LogSessionActivity(string appName, string appVersion, string deviceId, string deviceName, string remoteEndPoint, User user);
/// <summary>
/// Used to report that a session controller has connected.
@@ -324,7 +325,7 @@ namespace MediaBrowser.Controller.Session
Task<SessionInfo> GetSessionByAuthenticationToken(Device info, string deviceId, string remoteEndpoint, string appVersion);
/// <summary>
- /// Logouts the specified access token.
+ /// Logs out the specified access token.
/// </summary>
/// <param name="accessToken">The access token.</param>
/// <returns>A <see cref="Task"/> representing the log out process.</returns>
@@ -341,5 +342,13 @@ namespace MediaBrowser.Controller.Session
Task RevokeUserTokens(Guid userId, string currentAccessToken);
Task CloseIfNeededAsync(SessionInfo session);
+
+ /// <summary>
+ /// Used to close the livestream if needed.
+ /// </summary>
+ /// <param name="liveStreamId">The livestream id.</param>
+ /// <param name="sessionIdOrPlaySessionId">The session id or playsession id.</param>
+ /// <returns>Task.</returns>
+ Task CloseLiveStreamIfNeededAsync(string liveStreamId, string sessionIdOrPlaySessionId);
}
}
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index 3ba1bfce4..96783f607 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Session
private readonly ISessionManager _sessionManager;
private readonly ILogger _logger;
- private readonly object _progressLock = new();
+ private readonly Lock _progressLock = new();
private Timer _progressTimer;
private PlaybackProgressInfo _lastProgressInfo;
@@ -286,7 +286,7 @@ namespace MediaBrowser.Controller.Session
/// <summary>
/// Gets or sets the playlist item id.
/// </summary>
- /// <value>The splaylist item id.</value>
+ /// <value>The playlist item id.</value>
public string PlaylistItemId { get; set; }
/// <summary>
diff --git a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs
index bd47db39a..97f653edf 100644
--- a/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs
+++ b/MediaBrowser.Controller/Sorting/IUserBaseItemComparer.cs
@@ -1,11 +1,12 @@
#nullable disable
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Sorting
{
/// <summary>
- /// Represents a BaseItem comparer that requires a User to perform it's comparison.
+ /// Represents a BaseItem comparer that requires a User to perform its comparison.
/// </summary>
public interface IUserBaseItemComparer : IBaseItemComparer
{
@@ -13,7 +14,7 @@ namespace MediaBrowser.Controller.Sorting
/// Gets or sets the user.
/// </summary>
/// <value>The user.</value>
- Jellyfin.Data.Entities.User User { get; set; }
+ User User { get; set; }
/// <summary>
/// Gets or sets the user manager.
diff --git a/MediaBrowser.Controller/Streaming/StreamState.cs b/MediaBrowser.Controller/Streaming/StreamState.cs
index b5dbe29ec..195dda5fe 100644
--- a/MediaBrowser.Controller/Streaming/StreamState.cs
+++ b/MediaBrowser.Controller/Streaming/StreamState.cs
@@ -51,7 +51,7 @@ public class StreamState : EncodingJobInfo, IDisposable
public VideoRequestDto? VideoRequest => Request as VideoRequestDto;
/// <summary>
- /// Gets or sets the direct stream provicer.
+ /// Gets or sets the direct stream provider.
/// </summary>
/// <remarks>
/// Deprecated.
diff --git a/MediaBrowser.Controller/Trickplay/ITrickplayManager.cs b/MediaBrowser.Controller/Trickplay/ITrickplayManager.cs
index 800317800..9ac8ead11 100644
--- a/MediaBrowser.Controller/Trickplay/ITrickplayManager.cs
+++ b/MediaBrowser.Controller/Trickplay/ITrickplayManager.cs
@@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
+using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;