aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Dlna/Didl/DidlBuilder.cs9
-rw-r--r--Emby.Dlna/PlayTo/PlayToController.cs8
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs8
-rw-r--r--Emby.Server.Implementations/Collections/CollectionManager.cs51
-rw-r--r--Emby.Server.Implementations/Library/UserDataManager.cs8
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs2
-rw-r--r--Jellyfin.Api/Controllers/DynamicHlsController.cs24
-rw-r--r--Jellyfin.Api/Controllers/MoviesController.cs9
-rw-r--r--Jellyfin.Api/Controllers/SuggestionsController.cs2
-rw-r--r--Jellyfin.Api/Controllers/TvShowsController.cs2
-rw-r--r--Jellyfin.Api/Controllers/UserController.cs3
-rw-r--r--Jellyfin.Api/Controllers/VideoHlsController.cs24
-rw-r--r--Jellyfin.Api/Controllers/VideosController.cs25
-rw-r--r--Jellyfin.Api/Helpers/AudioHelper.cs25
-rw-r--r--Jellyfin.Api/Helpers/DynamicHlsHelper.cs27
-rw-r--r--Jellyfin.Api/Helpers/StreamingHelpers.cs14
-rw-r--r--Jellyfin.Api/Helpers/TranscodingJobHelper.cs8
-rw-r--r--Jellyfin.Api/Models/UserDtos/AuthenticateUserByName.cs5
-rw-r--r--Jellyfin.Server/Startup.cs14
-rw-r--r--MediaBrowser.Common/Net/DefaultHttpClientHandler.cs19
-rw-r--r--MediaBrowser.Controller/Entities/BaseItemExtensions.cs20
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs9
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs10
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs11
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs14
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs10
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs8
-rw-r--r--MediaBrowser.Controller/Playlists/Playlist.cs4
-rw-r--r--MediaBrowser.Controller/Session/AuthenticationRequest.cs1
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs3
-rw-r--r--MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs85
-rw-r--r--MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs37
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs23
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs47
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs18
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs15
36 files changed, 277 insertions, 325 deletions
diff --git a/Emby.Dlna/Didl/DidlBuilder.cs b/Emby.Dlna/Didl/DidlBuilder.cs
index 8b50d47fb..66ae07329 100644
--- a/Emby.Dlna/Didl/DidlBuilder.cs
+++ b/Emby.Dlna/Didl/DidlBuilder.cs
@@ -208,7 +208,8 @@ namespace Emby.Dlna.Didl
var targetWidth = streamInfo.TargetWidth;
var targetHeight = streamInfo.TargetHeight;
- var contentFeatureList = new ContentFeatureBuilder(_profile).BuildVideoHeader(
+ var contentFeatureList = ContentFeatureBuilder.BuildVideoHeader(
+ _profile,
streamInfo.Container,
streamInfo.TargetVideoCodec.FirstOrDefault(),
streamInfo.TargetAudioCodec.FirstOrDefault(),
@@ -599,7 +600,8 @@ namespace Emby.Dlna.Didl
? MimeTypes.GetMimeType(filename)
: mediaProfile.MimeType;
- var contentFeatures = new ContentFeatureBuilder(_profile).BuildAudioHeader(
+ var contentFeatures = ContentFeatureBuilder.BuildAudioHeader(
+ _profile,
streamInfo.Container,
streamInfo.TargetAudioCodec.FirstOrDefault(),
targetAudioBitrate,
@@ -1033,8 +1035,7 @@ namespace Emby.Dlna.Didl
var width = albumartUrlInfo.width ?? maxWidth;
var height = albumartUrlInfo.height ?? maxHeight;
- var contentFeatures = new ContentFeatureBuilder(_profile)
- .BuildImageHeader(format, width, height, imageInfo.IsDirectStream, org_Pn);
+ var contentFeatures = ContentFeatureBuilder.BuildImageHeader(_profile, format, width, height, imageInfo.IsDirectStream, org_Pn);
writer.WriteAttributeString(
"protocolInfo",
diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs
index 25ba18add..ee09cc65a 100644
--- a/Emby.Dlna/PlayTo/PlayToController.cs
+++ b/Emby.Dlna/PlayTo/PlayToController.cs
@@ -499,8 +499,8 @@ namespace Emby.Dlna.PlayTo
if (streamInfo.MediaType == DlnaProfileType.Audio)
{
- return new ContentFeatureBuilder(profile)
- .BuildAudioHeader(
+ return ContentFeatureBuilder.BuildAudioHeader(
+ profile,
streamInfo.Container,
streamInfo.TargetAudioCodec.FirstOrDefault(),
streamInfo.TargetAudioBitrate,
@@ -514,8 +514,8 @@ namespace Emby.Dlna.PlayTo
if (streamInfo.MediaType == DlnaProfileType.Video)
{
- var list = new ContentFeatureBuilder(profile)
- .BuildVideoHeader(
+ var list = ContentFeatureBuilder.BuildVideoHeader(
+ profile,
streamInfo.Container,
streamInfo.TargetVideoCodec.FirstOrDefault(),
streamInfo.TargetAudioCodec.FirstOrDefault(),
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 0512adf10..703f8d20d 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -607,12 +607,8 @@ namespace Emby.Server.Implementations
ServiceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
- // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
- ServiceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>));
-
- // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
- ServiceCollection.AddTransient(provider => new Lazy<EncodingHelper>(provider.GetRequiredService<EncodingHelper>));
ServiceCollection.AddSingleton<IMediaEncoder, MediaBrowser.MediaEncoding.Encoder.MediaEncoder>();
+ ServiceCollection.AddSingleton<EncodingHelper>();
// TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required
ServiceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>));
@@ -677,8 +673,6 @@ namespace Emby.Server.Implementations
ServiceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
- ServiceCollection.AddSingleton<EncodingHelper>();
-
ServiceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
ServiceCollection.AddSingleton<TranscodingJobHelper>();
diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs
index e984afdba..1b85a9d4b 100644
--- a/Emby.Server.Implementations/Collections/CollectionManager.cs
+++ b/Emby.Server.Implementations/Collections/CollectionManager.cs
@@ -121,7 +121,7 @@ namespace Emby.Server.Implementations.Collections
private IEnumerable<BoxSet> GetCollections(User user)
{
- var folder = GetCollectionsFolder(false).Result;
+ var folder = GetCollectionsFolder(false).GetAwaiter().GetResult();
return folder == null
? Enumerable.Empty<BoxSet>()
@@ -316,11 +316,11 @@ namespace Emby.Server.Implementations.Collections
{
var results = new Dictionary<Guid, BaseItem>();
- var allBoxsets = GetCollections(user).ToList();
+ var allBoxSets = GetCollections(user).ToList();
foreach (var item in items)
{
- if (!(item is ISupportsBoxSetGrouping))
+ if (item is not ISupportsBoxSetGrouping)
{
results[item.Id] = item;
}
@@ -328,34 +328,45 @@ namespace Emby.Server.Implementations.Collections
{
var itemId = item.Id;
- var currentBoxSets = allBoxsets
- .Where(i => i.ContainsLinkedChildByItemId(itemId))
- .ToList();
-
- if (currentBoxSets.Count > 0)
+ var itemIsInBoxSet = false;
+ foreach (var boxSet in allBoxSets)
{
- foreach (var boxset in currentBoxSets)
+ if (!boxSet.ContainsLinkedChildByItemId(itemId))
{
- results[boxset.Id] = boxset;
+ continue;
}
+
+ itemIsInBoxSet = true;
+
+ results.TryAdd(boxSet.Id, boxSet);
+ }
+
+ // skip any item that is in a box set
+ if (itemIsInBoxSet)
+ {
+ continue;
}
- else
+
+ var alreadyInResults = false;
+ // this is kind of a performance hack because only Video has alternate versions that should be in a box set?
+ if (item is Video video)
{
- var alreadyInResults = false;
- foreach (var child in item.GetMediaSources(true))
+ foreach (var childId in video.GetLocalAlternateVersionIds())
{
- if (Guid.TryParse(child.Id, out var id) && results.ContainsKey(id))
+ if (!results.ContainsKey(childId))
{
- alreadyInResults = true;
- break;
+ continue;
}
- }
- if (!alreadyInResults)
- {
- results[item.Id] = item;
+ alreadyInResults = true;
+ break;
}
}
+
+ if (!alreadyInResults)
+ {
+ results[itemId] = item;
+ }
}
}
diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs
index e8caea196..827e3c64b 100644
--- a/Emby.Server.Implementations/Library/UserDataManager.cs
+++ b/Emby.Server.Implementations/Library/UserDataManager.cs
@@ -248,15 +248,15 @@ namespace Emby.Server.Implementations.Library
}
else if (positionTicks > 0 && hasRuntime && item is AudioBook)
{
- var minIn = TimeSpan.FromTicks(positionTicks).TotalMinutes;
- var minOut = TimeSpan.FromTicks(runtimeTicks - positionTicks).TotalMinutes;
+ var playbackPositionInMinutes = TimeSpan.FromTicks(positionTicks).TotalMinutes;
+ var remainingTimeInMinutes = TimeSpan.FromTicks(runtimeTicks - positionTicks).TotalMinutes;
- if (minIn > _config.Configuration.MinAudiobookResume)
+ if (playbackPositionInMinutes < _config.Configuration.MinAudiobookResume)
{
// ignore progress during the beginning
positionTicks = 0;
}
- else if (minOut < _config.Configuration.MaxAudiobookResume || positionTicks >= runtimeTicks)
+ else if (remainingTimeInMinutes < _config.Configuration.MaxAudiobookResume || positionTicks >= runtimeTicks)
{
// mark as completed close to the end
positionTicks = 0;
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 10e28c33a..6f21ec31e 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -1485,7 +1485,7 @@ namespace Emby.Server.Implementations.Session
user = await _userManager.AuthenticateUser(
request.Username,
request.Password,
- request.PasswordSha1,
+ null,
request.RemoteEndPoint,
true).ConfigureAwait(false);
}
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index c4e75fe85..b4154b361 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -52,8 +52,6 @@ namespace Jellyfin.Api.Controllers
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder;
private readonly IFileSystem _fileSystem;
- private readonly ISubtitleEncoder _subtitleEncoder;
- private readonly IConfiguration _configuration;
private readonly IDeviceManager _deviceManager;
private readonly TranscodingJobHelper _transcodingJobHelper;
private readonly ILogger<DynamicHlsController> _logger;
@@ -72,12 +70,11 @@ namespace Jellyfin.Api.Controllers
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
- /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> class.</param>
/// <param name="logger">Instance of the <see cref="ILogger{DynamicHlsController}"/> interface.</param>
/// <param name="dynamicHlsHelper">Instance of <see cref="DynamicHlsHelper"/>.</param>
+ /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
public DynamicHlsController(
ILibraryManager libraryManager,
IUserManager userManager,
@@ -87,15 +84,12 @@ namespace Jellyfin.Api.Controllers
IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder,
IFileSystem fileSystem,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration,
IDeviceManager deviceManager,
TranscodingJobHelper transcodingJobHelper,
ILogger<DynamicHlsController> logger,
- DynamicHlsHelper dynamicHlsHelper)
+ DynamicHlsHelper dynamicHlsHelper,
+ EncodingHelper encodingHelper)
{
- _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration);
-
_libraryManager = libraryManager;
_userManager = userManager;
_dlnaManager = dlnaManager;
@@ -104,12 +98,12 @@ namespace Jellyfin.Api.Controllers
_serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder;
_fileSystem = fileSystem;
- _subtitleEncoder = subtitleEncoder;
- _configuration = configuration;
_deviceManager = deviceManager;
_transcodingJobHelper = transcodingJobHelper;
_logger = logger;
_dynamicHlsHelper = dynamicHlsHelper;
+ _encodingHelper = encodingHelper;
+
_encodingOptions = serverConfigurationManager.GetEncodingOptions();
}
@@ -1126,9 +1120,7 @@ namespace Jellyfin.Api.Controllers
_libraryManager,
_serverConfigurationManager,
_mediaEncoder,
- _fileSystem,
- _subtitleEncoder,
- _configuration,
+ _encodingHelper,
_dlnaManager,
_deviceManager,
_transcodingJobHelper,
@@ -1211,9 +1203,7 @@ namespace Jellyfin.Api.Controllers
_libraryManager,
_serverConfigurationManager,
_mediaEncoder,
- _fileSystem,
- _subtitleEncoder,
- _configuration,
+ _encodingHelper,
_dlnaManager,
_deviceManager,
_transcodingJobHelper,
diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs
index 4d788ad7d..d0a2358ae 100644
--- a/Jellyfin.Api/Controllers/MoviesController.cs
+++ b/Jellyfin.Api/Controllers/MoviesController.cs
@@ -89,7 +89,7 @@ namespace Jellyfin.Api.Controllers
// nameof(LiveTvProgram)
},
// IsMovie = true
- OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.Random, SortOrder.Descending) },
Limit = 7,
ParentId = parentIdGuid,
Recursive = true,
@@ -110,7 +110,7 @@ namespace Jellyfin.Api.Controllers
{
IncludeItemTypes = itemTypes.ToArray(),
IsMovie = true,
- OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) },
Limit = 10,
IsFavoriteOrLiked = true,
ExcludeItemIds = recentlyPlayedMovies.Select(i => i.Id).ToArray(),
@@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers
DtoOptions = dtoOptions
});
- var mostRecentMovies = recentlyPlayedMovies.Take(6).ToList();
+ var mostRecentMovies = recentlyPlayedMovies.GetRange(0, Math.Min(recentlyPlayedMovies.Count, 6));
// Get recently played directors
var recentDirectors = GetDirectors(mostRecentMovies)
.ToList();
@@ -191,7 +191,8 @@ namespace Jellyfin.Api.Controllers
foreach (var name in names)
{
- var items = _libraryManager.GetItemList(new InternalItemsQuery(user)
+ var items = _libraryManager.GetItemList(
+ new InternalItemsQuery(user)
{
Person = name,
// Account for duplicates by imdb id, since the database doesn't support this yet
diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs
index a55f13e66..a811a29c3 100644
--- a/Jellyfin.Api/Controllers/SuggestionsController.cs
+++ b/Jellyfin.Api/Controllers/SuggestionsController.cs
@@ -69,7 +69,7 @@ namespace Jellyfin.Api.Controllers
var dtoOptions = new DtoOptions().AddClientFields(Request);
var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
{
- OrderBy = new[] { ItemSortBy.Random }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.Random, SortOrder.Descending) },
MediaTypes = mediaType,
IncludeItemTypes = type,
IsVirtualItem = false,
diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs
index e1c67f830..59400db2a 100644
--- a/Jellyfin.Api/Controllers/TvShowsController.cs
+++ b/Jellyfin.Api/Controllers/TvShowsController.cs
@@ -155,7 +155,7 @@ namespace Jellyfin.Api.Controllers
var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { nameof(Episode) },
- OrderBy = new[] { ItemSortBy.PremiereDate, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.PremiereDate, SortOrder.Ascending), (ItemSortBy.SortName, SortOrder.Ascending) },
MinPremiereDate = minPremiereDate,
StartIndex = startIndex,
Limit = limit,
diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs
index 3c0d2aca1..b13db4baa 100644
--- a/Jellyfin.Api/Controllers/UserController.cs
+++ b/Jellyfin.Api/Controllers/UserController.cs
@@ -177,11 +177,9 @@ namespace Jellyfin.Api.Controllers
return StatusCode(StatusCodes.Status403Forbidden, "Only sha1 password is not allowed.");
}
- // Password should always be null
AuthenticateUserByName request = new AuthenticateUserByName
{
Username = user.Username,
- Password = null,
Pw = pw
};
return await AuthenticateUserByName(request).ConfigureAwait(false);
@@ -208,7 +206,6 @@ namespace Jellyfin.Api.Controllers
DeviceId = auth.DeviceId,
DeviceName = auth.Device,
Password = request.Pw,
- PasswordSha1 = request.Password,
RemoteEndPoint = HttpContext.GetNormalizedRemoteIp().ToString(),
Username = request.Username
}).ConfigureAwait(false);
diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs
index e95410d02..308334b23 100644
--- a/Jellyfin.Api/Controllers/VideoHlsController.cs
+++ b/Jellyfin.Api/Controllers/VideoHlsController.cs
@@ -48,9 +48,6 @@ namespace Jellyfin.Api.Controllers
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder;
- private readonly IFileSystem _fileSystem;
- private readonly ISubtitleEncoder _subtitleEncoder;
- private readonly IConfiguration _configuration;
private readonly IDeviceManager _deviceManager;
private readonly TranscodingJobHelper _transcodingJobHelper;
private readonly ILogger<VideoHlsController> _logger;
@@ -60,9 +57,6 @@ namespace Jellyfin.Api.Controllers
/// Initializes a new instance of the <see cref="VideoHlsController"/> class.
/// </summary>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
- /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
/// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
/// <param name="userManger">Instance of the <see cref="IUserManager"/> interface.</param>
/// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
@@ -72,11 +66,9 @@ namespace Jellyfin.Api.Controllers
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="transcodingJobHelper">The <see cref="TranscodingJobHelper"/> singleton.</param>
/// <param name="logger">Instance of the <see cref="ILogger{VideoHlsController}"/>.</param>
+ /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
public VideoHlsController(
IMediaEncoder mediaEncoder,
- IFileSystem fileSystem,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration,
IDlnaManager dlnaManager,
IUserManager userManger,
IAuthorizationContext authorizationContext,
@@ -85,10 +77,9 @@ namespace Jellyfin.Api.Controllers
IServerConfigurationManager serverConfigurationManager,
IDeviceManager deviceManager,
TranscodingJobHelper transcodingJobHelper,
- ILogger<VideoHlsController> logger)
+ ILogger<VideoHlsController> logger,
+ EncodingHelper encodingHelper)
{
- _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration);
-
_dlnaManager = dlnaManager;
_authContext = authorizationContext;
_userManager = userManger;
@@ -96,12 +87,11 @@ namespace Jellyfin.Api.Controllers
_mediaSourceManager = mediaSourceManager;
_serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder;
- _fileSystem = fileSystem;
- _subtitleEncoder = subtitleEncoder;
- _configuration = configuration;
_deviceManager = deviceManager;
_transcodingJobHelper = transcodingJobHelper;
_logger = logger;
+ _encodingHelper = encodingHelper;
+
_encodingOptions = serverConfigurationManager.GetEncodingOptions();
}
@@ -285,9 +275,7 @@ namespace Jellyfin.Api.Controllers
_libraryManager,
_serverConfigurationManager,
_mediaEncoder,
- _fileSystem,
- _subtitleEncoder,
- _configuration,
+ _encodingHelper,
_dlnaManager,
_deviceManager,
_transcodingJobHelper,
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index 699ca5327..8dbb6aaa5 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -49,12 +49,10 @@ namespace Jellyfin.Api.Controllers
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder;
- private readonly IFileSystem _fileSystem;
- private readonly ISubtitleEncoder _subtitleEncoder;
- private readonly IConfiguration _configuration;
private readonly IDeviceManager _deviceManager;
private readonly TranscodingJobHelper _transcodingJobHelper;
private readonly IHttpClientFactory _httpClientFactory;
+ private readonly EncodingHelper _encodingHelper;
private readonly TranscodingJobType _transcodingJobType = TranscodingJobType.Progressive;
@@ -69,12 +67,10 @@ namespace Jellyfin.Api.Controllers
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
- /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="transcodingJobHelper">Instance of the <see cref="TranscodingJobHelper"/> class.</param>
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
+ /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
public VideosController(
ILibraryManager libraryManager,
IUserManager userManager,
@@ -84,12 +80,10 @@ namespace Jellyfin.Api.Controllers
IMediaSourceManager mediaSourceManager,
IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder,
- IFileSystem fileSystem,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration,
IDeviceManager deviceManager,
TranscodingJobHelper transcodingJobHelper,
- IHttpClientFactory httpClientFactory)
+ IHttpClientFactory httpClientFactory,
+ EncodingHelper encodingHelper)
{
_libraryManager = libraryManager;
_userManager = userManager;
@@ -99,12 +93,10 @@ namespace Jellyfin.Api.Controllers
_mediaSourceManager = mediaSourceManager;
_serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder;
- _fileSystem = fileSystem;
- _subtitleEncoder = subtitleEncoder;
- _configuration = configuration;
_deviceManager = deviceManager;
_transcodingJobHelper = transcodingJobHelper;
_httpClientFactory = httpClientFactory;
+ _encodingHelper = encodingHelper;
}
/// <summary>
@@ -444,9 +436,7 @@ namespace Jellyfin.Api.Controllers
_libraryManager,
_serverConfigurationManager,
_mediaEncoder,
- _fileSystem,
- _subtitleEncoder,
- _configuration,
+ _encodingHelper,
_dlnaManager,
_deviceManager,
_transcodingJobHelper,
@@ -515,8 +505,7 @@ namespace Jellyfin.Api.Controllers
// Need to start ffmpeg (because media can't be returned directly)
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
- var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration);
- var ffmpegCommandLineArguments = encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast");
+ var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast");
return await FileStreamResponseHelpers.GetTranscodedFile(
state,
isHeadRequest,
diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs
index 9c35d1ec1..cf35ee23a 100644
--- a/Jellyfin.Api/Helpers/AudioHelper.cs
+++ b/Jellyfin.Api/Helpers/AudioHelper.cs
@@ -32,13 +32,11 @@ namespace Jellyfin.Api.Helpers
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder;
- private readonly IFileSystem _fileSystem;
- private readonly ISubtitleEncoder _subtitleEncoder;
- private readonly IConfiguration _configuration;
private readonly IDeviceManager _deviceManager;
private readonly TranscodingJobHelper _transcodingJobHelper;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IHttpContextAccessor _httpContextAccessor;
+ private readonly EncodingHelper _encodingHelper;
/// <summary>
/// Initializes a new instance of the <see cref="AudioHelper"/> class.
@@ -50,13 +48,11 @@ namespace Jellyfin.Api.Helpers
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
- /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="transcodingJobHelper">Instance of <see cref="TranscodingJobHelper"/>.</param>
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
/// <param name="httpContextAccessor">Instance of the <see cref="IHttpContextAccessor"/> interface.</param>
+ /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
public AudioHelper(
IDlnaManager dlnaManager,
IAuthorizationContext authContext,
@@ -65,13 +61,11 @@ namespace Jellyfin.Api.Helpers
IMediaSourceManager mediaSourceManager,
IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder,
- IFileSystem fileSystem,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration,
IDeviceManager deviceManager,
TranscodingJobHelper transcodingJobHelper,
IHttpClientFactory httpClientFactory,
- IHttpContextAccessor httpContextAccessor)
+ IHttpContextAccessor httpContextAccessor,
+ EncodingHelper encodingHelper)
{
_dlnaManager = dlnaManager;
_authContext = authContext;
@@ -80,13 +74,11 @@ namespace Jellyfin.Api.Helpers
_mediaSourceManager = mediaSourceManager;
_serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder;
- _fileSystem = fileSystem;
- _subtitleEncoder = subtitleEncoder;
- _configuration = configuration;
_deviceManager = deviceManager;
_transcodingJobHelper = transcodingJobHelper;
_httpClientFactory = httpClientFactory;
_httpContextAccessor = httpContextAccessor;
+ _encodingHelper = encodingHelper;
}
/// <summary>
@@ -116,9 +108,7 @@ namespace Jellyfin.Api.Helpers
_libraryManager,
_serverConfigurationManager,
_mediaEncoder,
- _fileSystem,
- _subtitleEncoder,
- _configuration,
+ _encodingHelper,
_dlnaManager,
_deviceManager,
_transcodingJobHelper,
@@ -187,8 +177,7 @@ namespace Jellyfin.Api.Helpers
// Need to start ffmpeg (because media can't be returned directly)
var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
- var encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration);
- var ffmpegCommandLineArguments = encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
+ var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveAudioFullCommandLine(state, encodingOptions, outputPath);
return await FileStreamResponseHelpers.GetTranscodedFile(
state,
isHeadRequest,
diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
index 1bb504ad1..fcada0e77 100644
--- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
+++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs
@@ -40,14 +40,12 @@ namespace Jellyfin.Api.Helpers
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IServerConfigurationManager _serverConfigurationManager;
private readonly IMediaEncoder _mediaEncoder;
- private readonly IFileSystem _fileSystem;
- private readonly ISubtitleEncoder _subtitleEncoder;
- private readonly IConfiguration _configuration;
private readonly IDeviceManager _deviceManager;
private readonly TranscodingJobHelper _transcodingJobHelper;
private readonly INetworkManager _networkManager;
private readonly ILogger<DynamicHlsHelper> _logger;
private readonly IHttpContextAccessor _httpContextAccessor;
+ private readonly EncodingHelper _encodingHelper;
/// <summary>
/// Initializes a new instance of the <see cref="DynamicHlsHelper"/> class.
@@ -59,14 +57,12 @@ namespace Jellyfin.Api.Helpers
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
- /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="transcodingJobHelper">Instance of <see cref="TranscodingJobHelper"/>.</param>
/// <param name="networkManager">Instance of the <see cref="INetworkManager"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{DynamicHlsHelper}"/> interface.</param>
/// <param name="httpContextAccessor">Instance of the <see cref="IHttpContextAccessor"/> interface.</param>
+ /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
public DynamicHlsHelper(
ILibraryManager libraryManager,
IUserManager userManager,
@@ -75,14 +71,12 @@ namespace Jellyfin.Api.Helpers
IMediaSourceManager mediaSourceManager,
IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder,
- IFileSystem fileSystem,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration,
IDeviceManager deviceManager,
TranscodingJobHelper transcodingJobHelper,
INetworkManager networkManager,
ILogger<DynamicHlsHelper> logger,
- IHttpContextAccessor httpContextAccessor)
+ IHttpContextAccessor httpContextAccessor,
+ EncodingHelper encodingHelper)
{
_libraryManager = libraryManager;
_userManager = userManager;
@@ -91,14 +85,12 @@ namespace Jellyfin.Api.Helpers
_mediaSourceManager = mediaSourceManager;
_serverConfigurationManager = serverConfigurationManager;
_mediaEncoder = mediaEncoder;
- _fileSystem = fileSystem;
- _subtitleEncoder = subtitleEncoder;
- _configuration = configuration;
_deviceManager = deviceManager;
_transcodingJobHelper = transcodingJobHelper;
_networkManager = networkManager;
_logger = logger;
_httpContextAccessor = httpContextAccessor;
+ _encodingHelper = encodingHelper;
}
/// <summary>
@@ -144,9 +136,7 @@ namespace Jellyfin.Api.Helpers
_libraryManager,
_serverConfigurationManager,
_mediaEncoder,
- _fileSystem,
- _subtitleEncoder,
- _configuration,
+ _encodingHelper,
_dlnaManager,
_deviceManager,
_transcodingJobHelper,
@@ -227,9 +217,8 @@ namespace Jellyfin.Api.Helpers
var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main");
sdrVideoUrl += "&AllowVideoStreamCopy=false";
- EncodingHelper encodingHelper = new EncodingHelper(_mediaEncoder, _fileSystem, _subtitleEncoder, _configuration);
- var sdrOutputVideoBitrate = encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0;
- var sdrOutputAudioBitrate = encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0;
+ var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec) ?? 0;
+ var sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream) ?? 0;
var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate;
AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup);
diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs
index e2306aa27..9218cb202 100644
--- a/Jellyfin.Api/Helpers/StreamingHelpers.cs
+++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs
@@ -41,9 +41,7 @@ namespace Jellyfin.Api.Helpers
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="mediaEncoder">Instance of the <see cref="IMediaEncoder"/> interface.</param>
- /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
- /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
- /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
+ /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
/// <param name="dlnaManager">Instance of the <see cref="IDlnaManager"/> interface.</param>
/// <param name="deviceManager">Instance of the <see cref="IDeviceManager"/> interface.</param>
/// <param name="transcodingJobHelper">Initialized <see cref="TranscodingJobHelper"/>.</param>
@@ -59,16 +57,13 @@ namespace Jellyfin.Api.Helpers
ILibraryManager libraryManager,
IServerConfigurationManager serverConfigurationManager,
IMediaEncoder mediaEncoder,
- IFileSystem fileSystem,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration,
+ EncodingHelper encodingHelper,
IDlnaManager dlnaManager,
IDeviceManager deviceManager,
TranscodingJobHelper transcodingJobHelper,
TranscodingJobType transcodingJobType,
CancellationToken cancellationToken)
{
- EncodingHelper encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration);
// Parse the DLNA time seek header
if (!streamingRequest.StartTimeTicks.HasValue)
{
@@ -306,7 +301,8 @@ namespace Jellyfin.Api.Helpers
if (!state.IsVideoRequest)
{
- responseHeaders.Add("contentFeatures.dlna.org", new ContentFeatureBuilder(profile).BuildAudioHeader(
+ responseHeaders.Add("contentFeatures.dlna.org", ContentFeatureBuilder.BuildAudioHeader(
+ profile,
state.OutputContainer,
audioCodec,
state.OutputAudioBitrate,
@@ -323,7 +319,7 @@ namespace Jellyfin.Api.Helpers
responseHeaders.Add(
"contentFeatures.dlna.org",
- new ContentFeatureBuilder(profile).BuildVideoHeader(state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty);
+ ContentFeatureBuilder.BuildVideoHeader(profile, state.OutputContainer, videoCodec, audioCodec, state.OutputWidth, state.OutputHeight, state.TargetVideoBitDepth, state.OutputVideoBitrate, state.TargetTimestamp, isStaticallyStreamed, state.RunTimeTicks, state.TargetVideoProfile, state.TargetVideoLevel, state.TargetFramerate, state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, state.IsTargetInterlaced, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, state.TargetVideoCodecTag, state.IsTargetAVC).FirstOrDefault() ?? string.Empty);
}
}
diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
index 240d132b1..0879cbd18 100644
--- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
+++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
@@ -62,8 +62,7 @@ namespace Jellyfin.Api.Helpers
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="sessionManager">Instance of the <see cref="ISessionManager"/> interface.</param>
/// <param name="authorizationContext">Instance of the <see cref="IAuthorizationContext"/> interface.</param>
- /// <param name="subtitleEncoder">Instance of the <see cref="ISubtitleEncoder"/> interface.</param>
- /// <param name="configuration">Instance of the <see cref="IConfiguration"/> interface.</param>
+ /// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
public TranscodingJobHelper(
ILogger<TranscodingJobHelper> logger,
@@ -73,8 +72,7 @@ namespace Jellyfin.Api.Helpers
IServerConfigurationManager serverConfigurationManager,
ISessionManager sessionManager,
IAuthorizationContext authorizationContext,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration,
+ EncodingHelper encodingHelper,
ILoggerFactory loggerFactory)
{
_logger = logger;
@@ -84,8 +82,8 @@ namespace Jellyfin.Api.Helpers
_serverConfigurationManager = serverConfigurationManager;
_sessionManager = sessionManager;
_authorizationContext = authorizationContext;
+ _encodingHelper = encodingHelper;
_loggerFactory = loggerFactory;
- _encodingHelper = new EncodingHelper(mediaEncoder, fileSystem, subtitleEncoder, configuration);
DeleteEncodedMediaCache();
diff --git a/Jellyfin.Api/Models/UserDtos/AuthenticateUserByName.cs b/Jellyfin.Api/Models/UserDtos/AuthenticateUserByName.cs
index 393627435..41f7b169e 100644
--- a/Jellyfin.Api/Models/UserDtos/AuthenticateUserByName.cs
+++ b/Jellyfin.Api/Models/UserDtos/AuthenticateUserByName.cs
@@ -1,4 +1,6 @@
-namespace Jellyfin.Api.Models.UserDtos
+using System;
+
+namespace Jellyfin.Api.Models.UserDtos
{
/// <summary>
/// The authenticate user by name request body.
@@ -18,6 +20,7 @@
/// <summary>
/// Gets or sets the sha1-hashed password.
/// </summary>
+ [Obsolete("Send password using pw field")]
public string? Password { get; set; }
}
}
diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs
index e56e61092..f75139884 100644
--- a/Jellyfin.Server/Startup.cs
+++ b/Jellyfin.Server/Startup.cs
@@ -1,5 +1,9 @@
+using System;
+using System.Net;
+using System.Net.Http;
using System.Net.Http.Headers;
using System.Net.Mime;
+using System.Text;
using Jellyfin.Networking.Configuration;
using Jellyfin.Server.Extensions;
using Jellyfin.Server.Implementations;
@@ -67,6 +71,12 @@ namespace Jellyfin.Server
var acceptJsonHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json, 1.0);
var acceptXmlHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Xml, 0.9);
var acceptAnyHeader = new MediaTypeWithQualityHeaderValue("*/*", 0.8);
+ Func<IServiceProvider, HttpMessageHandler> defaultHttpClientHandlerDelegate = (_) => new SocketsHttpHandler()
+ {
+ AutomaticDecompression = DecompressionMethods.All,
+ RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8
+ };
+
services
.AddHttpClient(NamedClient.Default, c =>
{
@@ -75,7 +85,7 @@ namespace Jellyfin.Server
c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
})
- .ConfigurePrimaryHttpMessageHandler(x => new DefaultHttpClientHandler());
+ .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate);
services.AddHttpClient(NamedClient.MusicBrainz, c =>
{
@@ -84,7 +94,7 @@ namespace Jellyfin.Server
c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader);
c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader);
})
- .ConfigurePrimaryHttpMessageHandler(x => new DefaultHttpClientHandler());
+ .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate);
services.AddHealthChecks()
.AddDbContextCheck<JellyfinDb>();
diff --git a/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs b/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs
deleted file mode 100644
index f1c5f2477..000000000
--- a/MediaBrowser.Common/Net/DefaultHttpClientHandler.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Net;
-using System.Net.Http;
-
-namespace MediaBrowser.Common.Net
-{
- /// <summary>
- /// Default http client handler.
- /// </summary>
- public class DefaultHttpClientHandler : HttpClientHandler
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="DefaultHttpClientHandler"/> class.
- /// </summary>
- public DefaultHttpClientHandler()
- {
- AutomaticDecompression = DecompressionMethods.All;
- }
- }
-}
diff --git a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs
index c65477d39..157ed8332 100644
--- a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs
+++ b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs
@@ -1,5 +1,7 @@
+#nullable enable
#pragma warning disable CS1591
+using System;
using System.Linq;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
@@ -64,9 +66,19 @@ namespace MediaBrowser.Controller.Entities
/// <param name="source">The source object.</param>
/// <param name="dest">The destination object.</param>
public static void DeepCopy<T, TU>(this T source, TU dest)
- where T : BaseItem
- where TU : BaseItem
+ where T : BaseItem
+ where TU : BaseItem
{
+ if (source == null)
+ {
+ throw new ArgumentNullException(nameof(source));
+ }
+
+ if (dest == null)
+ {
+ throw new ArgumentNullException(nameof(dest));
+ }
+
var destProps = typeof(TU).GetProperties().Where(x => x.CanWrite).ToList();
foreach (var sourceProp in typeof(T).GetProperties())
@@ -99,8 +111,8 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <param name="source">The source object.</param>
public static TU DeepCopy<T, TU>(this T source)
- where T : BaseItem
- where TU : BaseItem, new()
+ where T : BaseItem
+ where TU : BaseItem, new()
{
var dest = new TU();
source.DeepCopy(dest);
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index bdca5c0ee..d45f8758c 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -1433,9 +1433,14 @@ namespace MediaBrowser.Controller.Entities
var linkedChildren = LinkedChildren;
foreach (var i in linkedChildren)
{
- if (i.ItemId.HasValue && i.ItemId.Value == itemId)
+ if (i.ItemId.HasValue)
{
- return true;
+ if (i.ItemId.Value == itemId)
+ {
+ return true;
+ }
+
+ continue;
}
var child = GetLinkedChild(i);
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index dc12fbbea..70663ef47 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -99,7 +99,15 @@ namespace MediaBrowser.Controller.Entities.TV
take--;
}
- list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
+ var newList = seriesUserDataKeys.GetRange(0, take);
+ var suffix = ParentIndexNumber.Value.ToString("000", CultureInfo.InvariantCulture) + IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
+ for (int i = 0; i < take; i++)
+ {
+ newList[i] = newList[i] + suffix;
+ }
+
+ newList.AddRange(list);
+ list = newList;
}
return list;
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs
index 93bdd6e70..5b8168d3d 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Entities;
@@ -56,7 +57,15 @@ namespace MediaBrowser.Controller.Entities.TV
var series = Series;
if (series != null)
{
- list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000")));
+ var newList = series.GetUserDataKeys();
+ var suffix = (IndexNumber ?? 0).ToString("000", CultureInfo.InvariantCulture);
+ for (int i = 0; i < newList.Count; i++)
+ {
+ newList[i] = newList[i] + suffix;
+ }
+
+ newList.AddRange(list);
+ list = newList;
}
return list;
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index a410c1b66..9f9a2ad50 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -169,14 +169,12 @@ namespace MediaBrowser.Controller.Entities.TV
{
var list = base.GetUserDataKeys();
- var key = this.GetProviderId(MetadataProvider.Imdb);
- if (!string.IsNullOrEmpty(key))
+ if (this.TryGetProviderId(MetadataProvider.Imdb, out var key))
{
list.Insert(0, key);
}
- key = this.GetProviderId(MetadataProvider.Tvdb);
- if (!string.IsNullOrEmpty(key))
+ if (this.TryGetProviderId(MetadataProvider.Tvdb, out key))
{
list.Insert(0, key);
}
@@ -208,7 +206,7 @@ namespace MediaBrowser.Controller.Entities.TV
query.AncestorWithPresentationUniqueKey = null;
query.SeriesPresentationUniqueKey = seriesKey;
query.IncludeItemTypes = new[] { nameof(Season) };
- query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray();
+ query.OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) };
if (user != null && !user.DisplayMissingEpisodes)
{
@@ -228,7 +226,7 @@ namespace MediaBrowser.Controller.Entities.TV
query.SeriesPresentationUniqueKey = seriesKey;
if (query.OrderBy.Count == 0)
{
- query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray();
+ query.OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) };
}
if (query.IncludeItemTypes.Length == 0)
@@ -254,7 +252,7 @@ namespace MediaBrowser.Controller.Entities.TV
AncestorWithPresentationUniqueKey = null,
SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { nameof(Episode), nameof(Season) },
- OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
DtoOptions = options
};
@@ -365,7 +363,7 @@ namespace MediaBrowser.Controller.Entities.TV
AncestorWithPresentationUniqueKey = queryFromSeries ? null : seriesKey,
SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null,
IncludeItemTypes = new[] { nameof(Episode) },
- OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
DtoOptions = options
};
if (user != null)
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 4e33a6bbd..78a64d8c9 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -217,8 +217,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, InternalItemsQuery query)
{
- query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray();
-
+ query.OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Descending) };
query.Recursive = true;
query.Parent = parent;
query.SetUser(user);
@@ -230,7 +229,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query)
{
- query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray();
+ query.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Descending) };
query.IsResumable = true;
query.Recursive = true;
query.Parent = parent;
@@ -327,8 +326,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
{
- query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray();
-
+ query.OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Descending) };
query.Recursive = true;
query.Parent = parent;
query.SetUser(user);
@@ -356,7 +354,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetTvResume(Folder parent, User user, InternalItemsQuery query)
{
- query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray();
+ query.OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Descending) };
query.IsResumable = true;
query.Recursive = true;
query.Parent = parent;
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
index 1379efacb..2b5364775 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs
@@ -25,9 +25,7 @@ namespace MediaBrowser.Controller.MediaEncoding
private static readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IMediaEncoder _mediaEncoder;
- private readonly IFileSystem _fileSystem;
private readonly ISubtitleEncoder _subtitleEncoder;
- private readonly IConfiguration _configuration;
private static readonly string[] _videoProfiles = new[]
{
@@ -42,14 +40,10 @@ namespace MediaBrowser.Controller.MediaEncoding
public EncodingHelper(
IMediaEncoder mediaEncoder,
- IFileSystem fileSystem,
- ISubtitleEncoder subtitleEncoder,
- IConfiguration configuration)
+ ISubtitleEncoder subtitleEncoder)
{
_mediaEncoder = mediaEncoder;
- _fileSystem = fileSystem;
_subtitleEncoder = subtitleEncoder;
- _configuration = configuration;
}
public string GetH264Encoder(EncodingJobInfo state, EncodingOptions encodingOptions)
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index a5b7363fb..c9c168c4c 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -163,7 +163,7 @@ namespace MediaBrowser.Controller.Playlists
Recursive = true,
IncludeItemTypes = new[] { nameof(Audio) },
GenreIds = new[] { musicGenre.Id },
- OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.AlbumArtist, SortOrder.Ascending), (ItemSortBy.Album, SortOrder.Ascending), (ItemSortBy.SortName, SortOrder.Ascending) },
DtoOptions = options
});
}
@@ -175,7 +175,7 @@ namespace MediaBrowser.Controller.Playlists
Recursive = true,
IncludeItemTypes = new[] { nameof(Audio) },
ArtistIds = new[] { musicArtist.Id },
- OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.AlbumArtist, SortOrder.Ascending), (ItemSortBy.Album, SortOrder.Ascending), (ItemSortBy.SortName, SortOrder.Ascending) },
DtoOptions = options
});
}
diff --git a/MediaBrowser.Controller/Session/AuthenticationRequest.cs b/MediaBrowser.Controller/Session/AuthenticationRequest.cs
index cc321fd22..8c3ac58f2 100644
--- a/MediaBrowser.Controller/Session/AuthenticationRequest.cs
+++ b/MediaBrowser.Controller/Session/AuthenticationRequest.cs
@@ -12,6 +12,7 @@ namespace MediaBrowser.Controller.Session
public string Password { get; set; }
+ [Obsolete("Send full password in Password field")]
public string PasswordSha1 { get; set; }
public string App { get; set; }
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index 36bf77c84..62c0c0bb1 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -52,7 +52,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
private readonly IServerConfigurationManager _configurationManager;
private readonly IFileSystem _fileSystem;
private readonly ILocalizationManager _localization;
- private readonly Lazy<EncodingHelper> _encodingHelperFactory;
private readonly string _startupOptionFFmpegPath;
private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2);
@@ -76,14 +75,12 @@ namespace MediaBrowser.MediaEncoding.Encoder
IServerConfigurationManager configurationManager,
IFileSystem fileSystem,
ILocalizationManager localization,
- Lazy<EncodingHelper> encodingHelperFactory,
IConfiguration config)
{
_logger = logger;
_configurationManager = configurationManager;
_fileSystem = fileSystem;
_localization = localization;
- _encodingHelperFactory = encodingHelperFactory;
_startupOptionFFmpegPath = config.GetValue<string>(Controller.Extensions.ConfigurationExtensions.FfmpegPathKey) ?? string.Empty;
_jsonSerializerOptions = JsonDefaults.Options;
}
diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
index ec106f105..600a44157 100644
--- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
+++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs
@@ -10,14 +10,8 @@ namespace MediaBrowser.Model.Dlna
{
public class ContentFeatureBuilder
{
- private readonly DeviceProfile _profile;
-
- public ContentFeatureBuilder(DeviceProfile profile)
- {
- _profile = profile;
- }
-
- public string BuildImageHeader(
+ public static string BuildImageHeader(
+ DeviceProfile profile,
string container,
int? width,
int? height,
@@ -38,27 +32,31 @@ namespace MediaBrowser.Model.Dlna
";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));
- ResponseProfile mediaProfile = _profile.GetImageMediaProfile(
- container,
- width,
- height);
-
if (string.IsNullOrEmpty(orgPn))
{
+ ResponseProfile mediaProfile = profile.GetImageMediaProfile(
+ container,
+ width,
+ height);
+
orgPn = mediaProfile?.OrgPn;
+
+ if (string.IsNullOrEmpty(orgPn))
+ {
+ orgPn = GetImageOrgPnValue(container, width, height);
+ }
}
if (string.IsNullOrEmpty(orgPn))
{
- orgPn = GetImageOrgPnValue(container, width, height);
+ return orgOp.TrimStart(';') + orgCi + dlnaflags;
}
- string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
-
- return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
+ return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags;
}
- public string BuildAudioHeader(
+ public static string BuildAudioHeader(
+ DeviceProfile profile,
string container,
string audioCodec,
int? audioBitrate,
@@ -94,7 +92,7 @@ namespace MediaBrowser.Model.Dlna
";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));
- ResponseProfile mediaProfile = _profile.GetAudioMediaProfile(
+ ResponseProfile mediaProfile = profile.GetAudioMediaProfile(
container,
audioCodec,
audioChannels,
@@ -109,12 +107,16 @@ namespace MediaBrowser.Model.Dlna
orgPn = GetAudioOrgPnValue(container, audioBitrate, audioSampleRate, audioChannels);
}
- string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
+ if (string.IsNullOrEmpty(orgPn))
+ {
+ return orgOp.TrimStart(';') + orgCi + dlnaflags;
+ }
- return (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
+ return "DLNA.ORG_PN=" + orgPn + orgOp + orgCi + dlnaflags;
}
- public List<string> BuildVideoHeader(
+ public static List<string> BuildVideoHeader(
+ DeviceProfile profile,
string container,
string videoCodec,
string audioCodec,
@@ -163,7 +165,7 @@ namespace MediaBrowser.Model.Dlna
";DLNA.ORG_FLAGS={0}",
DlnaMaps.FlagsToString(flagValue));
- ResponseProfile mediaProfile = _profile.GetVideoMediaProfile(
+ ResponseProfile mediaProfile = profile.GetVideoMediaProfile(
container,
audioCodec,
videoCodec,
@@ -192,9 +194,9 @@ namespace MediaBrowser.Model.Dlna
}
else
{
- foreach (string s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp))
+ foreach (var s in GetVideoOrgPnValue(container, videoCodec, audioCodec, width, height, timestamp))
{
- orgPnValues.Add(s);
+ orgPnValues.Add(s.ToString());
break;
}
}
@@ -203,20 +205,20 @@ namespace MediaBrowser.Model.Dlna
foreach (string orgPn in orgPnValues)
{
- string contentFeatures = string.IsNullOrEmpty(orgPn) ? string.Empty : "DLNA.ORG_PN=" + orgPn;
-
- var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
-
- contentFeatureList.Add(value);
+ if (string.IsNullOrEmpty(orgPn))
+ {
+ contentFeatureList.Add(orgOp.TrimStart(';') + orgCi + dlnaflags);
+ continue;
+ }
+ else
+ {
+ contentFeatureList.Add("DLNA.ORG_PN=" + orgPn + orgCi + dlnaflags);
+ }
}
if (orgPnValues.Count == 0)
{
- string contentFeatures = string.Empty;
-
- var value = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';');
-
- contentFeatureList.Add(value);
+ contentFeatureList.Add(orgOp.TrimStart(';') + orgCi + dlnaflags);
}
return contentFeatureList;
@@ -224,19 +226,14 @@ namespace MediaBrowser.Model.Dlna
private static string GetImageOrgPnValue(string container, int? width, int? height)
{
- MediaFormatProfile? format = new MediaFormatProfileResolver()
- .ResolveImageFormat(
- container,
- width,
- height);
+ MediaFormatProfile? format = MediaFormatProfileResolver.ResolveImageFormat(container, width, height);
return format.HasValue ? format.Value.ToString() : null;
}
private static string GetAudioOrgPnValue(string container, int? audioBitrate, int? audioSampleRate, int? audioChannels)
{
- MediaFormatProfile? format = new MediaFormatProfileResolver()
- .ResolveAudioFormat(
+ MediaFormatProfile? format = MediaFormatProfileResolver.ResolveAudioFormat(
container,
audioBitrate,
audioSampleRate,
@@ -245,9 +242,9 @@ namespace MediaBrowser.Model.Dlna
return format.HasValue ? format.Value.ToString() : null;
}
- private static string[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
+ private static MediaFormatProfile[] GetVideoOrgPnValue(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestamp)
{
- return new MediaFormatProfileResolver().ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp);
+ return MediaFormatProfileResolver.ResolveVideoFormat(container, videoCodec, audioCodec, width, height, timestamp);
}
}
}
diff --git a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
index f61b8d59e..7ce248509 100644
--- a/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
+++ b/MediaBrowser.Model/Dlna/MediaFormatProfileResolver.cs
@@ -9,16 +9,9 @@ using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Model.Dlna
{
- public class MediaFormatProfileResolver
+ public static class MediaFormatProfileResolver
{
- public string[] ResolveVideoFormat(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
- {
- return ResolveVideoFormatInternal(container, videoCodec, audioCodec, width, height, timestampType)
- .Select(i => i.ToString())
- .ToArray();
- }
-
- private MediaFormatProfile[] ResolveVideoFormatInternal(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
+ public static MediaFormatProfile[] ResolveVideoFormat(string container, string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
{
if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase))
{
@@ -84,7 +77,7 @@ namespace MediaBrowser.Model.Dlna
return Array.Empty<MediaFormatProfile>();
}
- private MediaFormatProfile[] ResolveVideoMPEG2TSFormat(string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
+ private static MediaFormatProfile[] ResolveVideoMPEG2TSFormat(string videoCodec, string audioCodec, int? width, int? height, TransportStreamTimestamp timestampType)
{
string suffix = string.Empty;
@@ -209,12 +202,12 @@ namespace MediaBrowser.Model.Dlna
return Array.Empty<MediaFormatProfile>();
}
- private MediaFormatProfile ValueOf(string value)
+ private static MediaFormatProfile ValueOf(string value)
{
return (MediaFormatProfile)Enum.Parse(typeof(MediaFormatProfile), value, true);
}
- private MediaFormatProfile? ResolveVideoMP4Format(string videoCodec, string audioCodec, int? width, int? height)
+ private static MediaFormatProfile? ResolveVideoMP4Format(string videoCodec, string audioCodec, int? width, int? height)
{
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
@@ -287,7 +280,7 @@ namespace MediaBrowser.Model.Dlna
return null;
}
- private MediaFormatProfile? ResolveVideo3GPFormat(string videoCodec, string audioCodec)
+ private static MediaFormatProfile? ResolveVideo3GPFormat(string videoCodec, string audioCodec)
{
if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase))
{
@@ -317,7 +310,7 @@ namespace MediaBrowser.Model.Dlna
return null;
}
- private MediaFormatProfile? ResolveVideoASFFormat(string videoCodec, string audioCodec, int? width, int? height)
+ private static MediaFormatProfile? ResolveVideoASFFormat(string videoCodec, string audioCodec, int? width, int? height)
{
if (string.Equals(videoCodec, "wmv", StringComparison.OrdinalIgnoreCase) &&
(string.IsNullOrEmpty(audioCodec) || string.Equals(audioCodec, "wma", StringComparison.OrdinalIgnoreCase) || string.Equals(videoCodec, "wmapro", StringComparison.OrdinalIgnoreCase)))
@@ -371,7 +364,7 @@ namespace MediaBrowser.Model.Dlna
return null;
}
- public MediaFormatProfile? ResolveAudioFormat(string container, int? bitrate, int? frequency, int? channels)
+ public static MediaFormatProfile? ResolveAudioFormat(string container, int? bitrate, int? frequency, int? channels)
{
if (string.Equals(container, "asf", StringComparison.OrdinalIgnoreCase))
{
@@ -413,7 +406,7 @@ namespace MediaBrowser.Model.Dlna
return null;
}
- private MediaFormatProfile ResolveAudioASFFormat(int? bitrate)
+ private static MediaFormatProfile ResolveAudioASFFormat(int? bitrate)
{
if (bitrate.HasValue && bitrate.Value <= 193)
{
@@ -423,7 +416,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.WMA_FULL;
}
- private MediaFormatProfile? ResolveAudioLPCMFormat(int? frequency, int? channels)
+ private static MediaFormatProfile? ResolveAudioLPCMFormat(int? frequency, int? channels)
{
if (frequency.HasValue && channels.HasValue)
{
@@ -453,7 +446,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.LPCM16_48_STEREO;
}
- private MediaFormatProfile ResolveAudioMP4Format(int? bitrate)
+ private static MediaFormatProfile ResolveAudioMP4Format(int? bitrate)
{
if (bitrate.HasValue && bitrate.Value <= 320)
{
@@ -463,7 +456,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.AAC_ISO;
}
- private MediaFormatProfile ResolveAudioADTSFormat(int? bitrate)
+ private static MediaFormatProfile ResolveAudioADTSFormat(int? bitrate)
{
if (bitrate.HasValue && bitrate.Value <= 320)
{
@@ -473,7 +466,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.AAC_ADTS;
}
- public MediaFormatProfile? ResolveImageFormat(string container, int? width, int? height)
+ public static MediaFormatProfile? ResolveImageFormat(string container, int? width, int? height)
{
if (string.Equals(container, "jpeg", StringComparison.OrdinalIgnoreCase) ||
string.Equals(container, "jpg", StringComparison.OrdinalIgnoreCase))
@@ -499,7 +492,7 @@ namespace MediaBrowser.Model.Dlna
return null;
}
- private MediaFormatProfile ResolveImageJPGFormat(int? width, int? height)
+ private static MediaFormatProfile ResolveImageJPGFormat(int? width, int? height)
{
if (width.HasValue && height.HasValue)
{
@@ -524,7 +517,7 @@ namespace MediaBrowser.Model.Dlna
return MediaFormatProfile.JPEG_SM;
}
- private MediaFormatProfile ResolveImagePNGFormat(int? width, int? height)
+ private static MediaFormatProfile ResolveImagePNGFormat(int? width, int? height)
{
if (width.HasValue && height.HasValue)
{
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 3bb2c6f0b..08c92e15a 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -1021,26 +1021,26 @@ namespace MediaBrowser.Providers.Manager
// TODO: Need to hunt down the conditions for this happening
_activeRefreshes.AddOrUpdate(
id,
- (_) => throw new Exception(
+ (_) => throw new InvalidOperationException(
string.Format(
CultureInfo.InvariantCulture,
"Cannot update refresh progress of item '{0}' ({1}) because a refresh for this item is not running",
item.GetType().Name,
item.Id.ToString("N", CultureInfo.InvariantCulture))),
- (_, __) => progress);
+ (_, _) => progress);
RefreshProgress?.Invoke(this, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(item, progress)));
}
/// <inheritdoc/>
- public void QueueRefresh(Guid id, MetadataRefreshOptions options, RefreshPriority priority)
+ public void QueueRefresh(Guid itemId, MetadataRefreshOptions options, RefreshPriority priority)
{
if (_disposed)
{
return;
}
- _refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(id, options), (int)priority);
+ _refreshQueue.Enqueue(new Tuple<Guid, MetadataRefreshOptions>(itemId, options), (int)priority);
lock (_refreshQueueLock)
{
@@ -1073,17 +1073,16 @@ namespace MediaBrowser.Providers.Manager
try
{
var item = libraryManager.GetItemById(refreshItem.Item1);
- if (item != null)
+ if (item == null)
{
- // Try to throttle this a little bit.
- await Task.Delay(100, cancellationToken).ConfigureAwait(false);
+ continue;
+ }
- var task = item is MusicArtist artist
- ? RefreshArtist(artist, refreshItem.Item2, cancellationToken)
- : RefreshItem(item, refreshItem.Item2, cancellationToken);
+ var task = item is MusicArtist artist
+ ? RefreshArtist(artist, refreshItem.Item2, cancellationToken)
+ : RefreshItem(item, refreshItem.Item2, cancellationToken);
- await task.ConfigureAwait(false);
- }
+ await task.ConfigureAwait(false);
}
catch (OperationCanceledException)
{
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs
index 3f57c4bc4..bf42ceade 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonImageProvider.cs
@@ -49,37 +49,36 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, CancellationToken cancellationToken)
{
var person = (Person)item;
- var personTmdbId = Convert.ToInt32(person.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture);
- if (personTmdbId > 0)
+ if (!person.TryGetProviderId(MetadataProvider.Tmdb, out var personTmdbId))
{
- var personResult = await _tmdbClientManager.GetPersonAsync(personTmdbId, cancellationToken).ConfigureAwait(false);
- if (personResult?.Images?.Profiles == null)
- {
- return Enumerable.Empty<RemoteImageInfo>();
- }
+ return Enumerable.Empty<RemoteImageInfo>();
+ }
- var remoteImages = new List<RemoteImageInfo>();
- var language = item.GetPreferredMetadataLanguage();
+ var personResult = await _tmdbClientManager.GetPersonAsync(int.Parse(personTmdbId, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(false);
+ if (personResult?.Images?.Profiles == null)
+ {
+ return Enumerable.Empty<RemoteImageInfo>();
+ }
- for (var i = 0; i < personResult.Images.Profiles.Count; i++)
- {
- var image = personResult.Images.Profiles[i];
- remoteImages.Add(new RemoteImageInfo
- {
- ProviderName = Name,
- Type = ImageType.Primary,
- Width = image.Width,
- Height = image.Height,
- Language = TmdbUtils.AdjustImageLanguage(image.Iso_639_1, language),
- Url = _tmdbClientManager.GetProfileUrl(image.FilePath)
- });
- }
+ var remoteImages = new RemoteImageInfo[personResult.Images.Profiles.Count];
+ var language = item.GetPreferredMetadataLanguage();
- return remoteImages.OrderByLanguageDescending(language);
+ for (var i = 0; i < personResult.Images.Profiles.Count; i++)
+ {
+ var image = personResult.Images.Profiles[i];
+ remoteImages[i] = new RemoteImageInfo
+ {
+ ProviderName = Name,
+ Type = ImageType.Primary,
+ Width = image.Width,
+ Height = image.Height,
+ Language = TmdbUtils.AdjustImageLanguage(image.Iso_639_1, language),
+ Url = _tmdbClientManager.GetProfileUrl(image.FilePath)
+ };
}
- return Enumerable.Empty<RemoteImageInfo>();
+ return remoteImages.OrderByLanguageDescending(language);
}
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
index 4384c203e..1757c8267 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
@@ -30,11 +30,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken)
{
- var personTmdbId = Convert.ToInt32(searchInfo.GetProviderId(MetadataProvider.Tmdb), CultureInfo.InvariantCulture);
-
- if (personTmdbId <= 0)
+ if (searchInfo.TryGetProviderId(MetadataProvider.Tmdb, out var personTmdbId))
{
- var personResult = await _tmdbClientManager.GetPersonAsync(personTmdbId, cancellationToken).ConfigureAwait(false);
+ var personResult = await _tmdbClientManager.GetPersonAsync(int.Parse(personTmdbId, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(false);
if (personResult != null)
{
@@ -51,19 +49,15 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
}
result.SetProviderId(MetadataProvider.Tmdb, personResult.Id.ToString(CultureInfo.InvariantCulture));
- result.SetProviderId(MetadataProvider.Imdb, personResult.ExternalIds.ImdbId);
+ if (!string.IsNullOrEmpty(personResult.ExternalIds.ImdbId))
+ {
+ result.SetProviderId(MetadataProvider.Imdb, personResult.ExternalIds.ImdbId);
+ }
return new[] { result };
}
}
- // TODO why? Because of the old rate limit?
- if (searchInfo.IsAutomated)
- {
- // Don't hammer moviedb searching by name
- return Enumerable.Empty<RemoteSearchResult>();
- }
-
var personSearchResult = await _tmdbClientManager.SearchPersonAsync(searchInfo.Name, cancellationToken).ConfigureAwait(false);
var remoteSearchResults = new List<RemoteSearchResult>();
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
index 36e7fe91a..8ec8f6464 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
@@ -121,9 +121,20 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
CommunityRating = Convert.ToSingle(episodeResult.VoteAverage)
};
- if (!string.IsNullOrEmpty(episodeResult.ExternalIds?.TvdbId))
+ var externalIds = episodeResult.ExternalIds;
+ if (!string.IsNullOrEmpty(externalIds?.TvdbId))
{
- item.SetProviderId(MetadataProvider.Tvdb, episodeResult.ExternalIds.TvdbId);
+ item.SetProviderId(MetadataProvider.Tvdb, externalIds.TvdbId);
+ }
+
+ if (!string.IsNullOrEmpty(externalIds?.ImdbId))
+ {
+ item.SetProviderId(MetadataProvider.Imdb, externalIds.ImdbId);
+ }
+
+ if (!string.IsNullOrEmpty(externalIds?.TvrageId))
+ {
+ item.SetProviderId(MetadataProvider.TvRage, externalIds.TvrageId);
}
if (episodeResult.Videos?.Results != null)