aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers')
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs18
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs2
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj2
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioResolver.cs4
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs8
-rw-r--r--MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs58
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs4
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs5
-rw-r--r--MediaBrowser.Providers/TV/SeriesMetadataService.cs57
9 files changed, 117 insertions, 41 deletions
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 6d767914f..5a2936bd8 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -655,8 +655,6 @@ namespace MediaBrowser.Providers.Manager
};
temp.Item.Path = item.Path;
- var userDataList = new List<UserItemData>();
-
// If replacing all metadata, run internet providers first
if (options.ReplaceAllMetadata)
{
@@ -670,7 +668,7 @@ namespace MediaBrowser.Providers.Manager
var hasLocalMetadata = false;
- foreach (var provider in providers.OfType<ILocalMetadataProvider<TItemType>>().ToList())
+ foreach (var provider in providers.OfType<ILocalMetadataProvider<TItemType>>())
{
var providerName = provider.GetType().Name;
Logger.LogDebug("Running {Provider} for {Item}", providerName, logName);
@@ -687,6 +685,11 @@ namespace MediaBrowser.Providers.Manager
{
try
{
+ if (!options.IsReplacingImage(remoteImage.Type))
+ {
+ continue;
+ }
+
await ProviderManager.SaveImage(item, remoteImage.Url, remoteImage.Type, null, cancellationToken).ConfigureAwait(false);
refreshResult.UpdateType |= ItemUpdateType.ImageUpdate;
}
@@ -701,11 +704,6 @@ namespace MediaBrowser.Providers.Manager
refreshResult.UpdateType |= ItemUpdateType.ImageUpdate;
}
- if (localItem.UserDataList != null)
- {
- userDataList.AddRange(localItem.UserDataList);
- }
-
MergeData(localItem, temp, Array.Empty<MetadataField>(), !options.ReplaceAllMetadata, true);
refreshResult.UpdateType |= ItemUpdateType.MetadataImport;
@@ -764,15 +762,11 @@ namespace MediaBrowser.Providers.Manager
}
}
- // var isUnidentified = failedProviderCount > 0 && successfulProviderCount == 0;
-
foreach (var provider in customProviders.Where(i => i is not IPreRefreshProvider))
{
await RunCustomProvider(provider, item, logName, options, refreshResult, cancellationToken).ConfigureAwait(false);
}
- // ImportUserData(item, userDataList, cancellationToken);
-
return refreshResult;
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 01ff473f0..bbb33ddf0 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/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index f31445c06..9864db9ac 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -20,7 +20,7 @@
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
- <PackageReference Include="OptimizedPriorityQueue" Version="5.0.0" />
+ <PackageReference Include="OptimizedPriorityQueue" Version="5.1.0" />
<PackageReference Include="PlaylistsNET" Version="1.2.1" />
<PackageReference Include="TMDbLib" Version="1.9.2" />
</ItemGroup>
diff --git a/MediaBrowser.Providers/MediaInfo/AudioResolver.cs b/MediaBrowser.Providers/MediaInfo/AudioResolver.cs
index 0bdf447ba..17164ee5c 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioResolver.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
+using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -15,16 +16,19 @@ namespace MediaBrowser.Providers.MediaInfo
/// <summary>
/// Initializes a new instance of the <see cref="AudioResolver"/> class for external audio file processing.
/// </summary>
+ /// <param name="logger">The logger.</param>
/// <param name="localizationManager">The localization manager.</param>
/// <param name="mediaEncoder">The media encoder.</param>
/// <param name="fileSystem">The file system.</param>
/// <param name="namingOptions">The <see cref="NamingOptions"/> object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters.</param>
public AudioResolver(
+ ILogger<AudioResolver> logger,
ILocalizationManager localizationManager,
IMediaEncoder mediaEncoder,
IFileSystem fileSystem,
NamingOptions namingOptions)
: base(
+ logger,
localizationManager,
mediaEncoder,
fileSystem,
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index fcd3f28d4..e58c0e281 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -47,7 +47,6 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
public FFProbeProvider(
- ILogger<FFProbeProvider> logger,
IMediaSourceManager mediaSourceManager,
IMediaEncoder mediaEncoder,
IItemRepository itemRepo,
@@ -59,11 +58,12 @@ namespace MediaBrowser.Providers.MediaInfo
IChapterManager chapterManager,
ILibraryManager libraryManager,
IFileSystem fileSystem,
+ ILoggerFactory loggerFactory,
NamingOptions namingOptions)
{
- _logger = logger;
- _audioResolver = new AudioResolver(localization, mediaEncoder, fileSystem, namingOptions);
- _subtitleResolver = new SubtitleResolver(localization, mediaEncoder, fileSystem, namingOptions);
+ _logger = loggerFactory.CreateLogger<FFProbeProvider>();
+ _audioResolver = new AudioResolver(loggerFactory.CreateLogger<AudioResolver>(), localization, mediaEncoder, fileSystem, namingOptions);
+ _subtitleResolver = new SubtitleResolver(loggerFactory.CreateLogger<SubtitleResolver>(), localization, mediaEncoder, fileSystem, namingOptions);
_videoProber = new FFProbeVideoInfo(
_logger,
mediaSourceManager,
diff --git a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs
index 1421d0183..d55cc4491 100644
--- a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs
@@ -15,6 +15,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
+using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -33,6 +34,7 @@ namespace MediaBrowser.Providers.MediaInfo
/// </summary>
private readonly IMediaEncoder _mediaEncoder;
+ private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
/// <summary>
@@ -48,18 +50,21 @@ namespace MediaBrowser.Providers.MediaInfo
/// <summary>
/// Initializes a new instance of the <see cref="MediaInfoResolver"/> class.
/// </summary>
+ /// <param name="logger">The logger.</param>
/// <param name="localizationManager">The localization manager.</param>
/// <param name="mediaEncoder">The media encoder.</param>
/// <param name="fileSystem">The file system.</param>
/// <param name="namingOptions">The <see cref="NamingOptions"/> object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters.</param>
/// <param name="type">The <see cref="DlnaProfileType"/> of the parsed file.</param>
protected MediaInfoResolver(
+ ILogger logger,
ILocalizationManager localizationManager,
IMediaEncoder mediaEncoder,
IFileSystem fileSystem,
NamingOptions namingOptions,
DlnaProfileType type)
{
+ _logger = logger;
_mediaEncoder = mediaEncoder;
_fileSystem = fileSystem;
_namingOptions = namingOptions;
@@ -101,26 +106,44 @@ namespace MediaBrowser.Providers.MediaInfo
{
if (!pathInfo.Path.AsSpan().EndsWith(".strm", StringComparison.OrdinalIgnoreCase))
{
- var mediaInfo = await GetMediaInfo(pathInfo.Path, _type, cancellationToken).ConfigureAwait(false);
-
- if (mediaInfo.MediaStreams.Count == 1)
+ try
{
- MediaStream mediaStream = mediaInfo.MediaStreams[0];
- mediaStream.Index = startIndex++;
- mediaStream.IsDefault = pathInfo.IsDefault || mediaStream.IsDefault;
- mediaStream.IsForced = pathInfo.IsForced || mediaStream.IsForced;
+ var mediaInfo = await GetMediaInfo(pathInfo.Path, _type, cancellationToken).ConfigureAwait(false);
- mediaStreams.Add(MergeMetadata(mediaStream, pathInfo));
- }
- else
- {
- foreach (MediaStream mediaStream in mediaInfo.MediaStreams)
+ if (mediaInfo.MediaStreams.Count == 1)
{
- mediaStream.Index = startIndex++;
+ MediaStream mediaStream = mediaInfo.MediaStreams[0];
- mediaStreams.Add(MergeMetadata(mediaStream, pathInfo));
+ if ((mediaStream.Type == MediaStreamType.Audio && _type == DlnaProfileType.Audio)
+ || (mediaStream.Type == MediaStreamType.Subtitle && _type == DlnaProfileType.Subtitle))
+ {
+ mediaStream.Index = startIndex++;
+ mediaStream.IsDefault = pathInfo.IsDefault || mediaStream.IsDefault;
+ mediaStream.IsForced = pathInfo.IsForced || mediaStream.IsForced;
+
+ mediaStreams.Add(MergeMetadata(mediaStream, pathInfo));
+ }
+ }
+ else
+ {
+ foreach (MediaStream mediaStream in mediaInfo.MediaStreams)
+ {
+ if ((mediaStream.Type == MediaStreamType.Audio && _type == DlnaProfileType.Audio)
+ || (mediaStream.Type == MediaStreamType.Subtitle && _type == DlnaProfileType.Subtitle))
+ {
+ mediaStream.Index = startIndex++;
+
+ mediaStreams.Add(MergeMetadata(mediaStream, pathInfo));
+ }
+ }
}
}
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Error getting external streams from {Path}", pathInfo.Path);
+
+ continue;
+ }
}
}
@@ -222,13 +245,6 @@ namespace MediaBrowser.Providers.MediaInfo
mediaStream.Title = string.IsNullOrEmpty(mediaStream.Title) ? (string.IsNullOrEmpty(pathInfo.Title) ? null : pathInfo.Title) : mediaStream.Title;
mediaStream.Language = string.IsNullOrEmpty(mediaStream.Language) ? (string.IsNullOrEmpty(pathInfo.Language) ? null : pathInfo.Language) : mediaStream.Language;
- mediaStream.Type = _type switch
- {
- DlnaProfileType.Audio => MediaStreamType.Audio,
- DlnaProfileType.Subtitle => MediaStreamType.Subtitle,
- _ => mediaStream.Type
- };
-
return mediaStream;
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
index 4b9ba944a..70e5bd783 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO;
+using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -15,16 +16,19 @@ namespace MediaBrowser.Providers.MediaInfo
/// <summary>
/// Initializes a new instance of the <see cref="SubtitleResolver"/> class for external subtitle file processing.
/// </summary>
+ /// <param name="logger">The logger.</param>
/// <param name="localizationManager">The localization manager.</param>
/// <param name="mediaEncoder">The media encoder.</param>
/// <param name="fileSystem">The file system.</param>
/// <param name="namingOptions">The <see cref="NamingOptions"/> object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters.</param>
public SubtitleResolver(
+ ILogger<SubtitleResolver> logger,
ILocalizationManager localizationManager,
IMediaEncoder mediaEncoder,
IFileSystem fileSystem,
NamingOptions namingOptions)
: base(
+ logger,
localizationManager,
mediaEncoder,
fileSystem,
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
index 5ae5ff3be..915fb97fd 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
@@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Music
/// <summary>
/// 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.
/// </summary>
private readonly long _musicBrainzQueryIntervalMs;
@@ -465,7 +465,8 @@ namespace MediaBrowser.Providers.Music
ValidationType = ValidationType.None,
CheckCharacters = false,
IgnoreProcessingInstructions = true,
- IgnoreComments = true
+ IgnoreComments = true,
+ Async = true
};
using var reader = XmlReader.Create(oReader, settings);
diff --git a/MediaBrowser.Providers/TV/SeriesMetadataService.cs b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
index f49492f33..c09b6d813 100644
--- a/MediaBrowser.Providers/TV/SeriesMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeriesMetadataService.cs
@@ -8,6 +8,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
@@ -40,6 +41,7 @@ namespace MediaBrowser.Providers.TV
{
await base.AfterMetadataRefresh(item, refreshOptions, cancellationToken).ConfigureAwait(false);
+ RemoveObsoleteEpisodes(item);
RemoveObsoleteSeasons(item);
await FillInMissingSeasonsAsync(item, cancellationToken).ConfigureAwait(false);
}
@@ -121,6 +123,61 @@ namespace MediaBrowser.Providers.TV
}
}
+ private void RemoveObsoleteEpisodes(Series series)
+ {
+ var episodes = series.GetEpisodes(null, new DtoOptions()).OfType<Episode>().ToList();
+ var numberOfEpisodes = episodes.Count;
+ // TODO: O(n^2), but can it be done faster without overcomplicating it?
+ for (var i = 0; i < numberOfEpisodes; i++)
+ {
+ var currentEpisode = episodes[i];
+ // The outer loop only examines virtual episodes
+ if (!currentEpisode.IsVirtualItem)
+ {
+ continue;
+ }
+
+ // Virtual episodes without an episode number are practically orphaned and should be deleted
+ if (!currentEpisode.IndexNumber.HasValue)
+ {
+ DeleteEpisode(currentEpisode);
+ continue;
+ }
+
+ for (var j = i + 1; j < numberOfEpisodes; j++)
+ {
+ var comparisonEpisode = episodes[j];
+ // The inner loop is only for "physical" episodes
+ if (comparisonEpisode.IsVirtualItem
+ || currentEpisode.ParentIndexNumber != comparisonEpisode.ParentIndexNumber
+ || !comparisonEpisode.ContainsEpisodeNumber(currentEpisode.IndexNumber.Value))
+ {
+ continue;
+ }
+
+ DeleteEpisode(currentEpisode);
+ break;
+ }
+ }
+ }
+
+ private void DeleteEpisode(Episode episode)
+ {
+ Logger.LogInformation(
+ "Removing virtual episode S{SeasonNumber}E{EpisodeNumber} in series {SeriesName}",
+ episode.ParentIndexNumber,
+ episode.IndexNumber,
+ episode.SeriesName);
+
+ LibraryManager.DeleteItem(
+ episode,
+ new DeleteOptions
+ {
+ DeleteFileLocation = true
+ },
+ false);
+ }
+
/// <summary>
/// Creates seasons for all episodes that aren't in a season folder.
/// If no season number can be determined, a dummy season will be created.