diff options
Diffstat (limited to 'MediaBrowser.Providers')
21 files changed, 157 insertions, 127 deletions
diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs index 32ab7716f..b51ab4c08 100644 --- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs +++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.Providers.BoxSets protected override bool EnableUpdatingPremiereDateFromChildren => true; /// <inheritdoc /> - protected override IList<BaseItem> GetChildrenForMetadataUpdates(BoxSet item) + protected override IReadOnlyList<BaseItem> GetChildrenForMetadataUpdates(BoxSet item) { return item.GetLinkedChildren(); } diff --git a/MediaBrowser.Providers/Chapters/ChapterManager.cs b/MediaBrowser.Providers/Chapters/ChapterManager.cs deleted file mode 100644 index 3cbfe7d4d..000000000 --- a/MediaBrowser.Providers/Chapters/ChapterManager.cs +++ /dev/null @@ -1,26 +0,0 @@ -#pragma warning disable CS1591 - -using System; -using System.Collections.Generic; -using MediaBrowser.Controller.Chapters; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Entities; - -namespace MediaBrowser.Providers.Chapters -{ - public class ChapterManager : IChapterManager - { - private readonly IItemRepository _itemRepo; - - public ChapterManager(IItemRepository itemRepo) - { - _itemRepo = itemRepo; - } - - /// <inheritdoc /> - public void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters) - { - _itemRepo.SaveChapters(itemId, chapters); - } - } -} diff --git a/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs b/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs index 89d71e172..73912b579 100644 --- a/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs +++ b/MediaBrowser.Providers/Lyric/LyricScheduledTask.cs @@ -162,7 +162,7 @@ public class LyricScheduledTask : IScheduledTask [ new TaskTriggerInfo { - Type = TaskTriggerInfo.TriggerInterval, + Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks } ]; diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 36a7c2fab..64954818a 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -229,9 +229,7 @@ namespace MediaBrowser.Providers.Manager { var mimeType = MimeTypes.GetMimeType(response.Path); - var stream = AsyncFile.OpenRead(response.Path); - - await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); + await _providerManager.SaveImage(item, response.Path, mimeType, imageType, null, null, cancellationToken).ConfigureAwait(false); } } @@ -387,8 +385,8 @@ namespace MediaBrowser.Providers.Manager item.RemoveImages(images); - // Cleanup old metadata directory for episodes if empty - if (item is Episode) + // Cleanup old metadata directory for episodes if empty, as long as it's not a virtual item + if (item is Episode && !item.IsVirtualItem) { var oldLocalMetadataDirectory = Path.Combine(item.ContainingFolderPath, "metadata"); if (_fileSystem.DirectoryExists(oldLocalMetadataDirectory) && !_fileSystem.GetFiles(oldLocalMetadataDirectory).Any()) diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 7203bf115..778fbc712 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -74,10 +74,11 @@ namespace MediaBrowser.Providers.Manager public virtual async Task<ItemUpdateType> RefreshMetadata(BaseItem item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { var itemOfType = (TItemType)item; - var updateType = ItemUpdateType.None; - var libraryOptions = LibraryManager.GetLibraryOptions(item); + var isFirstRefresh = item.DateLastRefreshed == default; + var hasRefreshedMetadata = true; + var hasRefreshedImages = true; var requiresRefresh = libraryOptions.AutomaticRefreshIntervalDays > 0 && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= libraryOptions.AutomaticRefreshIntervalDays; @@ -131,9 +132,10 @@ namespace MediaBrowser.Providers.Manager People = LibraryManager.GetPeople(item) }; - bool hasRefreshedMetadata = true; - bool hasRefreshedImages = true; - var isFirstRefresh = item.DateLastRefreshed == default; + var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType); + updateType |= beforeSaveResult; + + updateType = await SaveInternal(item, refreshOptions, updateType, isFirstRefresh, requiresRefresh, metadataResult, cancellationToken).ConfigureAwait(false); // Next run metadata providers if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) @@ -188,43 +190,43 @@ namespace MediaBrowser.Providers.Manager } } - var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType); - updateType |= beforeSaveResult; + if (hasRefreshedMetadata && hasRefreshedImages) + { + item.DateLastRefreshed = DateTime.UtcNow; + } + + updateType = await SaveInternal(item, refreshOptions, updateType, isFirstRefresh, requiresRefresh, metadataResult, cancellationToken).ConfigureAwait(false); + + await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false); - // Save if changes were made, or it's never been saved before - if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata || requiresRefresh) + return updateType; + + async Task<ItemUpdateType> SaveInternal(BaseItem item, MetadataRefreshOptions refreshOptions, ItemUpdateType updateType, bool isFirstRefresh, bool requiresRefresh, MetadataResult<TItemType> metadataResult, CancellationToken cancellationToken) { - if (item.IsFileProtocol) + // Save if changes were made, or it's never been saved before + if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata || requiresRefresh) { - var file = TryGetFile(item.Path, refreshOptions.DirectoryService); - if (file is not null) + if (item.IsFileProtocol) { - item.DateModified = file.LastWriteTimeUtc; + var file = TryGetFile(item.Path, refreshOptions.DirectoryService); + if (file is not null) + { + item.DateModified = file.LastWriteTimeUtc; + } } - } - // If any of these properties are set then make sure the updateType is not None, just to force everything to save - if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata) - { - updateType |= ItemUpdateType.MetadataDownload; - } + // If any of these properties are set then make sure the updateType is not None, just to force everything to save + if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata) + { + updateType |= ItemUpdateType.MetadataDownload; + } - if (hasRefreshedMetadata && hasRefreshedImages) - { - item.DateLastRefreshed = DateTime.UtcNow; - } - else - { - item.DateLastRefreshed = default; + // Save to database + await SaveItemAsync(metadataResult, updateType, cancellationToken).ConfigureAwait(false); } - // Save to database - await SaveItemAsync(metadataResult, updateType, cancellationToken).ConfigureAwait(false); + return updateType; } - - await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false); - - return updateType; } private void ApplySearchResult(ItemLookupInfo lookupInfo, RemoteSearchResult result) @@ -322,17 +324,17 @@ namespace MediaBrowser.Providers.Manager return false; } - protected virtual IList<BaseItem> GetChildrenForMetadataUpdates(TItemType item) + protected virtual IReadOnlyList<BaseItem> GetChildrenForMetadataUpdates(TItemType item) { if (item is Folder folder) { return folder.GetRecursiveChildren(); } - return Array.Empty<BaseItem>(); + return []; } - protected virtual ItemUpdateType UpdateMetadataFromChildren(TItemType item, IList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected virtual ItemUpdateType UpdateMetadataFromChildren(TItemType item, IReadOnlyList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType) { var updateType = ItemUpdateType.None; @@ -371,7 +373,7 @@ namespace MediaBrowser.Providers.Manager return updateType; } - private ItemUpdateType UpdateCumulativeRunTimeTicks(TItemType item, IList<BaseItem> children) + private ItemUpdateType UpdateCumulativeRunTimeTicks(TItemType item, IReadOnlyList<BaseItem> children) { if (item is Folder folder && folder.SupportsCumulativeRunTimeTicks) { @@ -395,7 +397,7 @@ namespace MediaBrowser.Providers.Manager return ItemUpdateType.None; } - private ItemUpdateType UpdateDateLastMediaAdded(TItemType item, IList<BaseItem> children) + private ItemUpdateType UpdateDateLastMediaAdded(TItemType item, IReadOnlyList<BaseItem> children) { var updateType = ItemUpdateType.None; @@ -429,7 +431,7 @@ namespace MediaBrowser.Providers.Manager return updateType; } - private ItemUpdateType UpdatePremiereDate(TItemType item, IList<BaseItem> children) + private ItemUpdateType UpdatePremiereDate(TItemType item, IReadOnlyList<BaseItem> children) { var updateType = ItemUpdateType.None; @@ -467,7 +469,7 @@ namespace MediaBrowser.Providers.Manager return updateType; } - private ItemUpdateType UpdateGenres(TItemType item, IList<BaseItem> children) + private ItemUpdateType UpdateGenres(TItemType item, IReadOnlyList<BaseItem> children) { var updateType = ItemUpdateType.None; @@ -488,7 +490,7 @@ namespace MediaBrowser.Providers.Manager return updateType; } - private ItemUpdateType UpdateStudios(TItemType item, IList<BaseItem> children) + private ItemUpdateType UpdateStudios(TItemType item, IReadOnlyList<BaseItem> children) { var updateType = ItemUpdateType.None; @@ -509,7 +511,7 @@ namespace MediaBrowser.Providers.Manager return updateType; } - private ItemUpdateType UpdateOfficialRating(TItemType item, IList<BaseItem> children) + private ItemUpdateType UpdateOfficialRating(TItemType item, IReadOnlyList<BaseItem> children) { var updateType = ItemUpdateType.None; @@ -1142,13 +1144,8 @@ namespace MediaBrowser.Providers.Manager } } - private static void MergePeople(List<PersonInfo> source, List<PersonInfo> target) + private static void MergePeople(IReadOnlyList<PersonInfo> source, IReadOnlyList<PersonInfo> target) { - if (target is null) - { - target = new List<PersonInfo>(); - } - foreach (var person in target) { var normalizedName = person.Name.RemoveDiacritics(); diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 81a9af68b..6813cfa91 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Net.Mime; +using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; using AsyncKeyedLock; @@ -47,7 +48,7 @@ namespace MediaBrowser.Providers.Manager /// </summary> public class ProviderManager : IProviderManager, IDisposable { - private readonly object _refreshQueueLock = new(); + private readonly Lock _refreshQueueLock = new(); private readonly ILogger<ProviderManager> _logger; private readonly IHttpClientFactory _httpClientFactory; private readonly ILibraryMonitor _libraryMonitor; @@ -199,12 +200,20 @@ namespace MediaBrowser.Providers.Manager // TODO: Isolate this hack into the tvh plugin if (string.IsNullOrEmpty(contentType)) { + // Special case for imagecache if (url.Contains("/imagecache/", StringComparison.OrdinalIgnoreCase)) { contentType = MediaTypeNames.Image.Png; } else { + // Deduce content type from file extension + contentType = MimeTypes.GetMimeType(new Uri(url).GetLeftPart(UriPartial.Path)); + } + + // Throw if we still can't determine the content type + if (string.IsNullOrEmpty(contentType)) + { throw new HttpRequestException("Invalid image received: contentType not set.", null, response.StatusCode); } } @@ -251,15 +260,31 @@ namespace MediaBrowser.Providers.Manager } /// <inheritdoc/> - public Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken) + public async Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(source)) { throw new ArgumentNullException(nameof(source)); } - var fileStream = AsyncFile.OpenRead(source); - return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); + try + { + var fileStream = AsyncFile.OpenRead(source); + await new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger) + .SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken) + .ConfigureAwait(false); + } + finally + { + try + { + File.Delete(source); + } + catch (Exception ex) + { + _logger.LogError(ex, "Source file {Source} not found or in use, skip removing", source); + } + } } /// <inheritdoc/> @@ -1016,7 +1041,6 @@ namespace MediaBrowser.Providers.Manager /// <inheritdoc/> public void QueueRefresh(Guid itemId, MetadataRefreshOptions options, RefreshPriority priority) { - ArgumentNullException.ThrowIfNull(itemId); if (itemId.IsEmpty()) { throw new ArgumentException("Guid can't be empty", nameof(itemId)); diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 9a65852f0..34b3104b0 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -23,15 +23,14 @@ <PackageReference Include="Microsoft.Extensions.Http" /> <PackageReference Include="Newtonsoft.Json" /> <PackageReference Include="PlaylistsNET" /> - <PackageReference Include="z440.atl.core"/> + <PackageReference Include="z440.atl.core" /> <PackageReference Include="TMDbLib" /> </ItemGroup> <PropertyGroup> - <TargetFramework>net8.0</TargetFramework> + <TargetFramework>net9.0</TargetFramework> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> <GenerateDocumentationFile>true</GenerateDocumentationFile> - <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> <!-- Code Analyzers --> diff --git a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs index 27f6d120f..b4e3a860e 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioFileProber.cs @@ -36,6 +36,7 @@ namespace MediaBrowser.Providers.MediaInfo private readonly IMediaSourceManager _mediaSourceManager; private readonly LyricResolver _lyricResolver; private readonly ILyricManager _lyricManager; + private readonly IMediaStreamRepository _mediaStreamRepository; /// <summary> /// Initializes a new instance of the <see cref="AudioFileProber"/> class. @@ -47,6 +48,7 @@ namespace MediaBrowser.Providers.MediaInfo /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="lyricResolver">Instance of the <see cref="LyricResolver"/> interface.</param> /// <param name="lyricManager">Instance of the <see cref="ILyricManager"/> interface.</param> + /// <param name="mediaStreamRepository">Instance of the <see cref="IMediaStreamRepository"/>.</param> public AudioFileProber( ILogger<AudioFileProber> logger, IMediaSourceManager mediaSourceManager, @@ -54,7 +56,8 @@ namespace MediaBrowser.Providers.MediaInfo IItemRepository itemRepo, ILibraryManager libraryManager, LyricResolver lyricResolver, - ILyricManager lyricManager) + ILyricManager lyricManager, + IMediaStreamRepository mediaStreamRepository) { _mediaEncoder = mediaEncoder; _itemRepo = itemRepo; @@ -63,6 +66,7 @@ namespace MediaBrowser.Providers.MediaInfo _mediaSourceManager = mediaSourceManager; _lyricResolver = lyricResolver; _lyricManager = lyricManager; + _mediaStreamRepository = mediaStreamRepository; ATL.Settings.DisplayValueSeparator = InternalValueSeparator; ATL.Settings.UseFileNameWhenNoTitle = false; ATL.Settings.ID3v2_separatev2v3Values = false; @@ -149,7 +153,7 @@ namespace MediaBrowser.Providers.MediaInfo audio.HasLyrics = mediaStreams.Any(s => s.Type == MediaStreamType.Lyric); - _itemRepo.SaveMediaStreams(audio.Id, mediaStreams, cancellationToken); + _mediaStreamRepository.SaveMediaStreams(audio.Id, mediaStreams, cancellationToken); } /// <summary> @@ -347,7 +351,8 @@ namespace MediaBrowser.Providers.MediaInfo || track.AdditionalFields.TryGetValue("MusicBrainz Artist Id", out musicBrainzArtistTag)) && !string.IsNullOrEmpty(musicBrainzArtistTag)) { - audio.TrySetProviderId(MetadataProvider.MusicBrainzArtist, musicBrainzArtistTag); + var id = GetFirstMusicBrainzId(musicBrainzArtistTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); + audio.TrySetProviderId(MetadataProvider.MusicBrainzArtist, id); } } @@ -357,7 +362,8 @@ namespace MediaBrowser.Providers.MediaInfo || track.AdditionalFields.TryGetValue("MusicBrainz Album Artist Id", out musicBrainzReleaseArtistIdTag)) && !string.IsNullOrEmpty(musicBrainzReleaseArtistIdTag)) { - audio.TrySetProviderId(MetadataProvider.MusicBrainzAlbumArtist, musicBrainzReleaseArtistIdTag); + var id = GetFirstMusicBrainzId(musicBrainzReleaseArtistIdTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); + audio.TrySetProviderId(MetadataProvider.MusicBrainzAlbumArtist, id); } } @@ -367,7 +373,8 @@ namespace MediaBrowser.Providers.MediaInfo || track.AdditionalFields.TryGetValue("MusicBrainz Album Id", out musicBrainzReleaseIdTag)) && !string.IsNullOrEmpty(musicBrainzReleaseIdTag)) { - audio.TrySetProviderId(MetadataProvider.MusicBrainzAlbum, musicBrainzReleaseIdTag); + var id = GetFirstMusicBrainzId(musicBrainzReleaseIdTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); + audio.TrySetProviderId(MetadataProvider.MusicBrainzAlbum, id); } } @@ -377,7 +384,8 @@ namespace MediaBrowser.Providers.MediaInfo || track.AdditionalFields.TryGetValue("MusicBrainz Release Group Id", out musicBrainzReleaseGroupIdTag)) && !string.IsNullOrEmpty(musicBrainzReleaseGroupIdTag)) { - audio.TrySetProviderId(MetadataProvider.MusicBrainzReleaseGroup, musicBrainzReleaseGroupIdTag); + var id = GetFirstMusicBrainzId(musicBrainzReleaseGroupIdTag, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); + audio.TrySetProviderId(MetadataProvider.MusicBrainzReleaseGroup, id); } } @@ -387,7 +395,8 @@ namespace MediaBrowser.Providers.MediaInfo || track.AdditionalFields.TryGetValue("MusicBrainz Release Track Id", out trackMbId)) && !string.IsNullOrEmpty(trackMbId)) { - audio.TrySetProviderId(MetadataProvider.MusicBrainzTrack, trackMbId); + var id = GetFirstMusicBrainzId(trackMbId, libraryOptions.UseCustomTagDelimiters, libraryOptions.GetCustomTagDelimiters(), libraryOptions.DelimiterWhitelist); + audio.TrySetProviderId(MetadataProvider.MusicBrainzTrack, id); } } @@ -441,5 +450,18 @@ namespace MediaBrowser.Providers.MediaInfo return items; } + + // MusicBrainz IDs are multi-value tags, so we need to split them + // However, our current provider can only have one single ID, which means we need to pick the first one + private string? GetFirstMusicBrainzId(string tag, bool useCustomTagDelimiters, char[] tagDelimiters, string[] whitelist) + { + var val = tag.Split(InternalValueSeparator).FirstOrDefault(); + if (val is not null && useCustomTagDelimiters) + { + val = SplitWithCustomDelimiter(val, tagDelimiters, whitelist).FirstOrDefault(); + } + + return val; + } } } diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index d1c0ddb37..cc2b3face 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -1,4 +1,4 @@ -#nullable disable +#pragma warning disable CA1826 // CA1826 Do not use Enumerable methods on Indexable collections. using System; using System.Collections.Generic; @@ -74,18 +74,17 @@ namespace MediaBrowser.Providers.MediaInfo return GetImage((Audio)item, imageStreams, cancellationToken); } - private async Task<DynamicImageResponse> GetImage(Audio item, List<MediaStream> imageStreams, CancellationToken cancellationToken) + private async Task<DynamicImageResponse> GetImage(Audio item, IReadOnlyList<MediaStream> imageStreams, CancellationToken cancellationToken) { var path = GetAudioImagePath(item); if (!File.Exists(path)) { - Directory.CreateDirectory(Path.GetDirectoryName(path)); - + var directoryName = Path.GetDirectoryName(path) ?? throw new InvalidOperationException($"Invalid path '{path}'"); + Directory.CreateDirectory(directoryName); var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).Contains("front", StringComparison.OrdinalIgnoreCase)) ?? imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).Contains("cover", StringComparison.OrdinalIgnoreCase)) ?? imageStreams.FirstOrDefault(); - var imageStreamIndex = imageStream?.Index; var tempFile = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 246ba2733..16f3175d2 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -31,6 +31,7 @@ namespace MediaBrowser.Providers.MediaInfo public class FFProbeVideoInfo { private readonly ILogger<FFProbeVideoInfo> _logger; + private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaEncoder _mediaEncoder; private readonly IItemRepository _itemRepo; private readonly IBlurayExaminer _blurayExaminer; @@ -38,11 +39,12 @@ namespace MediaBrowser.Providers.MediaInfo private readonly IEncodingManager _encodingManager; private readonly IServerConfigurationManager _config; private readonly ISubtitleManager _subtitleManager; - private readonly IChapterManager _chapterManager; + private readonly IChapterRepository _chapterManager; private readonly ILibraryManager _libraryManager; private readonly AudioResolver _audioResolver; private readonly SubtitleResolver _subtitleResolver; - private readonly IMediaSourceManager _mediaSourceManager; + private readonly IMediaAttachmentRepository _mediaAttachmentRepository; + private readonly IMediaStreamRepository _mediaStreamRepository; public FFProbeVideoInfo( ILogger<FFProbeVideoInfo> logger, @@ -54,10 +56,12 @@ namespace MediaBrowser.Providers.MediaInfo IEncodingManager encodingManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, - IChapterManager chapterManager, + IChapterRepository chapterManager, ILibraryManager libraryManager, AudioResolver audioResolver, - SubtitleResolver subtitleResolver) + SubtitleResolver subtitleResolver, + IMediaAttachmentRepository mediaAttachmentRepository, + IMediaStreamRepository mediaStreamRepository) { _logger = logger; _mediaSourceManager = mediaSourceManager; @@ -72,6 +76,9 @@ namespace MediaBrowser.Providers.MediaInfo _libraryManager = libraryManager; _audioResolver = audioResolver; _subtitleResolver = subtitleResolver; + _mediaAttachmentRepository = mediaAttachmentRepository; + _mediaStreamRepository = mediaStreamRepository; + _mediaStreamRepository = mediaStreamRepository; } public async Task<ItemUpdateType> ProbeVideo<T>( @@ -267,11 +274,11 @@ namespace MediaBrowser.Providers.MediaInfo video.HasSubtitles = mediaStreams.Any(i => i.Type == MediaStreamType.Subtitle); - _itemRepo.SaveMediaStreams(video.Id, mediaStreams, cancellationToken); + _mediaStreamRepository.SaveMediaStreams(video.Id, mediaStreams, cancellationToken); if (mediaAttachments.Any()) { - _itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken); + _mediaAttachmentRepository.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken); } if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh @@ -354,7 +361,7 @@ namespace MediaBrowser.Providers.MediaInfo blurayVideoStream.Codec = ffmpegVideoStream.Codec; blurayVideoStream.BitRate = blurayVideoStream.BitRate.GetValueOrDefault() == 0 ? ffmpegVideoStream.BitRate : blurayVideoStream.BitRate; blurayVideoStream.Width = blurayVideoStream.Width.GetValueOrDefault() == 0 ? ffmpegVideoStream.Width : blurayVideoStream.Width; - blurayVideoStream.Height = blurayVideoStream.Height.GetValueOrDefault() == 0 ? ffmpegVideoStream.Width : blurayVideoStream.Height; + blurayVideoStream.Height = blurayVideoStream.Height.GetValueOrDefault() == 0 ? ffmpegVideoStream.Height : blurayVideoStream.Height; blurayVideoStream.ColorRange = ffmpegVideoStream.ColorRange; blurayVideoStream.ColorSpace = ffmpegVideoStream.ColorSpace; blurayVideoStream.ColorTransfer = ffmpegVideoStream.ColorTransfer; @@ -627,7 +634,7 @@ namespace MediaBrowser.Providers.MediaInfo { var runtime = video.RunTimeTicks.GetValueOrDefault(); - // Only process files with a runtime higher than 0 and lower than 12h. The latter are likely corrupted. + // Only process files with a runtime greater than 0 and less than 12h. The latter are likely corrupted. if (runtime < 0 || runtime > TimeSpan.FromHours(12).Ticks) { throw new ArgumentException( diff --git a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs index fbec4e963..f12390bc2 100644 --- a/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs +++ b/MediaBrowser.Providers/MediaInfo/MediaInfoResolver.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.Providers.MediaInfo mediaStream.Index = startIndex++; mediaStream.IsDefault = pathInfo.IsDefault || mediaStream.IsDefault; mediaStream.IsForced = pathInfo.IsForced || mediaStream.IsForced; - mediaStream.IsHearingImpaired = pathInfo.IsHearingImpaired || mediaStream.IsHearingImpaired; + mediaStream.IsHearingImpaired = pathInfo.IsHearingImpaired || mediaStream.IsHearingImpaired.GetValueOrDefault(); mediaStreams.Add(MergeMetadata(mediaStream, pathInfo)); } diff --git a/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs index 04da8fb88..1c2f8b913 100644 --- a/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/ProbeProvider.cs @@ -61,12 +61,14 @@ namespace MediaBrowser.Providers.MediaInfo /// <param name="encodingManager">Instance of the <see cref="IEncodingManager"/> interface.</param> /// <param name="config">Instance of the <see cref="IServerConfigurationManager"/> interface.</param> /// <param name="subtitleManager">Instance of the <see cref="ISubtitleManager"/> interface.</param> - /// <param name="chapterManager">Instance of the <see cref="IChapterManager"/> interface.</param> + /// <param name="chapterManager">Instance of the <see cref="IChapterRepository"/> interface.</param> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/>.</param> /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> /// <param name="namingOptions">The <see cref="NamingOptions"/>.</param> /// <param name="lyricManager">Instance of the <see cref="ILyricManager"/> interface.</param> + /// <param name="mediaAttachmentRepository">Instance of the <see cref="IMediaAttachmentRepository"/> interface.</param> + /// <param name="mediaStreamRepository">Instance of the <see cref="IMediaStreamRepository"/> interface.</param> public ProbeProvider( IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, @@ -76,12 +78,14 @@ namespace MediaBrowser.Providers.MediaInfo IEncodingManager encodingManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, - IChapterManager chapterManager, + IChapterRepository chapterManager, ILibraryManager libraryManager, IFileSystem fileSystem, ILoggerFactory loggerFactory, NamingOptions namingOptions, - ILyricManager lyricManager) + ILyricManager lyricManager, + IMediaAttachmentRepository mediaAttachmentRepository, + IMediaStreamRepository mediaStreamRepository) { _logger = loggerFactory.CreateLogger<ProbeProvider>(); _audioResolver = new AudioResolver(loggerFactory.CreateLogger<AudioResolver>(), localization, mediaEncoder, fileSystem, namingOptions); @@ -101,7 +105,9 @@ namespace MediaBrowser.Providers.MediaInfo chapterManager, libraryManager, _audioResolver, - _subtitleResolver); + _subtitleResolver, + mediaAttachmentRepository, + mediaStreamRepository); _audioProber = new AudioFileProber( loggerFactory.CreateLogger<AudioFileProber>(), @@ -110,7 +116,8 @@ namespace MediaBrowser.Providers.MediaInfo itemRepo, libraryManager, _lyricResolver, - lyricManager); + lyricManager, + mediaStreamRepository); } /// <inheritdoc /> diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs index 20fb4dab9..227f31025 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.MediaInfo public async Task<List<string>> DownloadSubtitles( Video video, - List<MediaStream> mediaStreams, + IReadOnlyList<MediaStream> mediaStreams, bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, bool requirePerfectMatch, @@ -68,7 +68,7 @@ namespace MediaBrowser.Providers.MediaInfo public Task<bool> DownloadSubtitles( Video video, - List<MediaStream> mediaStreams, + IReadOnlyList<MediaStream> mediaStreams, bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, bool requirePerfectMatch, @@ -120,7 +120,7 @@ namespace MediaBrowser.Providers.MediaInfo private async Task<bool> DownloadSubtitles( Video video, - List<MediaStream> mediaStreams, + IReadOnlyList<MediaStream> mediaStreams, bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, bool requirePerfectMatch, diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index 6eb75891a..938f3cb32 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -217,7 +217,7 @@ namespace MediaBrowser.Providers.MediaInfo return new[] { // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks } + new TaskTriggerInfo { Type = TaskTriggerInfoType.IntervalTrigger, IntervalTicks = TimeSpan.FromHours(24).Ticks } }; } } diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index ba7ad4072..3d446053b 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1826 // CA1826 Do not use Enumerable methods on Indexable collections. + using System; using System.Collections.Generic; using System.Linq; diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs index a39bd16ce..25698d8cb 100644 --- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs +++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs @@ -47,11 +47,11 @@ namespace MediaBrowser.Providers.Music protected override bool EnableUpdatingStudiosFromChildren => true; /// <inheritdoc /> - protected override IList<BaseItem> GetChildrenForMetadataUpdates(MusicAlbum item) + protected override IReadOnlyList<BaseItem> GetChildrenForMetadataUpdates(MusicAlbum item) => item.GetRecursiveChildren(i => i is Audio); /// <inheritdoc /> - protected override ItemUpdateType UpdateMetadataFromChildren(MusicAlbum item, IList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType UpdateMetadataFromChildren(MusicAlbum item, IReadOnlyList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType) { var updateType = base.UpdateMetadataFromChildren(item, children, isFullRefresh, currentUpdateType); diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs index 1f342c0db..c47f9a500 100644 --- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs +++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs @@ -1,6 +1,7 @@ #pragma warning disable CS1591 using System.Collections.Generic; +using System.Collections.Immutable; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -28,7 +29,7 @@ namespace MediaBrowser.Providers.Music protected override bool EnableUpdatingGenresFromChildren => true; /// <inheritdoc /> - protected override IList<BaseItem> GetChildrenForMetadataUpdates(MusicArtist item) + protected override IReadOnlyList<BaseItem> GetChildrenForMetadataUpdates(MusicArtist item) { return item.IsAccessedByName ? item.GetTaggedItems(new InternalItemsQuery diff --git a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs index 43889bfbf..7be54453f 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Providers.Playlists protected override bool EnableUpdatingStudiosFromChildren => true; /// <inheritdoc /> - protected override IList<BaseItem> GetChildrenForMetadataUpdates(Playlist item) + protected override IReadOnlyList<BaseItem> GetChildrenForMetadataUpdates(Playlist item) => item.GetLinkedChildren(); /// <inheritdoc /> diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index 8d68e2dcf..eef08b251 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -198,7 +198,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies }; movie.SetProviderId(MetadataProvider.Tmdb, tmdbId); - movie.SetProviderId(MetadataProvider.Imdb, movieResult.ImdbId); + movie.TrySetProviderId(MetadataProvider.Imdb, movieResult.ImdbId); if (movieResult.BelongsToCollection is not null) { movie.SetProviderId(MetadataProvider.TmdbCollection, movieResult.BelongsToCollection.Id.ToString(CultureInfo.InvariantCulture)); diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs index 8b690193e..b27ccaa6a 100644 --- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs @@ -80,11 +80,11 @@ namespace MediaBrowser.Providers.TV } /// <inheritdoc /> - protected override IList<BaseItem> GetChildrenForMetadataUpdates(Season item) + protected override IReadOnlyList<BaseItem> GetChildrenForMetadataUpdates(Season item) => item.GetEpisodes(); /// <inheritdoc /> - protected override ItemUpdateType UpdateMetadataFromChildren(Season item, IList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType UpdateMetadataFromChildren(Season item, IReadOnlyList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType) { var updateType = base.UpdateMetadataFromChildren(item, children, isFullRefresh, currentUpdateType); @@ -96,7 +96,7 @@ namespace MediaBrowser.Providers.TV return updateType; } - private ItemUpdateType SaveIsVirtualItem(Season item, IList<BaseItem> episodes) + private ItemUpdateType SaveIsVirtualItem(Season item, IReadOnlyList<BaseItem> episodes) { var isVirtualItem = item.LocationType == LocationType.Virtual && (episodes.Count == 0 || episodes.All(i => i.LocationType == LocationType.Virtual)); diff --git a/MediaBrowser.Providers/Trickplay/TrickplayImagesTask.cs b/MediaBrowser.Providers/Trickplay/TrickplayImagesTask.cs index 31c0eeb31..4310f93d4 100644 --- a/MediaBrowser.Providers/Trickplay/TrickplayImagesTask.cs +++ b/MediaBrowser.Providers/Trickplay/TrickplayImagesTask.cs @@ -63,7 +63,7 @@ public class TrickplayImagesTask : IScheduledTask { new TaskTriggerInfo { - Type = TaskTriggerInfo.TriggerDaily, + Type = TaskTriggerInfoType.DailyTrigger, TimeOfDayTicks = TimeSpan.FromHours(3).Ticks } }; |
