From 54b3debd2774caedf92a531a2461b42d7bb37af1 Mon Sep 17 00:00:00 2001 From: Joseph <1315585+joseph39@users.noreply.github.com> Date: Mon, 18 Jul 2022 23:30:27 -0700 Subject: Add referer parameter to ffmpeg As of https://trac.ffmpeg.org/ticket/2179, ffmpeg supports referer parameter which injects Referer header to the HTTP request for remote content. Have EncodingHelper pass this in if it's included in RemoteHttpHeaders. --- .../MediaEncoding/EncodingHelper.cs | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 6fb5c88740..ab2daf7a50 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -255,6 +255,21 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Empty; } + /// + /// Gets the referer param. + /// + /// The state. + /// System.String. + public string GetRefererParam(EncodingJobInfo state) + { + if (state.RemoteHttpHeaders.TryGetValue("Referer", out string referer)) + { + return "-referer \"" + referer + "\""; + } + + return string.Empty; + } + public static string GetInputFormat(string container) { if (string.IsNullOrEmpty(container)) @@ -4962,6 +4977,15 @@ namespace MediaBrowser.Controller.MediaEncoding inputModifier = inputModifier.Trim(); + var refererParam = GetRefererParam(state); + + if (!string.IsNullOrEmpty(refererParam)) + { + inputModifier += " " + refererParam; + } + + inputModifier = inputModifier.Trim(); + inputModifier += " " + GetFastSeekCommandLineParameter(state, encodingOptions, segmentContainer); inputModifier = inputModifier.Trim(); -- cgit v1.2.3 From 9ec2870b1034e0b64ebde3e29a3779c7f6bb2ac4 Mon Sep 17 00:00:00 2001 From: luz paz Date: Mon, 15 Aug 2022 06:48:34 -0400 Subject: Fix various typos Found via `codespell -q 3 -S ./Emby.Server.Implementations/Localization -L allready,doesnt,inh,receivedfrom,whoknows` --- Emby.Dlna/Didl/DidlBuilder.cs | 2 +- Emby.Dlna/DlnaManager.cs | 2 +- Emby.Dlna/IDlnaEventManager.cs | 4 ++-- Emby.Server.Implementations/Library/LibraryManager.cs | 2 +- .../Library/Resolvers/Movies/MovieResolver.cs | 2 +- Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs | 2 +- Emby.Server.Implementations/Session/SessionManager.cs | 2 +- .../Session/SessionWebSocketListener.cs | 2 +- Jellyfin.Api/Controllers/AudioController.cs | 2 +- Jellyfin.Api/Controllers/DynamicHlsController.cs | 4 ++-- Jellyfin.Api/Controllers/SearchController.cs | 6 +++--- Jellyfin.Api/Controllers/UserController.cs | 2 +- Jellyfin.Api/Models/StreamingDtos/StreamState.cs | 2 +- .../Models/SyncPlayDtos/RemoveFromPlaylistRequestDto.cs | 4 ++-- Jellyfin.Drawing.Skia/SkiaHelper.cs | 2 +- Jellyfin.Networking/Configuration/NetworkConfiguration.cs | 2 +- Jellyfin.Networking/Manager/NetworkManager.cs | 2 +- MediaBrowser.Controller/Entities/TV/Season.cs | 2 +- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 4 ++-- .../SyncPlay/GroupStates/WaitingGroupState.cs | 2 +- .../PlaybackRequests/RemoveFromPlaylistGroupRequest.cs | 4 ++-- MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs | 4 ++-- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 ++-- MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs | 2 +- MediaBrowser.Model/Dto/BaseItemDto.cs | 6 +++--- MediaBrowser.Model/Entities/MediaStream.cs | 2 +- MediaBrowser.Model/SyncPlay/GroupStateType.cs | 2 +- MediaBrowser.Model/Tasks/ITaskManager.cs | 10 +++++----- MediaBrowser.Model/Tasks/ITaskTrigger.cs | 4 ++-- MediaBrowser.Providers/Manager/ProviderManager.cs | 2 +- .../Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 2 +- src/Jellyfin.Extensions/SplitStringExtensions.cs | 2 +- src/Jellyfin.Extensions/StringExtensions.cs | 2 +- tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs | 6 +++--- tests/Jellyfin.Networking.Tests/NetworkParseTests.cs | 2 +- .../LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs | 2 +- .../Test Data/Updates/manifest-stable.json | 2 +- 38 files changed, 56 insertions(+), 56 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs index df6539a5a6..8e3a335c66 100644 --- a/Emby.Dlna/Didl/DidlBuilder.cs +++ b/Emby.Dlna/Didl/DidlBuilder.cs @@ -446,7 +446,7 @@ namespace Emby.Dlna.Didl /// /// /// If context is a season, this will return a string containing just episode number and name. - /// Otherwise the result will include series nams and season number. + /// Otherwise the result will include series names and season number. /// /// The episode. /// Current context. diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index fe78d74ee7..74624334bb 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -123,7 +123,7 @@ namespace Emby.Dlna /// /// Attempts to match a device with a profile. /// Rules: - /// - If the profile field has no value, the field matches irregardless of its contents. + /// - If the profile field has no value, the field matches regardless of its contents. /// - the profile field can be an exact match, or a reg exp. /// /// The of the device. diff --git a/Emby.Dlna/IDlnaEventManager.cs b/Emby.Dlna/IDlnaEventManager.cs index 33cf0896ba..eea030d6d1 100644 --- a/Emby.Dlna/IDlnaEventManager.cs +++ b/Emby.Dlna/IDlnaEventManager.cs @@ -16,7 +16,7 @@ namespace Emby.Dlna /// /// The subscription identifier. /// The notification type. - /// The requested timeout as a sting. + /// The requested timeout as a string. /// The callback url. /// The response. EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl); @@ -25,7 +25,7 @@ namespace Emby.Dlna /// Creates the event subscription. /// /// The notification type. - /// The requested timeout as a sting. + /// The requested timeout as a string. /// The callback url. /// The response. EventSubscriptionResponse CreateEventSubscription(string notificationType, string requestedTimeoutString, string callbackUrl); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 2843fb8f83..6796845525 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -2529,7 +2529,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error reading the episode informations with ffprobe. Episode: {EpisodeInfo}", episodeInfo.Path); + _logger.LogError(ex, "Error reading the episode information with ffprobe. Episode: {EpisodeInfo}", episodeInfo.Path); } var changed = false; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index a60251dacd..b2f388a667 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -387,7 +387,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (!string.IsNullOrEmpty(item.Path)) { - // check for imdb id - we use full media path, as we can assume, that this will match in any use case (wither id in parent dir or in file name) + // check for imdb id - we use full media path, as we can assume, that this will match in any use case (either id in parent dir or in file name) var imdbid = item.Path.AsSpan().GetAttributeValue("imdbid"); if (!string.IsNullOrWhiteSpace(imdbid)) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 708ff52d79..be06356a4f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -199,7 +199,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts if (string.IsNullOrWhiteSpace(numberString)) { // Using this as a fallback now as this leads to Problems with channels like "5 USA" - // where 5 isn't ment to be the channel number + // where 5 isn't meant to be the channel number // Check for channel number with the format from SatIp // #EXTINF:0,84. VOX Schweiz // #EXTINF:0,84.0 - VOX Schweiz diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index d25376297f..7f927e2709 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -1242,7 +1242,7 @@ namespace Emby.Server.Implementations.Session if (item == null) { - _logger.LogError("A non-existant item Id {0} was passed into TranslateItemForPlayback", id); + _logger.LogError("A non-existent item Id {0} was passed into TranslateItemForPlayback", id); return Array.Empty(); } diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index a085ee546d..fccf50f60f 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.Session private const float ForceKeepAliveFactor = 0.75f; /// - /// Lock used for accesing the KeepAlive cancellation token. + /// Lock used for accessing the KeepAlive cancellation token. /// private readonly object _keepAliveLock = new object(); diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index 54ac06276e..94f7a7b827 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -207,7 +207,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The dlna device profile id to utilize. /// The play session id. /// The segment container. - /// The segment lenght. + /// The segment length. /// The minimum number of segments. /// The media version id, if playing an alternate version. /// The device id of the client requesting. Used to stop encoding processes when needed. diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 1e8d038751..3ed80f6621 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -121,7 +121,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The dlna device profile id to utilize. /// The play session id. /// The segment container. - /// The segment lenght. + /// The segment length. /// The minimum number of segments. /// The media version id, if playing an alternate version. /// The device id of the client requesting. Used to stop encoding processes when needed. @@ -1832,7 +1832,7 @@ namespace Jellyfin.Api.Controllers // Set the key frame params for video encoding to match the hls segment time. args += _encodingHelper.GetHlsVideoKeyFrameArguments(state, codec, state.SegmentLength, isEventPlaylist, startNumber); - // Currenly b-frames in libx265 breaks the FMP4-HLS playback on iOS, disable it for now. + // Currently b-frames in libx265 breaks the FMP4-HLS playback on iOS, disable it for now. if (string.Equals(codec, "libx265", StringComparison.OrdinalIgnoreCase)) { args += " -bf 0"; diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 07e113ad3e..3b1f7a52ab 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -60,9 +60,9 @@ namespace Jellyfin.Api.Controllers /// Optional. The maximum number of records to return. /// Optional. Supply a user id to search within a user's library or omit to search all. /// The search term to filter on. - /// If specified, only results with the specified item types are returned. This allows multiple, comma delimeted. - /// If specified, results with these item types are filtered out. This allows multiple, comma delimeted. - /// If specified, only results with the specified media types are returned. This allows multiple, comma delimeted. + /// If specified, only results with the specified item types are returned. This allows multiple, comma delimited. + /// If specified, results with these item types are filtered out. This allows multiple, comma delimited. + /// If specified, only results with the specified media types are returned. This allows multiple, comma delimited. /// If specified, only children of the parent are returned. /// Optional filter for movies. /// Optional filter for series. diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 82c8563a80..d1109bebc8 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -502,7 +502,7 @@ namespace Jellyfin.Api.Controllers if (isLocal) { - _logger.LogWarning("Password reset proccess initiated from outside the local network with IP: {IP}", ip); + _logger.LogWarning("Password reset process initiated from outside the local network with IP: {IP}", ip); } var result = await _userManager.StartForgotPasswordProcess(forgotPasswordRequest.EnteredUsername, isLocal).ConfigureAwait(false); diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs index 192f33ebd1..8182e3c9e8 100644 --- a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs +++ b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs @@ -169,7 +169,7 @@ namespace Jellyfin.Api.Models.StreamingDtos /// /// Disposes the stream state. /// - /// Whether the object is currently beeing disposed. + /// Whether the object is currently being disposed. protected virtual void Dispose(bool disposing) { if (_disposed) diff --git a/Jellyfin.Api/Models/SyncPlayDtos/RemoveFromPlaylistRequestDto.cs b/Jellyfin.Api/Models/SyncPlayDtos/RemoveFromPlaylistRequestDto.cs index 02ce5a0488..226a584e1d 100644 --- a/Jellyfin.Api/Models/SyncPlayDtos/RemoveFromPlaylistRequestDto.cs +++ b/Jellyfin.Api/Models/SyncPlayDtos/RemoveFromPlaylistRequestDto.cs @@ -17,9 +17,9 @@ namespace Jellyfin.Api.Models.SyncPlayDtos } /// - /// Gets or sets the playlist identifiers ot the items. Ignored when clearing the playlist. + /// Gets or sets the playlist identifiers of the items. Ignored when clearing the playlist. /// - /// The playlist identifiers ot the items. + /// The playlist identifiers of the items. public IReadOnlyList PlaylistItemIds { get; set; } /// diff --git a/Jellyfin.Drawing.Skia/SkiaHelper.cs b/Jellyfin.Drawing.Skia/SkiaHelper.cs index c001c32b8c..0478fc7c31 100644 --- a/Jellyfin.Drawing.Skia/SkiaHelper.cs +++ b/Jellyfin.Drawing.Skia/SkiaHelper.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Drawing.Skia /// /// The current skia encoder. /// The list of image paths. - /// The current checked indes. + /// The current checked index. /// The new index. /// A valid bitmap, or null if no bitmap exists after currentIndex. public static SKBitmap? GetNextValidImage(SkiaEncoder skiaEncoder, IReadOnlyList paths, int currentIndex, out int newIndex) diff --git a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs index 61db223d92..361dbc8142 100644 --- a/Jellyfin.Networking/Configuration/NetworkConfiguration.cs +++ b/Jellyfin.Networking/Configuration/NetworkConfiguration.cs @@ -193,7 +193,7 @@ namespace Jellyfin.Networking.Configuration public bool AutoDiscovery { get; set; } = true; /// - /// Gets or sets the filter for remote IP connectivity. Used in conjuntion with . + /// Gets or sets the filter for remote IP connectivity. Used in conjunction with . /// public string[] RemoteIPFilter { get; set; } = Array.Empty(); diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index 4b7b87814c..fd0665dbdd 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -944,7 +944,7 @@ namespace Jellyfin.Networking.Manager // Add virtual machine interface names to the list of bind exclusions, so that they are auto-excluded. if (config.IgnoreVirtualInterfaces) { - // each virtual interface name must be pre-pended with the exclusion symbol ! + // each virtual interface name must be prepended with the exclusion symbol ! var virtualInterfaceNames = config.VirtualInterfaceNames.Split(',').Select(p => "!" + p).ToArray(); if (lanAddresses.Length > 0) { diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index bd8df2facb..599d35da64 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -244,7 +244,7 @@ namespace MediaBrowser.Controller.Entities.TV /// /// This is called before any metadata refresh and returns true or false indicating if changes were made. /// - /// true to replace metdata, false to not. + /// true to replace metadata, false to not. /// true if XXXX, false otherwise. public override bool BeforeMetadataRefresh(bool replaceAllMetadata) { diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index e5aae620ac..17e410fe13 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -194,7 +194,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// Gets the name of the output video codec. /// - /// Encording state. + /// Encoding state. /// Encoding options. /// Encoder string. public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions) @@ -1980,7 +1980,7 @@ namespace MediaBrowser.Controller.MediaEncoding } } - // Cap the max target bitrate to intMax/2 to satisify the bufsize=bitrate*2. + // Cap the max target bitrate to intMax/2 to satisfy the bufsize=bitrate*2. return Math.Min(bitrate ?? 0, int.MaxValue / 2); } diff --git a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs index a0c38b3097..2164945560 100644 --- a/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs +++ b/MediaBrowser.Controller/SyncPlay/GroupStates/WaitingGroupState.cs @@ -549,7 +549,7 @@ namespace MediaBrowser.Controller.SyncPlay.GroupStates if (InitialState.Equals(GroupStateType.Playing)) { - // Group went from playing to waiting state and a pause request occured while waiting. + // Group went from playing to waiting state and a pause request occurred while waiting. var pauseRequest = new PauseGroupRequest(); pausedState.HandleRequest(pauseRequest, context, Type, session, cancellationToken); } diff --git a/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs b/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs index 2f38d6adc3..619294e957 100644 --- a/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs +++ b/MediaBrowser.Controller/SyncPlay/PlaybackRequests/RemoveFromPlaylistGroupRequest.cs @@ -27,9 +27,9 @@ namespace MediaBrowser.Controller.SyncPlay.PlaybackRequests } /// - /// Gets the playlist identifiers ot the items. + /// Gets the playlist identifiers of the items. /// - /// The playlist identifiers ot the items. + /// The playlist identifiers of the items. public IReadOnlyList PlaylistItemIds { get; } /// diff --git a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs index f49876cca4..3a7685f347 100644 --- a/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs +++ b/MediaBrowser.Controller/SyncPlay/Queue/PlayQueueManager.cs @@ -102,7 +102,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue } /// - /// Appends new items to the playlist. The specified order is mantained. + /// Appends new items to the playlist. The specified order is maintained. /// /// The items to add to the playlist. public void Queue(IReadOnlyList items) @@ -197,7 +197,7 @@ namespace MediaBrowser.Controller.SyncPlay.Queue } /// - /// Adds new items to the playlist right after the playing item. The specified order is mantained. + /// Adds new items to the playlist right after the playing item. The specified order is maintained. /// /// The items to add to the playlist. public void QueueNext(IReadOnlyList items) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 77b97c9b48..7f301a9d8b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -619,9 +619,9 @@ namespace MediaBrowser.MediaEncoding.Encoder Video3DFormat.HalfSideBySide => "crop=iw/2:ih:0:0,scale=(iw*2):ih,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", // fsbs crop width in half,set the display aspect,crop out any black bars we may have made Video3DFormat.FullSideBySide => "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", - // htab crop heigh in half,scale to correct size, set the display aspect,crop out any black bars we may have made + // htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made Video3DFormat.HalfTopAndBottom => "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", - // ftab crop heigt in half, set the display aspect,crop out any black bars we may have made + // ftab crop height in half, set the display aspect,crop out any black bars we may have made Video3DFormat.FullTopAndBottom => "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1", _ => "scale=trunc(iw*sar):ih" }; diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 47c36494bd..c32c1c108c 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Model.Dlna flagValue |= DlnaFlags.ByteBasedSeek; } - // Time based seek is curently disabled when streaming. On LG CX3 adding DlnaFlags.TimeBasedSeek and orgPn causes the DLNA playback to fail (format not supported). Further investigations are needed before enabling the remaining code paths. + // Time based seek is currently disabled when streaming. On LG CX3 adding DlnaFlags.TimeBasedSeek and orgPn causes the DLNA playback to fail (format not supported). Further investigations are needed before enabling the remaining code paths. // else if (runtimeTicks.HasValue) // { // flagValue = flagValue | DlnaFlags.TimeBasedSeek; diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 094dc73b27..fdb84fa320 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -294,13 +294,13 @@ namespace MediaBrowser.Model.Dto public NameGuidPair[] GenreItems { get; set; } /// - /// Gets or sets wether the item has a logo, this will hold the Id of the Parent that has one. + /// Gets or sets whether the item has a logo, this will hold the Id of the Parent that has one. /// /// The parent logo item id. public Guid? ParentLogoItemId { get; set; } /// - /// Gets or sets wether the item has any backdrops, this will hold the Id of the Parent that has one. + /// Gets or sets whether the item has any backdrops, this will hold the Id of the Parent that has one. /// /// The parent backdrop item id. public Guid? ParentBackdropItemId { get; set; } @@ -506,7 +506,7 @@ namespace MediaBrowser.Model.Dto public string ParentLogoImageTag { get; set; } /// - /// Gets or sets wether the item has fan art, this will hold the Id of the Parent that has one. + /// Gets or sets whether the item has fan art, this will hold the Id of the Parent that has one. /// /// The parent art item id. public Guid? ParentArtItemId { get; set; } diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index ae8f3b0edf..90a60cf470 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -606,7 +606,7 @@ namespace MediaBrowser.Model.Entities <= 1024 when Height <= 576 => IsInterlaced ? "576i" : "576p", // 1280x720 <= 1280 when Height <= 962 => IsInterlaced ? "720i" : "720p", - // 2560x1080 (FHD ultra wide 21:9) using 1440px width to accomodate WQHD + // 2560x1080 (FHD ultra wide 21:9) using 1440px width to accommodate WQHD <= 2560 when Height <= 1440 => IsInterlaced ? "1080i" : "1080p", // 4K <= 4096 when Height <= 3072 => "4K", diff --git a/MediaBrowser.Model/SyncPlay/GroupStateType.cs b/MediaBrowser.Model/SyncPlay/GroupStateType.cs index 7aa454f928..96364cacc7 100644 --- a/MediaBrowser.Model/SyncPlay/GroupStateType.cs +++ b/MediaBrowser.Model/SyncPlay/GroupStateType.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Model.SyncPlay Idle = 0, /// - /// The group is in wating state. Playback is paused. Will start playing when users are ready. + /// The group is in waiting state. Playback is paused. Will start playing when users are ready. /// Waiting = 1, diff --git a/MediaBrowser.Model/Tasks/ITaskManager.cs b/MediaBrowser.Model/Tasks/ITaskManager.cs index a86bf2a1c8..13bebc479e 100644 --- a/MediaBrowser.Model/Tasks/ITaskManager.cs +++ b/MediaBrowser.Model/Tasks/ITaskManager.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Model.Tasks /// /// Cancels if running and queue. /// - /// An implementatin of . + /// An implementation of . /// Task options. void CancelIfRunningAndQueue(TaskOptions options) where T : IScheduledTask; @@ -30,21 +30,21 @@ namespace MediaBrowser.Model.Tasks /// /// Cancels if running and queue. /// - /// An implementatin of . + /// An implementation of . void CancelIfRunningAndQueue() where T : IScheduledTask; /// /// Cancels if running. /// - /// An implementatin of . + /// An implementation of . void CancelIfRunning() where T : IScheduledTask; /// /// Queues the scheduled task. /// - /// An implementatin of . + /// An implementation of . /// Task options. void QueueScheduledTask(TaskOptions options) where T : IScheduledTask; @@ -52,7 +52,7 @@ namespace MediaBrowser.Model.Tasks /// /// Queues the scheduled task. /// - /// An implementatin of . + /// An implementation of . void QueueScheduledTask() where T : IScheduledTask; diff --git a/MediaBrowser.Model/Tasks/ITaskTrigger.cs b/MediaBrowser.Model/Tasks/ITaskTrigger.cs index 8c3ec6626c..0536f4ef77 100644 --- a/MediaBrowser.Model/Tasks/ITaskTrigger.cs +++ b/MediaBrowser.Model/Tasks/ITaskTrigger.cs @@ -21,10 +21,10 @@ namespace MediaBrowser.Model.Tasks /// /// Stars waiting for the trigger action. /// - /// Result of the last run triggerd task. + /// Result of the last run triggered task. /// The . /// The name of the task. - /// Wheter or not this is is fired during startup. + /// Whether or not this is is fired during startup. void Start(TaskResult? lastResult, ILogger logger, string taskName, bool isApplicationStartup); /// diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 01ff473f0c..bbb33ddf0e 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -926,7 +926,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - _logger.LogError(ex, "Error in {0}.Suports", i.GetType().Name); + _logger.LogError(ex, "Error in {0}.Supports", i.GetType().Name); return false; } }); diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs index 4bf66c0988..915fb97fd2 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Music /// /// The Jellyfin user-agent is unrestricted but source IP must not exceed /// one request per second, therefore we rate limit to avoid throttling. - /// Be prudent, use a value slightly above the minimun required. + /// Be prudent, use a value slightly above the minimum required. /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting. /// private readonly long _musicBrainzQueryIntervalMs; diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 09ff84044d..da348239a1 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -1330,7 +1330,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers }; /// - /// Used to split names of comma or pipe delimeted genres and people. + /// Used to split names of comma or pipe delimited genres and people. /// /// The value. /// IEnumerable{System.String}. diff --git a/src/Jellyfin.Extensions/SplitStringExtensions.cs b/src/Jellyfin.Extensions/SplitStringExtensions.cs index 1d1c377f56..a4dc9fc6b1 100644 --- a/src/Jellyfin.Extensions/SplitStringExtensions.cs +++ b/src/Jellyfin.Extensions/SplitStringExtensions.cs @@ -55,7 +55,7 @@ namespace Jellyfin.Extensions public static Enumerator Split(this ReadOnlySpan str, char separator) => new(str, separator); /// - /// Provides an enumerator for the substrings seperated by the separator. + /// Provides an enumerator for the substrings separated by the separator. /// [StructLayout(LayoutKind.Auto)] public ref struct Enumerator diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs index dadc9f1d5c..59fb038a75 100644 --- a/src/Jellyfin.Extensions/StringExtensions.cs +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Extensions } /// - /// Checks wether or not the specified string has diacritics in it. + /// Checks whether or not the specified string has diacritics in it. /// /// The string to check. /// True if the string has diacritics, false otherwise. diff --git a/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs b/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs index 6948280a3d..162f53e567 100644 --- a/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs +++ b/tests/Jellyfin.Model.Tests/Cryptography/PasswordHashTests.cs @@ -152,9 +152,9 @@ namespace Jellyfin.Model.Tests.Cryptography [InlineData("$PBKDF2$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty segment [InlineData("$PBKDF2$iterations=1000$$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Empty salt segment [InlineData("$PBKDF2$iterations=1000$69F420$")] // Empty hash segment - [InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter - [InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter - [InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parmeter + [InlineData("$PBKDF2$=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter + [InlineData("$PBKDF2$=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter + [InlineData("$PBKDF2$iterations=$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D")] // Invalid parameter [InlineData("$PBKDF2$iterations=1000$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Ends on $ [InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$")] // Extra segment [InlineData("$PBKDF2$iterations=1000$69F420$62FBA410AFCA5B4475F35137AB2E8596B127E4D927BA23F6CC05C067E897042D$anotherone")] // Extra segment diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 6b93974373..52b0e5a955 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -393,7 +393,7 @@ namespace Jellyfin.Networking.Tests // User on external network, internal binding only - so assumption is a proxy forward, return external override. [InlineData("jellyfin.org", "192.168.1.0/24", "eth16", false, "0.0.0.0=http://helloworld.com", "http://helloworld.com")] - // User on external network, no binding - so result is the 1st external which is overriden. + // User on external network, no binding - so result is the 1st external which is overridden. [InlineData("jellyfin.org", "192.168.1.0/24", "", false, "0.0.0.0 = http://helloworld.com", "http://helloworld.com")] // User assumed to be internal, no binding - so result is the 1st internal. diff --git a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs index 3b3e38bd1f..e1d2bb2d58 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/LiveTv/SchedulesDirect/SchedulesDirectDeserializeTests.cs @@ -18,7 +18,7 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv.SchedulesDirect } /// - /// /token reponse. + /// /token response. /// [Fact] public void Deserialize_Token_Response_Live_Success() diff --git a/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json index b766e668e3..fa8fbd8d2c 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json +++ b/tests/Jellyfin.Server.Implementations.Tests/Test Data/Updates/manifest-stable.json @@ -253,7 +253,7 @@ "versions": [ { "version": "5.0.0.0", - "changelog": "Updated to use NextPVR API v5, no longer compatable with API v4.\n", + "changelog": "Updated to use NextPVR API v5, no longer compatible with API v4.\n", "targetAbi": "10.7.0.0", "sourceUrl": "https://repo.jellyfin.org/releases/plugin/nextpvr/nextpvr_5.0.0.0.zip", "checksum": "d70f694d14bf9462ba2b2ebe110068d3", -- cgit v1.2.3 From 5036afd69127cc6f6b0801329b2b04f21aee71f5 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 12 Aug 2022 20:37:31 +0200 Subject: Minor cleanup --- .../AppBase/BaseConfigurationManager.cs | 12 ++--------- Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs | 7 +----- .../Attributes/HttpUnsubscribeAttribute.cs | 7 +----- .../Controllers/DisplayPreferencesController.cs | 7 ++---- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 6 ++++-- .../Users/DisplayPreferencesManager.cs | 2 +- .../SymlinkFollowingPhysicalFileResultExecutor.cs | 11 ++-------- .../Configuration/ConfigurationUpdateEventArgs.cs | 25 ++++++++++++++++------ .../Configuration/IApplicationPaths.cs | 2 -- .../Entities/BasePluginFolder.cs | 4 +--- MediaBrowser.Controller/Entities/Extensions.cs | 8 +++---- .../IDisplayPreferencesManager.cs | 6 ++---- 12 files changed, 38 insertions(+), 59 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 2a4a8fb132..c42cec593a 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -365,11 +365,7 @@ namespace Emby.Server.Implementations.AppBase validatingStore.Validate(currentConfiguration, configuration); } - NamedConfigurationUpdating?.Invoke(this, new ConfigurationUpdateEventArgs - { - Key = key, - NewConfiguration = configuration - }); + NamedConfigurationUpdating?.Invoke(this, new ConfigurationUpdateEventArgs(key, configuration)); _configurations.AddOrUpdate(key, configuration, (_, _) => configuration); @@ -391,11 +387,7 @@ namespace Emby.Server.Implementations.AppBase /// The old configuration. protected virtual void OnNamedConfigurationUpdated(string key, object configuration) { - NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs - { - Key = key, - NewConfiguration = configuration - }); + NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs(key, configuration)); } /// diff --git a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs index af8727552c..7ac089a344 100644 --- a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs @@ -25,11 +25,6 @@ namespace Jellyfin.Api.Attributes /// The route template. May not be null. public HttpSubscribeAttribute(string template) : base(_supportedMethods, template) - { - if (template == null) - { - throw new ArgumentNullException(nameof(template)); - } - } + => ArgumentNullException.ThrowIfNull(template, nameof(template)); } } diff --git a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs index 1c0b70e719..16b3d08160 100644 --- a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs @@ -25,11 +25,6 @@ namespace Jellyfin.Api.Attributes /// The route template. May not be null. public HttpUnsubscribeAttribute(string template) : base(_supportedMethods, template) - { - if (template == null) - { - throw new ArgumentNullException(nameof(template)); - } - } + => ArgumentNullException.ThrowIfNull(template, nameof(template)); } } diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs index 27eb223390..64ee5680ce 100644 --- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs +++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs @@ -89,12 +89,9 @@ namespace Jellyfin.Api.Controllers // Load all custom display preferences var customDisplayPreferences = _displayPreferencesManager.ListCustomItemDisplayPreferences(displayPreferences.UserId, itemId, displayPreferences.Client); - if (customDisplayPreferences != null) + foreach (var (key, value) in customDisplayPreferences) { - foreach (var (key, value) in customDisplayPreferences) - { - dto.CustomPrefs.TryAdd(key, value); - } + dto.CustomPrefs.TryAdd(key, value); } // This will essentially be a noop if no changes have been made, but new prefs must be saved at least. diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 6875282318..13f155f357 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -145,9 +145,11 @@ namespace Jellyfin.Drawing.Skia /// The file at the specified path could not be used to generate a codec. public string GetImageBlurHash(int xComp, int yComp, string path) { - if (path == null) + ArgumentNullException.ThrowIfNull(path, nameof(path)); + + if (path.Length == 0) { - throw new ArgumentNullException(nameof(path)); + throw new ArgumentException("String can't be empty", nameof(path)); } var extension = Path.GetExtension(path.AsSpan()).TrimStart('.'); diff --git a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs index f5d38db20f..65edb30ad2 100644 --- a/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs +++ b/Jellyfin.Server.Implementations/Users/DisplayPreferencesManager.cs @@ -79,7 +79,7 @@ namespace Jellyfin.Server.Implementations.Users } /// - public void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary customPreferences) + public void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary customPreferences) { var existingPrefs = _dbContext.CustomItemDisplayPreferences .AsQueryable() diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index 7e7e4ca95b..28ed3894fd 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -69,15 +69,8 @@ namespace Jellyfin.Server.Infrastructure /// protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue? range, long rangeLength) { - if (context == null) - { - throw new ArgumentNullException(nameof(context)); - } - - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(context, nameof(context)); + ArgumentNullException.ThrowIfNull(result, nameof(result)); if (range != null && rangeLength == 0) { diff --git a/MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs b/MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs index 2df87d8792..90b1ff70c2 100644 --- a/MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs +++ b/MediaBrowser.Common/Configuration/ConfigurationUpdateEventArgs.cs @@ -1,22 +1,33 @@ -#nullable disable -#pragma warning disable CS1591 - using System; namespace MediaBrowser.Common.Configuration { + /// + /// for the ConfigurationUpdated event. + /// public class ConfigurationUpdateEventArgs : EventArgs { /// - /// Gets or sets the key. + /// Initializes a new instance of the class. + /// + /// The configuration key. + /// The new configuration. + public ConfigurationUpdateEventArgs(string key, object newConfiguration) + { + Key = key; + NewConfiguration = newConfiguration; + } + + /// + /// Gets the key. /// /// The key. - public string Key { get; set; } + public string Key { get; } /// - /// Gets or sets the new configuration. + /// Gets the new configuration. /// /// The new configuration. - public object NewConfiguration { get; set; } + public object NewConfiguration { get; } } } diff --git a/MediaBrowser.Common/Configuration/IApplicationPaths.cs b/MediaBrowser.Common/Configuration/IApplicationPaths.cs index 1370e6d79e..57c6546675 100644 --- a/MediaBrowser.Common/Configuration/IApplicationPaths.cs +++ b/MediaBrowser.Common/Configuration/IApplicationPaths.cs @@ -1,5 +1,3 @@ -#nullable disable - namespace MediaBrowser.Common.Configuration { /// diff --git a/MediaBrowser.Controller/Entities/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs index 272a37df1b..afafaf1c24 100644 --- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs +++ b/MediaBrowser.Controller/Entities/BasePluginFolder.cs @@ -1,5 +1,3 @@ -#nullable disable - #pragma warning disable CS1591 using System.Text.Json.Serialization; @@ -13,7 +11,7 @@ namespace MediaBrowser.Controller.Entities public abstract class BasePluginFolder : Folder, ICollectionFolder { [JsonIgnore] - public virtual string CollectionType => null; + public virtual string? CollectionType => null; [JsonIgnore] public override bool SupportsInheritedParentImages => false; diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index 9ce8eebe34..14534aa50b 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Linq; using Jellyfin.Extensions; @@ -19,9 +17,11 @@ namespace MediaBrowser.Controller.Entities /// Trailer URL. public static void AddTrailerUrl(this BaseItem item, string url) { - if (string.IsNullOrEmpty(url)) + ArgumentNullException.ThrowIfNull(url, nameof(url)); + + if (url.Length == 0) { - throw new ArgumentNullException(nameof(url)); + throw new ArgumentException("String can't be empty", nameof(url)); } var current = item.RemoteTrailers.FirstOrDefault(i => string.Equals(i.Url, url, StringComparison.OrdinalIgnoreCase)); diff --git a/MediaBrowser.Controller/IDisplayPreferencesManager.cs b/MediaBrowser.Controller/IDisplayPreferencesManager.cs index 1678d50675..10c0f56e09 100644 --- a/MediaBrowser.Controller/IDisplayPreferencesManager.cs +++ b/MediaBrowser.Controller/IDisplayPreferencesManager.cs @@ -1,5 +1,3 @@ -#nullable disable - using System; using System.Collections.Generic; using Jellyfin.Data.Entities; @@ -50,7 +48,7 @@ namespace MediaBrowser.Controller /// The item id. /// The client string. /// The dictionary of custom item display preferences. - Dictionary ListCustomItemDisplayPreferences(Guid userId, Guid itemId, string client); + Dictionary ListCustomItemDisplayPreferences(Guid userId, Guid itemId, string client); /// /// Sets the custom item display preference for the user and client. @@ -59,7 +57,7 @@ namespace MediaBrowser.Controller /// The item id. /// The client id. /// A dictionary of custom item display preferences. - void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary customPreferences); + void SetCustomItemDisplayPreferences(Guid userId, Guid itemId, string client, Dictionary customPreferences); /// /// Saves changes made to the database. -- cgit v1.2.3 From 61fa325ef05daac7c5105623d2de435ec94ef6a7 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Mon, 28 Mar 2022 23:11:21 +0200 Subject: Extend music parsing --- Emby.Naming/Common/NamingOptions.cs | 23 ++++ .../Library/Resolvers/Audio/MusicAlbumResolver.cs | 11 +- .../Entities/Audio/MusicAlbum.cs | 2 +- .../MediaBrowser.Providers.csproj | 1 + .../MediaInfo/FFProbeAudioInfo.cs | 119 +++++++++------- .../Music/AlbumMetadataService.cs | 152 +++++++++++++++++++-- .../Music/AudioMetadataService.cs | 40 ++++++ 7 files changed, 287 insertions(+), 61 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index e016d7e51f..ddeec679d4 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -181,6 +181,24 @@ namespace Emby.Naming.Common "volume" }; + ArtistSubfolders = new[] + { + "albums", + "broadcasts", + "bootlegs", + "compilations", + "dj-mixes", + "eps", + "live", + "mixtapes", + "others", + "remixes", + "singles", + "soundtracks", + "spokenwords", + "streets" + }; + AudioFileExtensions = new[] { ".669", @@ -732,6 +750,11 @@ namespace Emby.Naming.Common /// public string[] AlbumStackingPrefixes { get; set; } + /// + /// Gets or sets list of artist subfolders. + /// + public string[] ArtistSubfolders { get; set; } + /// /// Gets or sets list of subtitle file extensions. /// diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index da00b9cfa8..5e05ddfb16 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -98,7 +99,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio // Args points to an album if parent is an Artist folder or it directly contains music if (args.IsDirectory) { - // if (args.Parent is MusicArtist) return true; // saves us from testing children twice + foreach (var subfolder in _namingOptions.ArtistSubfolders) + { + if (Path.GetDirectoryName(args.Path.AsSpan()).Equals(subfolder, StringComparison.OrdinalIgnoreCase)) + { + _logger.LogDebug("Found release folder: {Path}", args.Path); + return false; + } + } + if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService)) { return true; diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index bd397bdd13..6555de8554 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -54,7 +54,7 @@ namespace MediaBrowser.Controller.Entities.Audio public string AlbumArtist => AlbumArtists.FirstOrDefault(); [JsonIgnore] - public override bool SupportsPeople => false; + public override bool SupportsPeople => true; /// /// Gets the tracks. diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 9864db9ac2..459045dffc 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -22,6 +22,7 @@ + diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index f22965436f..e801a20efb 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -17,6 +18,7 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.MediaInfo; +using TagLib; namespace MediaBrowser.Providers.MediaInfo { @@ -93,7 +95,7 @@ namespace MediaBrowser.Providers.MediaInfo // var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.'); // audio.Container = extension; - FetchDataFromTags(audio, mediaInfo); + FetchDataFromTags(audio); _itemRepo.SaveMediaStreams(audio.Id, mediaInfo.MediaStreams, cancellationToken); } @@ -102,71 +104,90 @@ namespace MediaBrowser.Providers.MediaInfo /// Fetches data from the tags dictionary. /// /// The audio. - /// The data. - private void FetchDataFromTags(Audio audio, Model.MediaInfo.MediaInfo data) + private void FetchDataFromTags(Audio audio) { - // Only set Name if title was found in the dictionary - if (!string.IsNullOrEmpty(data.Name)) + var file = TagLib.File.Create(audio.Path); + var tagTypes = file.TagTypesOnDisk; + Tag tags = null; + + if (tagTypes.HasFlag(TagTypes.Id3v2)) { - audio.Name = data.Name; + tags = file.GetTag(TagTypes.Id3v2); } - - if (!string.IsNullOrEmpty(data.ForcedSortName)) + else if (tagTypes.HasFlag(TagTypes.Ape)) { - audio.ForcedSortName = data.ForcedSortName; + tags = file.GetTag(TagTypes.Ape); } - - if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast)) + else if (tagTypes.HasFlag(TagTypes.FlacMetadata)) { - var people = new List(); + tags = file.GetTag(TagTypes.FlacMetadata); + } + else if (tagTypes.HasFlag(TagTypes.Id3v1)) + { + tags = file.GetTag(TagTypes.Id3v1); + } - foreach (var person in data.People) + if (tags != null) + { + if (audio.SupportsPeople && !audio.LockedFields.Contains(MetadataField.Cast)) { - PeopleHelper.AddPerson(people, new PersonInfo + var people = new List(); + var albumArtists = tags.AlbumArtists; + foreach (var albumArtist in albumArtists) { - Name = person.Name, - Type = person.Type, - Role = person.Role - }); - } - - _libraryManager.UpdatePeople(audio, people); - } + PeopleHelper.AddPerson(people, new PersonInfo + { + Name = albumArtist, + Type = "AlbumArtist" + }); + } - audio.Album = data.Album; - audio.Artists = data.Artists; - audio.AlbumArtists = data.AlbumArtists; - audio.IndexNumber = data.IndexNumber; - audio.ParentIndexNumber = data.ParentIndexNumber; - audio.ProductionYear = data.ProductionYear; - audio.PremiereDate = data.PremiereDate; + var performers = tags.Performers; + foreach (var performer in performers) + { + PeopleHelper.AddPerson(people, new PersonInfo + { + Name = performer, + Type = "Artist" + }); + } - // If we don't have a ProductionYear try and get it from PremiereDate - if (audio.PremiereDate.HasValue && !audio.ProductionYear.HasValue) - { - audio.ProductionYear = audio.PremiereDate.Value.ToLocalTime().Year; - } + foreach (var composer in tags.Composers) + { + PeopleHelper.AddPerson(people, new PersonInfo + { + Name = composer, + Type = "Composer" + }); + } + + _libraryManager.UpdatePeople(audio, people); + audio.Artists = performers; + audio.AlbumArtists = albumArtists; + } - if (!audio.LockedFields.Contains(MetadataField.Genres)) - { - audio.Genres = Array.Empty(); + audio.Name = tags.Title; + audio.Album = tags.Album; + audio.IndexNumber = Convert.ToInt32(tags.Track); + audio.ParentIndexNumber = Convert.ToInt32(tags.Disc); + if(tags.Year != 0) + { + var year = Convert.ToInt32(tags.Year); + audio.ProductionYear = year; + audio.PremiereDate = new DateTime(year, 01, 01); + } - foreach (var genre in data.Genres) + if (!audio.LockedFields.Contains(MetadataField.Genres)) { - audio.AddGenre(genre); + audio.Genres = tags.Genres.Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); } - } - if (!audio.LockedFields.Contains(MetadataField.Studios)) - { - audio.SetStudios(data.Studios); + audio.SetProviderId(MetadataProvider.MusicBrainzArtist, tags.MusicBrainzArtistId); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, tags.MusicBrainzReleaseArtistId); + audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, tags.MusicBrainzReleaseId); + audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, tags.MusicBrainzReleaseGroupId); + audio.SetProviderId(MetadataProvider.MusicBrainzTrack, tags.MusicBrainzTrackId); } - - audio.SetProviderId(MetadataProvider.MusicBrainzAlbumArtist, data.GetProviderId(MetadataProvider.MusicBrainzAlbumArtist)); - audio.SetProviderId(MetadataProvider.MusicBrainzArtist, data.GetProviderId(MetadataProvider.MusicBrainzArtist)); - audio.SetProviderId(MetadataProvider.MusicBrainzAlbum, data.GetProviderId(MetadataProvider.MusicBrainzAlbum)); - audio.SetProviderId(MetadataProvider.MusicBrainzReleaseGroup, data.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup)); - audio.SetProviderId(MetadataProvider.MusicBrainzTrack, data.GetProviderId(MetadataProvider.MusicBrainzTrack)); } } } diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs index 7743d3b27b..b8426f31c1 100644 --- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs +++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs @@ -61,40 +61,61 @@ namespace MediaBrowser.Providers.Music var songs = children.Cast /// The args. - /// true if [is music album] [the specified args]; otherwise, false. + /// true if [is music album] [the specified args], false otherwise. private bool IsMusicAlbum(ItemResolveArgs args) { - // Args points to an album if parent is an Artist folder or it directly contains music if (args.IsDirectory) { + // If args is a artist subfolder it's not a music album foreach (var subfolder in _namingOptions.ArtistSubfolders) { if (Path.GetDirectoryName(args.Path.AsSpan()).Equals(subfolder, StringComparison.OrdinalIgnoreCase)) @@ -108,6 +108,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio } } + // If args contains music it's a music album if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService)) { return true; @@ -120,22 +121,23 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio /// /// Determine if the supplied list contains what we should consider music. /// + /// true if the provided path list contains music, false otherwise. private bool ContainsMusic( ICollection list, bool allowSubfolders, IDirectoryService directoryService) { - // check for audio files before digging down into directories + // Check for audio files before digging down into directories var foundAudioFile = list.Any(fileSystemInfo => !fileSystemInfo.IsDirectory && AudioFileParser.IsAudioFile(fileSystemInfo.FullName, _namingOptions)); if (foundAudioFile) { - // at least one audio file exists + // At least one audio file exists return true; } if (!allowSubfolders) { - // not music since no audio file exists and we're not looking into subfolders + // Not music since no audio file exists and we're not looking into subfolders return false; } diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs index b7c1724c07..2538c2b5b4 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library.Resolvers.Audio { /// - /// Class MusicArtistResolver. + /// The music artist resolver. /// public class MusicArtistResolver : ItemResolver { @@ -23,8 +23,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio /// /// Initializes a new instance of the class. /// - /// The logger for the created instances. - /// The naming options. + /// Instance of the interface. + /// The . public MusicArtistResolver( ILogger logger, NamingOptions namingOptions) @@ -40,10 +40,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio public override ResolverPriority Priority => ResolverPriority.Second; /// - /// Resolves the specified args. + /// Resolves the specified resolver arguments. /// - /// The args. - /// MusicArtist. + /// The resolver arguments. + /// A . protected override MusicArtist Resolve(ItemResolveArgs args) { if (!args.IsDirectory) @@ -82,23 +82,24 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var albumResolver = new MusicAlbumResolver(_logger, _namingOptions); - // If we contain an album assume we are an artist folder var directories = args.FileSystemChildren.Where(i => i.IsDirectory); var result = Parallel.ForEach(directories, (fileSystemInfo, state) => { + // If we contain a artist subfolder assume we are an artist folder foreach (var subfolder in _namingOptions.ArtistSubfolders) { if (fileSystemInfo.Name.Equals(subfolder, StringComparison.OrdinalIgnoreCase)) { - // stop once we see a artist subfolder + // Stop once we see an artist subfolder state.Stop(); } } + // If we contain a music album assume we are an artist folder if (albumResolver.IsMusicAlbum(fileSystemInfo.FullName, directoryService)) { - // stop once we see a music album + // Stop once we see a music album state.Stop(); } }); diff --git a/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs index 32a9cbef2e..14428df5b3 100644 --- a/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs @@ -18,9 +18,9 @@ namespace MediaBrowser.Controller.Providers /// Fetches the metadata asynchronously. /// /// The item. - /// The options. - /// The cancellation token. - /// Task{ItemUpdateType}. + /// The . + /// The . + /// A fetching the . Task FetchAsync(TItemType item, MetadataRefreshOptions options, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs index 2591e880f6..2b26b31379 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs @@ -1,7 +1,5 @@ #nullable disable -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.Linq; @@ -21,6 +19,9 @@ using TagLib; namespace MediaBrowser.Providers.MediaInfo { + /// + /// Probes audio files for metadata. + /// public class AudioFileProber { private readonly IMediaEncoder _mediaEncoder; @@ -28,6 +29,13 @@ namespace MediaBrowser.Providers.MediaInfo private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. public AudioFileProber( IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, @@ -40,6 +48,14 @@ namespace MediaBrowser.Providers.MediaInfo _mediaSourceManager = mediaSourceManager; } + /// + /// Probes the specified item for metadata. + /// + /// The item to probe. + /// The . + /// The . + /// The type of item to resolve. + /// A probing the item for metadata. public async Task Probe( T item, MetadataRefreshOptions options, @@ -80,9 +96,9 @@ namespace MediaBrowser.Providers.MediaInfo /// /// Fetches the specified audio. /// - /// The audio. - /// The media information. - /// The cancellation token. + /// The . + /// The . + /// The . protected void Fetch(Audio audio, Model.MediaInfo.MediaInfo mediaInfo, CancellationToken cancellationToken) { audio.Container = mediaInfo.Container; @@ -91,18 +107,15 @@ namespace MediaBrowser.Providers.MediaInfo audio.RunTimeTicks = mediaInfo.RunTimeTicks; audio.Size = mediaInfo.Size; - // var extension = (Path.GetExtension(audio.Path) ?? string.Empty).TrimStart('.'); - // audio.Container = extension; - FetchDataFromTags(audio); _itemRepo.SaveMediaStreams(audio.Id, mediaInfo.MediaStreams, cancellationToken); } /// - /// Fetches data from the tags dictionary. + /// Fetches data from the tags. /// - /// The audio. + /// The . private void FetchDataFromTags(Audio audio) { var file = TagLib.File.Create(audio.Path); diff --git a/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs index 54c12a8f17..6591366076 100644 --- a/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs @@ -1,7 +1,5 @@ #nullable disable -#pragma warning disable CS1591 - using System; using System.IO; using System.Linq; @@ -27,6 +25,9 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.MediaInfo { + /// + /// The probe provider. + /// public class ProbeProvider : ICustomMetadataProvider, ICustomMetadataProvider, ICustomMetadataProvider, @@ -46,6 +47,22 @@ namespace MediaBrowser.Providers.MediaInfo private readonly AudioFileProber _audioProber; private readonly Task _cachedTask = Task.FromResult(ItemUpdateType.None); + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the . + /// Instance of the interface. + /// The . public ProbeProvider( IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, @@ -81,11 +98,13 @@ namespace MediaBrowser.Providers.MediaInfo _subtitleResolver); } - public string Name => "filemetadataprober"; + /// + public string Name => "Probe Provider"; - // Run last + /// public int Order => 100; + /// public bool HasChanged(BaseItem item, IDirectoryService directoryService) { var video = item as Video; @@ -127,41 +146,56 @@ namespace MediaBrowser.Providers.MediaInfo return false; } + /// public Task FetchAsync(Episode item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return FetchVideoInfo(item, options, cancellationToken); } + /// public Task FetchAsync(MusicVideo item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return FetchVideoInfo(item, options, cancellationToken); } + /// public Task FetchAsync(Movie item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return FetchVideoInfo(item, options, cancellationToken); } + /// public Task FetchAsync(Trailer item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return FetchVideoInfo(item, options, cancellationToken); } + /// public Task FetchAsync(Video item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return FetchVideoInfo(item, options, cancellationToken); } + /// public Task FetchAsync(Audio item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return FetchAudioInfo(item, options, cancellationToken); } + /// public Task FetchAsync(AudioBook item, MetadataRefreshOptions options, CancellationToken cancellationToken) { return FetchAudioInfo(item, options, cancellationToken); } + /// + /// Fetches video information for an item. + /// + /// The item. + /// The . + /// The . + /// The type of item to resolve. + /// A fetching the for an item. public Task FetchVideoInfo(T item, MetadataRefreshOptions options, CancellationToken cancellationToken) where T : Video { @@ -208,6 +242,14 @@ namespace MediaBrowser.Providers.MediaInfo .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i) && !i.StartsWith('#')); } + /// + /// Fetches audio information for an item. + /// + /// The item. + /// The . + /// The . + /// The type of item to resolve. + /// A fetching the for an item. public Task FetchAudioInfo(T item, MetadataRefreshOptions options, CancellationToken cancellationToken) where T : Audio { diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs index b8426f31c1..1a8e20be32 100644 --- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs +++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.Linq; @@ -15,8 +13,19 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Music { + /// + /// The album metadata service. + /// public class AlbumMetadataService : MetadataService { + /// + /// Initializes a new instance of the class. + /// + /// Instance of the . + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. public AlbumMetadataService( IServerConfigurationManager serverConfigurationManager, ILogger logger, diff --git a/MediaBrowser.Providers/Music/AudioMetadataService.cs b/MediaBrowser.Providers/Music/AudioMetadataService.cs index 64f40ef49f..7c38d0bcf5 100644 --- a/MediaBrowser.Providers/Music/AudioMetadataService.cs +++ b/MediaBrowser.Providers/Music/AudioMetadataService.cs @@ -1,5 +1,3 @@ -#pragma warning disable CS1591 - using System; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; @@ -12,8 +10,19 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Music { + /// + /// The audio metadata service. + /// public class AudioMetadataService : MetadataService { + /// + /// Initializes a new instance of the class. + /// + /// Instance of the . + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. + /// Instance of the interface. public AudioMetadataService( IServerConfigurationManager serverConfigurationManager, ILogger logger, -- cgit v1.2.3 From c71d6f2358ba8a5b1f80a2bef41b6f438c06d03c Mon Sep 17 00:00:00 2001 From: Zach Phelan Date: Tue, 13 Sep 2022 16:40:47 -0600 Subject: Sort special features same as other spots, removing unnecssary function Added to contributors --- CONTRIBUTORS.md | 1 + Jellyfin.Api/Controllers/UserLibraryController.cs | 3 ++- MediaBrowser.Controller/Entities/BaseItem.cs | 13 ------------- 3 files changed, 3 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 98acd4449f..8daaae4d94 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -148,6 +148,7 @@ - [xosdy](https://github.com/xosdy) - [XVicarious](https://github.com/XVicarious) - [YouKnowBlom](https://github.com/YouKnowBlom) + - [ZachPhelan](https://github.com/ZachPhelan) - [KristupasSavickas](https://github.com/KristupasSavickas) - [Pusta](https://github.com/pusta) - [nielsvanvelzen](https://github.com/nielsvanvelzen) diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 1656a1e98c..940fa27a70 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -233,7 +233,8 @@ namespace Jellyfin.Api.Controllers var dtoOptions = new DtoOptions().AddClientFields(Request); return Ok(item - .GetExtras(BaseItem.DisplayExtraTypes) + .GetExtras() + .Where(i => i.ExtraType.HasValue && BaseItem.DisplayExtraTypes.Contains(i.ExtraType.Value)) .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item))); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 5cee6ce406..988d0a534a 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2606,19 +2606,6 @@ namespace MediaBrowser.Controller.Entities .OrderBy(i => i.SortName); } - /// - /// Get all extras with specific types that are associated with this item. - /// - /// The types of extras to retrieve. - /// An enumerable containing the extras. - public IEnumerable GetExtras(IReadOnlyCollection extraTypes) - { - return ExtraIds - .Select(LibraryManager.GetItemById) - .Where(i => i != null) - .Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value)); - } - public virtual long GetRunTimeTicksForPlayState() { return RunTimeTicks ?? 0; -- cgit v1.2.3 From 8857edb66cbc0260981aa1aa3542da495e1b2443 Mon Sep 17 00:00:00 2001 From: Zach Phelan Date: Tue, 13 Sep 2022 17:13:02 -0600 Subject: Add function back for compatibility, add sorting --- MediaBrowser.Controller/Entities/BaseItem.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 988d0a534a..9461b01e31 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2606,6 +2606,20 @@ namespace MediaBrowser.Controller.Entities .OrderBy(i => i.SortName); } + /// + /// Get all extras with specific types that are associated with this item. + /// + /// The types of extras to retrieve. + /// An enumerable containing the extras. + public IEnumerable GetExtras(IReadOnlyCollection extraTypes) + { + return ExtraIds + .Select(LibraryManager.GetItemById) + .Where(i => i != null) + .Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value)) + .OrderBy(i => i.SortName); + } + public virtual long GetRunTimeTicksForPlayState() { return RunTimeTicks ?? 0; -- cgit v1.2.3 From d9be3874ba3842d5888c5cbbe583614ed990849e Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Thu, 15 Sep 2022 19:45:26 -0400 Subject: Auto stash before merge of "lyric-lrc-file-support" and "origin/lyric-lrc-file-support" --- Emby.Server.Implementations/ApplicationHost.cs | 2 + Emby.Server.Implementations/Dto/DtoService.cs | 9 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 5 +- Jellyfin.Api/Helpers/ItemHelper.cs | 106 ------------------- Jellyfin.Api/Jellyfin.Api.csproj | 1 - Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs | 34 ------ Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs | 117 --------------------- Jellyfin.Api/Models/UserDtos/Lyric.cs | 18 ---- Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs | 81 -------------- MediaBrowser.Controller/Lyrics/ILyricsProvider.cs | 24 +++++ MediaBrowser.Controller/Lyrics/Lyric.cs | 18 ++++ MediaBrowser.Controller/Lyrics/LyricInfo.cs | 87 +++++++++++++++ MediaBrowser.Controller/Lyrics/LyricResponse.cs | 15 +++ MediaBrowser.Model/Dto/BaseItemDto.cs | 2 +- MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs | 112 ++++++++++++++++++++ MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs | 74 +++++++++++++ .../MediaBrowser.Providers.csproj | 2 + 17 files changed, 345 insertions(+), 362 deletions(-) delete mode 100644 Jellyfin.Api/Helpers/ItemHelper.cs delete mode 100644 Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs delete mode 100644 Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs delete mode 100644 Jellyfin.Api/Models/UserDtos/Lyric.cs delete mode 100644 Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs create mode 100644 MediaBrowser.Controller/Lyrics/ILyricsProvider.cs create mode 100644 MediaBrowser.Controller/Lyrics/Lyric.cs create mode 100644 MediaBrowser.Controller/Lyrics/LyricInfo.cs create mode 100644 MediaBrowser.Controller/Lyrics/LyricResponse.cs create mode 100644 MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs create mode 100644 MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3e9c540e7b..5487e5e023 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -68,6 +68,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Notifications; @@ -95,6 +96,7 @@ using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; using MediaBrowser.Providers.Chapters; +using MediaBrowser.Providers.Lyric; using MediaBrowser.Providers.Manager; using MediaBrowser.Providers.Plugins.Tmdb; using MediaBrowser.Providers.Subtitles; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 96717cff53..bed82a4bbb 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -19,6 +19,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; @@ -51,6 +52,8 @@ namespace Emby.Server.Implementations.Dto private readonly IMediaSourceManager _mediaSourceManager; private readonly Lazy _livetvManagerFactory; + private readonly IEnumerable _lyricProviders; + public DtoService( ILogger logger, ILibraryManager libraryManager, @@ -60,7 +63,8 @@ namespace Emby.Server.Implementations.Dto IProviderManager providerManager, IApplicationHost appHost, IMediaSourceManager mediaSourceManager, - Lazy livetvManagerFactory) + Lazy livetvManagerFactory, + IEnumerable lyricProviders) { _logger = logger; _libraryManager = libraryManager; @@ -71,6 +75,7 @@ namespace Emby.Server.Implementations.Dto _appHost = appHost; _mediaSourceManager = mediaSourceManager; _livetvManagerFactory = livetvManagerFactory; + _lyricProviders = lyricProviders; } private ILiveTvManager LivetvManager => _livetvManagerFactory.Value; @@ -142,7 +147,7 @@ namespace Emby.Server.Implementations.Dto } else if (item is Audio) { - dto.HasLocalLyricsFile = ItemHelper.HasLyricFile(item.Path); + dto.HasLyrics = MediaBrowser.Controller.Lyrics.LyricInfo.HasLyricFile(_lyricProviders, item.Path); } if (item is IItemByName itemByName diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 123c5e0795..3da78c1169 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -13,6 +13,7 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -414,8 +415,8 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - // Super nieve implementation. I would suggest building a lyric service of some sort and doing this there. - foreach (var provider in _lyricProviders) + var result = MediaBrowser.Controller.Lyrics.LyricInfo.GetLyricData(_lyricProviders, item); + if (result is not null) { provider.Process(item); if (provider.HasData) diff --git a/Jellyfin.Api/Helpers/ItemHelper.cs b/Jellyfin.Api/Helpers/ItemHelper.cs deleted file mode 100644 index 49bb8af8e3..0000000000 --- a/Jellyfin.Api/Helpers/ItemHelper.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.Globalization; -using System.IO; -using System.Linq; -using Jellyfin.Api.Models.UserDtos; -using LrcParser.Model; -using LrcParser.Parser; -using MediaBrowser.Controller.Entities; - -namespace Jellyfin.Api.Helpers -{ - /// - /// Item helper. - /// - public static class ItemHelper - { - /// - /// Opens lyrics file, converts to a List of Lyrics, and returns it. - /// - /// Requested Item. - /// Collection of Lyrics. - internal static object? GetLyricData(BaseItem item) - { - // Find all classes that implement ILyricsProvider Interface - var foundLyricProviders = System.Reflection.Assembly.GetExecutingAssembly() - .GetTypes() - .Where(type => typeof(ILyricsProvider).IsAssignableFrom(type) && !type.IsInterface); - - if (!foundLyricProviders.Any()) - { - return null; - } - - foreach (var provider in foundLyricProviders) - { - ILyricsProvider? newProvider = Activator.CreateInstance(provider) as ILyricsProvider; - if (newProvider is not null) - { - newProvider.Process(item); - if (newProvider.HasData) - { - return newProvider.Data; - } - } - } - - return null; - } - - /// - /// Checks if requested item has a matching lyric file. - /// - /// Path of requested item. - /// True if item has a matching lyrics file. - public static string? GetLyricFilePath(string itemPath) - { - // Find all classes that implement ILyricsProvider Interface - var foundLyricProviders = System.Reflection.Assembly.GetExecutingAssembly() - .GetTypes() - .Where(type => typeof(ILyricsProvider).IsAssignableFrom(type) && !type.IsInterface); - - if (!foundLyricProviders.Any()) - { - return null; - } - - // Iterate over all found lyric providers - foreach (var provider in foundLyricProviders) - { - ILyricsProvider? foundProvider = Activator.CreateInstance(provider) as ILyricsProvider; - if (foundProvider?.FileExtensions is null) - { - continue; - } - - if (foundProvider.FileExtensions.Any()) - { - foreach (string lyricFileExtension in foundProvider.FileExtensions) - { - string lyricFilePath = @Path.ChangeExtension(itemPath, lyricFileExtension); - if (System.IO.File.Exists(lyricFilePath)) - { - return lyricFilePath; - } - } - } - } - - return null; - } - - - /// - /// Checks if requested item has a matching local lyric file. - /// - /// Path of requested item. - /// True if item has a matching lyrics file; otherwise false. - public static bool HasLyricFile(string itemPath) - { - string? lyricFilePath = GetLyricFilePath(itemPath); - return !string.IsNullOrEmpty(lyricFilePath); - } - } -} diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index 972387e02a..894d871383 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -17,7 +17,6 @@ - diff --git a/Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs b/Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs deleted file mode 100644 index 37f1f5bbe4..0000000000 --- a/Jellyfin.Api/Models/UserDtos/ILyricsProvider.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.ObjectModel; -using MediaBrowser.Controller.Entities; - -namespace Jellyfin.Api.Models.UserDtos -{ - /// - /// Interface ILyricsProvider. - /// - public interface ILyricsProvider - { - /// - /// Gets a value indicating the File Extenstions this provider works with. - /// - public Collection? FileExtensions { get; } - - /// - /// Gets a value indicating whether Process() generated data. - /// - /// true if data generated; otherwise, false. - bool HasData { get; } - - /// - /// Gets Data object generated by Process() method. - /// - /// Object with data if no error occured; otherwise, null. - object? Data { get; } - - /// - /// Opens lyric file for [the specified item], and processes it for API return. - /// - /// The item to to process. - void Process(BaseItem item); - } -} diff --git a/Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs b/Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs deleted file mode 100644 index 029acd6ca5..0000000000 --- a/Jellyfin.Api/Models/UserDtos/LrcLyricsProvider.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Dynamic; -using System.Globalization; -using System.Linq; -using LrcParser.Model; -using LrcParser.Parser; -using MediaBrowser.Controller.Entities; - -namespace Jellyfin.Api.Models.UserDtos -{ - /// - /// LRC File Lyric Provider. - /// - public class LrcLyricsProvider : ILyricsProvider - { - /// - /// Initializes a new instance of the class. - /// - public LrcLyricsProvider() - { - FileExtensions = new Collection - { - "lrc" - }; - } - - /// - /// Gets a value indicating the File Extenstions this provider works with. - /// - public Collection? FileExtensions { get; } - - /// - /// Gets or Sets a value indicating whether Process() generated data. - /// - /// true if data generated; otherwise, false. - public bool HasData { get; set; } - - /// - /// Gets or Sets Data object generated by Process() method. - /// - /// Object with data if no error occured; otherwise, null. - public object? Data { get; set; } - - /// - /// Opens lyric file for [the specified item], and processes it for API return. - /// - /// The item to to process. - public void Process(BaseItem item) - { - string? lyricFilePath = Helpers.ItemHelper.GetLyricFilePath(item.Path); - - if (string.IsNullOrEmpty(lyricFilePath)) - { - return; - } - - List lyricsList = new List(); - - List sortedLyricData = new List(); - var metaData = new ExpandoObject() as IDictionary; - string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); - - try - { - // Parse and sort lyric rows - LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); - Song lyricData = lrcLyricParser.Decode(lrcFileContent); - sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.ToArray()[0].Value).ToList(); - - // Parse metadata rows - var metaDataRows = lyricData.Lyrics - .Where(x => x.TimeTags.Count == 0) - .Where(x => x.Text.StartsWith("[", StringComparison.Ordinal) && x.Text.EndsWith("]", StringComparison.Ordinal)) - .Select(x => x.Text) - .ToList(); - - foreach (string metaDataRow in metaDataRows) - { - var metaDataField = metaDataRow.Split(":"); - - string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal); - string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal); - - metaData.Add(metaDataFieldName, metaDataFieldValue); - } - } - catch - { - return; - } - - if (!sortedLyricData.Any()) - { - return; - } - - for (int i = 0; i < sortedLyricData.Count; i++) - { - var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; - double ticks = Convert.ToDouble(timeData, new NumberFormatInfo()) * 10000; - lyricsList.Add(new Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); - } - - this.HasData = true; - if (metaData.Any()) - { - this.Data = new { MetaData = metaData, lyrics = lyricsList }; - } - else - { - this.Data = new { lyrics = lyricsList }; - } - } - } -} diff --git a/Jellyfin.Api/Models/UserDtos/Lyric.cs b/Jellyfin.Api/Models/UserDtos/Lyric.cs deleted file mode 100644 index f83fc9839b..0000000000 --- a/Jellyfin.Api/Models/UserDtos/Lyric.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Jellyfin.Api.Models.UserDtos -{ - /// - /// Lyric dto. - /// - public class Lyric - { - /// - /// Gets or sets the start time (ticks). - /// - public double? Start { get; set; } - - /// - /// Gets or sets the text. - /// - public string Text { get; set; } = string.Empty; - } -} diff --git a/Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs b/Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs deleted file mode 100644 index 03cce1ffbb..0000000000 --- a/Jellyfin.Api/Models/UserDtos/TxtLyricsProvider.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Dynamic; -using System.Globalization; -using System.Linq; -using LrcParser.Model; -using LrcParser.Parser; -using MediaBrowser.Controller.Entities; - -namespace Jellyfin.Api.Models.UserDtos -{ - /// - /// TXT File Lyric Provider. - /// - public class TxtLyricsProvider : ILyricsProvider - { - /// - /// Initializes a new instance of the class. - /// - public TxtLyricsProvider() - { - FileExtensions = new Collection - { - "lrc", "txt" - }; - } - - /// - /// Gets a value indicating the File Extenstions this provider works with. - /// - public Collection? FileExtensions { get; } - - /// - /// Gets or Sets a value indicating whether Process() generated data. - /// - /// true if data generated; otherwise, false. - public bool HasData { get; set; } - - /// - /// Gets or Sets Data object generated by Process() method. - /// - /// Object with data if no error occured; otherwise, null. - public object? Data { get; set; } - - /// - /// Opens lyric file for [the specified item], and processes it for API return. - /// - /// The item to to process. - public void Process(BaseItem item) - { - string? lyricFilePath = Helpers.ItemHelper.GetLyricFilePath(item.Path); - - if (string.IsNullOrEmpty(lyricFilePath)) - { - return; - } - - List lyricsList = new List(); - - string lyricData = System.IO.File.ReadAllText(lyricFilePath); - - // Splitting on Environment.NewLine caused some new lines to be missed in Windows. - char[] newLinedelims = new[] { '\r', '\n' }; - string[] lyricTextLines = lyricData.Split(newLinedelims, StringSplitOptions.RemoveEmptyEntries); - - if (!lyricTextLines.Any()) - { - return; - } - - foreach (string lyricLine in lyricTextLines) - { - lyricsList.Add(new Lyric { Text = lyricLine }); - } - - this.HasData = true; - this.Data = new { lyrics = lyricsList }; - } - } -} diff --git a/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs new file mode 100644 index 0000000000..bac32a398a --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Lyrics +{ + /// + /// Interface ILyricsProvider. + /// + public interface ILyricsProvider + { + /// + /// Gets the supported media types for this provider. + /// + /// The supported media types. + IEnumerable SupportedMediaTypes { get; } + + /// + /// Gets the lyrics. + /// + /// The item to to process. + /// Task{LyricResponse}. + LyricResponse? GetLyrics(BaseItem item); + } +} diff --git a/MediaBrowser.Controller/Lyrics/Lyric.cs b/MediaBrowser.Controller/Lyrics/Lyric.cs new file mode 100644 index 0000000000..d44546dd39 --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/Lyric.cs @@ -0,0 +1,18 @@ +namespace MediaBrowser.Controller.Lyrics +{ + /// + /// Lyric dto. + /// + public class Lyric + { + /// + /// Gets or sets the start time (ticks). + /// + public double? Start { get; set; } + + /// + /// Gets or sets the text. + /// + public string Text { get; set; } = string.Empty; + } +} diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs new file mode 100644 index 0000000000..83a10701a2 --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; +using MediaBrowser.Controller.Net; +using Microsoft.AspNetCore.Mvc; + +namespace MediaBrowser.Controller.Lyrics +{ + /// + /// Item helper. + /// + public class LyricInfo + { + /// + /// Opens lyrics file, converts to a List of Lyrics, and returns it. + /// + /// Collection of all registered interfaces. + /// Requested Item. + /// Collection of Lyrics. + public static LyricResponse? GetLyricData(IEnumerable lyricProviders, BaseItem item) + { + + foreach (var provider in lyricProviders) + { + var result = provider.GetLyrics(item); + if (result is not null) + { + return result; + } + } + + return new LyricResponse + { + Lyrics = new List + { + new Lyric { Start = 0, Text = "Test" } + } + }; + } + + /// + /// Checks if requested item has a matching lyric file. + /// + /// The current lyricProvider interface. + /// Path of requested item. + /// True if item has a matching lyrics file. + public static string? GetLyricFilePath(ILyricsProvider lyricProvider, string itemPath) + { + if (lyricProvider.SupportedMediaTypes.Any()) + { + foreach (string lyricFileExtension in lyricProvider.SupportedMediaTypes) + { + string lyricFilePath = @Path.ChangeExtension(itemPath, lyricFileExtension); + if (System.IO.File.Exists(lyricFilePath)) + { + return lyricFilePath; + } + } + } + + return null; + } + + /// + /// Checks if requested item has a matching local lyric file. + /// + /// Collection of all registered interfaces. + /// Path of requested item. + /// True if item has a matching lyrics file; otherwise false. + public static bool HasLyricFile(IEnumerable lyricProviders, string itemPath) + { + foreach (var provider in lyricProviders) + { + if (GetLyricFilePath(provider, itemPath) is not null) + { + return true; + } + } + + return false; + } + } +} diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs new file mode 100644 index 0000000000..e312638ecc --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -0,0 +1,15 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Lyrics +{ + public class LyricResponse + { + public IDictionary MetaData { get; set; } + + public IEnumerable Lyrics { get; set; } + } +} diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index b40a0210ad..2a86fded22 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -76,7 +76,7 @@ namespace MediaBrowser.Model.Dto public bool? CanDownload { get; set; } - public bool? HasLocalLyricsFile { get; set; } + public bool? HasLyrics { get; set; } public bool? HasSubtitles { get; set; } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs new file mode 100644 index 0000000000..e30d563087 --- /dev/null +++ b/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Jellyfin.Api.Helpers; +using LrcParser.Model; +using LrcParser.Parser; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; + +namespace MediaBrowser.Providers.Lyric +{ + /// + /// LRC File Lyric Provider. + /// + public class LrcLyricsProvider : ILyricsProvider + { + /// + /// Initializes a new instance of the class. + /// + public LrcLyricsProvider() + { + SupportedMediaTypes = new Collection + { + "lrc" + }; + } + + /// + /// Gets a value indicating the File Extenstions this provider works with. + /// + public IEnumerable SupportedMediaTypes { get; } + + /// + /// Gets or Sets Data object generated by Process() method. + /// + /// Object with data if no error occured; otherwise, null. + public object? Data { get; set; } + + /// + /// Opens lyric file for [the specified item], and processes it for API return. + /// + /// The item to to process. + /// A representing the asynchronous operation. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); + + if (string.IsNullOrEmpty(lyricFilePath)) + { + return null; + } + + List lyricsList = new List(); + + List sortedLyricData = new List(); + var metaData = new ExpandoObject() as IDictionary; + string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); + + try + { + // Parse and sort lyric rows + LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); + Song lyricData = lrcLyricParser.Decode(lrcFileContent); + sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.ToArray()[0].Value).ToList(); + + // Parse metadata rows + var metaDataRows = lyricData.Lyrics + .Where(x => x.TimeTags.Count == 0) + .Where(x => x.Text.StartsWith("[", StringComparison.Ordinal) && x.Text.EndsWith("]", StringComparison.Ordinal)) + .Select(x => x.Text) + .ToList(); + + foreach (string metaDataRow in metaDataRows) + { + var metaDataField = metaDataRow.Split(":"); + + string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal); + string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal); + + metaData.Add(metaDataFieldName, metaDataFieldValue); + } + } + catch + { + return null; + } + + if (!sortedLyricData.Any()) + { + return null; + } + + for (int i = 0; i < sortedLyricData.Count; i++) + { + var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; + double ticks = Convert.ToDouble(timeData, new NumberFormatInfo()) * 10000; + lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); + } + + if (metaData.Any()) + { + return new LyricResponse { MetaData = metaData, Lyrics = lyricsList }; + } + + return new LyricResponse { Lyrics = lyricsList }; + } + } +} diff --git a/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs new file mode 100644 index 0000000000..2a5da4e4d8 --- /dev/null +++ b/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; +using Jellyfin.Api.Helpers; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; + +namespace MediaBrowser.Providers.Lyric +{ + /// + /// TXT File Lyric Provider. + /// + public class TxtLyricsProvider : ILyricsProvider + { + /// + /// Initializes a new instance of the class. + /// + public TxtLyricsProvider() + { + SupportedMediaTypes = new Collection + { + "lrc", "txt" + }; + } + + /// + /// Gets a value indicating the File Extenstions this provider works with. + /// + public IEnumerable SupportedMediaTypes { get; } + + /// + /// Gets or Sets Data object generated by Process() method. + /// + /// Object with data if no error occured; otherwise, null. + public object? Data { get; set; } + + /// + /// Opens lyric file for [the specified item], and processes it for API return. + /// + /// The item to to process. + /// A representing the asynchronous operation. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); + + if (string.IsNullOrEmpty(lyricFilePath)) + { + return null; + } + + List lyricsList = new List(); + + string lyricData = System.IO.File.ReadAllText(lyricFilePath); + + // Splitting on Environment.NewLine caused some new lines to be missed in Windows. + char[] newLinedelims = new[] { '\r', '\n' }; + string[] lyricTextLines = lyricData.Split(newLinedelims, StringSplitOptions.RemoveEmptyEntries); + + if (!lyricTextLines.Any()) + { + return null; + } + + foreach (string lyricLine in lyricTextLines) + { + lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Text = lyricLine }); + } + + return new LyricResponse { Lyrics = lyricsList }; + } + } +} diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 9864db9ac2..8514489f8a 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -6,6 +6,7 @@ + @@ -16,6 +17,7 @@ + -- cgit v1.2.3 From f4fd908f8d7ffcdea6acaf75928f6c2960ed6338 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Thu, 15 Sep 2022 20:49:25 -0400 Subject: Create ILyricManager --- Emby.Server.Implementations/ApplicationHost.cs | 4 +- Emby.Server.Implementations/Dto/DtoService.cs | 8 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 16 ++- MediaBrowser.Controller/Lyrics/ILyricManager.cs | 37 +++++++ MediaBrowser.Controller/Lyrics/ILyricProvider.cs | 29 ++++++ MediaBrowser.Controller/Lyrics/ILyricsProvider.cs | 24 ----- MediaBrowser.Controller/Lyrics/LyricInfo.cs | 50 +-------- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 119 ++++++++++++++++++++++ MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs | 112 -------------------- MediaBrowser.Providers/Lyric/LyricManager.cs | 97 ++++++++++++++++++ MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 82 +++++++++++++++ MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs | 74 -------------- 12 files changed, 378 insertions(+), 274 deletions(-) create mode 100644 MediaBrowser.Controller/Lyrics/ILyricManager.cs create mode 100644 MediaBrowser.Controller/Lyrics/ILyricProvider.cs delete mode 100644 MediaBrowser.Controller/Lyrics/ILyricsProvider.cs create mode 100644 MediaBrowser.Providers/Lyric/LrcLyricProvider.cs delete mode 100644 MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs create mode 100644 MediaBrowser.Providers/Lyric/LyricManager.cs create mode 100644 MediaBrowser.Providers/Lyric/TxtLyricProvider.cs delete mode 100644 MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 5487e5e023..409fc04b16 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -583,8 +583,6 @@ namespace Emby.Server.Implementations serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -603,6 +601,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); @@ -790,6 +789,7 @@ namespace Emby.Server.Implementations Resolve().AddParts(GetExports(), GetExports(), GetExports()); Resolve().AddParts(GetExports()); + Resolve().AddParts(GetExports()); Resolve().AddParts(GetExports()); diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index bed82a4bbb..6ab574c5c5 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -52,7 +52,7 @@ namespace Emby.Server.Implementations.Dto private readonly IMediaSourceManager _mediaSourceManager; private readonly Lazy _livetvManagerFactory; - private readonly IEnumerable _lyricProviders; + private readonly ILyricManager _lyricManager; public DtoService( ILogger logger, @@ -64,7 +64,7 @@ namespace Emby.Server.Implementations.Dto IApplicationHost appHost, IMediaSourceManager mediaSourceManager, Lazy livetvManagerFactory, - IEnumerable lyricProviders) + ILyricManager lyricManager) { _logger = logger; _libraryManager = libraryManager; @@ -75,7 +75,7 @@ namespace Emby.Server.Implementations.Dto _appHost = appHost; _mediaSourceManager = mediaSourceManager; _livetvManagerFactory = livetvManagerFactory; - _lyricProviders = lyricProviders; + _lyricManager = lyricManager; } private ILiveTvManager LivetvManager => _livetvManagerFactory.Value; @@ -147,7 +147,7 @@ namespace Emby.Server.Implementations.Dto } else if (item is Audio) { - dto.HasLyrics = MediaBrowser.Controller.Lyrics.LyricInfo.HasLyricFile(_lyricProviders, item.Path); + dto.HasLyrics = _lyricManager.HasLyricFile(item); } if (item is IItemByName itemByName diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 3da78c1169..1421ab444a 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -38,7 +38,7 @@ namespace Jellyfin.Api.Controllers private readonly IDtoService _dtoService; private readonly IUserViewManager _userViewManager; private readonly IFileSystem _fileSystem; - private readonly IEnumerable _lyricProviders; + private readonly ILyricManager _lyricManager; /// /// Initializes a new instance of the class. @@ -49,7 +49,7 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Collection of all registered interfaces. + /// Instance of the interface. public UserLibraryController( IUserManager userManager, IUserDataManager userDataRepository, @@ -57,7 +57,7 @@ namespace Jellyfin.Api.Controllers IDtoService dtoService, IUserViewManager userViewManager, IFileSystem fileSystem, - IEnumerable lyricProviders) + ILyricManager lyricManager) { _userManager = userManager; _userDataRepository = userDataRepository; @@ -65,7 +65,7 @@ namespace Jellyfin.Api.Controllers _dtoService = dtoService; _userViewManager = userViewManager; _fileSystem = fileSystem; - _lyricProviders = lyricProviders; + _lyricManager = lyricManager; } /// @@ -415,14 +415,10 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var result = MediaBrowser.Controller.Lyrics.LyricInfo.GetLyricData(_lyricProviders, item); + var result = _lyricManager.GetLyric(item); if (result is not null) { - provider.Process(item); - if (provider.HasData) - { - return Ok(provider.Data); - } + return Ok(result); } return NotFound(); diff --git a/MediaBrowser.Controller/Lyrics/ILyricManager.cs b/MediaBrowser.Controller/Lyrics/ILyricManager.cs new file mode 100644 index 0000000000..4fd11b9e02 --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/ILyricManager.cs @@ -0,0 +1,37 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Providers; + +namespace MediaBrowser.Controller.Lyrics +{ + public interface ILyricManager + { + /// + /// Adds the parts. + /// + /// The lyric providers. + void AddParts(IEnumerable lyricProviders); + + /// + /// Gets the lyrics. + /// + /// The media item. + /// Lyrics for passed item. + LyricResponse GetLyric(BaseItem item); + + /// + /// Checks if requested item has a matching local lyric file. + /// + /// The media item. + /// True if item has a matching lyrics file; otherwise false. + bool HasLyricFile(BaseItem item); + } +} diff --git a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs new file mode 100644 index 0000000000..691fed1fd2 --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Lyrics +{ + /// + /// Interface ILyricsProvider. + /// + public interface ILyricProvider + { + /// + /// Gets a value indicating the provider name. + /// + string Name { get; } + + /// + /// Gets the supported media types for this provider. + /// + /// The supported media types. + IEnumerable SupportedMediaTypes { get; } + + /// + /// Gets the lyrics. + /// + /// The item to to process. + /// Task{LyricResponse}. + LyricResponse? GetLyrics(BaseItem item); + } +} diff --git a/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs deleted file mode 100644 index bac32a398a..0000000000 --- a/MediaBrowser.Controller/Lyrics/ILyricsProvider.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System.Collections.Generic; -using MediaBrowser.Controller.Entities; - -namespace MediaBrowser.Controller.Lyrics -{ - /// - /// Interface ILyricsProvider. - /// - public interface ILyricsProvider - { - /// - /// Gets the supported media types for this provider. - /// - /// The supported media types. - IEnumerable SupportedMediaTypes { get; } - - /// - /// Gets the lyrics. - /// - /// The item to to process. - /// Task{LyricResponse}. - LyricResponse? GetLyrics(BaseItem item); - } -} diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index 83a10701a2..d44e14237a 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -13,42 +13,15 @@ namespace MediaBrowser.Controller.Lyrics /// /// Item helper. /// - public class LyricInfo + public static class LyricInfo { - /// - /// Opens lyrics file, converts to a List of Lyrics, and returns it. - /// - /// Collection of all registered interfaces. - /// Requested Item. - /// Collection of Lyrics. - public static LyricResponse? GetLyricData(IEnumerable lyricProviders, BaseItem item) - { - - foreach (var provider in lyricProviders) - { - var result = provider.GetLyrics(item); - if (result is not null) - { - return result; - } - } - - return new LyricResponse - { - Lyrics = new List - { - new Lyric { Start = 0, Text = "Test" } - } - }; - } - /// /// Checks if requested item has a matching lyric file. /// /// The current lyricProvider interface. /// Path of requested item. /// True if item has a matching lyrics file. - public static string? GetLyricFilePath(ILyricsProvider lyricProvider, string itemPath) + public static string? GetLyricFilePath(ILyricProvider lyricProvider, string itemPath) { if (lyricProvider.SupportedMediaTypes.Any()) { @@ -64,24 +37,5 @@ namespace MediaBrowser.Controller.Lyrics return null; } - - /// - /// Checks if requested item has a matching local lyric file. - /// - /// Collection of all registered interfaces. - /// Path of requested item. - /// True if item has a matching lyrics file; otherwise false. - public static bool HasLyricFile(IEnumerable lyricProviders, string itemPath) - { - foreach (var provider in lyricProviders) - { - if (GetLyricFilePath(provider, itemPath) is not null) - { - return true; - } - } - - return false; - } } } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs new file mode 100644 index 0000000000..18a85c93ac --- /dev/null +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Dynamic; +using System.Globalization; +using System.Linq; +using System.Threading.Tasks; +using Jellyfin.Api.Helpers; +using LrcParser.Model; +using LrcParser.Parser; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; + +namespace MediaBrowser.Providers.Lyric +{ + /// + /// LRC File Lyric Provider. + /// + public class LrcLyricProvider : ILyricProvider + { + /// + /// Initializes a new instance of the class. + /// + public LrcLyricProvider() + { + Name = "LrcLyricProvider"; + + SupportedMediaTypes = new Collection + { + "lrc" + }; + } + + /// + /// Gets a value indicating the provider name. + /// + public string Name { get; } + + /// + /// Gets a value indicating the File Extenstions this provider works with. + /// + public IEnumerable SupportedMediaTypes { get; } + + /// + /// Gets or Sets Data object generated by Process() method. + /// + /// Object with data if no error occured; otherwise, null. + public object? Data { get; set; } + + /// + /// Opens lyric file for [the specified item], and processes it for API return. + /// + /// The item to to process. + /// A representing the asynchronous operation. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); + + if (string.IsNullOrEmpty(lyricFilePath)) + { + return null; + } + + List lyricsList = new List(); + + List sortedLyricData = new List(); + var metaData = new ExpandoObject() as IDictionary; + string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); + + try + { + // Parse and sort lyric rows + LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); + Song lyricData = lrcLyricParser.Decode(lrcFileContent); + sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.ToArray()[0].Value).ToList(); + + // Parse metadata rows + var metaDataRows = lyricData.Lyrics + .Where(x => x.TimeTags.Count == 0) + .Where(x => x.Text.StartsWith("[", StringComparison.Ordinal) && x.Text.EndsWith("]", StringComparison.Ordinal)) + .Select(x => x.Text) + .ToList(); + + foreach (string metaDataRow in metaDataRows) + { + var metaDataField = metaDataRow.Split(":"); + + string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal); + string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal); + + metaData.Add(metaDataFieldName, metaDataFieldValue); + } + } + catch + { + return null; + } + + if (!sortedLyricData.Any()) + { + return null; + } + + for (int i = 0; i < sortedLyricData.Count; i++) + { + var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; + double ticks = Convert.ToDouble(timeData, new NumberFormatInfo()) * 10000; + lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); + } + + if (metaData.Any()) + { + return new LyricResponse { MetaData = metaData, Lyrics = lyricsList }; + } + + return new LyricResponse { Lyrics = lyricsList }; + } + } +} diff --git a/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs deleted file mode 100644 index e30d563087..0000000000 --- a/MediaBrowser.Providers/Lyric/LrcLyricsProvider.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Dynamic; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using Jellyfin.Api.Helpers; -using LrcParser.Model; -using LrcParser.Parser; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Lyrics; - -namespace MediaBrowser.Providers.Lyric -{ - /// - /// LRC File Lyric Provider. - /// - public class LrcLyricsProvider : ILyricsProvider - { - /// - /// Initializes a new instance of the class. - /// - public LrcLyricsProvider() - { - SupportedMediaTypes = new Collection - { - "lrc" - }; - } - - /// - /// Gets a value indicating the File Extenstions this provider works with. - /// - public IEnumerable SupportedMediaTypes { get; } - - /// - /// Gets or Sets Data object generated by Process() method. - /// - /// Object with data if no error occured; otherwise, null. - public object? Data { get; set; } - - /// - /// Opens lyric file for [the specified item], and processes it for API return. - /// - /// The item to to process. - /// A representing the asynchronous operation. - public LyricResponse? GetLyrics(BaseItem item) - { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - - if (string.IsNullOrEmpty(lyricFilePath)) - { - return null; - } - - List lyricsList = new List(); - - List sortedLyricData = new List(); - var metaData = new ExpandoObject() as IDictionary; - string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); - - try - { - // Parse and sort lyric rows - LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); - Song lyricData = lrcLyricParser.Decode(lrcFileContent); - sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.ToArray()[0].Value).ToList(); - - // Parse metadata rows - var metaDataRows = lyricData.Lyrics - .Where(x => x.TimeTags.Count == 0) - .Where(x => x.Text.StartsWith("[", StringComparison.Ordinal) && x.Text.EndsWith("]", StringComparison.Ordinal)) - .Select(x => x.Text) - .ToList(); - - foreach (string metaDataRow in metaDataRows) - { - var metaDataField = metaDataRow.Split(":"); - - string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal); - string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal); - - metaData.Add(metaDataFieldName, metaDataFieldValue); - } - } - catch - { - return null; - } - - if (!sortedLyricData.Any()) - { - return null; - } - - for (int i = 0; i < sortedLyricData.Count; i++) - { - var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; - double ticks = Convert.ToDouble(timeData, new NumberFormatInfo()) * 10000; - lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); - } - - if (metaData.Any()) - { - return new LyricResponse { MetaData = metaData, Lyrics = lyricsList }; - } - - return new LyricResponse { Lyrics = lyricsList }; - } - } -} diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs new file mode 100644 index 0000000000..48572c63e4 --- /dev/null +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -0,0 +1,97 @@ +#nullable disable + +#pragma warning disable CS1591 + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Extensions; +using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Lyrics; +using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Subtitles; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Providers; +using Microsoft.Extensions.Logging; + +namespace MediaBrowser.Providers.Lyric +{ + public class LyricManager : ILyricManager + { + private readonly ILogger _logger; + private readonly IFileSystem _fileSystem; + private readonly ILibraryMonitor _monitor; + private readonly IMediaSourceManager _mediaSourceManager; + private readonly ILocalizationManager _localization; + + private ILyricProvider[] _lyricProviders; + + public LyricManager( + ILogger logger, + IFileSystem fileSystem, + ILibraryMonitor monitor, + IMediaSourceManager mediaSourceManager, + ILocalizationManager localizationManager) + { + _logger = logger; + _fileSystem = fileSystem; + _monitor = monitor; + _mediaSourceManager = mediaSourceManager; + _localization = localizationManager; + } + + /// + public void AddParts(IEnumerable lyricProviders) + { + _lyricProviders = lyricProviders + .OrderBy(i => i is IHasOrder hasOrder ? hasOrder.Order : 0) + .ToArray(); + } + + /// + public LyricResponse GetLyric(BaseItem item) + { + foreach (ILyricProvider provider in _lyricProviders) + { + var results = provider.GetLyrics(item); + if (results is not null) + { + return results; + } + } + + return null; + } + + /// + public bool HasLyricFile(BaseItem item) + { + foreach (ILyricProvider provider in _lyricProviders) + { + if (item is null) + { + continue; + } + + if (LyricInfo.GetLyricFilePath(provider, item.Path) is not null) + { + return true; + } + } + + return false; + } + } +} diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs new file mode 100644 index 0000000000..939d8708b2 --- /dev/null +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Threading.Tasks; +using System.Xml.Linq; +using Jellyfin.Api.Helpers; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Lyrics; + +namespace MediaBrowser.Providers.Lyric +{ + /// + /// TXT File Lyric Provider. + /// + public class TxtLyricProvider : ILyricProvider + { + /// + /// Initializes a new instance of the class. + /// + public TxtLyricProvider() + { + Name = "TxtLyricProvider"; + + SupportedMediaTypes = new Collection + { + "lrc", "txt" + }; + } + + /// + /// Gets a value indicating the provider name. + /// + public string Name { get; } + + /// + /// Gets a value indicating the File Extenstions this provider works with. + /// + public IEnumerable SupportedMediaTypes { get; } + + /// + /// Gets or Sets Data object generated by Process() method. + /// + /// Object with data if no error occured; otherwise, null. + public object? Data { get; set; } + + /// + /// Opens lyric file for [the specified item], and processes it for API return. + /// + /// The item to to process. + /// A representing the asynchronous operation. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); + + if (string.IsNullOrEmpty(lyricFilePath)) + { + return null; + } + + List lyricsList = new List(); + + string lyricData = System.IO.File.ReadAllText(lyricFilePath); + + // Splitting on Environment.NewLine caused some new lines to be missed in Windows. + char[] newLinedelims = new[] { '\r', '\n' }; + string[] lyricTextLines = lyricData.Split(newLinedelims, StringSplitOptions.RemoveEmptyEntries); + + if (!lyricTextLines.Any()) + { + return null; + } + + foreach (string lyricLine in lyricTextLines) + { + lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Text = lyricLine }); + } + + return new LyricResponse { Lyrics = lyricsList }; + } + } +} diff --git a/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs deleted file mode 100644 index 2a5da4e4d8..0000000000 --- a/MediaBrowser.Providers/Lyric/TxtLyricsProvider.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Threading.Tasks; -using Jellyfin.Api.Helpers; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Lyrics; - -namespace MediaBrowser.Providers.Lyric -{ - /// - /// TXT File Lyric Provider. - /// - public class TxtLyricsProvider : ILyricsProvider - { - /// - /// Initializes a new instance of the class. - /// - public TxtLyricsProvider() - { - SupportedMediaTypes = new Collection - { - "lrc", "txt" - }; - } - - /// - /// Gets a value indicating the File Extenstions this provider works with. - /// - public IEnumerable SupportedMediaTypes { get; } - - /// - /// Gets or Sets Data object generated by Process() method. - /// - /// Object with data if no error occured; otherwise, null. - public object? Data { get; set; } - - /// - /// Opens lyric file for [the specified item], and processes it for API return. - /// - /// The item to to process. - /// A representing the asynchronous operation. - public LyricResponse? GetLyrics(BaseItem item) - { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - - if (string.IsNullOrEmpty(lyricFilePath)) - { - return null; - } - - List lyricsList = new List(); - - string lyricData = System.IO.File.ReadAllText(lyricFilePath); - - // Splitting on Environment.NewLine caused some new lines to be missed in Windows. - char[] newLinedelims = new[] { '\r', '\n' }; - string[] lyricTextLines = lyricData.Split(newLinedelims, StringSplitOptions.RemoveEmptyEntries); - - if (!lyricTextLines.Any()) - { - return null; - } - - foreach (string lyricLine in lyricTextLines) - { - lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Text = lyricLine }); - } - - return new LyricResponse { Lyrics = lyricsList }; - } - } -} -- cgit v1.2.3 From f740d1b9f00d91bfad970f56abed67d8c8c16c9c Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Fri, 16 Sep 2022 20:52:40 -0400 Subject: Remove use of AddParts. Cleanup use of Lyric vs Lyrics. --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 6 +++--- Jellyfin.Server/CoreAppHost.cs | 6 ++++++ MediaBrowser.Controller/Lyrics/ILyricManager.cs | 18 ++-------------- MediaBrowser.Controller/Lyrics/ILyricProvider.cs | 4 ++-- MediaBrowser.Controller/Lyrics/Lyric.cs | 4 ++-- MediaBrowser.Controller/Lyrics/LyricInfo.cs | 8 +++---- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 9 ++++++++ MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 24 ++++++++------------- MediaBrowser.Providers/Lyric/LyricManager.cs | 16 +++++--------- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 26 +++++++++-------------- 11 files changed, 53 insertions(+), 70 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 409fc04b16..5edc25952d 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -789,7 +789,7 @@ namespace Emby.Server.Implementations Resolve().AddParts(GetExports(), GetExports(), GetExports()); Resolve().AddParts(GetExports()); - Resolve().AddParts(GetExports()); + //Resolve().AddParts(GetExports()); Resolve().AddParts(GetExports()); diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 1421ab444a..2cb2e93284 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -394,10 +394,10 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Lyrics returned. /// Something went wrong. No Lyrics will be returned. - /// An containing the intros to play. + /// An containing the item's lyrics. [HttpGet("Users/{userId}/Items/{itemId}/Lyrics")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetLyrics([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) + public ActionResult> GetLyrics([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -415,7 +415,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var result = _lyricManager.GetLyric(item); + var result = _lyricManager.GetLyrics(item); if (result is not null) { return Ok(result); diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 67e50b92d9..984711dc2d 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -19,6 +19,7 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Security; using MediaBrowser.Model.Activity; @@ -95,6 +96,11 @@ namespace Jellyfin.Server serviceCollection.AddScoped(); + foreach (var type in GetExportTypes()) + { + serviceCollection.AddSingleton(typeof(ILyricProvider), type); + } + base.RegisterServices(serviceCollection); } diff --git a/MediaBrowser.Controller/Lyrics/ILyricManager.cs b/MediaBrowser.Controller/Lyrics/ILyricManager.cs index 4fd11b9e02..c0f78d177d 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricManager.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricManager.cs @@ -1,37 +1,23 @@ -#nullable disable - #pragma warning disable CS1591 -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Lyrics { public interface ILyricManager { - /// - /// Adds the parts. - /// - /// The lyric providers. - void AddParts(IEnumerable lyricProviders); - /// /// Gets the lyrics. /// /// The media item. /// Lyrics for passed item. - LyricResponse GetLyric(BaseItem item); + LyricResponse GetLyrics(BaseItem item); /// /// Checks if requested item has a matching local lyric file. /// /// The media item. - /// True if item has a matching lyrics file; otherwise false. + /// True if item has a matching lyric file; otherwise false. bool HasLyricFile(BaseItem item); } } diff --git a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs index 691fed1fd2..5e677ab26f 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs @@ -22,8 +22,8 @@ namespace MediaBrowser.Controller.Lyrics /// /// Gets the lyrics. /// - /// The item to to process. - /// Task{LyricResponse}. + /// The media item. + /// If found, returns lyrics for passed item; otherwise, null. LyricResponse? GetLyrics(BaseItem item); } } diff --git a/MediaBrowser.Controller/Lyrics/Lyric.cs b/MediaBrowser.Controller/Lyrics/Lyric.cs index d44546dd39..56a0a8a72d 100644 --- a/MediaBrowser.Controller/Lyrics/Lyric.cs +++ b/MediaBrowser.Controller/Lyrics/Lyric.cs @@ -1,12 +1,12 @@ namespace MediaBrowser.Controller.Lyrics { /// - /// Lyric dto. + /// Lyric model. /// public class Lyric { /// - /// Gets or sets the start time (ticks). + /// Gets or sets the start time in ticks. /// public double? Start { get; set; } diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index d44e14237a..018f296b1a 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -11,16 +11,16 @@ using Microsoft.AspNetCore.Mvc; namespace MediaBrowser.Controller.Lyrics { /// - /// Item helper. + /// Lyric helper methods. /// public static class LyricInfo { /// - /// Checks if requested item has a matching lyric file. + /// Gets matching lyric file for a requested item. /// - /// The current lyricProvider interface. + /// The lyricProvider interface to use. /// Path of requested item. - /// True if item has a matching lyrics file. + /// Lyric file path if passed lyric provider's supported media type is found; otherwise, null. public static string? GetLyricFilePath(ILyricProvider lyricProvider, string itemPath) { if (lyricProvider.SupportedMediaTypes.Any()) diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index e312638ecc..498eb873c7 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -6,10 +6,19 @@ using System.Collections.Generic; namespace MediaBrowser.Controller.Lyrics { + /// + /// LyricResponse model. + /// public class LyricResponse { + /// + /// Gets or sets MetaData. + /// public IDictionary MetaData { get; set; } + /// + /// Gets or sets Lyrics. + /// public IEnumerable Lyrics { get; set; } } } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 18a85c93ac..10db10ac6f 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -14,7 +14,7 @@ using MediaBrowser.Controller.Lyrics; namespace MediaBrowser.Providers.Lyric { /// - /// LRC File Lyric Provider. + /// LRC Lyric Provider. /// public class LrcLyricProvider : ILyricProvider { @@ -37,21 +37,15 @@ namespace MediaBrowser.Providers.Lyric public string Name { get; } /// - /// Gets a value indicating the File Extenstions this provider works with. + /// Gets a value indicating the File Extenstions this provider supports. /// public IEnumerable SupportedMediaTypes { get; } /// - /// Gets or Sets Data object generated by Process() method. - /// - /// Object with data if no error occured; otherwise, null. - public object? Data { get; set; } - - /// - /// Opens lyric file for [the specified item], and processes it for API return. + /// Opens lyric file for the requested item, and processes it for API return. /// /// The item to to process. - /// A representing the asynchronous operation. + /// If provider can determine lyrics, returns a with or without metadata; otherwise, null. public LyricResponse? GetLyrics(BaseItem item) { string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); @@ -61,9 +55,9 @@ namespace MediaBrowser.Providers.Lyric return null; } - List lyricsList = new List(); - + List lyricList = new List(); List sortedLyricData = new List(); + var metaData = new ExpandoObject() as IDictionary; string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); @@ -105,15 +99,15 @@ namespace MediaBrowser.Providers.Lyric { var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; double ticks = Convert.ToDouble(timeData, new NumberFormatInfo()) * 10000; - lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); + lyricList.Add(new Controller.Lyrics.Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); } if (metaData.Any()) { - return new LyricResponse { MetaData = metaData, Lyrics = lyricsList }; + return new LyricResponse { MetaData = metaData, Lyrics = lyricList }; } - return new LyricResponse { Lyrics = lyricsList }; + return new LyricResponse { Lyrics = lyricList }; } } } diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs index 48572c63e4..698da46867 100644 --- a/MediaBrowser.Providers/Lyric/LyricManager.cs +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -36,32 +36,26 @@ namespace MediaBrowser.Providers.Lyric private readonly IMediaSourceManager _mediaSourceManager; private readonly ILocalizationManager _localization; - private ILyricProvider[] _lyricProviders; + private IEnumerable _lyricProviders; public LyricManager( ILogger logger, IFileSystem fileSystem, ILibraryMonitor monitor, IMediaSourceManager mediaSourceManager, - ILocalizationManager localizationManager) + ILocalizationManager localizationManager, + IEnumerable lyricProviders) { _logger = logger; _fileSystem = fileSystem; _monitor = monitor; _mediaSourceManager = mediaSourceManager; _localization = localizationManager; + _lyricProviders = lyricProviders; } /// - public void AddParts(IEnumerable lyricProviders) - { - _lyricProviders = lyricProviders - .OrderBy(i => i is IHasOrder hasOrder ? hasOrder.Order : 0) - .ToArray(); - } - - /// - public LyricResponse GetLyric(BaseItem item) + public LyricResponse GetLyrics(BaseItem item) { foreach (ILyricProvider provider in _lyricProviders) { diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index 939d8708b2..aa222ed97b 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -11,7 +11,7 @@ using MediaBrowser.Controller.Lyrics; namespace MediaBrowser.Providers.Lyric { /// - /// TXT File Lyric Provider. + /// TXT Lyric Provider. /// public class TxtLyricProvider : ILyricProvider { @@ -34,21 +34,15 @@ namespace MediaBrowser.Providers.Lyric public string Name { get; } /// - /// Gets a value indicating the File Extenstions this provider works with. + /// Gets a value indicating the File Extenstions this provider supports. /// public IEnumerable SupportedMediaTypes { get; } /// - /// Gets or Sets Data object generated by Process() method. - /// - /// Object with data if no error occured; otherwise, null. - public object? Data { get; set; } - - /// - /// Opens lyric file for [the specified item], and processes it for API return. + /// Opens lyric file for the requested item, and processes it for API return. /// /// The item to to process. - /// A representing the asynchronous operation. + /// If provider can determine lyrics, returns a ; otherwise, null. public LyricResponse? GetLyrics(BaseItem item) { string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); @@ -58,25 +52,25 @@ namespace MediaBrowser.Providers.Lyric return null; } - List lyricsList = new List(); + List lyricList = new List(); string lyricData = System.IO.File.ReadAllText(lyricFilePath); // Splitting on Environment.NewLine caused some new lines to be missed in Windows. - char[] newLinedelims = new[] { '\r', '\n' }; - string[] lyricTextLines = lyricData.Split(newLinedelims, StringSplitOptions.RemoveEmptyEntries); + char[] newLineDelims = new[] { '\r', '\n' }; + string[] lyricTextLines = lyricData.Split(newLineDelims, StringSplitOptions.RemoveEmptyEntries); if (!lyricTextLines.Any()) { return null; } - foreach (string lyricLine in lyricTextLines) + foreach (string lyricTextLine in lyricTextLines) { - lyricsList.Add(new MediaBrowser.Controller.Lyrics.Lyric { Text = lyricLine }); + lyricList.Add(new Controller.Lyrics.Lyric { Text = lyricTextLine }); } - return new LyricResponse { Lyrics = lyricsList }; + return new LyricResponse { Lyrics = lyricList }; } } } -- cgit v1.2.3 From 823e2ec029d8708b71452afc7442524823d82acb Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sat, 17 Sep 2022 09:22:07 -0400 Subject: Removing unused lines --- MediaBrowser.Controller/Lyrics/LyricInfo.cs | 7 ------- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 2 -- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 2 -- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 3 --- 4 files changed, 14 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index 018f296b1a..ae831b4d23 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -1,12 +1,5 @@ -using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading.Tasks; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Lyrics; -using MediaBrowser.Controller.Net; -using Microsoft.AspNetCore.Mvc; namespace MediaBrowser.Controller.Lyrics { diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 498eb873c7..59ee5c7f2c 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -1,7 +1,5 @@ #nullable disable -#pragma warning disable CS1591 - using System.Collections.Generic; namespace MediaBrowser.Controller.Lyrics diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 10db10ac6f..ea42d75255 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -4,8 +4,6 @@ using System.Collections.ObjectModel; using System.Dynamic; using System.Globalization; using System.Linq; -using System.Threading.Tasks; -using Jellyfin.Api.Helpers; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index aa222ed97b..8a51d7277c 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -2,9 +2,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Threading.Tasks; -using System.Xml.Linq; -using Jellyfin.Api.Helpers; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -- cgit v1.2.3 From 7d886116fd3b617cae6884a33b8b545358fa6289 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sat, 17 Sep 2022 10:42:48 -0400 Subject: Var type refinements --- MediaBrowser.Controller/Lyrics/Lyric.cs | 2 +- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 4 ++-- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 13 +++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/Lyric.cs b/MediaBrowser.Controller/Lyrics/Lyric.cs index 56a0a8a72d..35cdabbb9b 100644 --- a/MediaBrowser.Controller/Lyrics/Lyric.cs +++ b/MediaBrowser.Controller/Lyrics/Lyric.cs @@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Lyrics /// /// Gets or sets the start time in ticks. /// - public double? Start { get; set; } + public long? Start { get; set; } /// /// Gets or sets the text. diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 59ee5c7f2c..796ca3bc36 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -10,9 +10,9 @@ namespace MediaBrowser.Controller.Lyrics public class LyricResponse { /// - /// Gets or sets MetaData. + /// Gets or sets Metadata. /// - public IDictionary MetaData { get; set; } + public IDictionary Metadata { get; set; } /// /// Gets or sets Lyrics. diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index ea42d75255..59a172cee2 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -8,6 +8,7 @@ using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; +using Swashbuckle.AspNetCore.SwaggerGen; namespace MediaBrowser.Providers.Lyric { @@ -56,7 +57,7 @@ namespace MediaBrowser.Providers.Lyric List lyricList = new List(); List sortedLyricData = new List(); - var metaData = new ExpandoObject() as IDictionary; + IDictionary metaData = new Dictionary(); string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); try @@ -77,8 +78,8 @@ namespace MediaBrowser.Providers.Lyric { var metaDataField = metaDataRow.Split(":"); - string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal); - string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal); + string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal).Trim(); + string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal).Trim(); metaData.Add(metaDataFieldName, metaDataFieldValue); } @@ -96,13 +97,13 @@ namespace MediaBrowser.Providers.Lyric for (int i = 0; i < sortedLyricData.Count; i++) { var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; - double ticks = Convert.ToDouble(timeData, new NumberFormatInfo()) * 10000; - lyricList.Add(new Controller.Lyrics.Lyric { Start = Math.Ceiling(ticks), Text = sortedLyricData[i].Text }); + long ticks = Convert.ToInt64(timeData, new NumberFormatInfo()) * 10000; + lyricList.Add(new Controller.Lyrics.Lyric { Start = ticks, Text = sortedLyricData[i].Text }); } if (metaData.Any()) { - return new LyricResponse { MetaData = metaData, Lyrics = lyricList }; + return new LyricResponse { Metadata = metaData, Lyrics = lyricList }; } return new LyricResponse { Lyrics = lyricList }; -- cgit v1.2.3 From c65819221d9a84ec0ae69a243fdcb17bce7aa65f Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sat, 17 Sep 2022 17:37:38 -0400 Subject: Code cleanups. Remove pragma commands --- MediaBrowser.Controller/Lyrics/ILyricManager.cs | 36 ++--- MediaBrowser.Controller/Lyrics/ILyricProvider.cs | 39 +++--- MediaBrowser.Controller/Lyrics/Lyric.cs | 34 +++-- MediaBrowser.Controller/Lyrics/LyricInfo.cs | 39 +++--- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 27 ++-- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 152 ++++++++++----------- MediaBrowser.Providers/Lyric/LyricManager.cs | 72 +++++----- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 86 +++++------- .../MediaBrowser.Providers.csproj | 1 - 9 files changed, 231 insertions(+), 255 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/ILyricManager.cs b/MediaBrowser.Controller/Lyrics/ILyricManager.cs index c0f78d177d..dad0250f6b 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricManager.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricManager.cs @@ -1,23 +1,23 @@ -#pragma warning disable CS1591 - using MediaBrowser.Controller.Entities; -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Interface ILyricManager. +/// +public interface ILyricManager { - public interface ILyricManager - { - /// - /// Gets the lyrics. - /// - /// The media item. - /// Lyrics for passed item. - LyricResponse GetLyrics(BaseItem item); + /// + /// Gets the lyrics. + /// + /// The media item. + /// Lyrics for passed item. + LyricResponse GetLyrics(BaseItem item); - /// - /// Checks if requested item has a matching local lyric file. - /// - /// The media item. - /// True if item has a matching lyric file; otherwise false. - bool HasLyricFile(BaseItem item); - } + /// + /// Checks if requested item has a matching local lyric file. + /// + /// The media item. + /// True if item has a matching lyric file; otherwise false. + bool HasLyricFile(BaseItem item); } diff --git a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs index 5e677ab26f..1b52de255f 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs @@ -1,29 +1,28 @@ using System.Collections.Generic; using MediaBrowser.Controller.Entities; -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Interface ILyricsProvider. +/// +public interface ILyricProvider { /// - /// Interface ILyricsProvider. + /// Gets a value indicating the provider name. /// - public interface ILyricProvider - { - /// - /// Gets a value indicating the provider name. - /// - string Name { get; } + string Name { get; } - /// - /// Gets the supported media types for this provider. - /// - /// The supported media types. - IEnumerable SupportedMediaTypes { get; } + /// + /// Gets the supported media types for this provider. + /// + /// The supported media types. + IEnumerable SupportedMediaTypes { get; } - /// - /// Gets the lyrics. - /// - /// The media item. - /// If found, returns lyrics for passed item; otherwise, null. - LyricResponse? GetLyrics(BaseItem item); - } + /// + /// Gets the lyrics. + /// + /// The media item. + /// If found, returns lyrics for passed item; otherwise, null. + LyricResponse? GetLyrics(BaseItem item); } diff --git a/MediaBrowser.Controller/Lyrics/Lyric.cs b/MediaBrowser.Controller/Lyrics/Lyric.cs index 35cdabbb9b..f39fbb0221 100644 --- a/MediaBrowser.Controller/Lyrics/Lyric.cs +++ b/MediaBrowser.Controller/Lyrics/Lyric.cs @@ -1,18 +1,28 @@ -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Lyric model. +/// +public class Lyric { /// - /// Lyric model. + /// Initializes a new instance of the class. /// - public class Lyric + /// The lyric start time in ticks. + /// The lyric text. + public Lyric(string text, long? start = null) { - /// - /// Gets or sets the start time in ticks. - /// - public long? Start { get; set; } - - /// - /// Gets or sets the text. - /// - public string Text { get; set; } = string.Empty; + Start = start; + Text = text; } + + /// + /// Gets the start time in ticks. + /// + public long? Start { get; } + + /// + /// Gets the text. + /// + public string Text { get; } } diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index ae831b4d23..61e205b6cc 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -1,34 +1,29 @@ using System.IO; -using System.Linq; -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Lyric helper methods. +/// +public static class LyricInfo { /// - /// Lyric helper methods. + /// Gets matching lyric file for a requested item. /// - public static class LyricInfo + /// The lyricProvider interface to use. + /// Path of requested item. + /// Lyric file path if passed lyric provider's supported media type is found; otherwise, null. + public static string? GetLyricFilePath(ILyricProvider lyricProvider, string itemPath) { - /// - /// Gets matching lyric file for a requested item. - /// - /// The lyricProvider interface to use. - /// Path of requested item. - /// Lyric file path if passed lyric provider's supported media type is found; otherwise, null. - public static string? GetLyricFilePath(ILyricProvider lyricProvider, string itemPath) + foreach (string lyricFileExtension in lyricProvider.SupportedMediaTypes) { - if (lyricProvider.SupportedMediaTypes.Any()) + var lyricFilePath = Path.ChangeExtension(itemPath, lyricFileExtension); + if (File.Exists(lyricFilePath)) { - foreach (string lyricFileExtension in lyricProvider.SupportedMediaTypes) - { - string lyricFilePath = @Path.ChangeExtension(itemPath, lyricFileExtension); - if (System.IO.File.Exists(lyricFilePath)) - { - return lyricFilePath; - } - } + return lyricFilePath; } - - return null; } + + return null; } } diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 796ca3bc36..e18cb1101e 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -1,22 +1,19 @@ -#nullable disable - using System.Collections.Generic; -namespace MediaBrowser.Controller.Lyrics +namespace MediaBrowser.Controller.Lyrics; + +/// +/// LyricResponse model. +/// +public class LyricResponse { /// - /// LyricResponse model. + /// Gets or sets Metadata. /// - public class LyricResponse - { - /// - /// Gets or sets Metadata. - /// - public IDictionary Metadata { get; set; } + public IDictionary? Metadata { get; set; } - /// - /// Gets or sets Lyrics. - /// - public IEnumerable Lyrics { get; set; } - } + /// + /// Gets or sets Lyrics. + /// + public IEnumerable? Lyrics { get; set; } } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 59a172cee2..9bacfc2964 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -1,112 +1,102 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Dynamic; using System.Globalization; using System.Linq; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -using Swashbuckle.AspNetCore.SwaggerGen; -namespace MediaBrowser.Providers.Lyric +namespace MediaBrowser.Providers.Lyric; + +/// +/// LRC Lyric Provider. +/// +public class LrcLyricProvider : ILyricProvider { - /// - /// LRC Lyric Provider. - /// - public class LrcLyricProvider : ILyricProvider - { - /// - /// Initializes a new instance of the class. - /// - public LrcLyricProvider() - { - Name = "LrcLyricProvider"; + /// + public string Name { get; } = "LrcLyricProvider"; - SupportedMediaTypes = new Collection + /// + public IEnumerable SupportedMediaTypes + { + get => new Collection { "lrc" }; - } + } - /// - /// Gets a value indicating the provider name. - /// - public string Name { get; } - - /// - /// Gets a value indicating the File Extenstions this provider supports. - /// - public IEnumerable SupportedMediaTypes { get; } - - /// - /// Opens lyric file for the requested item, and processes it for API return. - /// - /// The item to to process. - /// If provider can determine lyrics, returns a with or without metadata; otherwise, null. - public LyricResponse? GetLyrics(BaseItem item) - { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); + /// + /// Opens lyric file for the requested item, and processes it for API return. + /// + /// The item to to process. + /// If provider can determine lyrics, returns a with or without metadata; otherwise, null. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - if (string.IsNullOrEmpty(lyricFilePath)) - { - return null; - } + if (string.IsNullOrEmpty(lyricFilePath)) + { + return null; + } - List lyricList = new List(); - List sortedLyricData = new List(); + List lyricList = new List(); + List sortedLyricData = new List(); - IDictionary metaData = new Dictionary(); - string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); + IDictionary metaData = new Dictionary(); + string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); - try + try + { + // Parse and sort lyric rows + LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); + Song lyricData = lrcLyricParser.Decode(lrcFileContent); + sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.First().Value).ToList(); + + // Parse metadata rows + var metaDataRows = lyricData.Lyrics + .Where(x => x.TimeTags.Count == 0) + .Where(x => x.Text.StartsWith('[') && x.Text.EndsWith(']')) + .Select(x => x.Text) + .ToList(); + + foreach (string metaDataRow in metaDataRows) { - // Parse and sort lyric rows - LyricParser lrcLyricParser = new LrcParser.Parser.Lrc.LrcParser(); - Song lyricData = lrcLyricParser.Decode(lrcFileContent); - sortedLyricData = lyricData.Lyrics.Where(x => x.TimeTags.Count > 0).OrderBy(x => x.TimeTags.ToArray()[0].Value).ToList(); - - // Parse metadata rows - var metaDataRows = lyricData.Lyrics - .Where(x => x.TimeTags.Count == 0) - .Where(x => x.Text.StartsWith("[", StringComparison.Ordinal) && x.Text.EndsWith("]", StringComparison.Ordinal)) - .Select(x => x.Text) - .ToList(); - - foreach (string metaDataRow in metaDataRows) + var metaDataField = metaDataRow.Split(':'); + if (metaDataField.Length != 2) { - var metaDataField = metaDataRow.Split(":"); - - string metaDataFieldName = metaDataField[0].Replace("[", string.Empty, StringComparison.Ordinal).Trim(); - string metaDataFieldValue = metaDataField[1].Replace("]", string.Empty, StringComparison.Ordinal).Trim(); - - metaData.Add(metaDataFieldName, metaDataFieldValue); + continue; } - } - catch - { - return null; - } - if (!sortedLyricData.Any()) - { - return null; - } + string metaDataFieldName = metaDataField[0][1..].Trim(); + string metaDataFieldValue = metaDataField[1][..^1].Trim(); - for (int i = 0; i < sortedLyricData.Count; i++) - { - var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; - long ticks = Convert.ToInt64(timeData, new NumberFormatInfo()) * 10000; - lyricList.Add(new Controller.Lyrics.Lyric { Start = ticks, Text = sortedLyricData[i].Text }); + metaData.Add(metaDataFieldName, metaDataFieldValue); } + } + catch + { + return null; + } - if (metaData.Any()) - { - return new LyricResponse { Metadata = metaData, Lyrics = lyricList }; - } + if (sortedLyricData.Count == 0) + { + return null; + } - return new LyricResponse { Lyrics = lyricList }; + for (int i = 0; i < sortedLyricData.Count; i++) + { + var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; + long ticks = TimeSpan.FromMilliseconds((double)timeData).Ticks; + lyricList.Add(new Controller.Lyrics.Lyric(sortedLyricData[i].Text, ticks)); } + + if (metaData.Any()) + { + return new LyricResponse { Metadata = metaData, Lyrics = lyricList }; + } + + return new LyricResponse { Lyrics = lyricList }; } } diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs index f5560b0542..06f913d079 100644 --- a/MediaBrowser.Providers/Lyric/LyricManager.cs +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -1,55 +1,57 @@ -#nullable disable - -#pragma warning disable CS1591 - using System.Collections.Generic; using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -namespace MediaBrowser.Providers.Lyric +namespace MediaBrowser.Providers.Lyric; + +/// +/// Lyric Manager. +/// +public class LyricManager : ILyricManager { - public class LyricManager : ILyricManager - { - private readonly ILyricProvider[] _lyricProviders; + private readonly ILyricProvider[] _lyricProviders; - public LyricManager(IEnumerable lyricProviders) - { - _lyricProviders = lyricProviders.ToArray(); - } + /// + /// Initializes a new instance of the class. + /// + /// All found lyricProviders. + public LyricManager(IEnumerable lyricProviders) + { + _lyricProviders = lyricProviders.ToArray(); + } - /// - public LyricResponse GetLyrics(BaseItem item) + /// + public LyricResponse GetLyrics(BaseItem item) + { + foreach (ILyricProvider provider in _lyricProviders) { - foreach (ILyricProvider provider in _lyricProviders) + var results = provider.GetLyrics(item); + if (results is not null) { - var results = provider.GetLyrics(item); - if (results is not null) - { - return results; - } + return results; } - - return null; } - /// - public bool HasLyricFile(BaseItem item) + return null; + } + + /// + public bool HasLyricFile(BaseItem item) + { + foreach (ILyricProvider provider in _lyricProviders) { - foreach (ILyricProvider provider in _lyricProviders) + if (item is null) { - if (item is null) - { - continue; - } - - if (LyricInfo.GetLyricFilePath(provider, item.Path) is not null) - { - return true; - } + continue; } - return false; + if (LyricInfo.GetLyricFilePath(provider, item.Path) is not null) + { + return true; + } } + + return false; } } diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index 8a51d7277c..d417c85981 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -5,69 +5,53 @@ using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -namespace MediaBrowser.Providers.Lyric +namespace MediaBrowser.Providers.Lyric; + +/// +/// TXT Lyric Provider. +/// +public class TxtLyricProvider : ILyricProvider { - /// - /// TXT Lyric Provider. - /// - public class TxtLyricProvider : ILyricProvider - { - /// - /// Initializes a new instance of the class. - /// - public TxtLyricProvider() - { - Name = "TxtLyricProvider"; + /// + public string Name { get; } = "TxtLyricProvider"; - SupportedMediaTypes = new Collection + /// + public IEnumerable SupportedMediaTypes + { + get => new Collection { "lrc", "txt" }; - } - - /// - /// Gets a value indicating the provider name. - /// - public string Name { get; } + } - /// - /// Gets a value indicating the File Extenstions this provider supports. - /// - public IEnumerable SupportedMediaTypes { get; } + /// + /// Opens lyric file for the requested item, and processes it for API return. + /// + /// The item to to process. + /// If provider can determine lyrics, returns a ; otherwise, null. + public LyricResponse? GetLyrics(BaseItem item) + { + string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - /// - /// Opens lyric file for the requested item, and processes it for API return. - /// - /// The item to to process. - /// If provider can determine lyrics, returns a ; otherwise, null. - public LyricResponse? GetLyrics(BaseItem item) + if (string.IsNullOrEmpty(lyricFilePath)) { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); - - if (string.IsNullOrEmpty(lyricFilePath)) - { - return null; - } - - List lyricList = new List(); - - string lyricData = System.IO.File.ReadAllText(lyricFilePath); + return null; + } - // Splitting on Environment.NewLine caused some new lines to be missed in Windows. - char[] newLineDelims = new[] { '\r', '\n' }; - string[] lyricTextLines = lyricData.Split(newLineDelims, StringSplitOptions.RemoveEmptyEntries); + string[] lyricTextLines = System.IO.File.ReadAllLines(lyricFilePath); - if (!lyricTextLines.Any()) - { - return null; - } + List lyricList = new List(); - foreach (string lyricTextLine in lyricTextLines) - { - lyricList.Add(new Controller.Lyrics.Lyric { Text = lyricTextLine }); - } + if (lyricTextLines.Length == 0) + { + return null; + } - return new LyricResponse { Lyrics = lyricList }; + foreach (string lyricTextLine in lyricTextLines) + { + lyricList.Add(new Controller.Lyrics.Lyric(lyricTextLine)); } + + return new LyricResponse { Lyrics = lyricList }; } } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 8514489f8a..e12776ba05 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -6,7 +6,6 @@ - -- cgit v1.2.3 From 64b013b121f472d2658e5f2b3a672c4c4ced342d Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sat, 17 Sep 2022 17:48:27 -0400 Subject: Resolve Azure build issues --- MediaBrowser.Controller/Lyrics/ILyricManager.cs | 2 +- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 7 ++++++- MediaBrowser.Providers/Lyric/LyricManager.cs | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/ILyricManager.cs b/MediaBrowser.Controller/Lyrics/ILyricManager.cs index dad0250f6b..5920bcc628 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricManager.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricManager.cs @@ -12,7 +12,7 @@ public interface ILyricManager /// /// The media item. /// Lyrics for passed item. - LyricResponse GetLyrics(BaseItem item); + LyricResponse? GetLyrics(BaseItem item); /// /// Checks if requested item has a matching local lyric file. diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 9bacfc2964..db87d92368 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -87,7 +87,12 @@ public class LrcLyricProvider : ILyricProvider for (int i = 0; i < sortedLyricData.Count; i++) { - var timeData = sortedLyricData[i].TimeTags.ToArray()[0].Value; + var timeData = sortedLyricData[i].TimeTags.First().Value; + if (timeData is null) + { + continue; + } + long ticks = TimeSpan.FromMilliseconds((double)timeData).Ticks; lyricList.Add(new Controller.Lyrics.Lyric(sortedLyricData[i].Text, ticks)); } diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs index 06f913d079..0de008db7f 100644 --- a/MediaBrowser.Providers/Lyric/LyricManager.cs +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -22,7 +22,7 @@ public class LyricManager : ILyricManager } /// - public LyricResponse GetLyrics(BaseItem item) + public LyricResponse? GetLyrics(BaseItem item) { foreach (ILyricProvider provider in _lyricProviders) { -- cgit v1.2.3 From 0b86630be7737e28555f0132322ecd02915284c5 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sat, 17 Sep 2022 19:47:29 -0400 Subject: Use model properties for LRC metadata --- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 2 +- MediaBrowser.Controller/Lyrics/Metadata.cs | 54 ++++++++++++++++++++++ .../MediaBrowser.Controller.csproj | 1 + MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 11 +++-- 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 MediaBrowser.Controller/Lyrics/Metadata.cs (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index e18cb1101e..adc13050ee 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -10,7 +10,7 @@ public class LyricResponse /// /// Gets or sets Metadata. /// - public IDictionary? Metadata { get; set; } + public Metadata? Metadata { get; set; } /// /// Gets or sets Lyrics. diff --git a/MediaBrowser.Controller/Lyrics/Metadata.cs b/MediaBrowser.Controller/Lyrics/Metadata.cs new file mode 100644 index 0000000000..114b56777a --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/Metadata.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Metadata model. +/// +public class Metadata +{ + /// + /// Gets or sets Artist - [ar:The song artist]. + /// + public string? Ar { get; set; } + + /// + /// Gets or sets Album - [al:The album this song is on]. + /// + public string? Al { get; set; } + + /// + /// Gets or sets Title - [ti:The title of the song]. + /// + public string? Ti { get; set; } + + /// + /// Gets or sets Author - [au:Creator of the lyric data]. + /// + public string? Au { get; set; } + + /// + /// Gets or sets Length - [length:How long the song is]. + /// + public string? Length { get; set; } + + /// + /// Gets or sets By - [by:Creator of the LRC file]. + /// + public string? By { get; set; } + + /// + /// Gets or sets Offset - [offsec:+/- Timestamp adjustment in milliseconds]. + /// + public string? Offset { get; set; } + + /// + /// Gets or sets Creator - [re:The Software used to create the LRC file]. + /// + public string? Re { get; set; } + + /// + /// Gets or sets Version - [ve:The version of the Creator used]. + /// + public string? Ve { get; set; } +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index d4e025a43e..c08e276dcf 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -18,6 +18,7 @@ + diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index db87d92368..b527c5303c 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; +using AutoMapper; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; @@ -44,7 +45,8 @@ public class LrcLyricProvider : ILyricProvider List lyricList = new List(); List sortedLyricData = new List(); - IDictionary metaData = new Dictionary(); + // Must be for automapper support + IDictionary metaData = new Dictionary(); string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); try @@ -69,7 +71,7 @@ public class LrcLyricProvider : ILyricProvider continue; } - string metaDataFieldName = metaDataField[0][1..].Trim(); + string metaDataFieldName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(metaDataField[0][1..].Trim().ToLowerInvariant()); string metaDataFieldValue = metaDataField[1][..^1].Trim(); metaData.Add(metaDataFieldName, metaDataFieldValue); @@ -85,6 +87,9 @@ public class LrcLyricProvider : ILyricProvider return null; } + var config = new MapperConfiguration(cfg => { }); + var mapper = config.CreateMapper(); + for (int i = 0; i < sortedLyricData.Count; i++) { var timeData = sortedLyricData[i].TimeTags.First().Value; @@ -99,7 +104,7 @@ public class LrcLyricProvider : ILyricProvider if (metaData.Any()) { - return new LyricResponse { Metadata = metaData, Lyrics = lyricList }; + return new LyricResponse { Metadata = mapper.Map(metaData), Lyrics = lyricList }; } return new LyricResponse { Lyrics = lyricList }; -- cgit v1.2.3 From a52d108af6b8519715bc7005e7db3f1a116760bc Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sun, 18 Sep 2022 11:47:57 -0400 Subject: Remove automapper tool --- MediaBrowser.Controller/Lyrics/LyricMetadata.cs | 52 +++++++++++++++ MediaBrowser.Controller/Lyrics/LyricResponse.cs | 2 +- MediaBrowser.Controller/Lyrics/Metadata.cs | 54 --------------- .../MediaBrowser.Controller.csproj | 1 - MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 78 +++++++++++++++++++--- 5 files changed, 120 insertions(+), 67 deletions(-) create mode 100644 MediaBrowser.Controller/Lyrics/LyricMetadata.cs delete mode 100644 MediaBrowser.Controller/Lyrics/Metadata.cs (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricMetadata.cs b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs new file mode 100644 index 0000000000..36a833f85c --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs @@ -0,0 +1,52 @@ +namespace MediaBrowser.Controller.Lyrics; + +/// +/// LyricMetadata model. +/// +public class LyricMetadata +{ + /// + /// Gets or sets Artist - The song artist. + /// + public string? Artist { get; set; } + + /// + /// Gets or sets Album - The album this song is on. + /// + public string? Album { get; set; } + + /// + /// Gets or sets Title - The title of the song. + /// + public string? Title { get; set; } + + /// + /// Gets or sets Author - Creator of the lyric data. + /// + public string? Author { get; set; } + + /// + /// Gets or sets Length - How long the song is. + /// + public string? Length { get; set; } + + /// + /// Gets or sets By - Creator of the LRC file. + /// + public string? By { get; set; } + + /// + /// Gets or sets Offset - Offset:+/- Timestamp adjustment in milliseconds. + /// + public string? Offset { get; set; } + + /// + /// Gets or sets Creator - The Software used to create the LRC file. + /// + public string? Creator { get; set; } + + /// + /// Gets or sets Version - The version of the Creator used. + /// + public string? Version { get; set; } +} diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index adc13050ee..9892483889 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -10,7 +10,7 @@ public class LyricResponse /// /// Gets or sets Metadata. /// - public Metadata? Metadata { get; set; } + public LyricMetadata? Metadata { get; set; } /// /// Gets or sets Lyrics. diff --git a/MediaBrowser.Controller/Lyrics/Metadata.cs b/MediaBrowser.Controller/Lyrics/Metadata.cs deleted file mode 100644 index 114b56777a..0000000000 --- a/MediaBrowser.Controller/Lyrics/Metadata.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Lyrics; - -/// -/// Metadata model. -/// -public class Metadata -{ - /// - /// Gets or sets Artist - [ar:The song artist]. - /// - public string? Ar { get; set; } - - /// - /// Gets or sets Album - [al:The album this song is on]. - /// - public string? Al { get; set; } - - /// - /// Gets or sets Title - [ti:The title of the song]. - /// - public string? Ti { get; set; } - - /// - /// Gets or sets Author - [au:Creator of the lyric data]. - /// - public string? Au { get; set; } - - /// - /// Gets or sets Length - [length:How long the song is]. - /// - public string? Length { get; set; } - - /// - /// Gets or sets By - [by:Creator of the LRC file]. - /// - public string? By { get; set; } - - /// - /// Gets or sets Offset - [offsec:+/- Timestamp adjustment in milliseconds]. - /// - public string? Offset { get; set; } - - /// - /// Gets or sets Creator - [re:The Software used to create the LRC file]. - /// - public string? Re { get; set; } - - /// - /// Gets or sets Version - [ve:The version of the Creator used]. - /// - public string? Ve { get; set; } -} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index c08e276dcf..d4e025a43e 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -18,7 +18,6 @@ - diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index b527c5303c..4cc06dac8d 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Globalization; using System.Linq; -using AutoMapper; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; +using Newtonsoft.Json.Linq; namespace MediaBrowser.Providers.Lyric; @@ -45,8 +44,7 @@ public class LrcLyricProvider : ILyricProvider List lyricList = new List(); List sortedLyricData = new List(); - // Must be for automapper support - IDictionary metaData = new Dictionary(); + IDictionary fileMetaData = new Dictionary(); string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); try @@ -71,10 +69,10 @@ public class LrcLyricProvider : ILyricProvider continue; } - string metaDataFieldName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(metaDataField[0][1..].Trim().ToLowerInvariant()); + string metaDataFieldName = metaDataField[0][1..].Trim().ToLowerInvariant(); string metaDataFieldValue = metaDataField[1][..^1].Trim(); - metaData.Add(metaDataFieldName, metaDataFieldValue); + fileMetaData.Add(metaDataFieldName, metaDataFieldValue); } } catch @@ -87,9 +85,6 @@ public class LrcLyricProvider : ILyricProvider return null; } - var config = new MapperConfiguration(cfg => { }); - var mapper = config.CreateMapper(); - for (int i = 0; i < sortedLyricData.Count; i++) { var timeData = sortedLyricData[i].TimeTags.First().Value; @@ -102,11 +97,72 @@ public class LrcLyricProvider : ILyricProvider lyricList.Add(new Controller.Lyrics.Lyric(sortedLyricData[i].Text, ticks)); } - if (metaData.Any()) + if (fileMetaData.Any()) { - return new LyricResponse { Metadata = mapper.Map(metaData), Lyrics = lyricList }; + // Map metaData values from LRC file to LyricMetadata properties + LyricMetadata lyricMetadata = MapMetadataValues(fileMetaData); + + return new LyricResponse { Metadata = lyricMetadata, Lyrics = lyricList }; } return new LyricResponse { Lyrics = lyricList }; } + + /// + /// Converts metadata from an LRC file to LyricMetadata properties. + /// + /// The metadata from the LRC file. + /// A lyricMetadata object with mapped property data. + private LyricMetadata MapMetadataValues(IDictionary metaData) + { + LyricMetadata lyricMetadata = new LyricMetadata(); + + if (metaData.TryGetValue("ar", out var artist) && artist is not null) + { + lyricMetadata.Artist = artist; + } + + if (metaData.TryGetValue("al", out var album) && album is not null) + { + lyricMetadata.Album = album; + } + + if (metaData.TryGetValue("ti", out var title) && title is not null) + { + lyricMetadata.Title = title; + } + + if (metaData.TryGetValue("au", out var author) && author is not null) + { + lyricMetadata.Author = author; + } + + if (metaData.TryGetValue("length", out var length) && length is not null) + { + lyricMetadata.Length = length; + } + + if (metaData.TryGetValue("by", out var by) && by is not null) + { + lyricMetadata.By = by; + } + + if (metaData.TryGetValue("offset", out var offset) && offset is not null) + { + lyricMetadata.Offset = offset; + } + + if (metaData.TryGetValue("re", out var creator) && creator is not null) + { + lyricMetadata.Creator = creator; + } + + if (metaData.TryGetValue("ve", out var version) && version is not null) + { + lyricMetadata.Version = version; + } + + return lyricMetadata; + + } } -- cgit v1.2.3 From f737581d49dd9f6ab0c68269f8be073df27fb0ba Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sun, 18 Sep 2022 13:13:01 -0400 Subject: Use providers in order of priority --- MediaBrowser.Controller/Lyrics/ILyricProvider.cs | 7 ++++ MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 48 ++++++++++++++++-------- MediaBrowser.Providers/Lyric/LyricManager.cs | 2 +- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 7 ++++ 4 files changed, 47 insertions(+), 17 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs index 1b52de255f..651fe507f9 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Resolvers; namespace MediaBrowser.Controller.Lyrics; @@ -13,6 +14,12 @@ public interface ILyricProvider /// string Name { get; } + /// + /// Gets the priority. + /// + /// The priority. + ResolverPriority Priority { get; } + /// /// Gets the supported media types for this provider. /// diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 90396e5532..4690c3e209 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -1,12 +1,12 @@ using System; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.Linq; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; -using Newtonsoft.Json.Linq; +using MediaBrowser.Controller.Resolvers; +using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Lyric; @@ -15,9 +15,26 @@ namespace MediaBrowser.Providers.Lyric; /// public class LrcLyricProvider : ILyricProvider { + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + public LrcLyricProvider(ILogger logger) + { + _logger = logger; + } + /// public string Name => "LrcLyricProvider"; + /// + /// Gets the priority. + /// + /// The priority. + public ResolverPriority Priority => ResolverPriority.First; + /// public IEnumerable SupportedMediaTypes { get; } = new[] { "lrc" }; @@ -38,7 +55,7 @@ public class LrcLyricProvider : ILyricProvider List lyricList = new List(); List sortedLyricData = new List(); - IDictionary fileMetaData = new Dictionary(); + IDictionary fileMetaData = new Dictionary(StringComparer.OrdinalIgnoreCase); string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); try @@ -63,15 +80,15 @@ public class LrcLyricProvider : ILyricProvider continue; } - string metaDataFieldName = metaDataField[0][1..].Trim().ToLowerInvariant(); + string metaDataFieldName = metaDataField[0][1..].Trim(); string metaDataFieldValue = metaDataField[1][..^1].Trim(); fileMetaData.Add(metaDataFieldName, metaDataFieldValue); } } - catch + catch (Exception ex) { - return null; + _logger.LogError(ex, "Error parsing lyric data from {Provider}", Name); } if (sortedLyricData.Count == 0) @@ -111,52 +128,51 @@ public class LrcLyricProvider : ILyricProvider { LyricMetadata lyricMetadata = new LyricMetadata(); - if (metaData.TryGetValue("ar", out var artist) && artist is not null) + if (metaData.TryGetValue("ar", out var artist) && !string.IsNullOrEmpty(artist)) { lyricMetadata.Artist = artist; } - if (metaData.TryGetValue("al", out var album) && album is not null) + if (metaData.TryGetValue("al", out var album) && !string.IsNullOrEmpty(album)) { lyricMetadata.Album = album; } - if (metaData.TryGetValue("ti", out var title) && title is not null) + if (metaData.TryGetValue("ti", out var title) && !string.IsNullOrEmpty(title)) { lyricMetadata.Title = title; } - if (metaData.TryGetValue("au", out var author) && author is not null) + if (metaData.TryGetValue("au", out var author) && !string.IsNullOrEmpty(author)) { lyricMetadata.Author = author; } - if (metaData.TryGetValue("length", out var length) && length is not null) + if (metaData.TryGetValue("length", out var length) && !string.IsNullOrEmpty(length)) { lyricMetadata.Length = length; } - if (metaData.TryGetValue("by", out var by) && by is not null) + if (metaData.TryGetValue("by", out var by) && !string.IsNullOrEmpty(by)) { lyricMetadata.By = by; } - if (metaData.TryGetValue("offset", out var offset) && offset is not null) + if (metaData.TryGetValue("offset", out var offset) && !string.IsNullOrEmpty(offset)) { lyricMetadata.Offset = offset; } - if (metaData.TryGetValue("re", out var creator) && creator is not null) + if (metaData.TryGetValue("re", out var creator) && !string.IsNullOrEmpty(creator)) { lyricMetadata.Creator = creator; } - if (metaData.TryGetValue("ve", out var version) && version is not null) + if (metaData.TryGetValue("ve", out var version) && !string.IsNullOrEmpty(version)) { lyricMetadata.Version = version; } return lyricMetadata; - } } diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs index 0de008db7f..7487c68615 100644 --- a/MediaBrowser.Providers/Lyric/LyricManager.cs +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -18,7 +18,7 @@ public class LyricManager : ILyricManager /// All found lyricProviders. public LyricManager(IEnumerable lyricProviders) { - _lyricProviders = lyricProviders.ToArray(); + _lyricProviders = lyricProviders.OrderBy(i => i.Priority).ToArray(); } /// diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index a2161c427f..c690086862 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -4,6 +4,7 @@ using System.Collections.ObjectModel; using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; +using MediaBrowser.Controller.Resolvers; namespace MediaBrowser.Providers.Lyric; @@ -15,6 +16,12 @@ public class TxtLyricProvider : ILyricProvider /// public string Name => "TxtLyricProvider"; + /// + /// Gets the priority. + /// + /// The priority. + public ResolverPriority Priority => ResolverPriority.Second; + /// public IEnumerable SupportedMediaTypes { get; } = new[] { "lrc", "txt" }; -- cgit v1.2.3 From dce81d88182c90fdce90f2690b3adb22485fecd4 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sun, 18 Sep 2022 14:53:25 -0400 Subject: Update MediaBrowser.Controller/Lyrics/LyricResponse.cs Co-authored-by: Niels van Velzen --- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 9892483889..f3d8b07bc8 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -10,7 +10,7 @@ public class LyricResponse /// /// Gets or sets Metadata. /// - public LyricMetadata? Metadata { get; set; } + public LyricMetadata Metadata { get; set; } /// /// Gets or sets Lyrics. -- cgit v1.2.3 From dddebec794c72242952cb45e84fed452d828a641 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sun, 18 Sep 2022 14:53:36 -0400 Subject: Update MediaBrowser.Controller/Lyrics/LyricResponse.cs Co-authored-by: Niels van Velzen --- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index f3d8b07bc8..405e8cac18 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -15,5 +15,5 @@ public class LyricResponse /// /// Gets or sets Lyrics. /// - public IEnumerable? Lyrics { get; set; } + public IEnumerable Lyrics { get; set; } } -- cgit v1.2.3 From 7e923e268865d8c0933a22247424d205429a474b Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sun, 18 Sep 2022 16:05:50 -0400 Subject: Use numeric values for metadata values --- MediaBrowser.Controller/Lyrics/ILyricProvider.cs | 2 +- MediaBrowser.Controller/Lyrics/Lyric.cs | 28 ------------- MediaBrowser.Controller/Lyrics/LyricLine.cs | 28 +++++++++++++ MediaBrowser.Controller/Lyrics/LyricMetadata.cs | 6 ++- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 2 +- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 53 ++++++++++++++++++++---- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 9 ++-- 7 files changed, 81 insertions(+), 47 deletions(-) delete mode 100644 MediaBrowser.Controller/Lyrics/Lyric.cs create mode 100644 MediaBrowser.Controller/Lyrics/LyricLine.cs (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs index 651fe507f9..c5b6252267 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs @@ -24,7 +24,7 @@ public interface ILyricProvider /// Gets the supported media types for this provider. /// /// The supported media types. - IEnumerable SupportedMediaTypes { get; } + IReadOnlyCollection SupportedMediaTypes { get; } /// /// Gets the lyrics. diff --git a/MediaBrowser.Controller/Lyrics/Lyric.cs b/MediaBrowser.Controller/Lyrics/Lyric.cs deleted file mode 100644 index f39fbb0221..0000000000 --- a/MediaBrowser.Controller/Lyrics/Lyric.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace MediaBrowser.Controller.Lyrics; - -/// -/// Lyric model. -/// -public class Lyric -{ - /// - /// Initializes a new instance of the class. - /// - /// The lyric start time in ticks. - /// The lyric text. - public Lyric(string text, long? start = null) - { - Start = start; - Text = text; - } - - /// - /// Gets the start time in ticks. - /// - public long? Start { get; } - - /// - /// Gets the text. - /// - public string Text { get; } -} diff --git a/MediaBrowser.Controller/Lyrics/LyricLine.cs b/MediaBrowser.Controller/Lyrics/LyricLine.cs new file mode 100644 index 0000000000..43997f6564 --- /dev/null +++ b/MediaBrowser.Controller/Lyrics/LyricLine.cs @@ -0,0 +1,28 @@ +namespace MediaBrowser.Controller.Lyrics; + +/// +/// Lyric model. +/// +public class LyricLine +{ + /// + /// Initializes a new instance of the class. + /// + /// The lyric start time in ticks. + /// The lyric text. + public LyricLine(string text, long? start = null) + { + Start = start; + Text = text; + } + + /// + /// Gets the start time in ticks. + /// + public long? Start { get; } + + /// + /// Gets the text. + /// + public string Text { get; } +} diff --git a/MediaBrowser.Controller/Lyrics/LyricMetadata.cs b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs index 36a833f85c..0ba7779750 100644 --- a/MediaBrowser.Controller/Lyrics/LyricMetadata.cs +++ b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs @@ -1,3 +1,5 @@ +using System; + namespace MediaBrowser.Controller.Lyrics; /// @@ -28,7 +30,7 @@ public class LyricMetadata /// /// Gets or sets Length - How long the song is. /// - public string? Length { get; set; } + public long? Length { get; set; } /// /// Gets or sets By - Creator of the LRC file. @@ -38,7 +40,7 @@ public class LyricMetadata /// /// Gets or sets Offset - Offset:+/- Timestamp adjustment in milliseconds. /// - public string? Offset { get; set; } + public long? Offset { get; set; } /// /// Gets or sets Creator - The Software used to create the LRC file. diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 405e8cac18..b3c65ac8c0 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -15,5 +15,5 @@ public class LyricResponse /// /// Gets or sets Lyrics. /// - public IEnumerable Lyrics { get; set; } + public IEnumerable Lyrics { get; set; } } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 4690c3e209..50fa519b3e 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Model.Entities; using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Lyric; @@ -36,7 +38,7 @@ public class LrcLyricProvider : ILyricProvider public ResolverPriority Priority => ResolverPriority.First; /// - public IEnumerable SupportedMediaTypes { get; } = new[] { "lrc" }; + public IReadOnlyCollection SupportedMediaTypes { get; } = new[] { "lrc" }; /// /// Opens lyric file for the requested item, and processes it for API return. @@ -52,7 +54,7 @@ public class LrcLyricProvider : ILyricProvider return null; } - List lyricList = new List(); + List lyricList = new List(); List sortedLyricData = new List(); IDictionary fileMetaData = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -74,14 +76,28 @@ public class LrcLyricProvider : ILyricProvider foreach (string metaDataRow in metaDataRows) { - var metaDataField = metaDataRow.Split(':'); - if (metaDataField.Length != 2) + int colonCount = metaDataRow.Count(f => (f == ':')); + if (colonCount == 0) { continue; } - string metaDataFieldName = metaDataField[0][1..].Trim(); - string metaDataFieldValue = metaDataField[1][..^1].Trim(); + string[] metaDataField; + string metaDataFieldName; + string metaDataFieldValue; + + if (colonCount == 1) + { + metaDataField = metaDataRow.Split(':'); + metaDataFieldName = metaDataField[0][1..].Trim(); + metaDataFieldValue = metaDataField[1][..^1].Trim(); + } + else + { + int colonIndex = metaDataRow.IndexOf(':', StringComparison.OrdinalIgnoreCase); + metaDataFieldName = metaDataRow[..colonIndex][1..].Trim(); + metaDataFieldValue = metaDataRow[(colonIndex + 1)..][..^1].Trim(); + } fileMetaData.Add(metaDataFieldName, metaDataFieldValue); } @@ -105,7 +121,7 @@ public class LrcLyricProvider : ILyricProvider } long ticks = TimeSpan.FromMilliseconds(timeData.Value).Ticks; - lyricList.Add(new Controller.Lyrics.Lyric(sortedLyricData[i].Text, ticks)); + lyricList.Add(new LyricLine(sortedLyricData[i].Text, ticks)); } if (fileMetaData.Count != 0) @@ -150,7 +166,23 @@ public class LrcLyricProvider : ILyricProvider if (metaData.TryGetValue("length", out var length) && !string.IsNullOrEmpty(length)) { - lyricMetadata.Length = length; + // Ensure minutes include leading zero + var lengthData = length.Split(':'); + if (lengthData[0].Length == 1) + { + length = "0" + length; + } + + // If only Minutes and Seconds were provided, prepend zeros for hours + if (lengthData.Length == 2) + { + length = "00:" + length; + } + + if (DateTime.TryParseExact(length, "HH:mm:ss", null, DateTimeStyles.None, out var value)) + { + lyricMetadata.Length = value.TimeOfDay.Ticks; + } } if (metaData.TryGetValue("by", out var by) && !string.IsNullOrEmpty(by)) @@ -160,7 +192,10 @@ public class LrcLyricProvider : ILyricProvider if (metaData.TryGetValue("offset", out var offset) && !string.IsNullOrEmpty(offset)) { - lyricMetadata.Offset = offset; + if (int.TryParse(offset, out var value)) + { + lyricMetadata.Offset = TimeSpan.FromMilliseconds(value).Ticks; + } } if (metaData.TryGetValue("re", out var creator) && !string.IsNullOrEmpty(creator)) diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index c690086862..cd0e1599e7 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -1,7 +1,4 @@ -using System; using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Resolvers; @@ -23,7 +20,7 @@ public class TxtLyricProvider : ILyricProvider public ResolverPriority Priority => ResolverPriority.Second; /// - public IEnumerable SupportedMediaTypes { get; } = new[] { "lrc", "txt" }; + public IReadOnlyCollection SupportedMediaTypes { get; } = new[] { "lrc", "txt" }; /// /// Opens lyric file for the requested item, and processes it for API return. @@ -41,7 +38,7 @@ public class TxtLyricProvider : ILyricProvider string[] lyricTextLines = System.IO.File.ReadAllLines(lyricFilePath); - List lyricList = new List(); + List lyricList = new List(); if (lyricTextLines.Length == 0) { @@ -50,7 +47,7 @@ public class TxtLyricProvider : ILyricProvider foreach (string lyricTextLine in lyricTextLines) { - lyricList.Add(new Controller.Lyrics.Lyric(lyricTextLine)); + lyricList.Add(new LyricLine(lyricTextLine)); } return new LyricResponse { Lyrics = lyricList }; -- cgit v1.2.3 From 552b6aceae94bd8079a027407d15acf6d46f9b6e Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sun, 18 Sep 2022 16:17:26 -0400 Subject: Add default values to LyricResponse --- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index b3c65ac8c0..ded3ca10e2 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -10,10 +10,10 @@ public class LyricResponse /// /// Gets or sets Metadata. /// - public LyricMetadata Metadata { get; set; } + public LyricMetadata Metadata { get; set; } = new LyricMetadata(); /// /// Gets or sets Lyrics. /// - public IEnumerable Lyrics { get; set; } + public IReadOnlyCollection Lyrics { get; set; } = new List(); } -- cgit v1.2.3 From 28d017865b7f51babc7c13dbfaf71a660d834d46 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Sun, 18 Sep 2022 21:17:53 -0400 Subject: Code Cleanup --- MediaBrowser.Controller/Lyrics/LyricLine.cs | 2 +- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 4 +-- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 39 ++++++------------------ MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 4 +-- 4 files changed, 14 insertions(+), 35 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricLine.cs b/MediaBrowser.Controller/Lyrics/LyricLine.cs index 43997f6564..eb5ff9972e 100644 --- a/MediaBrowser.Controller/Lyrics/LyricLine.cs +++ b/MediaBrowser.Controller/Lyrics/LyricLine.cs @@ -8,8 +8,8 @@ public class LyricLine /// /// Initializes a new instance of the class. /// - /// The lyric start time in ticks. /// The lyric text. + /// The lyric start time in ticks. public LyricLine(string text, long? start = null) { Start = start; diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index ded3ca10e2..64c3b3c28b 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -10,10 +10,10 @@ public class LyricResponse /// /// Gets or sets Metadata. /// - public LyricMetadata Metadata { get; set; } = new LyricMetadata(); + public LyricMetadata Metadata { get; set; } = new(); /// /// Gets or sets Lyrics. /// - public IReadOnlyCollection Lyrics { get; set; } = new List(); + public IReadOnlyList Lyrics { get; set; } = new List(); } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 50fa519b3e..9d622a1cdf 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -38,7 +38,7 @@ public class LrcLyricProvider : ILyricProvider public ResolverPriority Priority => ResolverPriority.First; /// - public IReadOnlyCollection SupportedMediaTypes { get; } = new[] { "lrc" }; + public IReadOnlyCollection SupportedMediaTypes { get; } = new[] { "lrc", "elrc" }; /// /// Opens lyric file for the requested item, and processes it for API return. @@ -54,8 +54,8 @@ public class LrcLyricProvider : ILyricProvider return null; } - List lyricList = new List(); - List sortedLyricData = new List(); + List lyricList = new(); + List sortedLyricData = new(); IDictionary fileMetaData = new Dictionary(StringComparer.OrdinalIgnoreCase); string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); @@ -85,19 +85,11 @@ public class LrcLyricProvider : ILyricProvider string[] metaDataField; string metaDataFieldName; string metaDataFieldValue; + string[] test; - if (colonCount == 1) - { - metaDataField = metaDataRow.Split(':'); - metaDataFieldName = metaDataField[0][1..].Trim(); - metaDataFieldValue = metaDataField[1][..^1].Trim(); - } - else - { - int colonIndex = metaDataRow.IndexOf(':', StringComparison.OrdinalIgnoreCase); - metaDataFieldName = metaDataRow[..colonIndex][1..].Trim(); - metaDataFieldValue = metaDataRow[(colonIndex + 1)..][..^1].Trim(); - } + metaDataField = metaDataRow.Split(':', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + metaDataFieldName = metaDataField[0][1..].Trim(); + metaDataFieldValue = metaDataField[1][..^1].Trim(); fileMetaData.Add(metaDataFieldName, metaDataFieldValue); } @@ -142,7 +134,7 @@ public class LrcLyricProvider : ILyricProvider /// A lyricMetadata object with mapped property data. private LyricMetadata MapMetadataValues(IDictionary metaData) { - LyricMetadata lyricMetadata = new LyricMetadata(); + LyricMetadata lyricMetadata = new(); if (metaData.TryGetValue("ar", out var artist) && !string.IsNullOrEmpty(artist)) { @@ -166,20 +158,7 @@ public class LrcLyricProvider : ILyricProvider if (metaData.TryGetValue("length", out var length) && !string.IsNullOrEmpty(length)) { - // Ensure minutes include leading zero - var lengthData = length.Split(':'); - if (lengthData[0].Length == 1) - { - length = "0" + length; - } - - // If only Minutes and Seconds were provided, prepend zeros for hours - if (lengthData.Length == 2) - { - length = "00:" + length; - } - - if (DateTime.TryParseExact(length, "HH:mm:ss", null, DateTimeStyles.None, out var value)) + if (DateTime.TryParseExact(length, new string[] { "HH:mm:ss", "H:mm:ss", "mm:ss", "m:ss" }, null, DateTimeStyles.None, out var value)) { lyricMetadata.Length = value.TimeOfDay.Ticks; } diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index cd0e1599e7..542df13873 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -20,7 +20,7 @@ public class TxtLyricProvider : ILyricProvider public ResolverPriority Priority => ResolverPriority.Second; /// - public IReadOnlyCollection SupportedMediaTypes { get; } = new[] { "lrc", "txt" }; + public IReadOnlyCollection SupportedMediaTypes { get; } = new[] { "lrc", "elrc", "txt" }; /// /// Opens lyric file for the requested item, and processes it for API return. @@ -38,7 +38,7 @@ public class TxtLyricProvider : ILyricProvider string[] lyricTextLines = System.IO.File.ReadAllLines(lyricFilePath); - List lyricList = new List(); + List lyricList = new(); if (lyricTextLines.Length == 0) { -- cgit v1.2.3 From 5d2364f0646ba4f4b6866115ad82fd8fac0733de Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Mon, 19 Sep 2022 16:59:16 -0400 Subject: Move AcceptedTimeFormats to class level variable --- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 3 ++- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 64c3b3c28b..56a5696450 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; namespace MediaBrowser.Controller.Lyrics; @@ -15,5 +16,5 @@ public class LyricResponse /// /// Gets or sets Lyrics. /// - public IReadOnlyList Lyrics { get; set; } = new List(); + public IReadOnlyList Lyrics { get; set; } = Array.Empty(); } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index ea10749b95..b67b8c5d39 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -39,6 +39,8 @@ public class LrcLyricProvider : ILyricProvider /// public IReadOnlyCollection SupportedMediaTypes { get; } = new[] { "lrc", "elrc" }; + private static string[] AcceptedTimeFormats => new[] { "HH:mm:ss", "H:mm:ss", "mm:ss", "m:ss" }; + /// /// Opens lyric file for the requested item, and processes it for API return. /// @@ -88,8 +90,8 @@ public class LrcLyricProvider : ILyricProvider } string[] metaDataField = metaDataRow.Split(':', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - string metaDataFieldName = metaDataField[0][1..].Trim(); - string metaDataFieldValue = metaDataField[1][..^1].Trim(); + string metaDataFieldName = metaDataField[0][1..]; + string metaDataFieldValue = metaDataField[1][..^1]; fileMetaData.Add(metaDataFieldName, metaDataFieldValue); } @@ -155,7 +157,7 @@ public class LrcLyricProvider : ILyricProvider if (metaData.TryGetValue("length", out var length) && !string.IsNullOrEmpty(length)) { - if (DateTime.TryParseExact(length, new string[] { "HH:mm:ss", "H:mm:ss", "mm:ss", "m:ss" }, null, DateTimeStyles.None, out var value)) + if (DateTime.TryParseExact(length, AcceptedTimeFormats, null, DateTimeStyles.None, out var value)) { lyricMetadata.Length = value.TimeOfDay.Ticks; } -- cgit v1.2.3 From 6f0d33b1caafdf5c8c0413bf3fdcddc822a08f51 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Tue, 20 Sep 2022 08:36:43 -0400 Subject: Use Directory GetFiles to find lyric files --- Emby.Server.Implementations/ApplicationHost.cs | 1 - MediaBrowser.Controller/Lyrics/LyricInfo.cs | 20 ++++++++++++++++---- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 12 ++++++++---- MediaBrowser.Providers/Lyric/LyricManager.cs | 2 +- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 2 +- 5 files changed, 26 insertions(+), 11 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 3c3c90e61e..67c63bb599 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -46,7 +46,6 @@ using Emby.Server.Implementations.SyncPlay; using Emby.Server.Implementations.TV; using Emby.Server.Implementations.Updates; using Jellyfin.Api.Helpers; -using Jellyfin.Api.Models.UserDtos; using Jellyfin.MediaEncoding.Hls.Playlist; using Jellyfin.Networking.Configuration; using Jellyfin.Networking.Manager; diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index 61e205b6cc..a063a4cc55 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -1,4 +1,7 @@ +using System.Collections.Generic; using System.IO; +using System.Linq; +using Jellyfin.Extensions; namespace MediaBrowser.Controller.Lyrics; @@ -13,12 +16,21 @@ public static class LyricInfo /// The lyricProvider interface to use. /// Path of requested item. /// Lyric file path if passed lyric provider's supported media type is found; otherwise, null. - public static string? GetLyricFilePath(ILyricProvider lyricProvider, string itemPath) + public static string? GetLyricFilePath(this ILyricProvider lyricProvider, string itemPath) { - foreach (string lyricFileExtension in lyricProvider.SupportedMediaTypes) + if (lyricProvider is null) { - var lyricFilePath = Path.ChangeExtension(itemPath, lyricFileExtension); - if (File.Exists(lyricFilePath)) + return null; + } + + if (!Directory.Exists(Path.GetDirectoryName(itemPath))) + { + return null; + } + + foreach (var lyricFilePath in Directory.GetFiles(Path.GetDirectoryName(itemPath), $"{Path.GetFileNameWithoutExtension(itemPath)}.*")) + { + if (lyricProvider.SupportedMediaTypes.Contains(Path.GetExtension(lyricFilePath)[1..])) { return lyricFilePath; } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 3177abb963..8ed0552cc2 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -20,7 +20,7 @@ public class LrcLyricProvider : ILyricProvider private readonly LyricParser _lrcLyricParser; - private static readonly IReadOnlyList _acceptedTimeFormats = new string[] { "HH:mm:ss", "H:mm:ss", "mm:ss", "m:ss" }; + private static readonly string[] _acceptedTimeFormats = { "HH:mm:ss", "H:mm:ss", "mm:ss", "m:ss" }; /// /// Initializes a new instance of the class. @@ -51,14 +51,14 @@ public class LrcLyricProvider : ILyricProvider /// If provider can determine lyrics, returns a with or without metadata; otherwise, null. public LyricResponse? GetLyrics(BaseItem item) { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); + string? lyricFilePath = this.GetLyricFilePath(item.Path); if (string.IsNullOrEmpty(lyricFilePath)) { return null; } - IDictionary fileMetaData = new Dictionary(StringComparer.OrdinalIgnoreCase); + var fileMetaData = new Dictionary(StringComparer.OrdinalIgnoreCase); string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); Song lyricData; @@ -90,6 +90,10 @@ public class LrcLyricProvider : ILyricProvider } string[] metaDataField = metaDataRow.Split(':', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + + // Remove square bracket before field name, and after field value + // Example 1: [au: 1hitsong] + // Example 2: [ar: Calabrese] string metaDataFieldName = metaDataField[0][1..]; string metaDataFieldValue = metaDataField[1][..^1]; @@ -162,7 +166,7 @@ public class LrcLyricProvider : ILyricProvider if (metaData.TryGetValue("length", out var length) && !string.IsNullOrEmpty(length)) { - if (DateTime.TryParseExact(length, _acceptedTimeFormats.ToArray(), null, DateTimeStyles.None, out var value)) + if (DateTime.TryParseExact(length, _acceptedTimeFormats, null, DateTimeStyles.None, out var value)) { lyricMetadata.Length = value.TimeOfDay.Ticks; } diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs index 7487c68615..336b324a7f 100644 --- a/MediaBrowser.Providers/Lyric/LyricManager.cs +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -46,7 +46,7 @@ public class LyricManager : ILyricManager continue; } - if (LyricInfo.GetLyricFilePath(provider, item.Path) is not null) + if (provider.GetLyricFilePath(item.Path) is not null) { return true; } diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index 6a189e132e..df6d526301 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -29,7 +29,7 @@ public class TxtLyricProvider : ILyricProvider /// If provider can determine lyrics, returns a ; otherwise, null. public LyricResponse? GetLyrics(BaseItem item) { - string? lyricFilePath = LyricInfo.GetLyricFilePath(this, item.Path); + string? lyricFilePath = this.GetLyricFilePath(item.Path); if (string.IsNullOrEmpty(lyricFilePath)) { -- cgit v1.2.3 From 0d5bd85d6d292b0876f60bf0654e243f595ec9f9 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Tue, 20 Sep 2022 08:48:08 -0400 Subject: Resolve Azure build error --- MediaBrowser.Controller/Lyrics/LyricInfo.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index a063a4cc55..57964eee51 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -18,18 +18,29 @@ public static class LyricInfo /// Lyric file path if passed lyric provider's supported media type is found; otherwise, null. public static string? GetLyricFilePath(this ILyricProvider lyricProvider, string itemPath) { + // Ensure we have a provider if (lyricProvider is null) { return null; } - if (!Directory.Exists(Path.GetDirectoryName(itemPath))) + // Ensure the path to the item is not null + string? itemDirectoryPath = Path.GetDirectoryName(itemPath); + if (itemDirectoryPath is null) { return null; } - foreach (var lyricFilePath in Directory.GetFiles(Path.GetDirectoryName(itemPath), $"{Path.GetFileNameWithoutExtension(itemPath)}.*")) + // Ensure the directory path exists + if (!Directory.Exists(itemDirectoryPath)) { + return null; + } + + foreach (var lyricFilePath in Directory.GetFiles(itemDirectoryPath, $"{Path.GetFileNameWithoutExtension(itemPath)}.*")) + { + if (lyricFilePath is null) { continue; } + if (lyricProvider.SupportedMediaTypes.Contains(Path.GetExtension(lyricFilePath)[1..])) { return lyricFilePath; -- cgit v1.2.3 From b1771f07e92dd47f8e49c7f96f61b731d4a6065c Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Tue, 20 Sep 2022 13:34:46 -0400 Subject: Use Span in SupportedMediaTypes comparison --- MediaBrowser.Controller/Lyrics/LyricInfo.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index 57964eee51..6ebb83d125 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -1,6 +1,5 @@ -using System.Collections.Generic; +using System; using System.IO; -using System.Linq; using Jellyfin.Extensions; namespace MediaBrowser.Controller.Lyrics; @@ -39,9 +38,7 @@ public static class LyricInfo foreach (var lyricFilePath in Directory.GetFiles(itemDirectoryPath, $"{Path.GetFileNameWithoutExtension(itemPath)}.*")) { - if (lyricFilePath is null) { continue; } - - if (lyricProvider.SupportedMediaTypes.Contains(Path.GetExtension(lyricFilePath)[1..])) + if (EnumerableExtensions.Contains(lyricProvider.SupportedMediaTypes, Path.GetExtension(lyricFilePath.AsSpan())[1..], StringComparison.OrdinalIgnoreCase)) { return lyricFilePath; } -- cgit v1.2.3 From 35399ce8fef0559f65bee4f519c582d192a04e52 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Wed, 21 Sep 2022 17:49:28 -0400 Subject: Update summaries, Use spans --- MediaBrowser.Controller/Lyrics/LyricLine.cs | 10 +++++----- MediaBrowser.Controller/Lyrics/LyricMetadata.cs | 18 +++++++++--------- MediaBrowser.Controller/Lyrics/LyricResponse.cs | 4 ++-- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 16 ++++++++-------- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 10 ++++++---- 5 files changed, 30 insertions(+), 28 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricLine.cs b/MediaBrowser.Controller/Lyrics/LyricLine.cs index eb5ff9972e..c406f92fcc 100644 --- a/MediaBrowser.Controller/Lyrics/LyricLine.cs +++ b/MediaBrowser.Controller/Lyrics/LyricLine.cs @@ -12,17 +12,17 @@ public class LyricLine /// The lyric start time in ticks. public LyricLine(string text, long? start = null) { - Start = start; Text = text; + Start = start; } /// - /// Gets the start time in ticks. + /// Gets the text of this lyric line. /// - public long? Start { get; } + public string Text { get; } /// - /// Gets the text. + /// Gets the start time in ticks. /// - public string Text { get; } + public long? Start { get; } } diff --git a/MediaBrowser.Controller/Lyrics/LyricMetadata.cs b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs index 0ba7779750..6091ede52a 100644 --- a/MediaBrowser.Controller/Lyrics/LyricMetadata.cs +++ b/MediaBrowser.Controller/Lyrics/LyricMetadata.cs @@ -8,47 +8,47 @@ namespace MediaBrowser.Controller.Lyrics; public class LyricMetadata { /// - /// Gets or sets Artist - The song artist. + /// Gets or sets the song artist. /// public string? Artist { get; set; } /// - /// Gets or sets Album - The album this song is on. + /// Gets or sets the album this song is on. /// public string? Album { get; set; } /// - /// Gets or sets Title - The title of the song. + /// Gets or sets the title of the song. /// public string? Title { get; set; } /// - /// Gets or sets Author - Creator of the lyric data. + /// Gets or sets the author of the lyric data. /// public string? Author { get; set; } /// - /// Gets or sets Length - How long the song is. + /// Gets or sets the length of the song in ticks. /// public long? Length { get; set; } /// - /// Gets or sets By - Creator of the LRC file. + /// Gets or sets who the LRC file was created by. /// public string? By { get; set; } /// - /// Gets or sets Offset - Offset:+/- Timestamp adjustment in milliseconds. + /// Gets or sets the lyric offset compared to audio in ticks. /// public long? Offset { get; set; } /// - /// Gets or sets Creator - The Software used to create the LRC file. + /// Gets or sets the software used to create the LRC file. /// public string? Creator { get; set; } /// - /// Gets or sets Version - The version of the Creator used. + /// Gets or sets the version of the creator used. /// public string? Version { get; set; } } diff --git a/MediaBrowser.Controller/Lyrics/LyricResponse.cs b/MediaBrowser.Controller/Lyrics/LyricResponse.cs index 56a5696450..0d52b5ec50 100644 --- a/MediaBrowser.Controller/Lyrics/LyricResponse.cs +++ b/MediaBrowser.Controller/Lyrics/LyricResponse.cs @@ -9,12 +9,12 @@ namespace MediaBrowser.Controller.Lyrics; public class LyricResponse { /// - /// Gets or sets Metadata. + /// Gets or sets Metadata for the lyrics. /// public LyricMetadata Metadata { get; set; } = new(); /// - /// Gets or sets Lyrics. + /// Gets or sets a collection of individual lyric lines. /// public IReadOnlyList Lyrics { get; set; } = Array.Empty(); } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 8ed0552cc2..1dbe5958e8 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.IO; using System.Linq; using LrcParser.Model; using LrcParser.Parser; @@ -59,7 +60,7 @@ public class LrcLyricProvider : ILyricProvider } var fileMetaData = new Dictionary(StringComparer.OrdinalIgnoreCase); - string lrcFileContent = System.IO.File.ReadAllText(lyricFilePath); + string lrcFileContent = File.ReadAllText(lyricFilePath); Song lyricData; @@ -84,25 +85,24 @@ public class LrcLyricProvider : ILyricProvider foreach (string metaDataRow in metaDataRows) { - if (!metaDataRow.Contains(':', StringComparison.OrdinalIgnoreCase)) + var index = metaDataRow.IndexOf(':', StringComparison.OrdinalIgnoreCase); + if (index == -1) { continue; } - string[] metaDataField = metaDataRow.Split(':', 2, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); - // Remove square bracket before field name, and after field value // Example 1: [au: 1hitsong] // Example 2: [ar: Calabrese] - string metaDataFieldName = metaDataField[0][1..]; - string metaDataFieldValue = metaDataField[1][..^1]; + var metaDataFieldNameSpan = metaDataRow.AsSpan(1, index - 1).Trim(); + var metaDataFieldValueSpan = metaDataRow.AsSpan(index + 1, metaDataRow.Length - index - 2).Trim(); - if (string.IsNullOrEmpty(metaDataFieldName) || string.IsNullOrEmpty(metaDataFieldValue)) + if (metaDataFieldValueSpan.IsEmpty || metaDataFieldValueSpan.IsEmpty) { continue; } - fileMetaData[metaDataFieldName] = metaDataFieldValue; + fileMetaData[metaDataFieldNameSpan.ToString()] = metaDataFieldValueSpan.ToString(); } if (sortedLyricData.Count == 0) diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index df6d526301..bce8810545 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.IO; +using System.Linq; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Resolvers; @@ -36,18 +38,18 @@ public class TxtLyricProvider : ILyricProvider return null; } - string[] lyricTextLines = System.IO.File.ReadAllLines(lyricFilePath); + string[] lyricTextLines = File.ReadAllLines(lyricFilePath); if (lyricTextLines.Length == 0) { return null; } - List lyricList = new(lyricTextLines.Length); + LyricLine[] lyricList = new LyricLine[lyricTextLines.Length]; - foreach (string lyricTextLine in lyricTextLines) + for (int lyricLine = 0; lyricLine < lyricTextLines.Length; lyricLine++) { - lyricList.Add(new LyricLine(lyricTextLine)); + lyricList[lyricLine] = new LyricLine(lyricTextLines[lyricLine]); } return new LyricResponse { Lyrics = lyricList }; -- cgit v1.2.3 From a50bdb47709be0412b3abb2729f8c657b5d0c779 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Thu, 22 Sep 2022 08:13:53 -0400 Subject: Use async functions --- Jellyfin.Api/Controllers/UserLibraryController.cs | 4 ++-- MediaBrowser.Controller/Lyrics/ILyricManager.cs | 5 +++-- MediaBrowser.Controller/Lyrics/ILyricProvider.cs | 5 +++-- MediaBrowser.Providers/Lyric/LrcLyricProvider.cs | 23 +++++++++++++++++------ MediaBrowser.Providers/Lyric/LyricManager.cs | 5 +++-- MediaBrowser.Providers/Lyric/TxtLyricProvider.cs | 5 +++-- 6 files changed, 31 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index df91a8efc7..682a6e832d 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -397,7 +397,7 @@ namespace Jellyfin.Api.Controllers /// An containing the item's lyrics. [HttpGet("Users/{userId}/Items/{itemId}/Lyrics")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetLyrics([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) + public async Task> GetLyrics([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -415,7 +415,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var result = _lyricManager.GetLyrics(item); + var result = await _lyricManager.GetLyrics(item).ConfigureAwait(false); if (result is not null) { return Ok(result); diff --git a/MediaBrowser.Controller/Lyrics/ILyricManager.cs b/MediaBrowser.Controller/Lyrics/ILyricManager.cs index 5920bcc628..bb93e1e4c6 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricManager.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricManager.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Lyrics; @@ -11,8 +12,8 @@ public interface ILyricManager /// Gets the lyrics. /// /// The media item. - /// Lyrics for passed item. - LyricResponse? GetLyrics(BaseItem item); + /// A task representing found lyrics the passed item. + Task GetLyrics(BaseItem item); /// /// Checks if requested item has a matching local lyric file. diff --git a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs index c5b6252267..2a04c61520 100644 --- a/MediaBrowser.Controller/Lyrics/ILyricProvider.cs +++ b/MediaBrowser.Controller/Lyrics/ILyricProvider.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Threading.Tasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Resolvers; @@ -30,6 +31,6 @@ public interface ILyricProvider /// Gets the lyrics. /// /// The media item. - /// If found, returns lyrics for passed item; otherwise, null. - LyricResponse? GetLyrics(BaseItem item); + /// A task representing found lyrics. + Task GetLyrics(BaseItem item); } diff --git a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs index 1dbe5958e8..d06db3afc6 100644 --- a/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/LrcLyricProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Threading.Tasks; using LrcParser.Model; using LrcParser.Parser; using MediaBrowser.Controller.Entities; @@ -50,7 +51,7 @@ public class LrcLyricProvider : ILyricProvider /// /// The item to to process. /// If provider can determine lyrics, returns a with or without metadata; otherwise, null. - public LyricResponse? GetLyrics(BaseItem item) + public async Task GetLyrics(BaseItem item) { string? lyricFilePath = this.GetLyricFilePath(item.Path); @@ -60,7 +61,7 @@ public class LrcLyricProvider : ILyricProvider } var fileMetaData = new Dictionary(StringComparer.OrdinalIgnoreCase); - string lrcFileContent = File.ReadAllText(lyricFilePath); + string lrcFileContent = await Task.FromResult(File.ReadAllText(lyricFilePath)).ConfigureAwait(false); Song lyricData; @@ -94,15 +95,15 @@ public class LrcLyricProvider : ILyricProvider // Remove square bracket before field name, and after field value // Example 1: [au: 1hitsong] // Example 2: [ar: Calabrese] - var metaDataFieldNameSpan = metaDataRow.AsSpan(1, index - 1).Trim(); - var metaDataFieldValueSpan = metaDataRow.AsSpan(index + 1, metaDataRow.Length - index - 2).Trim(); + var metaDataFieldName = GetMetadataFieldName(metaDataRow, index); + var metaDataFieldValue = GetMetadataValue(metaDataRow, index); - if (metaDataFieldValueSpan.IsEmpty || metaDataFieldValueSpan.IsEmpty) + if (string.IsNullOrEmpty(metaDataFieldName) || string.IsNullOrEmpty(metaDataFieldValue)) { continue; } - fileMetaData[metaDataFieldNameSpan.ToString()] = metaDataFieldValueSpan.ToString(); + fileMetaData[metaDataFieldName.ToString()] = metaDataFieldValue.ToString(); } if (sortedLyricData.Count == 0) @@ -197,4 +198,14 @@ public class LrcLyricProvider : ILyricProvider return lyricMetadata; } + + private static string GetMetadataFieldName(string metaDataRow, int index) + { + return metaDataRow.AsSpan(1, index - 1).Trim().ToString(); + } + + private static string GetMetadataValue(string metaDataRow, int index) + { + return metaDataRow.AsSpan(index + 1, metaDataRow.Length - index - 2).Trim().ToString(); + } } diff --git a/MediaBrowser.Providers/Lyric/LyricManager.cs b/MediaBrowser.Providers/Lyric/LyricManager.cs index 336b324a7f..f9547e0f05 100644 --- a/MediaBrowser.Providers/Lyric/LyricManager.cs +++ b/MediaBrowser.Providers/Lyric/LyricManager.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; @@ -22,11 +23,11 @@ public class LyricManager : ILyricManager } /// - public LyricResponse? GetLyrics(BaseItem item) + public async Task GetLyrics(BaseItem item) { foreach (ILyricProvider provider in _lyricProviders) { - var results = provider.GetLyrics(item); + var results = await provider.GetLyrics(item).ConfigureAwait(false); if (results is not null) { return results; diff --git a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs index bce8810545..9df4ec83e7 100644 --- a/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs +++ b/MediaBrowser.Providers/Lyric/TxtLyricProvider.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading.Tasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Lyrics; using MediaBrowser.Controller.Resolvers; @@ -29,7 +30,7 @@ public class TxtLyricProvider : ILyricProvider /// /// The item to to process. /// If provider can determine lyrics, returns a ; otherwise, null. - public LyricResponse? GetLyrics(BaseItem item) + public async Task GetLyrics(BaseItem item) { string? lyricFilePath = this.GetLyricFilePath(item.Path); @@ -38,7 +39,7 @@ public class TxtLyricProvider : ILyricProvider return null; } - string[] lyricTextLines = File.ReadAllLines(lyricFilePath); + string[] lyricTextLines = await Task.FromResult(File.ReadAllLines(lyricFilePath)).ConfigureAwait(false); if (lyricTextLines.Length == 0) { -- cgit v1.2.3 From e579b4d42d4fa934488c29f4feb442d68a677721 Mon Sep 17 00:00:00 2001 From: Luke F <283772+lukefor@users.noreply.github.com> Date: Fri, 23 Sep 2022 23:09:34 -0400 Subject: Backport pull request #8189 from jellyfin/release-10.8.z Fix GetItems IndexOutOfRangeException when IDs do not exist Original-merge: 527ed0607d5f31a232293b39daac19018518b1a0 Merged-by: Claus Vium Backported-by: Joshua M. Boniface --- MediaBrowser.Controller/Entities/Folder.cs | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 1860da4c79..92d12a86ca 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -892,29 +892,7 @@ namespace MediaBrowser.Controller.Entities private static BaseItem[] SortItemsByRequest(InternalItemsQuery query, IReadOnlyList items) { - var ids = query.ItemIds; - int size = items.Count; - - // ids can potentially contain non-unique guids, but query result cannot, - // so we include only first occurrence of each guid - var positions = new Dictionary(size); - int index = 0; - for (int i = 0; i < ids.Length; i++) - { - if (positions.TryAdd(ids[i], index)) - { - index++; - } - } - - var newItems = new BaseItem[size]; - for (int i = 0; i < size; i++) - { - var item = items[i]; - newItems[positions[item.Id]] = item; - } - - return newItems; + return items.OrderBy(i => Array.IndexOf(query.ItemIds, i.Id)).ToArray(); } public QueryResult GetItems(InternalItemsQuery query) -- cgit v1.2.3 From 0309c5622e31df7593a07880e2669bd623b71f88 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Fri, 23 Sep 2022 23:09:35 -0400 Subject: Backport pull request #8213 from jellyfin/release-10.8.z Fix high single thread usage in throttler Original-merge: ba026716c1609941ec50a26e50ef5e68cc84d0c0 Merged-by: Claus Vium Backported-by: Joshua M. Boniface --- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 2 +- .../Models/PlaybackDtos/TranscodingThrottler.cs | 15 ++++++-- .../MediaEncoding/IMediaEncoder.cs | 6 +++ .../Encoder/EncoderValidator.cs | 43 ++++++++++++++++++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 6 +++ 5 files changed, 59 insertions(+), 13 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 13dc878c1b..2adb006e48 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -654,7 +654,7 @@ namespace Jellyfin.Api.Helpers { if (EnableThrottling(state)) { - transcodingJob.TranscodingThrottler = new TranscodingThrottler(transcodingJob, new Logger(new LoggerFactory()), _serverConfigurationManager, _fileSystem); + transcodingJob.TranscodingThrottler = new TranscodingThrottler(transcodingJob, new Logger(new LoggerFactory()), _serverConfigurationManager, _fileSystem, _mediaEncoder); transcodingJob.TranscodingThrottler.Start(); } } diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index 7a1ca252cf..99376873c0 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -2,6 +2,7 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; @@ -17,6 +18,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos private readonly ILogger _logger; private readonly IConfigurationManager _config; private readonly IFileSystem _fileSystem; + private readonly IMediaEncoder _mediaEncoder; private Timer? _timer; private bool _isPaused; @@ -27,12 +29,14 @@ namespace Jellyfin.Api.Models.PlaybackDtos /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - public TranscodingThrottler(TranscodingJobDto job, ILogger logger, IConfigurationManager config, IFileSystem fileSystem) + /// Instance of the interface. + public TranscodingThrottler(TranscodingJobDto job, ILogger logger, IConfigurationManager config, IFileSystem fileSystem, IMediaEncoder mediaEncoder) { _job = job; _logger = logger; _config = config; _fileSystem = fileSystem; + _mediaEncoder = mediaEncoder; } /// @@ -55,7 +59,8 @@ namespace Jellyfin.Api.Models.PlaybackDtos try { - await _job.Process!.StandardInput.WriteLineAsync().ConfigureAwait(false); + var resumeKey = _mediaEncoder.IsPkeyPauseSupported ? "u" : Environment.NewLine; + await _job.Process!.StandardInput.WriteAsync(resumeKey).ConfigureAwait(false); _isPaused = false; } catch (Exception ex) @@ -125,11 +130,13 @@ namespace Jellyfin.Api.Models.PlaybackDtos { if (!_isPaused) { - _logger.LogDebug("Sending pause command to ffmpeg"); + var pauseKey = _mediaEncoder.IsPkeyPauseSupported ? "p" : "c"; + + _logger.LogDebug("Sending pause command [{Key}] to ffmpeg", pauseKey); try { - await _job.Process!.StandardInput.WriteAsync("c").ConfigureAwait(false); + await _job.Process!.StandardInput.WriteAsync(pauseKey).ConfigureAwait(false); _isPaused = true; } catch (Exception ex) diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index dae30cd8b3..69d0bf45cc 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -37,6 +37,12 @@ namespace MediaBrowser.Controller.MediaEncoding /// The version of encoder. Version EncoderVersion { get; } + /// + /// Whether p key pausing is supported. + /// + /// true if p key pausing is supported, false otherwise. + bool IsPkeyPauseSupported { get; } + /// /// Gets a value indicating whether the configured Vaapi device is from AMD(radeonsi/r600 Mesa driver). /// diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index d378c6e134..9b4b1db947 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -153,7 +153,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-version", false); + output = GetProcessOutput(_encoderPath, "-version", false, null); } catch (Exception ex) { @@ -234,7 +234,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-version", false); + output = GetProcessOutput(_encoderPath, "-version", false, null); } catch (Exception ex) { @@ -341,7 +341,7 @@ namespace MediaBrowser.MediaEncoding.Encoder try { - var output = GetProcessOutput(_encoderPath, "-v verbose -hide_banner -init_hw_device vaapi=va:" + renderNodePath, true); + var output = GetProcessOutput(_encoderPath, "-v verbose -hide_banner -init_hw_device vaapi=va:" + renderNodePath, true, null); return output.Contains(driverName, StringComparison.Ordinal); } catch (Exception ex) @@ -356,7 +356,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string? output = null; try { - output = GetProcessOutput(_encoderPath, "-hwaccels", false); + output = GetProcessOutput(_encoderPath, "-hwaccels", false, null); } catch (Exception ex) { @@ -384,7 +384,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-h filter=" + filter, false); + output = GetProcessOutput(_encoderPath, "-h filter=" + filter, false, null); } catch (Exception ex) { @@ -402,13 +402,34 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } + public bool CheckSupportedRuntimeKey(string keyDesc) + { + if (string.IsNullOrEmpty(keyDesc)) + { + return false; + } + + string output; + try + { + output = GetProcessOutput(_encoderPath, "-hide_banner -f lavfi -i nullsrc=s=1x1:d=500 -f null -", true, "?"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error checking supported runtime key"); + return false; + } + + return output.Contains(keyDesc, StringComparison.Ordinal); + } + private IEnumerable GetCodecs(Codec codec) { string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; string output; try { - output = GetProcessOutput(_encoderPath, "-" + codecstr, false); + output = GetProcessOutput(_encoderPath, "-" + codecstr, false, null); } catch (Exception ex) { @@ -439,7 +460,7 @@ namespace MediaBrowser.MediaEncoding.Encoder string output; try { - output = GetProcessOutput(_encoderPath, "-filters", false); + output = GetProcessOutput(_encoderPath, "-filters", false, null); } catch (Exception ex) { @@ -477,7 +498,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return dict; } - private string GetProcessOutput(string path, string arguments, bool readStdErr) + private string GetProcessOutput(string path, string arguments, bool readStdErr, string? testKey) { using (var process = new Process() { @@ -487,6 +508,7 @@ namespace MediaBrowser.MediaEncoding.Encoder UseShellExecute = false, WindowStyle = ProcessWindowStyle.Hidden, ErrorDialog = false, + RedirectStandardInput = !string.IsNullOrEmpty(testKey), RedirectStandardOutput = true, RedirectStandardError = true } @@ -496,6 +518,11 @@ namespace MediaBrowser.MediaEncoding.Encoder process.Start(); + if (!string.IsNullOrEmpty(testKey)) + { + process.StandardInput.Write(testKey); + } + return readStdErr ? process.StandardError.ReadToEnd() : process.StandardOutput.ReadToEnd(); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 7f301a9d8b..4e9f33bd92 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -67,6 +67,8 @@ namespace MediaBrowser.MediaEncoding.Encoder private List _filters = new List(); private IDictionary _filtersWithOption = new Dictionary(); + private bool _isPkeyPauseSupported = false; + private bool _isVaapiDeviceAmd = false; private bool _isVaapiDeviceInteliHD = false; private bool _isVaapiDeviceInteli965 = false; @@ -100,6 +102,8 @@ namespace MediaBrowser.MediaEncoding.Encoder public Version EncoderVersion => _ffmpegVersion; + public bool IsPkeyPauseSupported => _isPkeyPauseSupported; + public bool IsVaapiDeviceAmd => _isVaapiDeviceAmd; public bool IsVaapiDeviceInteliHD => _isVaapiDeviceInteliHD; @@ -154,6 +158,8 @@ namespace MediaBrowser.MediaEncoding.Encoder _threads = EncodingHelper.GetNumberOfThreads(null, options, null); + _isPkeyPauseSupported = validator.CheckSupportedRuntimeKey("p pause transcoding"); + // Check the Vaapi device vendor if (OperatingSystem.IsLinux() && SupportsHwaccel("vaapi") -- cgit v1.2.3 From e8c12e5078448b3ca8cd6a043cd529b70053b0c5 Mon Sep 17 00:00:00 2001 From: Bill Thornton Date: Fri, 23 Sep 2022 23:09:36 -0400 Subject: Backport pull request #8280 from jellyfin/release-10.8.z Fix ffmpeg analyze duration env var taking priority over media source Original-merge: 632fb05f467a935da5765fccd1595dfd501247d0 Merged-by: Claus Vium Backported-by: Joshua M. Boniface --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 8 ++++---- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 1d10777168..42c5517f9d 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -4991,13 +4991,13 @@ namespace MediaBrowser.Controller.MediaEncoding // The default value of -probesize is more than enough, so leave it as is. var ffmpegAnalyzeDuration = _config.GetFFmpegAnalyzeDuration() ?? string.Empty; - if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) + if (state.MediaSource.AnalyzeDurationMs > 0) { - analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration; + analyzeDurationArgument = "-analyzeduration " + (state.MediaSource.AnalyzeDurationMs.Value * 1000).ToString(CultureInfo.InvariantCulture); } - else if (state.MediaSource.AnalyzeDurationMs.HasValue) + else if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) { - analyzeDurationArgument = "-analyzeduration " + (state.MediaSource.AnalyzeDurationMs.Value * 1000).ToString(CultureInfo.InvariantCulture); + analyzeDurationArgument = "-analyzeduration " + ffmpegAnalyzeDuration; } if (!string.IsNullOrEmpty(analyzeDurationArgument)) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 4e9f33bd92..757a01715a 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -382,15 +382,15 @@ namespace MediaBrowser.MediaEncoding.Encoder string analyzeDuration = string.Empty; string ffmpegAnalyzeDuration = _config.GetFFmpegAnalyzeDuration() ?? string.Empty; - if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) - { - analyzeDuration = "-analyzeduration " + ffmpegAnalyzeDuration; - } - else if (request.MediaSource.AnalyzeDurationMs > 0) + if (request.MediaSource.AnalyzeDurationMs > 0) { analyzeDuration = "-analyzeduration " + (request.MediaSource.AnalyzeDurationMs * 1000).ToString(); } + else if (!string.IsNullOrEmpty(ffmpegAnalyzeDuration)) + { + analyzeDuration = "-analyzeduration " + ffmpegAnalyzeDuration; + } var forceEnableLogging = request.MediaSource.Protocol != MediaProtocol.File; -- cgit v1.2.3 From 5efa138c221fddf86696ed6b1c58409ad8527bd3 Mon Sep 17 00:00:00 2001 From: 1hitsong <3330318+1hitsong@users.noreply.github.com> Date: Mon, 26 Sep 2022 16:24:21 -0400 Subject: Update MediaBrowser.Controller/Lyrics/LyricInfo.cs Co-authored-by: Bond-009 --- MediaBrowser.Controller/Lyrics/LyricInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Lyrics/LyricInfo.cs b/MediaBrowser.Controller/Lyrics/LyricInfo.cs index 6ebb83d125..6ec6df5825 100644 --- a/MediaBrowser.Controller/Lyrics/LyricInfo.cs +++ b/MediaBrowser.Controller/Lyrics/LyricInfo.cs @@ -38,7 +38,7 @@ public static class LyricInfo foreach (var lyricFilePath in Directory.GetFiles(itemDirectoryPath, $"{Path.GetFileNameWithoutExtension(itemPath)}.*")) { - if (EnumerableExtensions.Contains(lyricProvider.SupportedMediaTypes, Path.GetExtension(lyricFilePath.AsSpan())[1..], StringComparison.OrdinalIgnoreCase)) + if (lyricProvider.SupportedMediaTypes.Contains(Path.GetExtension(lyricFilePath.AsSpan())[1..], StringComparison.OrdinalIgnoreCase)) { return lyricFilePath; } -- cgit v1.2.3 From 4edeccc5e0ff391a5f8c35f5f9b81a5ca0e228de Mon Sep 17 00:00:00 2001 From: Hannes Braun Date: Wed, 28 Sep 2022 16:17:08 +0200 Subject: Remove redundant using directives --- Emby.Server.Implementations/HttpServer/Security/SessionContext.cs | 1 - Emby.Server.Implementations/HttpServer/WebSocketConnection.cs | 1 - Emby.Server.Implementations/Library/LibraryManager.cs | 1 - Emby.Server.Implementations/Session/SessionWebSocketListener.cs | 1 - Emby.Server.Implementations/Sorting/StudioComparer.cs | 1 - MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs | 1 - MediaBrowser.Controller/Net/IWebSocketConnection.cs | 1 - MediaBrowser.Controller/Playlists/Playlist.cs | 1 - MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs | 1 - MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs | 2 -- MediaBrowser.Model/Branding/BrandingOptions.cs | 1 - MediaBrowser.Model/Configuration/EncodingOptions.cs | 2 -- MediaBrowser.Model/Dlna/StreamInfo.cs | 1 - src/Jellyfin.Extensions/StringExtensions.cs | 1 - src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs | 1 - tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs | 1 - tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs | 1 - tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs | 1 - tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs | 1 - tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs | 1 - .../Sorting/ParentIndexNumberComparerTests.cs | 1 - tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs | 1 - tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs | 1 - 23 files changed, 25 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs index 15ab363fe6..e0d20e2100 100644 --- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs +++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs @@ -1,6 +1,5 @@ #pragma warning disable CS1591 -using System; using System.Threading.Tasks; using Jellyfin.Data.Entities; using MediaBrowser.Common.Extensions; diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 818ccbb1b8..d095248fab 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -11,7 +11,6 @@ using Jellyfin.Extensions.Json; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Net; using MediaBrowser.Model.Session; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.HttpServer diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 250e7619fb..67f9c57658 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -46,7 +46,6 @@ using MediaBrowser.Model.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Caching.Memory; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Episode = MediaBrowser.Controller.Entities.TV.Episode; using EpisodeInfo = Emby.Naming.TV.EpisodeInfo; diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index fccf50f60f..35fd5caae7 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Net; diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index 4d89cfa8b2..c917daaad1 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -3,7 +3,6 @@ #pragma warning disable CS1591 using System; -using System.Linq; using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Sorting; diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 491662861f..c9625cf1da 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Text.Json.Serialization; using Jellyfin.Data.Entities; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Drawing; diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs index 43c7ce3708..4f2492b891 100644 --- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs +++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs @@ -6,7 +6,6 @@ using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Net; -using Microsoft.AspNetCore.Http; namespace MediaBrowser.Controller.Net { diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 828ecb2c51..7ae9ff7463 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.IO; using System.Linq; using System.Text.Json.Serialization; diff --git a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs index 095757bef7..5dbc438e44 100644 --- a/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs +++ b/MediaBrowser.MediaEncoding/Probing/MediaStreamInfoSideData.cs @@ -1,4 +1,3 @@ -using System.Collections.Generic; using System.Text.Json.Serialization; namespace MediaBrowser.MediaEncoding.Probing diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs index eb8ff96246..0d4489517e 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEditParser.cs @@ -3,12 +3,10 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Reflection; using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging; using Nikse.SubtitleEdit.Core.Common; -using Nikse.SubtitleEdit.Core.SubtitleFormats; using SubtitleFormat = Nikse.SubtitleEdit.Core.SubtitleFormats.SubtitleFormat; namespace MediaBrowser.MediaEncoding.Subtitles diff --git a/MediaBrowser.Model/Branding/BrandingOptions.cs b/MediaBrowser.Model/Branding/BrandingOptions.cs index a0adb56ef7..695267d46d 100644 --- a/MediaBrowser.Model/Branding/BrandingOptions.cs +++ b/MediaBrowser.Model/Branding/BrandingOptions.cs @@ -1,5 +1,4 @@ using System.Text.Json.Serialization; -using System.Xml.Serialization; namespace MediaBrowser.Model.Branding; diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index 73ebfba70e..f4cd2f0065 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -1,5 +1,3 @@ -using System; - #nullable disable #pragma warning disable CS1591 diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 0c66351c70..5cfa2e7e3c 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; diff --git a/src/Jellyfin.Extensions/StringExtensions.cs b/src/Jellyfin.Extensions/StringExtensions.cs index 59fb038a75..b19be071bf 100644 --- a/src/Jellyfin.Extensions/StringExtensions.cs +++ b/src/Jellyfin.Extensions/StringExtensions.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Globalization; using System.Text; using System.Text.RegularExpressions; diff --git a/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs index 497210f417..083e93de1a 100644 --- a/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs +++ b/src/Jellyfin.MediaEncoding.Hls/Extractors/IKeyframeExtractor.cs @@ -1,4 +1,3 @@ -using System; using System.Diagnostics.CodeAnalysis; using Jellyfin.MediaEncoding.Keyframes; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs index e14850eed7..fe0d7fc90f 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/AssParserTests.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using System.IO; -using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; using Microsoft.Extensions.Logging.Abstractions; using Xunit; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs index 0038b18736..2aebee5562 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SrtParserTests.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using System.IO; -using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; using Microsoft.Extensions.Logging.Abstractions; using Xunit; diff --git a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs index 3b9a71690c..6abf2d26cb 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs +++ b/tests/Jellyfin.MediaEncoding.Tests/Subtitles/SsaParserTests.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; -using System.Threading; using MediaBrowser.MediaEncoding.Subtitles; using MediaBrowser.Model.MediaInfo; using Microsoft.Extensions.Logging.Abstractions; diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs index 9a9a57be47..79f2366b89 100644 --- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; -using MediaBrowser.Model.IO; using Xunit; namespace Jellyfin.Naming.Tests.Video diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs index b761878426..cc9cfdd7dd 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs @@ -3,7 +3,6 @@ using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using Xunit; namespace Jellyfin.Naming.Tests.Video diff --git a/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs index 40f271d61b..261092e019 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Sorting/ParentIndexNumberComparerTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using Emby.Server.Implementations.Sorting; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs index adaf624a91..48c49bf848 100644 --- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs @@ -11,7 +11,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; using Serilog.Extensions.Logging; -using static MediaBrowser.Controller.Extensions.ConfigurationExtensions; namespace Jellyfin.Server.Integration.Tests { diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 7c99520308..988abce812 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using Jellyfin.Data.Entities; -- cgit v1.2.3 From 5dc30c6a6d8af9a758fd730c9da69c13847c21c3 Mon Sep 17 00:00:00 2001 From: cvium Date: Thu, 6 Oct 2022 13:57:47 +0200 Subject: fix: use HttpContext and ClaimsPrincipal instead of IAuthorizationContext --- Emby.Server.Implementations/ApplicationHost.cs | 2 - .../HttpServer/Security/SessionContext.cs | 59 --------------- .../Session/SessionWebSocketListener.cs | 16 ++-- Jellyfin.Api/Auth/BaseAuthorizationHandler.cs | 9 ++- .../SyncPlayAccessPolicy/SyncPlayAccessHandler.cs | 9 ++- Jellyfin.Api/Controllers/ArtistsController.cs | 6 +- Jellyfin.Api/Controllers/ClientLogController.cs | 7 +- Jellyfin.Api/Controllers/CollectionController.cs | 11 +-- Jellyfin.Api/Controllers/DynamicHlsController.cs | 14 +--- Jellyfin.Api/Controllers/GenresController.cs | 4 +- Jellyfin.Api/Controllers/ImageController.cs | 19 ++--- Jellyfin.Api/Controllers/InstantMixController.cs | 14 ++-- Jellyfin.Api/Controllers/ItemsController.cs | 20 ++--- Jellyfin.Api/Controllers/LibraryController.cs | 37 ++++----- Jellyfin.Api/Controllers/LiveTvController.cs | 39 ++++++---- Jellyfin.Api/Controllers/MediaInfoController.cs | 16 ++-- Jellyfin.Api/Controllers/MoviesController.cs | 2 +- Jellyfin.Api/Controllers/MusicGenresController.cs | 4 +- Jellyfin.Api/Controllers/PersonsController.cs | 4 +- Jellyfin.Api/Controllers/PlaylistsController.cs | 2 +- Jellyfin.Api/Controllers/PlaystateController.cs | 28 +++---- Jellyfin.Api/Controllers/QuickConnectController.cs | 7 +- Jellyfin.Api/Controllers/SessionController.cs | 33 ++++---- Jellyfin.Api/Controllers/StudiosController.cs | 4 +- Jellyfin.Api/Controllers/SubtitleController.cs | 8 +- Jellyfin.Api/Controllers/SuggestionsController.cs | 2 +- Jellyfin.Api/Controllers/SyncPlayController.cs | 54 ++++++------- Jellyfin.Api/Controllers/TvShowsController.cs | 8 +- .../Controllers/UniversalAudioController.cs | 14 +--- Jellyfin.Api/Controllers/UserController.cs | 23 +++--- Jellyfin.Api/Controllers/UserLibraryController.cs | 12 +-- Jellyfin.Api/Controllers/UserViewsController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 9 +-- Jellyfin.Api/Controllers/YearsController.cs | 4 +- .../Extensions/ClaimsPrincipalExtensions.cs | 81 ++++++++++++++++++++ Jellyfin.Api/Extensions/DtoExtensions.cs | 8 +- Jellyfin.Api/Helpers/AudioHelper.cs | 8 +- Jellyfin.Api/Helpers/ClaimHelpers.cs | 88 ---------------------- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 11 +-- Jellyfin.Api/Helpers/MediaInfoHelper.cs | 33 ++++---- Jellyfin.Api/Helpers/RequestHelpers.cs | 48 +++++++----- Jellyfin.Api/Helpers/StreamingHelpers.cs | 15 ++-- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 17 +++-- MediaBrowser.Controller/Net/ISessionContext.cs | 20 ----- 44 files changed, 335 insertions(+), 496 deletions(-) delete mode 100644 Emby.Server.Implementations/HttpServer/Security/SessionContext.cs create mode 100644 Jellyfin.Api/Extensions/ClaimsPrincipalExtensions.cs delete mode 100644 Jellyfin.Api/Helpers/ClaimHelpers.cs delete mode 100644 MediaBrowser.Controller/Net/ISessionContext.cs (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 91a16c199d..9a9de1059e 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -630,8 +630,6 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); - serviceCollection.AddScoped(); - serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs deleted file mode 100644 index e0d20e2100..0000000000 --- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs +++ /dev/null @@ -1,59 +0,0 @@ -#pragma warning disable CS1591 - -using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; -using MediaBrowser.Controller.Session; -using Microsoft.AspNetCore.Http; - -namespace Emby.Server.Implementations.HttpServer.Security -{ - public class SessionContext : ISessionContext - { - private readonly IUserManager _userManager; - private readonly ISessionManager _sessionManager; - private readonly IAuthorizationContext _authContext; - - public SessionContext(IUserManager userManager, IAuthorizationContext authContext, ISessionManager sessionManager) - { - _userManager = userManager; - _authContext = authContext; - _sessionManager = sessionManager; - } - - public async Task GetSession(HttpContext requestContext) - { - var authorization = await _authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); - - var user = authorization.User; - return await _sessionManager.LogSessionActivity( - authorization.Client, - authorization.Version, - authorization.DeviceId, - authorization.Device, - requestContext.GetNormalizedRemoteIp().ToString(), - user).ConfigureAwait(false); - } - - public Task GetSession(object requestContext) - { - return GetSession((HttpContext)requestContext); - } - - public async Task GetUser(HttpContext requestContext) - { - var session = await GetSession(requestContext).ConfigureAwait(false); - - return session.UserId.Equals(default) - ? null - : _userManager.GetUserById(session.UserId); - } - - public Task GetUser(object requestContext) - { - return GetUser(((HttpRequest)requestContext).HttpContext); - } - } -} diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index 35fd5caae7..c654828b1e 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Net; @@ -53,7 +54,6 @@ namespace Emby.Server.Implementations.Session private readonly ISessionManager _sessionManager; private readonly ILogger _logger; private readonly ILoggerFactory _loggerFactory; - private readonly IAuthorizationContext _authorizationContext; /// /// The KeepAlive cancellation token. @@ -66,17 +66,14 @@ namespace Emby.Server.Implementations.Session /// The logger. /// The session manager. /// The logger factory. - /// The authorization context. public SessionWebSocketListener( ILogger logger, ISessionManager sessionManager, - ILoggerFactory loggerFactory, - IAuthorizationContext authorizationContext) + ILoggerFactory loggerFactory) { _logger = logger; _sessionManager = sessionManager; _loggerFactory = loggerFactory; - _authorizationContext = authorizationContext; } /// @@ -110,21 +107,18 @@ namespace Emby.Server.Implementations.Session private async Task GetSession(HttpContext httpContext, string remoteEndpoint) { - var authorizationInfo = await _authorizationContext.GetAuthorizationInfo(httpContext) - .ConfigureAwait(false); - - if (!authorizationInfo.IsAuthenticated) + if (!httpContext.User.Identity?.IsAuthenticated ?? false) { return null; } - var deviceId = authorizationInfo.DeviceId; + var deviceId = httpContext.User.GetDeviceId(); if (httpContext.Request.Query.TryGetValue("deviceId", out var queryDeviceId)) { deviceId = queryDeviceId; } - return await _sessionManager.GetSessionByAuthenticationToken(authorizationInfo.Token, deviceId, remoteEndpoint) + return await _sessionManager.GetSessionByAuthenticationToken(httpContext.User.GetToken(), deviceId, remoteEndpoint) .ConfigureAwait(false); } diff --git a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs b/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs index 13d3257dff..92ee1dd59a 100644 --- a/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs +++ b/Jellyfin.Api/Auth/BaseAuthorizationHandler.cs @@ -1,4 +1,5 @@ using System.Security.Claims; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; @@ -51,21 +52,21 @@ namespace Jellyfin.Api.Auth bool requiredDownloadPermission = false) { // ApiKey is currently global admin, always allow. - var isApiKey = ClaimHelpers.GetIsApiKey(claimsPrincipal); + var isApiKey = claimsPrincipal.GetIsApiKey(); if (isApiKey) { return true; } // Ensure claim has userId. - var userId = ClaimHelpers.GetUserId(claimsPrincipal); - if (!userId.HasValue) + var userId = claimsPrincipal.GetUserId(); + if (userId.Equals(default)) { return false; } // Ensure userId links to a valid user. - var user = _userManager.GetUserById(userId.Value); + var user = _userManager.GetUserById(userId); if (user == null) { return false; diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs index e6c04eb082..cdd7d8a52b 100644 --- a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs +++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Data.Enums; using MediaBrowser.Common.Net; @@ -44,14 +45,14 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy return Task.CompletedTask; } - var userId = ClaimHelpers.GetUserId(context.User); - var user = _userManager.GetUserById(userId!.Value); + var userId = context.User.GetUserId(); + var user = _userManager.GetUserById(userId); if (requirement.RequiredAccess == SyncPlayAccessRequirementType.HasAccess) { if (user.SyncPlayAccess == SyncPlayUserAccessType.CreateAndJoinGroups || user.SyncPlayAccess == SyncPlayUserAccessType.JoinGroups - || _syncPlayManager.IsUserActive(userId.Value)) + || _syncPlayManager.IsUserActive(userId)) { context.Succeed(requirement); } @@ -85,7 +86,7 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy } else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.IsInGroup) { - if (_syncPlayManager.IsUserActive(userId.Value)) + if (_syncPlayManager.IsUserActive(userId)) { context.Succeed(requirement); } diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index 44796bcc4c..c059cb198a 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = null; @@ -323,7 +323,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = null; @@ -463,7 +463,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetArtistByName([FromRoute, Required] string name, [FromQuery] Guid? userId) { - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var item = _libraryManager.GetArtist(name, dtoOptions); diff --git a/Jellyfin.Api/Controllers/ClientLogController.cs b/Jellyfin.Api/Controllers/ClientLogController.cs index 98fd224307..ed073a687e 100644 --- a/Jellyfin.Api/Controllers/ClientLogController.cs +++ b/Jellyfin.Api/Controllers/ClientLogController.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.ClientLogDtos; using MediaBrowser.Controller.ClientEvent; @@ -69,10 +70,10 @@ namespace Jellyfin.Api.Controllers private (string ClientName, string ClientVersion) GetRequestInformation() { - var clientName = ClaimHelpers.GetClient(HttpContext.User) ?? "unknown-client"; - var clientVersion = ClaimHelpers.GetIsApiKey(HttpContext.User) + var clientName = HttpContext.User.GetClient() ?? "unknown-client"; + var clientVersion = HttpContext.User.GetIsApiKey() ? "apikey" - : ClaimHelpers.GetVersion(HttpContext.User) ?? "unknown-version"; + : HttpContext.User.GetVersion() ?? "unknown-version"; return (clientName, clientVersion); } diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 8a98d856c4..effc9ed7aa 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -6,7 +6,6 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Collections; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -23,22 +22,18 @@ namespace Jellyfin.Api.Controllers { private readonly ICollectionManager _collectionManager; private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; /// /// Initializes a new instance of the class. /// /// Instance of interface. /// Instance of interface. - /// Instance of interface. public CollectionController( ICollectionManager collectionManager, - IDtoService dtoService, - IAuthorizationContext authContext) + IDtoService dtoService) { _collectionManager = collectionManager; _dtoService = dtoService; - _authContext = authContext; } /// @@ -58,7 +53,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] Guid? parentId, [FromQuery] bool isLocked = false) { - var userId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).UserId; + var userId = User.GetUserId(); var item = await _collectionManager.CreateCollectionAsync(new CollectionCreationOptions { @@ -69,7 +64,7 @@ namespace Jellyfin.Api.Controllers UserIds = new[] { userId } }).ConfigureAwait(false); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var dto = _dtoService.GetBaseItemDto(item, dtoOptions); diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 3ed80f6621..0f4d3c1ebc 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -20,7 +20,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.IO; @@ -46,7 +45,6 @@ namespace Jellyfin.Api.Controllers private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; @@ -65,7 +63,6 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. @@ -80,7 +77,6 @@ namespace Jellyfin.Api.Controllers ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, - IAuthorizationContext authContext, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, @@ -95,7 +91,6 @@ namespace Jellyfin.Api.Controllers _libraryManager = libraryManager; _userManager = userManager; _dlnaManager = dlnaManager; - _authContext = authContext; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; @@ -287,8 +282,7 @@ namespace Jellyfin.Api.Controllers var cancellationToken = cancellationTokenSource.Token; var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, @@ -1393,8 +1387,7 @@ namespace Jellyfin.Api.Controllers { using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, @@ -1434,8 +1427,7 @@ namespace Jellyfin.Api.Controllers var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index e28a50750a..611643bd8a 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -157,7 +157,7 @@ namespace Jellyfin.Api.Controllers public ActionResult GetGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); Genre? item; if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase)) diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 6c7842c7b9..f092bd8820 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -17,7 +17,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Branding; using MediaBrowser.Model.Drawing; @@ -44,11 +43,9 @@ namespace Jellyfin.Api.Controllers private readonly IProviderManager _providerManager; private readonly IImageProcessor _imageProcessor; private readonly IFileSystem _fileSystem; - private readonly IAuthorizationContext _authContext; private readonly ILogger _logger; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IApplicationPaths _appPaths; - private readonly IImageEncoder _imageEncoder; /// /// Initializes a new instance of the class. @@ -58,33 +55,27 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. public ImageController( IUserManager userManager, ILibraryManager libraryManager, IProviderManager providerManager, IImageProcessor imageProcessor, IFileSystem fileSystem, - IAuthorizationContext authContext, ILogger logger, IServerConfigurationManager serverConfigurationManager, - IApplicationPaths appPaths, - IImageEncoder imageEncoder) + IApplicationPaths appPaths) { _userManager = userManager; _libraryManager = libraryManager; _providerManager = providerManager; _imageProcessor = imageProcessor; _fileSystem = fileSystem; - _authContext = authContext; _logger = logger; _serverConfigurationManager = serverConfigurationManager; _appPaths = appPaths; - _imageEncoder = imageEncoder; } /// @@ -108,7 +99,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromQuery] int? index = null) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); } @@ -155,7 +146,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromRoute] int index) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the image."); } @@ -201,7 +192,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromQuery] int? index = null) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); } @@ -245,7 +236,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] ImageType imageType, [FromRoute] int index) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, HttpContext.User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to delete the image."); } diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 9abea5938f..2e0d3cb99e 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -151,7 +151,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -186,7 +186,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -222,7 +222,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -258,7 +258,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); @@ -331,7 +331,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 4d09070dbb..3c7c375d4e 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -10,7 +10,6 @@ using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -34,7 +33,6 @@ namespace Jellyfin.Api.Controllers private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localization; private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; private readonly ILogger _logger; private readonly ISessionManager _sessionManager; @@ -45,7 +43,6 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. public ItemsController( @@ -53,7 +50,6 @@ namespace Jellyfin.Api.Controllers ILibraryManager libraryManager, ILocalizationManager localization, IDtoService dtoService, - IAuthorizationContext authContext, ILogger logger, ISessionManager sessionManager) { @@ -61,7 +57,6 @@ namespace Jellyfin.Api.Controllers _libraryManager = libraryManager; _localization = localization; _dtoService = dtoService; - _authContext = authContext; _logger = logger; _sessionManager = sessionManager; } @@ -244,21 +239,20 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true, [FromQuery] bool? enableImages = true) { - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - + var isApiKey = User.GetIsApiKey(); // if api key is used (auth.IsApiKey == true), then `user` will be null throughout this method - var user = !auth.IsApiKey && userId.HasValue && !userId.Value.Equals(default) + var user = !isApiKey && userId.HasValue && !userId.Value.Equals(default) ? _userManager.GetUserById(userId.Value) : null; // beyond this point, we're either using an api key or we have a valid user - if (!auth.IsApiKey && user is null) + if (!isApiKey && user is null) { return BadRequest("userId is required"); } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); if (includeItemTypes.Length == 1 @@ -288,12 +282,12 @@ namespace Jellyfin.Api.Controllers includeItemTypes = new[] { BaseItemKind.Playlist }; } - var enabledChannels = auth.IsApiKey + var enabledChannels = isApiKey ? Array.Empty() : user!.GetPreferenceValues(PreferenceKind.EnabledChannels); // api keys are always enabled for all folders - bool isInEnabledFolder = auth.IsApiKey + bool isInEnabledFolder = isApiKey || Array.IndexOf(user!.GetPreferenceValues(PreferenceKind.EnabledFolders), item.Id) != -1 // Assume all folders inside an EnabledChannel are enabled || Array.IndexOf(enabledChannels, item.Id) != -1 @@ -850,7 +844,7 @@ namespace Jellyfin.Api.Controllers var user = _userManager.GetUserById(userId); var parentIdGuid = parentId ?? Guid.Empty; var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var ancestorIds = Array.Empty(); diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 4cc17dd0fc..e9492a6a47 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -24,7 +24,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Configuration; @@ -50,7 +49,6 @@ namespace Jellyfin.Api.Controllers private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDtoService _dtoService; - private readonly IAuthorizationContext _authContext; private readonly IActivityManager _activityManager; private readonly ILocalizationManager _localization; private readonly ILibraryMonitor _libraryMonitor; @@ -64,7 +62,6 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. @@ -75,7 +72,6 @@ namespace Jellyfin.Api.Controllers ILibraryManager libraryManager, IUserManager userManager, IDtoService dtoService, - IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILibraryMonitor libraryMonitor, @@ -86,7 +82,6 @@ namespace Jellyfin.Api.Controllers _libraryManager = libraryManager; _userManager = userManager; _dtoService = dtoService; - _authContext = authContext; _activityManager = activityManager; _localization = localization; _libraryMonitor = libraryMonitor; @@ -184,7 +179,7 @@ namespace Jellyfin.Api.Controllers item = parent; } - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var items = themeItems .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)) .ToArray(); @@ -250,7 +245,7 @@ namespace Jellyfin.Api.Controllers item = parent; } - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var items = themeItems .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)) .ToArray(); @@ -331,11 +326,10 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public async Task DeleteItem(Guid itemId) + public ActionResult DeleteItem(Guid itemId) { var item = _libraryManager.GetItemById(itemId); - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - var user = auth.User; + var user = _userManager.GetUserById(User.GetUserId()); if (!item.CanDelete(user)) { @@ -361,7 +355,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] - public async Task DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids) + public ActionResult DeleteItems([FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] ids) { if (ids.Length == 0) { @@ -371,8 +365,7 @@ namespace Jellyfin.Api.Controllers foreach (var i in ids) { var item = _libraryManager.GetItemById(i); - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - var user = auth.User; + var user = _userManager.GetUserById(User.GetUserId()); if (!item.CanDelete(user)) { @@ -453,7 +446,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); BaseItem? parent = item.GetParent(); while (parent != null) @@ -505,7 +498,7 @@ namespace Jellyfin.Api.Controllers items = items.Where(i => i.IsHidden == val).ToList(); } - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var resultArray = _dtoService.GetBaseItemDtos(items, dtoOptions); return new QueryResult(resultArray); } @@ -622,9 +615,7 @@ namespace Jellyfin.Api.Controllers return NotFound(); } - var auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - - var user = auth.User; + var user = _userManager.GetUserById(User.GetUserId()); if (user != null) { @@ -643,7 +634,7 @@ namespace Jellyfin.Api.Controllers if (user != null) { - await LogDownloadAsync(item, user, auth).ConfigureAwait(false); + await LogDownloadAsync(item, user).ConfigureAwait(false); } var path = item.Path; @@ -704,7 +695,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request); + .AddClientFields(User); var program = item as IHasProgramAttributes; bool? isMovie = item is Movie || (program != null && program.IsMovie) || item is Trailer; @@ -892,16 +883,16 @@ namespace Jellyfin.Api.Controllers : item; } - private async Task LogDownloadAsync(BaseItem item, User user, AuthorizationInfo auth) + private async Task LogDownloadAsync(BaseItem item, User user) { try { await _activityManager.CreateAsync(new ActivityLog( string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("UserDownloadingItemWithValues"), user.Username, item.Name), "UserDownloadingContent", - auth.UserId) + User.GetUserId()) { - ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), auth.Client, auth.Device), + ShortOverview = string.Format(CultureInfo.InvariantCulture, _localization.GetLocalizedString("AppDeviceValues"), User.GetClient(), User.GetDevice()), }).ConfigureAwait(false); } catch diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 05340099bf..394df0f58b 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -17,6 +17,7 @@ using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.LiveTvDtos; using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -24,6 +25,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.LiveTv; @@ -45,10 +47,10 @@ namespace Jellyfin.Api.Controllers private readonly IHttpClientFactory _httpClientFactory; private readonly ILibraryManager _libraryManager; private readonly IDtoService _dtoService; - private readonly ISessionContext _sessionContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IConfigurationManager _configurationManager; private readonly TranscodingJobHelper _transcodingJobHelper; + private readonly ISessionManager _sessionManager; /// /// Initializes a new instance of the class. @@ -58,30 +60,30 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the class. + /// Instance of the interface. public LiveTvController( ILiveTvManager liveTvManager, IUserManager userManager, IHttpClientFactory httpClientFactory, ILibraryManager libraryManager, IDtoService dtoService, - ISessionContext sessionContext, IMediaSourceManager mediaSourceManager, IConfigurationManager configurationManager, - TranscodingJobHelper transcodingJobHelper) + TranscodingJobHelper transcodingJobHelper, + ISessionManager sessionManager) { _liveTvManager = liveTvManager; _userManager = userManager; _httpClientFactory = httpClientFactory; _libraryManager = libraryManager; _dtoService = dtoService; - _sessionContext = sessionContext; _mediaSourceManager = mediaSourceManager; _configurationManager = configurationManager; _transcodingJobHelper = transcodingJobHelper; + _sessionManager = sessionManager; } /// @@ -154,7 +156,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool addCurrentProgram = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var channelResult = _liveTvManager.GetInternalChannels( @@ -219,7 +221,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetItemById(channelId); var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -272,7 +274,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); return _liveTvManager.GetRecordings( @@ -410,7 +412,7 @@ namespace Jellyfin.Api.Controllers var item = recordingId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId); var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -599,7 +601,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); } @@ -653,7 +655,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = body.Fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes); return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); } @@ -719,7 +721,7 @@ namespace Jellyfin.Api.Controllers }; var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); return await _liveTvManager.GetRecommendedProgramsAsync(query, dtoOptions, CancellationToken.None).ConfigureAwait(false); } @@ -1210,9 +1212,16 @@ namespace Jellyfin.Api.Controllers private async Task AssertUserCanManageLiveTv() { - var user = await _sessionContext.GetUser(Request).ConfigureAwait(false); - - if (user == null) + var user = _userManager.GetUserById(User.GetUserId()); + var session = await _sessionManager.LogSessionActivity( + User.GetClient(), + User.GetVersion(), + User.GetDeviceId(), + User.GetDevice(), + HttpContext.GetNormalizedRemoteIp().ToString(), + user).ConfigureAwait(false); + + if (session.UserId.Equals(default)) { throw new SecurityException("Anonymous live tv management is not allowed."); } diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index d2852ed011..c111e92186 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -6,12 +6,12 @@ using System.Net.Mime; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.MediaInfoDtos; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.MediaInfo; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -31,7 +31,6 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IDeviceManager _deviceManager; private readonly ILibraryManager _libraryManager; - private readonly IAuthorizationContext _authContext; private readonly ILogger _logger; private readonly MediaInfoHelper _mediaInfoHelper; @@ -41,21 +40,18 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the . public MediaInfoController( IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, - IAuthorizationContext authContext, ILogger logger, MediaInfoHelper mediaInfoHelper) { _mediaSourceManager = mediaSourceManager; _deviceManager = deviceManager; _libraryManager = libraryManager; - _authContext = authContext; _logger = logger; _mediaInfoHelper = mediaInfoHelper; } @@ -122,14 +118,12 @@ namespace Jellyfin.Api.Controllers [FromQuery, ParameterObsolete] bool? allowAudioStreamCopy, [FromBody(EmptyBodyBehavior = EmptyBodyBehavior.Allow)] PlaybackInfoDto? playbackInfoDto) { - var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - var profile = playbackInfoDto?.DeviceProfile; _logger.LogDebug("GetPostedPlaybackInfo profile: {@Profile}", profile); if (profile == null) { - var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); + var caps = _deviceManager.GetCapabilities(User.GetDeviceId()); if (caps != null) { profile = caps.DeviceProfile; @@ -176,7 +170,7 @@ namespace Jellyfin.Api.Controllers item, mediaSource, profile, - authInfo, + User, maxStreamingBitrate ?? profile.MaxStreamingBitrate, startTimeTicks ?? 0, mediaSourceId ?? string.Empty, @@ -203,7 +197,7 @@ namespace Jellyfin.Api.Controllers if (mediaSource != null && mediaSource.RequiresOpening && string.IsNullOrWhiteSpace(mediaSource.LiveStreamId)) { var openStreamResult = await _mediaInfoHelper.OpenMediaSource( - Request, + HttpContext, new LiveStreamRequest { AudioStreamIndex = audioStreamIndex, @@ -276,7 +270,7 @@ namespace Jellyfin.Api.Controllers EnableDirectStream = enableDirectStream ?? openLiveStreamDto?.EnableDirectStream ?? true, DirectPlayProtocols = openLiveStreamDto?.DirectPlayProtocols ?? new[] { MediaProtocol.Http } }; - return await _mediaInfoHelper.OpenMediaSource(Request, request).ConfigureAwait(false); + return await _mediaInfoHelper.OpenMediaSource(HttpContext, request).ConfigureAwait(false); } /// diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs index 4669447049..8195fc7609 100644 --- a/Jellyfin.Api/Controllers/MoviesController.cs +++ b/Jellyfin.Api/Controllers/MoviesController.cs @@ -72,7 +72,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId.Value); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request); + .AddClientFields(User); var categories = new List(); diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 0499b29857..f4fb5f44ab 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -92,7 +92,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -145,7 +145,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) { - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); MusicGenre? item; diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index 33f1aea394..42be969b29 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool? enableImages = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -119,7 +119,7 @@ namespace Jellyfin.Api.Controllers public ActionResult GetPerson([FromRoute, Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); var item = _libraryManager.GetPerson(name); if (item == null) diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index ad85f2fb24..fb045f891e 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -200,7 +200,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var dtos = _dtoService.GetBaseItemDtos(items.Select(i => i.Item2).ToList(), dtoOptions, user); diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 6dee1c2192..0dd4bf8035 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -3,11 +3,11 @@ using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Session; @@ -29,7 +29,6 @@ namespace Jellyfin.Api.Controllers private readonly IUserDataManager _userDataRepository; private readonly ILibraryManager _libraryManager; private readonly ISessionManager _sessionManager; - private readonly IAuthorizationContext _authContext; private readonly ILogger _logger; private readonly TranscodingJobHelper _transcodingJobHelper; @@ -40,7 +39,6 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Th singleton. public PlaystateController( @@ -48,7 +46,6 @@ namespace Jellyfin.Api.Controllers IUserDataManager userDataRepository, ILibraryManager libraryManager, ISessionManager sessionManager, - IAuthorizationContext authContext, ILoggerFactory loggerFactory, TranscodingJobHelper transcodingJobHelper) { @@ -56,7 +53,6 @@ namespace Jellyfin.Api.Controllers _userDataRepository = userDataRepository; _libraryManager = libraryManager; _sessionManager = sessionManager; - _authContext = authContext; _logger = loggerFactory.CreateLogger(); _transcodingJobHelper = transcodingJobHelper; @@ -78,7 +74,7 @@ namespace Jellyfin.Api.Controllers [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed) { var user = _userManager.GetUserById(userId); - var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var dto = UpdatePlayedStatus(user, itemId, true, datePlayed); foreach (var additionalUserInfo in session.AdditionalUsers) { @@ -101,7 +97,7 @@ namespace Jellyfin.Api.Controllers public async Task> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); - var session = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var session = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var dto = UpdatePlayedStatus(user, itemId, false, null); foreach (var additionalUserInfo in session.AdditionalUsers) { @@ -123,7 +119,7 @@ namespace Jellyfin.Api.Controllers public async Task ReportPlaybackStart([FromBody] PlaybackStartInfo playbackStartInfo) { playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); - playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); return NoContent(); } @@ -139,7 +135,7 @@ namespace Jellyfin.Api.Controllers public async Task ReportPlaybackProgress([FromBody] PlaybackProgressInfo playbackProgressInfo) { playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); - playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); return NoContent(); } @@ -171,11 +167,10 @@ namespace Jellyfin.Api.Controllers _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) { - var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); + await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } - playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); return NoContent(); } @@ -221,7 +216,7 @@ namespace Jellyfin.Api.Controllers }; playbackStartInfo.PlayMethod = ValidatePlayMethod(playbackStartInfo.PlayMethod, playbackStartInfo.PlaySessionId); - playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStartInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStart(playbackStartInfo).ConfigureAwait(false); return NoContent(); } @@ -279,7 +274,7 @@ namespace Jellyfin.Api.Controllers }; playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); - playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); return NoContent(); } @@ -321,11 +316,10 @@ namespace Jellyfin.Api.Controllers _logger.LogDebug("ReportPlaybackStopped PlaySessionId: {0}", playbackStopInfo.PlaySessionId ?? string.Empty); if (!string.IsNullOrWhiteSpace(playbackStopInfo.PlaySessionId)) { - var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - await _transcodingJobHelper.KillTranscodingJobs(authInfo.DeviceId, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); + await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } - playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/QuickConnectController.cs b/Jellyfin.Api/Controllers/QuickConnectController.cs index 1df26355f0..77d88475ff 100644 --- a/Jellyfin.Api/Controllers/QuickConnectController.cs +++ b/Jellyfin.Api/Controllers/QuickConnectController.cs @@ -1,6 +1,7 @@ using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Authentication; @@ -104,15 +105,15 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task> AuthorizeQuickConnect([FromQuery, Required] string code) { - var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); - if (!userId.HasValue) + var userId = User.GetUserId(); + if (userId.Equals(default)) { return StatusCode(StatusCodes.Status403Forbidden, "Unknown user id"); } try { - return await _quickConnect.AuthorizeRequest(userId.Value, code).ConfigureAwait(false); + return await _quickConnect.AuthorizeRequest(userId, code).ConfigureAwait(false); } catch (AuthenticationException) { diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 860bccb9bd..28415555ed 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -5,13 +5,13 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.SessionDtos; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Session; @@ -29,7 +29,6 @@ namespace Jellyfin.Api.Controllers { private readonly ISessionManager _sessionManager; private readonly IUserManager _userManager; - private readonly IAuthorizationContext _authContext; private readonly IDeviceManager _deviceManager; /// @@ -37,17 +36,14 @@ namespace Jellyfin.Api.Controllers /// /// Instance of interface. /// Instance of interface. - /// Instance of interface. /// Instance of interface. public SessionController( ISessionManager sessionManager, IUserManager userManager, - IAuthorizationContext authContext, IDeviceManager deviceManager) { _sessionManager = sessionManager; _userManager = userManager; - _authContext = authContext; _deviceManager = deviceManager; } @@ -139,7 +135,7 @@ namespace Jellyfin.Api.Controllers }; await _sessionManager.SendBrowseCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, command, CancellationToken.None) @@ -186,7 +182,7 @@ namespace Jellyfin.Api.Controllers }; await _sessionManager.SendPlayCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, playRequest, CancellationToken.None) @@ -214,7 +210,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? controllingUserId) { await _sessionManager.SendPlaystateCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, new PlaystateRequest() { @@ -242,14 +238,14 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string sessionId, [FromRoute, Required] GeneralCommandType command) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var generalCommand = new GeneralCommand { Name = command, ControllingUserId = currentSession.UserId }; - await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None); + await _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None).ConfigureAwait(false); return NoContent(); } @@ -268,7 +264,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string sessionId, [FromRoute, Required] GeneralCommandType command) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var generalCommand = new GeneralCommand { @@ -296,8 +292,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string sessionId, [FromBody, Required] GeneralCommand command) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authContext, Request) - .ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); if (command == null) { @@ -336,7 +331,7 @@ namespace Jellyfin.Api.Controllers } await _sessionManager.SendMessageCommand( - await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, command, CancellationToken.None) @@ -405,7 +400,7 @@ namespace Jellyfin.Api.Controllers { if (string.IsNullOrWhiteSpace(id)) { - id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + id = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); } _sessionManager.ReportCapabilities(id, new ClientCapabilities @@ -435,7 +430,7 @@ namespace Jellyfin.Api.Controllers { if (string.IsNullOrWhiteSpace(id)) { - id = await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + id = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); } _sessionManager.ReportCapabilities(id, capabilities.ToClientCapabilities()); @@ -457,7 +452,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? sessionId, [FromQuery, Required] string? itemId) { - string session = sessionId ?? await RequestHelpers.GetSessionId(_sessionManager, _authContext, Request).ConfigureAwait(false); + string session = sessionId ?? await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); _sessionManager.ReportNowViewingItem(session, itemId); return NoContent(); @@ -473,9 +468,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ReportSessionEnded() { - AuthorizationInfo auth = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - - await _sessionManager.Logout(auth.Token).ConfigureAwait(false); + await _sessionManager.Logout(User.GetToken()).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index 053c7baaa1..1288fb5124 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetStudio([FromRoute, Required] string name, [FromQuery] Guid? userId) { - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var item = _libraryManager.GetStudio(name); if (userId.HasValue && !userId.Equals(default)) diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 16acedcf35..1258a9876b 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -11,13 +11,13 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.SubtitleDtos; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Subtitles; using MediaBrowser.Model.Entities; @@ -45,7 +45,6 @@ namespace Jellyfin.Api.Controllers private readonly IMediaSourceManager _mediaSourceManager; private readonly IProviderManager _providerManager; private readonly IFileSystem _fileSystem; - private readonly IAuthorizationContext _authContext; private readonly ILogger _logger; /// @@ -58,7 +57,6 @@ namespace Jellyfin.Api.Controllers /// Instance of interface. /// Instance of interface. /// Instance of interface. - /// Instance of interface. /// Instance of interface. public SubtitleController( IServerConfigurationManager serverConfigurationManager, @@ -68,7 +66,6 @@ namespace Jellyfin.Api.Controllers IMediaSourceManager mediaSourceManager, IProviderManager providerManager, IFileSystem fileSystem, - IAuthorizationContext authContext, ILogger logger) { _serverConfigurationManager = serverConfigurationManager; @@ -78,7 +75,6 @@ namespace Jellyfin.Api.Controllers _mediaSourceManager = mediaSourceManager; _providerManager = providerManager; _fileSystem = fileSystem; - _authContext = authContext; _logger = logger; } @@ -361,7 +357,7 @@ namespace Jellyfin.Api.Controllers long positionTicks = 0; - var accessToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; + var accessToken = User.GetToken(); while (positionTicks < runtime) { diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index e9c46dcf3a..1cf528153f 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -67,7 +67,7 @@ namespace Jellyfin.Api.Controllers ? null : _userManager.GetUserById(userId); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user) { OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) }, diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs index c6b70f3d20..e194fc556e 100644 --- a/Jellyfin.Api/Controllers/SyncPlayController.cs +++ b/Jellyfin.Api/Controllers/SyncPlayController.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.SyncPlayDtos; -using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.SyncPlay; using MediaBrowser.Controller.SyncPlay.PlaybackRequests; @@ -24,23 +24,23 @@ namespace Jellyfin.Api.Controllers public class SyncPlayController : BaseJellyfinApiController { private readonly ISessionManager _sessionManager; - private readonly IAuthorizationContext _authorizationContext; private readonly ISyncPlayManager _syncPlayManager; + private readonly IUserManager _userManager; /// /// Initializes a new instance of the class. /// /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public SyncPlayController( ISessionManager sessionManager, - IAuthorizationContext authorizationContext, - ISyncPlayManager syncPlayManager) + ISyncPlayManager syncPlayManager, + IUserManager userManager) { _sessionManager = sessionManager; - _authorizationContext = authorizationContext; _syncPlayManager = syncPlayManager; + _userManager = userManager; } /// @@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayCreateGroup( [FromBody, Required] NewGroupRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new NewGroupRequest(requestData.GroupName); _syncPlayManager.NewGroup(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayJoinGroup( [FromBody, Required] JoinGroupRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new JoinGroupRequest(requestData.GroupId); _syncPlayManager.JoinGroup(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task SyncPlayLeaveGroup() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new LeaveGroupRequest(); _syncPlayManager.LeaveGroup(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -105,7 +105,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayJoinGroup)] public async Task>> SyncPlayGetGroups() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new ListGroupsRequest(); return Ok(_syncPlayManager.ListGroups(currentSession, syncPlayRequest)); } @@ -122,7 +122,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlaySetNewQueue( [FromBody, Required] PlayRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PlayGroupRequest( requestData.PlayingQueue, requestData.PlayingItemPosition, @@ -143,7 +143,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlaySetPlaylistItem( [FromBody, Required] SetPlaylistItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SetPlaylistItemGroupRequest(requestData.PlaylistItemId); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayRemoveFromPlaylist( [FromBody, Required] RemoveFromPlaylistRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new RemoveFromPlaylistGroupRequest(requestData.PlaylistItemIds, requestData.ClearPlaylist, requestData.ClearPlayingItem); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayMovePlaylistItem( [FromBody, Required] MovePlaylistItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new MovePlaylistItemGroupRequest(requestData.PlaylistItemId, requestData.NewIndex); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -197,7 +197,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayQueue( [FromBody, Required] QueueRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new QueueGroupRequest(requestData.ItemIds, requestData.Mode); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -213,7 +213,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task SyncPlayUnpause() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new UnpauseGroupRequest(); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -229,7 +229,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task SyncPlayPause() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PauseGroupRequest(); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -245,7 +245,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.SyncPlayIsInGroup)] public async Task SyncPlayStop() { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new StopGroupRequest(); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -263,7 +263,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlaySeek( [FromBody, Required] SeekRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SeekGroupRequest(requestData.PositionTicks); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -281,7 +281,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayBuffering( [FromBody, Required] BufferRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new BufferGroupRequest( requestData.When, requestData.PositionTicks, @@ -303,7 +303,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayReady( [FromBody, Required] ReadyRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new ReadyGroupRequest( requestData.When, requestData.PositionTicks, @@ -325,7 +325,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlaySetIgnoreWait( [FromBody, Required] IgnoreWaitRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new IgnoreWaitGroupRequest(requestData.IgnoreWait); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -343,7 +343,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayNextItem( [FromBody, Required] NextItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new NextItemGroupRequest(requestData.PlaylistItemId); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -361,7 +361,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayPreviousItem( [FromBody, Required] PreviousItemRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PreviousItemGroupRequest(requestData.PlaylistItemId); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -379,7 +379,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlaySetRepeatMode( [FromBody, Required] SetRepeatModeRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SetRepeatModeGroupRequest(requestData.Mode); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -397,7 +397,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlaySetShuffleMode( [FromBody, Required] SetShuffleModeRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new SetShuffleModeGroupRequest(requestData.Mode); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); @@ -414,7 +414,7 @@ namespace Jellyfin.Api.Controllers public async Task SyncPlayPing( [FromBody, Required] PingRequestDto requestData) { - var currentSession = await RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request).ConfigureAwait(false); + var currentSession = await RequestHelpers.GetSession(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); var syncPlayRequest = new PingGroupRequest(requestData.Ping); _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None); return NoContent(); diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index e39d05a6f5..ea13ceb91c 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableRewatching = false) { var options = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var result = _tvSeriesManager.GetNextUp( @@ -154,7 +154,7 @@ namespace Jellyfin.Api.Controllers var parentIdGuid = parentId ?? Guid.Empty; var options = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers List episodes; var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); if (seasonId.HasValue) // Season id was supplied. Get episodes by season id. @@ -349,7 +349,7 @@ namespace Jellyfin.Api.Controllers }); var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user); diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index c463fb08aa..01e13b4fe3 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -6,13 +6,13 @@ using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.MediaInfo; using Microsoft.AspNetCore.Authorization; @@ -28,7 +28,6 @@ namespace Jellyfin.Api.Controllers [Route("")] public class UniversalAudioController : BaseJellyfinApiController { - private readonly IAuthorizationContext _authorizationContext; private readonly ILibraryManager _libraryManager; private readonly ILogger _logger; private readonly MediaInfoHelper _mediaInfoHelper; @@ -38,21 +37,18 @@ namespace Jellyfin.Api.Controllers /// /// Initializes a new instance of the class. /// - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of . /// Instance of . /// Instance of . public UniversalAudioController( - IAuthorizationContext authorizationContext, ILibraryManager libraryManager, ILogger logger, MediaInfoHelper mediaInfoHelper, AudioHelper audioHelper, DynamicHlsHelper dynamicHlsHelper) { - _authorizationContext = authorizationContext; _libraryManager = libraryManager; _logger = logger; _mediaInfoHelper = mediaInfoHelper; @@ -111,16 +107,12 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableRedirection = true) { var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); - var authorizationInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - authorizationInfo.DeviceId = deviceId; if (!userId.HasValue || userId.Value.Equals(Guid.Empty)) { - userId = authorizationInfo.UserId; + userId = User.GetUserId(); } - var authInfo = await _authorizationContext.GetAuthorizationInfo(Request).ConfigureAwait(false); - _logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", deviceProfile); var info = await _mediaInfoHelper.GetPlaybackInfo( @@ -138,7 +130,7 @@ namespace Jellyfin.Api.Controllers item, sourceInfo, deviceProfile, - authInfo, + User, maxStreamingBitrate ?? deviceProfile.MaxStreamingBitrate, startTimeTicks ?? 0, mediaSourceId ?? string.Empty, diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index d1109bebc8..004690541b 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.UserDtos; using Jellyfin.Data.Enums; @@ -264,7 +265,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UpdateUserPassword request) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the password."); } @@ -282,7 +283,7 @@ namespace Jellyfin.Api.Controllers } else { - if (!HttpContext.User.IsInRole(UserRoles.Administrator)) + if (!User.IsInRole(UserRoles.Administrator)) { var success = await _userManager.AuthenticateUser( user.Username, @@ -299,7 +300,7 @@ namespace Jellyfin.Api.Controllers await _userManager.ChangePassword(user, request.NewPw).ConfigureAwait(false); - var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; + var currentToken = User.GetToken(); await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); } @@ -325,7 +326,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UpdateUserEasyPassword request) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User is not allowed to update the easy password."); } @@ -367,7 +368,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UserDto updateUser) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User update not allowed."); } @@ -427,7 +428,7 @@ namespace Jellyfin.Api.Controllers return StatusCode(StatusCodes.Status403Forbidden, "There must be at least one enabled user in the system."); } - var currentToken = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Token; + var currentToken = User.GetToken(); await _sessionManager.RevokeUserTokens(user.Id, currentToken).ConfigureAwait(false); } @@ -452,7 +453,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromBody, Required] UserConfiguration userConfig) { - if (!await RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false).ConfigureAwait(false)) + if (!RequestHelpers.AssertCanUpdateUser(_userManager, User, userId, true)) { return StatusCode(StatusCodes.Status403Forbidden, "User configuration update not allowed"); } @@ -536,13 +537,13 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult GetCurrentUser() { - var userId = ClaimHelpers.GetUserId(Request.HttpContext.User); - if (userId is null) + var userId = User.GetUserId(); + if (userId.Equals(default)) { return BadRequest(); } - var user = _userManager.GetUserById(userId.Value); + var user = _userManager.GetUserById(userId); if (user == null) { return BadRequest(); @@ -567,7 +568,7 @@ namespace Jellyfin.Api.Controllers if (filterByDevice) { - var deviceId = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).DeviceId; + var deviceId = User.GetDeviceId(); if (!string.IsNullOrWhiteSpace(deviceId)) { diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 940fa27a70..ee8a17b62d 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers await RefreshItemOnDemandIfNeeded(item).ConfigureAwait(false); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -98,7 +98,7 @@ namespace Jellyfin.Api.Controllers { var user = _userManager.GetUserById(userId); var item = _libraryManager.GetUserRootFolder(); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); return _dtoService.GetBaseItemDto(item, dtoOptions, user); } @@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetItemById(itemId); var items = await _libraryManager.GetIntros(item, user).ConfigureAwait(false); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var dtos = items.Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user)).ToArray(); return new QueryResult(dtos); @@ -200,7 +200,7 @@ namespace Jellyfin.Api.Controllers ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); if (item is IHasTrailers hasTrailers) { @@ -230,7 +230,7 @@ namespace Jellyfin.Api.Controllers ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); return Ok(item .GetExtras() @@ -280,7 +280,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var list = _userViewManager.GetLatestItems( diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 04732ccf25..85d154cac2 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Controllers var folders = _userViewManager.GetUserViews(query); - var dtoOptions = new DtoOptions().AddClientFields(Request); + var dtoOptions = new DtoOptions().AddClientFields(User); var fields = dtoOptions.Fields.ToList(); fields.Add(ItemFields.PrimaryImageAspectRatio); diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 4e28959345..bf08ad376b 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -43,7 +43,6 @@ namespace Jellyfin.Api.Controllers private readonly IUserManager _userManager; private readonly IDtoService _dtoService; private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; @@ -61,7 +60,6 @@ namespace Jellyfin.Api.Controllers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. @@ -74,7 +72,6 @@ namespace Jellyfin.Api.Controllers IUserManager userManager, IDtoService dtoService, IDlnaManager dlnaManager, - IAuthorizationContext authContext, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, @@ -87,7 +84,6 @@ namespace Jellyfin.Api.Controllers _userManager = userManager; _dtoService = dtoService; _dlnaManager = dlnaManager; - _authContext = authContext; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; @@ -120,7 +116,7 @@ namespace Jellyfin.Api.Controllers : _libraryManager.GetItemById(itemId); var dtoOptions = new DtoOptions(); - dtoOptions = dtoOptions.AddClientFields(Request); + dtoOptions = dtoOptions.AddClientFields(User); BaseItemDto[] items; if (item is Video video) @@ -429,8 +425,7 @@ namespace Jellyfin.Api.Controllers var state = await StreamingHelpers.GetStreamingState( streamingRequest, - Request, - _authContext, + HttpContext, _mediaSourceManager, _userManager, _libraryManager, diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 7c02e25501..b732bdff3c 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -87,7 +87,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool? enableImages = true) { var dtoOptions = new DtoOptions { Fields = fields } - .AddClientFields(Request) + .AddClientFields(User) .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); User? user = userId is null || userId.Value.Equals(default) @@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers } var dtoOptions = new DtoOptions() - .AddClientFields(Request); + .AddClientFields(User); if (userId.HasValue && !userId.Value.Equals(default)) { diff --git a/Jellyfin.Api/Extensions/ClaimsPrincipalExtensions.cs b/Jellyfin.Api/Extensions/ClaimsPrincipalExtensions.cs new file mode 100644 index 0000000000..6b3e78d4d1 --- /dev/null +++ b/Jellyfin.Api/Extensions/ClaimsPrincipalExtensions.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; +using System.Security.Claims; +using Jellyfin.Api.Constants; + +namespace Jellyfin.Api.Extensions; + +/// +/// Extensions for . +/// +public static class ClaimsPrincipalExtensions +{ + /// + /// Get user id from claims. + /// + /// Current claims principal. + /// User id. + public static Guid GetUserId(this ClaimsPrincipal user) + { + var value = GetClaimValue(user, InternalClaimTypes.UserId); + return string.IsNullOrEmpty(value) + ? default + : Guid.Parse(value); + } + + /// + /// Get device id from claims. + /// + /// Current claims principal. + /// Device id. + public static string? GetDeviceId(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.DeviceId); + + /// + /// Get device from claims. + /// + /// Current claims principal. + /// Device. + public static string? GetDevice(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Device); + + /// + /// Get client from claims. + /// + /// Current claims principal. + /// Client. + public static string? GetClient(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Client); + + /// + /// Get version from claims. + /// + /// Current claims principal. + /// Version. + public static string? GetVersion(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Version); + + /// + /// Get token from claims. + /// + /// Current claims principal. + /// Token. + public static string? GetToken(this ClaimsPrincipal user) + => GetClaimValue(user, InternalClaimTypes.Token); + + /// + /// Gets a flag specifying whether the request is using an api key. + /// + /// Current claims principal. + /// The flag specifying whether the request is using an api key. + public static bool GetIsApiKey(this ClaimsPrincipal user) + { + var claimValue = GetClaimValue(user, InternalClaimTypes.IsApiKey); + return !string.IsNullOrEmpty(claimValue) + && bool.TryParse(claimValue, out var parsedClaimValue) + && parsedClaimValue; + } + + private static string? GetClaimValue(in ClaimsPrincipal user, string name) + => user.Claims.FirstOrDefault(claim => claim.Type.Equals(name, StringComparison.OrdinalIgnoreCase))?.Value; +} diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs index 5e338b67da..9e784f7c45 100644 --- a/Jellyfin.Api/Extensions/DtoExtensions.cs +++ b/Jellyfin.Api/Extensions/DtoExtensions.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using Jellyfin.Api.Helpers; +using System.Security.Claims; using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Model.Entities; @@ -22,14 +22,14 @@ namespace Jellyfin.Api.Extensions /// Legacy order: 2. /// /// DtoOptions object. - /// Current request. + /// Current claims principal. /// Modified DtoOptions object. internal static DtoOptions AddClientFields( - this DtoOptions dtoOptions, HttpRequest request) + this DtoOptions dtoOptions, ClaimsPrincipal user) { dtoOptions.Fields ??= Array.Empty(); - string? client = ClaimHelpers.GetClient(request.HttpContext.User); + string? client = user.GetClient(); // No client in claim if (string.IsNullOrEmpty(client)) diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 27497cd599..bc83ff48a8 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -11,7 +11,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; using Microsoft.AspNetCore.Http; @@ -25,7 +24,6 @@ namespace Jellyfin.Api.Helpers public class AudioHelper { private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IUserManager _userManager; private readonly ILibraryManager _libraryManager; private readonly IMediaSourceManager _mediaSourceManager; @@ -41,7 +39,6 @@ namespace Jellyfin.Api.Helpers /// Initializes a new instance of the class. /// /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. @@ -54,7 +51,6 @@ namespace Jellyfin.Api.Helpers /// Instance of . public AudioHelper( IDlnaManager dlnaManager, - IAuthorizationContext authContext, IUserManager userManager, ILibraryManager libraryManager, IMediaSourceManager mediaSourceManager, @@ -67,7 +63,6 @@ namespace Jellyfin.Api.Helpers EncodingHelper encodingHelper) { _dlnaManager = dlnaManager; - _authContext = authContext; _userManager = userManager; _libraryManager = libraryManager; _mediaSourceManager = mediaSourceManager; @@ -102,8 +97,7 @@ namespace Jellyfin.Api.Helpers using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - _httpContextAccessor.HttpContext.Request, - _authContext, + _httpContextAccessor.HttpContext, _mediaSourceManager, _userManager, _libraryManager, diff --git a/Jellyfin.Api/Helpers/ClaimHelpers.cs b/Jellyfin.Api/Helpers/ClaimHelpers.cs deleted file mode 100644 index c1c2f93b49..0000000000 --- a/Jellyfin.Api/Helpers/ClaimHelpers.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Linq; -using System.Security.Claims; -using Jellyfin.Api.Constants; - -namespace Jellyfin.Api.Helpers -{ - /// - /// Claim Helpers. - /// - public static class ClaimHelpers - { - /// - /// Get user id from claims. - /// - /// Current claims principal. - /// User id. - public static Guid? GetUserId(in ClaimsPrincipal user) - { - var value = GetClaimValue(user, InternalClaimTypes.UserId); - return string.IsNullOrEmpty(value) - ? null - : Guid.Parse(value); - } - - /// - /// Get device id from claims. - /// - /// Current claims principal. - /// Device id. - public static string? GetDeviceId(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.DeviceId); - - /// - /// Get device from claims. - /// - /// Current claims principal. - /// Device. - public static string? GetDevice(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Device); - - /// - /// Get client from claims. - /// - /// Current claims principal. - /// Client. - public static string? GetClient(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Client); - - /// - /// Get version from claims. - /// - /// Current claims principal. - /// Version. - public static string? GetVersion(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Version); - - /// - /// Get token from claims. - /// - /// Current claims principal. - /// Token. - public static string? GetToken(in ClaimsPrincipal user) - => GetClaimValue(user, InternalClaimTypes.Token); - - /// - /// Gets a flag specifying whether the request is using an api key. - /// - /// Current claims principal. - /// The flag specifying whether the request is using an api key. - public static bool GetIsApiKey(in ClaimsPrincipal user) - { - var claimValue = GetClaimValue(user, InternalClaimTypes.IsApiKey); - return !string.IsNullOrEmpty(claimValue) - && bool.TryParse(claimValue, out var parsedClaimValue) - && parsedClaimValue; - } - - private static string? GetClaimValue(in ClaimsPrincipal user, string name) - { - return user?.Identities - .SelectMany(c => c.Claims) - .Where(claim => claim.Type.Equals(name, StringComparison.OrdinalIgnoreCase)) - .Select(claim => claim.Value) - .FirstOrDefault(); - } - } -} diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 83c9141a93..fa392e5674 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -7,6 +7,7 @@ using System.Security.Claims; using System.Text; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; @@ -15,7 +16,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Net; @@ -34,7 +34,6 @@ namespace Jellyfin.Api.Helpers private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; private readonly IDlnaManager _dlnaManager; - private readonly IAuthorizationContext _authContext; private readonly IMediaSourceManager _mediaSourceManager; private readonly IServerConfigurationManager _serverConfigurationManager; private readonly IMediaEncoder _mediaEncoder; @@ -51,7 +50,6 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. @@ -65,7 +63,6 @@ namespace Jellyfin.Api.Helpers ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, - IAuthorizationContext authContext, IMediaSourceManager mediaSourceManager, IServerConfigurationManager serverConfigurationManager, IMediaEncoder mediaEncoder, @@ -79,7 +76,6 @@ namespace Jellyfin.Api.Helpers _libraryManager = libraryManager; _userManager = userManager; _dlnaManager = dlnaManager; - _authContext = authContext; _mediaSourceManager = mediaSourceManager; _serverConfigurationManager = serverConfigurationManager; _mediaEncoder = mediaEncoder; @@ -128,8 +124,7 @@ namespace Jellyfin.Api.Helpers using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - _httpContextAccessor.HttpContext.Request, - _authContext, + _httpContextAccessor.HttpContext, _mediaSourceManager, _userManager, _libraryManager, @@ -483,7 +478,7 @@ namespace Jellyfin.Api.Helpers state.Request.MediaSourceId, stream.Index.ToString(CultureInfo.InvariantCulture), 30.ToString(CultureInfo.InvariantCulture), - ClaimHelpers.GetToken(user)); + user.GetToken()); var line = string.Format( CultureInfo.InvariantCulture, diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs index 5c05c57a61..11f490bb41 100644 --- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs +++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs @@ -2,9 +2,11 @@ using System.Globalization; using System.Linq; using System.Net; +using System.Security.Claims; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; @@ -15,7 +17,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -39,7 +40,6 @@ namespace Jellyfin.Api.Helpers private readonly ILogger _logger; private readonly INetworkManager _networkManager; private readonly IDeviceManager _deviceManager; - private readonly IAuthorizationContext _authContext; /// /// Initializes a new instance of the class. @@ -52,7 +52,6 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. public MediaInfoHelper( IUserManager userManager, ILibraryManager libraryManager, @@ -61,8 +60,7 @@ namespace Jellyfin.Api.Helpers IServerConfigurationManager serverConfigurationManager, ILogger logger, INetworkManager networkManager, - IDeviceManager deviceManager, - IAuthorizationContext authContext) + IDeviceManager deviceManager) { _userManager = userManager; _libraryManager = libraryManager; @@ -72,7 +70,6 @@ namespace Jellyfin.Api.Helpers _logger = logger; _networkManager = networkManager; _deviceManager = deviceManager; - _authContext = authContext; } /// @@ -147,7 +144,7 @@ namespace Jellyfin.Api.Helpers /// Item to set data for. /// Media source info. /// Device profile. - /// Authorization info. + /// Current claims principal. /// Max bitrate. /// Start time ticks. /// Media source id. @@ -166,7 +163,7 @@ namespace Jellyfin.Api.Helpers BaseItem item, MediaSourceInfo mediaSource, DeviceProfile profile, - AuthorizationInfo auth, + ClaimsPrincipal claimsPrincipal, int? maxBitrate, long startTimeTicks, string mediaSourceId, @@ -188,7 +185,7 @@ namespace Jellyfin.Api.Helpers { MediaSources = new[] { mediaSource }, Context = EncodingContext.Streaming, - DeviceId = auth.DeviceId, + DeviceId = claimsPrincipal.GetDeviceId(), ItemId = item.Id, Profile = profile, MaxAudioChannels = maxAudioChannels, @@ -290,7 +287,7 @@ namespace Jellyfin.Api.Helpers mediaSource.SupportsDirectPlay = false; mediaSource.SupportsDirectStream = false; - mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); + mediaSource.TranscodingUrl = streamInfo.ToUrl("-", claimsPrincipal.GetToken()).TrimStart('-'); mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false"; mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false"; mediaSource.TranscodingContainer = streamInfo.Container; @@ -301,7 +298,7 @@ namespace Jellyfin.Api.Helpers if (!mediaSource.SupportsDirectPlay && (mediaSource.SupportsTranscoding || mediaSource.SupportsDirectStream)) { streamInfo.PlayMethod = PlayMethod.Transcode; - mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-'); + mediaSource.TranscodingUrl = streamInfo.ToUrl("-", claimsPrincipal.GetToken()).TrimStart('-'); if (!allowVideoStreamCopy) { @@ -316,7 +313,7 @@ namespace Jellyfin.Api.Helpers } // Do this after the above so that StartPositionTicks is set - SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token); + SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, claimsPrincipal.GetToken()); mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex; } @@ -384,19 +381,17 @@ namespace Jellyfin.Api.Helpers /// /// Open media source. /// - /// Http Request. + /// Http Context. /// Live stream request. /// A containing the . - public async Task OpenMediaSource(HttpRequest httpRequest, LiveStreamRequest request) + public async Task OpenMediaSource(HttpContext httpContext, LiveStreamRequest request) { - var authInfo = await _authContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false); - var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); var profile = request.DeviceProfile; if (profile == null) { - var clientCapabilities = _deviceManager.GetCapabilities(authInfo.DeviceId); + var clientCapabilities = _deviceManager.GetCapabilities(httpContext.User.GetDeviceId()); if (clientCapabilities != null) { profile = clientCapabilities.DeviceProfile; @@ -411,7 +406,7 @@ namespace Jellyfin.Api.Helpers item, result.MediaSource, profile, - authInfo, + httpContext.User, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, result.MediaSource.Id, @@ -425,7 +420,7 @@ namespace Jellyfin.Api.Helpers true, true, true, - httpRequest.HttpContext.GetNormalizedRemoteIp()); + httpContext.GetNormalizedRemoteIp()); } else { diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index 20427d7fab..8c5af013aa 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -1,13 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Claims; using System.Threading.Tasks; +using Jellyfin.Api.Constants; +using Jellyfin.Api.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Net; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -55,37 +58,42 @@ namespace Jellyfin.Api.Helpers /// /// Checks if the user can update an entry. /// - /// Instance of the interface. - /// The . + /// An instance of the interface. + /// The for the current request. /// The user id. /// Whether to restrict the user preferences. /// A whether the user can update the entry. - internal static async Task AssertCanUpdateUser(IAuthorizationContext authContext, HttpRequest requestContext, Guid userId, bool restrictUserPreferences) + internal static bool AssertCanUpdateUser(IUserManager userManager, ClaimsPrincipal claimsPrincipal, Guid userId, bool restrictUserPreferences) { - var auth = await authContext.GetAuthorizationInfo(requestContext).ConfigureAwait(false); - - var authenticatedUser = auth.User; + var authenticatedUserId = claimsPrincipal.GetUserId(); + var isAdministrator = claimsPrincipal.IsInRole(UserRoles.Administrator); // If they're going to update the record of another user, they must be an administrator - if ((!userId.Equals(auth.UserId) && !authenticatedUser.HasPermission(PermissionKind.IsAdministrator)) - || (restrictUserPreferences && !authenticatedUser.EnableUserPreferenceAccess)) + if (!userId.Equals(authenticatedUserId) && !isAdministrator) { return false; } - return true; + // TODO the EnableUserPreferenceAccess policy does not seem to be used elsewhere + if (!restrictUserPreferences || isAdministrator) + { + return true; + } + + var user = userManager.GetUserById(userId); + return user.EnableUserPreferenceAccess; } - internal static async Task GetSession(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) + internal static async Task GetSession(ISessionManager sessionManager, IUserManager userManager, HttpContext httpContext) { - var authorization = await authContext.GetAuthorizationInfo(request).ConfigureAwait(false); - var user = authorization.User; + var userId = httpContext.User.GetUserId(); + var user = userManager.GetUserById(userId); var session = await sessionManager.LogSessionActivity( - authorization.Client, - authorization.Version, - authorization.DeviceId, - authorization.Device, - request.HttpContext.GetNormalizedRemoteIp().ToString(), + httpContext.User.GetClient(), + httpContext.User.GetVersion(), + httpContext.User.GetDeviceId(), + httpContext.User.GetDevice(), + httpContext.GetNormalizedRemoteIp().ToString(), user).ConfigureAwait(false); if (session == null) @@ -96,9 +104,9 @@ namespace Jellyfin.Api.Helpers return session; } - internal static async Task GetSessionId(ISessionManager sessionManager, IAuthorizationContext authContext, HttpRequest request) + internal static async Task GetSessionId(ISessionManager sessionManager, IUserManager userManager, HttpContext httpContext) { - var session = await GetSession(sessionManager, authContext, request).ConfigureAwait(false); + var session = await GetSession(sessionManager, userManager, httpContext).ConfigureAwait(false); return session.Id; } diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index b552df0a45..3705737739 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; @@ -14,7 +15,6 @@ using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -33,8 +33,7 @@ namespace Jellyfin.Api.Helpers /// Gets the current streaming state. /// /// The . - /// The . - /// Instance of the interface. + /// The . /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. @@ -49,8 +48,7 @@ namespace Jellyfin.Api.Helpers /// A containing the current . public static async Task GetStreamingState( StreamingRequestDto streamingRequest, - HttpRequest httpRequest, - IAuthorizationContext authorizationContext, + HttpContext httpContext, IMediaSourceManager mediaSourceManager, IUserManager userManager, ILibraryManager libraryManager, @@ -63,6 +61,7 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, CancellationToken cancellationToken) { + var httpRequest = httpContext.Request; // Parse the DLNA time seek header if (!streamingRequest.StartTimeTicks.HasValue) { @@ -101,10 +100,10 @@ namespace Jellyfin.Api.Helpers EnableDlnaHeaders = enableDlnaHeaders }; - var auth = await authorizationContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false); - if (!auth.UserId.Equals(default)) + var userId = httpContext.User.GetUserId(); + if (!userId.Equals(default)) { - state.User = userManager.GetUserById(auth.UserId); + state.User = userManager.GetUserById(userId); } if (state.IsVideoRequest && !string.IsNullOrWhiteSpace(state.Request.VideoCodec)) diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 2adb006e48..c663c6e310 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Extensions; using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Data.Enums; @@ -17,7 +18,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; @@ -46,7 +46,6 @@ namespace Jellyfin.Api.Helpers private readonly IAttachmentExtractor _attachmentExtractor; private readonly IApplicationPaths _appPaths; - private readonly IAuthorizationContext _authorizationContext; private readonly EncodingHelper _encodingHelper; private readonly IFileSystem _fileSystem; private readonly ILogger _logger; @@ -55,6 +54,7 @@ namespace Jellyfin.Api.Helpers private readonly IServerConfigurationManager _serverConfigurationManager; private readonly ISessionManager _sessionManager; private readonly ILoggerFactory _loggerFactory; + private readonly IUserManager _userManager; /// /// Initializes a new instance of the class. @@ -67,9 +67,9 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. - /// Instance of the interface. /// Instance of . /// Instance of the interface. + /// Instance of the interface. public TranscodingJobHelper( IAttachmentExtractor attachmentExtractor, IApplicationPaths appPaths, @@ -79,9 +79,9 @@ namespace Jellyfin.Api.Helpers IMediaEncoder mediaEncoder, IServerConfigurationManager serverConfigurationManager, ISessionManager sessionManager, - IAuthorizationContext authorizationContext, EncodingHelper encodingHelper, - ILoggerFactory loggerFactory) + ILoggerFactory loggerFactory, + IUserManager userManager) { _attachmentExtractor = attachmentExtractor; _appPaths = appPaths; @@ -91,9 +91,9 @@ namespace Jellyfin.Api.Helpers _mediaEncoder = mediaEncoder; _serverConfigurationManager = serverConfigurationManager; _sessionManager = sessionManager; - _authorizationContext = authorizationContext; _encodingHelper = encodingHelper; _loggerFactory = loggerFactory; + _userManager = userManager; DeleteEncodedMediaCache(); @@ -512,8 +512,9 @@ namespace Jellyfin.Api.Helpers if (state.VideoRequest != null && !EncodingHelper.IsCopyCodec(state.OutputVideoCodec)) { - var auth = await _authorizationContext.GetAuthorizationInfo(request).ConfigureAwait(false); - if (auth.User != null && !auth.User.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) + var userId = request.HttpContext.User.GetUserId(); + var user = userId.Equals(default) ? null : _userManager.GetUserById(userId); + if (user != null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)) { this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state); diff --git a/MediaBrowser.Controller/Net/ISessionContext.cs b/MediaBrowser.Controller/Net/ISessionContext.cs deleted file mode 100644 index b48181b3fb..0000000000 --- a/MediaBrowser.Controller/Net/ISessionContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -#pragma warning disable CS1591 - -using System.Threading.Tasks; -using Jellyfin.Data.Entities; -using MediaBrowser.Controller.Session; -using Microsoft.AspNetCore.Http; - -namespace MediaBrowser.Controller.Net -{ - public interface ISessionContext - { - Task GetSession(object requestContext); - - Task GetUser(object requestContext); - - Task GetSession(HttpContext requestContext); - - Task GetUser(HttpContext requestContext); - } -} -- cgit v1.2.3 From a9a5fcde81060c9da2096235d61128006339a2ee Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 6 Oct 2022 20:21:23 +0200 Subject: Use ArgumentNullException.ThrowIfNull helper method Did a simple search/replace on the whole repo (except the RSSDP project) This reduces LOC and should improve performance (methods containing a throw statement don't get inlined) ``` if \((\w+) == null\) \s+\{ \s+throw new ArgumentNullException\((.*)\); \s+\} ``` ``` ArgumentNullException.ThrowIfNull($1); ``` --- .../ContentDirectory/ContentDirectoryService.cs | 5 +- Emby.Dlna/ContentDirectory/ControlHandler.cs | 10 +-- Emby.Dlna/DlnaManager.cs | 10 +-- Emby.Dlna/PlayTo/Device.cs | 15 +--- Emby.Dlna/PlayTo/TransportCommands.cs | 5 +- Emby.Dlna/PlayTo/UpnpContainer.cs | 5 +- Emby.Dlna/PlayTo/uBaseObject.cs | 5 +- .../AppBase/BaseConfigurationManager.cs | 5 +- .../Channels/ChannelManager.cs | 5 +- .../Data/SqliteExtensions.cs | 5 +- .../Data/SqliteItemRepository.cs | 85 +++++----------------- .../Data/SqliteUserDataRepository.cs | 15 +--- .../Library/LibraryManager.cs | 47 +++--------- .../Library/MediaSourceManager.cs | 5 +- .../Library/Resolvers/PhotoResolver.cs | 5 +- .../Library/UserDataManager.cs | 15 +--- .../LiveTv/EmbyTV/EmbyTV.cs | 10 +-- .../LiveTv/EmbyTV/ItemDataProvider.cs | 10 +-- .../LiveTv/TunerHosts/M3uParser.cs | 5 +- Emby.Server.Implementations/Net/SocketFactory.cs | 5 +- Emby.Server.Implementations/Net/UdpSocket.cs | 10 +-- .../Plugins/PluginManager.cs | 20 +---- .../ScheduledTasks/ScheduledTaskWorker.cs | 30 ++------ .../Session/SessionManager.cs | 35 ++------- .../Sorting/AiredEpisodeOrderComparer.cs | 10 +-- .../Sorting/CommunityRatingComparer.cs | 10 +-- .../Sorting/DateCreatedComparer.cs | 10 +-- .../Sorting/IndexNumberComparer.cs | 10 +-- .../Sorting/NameComparer.cs | 10 +-- .../Sorting/OfficialRatingComparer.cs | 12 +-- .../Sorting/ParentIndexNumberComparer.cs | 10 +-- .../Sorting/RuntimeComparer.cs | 10 +-- .../Sorting/SortNameComparer.cs | 10 +-- .../Sorting/StudioComparer.cs | 10 +-- .../Updates/InstallationManager.cs | 5 +- Jellyfin.Drawing.Skia/StripCollageBuilder.cs | 5 +- Jellyfin.Networking/Manager/NetworkManager.cs | 15 +--- .../Devices/DeviceManager.cs | 5 +- .../Users/UserManager.cs | 10 +-- MediaBrowser.Common/Net/IPNetAddress.cs | 5 +- MediaBrowser.Common/Net/IPObject.cs | 25 ++----- MediaBrowser.Common/Net/NetworkExtensions.cs | 20 +---- MediaBrowser.Common/Plugins/BasePluginOfT.cs | 5 +- .../Entities/AggregateFolder.cs | 5 +- MediaBrowser.Controller/Entities/BaseItem.cs | 35 ++------- .../Entities/BaseItemExtensions.cs | 10 +-- MediaBrowser.Controller/Entities/Folder.cs | 20 +---- MediaBrowser.Controller/Entities/PeopleHelper.cs | 5 +- MediaBrowser.Controller/IO/FileData.cs | 5 +- .../MediaEncoding/EncodingHelper.cs | 10 +-- .../Net/BasePeriodicWebSocketListener.cs | 10 +-- .../Parsers/BaseItemXmlParser.cs | 5 +- .../Attachments/AttachmentExtractor.cs | 5 +- .../Probing/FFProbeHelpers.cs | 5 +- .../Subtitles/SubtitleEncoder.cs | 5 +- MediaBrowser.Model/Cryptography/PasswordHash.cs | 5 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 5 +- .../Entities/ProviderIdsExtensions.cs | 15 +--- src/Jellyfin.Extensions/EnumerableExtensions.cs | 5 +- .../Jellyfin.Networking.Tests/NetworkParseTests.cs | 60 +++------------ 60 files changed, 156 insertions(+), 618 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs index 9020dea994..319a9f5500 100644 --- a/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs +++ b/Emby.Dlna/ContentDirectory/ContentDirectoryService.cs @@ -103,10 +103,7 @@ namespace Emby.Dlna.ContentDirectory /// public Task ProcessControlRequestAsync(ControlRequest request) { - if (request == null) - { - throw new ArgumentNullException(nameof(request)); - } + ArgumentNullException.ThrowIfNull(request); var profile = _dlna.GetProfile(request.Headers) ?? _dlna.GetDefaultProfile(); diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index 57170bb316..fc69960fd6 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -114,15 +114,9 @@ namespace Emby.Dlna.ContentDirectory /// protected override void WriteResult(string methodName, IReadOnlyDictionary methodParams, XmlWriter xmlWriter) { - if (xmlWriter == null) - { - throw new ArgumentNullException(nameof(xmlWriter)); - } + ArgumentNullException.ThrowIfNull(xmlWriter); - if (methodParams == null) - { - throw new ArgumentNullException(nameof(methodParams)); - } + ArgumentNullException.ThrowIfNull(methodParams); const string DeviceId = "test"; diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 74624334bb..57864d2780 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -100,10 +100,7 @@ namespace Emby.Dlna /// public DeviceProfile? GetProfile(DeviceIdentification deviceInfo) { - if (deviceInfo == null) - { - throw new ArgumentNullException(nameof(deviceInfo)); - } + ArgumentNullException.ThrowIfNull(deviceInfo); var profile = GetProfiles() .FirstOrDefault(i => i.Identification != null && IsMatch(deviceInfo, i.Identification)); @@ -170,10 +167,7 @@ namespace Emby.Dlna /// public DeviceProfile? GetProfile(IHeaderDictionary headers) { - if (headers == null) - { - throw new ArgumentNullException(nameof(headers)); - } + ArgumentNullException.ThrowIfNull(headers); var profile = GetProfiles().FirstOrDefault(i => i.Identification != null && IsMatch(headers, i.Identification)); if (profile == null) diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 0b480f5ab0..34981bd3f4 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -931,10 +931,7 @@ namespace Emby.Dlna.PlayTo private static UBaseObject CreateUBaseObject(XElement container, string trackUri) { - if (container == null) - { - throw new ArgumentNullException(nameof(container)); - } + ArgumentNullException.ThrowIfNull(container); var url = container.GetValue(UPnpNamespaces.Res); @@ -958,10 +955,7 @@ namespace Emby.Dlna.PlayTo private static string[] GetProtocolInfo(XElement container) { - if (container == null) - { - throw new ArgumentNullException(nameof(container)); - } + ArgumentNullException.ThrowIfNull(container); var resElement = container.Element(UPnpNamespaces.Res); @@ -1183,10 +1177,7 @@ namespace Emby.Dlna.PlayTo #nullable enable private static DeviceIcon CreateIcon(XElement element) { - if (element == null) - { - throw new ArgumentNullException(nameof(element)); - } + ArgumentNullException.ThrowIfNull(element); var width = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("width")); var height = element.GetDescendantValue(UPnpNamespaces.Ud.GetName("height")); diff --git a/Emby.Dlna/PlayTo/TransportCommands.cs b/Emby.Dlna/PlayTo/TransportCommands.cs index d373b57f55..9c3a9103be 100644 --- a/Emby.Dlna/PlayTo/TransportCommands.cs +++ b/Emby.Dlna/PlayTo/TransportCommands.cs @@ -61,10 +61,7 @@ namespace Emby.Dlna.PlayTo private static Argument ArgumentFromXml(XElement container) { - if (container == null) - { - throw new ArgumentNullException(nameof(container)); - } + ArgumentNullException.ThrowIfNull(container); return new Argument { diff --git a/Emby.Dlna/PlayTo/UpnpContainer.cs b/Emby.Dlna/PlayTo/UpnpContainer.cs index 05f27603fb..017d51e606 100644 --- a/Emby.Dlna/PlayTo/UpnpContainer.cs +++ b/Emby.Dlna/PlayTo/UpnpContainer.cs @@ -10,10 +10,7 @@ namespace Emby.Dlna.PlayTo { public static UBaseObject Create(XElement container) { - if (container == null) - { - throw new ArgumentNullException(nameof(container)); - } + ArgumentNullException.ThrowIfNull(container); return new UBaseObject { diff --git a/Emby.Dlna/PlayTo/uBaseObject.cs b/Emby.Dlna/PlayTo/uBaseObject.cs index 02d2da58d6..2e0f2063be 100644 --- a/Emby.Dlna/PlayTo/uBaseObject.cs +++ b/Emby.Dlna/PlayTo/uBaseObject.cs @@ -54,10 +54,7 @@ namespace Emby.Dlna.PlayTo public bool Equals(UBaseObject obj) { - if (obj == null) - { - throw new ArgumentNullException(nameof(obj)); - } + ArgumentNullException.ThrowIfNull(obj); return string.Equals(Id, obj.Id, StringComparison.Ordinal); } diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index c42cec593a..26b4649dd8 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -210,10 +210,7 @@ namespace Emby.Server.Implementations.AppBase /// newConfiguration is null. public virtual void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration) { - if (newConfiguration == null) - { - throw new ArgumentNullException(nameof(newConfiguration)); - } + ArgumentNullException.ThrowIfNull(newConfiguration); ValidateCachePath(newConfiguration); diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 92a85e8626..6837cce5cc 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -1188,10 +1188,7 @@ namespace Emby.Server.Implementations.Channels internal IChannel GetChannelProvider(Channel channel) { - if (channel == null) - { - throw new ArgumentNullException(nameof(channel)); - } + ArgumentNullException.ThrowIfNull(channel); var result = GetAllChannels() .FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(channel.ChannelId) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs index 381eb92a88..736b8125d7 100644 --- a/Emby.Server.Implementations/Data/SqliteExtensions.cs +++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs @@ -54,10 +54,7 @@ namespace Emby.Server.Implementations.Data public static void RunQueries(this SQLiteDatabaseConnection connection, string[] queries) { - if (queries == null) - { - throw new ArgumentNullException(nameof(queries)); - } + ArgumentNullException.ThrowIfNull(queries); connection.RunInTransaction(conn => { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 1b176e60d7..9c9fa73830 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -583,10 +583,7 @@ namespace Emby.Server.Implementations.Data public void SaveImages(BaseItem item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); CheckDisposed(); @@ -617,10 +614,7 @@ namespace Emby.Server.Implementations.Data /// public void SaveItems(IEnumerable items, CancellationToken cancellationToken) { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } + ArgumentNullException.ThrowIfNull(items); cancellationToken.ThrowIfCancellationRequested(); @@ -2085,10 +2079,7 @@ namespace Emby.Server.Implementations.Data throw new ArgumentNullException(nameof(id)); } - if (chapters == null) - { - throw new ArgumentNullException(nameof(chapters)); - } + ArgumentNullException.ThrowIfNull(chapters); var idBlob = id.ToByteArray(); @@ -2557,10 +2548,7 @@ namespace Emby.Server.Implementations.Data public int GetCount(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -2613,10 +2601,7 @@ namespace Emby.Server.Implementations.Data public List GetItemList(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -2794,10 +2779,7 @@ namespace Emby.Server.Implementations.Data public QueryResult GetItems(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -3174,10 +3156,7 @@ namespace Emby.Server.Implementations.Data public List GetItemIdsList(InternalItemsQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -4837,10 +4816,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type public List GetPeopleNames(InternalPeopleQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -4880,10 +4856,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type public List GetPeople(InternalPeopleQuery query) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); CheckDisposed(); @@ -4999,10 +4972,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(itemId)); } - if (ancestorIds == null) - { - throw new ArgumentNullException(nameof(ancestorIds)); - } + ArgumentNullException.ThrowIfNull(ancestorIds); CheckDisposed(); @@ -5175,10 +5145,7 @@ AND Type = @InternalPersonType)"); private QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) { - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); if (!query.Limit.HasValue) { @@ -5531,10 +5498,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(itemId)); } - if (values == null) - { - throw new ArgumentNullException(nameof(values)); - } + ArgumentNullException.ThrowIfNull(values); CheckDisposed(); @@ -5607,10 +5571,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(itemId)); } - if (people == null) - { - throw new ArgumentNullException(nameof(people)); - } + ArgumentNullException.ThrowIfNull(people); CheckDisposed(); @@ -5710,10 +5671,7 @@ AND Type = @InternalPersonType)"); { CheckDisposed(); - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); var cmdText = _mediaStreamSaveColumnsSelectQuery; @@ -5766,10 +5724,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentNullException(nameof(id)); } - if (streams == null) - { - throw new ArgumentNullException(nameof(streams)); - } + ArgumentNullException.ThrowIfNull(streams); cancellationToken.ThrowIfCancellationRequested(); @@ -6107,10 +6062,7 @@ AND Type = @InternalPersonType)"); { CheckDisposed(); - if (query == null) - { - throw new ArgumentNullException(nameof(query)); - } + ArgumentNullException.ThrowIfNull(query); var cmdText = _mediaAttachmentSaveColumnsSelectQuery; @@ -6152,10 +6104,7 @@ AND Type = @InternalPersonType)"); throw new ArgumentException("Guid can't be empty.", nameof(id)); } - if (attachments == null) - { - throw new ArgumentNullException(nameof(attachments)); - } + ArgumentNullException.ThrowIfNull(attachments); cancellationToken.ThrowIfCancellationRequested(); diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index ba86dc156e..8d78d644dc 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -133,10 +133,7 @@ namespace Emby.Server.Implementations.Data /// public void SaveUserData(long userId, string key, UserItemData userData, CancellationToken cancellationToken) { - if (userData == null) - { - throw new ArgumentNullException(nameof(userData)); - } + ArgumentNullException.ThrowIfNull(userData); if (userId <= 0) { @@ -154,10 +151,7 @@ namespace Emby.Server.Implementations.Data /// public void SaveAllUserData(long userId, UserItemData[] userData, CancellationToken cancellationToken) { - if (userData == null) - { - throw new ArgumentNullException(nameof(userData)); - } + ArgumentNullException.ThrowIfNull(userData); if (userId <= 0) { @@ -304,10 +298,7 @@ namespace Emby.Server.Implementations.Data public UserItemData GetUserData(long userId, List keys) { - if (keys == null) - { - throw new ArgumentNullException(nameof(keys)); - } + ArgumentNullException.ThrowIfNull(keys); if (keys.Count == 0) { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 67f9c57658..ee94670eb0 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -281,10 +281,7 @@ namespace Emby.Server.Implementations.Library public void RegisterItem(BaseItem item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (item is IItemByName) { @@ -311,10 +308,7 @@ namespace Emby.Server.Implementations.Library public void DeleteItem(BaseItem item, DeleteOptions options, bool notifyParentItem) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); var parent = item.GetOwner() ?? item.GetParent(); @@ -323,10 +317,7 @@ namespace Emby.Server.Implementations.Library public void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (item.SourceType == SourceType.Channel) { @@ -509,10 +500,7 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(key)); } - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } + ArgumentNullException.ThrowIfNull(type); string programDataPath = _configurationManager.ApplicationPaths.ProgramDataPath; if (key.StartsWith(programDataPath, StringComparison.Ordinal)) @@ -544,10 +532,7 @@ namespace Emby.Server.Implementations.Library string collectionType = null, LibraryOptions libraryOptions = null) { - if (fileInfo == null) - { - throw new ArgumentNullException(nameof(fileInfo)); - } + ArgumentNullException.ThrowIfNull(fileInfo); var fullPath = fileInfo.FullName; @@ -1854,10 +1839,7 @@ namespace Emby.Server.Implementations.Library /// public async Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); var outdated = forceUpdate ? item.ImageInfos.Where(i => i.Path != null).ToArray() @@ -2296,10 +2278,7 @@ namespace Emby.Server.Implementations.Library string viewType, string sortName) { - if (parent == null) - { - throw new ArgumentNullException(nameof(parent)); - } + ArgumentNullException.ThrowIfNull(parent); var name = parent.Name; var parentId = parent.Id; @@ -2779,7 +2758,7 @@ namespace Emby.Server.Implementations.Library } }) .Where(i => i != null) - .Where(i => query.User == null ? + .Where(i => query.User == null ? true : i.IsVisible(query.User)) .ToList(); @@ -2983,10 +2962,7 @@ namespace Emby.Server.Implementations.Library private void AddMediaPathInternal(string virtualFolderName, MediaPathInfo pathInfo, bool saveLibraryOptions) { - if (pathInfo == null) - { - throw new ArgumentNullException(nameof(pathInfo)); - } + ArgumentNullException.ThrowIfNull(pathInfo); var path = pathInfo.Path; @@ -3033,10 +3009,7 @@ namespace Emby.Server.Implementations.Library public void UpdateMediaPath(string virtualFolderName, MediaPathInfo mediaPath) { - if (mediaPath == null) - { - throw new ArgumentNullException(nameof(mediaPath)); - } + ArgumentNullException.ThrowIfNull(mediaPath); var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index c0aef18997..bfccc7db72 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -322,10 +322,7 @@ namespace Emby.Server.Implementations.Library public List GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); var hasMediaSources = (IHasMediaSources)item; diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index bc2915db62..af4abfb805 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -91,10 +91,7 @@ namespace Emby.Server.Implementations.Library.Resolvers internal static bool IsImageFile(string path, IImageProcessor imageProcessor) { - if (path == null) - { - throw new ArgumentNullException(nameof(path)); - } + ArgumentNullException.ThrowIfNull(path); var filename = Path.GetFileNameWithoutExtension(path); diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index 3810a76c45..aecab7d9c8 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -53,15 +53,9 @@ namespace Emby.Server.Implementations.Library public void SaveUserData(User user, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken) { - if (userData == null) - { - throw new ArgumentNullException(nameof(userData)); - } + ArgumentNullException.ThrowIfNull(userData); - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); cancellationToken.ThrowIfCancellationRequested(); @@ -194,10 +188,7 @@ namespace Emby.Server.Implementations.Library /// is null. private UserItemDataDto GetUserItemDataDto(UserItemData data) { - if (data == null) - { - throw new ArgumentNullException(nameof(data)); - } + ArgumentNullException.ThrowIfNull(data); return new UserItemDataDto { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 065309688c..4da6776369 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1223,10 +1223,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private async Task RecordStream(TimerInfo timer, DateTime recordingEndDate, ActiveRecordingInfo activeRecordingInfo) { - if (timer == null) - { - throw new ArgumentNullException(nameof(timer)); - } + ArgumentNullException.ThrowIfNull(timer); LiveTvProgram programInfo = null; @@ -2347,10 +2344,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private IEnumerable GetTimersForSeries(SeriesTimerInfo seriesTimer) { - if (seriesTimer == null) - { - throw new ArgumentNullException(nameof(seriesTimer)); - } + ArgumentNullException.ThrowIfNull(seriesTimer); var query = new InternalItemsQuery { diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 46979bfc57..58b798ce67 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -84,10 +84,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public virtual void Update(T item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); lock (_fileDataLock) { @@ -107,10 +104,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public virtual void Add(T item) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); lock (_fileDataLock) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index be06356a4f..a423ec8f48 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -44,10 +44,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public async Task GetListingsStream(TunerHostInfo info, CancellationToken cancellationToken) { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); if (!info.Url.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 21795c8f86..303875df55 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -63,10 +63,7 @@ namespace Emby.Server.Implementations.Net /// public ISocket CreateUdpMulticastSocket(IPAddress ipAddress, int multicastTimeToLive, int localPort) { - if (ipAddress == null) - { - throw new ArgumentNullException(nameof(ipAddress)); - } + ArgumentNullException.ThrowIfNull(ipAddress); if (multicastTimeToLive <= 0) { diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 2c20daa57f..c3994fc040 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -35,10 +35,7 @@ namespace Emby.Server.Implementations.Net public UdpSocket(Socket socket, int localPort, IPAddress ip) { - if (socket == null) - { - throw new ArgumentNullException(nameof(socket)); - } + ArgumentNullException.ThrowIfNull(socket); _socket = socket; _localPort = localPort; @@ -51,10 +48,7 @@ namespace Emby.Server.Implementations.Net public UdpSocket(Socket socket, IPEndPoint endPoint) { - if (socket == null) - { - throw new ArgumentNullException(nameof(socket)); - } + ArgumentNullException.ThrowIfNull(socket); _socket = socket; _socket.Connect(endPoint); diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs index 45ef36441d..ec4e0dbeb9 100644 --- a/Emby.Server.Implementations/Plugins/PluginManager.cs +++ b/Emby.Server.Implementations/Plugins/PluginManager.cs @@ -234,10 +234,7 @@ namespace Emby.Server.Implementations.Plugins /// Outcome of the operation. public bool RemovePlugin(LocalPlugin plugin) { - if (plugin == null) - { - throw new ArgumentNullException(nameof(plugin)); - } + ArgumentNullException.ThrowIfNull(plugin); if (DeletePlugin(plugin)) { @@ -288,10 +285,7 @@ namespace Emby.Server.Implementations.Plugins /// The of the plug to disable. public void EnablePlugin(LocalPlugin plugin) { - if (plugin == null) - { - throw new ArgumentNullException(nameof(plugin)); - } + ArgumentNullException.ThrowIfNull(plugin); if (ChangePluginState(plugin, PluginStatus.Active)) { @@ -306,10 +300,7 @@ namespace Emby.Server.Implementations.Plugins /// The of the plug to disable. public void DisablePlugin(LocalPlugin plugin) { - if (plugin == null) - { - throw new ArgumentNullException(nameof(plugin)); - } + ArgumentNullException.ThrowIfNull(plugin); // Update the manifest on disk if (ChangePluginState(plugin, PluginStatus.Disabled)) @@ -326,10 +317,7 @@ namespace Emby.Server.Implementations.Plugins public void FailPlugin(Assembly assembly) { // Only save if disabled. - if (assembly == null) - { - throw new ArgumentNullException(nameof(assembly)); - } + ArgumentNullException.ThrowIfNull(assembly); var plugin = _plugins.FirstOrDefault(p => p.DllFiles.Contains(assembly.Location)); if (plugin == null) diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 2c4d6884d2..b370e06efa 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -92,25 +92,13 @@ namespace Emby.Server.Implementations.ScheduledTasks /// public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, ILogger logger) { - if (scheduledTask == null) - { - throw new ArgumentNullException(nameof(scheduledTask)); - } + ArgumentNullException.ThrowIfNull(scheduledTask); - if (applicationPaths == null) - { - throw new ArgumentNullException(nameof(applicationPaths)); - } + ArgumentNullException.ThrowIfNull(applicationPaths); - if (taskManager == null) - { - throw new ArgumentNullException(nameof(taskManager)); - } + ArgumentNullException.ThrowIfNull(taskManager); - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } + ArgumentNullException.ThrowIfNull(logger); ScheduledTask = scheduledTask; _applicationPaths = applicationPaths; @@ -249,10 +237,7 @@ namespace Emby.Server.Implementations.ScheduledTasks get => _triggers; set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + ArgumentNullException.ThrowIfNull(value); // Cleanup current triggers if (_triggers != null) @@ -281,10 +266,7 @@ namespace Emby.Server.Implementations.ScheduledTasks set { - if (value == null) - { - throw new ArgumentNullException(nameof(value)); - } + ArgumentNullException.ThrowIfNull(value); // This null check is not great, but is needed to handle bad user input, or user mucking with the config file incorrectly var triggerList = value.Where(i => i != null).ToArray(); diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 7f927e2709..0d1029882b 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -665,10 +665,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); var session = GetSession(info.SessionId); @@ -762,10 +759,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); var session = GetSession(info.SessionId); @@ -897,10 +891,7 @@ namespace Emby.Server.Implementations.Session { CheckDisposed(); - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); if (info.PositionTicks.HasValue && info.PositionTicks.Value < 0) { @@ -1341,15 +1332,9 @@ namespace Emby.Server.Implementations.Session private static void AssertCanControl(SessionInfo session, SessionInfo controllingSession) { - if (session == null) - { - throw new ArgumentNullException(nameof(session)); - } + ArgumentNullException.ThrowIfNull(session); - if (controllingSession == null) - { - throw new ArgumentNullException(nameof(controllingSession)); - } + ArgumentNullException.ThrowIfNull(controllingSession); } /// @@ -1688,10 +1673,7 @@ namespace Emby.Server.Implementations.Session /// private BaseItemDto GetItemInfo(BaseItem item, MediaSourceInfo mediaSource) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); var dtoOptions = _itemInfoDtoOptions; @@ -1802,10 +1784,7 @@ namespace Emby.Server.Implementations.Session /// public Task GetSessionByAuthenticationToken(Device info, string deviceId, string remoteEndpoint, string appVersion) { - if (info == null) - { - throw new ArgumentNullException(nameof(info)); - } + ArgumentNullException.ThrowIfNull(info); var user = info.UserId.Equals(default) ? null diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index db8b689491..2d21bd9c2a 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); var episode1 = x as Episode; var episode2 = y as Episode; diff --git a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs index 5f142fa4bb..5cb11ab465 100644 --- a/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/CommunityRatingComparer.cs @@ -23,15 +23,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return (x.CommunityRating ?? 0).CompareTo(y.CommunityRating ?? 0); } diff --git a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs index 8b460166ca..6133aaccc6 100644 --- a/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs +++ b/Emby.Server.Implementations/Sorting/DateCreatedComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return DateTime.Compare(x.DateCreated, y.DateCreated); } diff --git a/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs b/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs index c5b00afb15..1bcaccd8a3 100644 --- a/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs +++ b/Emby.Server.Implementations/Sorting/IndexNumberComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); if (!x.IndexNumber.HasValue && !y.IndexNumber.HasValue) { diff --git a/Emby.Server.Implementations/Sorting/NameComparer.cs b/Emby.Server.Implementations/Sorting/NameComparer.cs index c2875eeb97..93bec4db99 100644 --- a/Emby.Server.Implementations/Sorting/NameComparer.cs +++ b/Emby.Server.Implementations/Sorting/NameComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase); } diff --git a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs index a81f78ebfc..ce44f99a69 100644 --- a/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs +++ b/Emby.Server.Implementations/Sorting/OfficialRatingComparer.cs @@ -31,15 +31,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } - - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(x); + + ArgumentNullException.ThrowIfNull(y); var levelX = string.IsNullOrEmpty(x.OfficialRating) ? 0 : _localization.GetRatingLevel(x.OfficialRating) ?? 0; var levelY = string.IsNullOrEmpty(y.OfficialRating) ? 0 : _localization.GetRatingLevel(y.OfficialRating) ?? 0; diff --git a/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs b/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs index 8c408bb4d2..c54750843e 100644 --- a/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs +++ b/Emby.Server.Implementations/Sorting/ParentIndexNumberComparer.cs @@ -24,15 +24,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem? x, BaseItem? y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); if (!x.ParentIndexNumber.HasValue && !y.ParentIndexNumber.HasValue) { diff --git a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs index e32e5552e4..646bafbb54 100644 --- a/Emby.Server.Implementations/Sorting/RuntimeComparer.cs +++ b/Emby.Server.Implementations/Sorting/RuntimeComparer.cs @@ -26,15 +26,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem x, BaseItem y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return (x.RunTimeTicks ?? 0).CompareTo(y.RunTimeTicks ?? 0); } diff --git a/Emby.Server.Implementations/Sorting/SortNameComparer.cs b/Emby.Server.Implementations/Sorting/SortNameComparer.cs index 79be9a89a4..628b9b3dda 100644 --- a/Emby.Server.Implementations/Sorting/SortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SortNameComparer.cs @@ -26,15 +26,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem x, BaseItem y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return string.Compare(x.SortName, y.SortName, StringComparison.OrdinalIgnoreCase); } diff --git a/Emby.Server.Implementations/Sorting/StudioComparer.cs b/Emby.Server.Implementations/Sorting/StudioComparer.cs index c917daaad1..457c062714 100644 --- a/Emby.Server.Implementations/Sorting/StudioComparer.cs +++ b/Emby.Server.Implementations/Sorting/StudioComparer.cs @@ -26,15 +26,9 @@ namespace Emby.Server.Implementations.Sorting /// System.Int32. public int Compare(BaseItem x, BaseItem y) { - if (x == null) - { - throw new ArgumentNullException(nameof(x)); - } + ArgumentNullException.ThrowIfNull(x); - if (y == null) - { - throw new ArgumentNullException(nameof(y)); - } + ArgumentNullException.ThrowIfNull(y); return AlphanumericComparator.CompareValues(x.Studios.FirstOrDefault(), y.Studios.FirstOrDefault()); } diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 40c386e823..550f0e0755 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -294,10 +294,7 @@ namespace Emby.Server.Implementations.Updates /// public async Task InstallPackage(InstallationInfo package, CancellationToken cancellationToken) { - if (package == null) - { - throw new ArgumentNullException(nameof(package)); - } + ArgumentNullException.ThrowIfNull(package); var innerCancellationTokenSource = new CancellationTokenSource(); diff --git a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs index 6bece9db6e..b55a994056 100644 --- a/Jellyfin.Drawing.Skia/StripCollageBuilder.cs +++ b/Jellyfin.Drawing.Skia/StripCollageBuilder.cs @@ -29,10 +29,7 @@ namespace Jellyfin.Drawing.Skia /// The image format. public static SKEncodedImageFormat GetEncodedFormat(string outputPath) { - if (outputPath == null) - { - throw new ArgumentNullException(nameof(outputPath)); - } + ArgumentNullException.ThrowIfNull(outputPath); var ext = Path.GetExtension(outputPath); diff --git a/Jellyfin.Networking/Manager/NetworkManager.cs b/Jellyfin.Networking/Manager/NetworkManager.cs index fd0665dbdd..9e06cdfe71 100644 --- a/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/Jellyfin.Networking/Manager/NetworkManager.cs @@ -353,10 +353,7 @@ namespace Jellyfin.Networking.Manager public string GetBindInterface(IPObject source, out int? port) { port = null; - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); // Do we have a source? bool haveSource = !source.Address.Equals(IPAddress.None); @@ -476,10 +473,7 @@ namespace Jellyfin.Networking.Manager /// public bool IsInLocalNetwork(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.Equals(IPAddress.None)) { @@ -499,10 +493,7 @@ namespace Jellyfin.Networking.Manager /// public bool IsPrivateAddressRange(IPObject address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); // See conversation at https://github.com/jellyfin/jellyfin/pull/3515. if (TrustAllIP6Interfaces && address.AddressFamily == AddressFamily.InterNetworkV6) diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs index 3203bed183..0728f11799 100644 --- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs +++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs @@ -201,10 +201,7 @@ namespace Jellyfin.Server.Implementations.Devices /// public bool CanAccessDevice(User user, string deviceId) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); if (string.IsNullOrEmpty(deviceId)) { diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 6a2ef74dd2..ed90e81c6f 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -130,10 +130,7 @@ namespace Jellyfin.Server.Implementations.Users /// public async Task RenameUser(User user, string newName) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); ThrowIfInvalidUsername(newName); @@ -267,10 +264,7 @@ namespace Jellyfin.Server.Implementations.Users /// public async Task ChangePassword(User user, string newPassword) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); await GetAuthenticationProvider(user).ChangePassword(user, newPassword).ConfigureAwait(false); await UpdateUserAsync(user).ConfigureAwait(false); diff --git a/MediaBrowser.Common/Net/IPNetAddress.cs b/MediaBrowser.Common/Net/IPNetAddress.cs index f1428d4bef..98d1c2d97b 100644 --- a/MediaBrowser.Common/Net/IPNetAddress.cs +++ b/MediaBrowser.Common/Net/IPNetAddress.cs @@ -160,10 +160,7 @@ namespace MediaBrowser.Common.Net /// public override bool Contains(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { diff --git a/MediaBrowser.Common/Net/IPObject.cs b/MediaBrowser.Common/Net/IPObject.cs index 3a5187bc3d..37385972f7 100644 --- a/MediaBrowser.Common/Net/IPObject.cs +++ b/MediaBrowser.Common/Net/IPObject.cs @@ -55,10 +55,7 @@ namespace MediaBrowser.Common.Net /// IPAddress. public static (IPAddress Address, byte PrefixLength) NetworkAddressOf(IPAddress address, byte prefixLength) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { @@ -109,10 +106,7 @@ namespace MediaBrowser.Common.Net /// True if it is. public static bool IsIP6(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { @@ -129,10 +123,7 @@ namespace MediaBrowser.Common.Net /// True if it contains a private address. public static bool IsPrivateAddressRange(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (!address.Equals(IPAddress.None)) { @@ -179,10 +170,7 @@ namespace MediaBrowser.Common.Net /// public static bool IsIPv6LinkLocal(IPAddress address) { - if (address == null) - { - throw new ArgumentNullException(nameof(address)); - } + ArgumentNullException.ThrowIfNull(address); if (address.IsIPv4MappedToIPv6) { @@ -226,10 +214,7 @@ namespace MediaBrowser.Common.Net /// Byte CIDR representing the mask. public static byte MaskToCidr(IPAddress mask) { - if (mask == null) - { - throw new ArgumentNullException(nameof(mask)); - } + ArgumentNullException.ThrowIfNull(mask); byte cidrnet = 0; if (!mask.Equals(IPAddress.Any)) diff --git a/MediaBrowser.Common/Net/NetworkExtensions.cs b/MediaBrowser.Common/Net/NetworkExtensions.cs index 264bfacb49..7ad0058540 100644 --- a/MediaBrowser.Common/Net/NetworkExtensions.cs +++ b/MediaBrowser.Common/Net/NetworkExtensions.cs @@ -61,10 +61,7 @@ namespace MediaBrowser.Common.Net return false; } - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (item.IsIPv4MappedToIPv6) { @@ -96,10 +93,7 @@ namespace MediaBrowser.Common.Net return false; } - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); foreach (var i in source) { @@ -153,10 +147,7 @@ namespace MediaBrowser.Common.Net /// Collection{IPObject} object containing the subnets. public static Collection AsNetworks(this Collection source) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); Collection res = new Collection(); @@ -239,10 +230,7 @@ namespace MediaBrowser.Common.Net return new Collection(); } - if (target == null) - { - throw new ArgumentNullException(nameof(target)); - } + ArgumentNullException.ThrowIfNull(target); Collection nc = new Collection(); diff --git a/MediaBrowser.Common/Plugins/BasePluginOfT.cs b/MediaBrowser.Common/Plugins/BasePluginOfT.cs index afda83a7c5..0da5592d38 100644 --- a/MediaBrowser.Common/Plugins/BasePluginOfT.cs +++ b/MediaBrowser.Common/Plugins/BasePluginOfT.cs @@ -164,10 +164,7 @@ namespace MediaBrowser.Common.Plugins /// public virtual void UpdateConfiguration(BasePluginConfiguration configuration) { - if (configuration == null) - { - throw new ArgumentNullException(nameof(configuration)); - } + ArgumentNullException.ThrowIfNull(configuration); Configuration = (TConfigurationType)configuration; diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 77a857b785..e671e5c711 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -171,10 +171,7 @@ namespace MediaBrowser.Controller.Entities /// Throws if child is null. public void AddVirtualChild(BaseItem child) { - if (child == null) - { - throw new ArgumentNullException(nameof(child)); - } + ArgumentNullException.ThrowIfNull(child); _virtualChildren.Add(child); } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9461b01e31..41fce67fa7 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1101,10 +1101,7 @@ namespace MediaBrowser.Controller.Entities private MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, BaseItem item, MediaSourceType type) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); var protocol = item.PathProtocol; @@ -1544,10 +1541,7 @@ namespace MediaBrowser.Controller.Entities /// If user is null. public bool IsParentalAllowed(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); if (!IsVisibleViaTags(user)) { @@ -1667,10 +1661,7 @@ namespace MediaBrowser.Controller.Entities /// is null. public virtual bool IsVisible(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); return IsParentalAllowed(user); } @@ -1842,10 +1833,7 @@ namespace MediaBrowser.Controller.Entities DateTime? datePlayed, bool resetPosition) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var data = UserDataManager.GetUserData(user, this); @@ -1876,10 +1864,7 @@ namespace MediaBrowser.Controller.Entities /// Throws if user is null. public virtual void MarkUnplayed(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var data = UserDataManager.GetUserData(user, this); @@ -2110,10 +2095,7 @@ namespace MediaBrowser.Controller.Entities /// Image index. public int GetImageIndex(ItemImageInfo image) { - if (image == null) - { - throw new ArgumentNullException(nameof(image)); - } + ArgumentNullException.ThrowIfNull(image); if (image.Type == ImageType.Chapter) { @@ -2320,10 +2302,7 @@ namespace MediaBrowser.Controller.Entities public virtual bool IsUnplayed(User user) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var userdata = UserDataManager.GetUserData(user, this); diff --git a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs index e0583e6308..948eb43754 100644 --- a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs +++ b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs @@ -71,15 +71,9 @@ namespace MediaBrowser.Controller.Entities where T : BaseItem where TU : BaseItem { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); - if (dest == null) - { - throw new ArgumentNullException(nameof(dest)); - } + ArgumentNullException.ThrowIfNull(dest); var destProps = typeof(TU).GetProperties().Where(x => x.CanWrite).ToList(); diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 92d12a86ca..808f918104 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1023,10 +1023,7 @@ namespace MediaBrowser.Controller.Entities IServerConfigurationManager configurationManager, ICollectionManager collectionManager) { - if (items == null) - { - throw new ArgumentNullException(nameof(items)); - } + ArgumentNullException.ThrowIfNull(items); if (CollapseBoxSetItems(query, queryParent, user, configurationManager)) { @@ -1273,20 +1270,14 @@ namespace MediaBrowser.Controller.Entities public List GetChildren(User user, bool includeLinkedChildren) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); return GetChildren(user, includeLinkedChildren, null); } public virtual List GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); // the true root should return our users root folder children if (IsPhysicalRoot) @@ -1367,10 +1358,7 @@ namespace MediaBrowser.Controller.Entities public virtual IEnumerable GetRecursiveChildren(User user, InternalItemsQuery query) { - if (user == null) - { - throw new ArgumentNullException(nameof(user)); - } + ArgumentNullException.ThrowIfNull(user); var result = new Dictionary(); diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs index 687ce1ec8d..8571bfcea5 100644 --- a/MediaBrowser.Controller/Entities/PeopleHelper.cs +++ b/MediaBrowser.Controller/Entities/PeopleHelper.cs @@ -11,10 +11,7 @@ namespace MediaBrowser.Controller.Entities { public static void AddPerson(List people, PersonInfo person) { - if (person == null) - { - throw new ArgumentNullException(nameof(person)); - } + ArgumentNullException.ThrowIfNull(person); if (string.IsNullOrEmpty(person.Name)) { diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 2429ac42db..71feae536c 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -40,10 +40,7 @@ namespace MediaBrowser.Controller.IO throw new ArgumentNullException(nameof(path)); } - if (args == null) - { - throw new ArgumentNullException(nameof(args)); - } + ArgumentNullException.ThrowIfNull(args); var entries = directoryService.GetFileSystemEntries(path); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 42c5517f9d..d0362b128c 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -5105,15 +5105,9 @@ namespace MediaBrowser.Controller.MediaEncoding MediaSourceInfo mediaSource, string requestedUrl) { - if (state == null) - { - throw new ArgumentNullException(nameof(state)); - } + ArgumentNullException.ThrowIfNull(state); - if (mediaSource == null) - { - throw new ArgumentNullException(nameof(mediaSource)); - } + ArgumentNullException.ThrowIfNull(mediaSource); var path = mediaSource.Path; var protocol = mediaSource.Protocol; diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs index eadc09fd4b..647de50030 100644 --- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -38,10 +38,7 @@ namespace MediaBrowser.Controller.Net protected BasePeriodicWebSocketListener(ILogger> logger) { - if (logger == null) - { - throw new ArgumentNullException(nameof(logger)); - } + ArgumentNullException.ThrowIfNull(logger); Logger = logger; } @@ -77,10 +74,7 @@ namespace MediaBrowser.Controller.Net /// Task. public Task ProcessMessageAsync(WebSocketMessageInfo message) { - if (message == null) - { - throw new ArgumentNullException(nameof(message)); - } + ArgumentNullException.ThrowIfNull(message); if (message.MessageType == StartType) { diff --git a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs index 777fe67746..a9e1b4a51e 100644 --- a/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs +++ b/MediaBrowser.LocalMetadata/Parsers/BaseItemXmlParser.cs @@ -53,10 +53,7 @@ namespace MediaBrowser.LocalMetadata.Parsers /// Item is null. public void Fetch(MetadataResult item, string metadataFile, CancellationToken cancellationToken) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (string.IsNullOrEmpty(metadataFile)) { diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 142571e8f6..22abf93ac3 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -52,10 +52,7 @@ namespace MediaBrowser.MediaEncoding.Attachments /// public async Task<(MediaAttachment Attachment, Stream Stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (string.IsNullOrWhiteSpace(mediaSourceId)) { diff --git a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs index a9e753726d..205e84153b 100644 --- a/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs +++ b/MediaBrowser.MediaEncoding/Probing/FFProbeHelpers.cs @@ -15,10 +15,7 @@ namespace MediaBrowser.MediaEncoding.Probing /// The result. public static void NormalizeFFProbeResult(InternalMediaInfoResult result) { - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); if (result.Format?.Tags != null) { diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 115f085ff8..9185faf67b 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -120,10 +120,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles async Task ISubtitleEncoder.GetSubtitles(BaseItem item, string mediaSourceId, int subtitleStreamIndex, string outputFormat, long startTimeTicks, long endTimeTicks, bool preserveOriginalTimestamps, CancellationToken cancellationToken) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); if (string.IsNullOrWhiteSpace(mediaSourceId)) { diff --git a/MediaBrowser.Model/Cryptography/PasswordHash.cs b/MediaBrowser.Model/Cryptography/PasswordHash.cs index eec5410411..32a34d23c1 100644 --- a/MediaBrowser.Model/Cryptography/PasswordHash.cs +++ b/MediaBrowser.Model/Cryptography/PasswordHash.cs @@ -29,10 +29,7 @@ namespace MediaBrowser.Model.Cryptography public PasswordHash(string id, byte[] hash, byte[] salt, Dictionary parameters) { - if (id == null) - { - throw new ArgumentNullException(nameof(id)); - } + ArgumentNullException.ThrowIfNull(id); if (id.Length == 0) { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index fdb9fd5d54..b121a29058 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -565,10 +565,7 @@ namespace MediaBrowser.Model.Dlna private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options) { - if (item == null) - { - throw new ArgumentNullException(nameof(item)); - } + ArgumentNullException.ThrowIfNull(item); StreamInfo playlistItem = new StreamInfo { diff --git a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs index 62a2f3ce84..d3b8400f34 100644 --- a/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs +++ b/MediaBrowser.Model/Entities/ProviderIdsExtensions.cs @@ -28,10 +28,7 @@ namespace MediaBrowser.Model.Entities /// true if a provider id with the given name was found; otherwise false. public static bool HasProviderId(this IHasProviderIds instance, string name) { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } + ArgumentNullException.ThrowIfNull(instance); return instance.TryGetProviderId(name, out _); } @@ -56,10 +53,7 @@ namespace MediaBrowser.Model.Entities /// true if a provider id with the given name was found; otherwise false. public static bool TryGetProviderId(this IHasProviderIds instance, string name, [NotNullWhen(true)] out string? id) { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } + ArgumentNullException.ThrowIfNull(instance); if (instance.ProviderIds == null) { @@ -121,10 +115,7 @@ namespace MediaBrowser.Model.Entities /// The value. public static void SetProviderId(this IHasProviderIds instance, string name, string? value) { - if (instance == null) - { - throw new ArgumentNullException(nameof(instance)); - } + ArgumentNullException.ThrowIfNull(instance); // If it's null remove the key from the dictionary if (string.IsNullOrEmpty(value)) diff --git a/src/Jellyfin.Extensions/EnumerableExtensions.cs b/src/Jellyfin.Extensions/EnumerableExtensions.cs index b5fe933571..a31a57dc65 100644 --- a/src/Jellyfin.Extensions/EnumerableExtensions.cs +++ b/src/Jellyfin.Extensions/EnumerableExtensions.cs @@ -18,10 +18,7 @@ namespace Jellyfin.Extensions /// The source is null. public static bool Contains(this IEnumerable source, ReadOnlySpan value, StringComparison stringComparison) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); if (source is IList list) { diff --git a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs index 52b0e5a955..166bc0513a 100644 --- a/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs +++ b/tests/Jellyfin.Networking.Tests/NetworkParseTests.cs @@ -103,10 +103,7 @@ namespace Jellyfin.Networking.Tests "[192.158.0.0/16,192.0.0.0/8]")] public void TestCollections(string settings, string result1, string result2, string result3, string result4, string result5) { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } + ArgumentNullException.ThrowIfNull(settings); var conf = new NetworkConfiguration() { @@ -155,20 +152,11 @@ namespace Jellyfin.Networking.Tests [InlineData("127.0.0.1", "127.0.0.1/8", "[127.0.0.1/32]")] public void UnionCheck(string settings, string compare, string result) { - if (settings == null) - { - throw new ArgumentNullException(nameof(settings)); - } + ArgumentNullException.ThrowIfNull(settings); - if (compare == null) - { - throw new ArgumentNullException(nameof(compare)); - } + ArgumentNullException.ThrowIfNull(compare); - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); var conf = new NetworkConfiguration() { @@ -264,20 +252,11 @@ namespace Jellyfin.Networking.Tests public void TestCollectionEquality(string source, string dest, string result) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); - if (dest == null) - { - throw new ArgumentNullException(nameof(dest)); - } + ArgumentNullException.ThrowIfNull(dest); - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); var conf = new NetworkConfiguration() { @@ -331,20 +310,11 @@ namespace Jellyfin.Networking.Tests [InlineData("", "", false, "eth16")] public void TestBindInterfaces(string source, string bindAddresses, bool ipv6enabled, string result) { - if (source == null) - { - throw new ArgumentNullException(nameof(source)); - } + ArgumentNullException.ThrowIfNull(source); - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } + ArgumentNullException.ThrowIfNull(bindAddresses); - if (result == null) - { - throw new ArgumentNullException(nameof(result)); - } + ArgumentNullException.ThrowIfNull(result); var conf = new NetworkConfiguration() { @@ -403,15 +373,9 @@ namespace Jellyfin.Networking.Tests [InlineData("192.168.1.1", "192.168.1.0/24", "", false, "eth16=http://helloworld.com", "http://helloworld.com")] public void TestBindInterfaceOverrides(string source, string lan, string bindAddresses, bool ipv6enabled, string publishedServers, string result) { - if (lan == null) - { - throw new ArgumentNullException(nameof(lan)); - } + ArgumentNullException.ThrowIfNull(lan); - if (bindAddresses == null) - { - throw new ArgumentNullException(nameof(bindAddresses)); - } + ArgumentNullException.ThrowIfNull(bindAddresses); var conf = new NetworkConfiguration() { -- cgit v1.2.3 From f5613add1af9e789a7c16f6f631cccd329d5841a Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Thu, 6 Oct 2022 20:39:22 +0200 Subject: Remove extra argument --- Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs | 2 +- Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs | 2 +- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 2 +- .../Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs | 4 ++-- MediaBrowser.Controller/Entities/Extensions.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs index 7ac089a344..4dcf5976a2 100644 --- a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs @@ -25,6 +25,6 @@ namespace Jellyfin.Api.Attributes /// The route template. May not be null. public HttpSubscribeAttribute(string template) : base(_supportedMethods, template) - => ArgumentNullException.ThrowIfNull(template, nameof(template)); + => ArgumentNullException.ThrowIfNull(template); } } diff --git a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs index 16b3d08160..d0238424a7 100644 --- a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs @@ -25,6 +25,6 @@ namespace Jellyfin.Api.Attributes /// The route template. May not be null. public HttpUnsubscribeAttribute(string template) : base(_supportedMethods, template) - => ArgumentNullException.ThrowIfNull(template, nameof(template)); + => ArgumentNullException.ThrowIfNull(template); } } diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 13f155f357..84b261b545 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -145,7 +145,7 @@ namespace Jellyfin.Drawing.Skia /// The file at the specified path could not be used to generate a codec. public string GetImageBlurHash(int xComp, int yComp, string path) { - ArgumentNullException.ThrowIfNull(path, nameof(path)); + ArgumentNullException.ThrowIfNull(path); if (path.Length == 0) { diff --git a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs index 28ed3894fd..bb264d5127 100644 --- a/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs +++ b/Jellyfin.Server/Infrastructure/SymlinkFollowingPhysicalFileResultExecutor.cs @@ -69,8 +69,8 @@ namespace Jellyfin.Server.Infrastructure /// protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue? range, long rangeLength) { - ArgumentNullException.ThrowIfNull(context, nameof(context)); - ArgumentNullException.ThrowIfNull(result, nameof(result)); + ArgumentNullException.ThrowIfNull(context); + ArgumentNullException.ThrowIfNull(result); if (range != null && rangeLength == 0) { diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index 14534aa50b..1acb92fdc6 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities /// Trailer URL. public static void AddTrailerUrl(this BaseItem item, string url) { - ArgumentNullException.ThrowIfNull(url, nameof(url)); + ArgumentNullException.ThrowIfNull(url); if (url.Length == 0) { -- cgit v1.2.3 From f6af28cf96624f0f3ec6073fcee099623491c0b4 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 11 Oct 2022 23:37:29 +0200 Subject: Fix some things that slipped through the cracks --- .../Library/Resolvers/BaseVideoResolver.cs | 2 +- .../Library/Resolvers/Books/BookResolver.cs | 5 +- .../Library/Resolvers/GenericFolderResolver.cs | 1 + .../Library/Resolvers/ItemResolver.cs | 58 ---------------------- .../Library/Resolvers/Movies/MovieResolver.cs | 2 +- .../Library/Resolvers/PhotoResolver.cs | 1 + .../Library/Resolvers/TV/EpisodeResolver.cs | 2 +- .../LiveTv/EmbyTV/EmbyTV.cs | 4 +- .../LiveTv/Listings/XmlTvListingsProvider.cs | 19 +++---- Jellyfin.Api/Controllers/PlaystateController.cs | 4 +- Jellyfin.Api/Controllers/SessionController.cs | 4 +- .../Controllers/UniversalAudioController.cs | 2 +- MediaBrowser.Controller/Properties/AssemblyInfo.cs | 2 + MediaBrowser.Controller/Resolvers/ItemResolver.cs | 4 +- jellyfin.ruleset | 10 ++++ 15 files changed, 36 insertions(+), 84 deletions(-) delete mode 100644 Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 3d6b9f3b62..b2a7abb1bd 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -38,7 +38,7 @@ namespace Emby.Server.Implementations.Library.Resolvers /// /// The args. /// `0. - public override T Resolve(ItemResolveArgs args) + protected override T Resolve(ItemResolveArgs args) { return ResolveVideo(args, false); } diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index 8f224f547a..6fc200e3b1 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -8,15 +8,16 @@ using System.Linq; using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Resolvers.Books { - public class BookResolver : MediaBrowser.Controller.Resolvers.ItemResolver + public class BookResolver : ItemResolver { private readonly string[] _validExtensions = { ".azw", ".azw3", ".cb7", ".cbr", ".cbt", ".cbz", ".epub", ".mobi", ".pdf" }; - public override Book Resolve(ItemResolveArgs args) + protected override Book Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs index f109a5e9a2..0799622825 100644 --- a/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Resolvers; namespace Emby.Server.Implementations.Library.Resolvers { diff --git a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs deleted file mode 100644 index 3f29ab191f..0000000000 --- a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs +++ /dev/null @@ -1,58 +0,0 @@ -#nullable disable - -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Resolvers; - -namespace Emby.Server.Implementations.Library.Resolvers -{ - /// - /// Class ItemResolver. - /// - /// The type of BaseItem. - public abstract class ItemResolver : IItemResolver - where T : BaseItem, new() - { - /// - /// Gets the priority. - /// - /// The priority. - public virtual ResolverPriority Priority => ResolverPriority.First; - - /// - /// Resolves the specified args. - /// - /// The args. - /// `0. - protected virtual T Resolve(ItemResolveArgs args) - { - return null; - } - - /// - /// Sets initial values on the newly resolved item. - /// - /// The item. - /// The args. - protected virtual void SetInitialItemValues(T item, ItemResolveArgs args) - { - } - - /// - /// Resolves the path. - /// - /// The args. - /// BaseItem. - BaseItem IItemResolver.ResolvePath(ItemResolveArgs args) - { - var item = Resolve(args); - - if (item != null) - { - SetInitialItemValues(item, args); - } - - return item; - } - } -} diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index b2f388a667..8f9e5f01b1 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -80,7 +80,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// /// The args. /// Video. - public override Video Resolve(ItemResolveArgs args) + protected override Video Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index af4abfb805..e11fb262eb 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -12,6 +12,7 @@ using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Resolvers diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index bfa73af2f4..9ba079edfd 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -30,7 +30,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// /// The args. /// Episode. - public override Episode Resolve(ItemResolveArgs args) + protected override Episode Resolve(ItemResolveArgs args) { var parent = args.Parent; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 3db422c2f0..74321a256e 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -2218,9 +2218,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { continue; } - + // Skip ShowId without SubKey from duplicate removal actions - https://github.com/jellyfin/jellyfin/issues/5856 - if (group.Key.EndsWith("0000")) + if (group.Key.EndsWith("0000", StringComparison.Ordinal)) { continue; } diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 8ed8e1fc6e..0232843b16 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -88,25 +88,20 @@ namespace Emby.Server.Implementations.LiveTv.Listings using var response = await _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(info.Path, cancellationToken).ConfigureAwait(false); await using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false); - return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false); } else { - await using var stream = new FileStream(info.Path, FileMode.Open, FileAccess.Read, FileShare.Read, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); - + await using var stream = AsyncFile.OpenRead(info.Path); return await UnzipIfNeededAndCopy(info.Path, stream, cacheFile, cancellationToken).ConfigureAwait(false); } } private async Task UnzipIfNeededAndCopy(string originalUrl, Stream stream, string file, CancellationToken cancellationToken) { - int index = originalUrl.IndexOf('?', StringComparison.CurrentCulture); - string ext = Path.GetExtension(index > -1 ? originalUrl.Remove(index) : originalUrl); - - await using var fileStream = new FileStream(file, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.CopyToBufferSize, FileOptions.Asynchronous); + await using var fileStream = new FileStream(file, FileMode.CreateNew, FileAccess.Write, FileShare.None, IODefaults.FileStreamBufferSize, FileOptions.Asynchronous); - if (ext.Equals(".gz", StringComparison.OrdinalIgnoreCase)) + if (Path.GetExtension(originalUrl.AsSpan().LeftPart('?')).Equals(".gz", StringComparison.OrdinalIgnoreCase)) { try { @@ -166,16 +161,16 @@ namespace Emby.Server.Implementations.LiveTv.Listings IsMovie = program.Categories.Any(c => info.MovieCategories.Contains(c, StringComparison.OrdinalIgnoreCase)), IsNews = program.Categories.Any(c => info.NewsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)), IsSports = program.Categories.Any(c => info.SportsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)), - ImageUrl = program.Icon != null && !string.IsNullOrEmpty(program.Icon.Source) ? program.Icon.Source : null, - HasImage = program.Icon != null && !string.IsNullOrEmpty(program.Icon.Source), - OfficialRating = program.Rating != null && !string.IsNullOrEmpty(program.Rating.Value) ? program.Rating.Value : null, + ImageUrl = !string.IsNullOrEmpty(program.Icon?.Source) ? program.Icon.Source : null, + HasImage = !string.IsNullOrEmpty(program.Icon?.Source), + OfficialRating = !string.IsNullOrEmpty(program.Rating?.Value) ? program.Rating.Value : null, CommunityRating = program.StarRating, SeriesId = program.Episode == null ? null : program.Title.GetMD5().ToString("N", CultureInfo.InvariantCulture) }; if (string.IsNullOrWhiteSpace(program.ProgramId)) { - string uniqueString = (program.Title ?? string.Empty) + (episodeTitle ?? string.Empty) /*+ (p.IceTvEpisodeNumber ?? string.Empty)*/; + string uniqueString = (program.Title ?? string.Empty) + (episodeTitle ?? string.Empty); if (programInfo.SeasonNumber.HasValue) { diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 0dd4bf8035..3a2ba033ea 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -274,7 +274,7 @@ namespace Jellyfin.Api.Controllers }; playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); - playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; + playbackProgressInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackProgress(playbackProgressInfo).ConfigureAwait(false); return NoContent(); } @@ -319,7 +319,7 @@ namespace Jellyfin.Api.Controllers await _transcodingJobHelper.KillTranscodingJobs(User.GetDeviceId()!, playbackStopInfo.PlaySessionId, s => true).ConfigureAwait(false); } - playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false);; + playbackStopInfo.SessionId = await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false); await _sessionManager.OnPlaybackStopped(playbackStopInfo).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 28415555ed..31b95162d4 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -182,7 +182,7 @@ namespace Jellyfin.Api.Controllers }; await _sessionManager.SendPlayCommand( - await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, playRequest, CancellationToken.None) @@ -210,7 +210,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? controllingUserId) { await _sessionManager.SendPlaystateCommand( - await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), + await RequestHelpers.GetSessionId(_sessionManager, _userManager, HttpContext).ConfigureAwait(false), sessionId, new PlaystateRequest() { diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 01e13b4fe3..d77126a353 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -108,7 +108,7 @@ namespace Jellyfin.Api.Controllers { var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); - if (!userId.HasValue || userId.Value.Equals(Guid.Empty)) + if (!userId.HasValue || userId.Value.Equals(default)) { userId = User.GetUserId(); } diff --git a/MediaBrowser.Controller/Properties/AssemblyInfo.cs b/MediaBrowser.Controller/Properties/AssemblyInfo.cs index 60e7923091..4cd5c76c1e 100644 --- a/MediaBrowser.Controller/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Controller/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Resources; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following @@ -14,6 +15,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] +[assembly: InternalsVisibleTo("Jellyfin.Server.Implementations.Tests")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/MediaBrowser.Controller/Resolvers/ItemResolver.cs b/MediaBrowser.Controller/Resolvers/ItemResolver.cs index 7fd54fcc69..e7bf013fa2 100644 --- a/MediaBrowser.Controller/Resolvers/ItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/ItemResolver.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Controller.Resolvers /// /// The args. /// `0. - public virtual T Resolve(ItemResolveArgs args) + protected internal virtual T Resolve(ItemResolveArgs args) { return null; } @@ -42,7 +42,7 @@ namespace MediaBrowser.Controller.Resolvers /// /// The args. /// BaseItem. - BaseItem IItemResolver.ResolvePath(ItemResolveArgs args) + public BaseItem ResolvePath(ItemResolveArgs args) { var item = Resolve(args); diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 5ac5f49239..8144db93d5 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -5,8 +5,16 @@ + + + + + + + + @@ -69,6 +77,8 @@ + + -- cgit v1.2.3 From 224bb355ddb0c991873d172dec96d47f36ab02ea Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 11 Oct 2022 21:45:49 +0200 Subject: Rewrite BaseItem.ModifySortChunks --- MediaBrowser.Controller/Entities/BaseItem.cs | 68 ++++++++-------------- MediaBrowser.Controller/Properties/AssemblyInfo.cs | 1 + .../Entities/BaseItemTests.cs | 18 ++++++ 3 files changed, 44 insertions(+), 43 deletions(-) create mode 100644 tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 41fce67fa7..24163f1df9 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -775,36 +775,6 @@ namespace MediaBrowser.Controller.Entities return Id.ToString("N", CultureInfo.InvariantCulture); } - private List> GetSortChunks(string s1) - { - var list = new List>(); - - int thisMarker = 0; - - while (thisMarker < s1.Length) - { - char thisCh = s1[thisMarker]; - - var thisChunk = new StringBuilder(); - bool isNumeric = char.IsDigit(thisCh); - - while (thisMarker < s1.Length && char.IsDigit(thisCh) == isNumeric) - { - thisChunk.Append(thisCh); - thisMarker++; - - if (thisMarker < s1.Length) - { - thisCh = s1[thisMarker]; - } - } - - list.Add(new Tuple(thisChunk, isNumeric)); - } - - return list; - } - public virtual bool CanDelete() { if (SourceType == SourceType.Channel) @@ -951,28 +921,40 @@ namespace MediaBrowser.Controller.Entities return ModifySortChunks(sortable); } - private string ModifySortChunks(string name) + internal static string ModifySortChunks(string name) { - var chunks = GetSortChunks(name); + void AppendChunk(StringBuilder builder, bool isDigitChunk, ReadOnlySpan chunk) + { + if (isDigitChunk && chunk.Length < 10) + { + builder.Append('0', 10 - chunk.Length); + } - var builder = new StringBuilder(); + builder.Append(chunk); + } - foreach (var chunk in chunks) + if (name.Length == 0) { - var chunkBuilder = chunk.Item1; + return string.Empty; + } + + var builder = new StringBuilder(name.Length); - // This chunk is numeric - if (chunk.Item2) + int chunkStart = 0; + bool isDigitChunk = char.IsDigit(name[0]); + for (int i = 0; i < name.Length; i++) + { + var isDigit = char.IsDigit(name[i]); + if (isDigit != isDigitChunk) { - while (chunkBuilder.Length < 10) - { - chunkBuilder.Insert(0, '0'); - } + AppendChunk(builder, isDigitChunk, name.AsSpan(chunkStart, i - chunkStart)); + chunkStart = i; + isDigitChunk = isDigit; } - - builder.Append(chunkBuilder); } + AppendChunk(builder, isDigitChunk, name.AsSpan(chunkStart)); + // logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); return builder.ToString().RemoveDiacritics(); } diff --git a/MediaBrowser.Controller/Properties/AssemblyInfo.cs b/MediaBrowser.Controller/Properties/AssemblyInfo.cs index 4cd5c76c1e..534dec8d2a 100644 --- a/MediaBrowser.Controller/Properties/AssemblyInfo.cs +++ b/MediaBrowser.Controller/Properties/AssemblyInfo.cs @@ -15,6 +15,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("en")] +[assembly: InternalsVisibleTo("Jellyfin.Controller.Tests")] [assembly: InternalsVisibleTo("Jellyfin.Server.Implementations.Tests")] // Setting ComVisible to false makes the types in this assembly not visible diff --git a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs new file mode 100644 index 0000000000..985bbcde1f --- /dev/null +++ b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs @@ -0,0 +1,18 @@ +using MediaBrowser.Controller.Entities; +using Xunit; + +namespace Jellyfin.Controller.Tests.Entities +{ + public class BaseItemTests + { + [Theory] + [InlineData("", "")] + [InlineData("1", "0000000001")] + [InlineData("t", "t")] + [InlineData("test", "test")] + [InlineData("test1", "test0000000001")] + [InlineData("1test 2", "0000000001test 0000000002")] + public void BaseItem_ModifySortChunks_Valid(string input, string expected) + => Assert.Equal(expected, BaseItem.ModifySortChunks(input)); + } +} -- cgit v1.2.3 From 560d0838c7ad0582b80f3a8bf92b7e7d73f8e989 Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Sun, 16 Oct 2022 23:08:59 +0800 Subject: Add Vulkan filtering support for AMD VAAPI (Vega/gfx9+) This requires: - VK_EXT_image_drm_format_modifier extension - Linux kernel version >= 5.15 - jellyfin-ffmpeg5 >= 5.0.1-2 Signed-off-by: nyanmisaka --- .../MediaEncoding/EncodingHelper.cs | 281 ++++++++++++++++++++- .../MediaEncoding/FilterOptionType.cs | 7 +- .../MediaEncoding/IMediaEncoder.cs | 6 + .../Encoder/EncoderValidator.cs | 42 ++- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 19 ++ 5 files changed, 340 insertions(+), 15 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 42c5517f9d..b378dc7c93 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -31,10 +31,13 @@ namespace MediaBrowser.Controller.MediaEncoding private const string VideotoolboxAlias = "vt"; private const string OpenclAlias = "ocl"; private const string CudaAlias = "cu"; + private const string DrmAlias = "dr"; + private const string VulkanAlias = "vk"; private readonly IApplicationPaths _appPaths; private readonly IMediaEncoder _mediaEncoder; private readonly ISubtitleEncoder _subtitleEncoder; private readonly IConfiguration _config; + private readonly Version _minKernelVersionAmdVkFmtModifier = new Version(5, 15); private readonly Version _minKernelVersioni915Hang = new Version(5, 18); private static readonly string[] _videoProfilesH264 = new[] @@ -149,6 +152,14 @@ namespace MediaBrowser.Controller.MediaEncoding && _mediaEncoder.SupportsFilter("hwupload_cuda"); } + private bool IsVulkanFullSupported() + { + return _mediaEncoder.SupportsHwaccel("vulkan") + && _mediaEncoder.SupportsFilter("libplacebo") + && _mediaEncoder.SupportsFilter("scale_vulkan") + && _mediaEncoder.SupportsFilterWithOption(FilterOptionType.OverlayVulkanFrameSync); + } + private bool IsHwTonemapAvailable(EncodingJobInfo state, EncodingOptions options) { if (state.VideoStream == null @@ -176,6 +187,19 @@ namespace MediaBrowser.Controller.MediaEncoding || string.Equals(state.VideoStream.VideoRangeType, "HLG", StringComparison.OrdinalIgnoreCase)); } + private bool IsVulkanHwTonemapAvailable(EncodingJobInfo state, EncodingOptions options) + { + if (state.VideoStream == null) + { + return false; + } + + // libplacebo has partial Dolby Vision to SDR tonemapping support. + return options.EnableTonemapping + && string.Equals(state.VideoStream.VideoRange, "HDR", StringComparison.OrdinalIgnoreCase) + && GetVideoColorBitDepth(state) == 10; + } + private bool IsVaapiVppTonemapAvailable(EncodingJobInfo state, EncodingOptions options) { if (state.VideoStream == null @@ -756,8 +780,13 @@ namespace MediaBrowser.Controller.MediaEncoding } else if (_mediaEncoder.IsVaapiDeviceAmd) { - args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias)); - filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); + if (!IsVulkanFullSupported() + || !_mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier + || Environment.OSVersion.Version < _minKernelVersionAmdVkFmtModifier) + { + args.Append(GetOpenclDeviceArgs(0, "Advanced Micro Devices", null, OpenclAlias)); + filterDevArgs = GetFilterHwDeviceArgs(OpenclAlias); + } } else { @@ -2774,22 +2803,41 @@ namespace MediaBrowser.Controller.MediaEncoding return string.Empty; } - var args = "tonemap_{0}=format={1}:p=bt709:t=bt709:m=bt709"; + var args = string.Empty; + var algorithm = options.TonemappingAlgorithm; - if (hwTonemapSuffix.Contains("vaapi", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(hwTonemapSuffix, "vaapi", StringComparison.OrdinalIgnoreCase)) { - args += ",procamp_vaapi=b={2}:c={3}:extra_hw_frames=16"; + args = "tonemap_vaapi=format={0}:p=bt709:t=bt709:m=bt709,procamp_vaapi=b={1}:c={2}:extra_hw_frames=16"; return string.Format( CultureInfo.InvariantCulture, args, - hwTonemapSuffix, videoFormat ?? "nv12", options.VppTonemappingBrightness, options.VppTonemappingContrast); } + else if (string.Equals(hwTonemapSuffix, "vulkan", StringComparison.OrdinalIgnoreCase)) + { + args = "libplacebo=format={1}:tonemapping={2}:color_primaries=bt709:color_trc=bt709:colorspace=bt709:peak_detect=0:upscaler=none:downscaler=none"; + + if (!string.Equals(options.TonemappingRange, "auto", StringComparison.OrdinalIgnoreCase)) + { + args += ":range={6}"; + } + + if (string.Equals(options.TonemappingAlgorithm, "bt2390", StringComparison.OrdinalIgnoreCase)) + { + algorithm = "bt.2390"; + } + + else if (string.Equals(options.TonemappingAlgorithm, "none", StringComparison.OrdinalIgnoreCase)) + { + algorithm = "clip"; + } + } else { - args += ":tonemap={2}:peak={3}:desat={4}"; + args = "tonemap_{0}=format={1}:p=bt709:t=bt709:m=bt709:tonemap={2}:peak={3}:desat={4}"; if (options.TonemappingParam != 0) { @@ -2807,7 +2855,7 @@ namespace MediaBrowser.Controller.MediaEncoding args, hwTonemapSuffix, videoFormat ?? "nv12", - options.TonemappingAlgorithm, + algorithm, options.TonemappingPeak, options.TonemappingDesat, options.TonemappingParam, @@ -3770,7 +3818,9 @@ namespace MediaBrowser.Controller.MediaEncoding var vidDecoder = GetHardwareVideoDecoder(state, options) ?? string.Empty; var isSwDecoder = string.IsNullOrEmpty(vidDecoder); var isSwEncoder = !vidEncoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase); - var isVaapiOclSupported = isLinux && IsVaapiSupported(state) && IsVaapiFullSupported() && IsOpenclFullSupported(); + var isVaapiFullSupported = isLinux && IsVaapiSupported(state) && IsVaapiFullSupported(); + var isVaapiOclSupported = isVaapiFullSupported && IsOpenclFullSupported(); + var isVaapiVkSupported = isVaapiFullSupported && IsVulkanFullSupported(); // legacy vaapi pipeline(copy-back) if ((isSwDecoder && isSwEncoder) @@ -3798,14 +3848,24 @@ namespace MediaBrowser.Controller.MediaEncoding if (_mediaEncoder.IsVaapiDeviceInteliHD) { // Intel iHD path, with extra vpp tonemap and overlay support. - return GetVaapiFullVidFiltersPrefered(state, options, vidDecoder, vidEncoder); + return GetIntelVaapiFullVidFiltersPrefered(state, options, vidDecoder, vidEncoder); + } + + // prefered vaapi + vulkan filters pipeline + if (_mediaEncoder.IsVaapiDeviceAmd + && isVaapiVkSupported + && _mediaEncoder.IsVaapiDeviceSupportVulkanFmtModifier + && Environment.OSVersion.Version >= _minKernelVersionAmdVkFmtModifier) + { + // AMD radeonsi path(Vega/gfx9+, kernel>=5.15), with extra vulkan tonemap and overlay support. + return GetAmdVaapiFullVidFiltersPrefered(state, options, vidDecoder, vidEncoder); } - // Intel i965 and Amd radeonsi/r600 path, only featuring scale and deinterlace support. + // Intel i965 and Amd radeonsi/r600 path(Polaris/gfx8-), only featuring scale and deinterlace support. return GetVaapiLimitedVidFiltersPrefered(state, options, vidDecoder, vidEncoder); } - public (List MainFilters, List SubFilters, List OverlayFilters) GetVaapiFullVidFiltersPrefered( + public (List MainFilters, List SubFilters, List OverlayFilters) GetIntelVaapiFullVidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, string vidDecoder, @@ -4003,6 +4063,203 @@ namespace MediaBrowser.Controller.MediaEncoding return (mainFilters, subFilters, overlayFilters); } + public (List MainFilters, List SubFilters, List OverlayFilters) GetAmdVaapiFullVidFiltersPrefered( + EncodingJobInfo state, + EncodingOptions options, + string vidDecoder, + string vidEncoder) + { + var inW = state.VideoStream?.Width; + var inH = state.VideoStream?.Height; + var reqW = state.BaseRequest.Width; + var reqH = state.BaseRequest.Height; + var reqMaxW = state.BaseRequest.MaxWidth; + var reqMaxH = state.BaseRequest.MaxHeight; + var threeDFormat = state.MediaSource.Video3DFormat; + + var isVaapiDecoder = vidDecoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase); + var isVaapiEncoder = vidEncoder.Contains("vaapi", StringComparison.OrdinalIgnoreCase); + var isSwDecoder = string.IsNullOrEmpty(vidDecoder); + var isSwEncoder = !isVaapiEncoder; + var isVaInVaOut = isVaapiDecoder && isVaapiEncoder; + + var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true); + var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true); + var doVkTonemap = IsVulkanHwTonemapAvailable(state, options); + var doDeintH2645 = doDeintH264 || doDeintHevc; + + var hasSubs = state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; + var hasTextSubs = hasSubs && state.SubtitleStream.IsTextSubtitleStream; + var hasGraphicalSubs = hasSubs && !state.SubtitleStream.IsTextSubtitleStream; + var hasAssSubs = hasSubs + && (string.Equals(state.SubtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) + || string.Equals(state.SubtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase)); + + /* Make main filters for video stream */ + var mainFilters = new List(); + + mainFilters.Add(GetOverwriteColorPropertiesParam(state, doVkTonemap)); + + if (isSwDecoder) + { + // INPUT sw surface(memory) + // sw deint + if (doDeintH2645) + { + var swDeintFilter = GetSwDeinterlaceFilter(state, options); + mainFilters.Add(swDeintFilter); + } + + var outFormat = doVkTonemap ? "yuv420p10le" : "nv12"; + var swScaleFilter = GetSwScaleFilter(state, options, vidEncoder, inW, inH, threeDFormat, reqW, reqH, reqMaxW, reqMaxH); + // sw scale + mainFilters.Add(swScaleFilter); + mainFilters.Add("format=" + outFormat); + + // keep video at memory except vk tonemap, + // since the overhead caused by hwupload >>> using sw filter. + // sw => hw + if (doVkTonemap) + { + mainFilters.Add("hwupload=derive_device=vulkan:extra_hw_frames=16"); + } + } + else if (isVaapiDecoder) + { + // INPUT vaapi surface(vram) + // hw deint + if (doDeintH2645) + { + var deintFilter = GetHwDeinterlaceFilter(state, options, "vaapi"); + mainFilters.Add(deintFilter); + } + + var outFormat = doVkTonemap ? string.Empty : (hasSubs && isVaInVaOut ? "bgra" : "nv12"); + var hwScaleFilter = GetHwScaleFilter("vaapi", outFormat, inW, inH, reqW, reqH, reqMaxW, reqMaxH); + + // allocate extra pool sizes for overlay_vulkan + if (!string.IsNullOrEmpty(hwScaleFilter) && isVaInVaOut && hasSubs) + { + hwScaleFilter += ":extra_hw_frames=32"; + } + + // hw scale + mainFilters.Add(hwScaleFilter); + } + + if ((isVaapiDecoder && doVkTonemap) || (isVaInVaOut && (doVkTonemap || hasSubs))) + { + // map from vaapi to vulkan via vaapi-vulkan interop (Vega/gfx9+). + mainFilters.Add("hwmap=derive_device=vulkan"); + } + + // vk tonemap + if (doVkTonemap) + { + var outFormat = isVaInVaOut && hasSubs ? "bgra" : "nv12"; + var tonemapFilter = GetHwTonemapFilter(options, "vulkan", outFormat); + mainFilters.Add(tonemapFilter); + } + + if (doVkTonemap && isVaInVaOut && !hasSubs) + { + // OUTPUT vaapi(nv12/bgra) surface(vram) + // reverse-mapping via vaapi-vulkan interop. + mainFilters.Add("hwmap=derive_device=vaapi:reverse=1"); + mainFilters.Add("format=vaapi"); + } + + var memoryOutput = false; + var isUploadForVkTonemap = isSwDecoder && doVkTonemap; + if ((isVaapiDecoder && isSwEncoder) || isUploadForVkTonemap) + { + memoryOutput = true; + + // OUTPUT nv12 surface(memory) + mainFilters.Add("hwdownload"); + mainFilters.Add("format=nv12"); + } + + // OUTPUT nv12 surface(memory) + if (isSwDecoder && isVaapiEncoder) + { + memoryOutput = true; + } + + if (memoryOutput) + { + // text subtitles + if (hasTextSubs) + { + var textSubtitlesFilter = GetTextSubtitlesFilter(state, false, false); + mainFilters.Add(textSubtitlesFilter); + } + } + + if (memoryOutput && isVaapiEncoder) + { + if (!hasGraphicalSubs) + { + mainFilters.Add("hwupload_vaapi"); + } + } + + /* Make sub and overlay filters for subtitle stream */ + var subFilters = new List(); + var overlayFilters = new List(); + if (isVaInVaOut) + { + if (hasSubs) + { + if (hasGraphicalSubs) + { + // scale=s=1280x720,format=bgra,hwupload + var subSwScaleFilter = GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH); + subFilters.Add(subSwScaleFilter); + subFilters.Add("format=bgra"); + } + else if (hasTextSubs) + { + var alphaSrcFilter = GetAlphaSrcFilter(state, inW, inH, reqW, reqH, reqMaxW, reqMaxH, hasAssSubs ? 10 : 5); + var subTextSubtitlesFilter = GetTextSubtitlesFilter(state, true, true); + subFilters.Add(alphaSrcFilter); + subFilters.Add("format=bgra"); + subFilters.Add(subTextSubtitlesFilter); + } + + subFilters.Add("hwupload=derive_device=vulkan:extra_hw_frames=16"); + + overlayFilters.Add("overlay_vulkan=eof_action=endall:shortest=1:repeatlast=0"); + + // explicitly sync using libplacebo. + overlayFilters.Add("libplacebo=format=nv12:upscaler=none:downscaler=none"); + + // OUTPUT vaapi(nv12/bgra) surface(vram) + // reverse-mapping via vaapi-vulkan interop. + overlayFilters.Add("hwmap=derive_device=vaapi:reverse=1"); + overlayFilters.Add("format=vaapi"); + } + } + else if (memoryOutput) + { + if (hasGraphicalSubs) + { + var subSwScaleFilter = isSwDecoder + ? GetSwScaleFilter(state, options, vidEncoder, inW, inH, threeDFormat, reqW, reqH, reqMaxW, reqMaxH) + : GetCustomSwScaleFilter(inW, inH, reqW, reqH, reqMaxW, reqMaxH); + subFilters.Add(subSwScaleFilter); + overlayFilters.Add("overlay=eof_action=pass:shortest=1:repeatlast=0"); + + if (isVaapiEncoder) + { + overlayFilters.Add("hwupload_vaapi"); + } + } + } + + return (mainFilters, subFilters, overlayFilters); + } + public (List MainFilters, List SubFilters, List OverlayFilters) GetVaapiLimitedVidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, diff --git a/MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs b/MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs index a4869cb670..b1d319d211 100644 --- a/MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs +++ b/MediaBrowser.Controller/MediaEncoding/FilterOptionType.cs @@ -28,6 +28,11 @@ namespace MediaBrowser.Controller.MediaEncoding /// /// The overlay_vaapi_framesync. /// - OverlayVaapiFrameSync = 4 + OverlayVaapiFrameSync = 4, + + /// + /// The overlay_vulkan_framesync. + /// + OverlayVulkanFrameSync = 5 } } diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 69d0bf45cc..52c57b906e 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -61,6 +61,12 @@ namespace MediaBrowser.Controller.MediaEncoding /// true if the Vaapi device is an Intel(legacy i965 driver) GPU, false otherwise. bool IsVaapiDeviceInteli965 { get; } + /// + /// Gets a value indicating whether the configured Vaapi device supports vulkan drm format modifier. + /// + /// true if the Vaapi device supports vulkan drm format modifier, false otherwise. + bool IsVaapiDeviceSupportVulkanFmtModifier { get; } + /// /// Whether given encoder codec is supported. /// diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 9b4b1db947..8c8fc6b0f8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -102,7 +102,11 @@ namespace MediaBrowser.MediaEncoding.Encoder "tonemap_vaapi", "procamp_vaapi", "overlay_vaapi", - "hwupload_vaapi" + "hwupload_vaapi", + // vulkan + "libplacebo", + "scale_vulkan", + "overlay_vulkan" }; private static readonly IReadOnlyDictionary _filterOptionsDict = new Dictionary @@ -111,7 +115,8 @@ namespace MediaBrowser.MediaEncoding.Encoder { 1, new string[] { "tonemap_cuda", "GPU accelerated HDR to SDR tonemapping" } }, { 2, new string[] { "tonemap_opencl", "bt2390" } }, { 3, new string[] { "overlay_opencl", "Action to take when encountering EOF from secondary input" } }, - { 4, new string[] { "overlay_vaapi", "Action to take when encountering EOF from secondary input" } } + { 4, new string[] { "overlay_vaapi", "Action to take when encountering EOF from secondary input" } }, + { 5, new string[] { "overlay_vulkan", "Action to take when encountering EOF from secondary input" } } }; // These are the library versions that corresponds to our minimum ffmpeg version 4.x according to the version table below @@ -351,6 +356,39 @@ namespace MediaBrowser.MediaEncoding.Encoder } } + public bool CheckVulkanDrmDeviceByExtensionName(string renderNodePath, string[] vulkanExtensions) + { + if (!OperatingSystem.IsLinux()) + { + return false; + } + + if (string.IsNullOrEmpty(renderNodePath)) + { + return false; + } + + try + { + var command = "-v verbose -hide_banner -init_hw_device drm=dr:" + renderNodePath + " -init_hw_device vulkan=vk@dr"; + var output = GetProcessOutput(_encoderPath, command, true, null); + foreach (string ext in vulkanExtensions) + { + if (!output.Contains(ext, StringComparison.Ordinal)) + { + return false; + } + } + + return true; + } + catch (Exception ex) + { + _logger.LogError(ex, "Error detecting the given drm render node path"); + return false; + } + } + private IEnumerable GetHwaccelTypes() { string? output = null; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 757a01715a..ec3412f90b 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -72,6 +72,16 @@ namespace MediaBrowser.MediaEncoding.Encoder private bool _isVaapiDeviceAmd = false; private bool _isVaapiDeviceInteliHD = false; private bool _isVaapiDeviceInteli965 = false; + private bool _isVaapiDeviceSupportVulkanFmtModifier = false; + + private static string[] _vulkanFmtModifierExts = { + "VK_KHR_sampler_ycbcr_conversion", + "VK_EXT_image_drm_format_modifier", + "VK_KHR_external_memory_fd", + "VK_EXT_external_memory_dma_buf", + "VK_KHR_external_semaphore_fd", + "VK_EXT_external_memory_host" + }; private Version _ffmpegVersion = null; private string _ffmpegPath = string.Empty; @@ -110,6 +120,8 @@ namespace MediaBrowser.MediaEncoding.Encoder public bool IsVaapiDeviceInteli965 => _isVaapiDeviceInteli965; + public bool IsVaapiDeviceSupportVulkanFmtModifier => _isVaapiDeviceSupportVulkanFmtModifier; + /// /// Run at startup or if the user removes a Custom path from transcode page. /// Sets global variables FFmpegPath. @@ -169,6 +181,8 @@ namespace MediaBrowser.MediaEncoding.Encoder _isVaapiDeviceAmd = validator.CheckVaapiDeviceByDriverName("Mesa Gallium driver", options.VaapiDevice); _isVaapiDeviceInteliHD = validator.CheckVaapiDeviceByDriverName("Intel iHD driver", options.VaapiDevice); _isVaapiDeviceInteli965 = validator.CheckVaapiDeviceByDriverName("Intel i965 driver", options.VaapiDevice); + _isVaapiDeviceSupportVulkanFmtModifier = validator.CheckVulkanDrmDeviceByExtensionName(options.VaapiDevice, _vulkanFmtModifierExts); + if (_isVaapiDeviceAmd) { _logger.LogInformation("VAAPI device {RenderNodePath} is AMD GPU", options.VaapiDevice); @@ -181,6 +195,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { _logger.LogInformation("VAAPI device {RenderNodePath} is Intel GPU (i965)", options.VaapiDevice); } + + if (_isVaapiDeviceSupportVulkanFmtModifier) + { + _logger.LogInformation("VAAPI device {RenderNodePath} supports Vulkan DRM format modifier", options.VaapiDevice); + } } } -- cgit v1.2.3 From c2c286be6ed1ed33cb78aaebd9f14dc7f19fe0d1 Mon Sep 17 00:00:00 2001 From: jgriff6 <74262798+jgriff6@users.noreply.github.com> Date: Tue, 25 Oct 2022 01:47:53 +0100 Subject: Remove unnecessary IsPathLocked function --- Emby.Server.Implementations/IO/LibraryMonitor.cs | 6 ------ MediaBrowser.Controller/Library/ILibraryMonitor.cs | 7 ------- 2 files changed, 13 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 341d67b8a2..c1422c43da 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -79,12 +79,6 @@ namespace Emby.Server.Implementations.IO TemporarilyIgnore(path); } - public bool IsPathLocked(string path) - { - // This method is not used by the core but it used by auto-organize - return _tempIgnoredPaths.Keys.Any(i => _fileSystem.AreEqual(i, path) || _fileSystem.ContainsSubPath(i, path)); - } - public async void ReportFileSystemChangeComplete(string path, bool refreshPath) { if (string.IsNullOrEmpty(path)) diff --git a/MediaBrowser.Controller/Library/ILibraryMonitor.cs b/MediaBrowser.Controller/Library/ILibraryMonitor.cs index 455054bd12..de74aa5a11 100644 --- a/MediaBrowser.Controller/Library/ILibraryMonitor.cs +++ b/MediaBrowser.Controller/Library/ILibraryMonitor.cs @@ -34,12 +34,5 @@ namespace MediaBrowser.Controller.Library /// /// The path. void ReportFileSystemChanged(string path); - - /// - /// Determines whether [is path locked] [the specified path]. - /// - /// The path. - /// true if [is path locked] [the specified path]; otherwise, false. - bool IsPathLocked(string path); } } -- cgit v1.2.3 From 09e8a7e62c9a8ef567f2d336e37a7cc732e3aaab Mon Sep 17 00:00:00 2001 From: photonconvergence <116527579+photonconvergence@users.noreply.github.com> Date: Thu, 27 Oct 2022 18:01:04 -0700 Subject: Fix extra type differentiation Change rules for Featurettes and Shorts so they don't both get classed as ExtraType.Clip. Fix test that these changes break --- Emby.Naming/Common/NamingOptions.cs | 14 ++++++++++---- MediaBrowser.Controller/Entities/BaseItem.cs | 4 +++- MediaBrowser.Model/Entities/ExtraType.cs | 4 +++- tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs | 5 +++-- 4 files changed, 19 insertions(+), 8 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 513733ab55..25131e9c53 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -512,13 +512,13 @@ namespace Emby.Naming.Common MediaType.Video), new ExtraRule( - ExtraType.Clip, + ExtraType.Short, ExtraRuleType.DirectoryName, "shorts", MediaType.Video), new ExtraRule( - ExtraType.Clip, + ExtraType.Featurette, ExtraRuleType.DirectoryName, "featurettes", MediaType.Video), @@ -535,6 +535,12 @@ namespace Emby.Naming.Common "other", MediaType.Video), + new ExtraRule( + ExtraType.Clip, + ExtraRuleType.DirectoryName, + "clips", + MediaType.Video), + new ExtraRule( ExtraType.Trailer, ExtraRuleType.Filename, @@ -638,13 +644,13 @@ namespace Emby.Naming.Common MediaType.Video), new ExtraRule( - ExtraType.Clip, + ExtraType.Featurette, ExtraRuleType.Suffix, "-featurette", MediaType.Video), new ExtraRule( - ExtraType.Clip, + ExtraType.Short, ExtraRuleType.Suffix, "-short", MediaType.Video), diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 24163f1df9..7f5f9f74bd 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -75,7 +75,9 @@ namespace MediaBrowser.Controller.Entities Model.Entities.ExtraType.DeletedScene, Model.Entities.ExtraType.Interview, Model.Entities.ExtraType.Sample, - Model.Entities.ExtraType.Scene + Model.Entities.ExtraType.Scene, + Model.Entities.ExtraType.Featurette, + Model.Entities.ExtraType.Short }; private string _sortName; diff --git a/MediaBrowser.Model/Entities/ExtraType.cs b/MediaBrowser.Model/Entities/ExtraType.cs index aca4bd2829..66da80d96b 100644 --- a/MediaBrowser.Model/Entities/ExtraType.cs +++ b/MediaBrowser.Model/Entities/ExtraType.cs @@ -13,6 +13,8 @@ namespace MediaBrowser.Model.Entities Scene = 6, Sample = 7, ThemeSong = 8, - ThemeVideo = 9 + ThemeVideo = 9, + Featurette = 10, + Short = 11 } } diff --git a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs index 731580e0c9..2c33ab4929 100644 --- a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs @@ -51,8 +51,9 @@ namespace Jellyfin.Naming.Tests.Video [InlineData(ExtraType.Interview, "interviews")] [InlineData(ExtraType.Scene, "scenes")] [InlineData(ExtraType.Sample, "samples")] - [InlineData(ExtraType.Clip, "shorts")] - [InlineData(ExtraType.Clip, "featurettes")] + [InlineData(ExtraType.Short, "shorts")] + [InlineData(ExtraType.Featurette, "featurettes")] + [InlineData(ExtraType.Clip, "clips")] [InlineData(ExtraType.ThemeVideo, "backdrops")] [InlineData(ExtraType.Unknown, "extras")] public void TestDirectories(ExtraType type, string dirName) -- cgit v1.2.3 From 812a4170eee4383b5c1f5cd52cb58cc04d50cb36 Mon Sep 17 00:00:00 2001 From: cvium Date: Fri, 28 Oct 2022 22:38:58 -0400 Subject: Backport pull request #8501 from jellyfin/release-10.8.z fix: set MinIndexNumber for the next up query Original-merge: 679e83082f76b0d6c54d0aa4b8fe1138c1a10ccd Merged-by: Claus Vium Backported-by: Joshua M. Boniface --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 6 ++++++ Emby.Server.Implementations/TV/TVSeriesManager.cs | 4 +++- MediaBrowser.Controller/Entities/InternalItemsQuery.cs | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 7622d2fe68..0ebcd4c0b6 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -3524,6 +3524,12 @@ namespace Emby.Server.Implementations.Data statement?.TryBind("@MinIndexNumber", query.MinIndexNumber.Value); } + if (query.MinParentIndexNumber.HasValue) + { + whereClauses.Add("ParentIndexNumber>=@MinParentIndexNumber"); + statement?.TryBind("@MinParentIndexNumber", query.MinParentIndexNumber.Value); + } + if (query.MinDateCreated.HasValue) { whereClauses.Add("DateCreated>=@MinDateCreated"); diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 6005896ad9..be57d9c68e 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -223,7 +223,9 @@ namespace Emby.Server.Implementations.TV IsPlayed = rewatching, IsVirtualItem = false, ParentIndexNumberNotEquals = 0, - DtoOptions = dtoOptions + DtoOptions = dtoOptions, + MinIndexNumber = lastWatchedEpisode?.IndexNumberEnd ?? lastWatchedEpisode?.IndexNumber, + MinParentIndexNumber = lastWatchedEpisode?.ParentIndexNumber }; Episode nextEpisode; diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 13bfd07c34..9ae21bb595 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -205,6 +205,8 @@ namespace MediaBrowser.Controller.Entities public int? MinIndexNumber { get; set; } + public int? MinParentIndexNumber { get; set; } + public int? AiredDuringSeason { get; set; } public double? MinCriticRating { get; set; } -- cgit v1.2.3 From a214ca259838fa7d1a7052b7bd7ba6a16720406f Mon Sep 17 00:00:00 2001 From: nyanmisaka Date: Fri, 28 Oct 2022 22:39:01 -0400 Subject: Backport pull request #8620 from jellyfin/release-10.8.z Fix the DG2 HDR TM tearing issue on Windows Original-merge: 3bdc2bff5f26f8a564d8f601a599134950e8d974 Merged-by: Claus Vium Backported-by: Joshua M. Boniface --- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 235a861389..cee08eedac 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -1459,7 +1459,11 @@ namespace MediaBrowser.Controller.MediaEncoding param += " -preset 7"; } - param += " -look_ahead 0"; + // Only h264_qsv has look_ahead option + if (string.Equals(videoEncoder, "h264_qsv", StringComparison.OrdinalIgnoreCase)) + { + param += " -look_ahead 0"; + } } else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc) || string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase)) // hevc (hevc_nvenc) @@ -1497,7 +1501,7 @@ namespace MediaBrowser.Controller.MediaEncoding break; default: - param += " -preset p4"; + param += " -preset p1"; break; } } @@ -3467,6 +3471,12 @@ namespace MediaBrowser.Controller.MediaEncoding // map from d3d11va to qsv. mainFilters.Add("hwmap=derive_device=qsv"); } + else + { + // Insert a qsv scaler to sync the decoder surface, + // msdk will passthrough this internally. + mainFilters.Add("hwmap=derive_device=qsv,scale_qsv"); + } } // hw deint -- cgit v1.2.3 From 08d2acba20a7b0461ae84d778d777a5046cbf717 Mon Sep 17 00:00:00 2001 From: cvium Date: Mon, 31 Oct 2022 23:08:42 -0400 Subject: Backport pull request #8662 from jellyfin/release-10.8.z fix: use a combination of ParentIndexNumber and IndexNumber to determine next up episodes Original-merge: 45f3fb1cfc54f4dced7f6e02b7fc433056678634 Merged-by: Joshua M. Boniface Backported-by: Joshua M. Boniface --- .../Data/SqliteItemRepository.cs | 7 ++--- Emby.Server.Implementations/TV/TVSeriesManager.cs | 30 +++++++++------------- .../Entities/InternalItemsQuery.cs | 10 +++++++- 3 files changed, 25 insertions(+), 22 deletions(-) (limited to 'MediaBrowser.Controller') diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 0ebcd4c0b6..371111dffe 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -3524,10 +3524,11 @@ namespace Emby.Server.Implementations.Data statement?.TryBind("@MinIndexNumber", query.MinIndexNumber.Value); } - if (query.MinParentIndexNumber.HasValue) + if (query.MinParentAndIndexNumber.HasValue) { - whereClauses.Add("ParentIndexNumber>=@MinParentIndexNumber"); - statement?.TryBind("@MinParentIndexNumber", query.MinParentIndexNumber.Value); + whereClauses.Add("((ParentIndexNumber=@MinParentAndIndexNumberParent and IndexNumber>=@MinParentAndIndexNumberIndex) or ParentIndexNumber>@MinParentAndIndexNumberParent)"); + statement?.TryBind("@MinParentAndIndexNumberParent", query.MinParentAndIndexNumber.Value.ParentIndexNumber); + statement?.TryBind("@MinParentAndIndexNumberIndex", query.MinParentAndIndexNumber.Value.IndexNumber); } if (query.MinDateCreated.HasValue) diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index be57d9c68e..5c9b9df153 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -192,7 +192,6 @@ namespace Emby.Server.Implementations.TV AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }, IsPlayed = true, Limit = 1, ParentIndexNumberNotEquals = 0, @@ -203,11 +202,10 @@ namespace Emby.Server.Implementations.TV } }; - if (rewatching) - { - // find last watched by date played, not by newest episode watched - lastQuery.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }; - } + // If rewatching is enabled, sort first by date played and then by season and episode numbers + lastQuery.OrderBy = rewatching + ? new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) } + : new[] { (ItemSortBy.ParentIndexNumber, SortOrder.Descending), (ItemSortBy.IndexNumber, SortOrder.Descending) }; var lastWatchedEpisode = _libraryManager.GetItemList(lastQuery).Cast().FirstOrDefault(); @@ -223,23 +221,19 @@ namespace Emby.Server.Implementations.TV IsPlayed = rewatching, IsVirtualItem = false, ParentIndexNumberNotEquals = 0, - DtoOptions = dtoOptions, - MinIndexNumber = lastWatchedEpisode?.IndexNumberEnd ?? lastWatchedEpisode?.IndexNumber, - MinParentIndexNumber = lastWatchedEpisode?.ParentIndexNumber + DtoOptions = dtoOptions }; - Episode nextEpisode; - if (rewatching) - { - nextQuery.Limit = 2; - // get watched episode after most recently watched - nextEpisode = _libraryManager.GetItemList(nextQuery).Cast().ElementAtOrDefault(1); - } - else + // Locate the next up episode based on the last watched episode's season and episode number + var lastWatchedParentIndexNumber = lastWatchedEpisode?.ParentIndexNumber; + var lastWatchedIndexNumber = lastWatchedEpisode?.IndexNumberEnd ?? lastWatchedEpisode?.IndexNumber; + if (lastWatchedParentIndexNumber.HasValue && lastWatchedIndexNumber.HasValue) { - nextEpisode = _libraryManager.GetItemList(nextQuery).Cast().FirstOrDefault(); + nextQuery.MinParentAndIndexNumber = (lastWatchedParentIndexNumber.Value, lastWatchedIndexNumber.Value + 1); } + var nextEpisode = _libraryManager.GetItemList(nextQuery).Cast().FirstOrDefault(); + if (_configurationManager.Configuration.DisplaySpecialsWithinSeasons) { var consideredEpisodes = _libraryManager.GetItemList(new InternalItemsQuery(user) diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 9ae21bb595..1bf5285382 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -205,7 +205,15 @@ namespace MediaBrowser.Controller.Entities public int? MinIndexNumber { get; set; } - public int? MinParentIndexNumber { get; set; } + /// + /// Gets or sets the minimum ParentIndexNumber and IndexNumber. + /// + /// + /// It produces this where clause: + /// (ParentIndexNumber = X and IndexNumber >= Y) or ParentIndexNumber > X. + /// + /// + public (int ParentIndexNumber, int IndexNumber)? MinParentAndIndexNumber { get; set; } public int? AiredDuringSeason { get; set; } -- cgit v1.2.3