From e3fccd5ae67b44be1fa44e82fb0954f29cc825ef Mon Sep 17 00:00:00 2001 From: KonH Date: Sun, 3 Oct 2021 11:00:45 +0700 Subject: Fix warning: Qualifier is redundant (#2149) --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1237268d7..838a9f2f8 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2997,7 +2997,7 @@ namespace MediaBrowser.Controller.Entities } /// - public bool Equals(BaseItem other) => object.Equals(Id, other?.Id); + public bool Equals(BaseItem other) => Equals(Id, other?.Id); /// public override int GetHashCode() => HashCode.Combine(Id); -- cgit v1.2.3 From b478b115e3194aa383f86d7d6fbf07e0f2bfadea Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Mon, 1 Nov 2021 02:38:12 +0100 Subject: Refactor to validate all images up front --- MediaBrowser.Controller/Entities/BaseItem.cs | 19 ++---------- .../Manager/ItemImageProvider.cs | 29 ++---------------- .../Manager/ItemImageProviderTests.cs | 35 ++++++++++++++-------- 3 files changed, 27 insertions(+), 56 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 838a9f2f8..7dd8e310e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2495,11 +2495,11 @@ namespace MediaBrowser.Controller.Entities } /// - /// Adds the images. + /// Adds the images, updating metadata if they already are part of this item. /// /// Type of the image. /// The images. - /// true if XXXX, false otherwise. + /// true if images were added or updated, false otherwise. /// Cannot call AddImages with chapter images. public bool AddImages(ImageType imageType, List images) { @@ -2512,7 +2512,6 @@ namespace MediaBrowser.Controller.Entities .ToList(); var newImageList = new List(); - var imageAdded = false; var imageUpdated = false; foreach (var newImage in images) @@ -2528,7 +2527,6 @@ namespace MediaBrowser.Controller.Entities if (existing == null) { newImageList.Add(newImage); - imageAdded = true; } else { @@ -2549,19 +2547,6 @@ namespace MediaBrowser.Controller.Entities } } - if (imageAdded || images.Count != existingImages.Count) - { - var newImagePaths = images.Select(i => i.FullName).ToList(); - - var deleted = existingImages - .FindAll(i => i.IsLocalFile && !newImagePaths.Contains(i.Path.AsSpan(), StringComparison.OrdinalIgnoreCase) && !File.Exists(i.Path)); - - if (deleted.Count > 0) - { - ImageInfos = ImageInfos.Except(deleted).ToArray(); - } - } - if (newImageList.Count > 0) { ImageInfos = ImageInfos.Concat(newImageList.Select(i => GetImageInfo(i, imageType))).ToArray(); diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index c80407bcb..f60fce11b 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -395,7 +395,7 @@ namespace MediaBrowser.Providers.Manager /// true if changes were made to the item; otherwise false. public bool MergeImages(BaseItem item, IReadOnlyList images) { - var changed = false; + var changed = item.ValidateImages(new DirectoryService(_fileSystem)); for (var i = 0; i < _singularImages.Length; i++) { @@ -431,18 +431,6 @@ namespace MediaBrowser.Providers.Manager currentImage.DateModified = newDateModified; } } - else - { - var existing = item.GetImageInfo(type, 0); - if (existing != null) - { - if (existing.IsLocalFile && !File.Exists(existing.Path)) - { - item.RemoveImage(existing); - changed = true; - } - } - } } if (UpdateMultiImages(item, images, ImageType.Backdrop)) @@ -450,12 +438,9 @@ namespace MediaBrowser.Providers.Manager changed = true; } - if (item is IHasScreenshots) + if (item is IHasScreenshots && UpdateMultiImages(item, images, ImageType.Screenshot)) { - if (UpdateMultiImages(item, images, ImageType.Screenshot)) - { - changed = true; - } + changed = true; } return changed; @@ -480,14 +465,6 @@ namespace MediaBrowser.Providers.Manager { var changed = false; - var deletedImages = item.GetImages(type).Where(i => i.IsLocalFile && !File.Exists(i.Path)).ToList(); - - if (deletedImages.Count > 0) - { - item.RemoveImages(deletedImages); - changed = true; - } - var newImageFileInfos = images .Where(i => i.Type == type) .Select(i => i.FileInfo) diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 253bcb7ca..b5efd8f01 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -183,7 +183,7 @@ namespace Jellyfin.Providers.Tests.Manager var images = GetImages(imageType, imageCount, true); - var itemImageProvider = GetItemImageProvider(null, fileSystem.Object); + var itemImageProvider = GetItemImageProvider(null, fileSystem); var changed = itemImageProvider.MergeImages(item, images); Assert.False(changed); @@ -213,7 +213,7 @@ namespace Jellyfin.Providers.Tests.Manager var images = GetImages(imageType, imageCount, true); - var itemImageProvider = GetItemImageProvider(null, fileSystem.Object); + var itemImageProvider = GetItemImageProvider(null, fileSystem); var changed = itemImageProvider.MergeImages(item, images); Assert.True(changed); @@ -363,7 +363,7 @@ namespace Jellyfin.Providers.Tests.Manager ReplaceAllImages = true }; - var itemImageProvider = GetItemImageProvider(null, Mock.Of()); + var itemImageProvider = GetItemImageProvider(null, new Mock()); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { dynamicProvider.Object }, refreshOptions, CancellationToken.None); Assert.True(result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); @@ -401,7 +401,7 @@ namespace Jellyfin.Providers.Tests.Manager var providerManager = new Mock(MockBehavior.Strict); providerManager.Setup(pm => pm.GetAvailableRemoteImages(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(remoteInfo); - var itemImageProvider = GetItemImageProvider(providerManager.Object, Mock.Of()); + var itemImageProvider = GetItemImageProvider(providerManager.Object, null); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { remoteProvider.Object }, refreshOptions, CancellationToken.None); Assert.False(result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); @@ -459,7 +459,7 @@ namespace Jellyfin.Providers.Tests.Manager var fileSystem = new Mock(); fileSystem.Setup(fs => fs.GetFileInfo(It.IsAny())) .Returns(new FileSystemMetadata { Length = 1 }); - var itemImageProvider = GetItemImageProvider(providerManager.Object, fileSystem.Object); + var itemImageProvider = GetItemImageProvider(providerManager.Object, fileSystem); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { remoteProvider.Object }, refreshOptions, CancellationToken.None); Assert.True(result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); @@ -496,7 +496,7 @@ namespace Jellyfin.Providers.Tests.Manager var providerManager = new Mock(MockBehavior.Strict); providerManager.Setup(pm => pm.GetAvailableRemoteImages(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(remoteInfo); - var itemImageProvider = GetItemImageProvider(providerManager.Object, Mock.Of()); + var itemImageProvider = GetItemImageProvider(providerManager.Object, null); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { remoteProvider.Object }, refreshOptions, CancellationToken.None); Assert.True(result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); @@ -505,7 +505,7 @@ namespace Jellyfin.Providers.Tests.Manager // images from the provider manager are sorted by preference (earlier images are higher priority) so we can verify that low url numbers are chosen foreach (var image in actualImages) { - var index = int.Parse(Regex.Match(image.Path, @"\d+").Value, NumberStyles.Integer, CultureInfo.InvariantCulture); + var index = int.Parse(Regex.Match(image.Path, @"[0-9]+").Value, NumberStyles.Integer, CultureInfo.InvariantCulture); Assert.True(index < imageCount); } } @@ -543,14 +543,14 @@ namespace Jellyfin.Providers.Tests.Manager var providerManager = new Mock(MockBehavior.Strict); providerManager.Setup(pm => pm.GetAvailableRemoteImages(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(remoteInfo); - var itemImageProvider = GetItemImageProvider(providerManager.Object, Mock.Of()); + var itemImageProvider = GetItemImageProvider(providerManager.Object, new Mock()); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { remoteProvider.Object }, refreshOptions, CancellationToken.None); Assert.True(result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); Assert.Equal(imageCount, item.GetImages(imageType).Count()); foreach (var image in item.GetImages(imageType)) { - Assert.Matches(@"image url \d", image.Path); + Assert.Matches(@"image url [0-9]", image.Path); } } @@ -573,19 +573,28 @@ namespace Jellyfin.Providers.Tests.Manager ReplaceAllImages = true }; - var itemImageProvider = GetItemImageProvider(Mock.Of(), Mock.Of()); + var itemImageProvider = GetItemImageProvider(Mock.Of(), null); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { remoteProvider.Object }, refreshOptions, CancellationToken.None); Assert.False(result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); Assert.Equal(imageCount, item.GetImages(imageType).Count()); } - private static ItemImageProvider GetItemImageProvider(IProviderManager? providerManager, IFileSystem? fileSystem) + private static ItemImageProvider GetItemImageProvider(IProviderManager? providerManager, Mock? mockFileSystem) { // strict to ensure this isn't accidentally used where a prepared mock is intended providerManager ??= Mock.Of(MockBehavior.Strict); - fileSystem ??= Mock.Of(MockBehavior.Strict); - return new ItemImageProvider(new NullLogger(), providerManager, fileSystem); + + // BaseItem.ValidateImages depends on the directory service being able to list directory contents, give it the expected valid file paths + mockFileSystem ??= new Mock(MockBehavior.Strict); + mockFileSystem.Setup(fs => fs.GetFilePaths(It.IsAny(), It.IsAny())) + .Returns(new[] + { + string.Format(CultureInfo.InvariantCulture, TestDataImagePath, 0), + string.Format(CultureInfo.InvariantCulture, TestDataImagePath, 1) + }); + + return new ItemImageProvider(new NullLogger(), providerManager, mockFileSystem.Object); } private static BaseItem GetItemWithImages(ImageType type, int count, bool validPaths) -- cgit v1.2.3 From 7fcf01235c2360ec64cad685df7f155ef3dee69a Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Tue, 2 Nov 2021 16:16:06 +0100 Subject: Change RemoveImages to array, improve download test --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Manager/ItemImageProvider.cs | 20 +++++------ .../Manager/ItemImageProviderTests.cs | 39 +++++++++++++--------- 3 files changed, 35 insertions(+), 26 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 7dd8e310e..02ee97b23 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2345,7 +2345,7 @@ namespace MediaBrowser.Controller.Entities RemoveImages(new List { image }); } - public void RemoveImages(List deletedImages) + public void RemoveImages(IEnumerable deletedImages) { ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 2c7d43c86..8d5795f8e 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -103,16 +103,16 @@ namespace MediaBrowser.Providers.Manager ImageRefreshOptions refreshOptions, CancellationToken cancellationToken) { - List oldBackdropImages = new List(); + var oldBackdropImages = Array.Empty(); if (refreshOptions.IsReplacingImage(ImageType.Backdrop)) { - oldBackdropImages = item.GetImages(ImageType.Backdrop).ToList(); + oldBackdropImages = item.GetImages(ImageType.Backdrop).ToArray(); } - List oldScreenshotImages = new List(); + var oldScreenshotImages = Array.Empty(); if (refreshOptions.IsReplacingImage(ImageType.Screenshot)) { - oldScreenshotImages = item.GetImages(ImageType.Screenshot).ToList(); + oldScreenshotImages = item.GetImages(ImageType.Screenshot).ToArray(); } var result = new RefreshResult { UpdateType = ItemUpdateType.None }; @@ -121,8 +121,8 @@ namespace MediaBrowser.Providers.Manager var typeOptions = libraryOptions.GetTypeOptions(typeName) ?? new TypeOptions { Type = typeName }; // track library limits, adding buffer to allow lazy replacing of current images - var backdropLimit = typeOptions.GetLimit(ImageType.Backdrop) + oldBackdropImages.Count; - var screenshotLimit = typeOptions.GetLimit(ImageType.Screenshot) + oldScreenshotImages.Count; + var backdropLimit = typeOptions.GetLimit(ImageType.Backdrop) + oldBackdropImages.Length; + var screenshotLimit = typeOptions.GetLimit(ImageType.Screenshot) + oldScreenshotImages.Length; var downloadedImages = new List(); foreach (var provider in providers) @@ -140,12 +140,12 @@ namespace MediaBrowser.Providers.Manager } // only delete existing multi-images if new ones were added - if (oldBackdropImages.Count > 0 && oldBackdropImages.Count < item.GetImages(ImageType.Backdrop).Count()) + if (oldBackdropImages.Length > 0 && oldBackdropImages.Length < item.GetImages(ImageType.Backdrop).Count()) { PruneImages(item, oldBackdropImages); } - if (oldScreenshotImages.Count > 0 && oldScreenshotImages.Count < item.GetImages(ImageType.Screenshot).Count()) + if (oldScreenshotImages.Length > 0 && oldScreenshotImages.Length < item.GetImages(ImageType.Screenshot).Count()) { PruneImages(item, oldScreenshotImages); } @@ -366,9 +366,9 @@ namespace MediaBrowser.Providers.Manager return options.IsEnabled(type); } - private void PruneImages(BaseItem item, List images) + private void PruneImages(BaseItem item, ItemImageInfo[] images) { - for (var i = 0; i < images.Count; i++) + for (var i = 0; i < images.Length; i++) { var image = images[i]; diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index b5efd8f01..54f2cb71b 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -409,21 +409,23 @@ namespace Jellyfin.Providers.Tests.Manager } [Theory] - [MemberData(nameof(GetImageTypesWithCount))] - public async void RefreshImages_EmptyNonStubItemPopulatedProviderRemote_DownloadsImages(ImageType imageType, int imageCount) + [InlineData(ImageType.Primary, 0, false)] // singular type only fetches if type is missing from item, no caching + [InlineData(ImageType.Backdrop, 0, false)] // empty item, no cache to check + [InlineData(ImageType.Backdrop, 1, false)] // populated item, cached so no download + [InlineData(ImageType.Backdrop, 1, true)] // populated item, forced to download + public async void RefreshImages_NonStubItemPopulatedProviderRemote_DownloadsIfNecessary(ImageType imageType, int initialImageCount, bool fullRefresh) { - // Has to exist for querying DateModified time on file, results stored but not checked so not populating - BaseItem.FileSystem ??= Mock.Of(); + var targetImageCount = 1; // Set path and media source manager so images will be downloaded (EnableImageStub will return false) - var item = new MovieWithScreenshots - { - Path = "non-empty path" - }; + var item = GetItemWithImages(imageType, initialImageCount, false); + item.Path = "non-empty path"; BaseItem.MediaSourceManager = Mock.Of(); - var libraryOptions = GetLibraryOptions(item, imageType, imageCount); + // seek 2 so it won't short-circuit out of downloading when populated + var libraryOptions = GetLibraryOptions(item, imageType, 2); + var content = "Content"; var remoteProvider = new Mock(MockBehavior.Strict); remoteProvider.Setup(rp => rp.Name).Returns("MockRemoteProvider"); remoteProvider.Setup(rp => rp.GetSupportedImages(item)) @@ -433,13 +435,19 @@ namespace Jellyfin.Providers.Tests.Manager { ReasonPhrase = url, StatusCode = HttpStatusCode.OK, - Content = new StringContent("Content", Encoding.UTF8, "image/jpeg") + Content = new StringContent(content, Encoding.UTF8, "image/jpeg") }); - var refreshOptions = new ImageRefreshOptions(null); + var refreshOptions = fullRefresh + ? new ImageRefreshOptions(null) + { + ImageRefreshMode = MetadataRefreshMode.FullRefresh, + ReplaceAllImages = true + } + : new ImageRefreshOptions(null); var remoteInfo = new List(); - for (int i = 0; i < imageCount; i++) + for (int i = 0; i < targetImageCount; i++) { remoteInfo.Add(new RemoteImageInfo { @@ -457,13 +465,14 @@ namespace Jellyfin.Providers.Tests.Manager callbackItem.SetImagePath(callbackType, callbackItem.AllowsMultipleImages(callbackType) ? callbackItem.GetImages(callbackType).Count() : 0, new FileSystemMetadata())) .Returns(Task.CompletedTask); var fileSystem = new Mock(); + // match reported file size to image content length - condition for skipping already downloaded multi-images fileSystem.Setup(fs => fs.GetFileInfo(It.IsAny())) - .Returns(new FileSystemMetadata { Length = 1 }); + .Returns(new FileSystemMetadata { Length = content.Length }); var itemImageProvider = GetItemImageProvider(providerManager.Object, fileSystem); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { remoteProvider.Object }, refreshOptions, CancellationToken.None); - Assert.True(result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); - Assert.Equal(imageCount, item.GetImages(imageType).Count()); + Assert.Equal(initialImageCount == 0 || fullRefresh, result.UpdateType.HasFlag(ItemUpdateType.ImageUpdate)); + Assert.Equal(targetImageCount, item.GetImages(imageType).Count()); } [Theory] -- cgit v1.2.3 From 416894008ea641b8d069ee482f7e63d2b9d5723d Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 3 Nov 2021 14:02:57 +0100 Subject: Minor improvements * Removed some allocations * Removed some useless abstractions --- MediaBrowser.Controller/Entities/BaseItem.cs | 106 +++++++-------------- .../Manager/ItemImageProviderTests.cs | 55 ++++++----- 2 files changed, 64 insertions(+), 97 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 02ee97b23..0df70705e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -84,8 +84,6 @@ namespace MediaBrowser.Controller.Entities Model.Entities.ExtraType.Scene }; - public static readonly char[] SlugReplaceChars = { '?', '/', '&' }; - /// /// The supported extra folder names and types. See . /// @@ -354,11 +352,6 @@ namespace MediaBrowser.Controller.Entities { get { - // if (IsOffline) - // { - // return LocationType.Offline; - // } - var path = Path; if (string.IsNullOrEmpty(path)) { @@ -391,7 +384,7 @@ namespace MediaBrowser.Controller.Entities } [JsonIgnore] - public bool IsFileProtocol => IsPathProtocol(MediaProtocol.File); + public bool IsFileProtocol => PathProtocol == MediaProtocol.File; [JsonIgnore] public bool HasPathProtocol => PathProtocol.HasValue; @@ -583,14 +576,7 @@ namespace MediaBrowser.Controller.Entities } [JsonIgnore] - public virtual Guid DisplayParentId - { - get - { - var parentId = ParentId; - return parentId; - } - } + public virtual Guid DisplayParentId => ParentId; [JsonIgnore] public BaseItem DisplayParent @@ -853,13 +839,6 @@ namespace MediaBrowser.Controller.Entities return Id.ToString("N", CultureInfo.InvariantCulture); } - public bool IsPathProtocol(MediaProtocol protocol) - { - var current = PathProtocol; - - return current.HasValue && current.Value == protocol; - } - private List> GetSortChunks(string s1) { var list = new List>(); @@ -987,7 +966,7 @@ namespace MediaBrowser.Controller.Entities ReadOnlySpan idString = Id.ToString("N", CultureInfo.InvariantCulture); - return System.IO.Path.Join(basePath, "library", idString.Slice(0, 2), idString); + return System.IO.Path.Join(basePath, "library", idString[..2], idString); } /// @@ -1302,8 +1281,7 @@ namespace MediaBrowser.Controller.Entities terms.Add(item.Name); } - var video = item as Video; - if (video != null) + if (item is Video video) { if (video.Video3DFormat.HasValue) { @@ -1338,7 +1316,7 @@ namespace MediaBrowser.Controller.Entities } } - return string.Join('/', terms.ToArray()); + return string.Join('/', terms); } /// @@ -1361,9 +1339,7 @@ namespace MediaBrowser.Controller.Entities .Select(audio => { // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio; - - if (dbItem != null) + if (LibraryManager.GetItemById(audio.Id) is Audio.Audio dbItem) { audio = dbItem; } @@ -1570,8 +1546,7 @@ namespace MediaBrowser.Controller.Entities } } - var hasTrailers = this as IHasTrailers; - if (hasTrailers != null) + if (this is IHasTrailers hasTrailers) { localTrailersChanged = await RefreshLocalTrailers(hasTrailers, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); } @@ -2268,7 +2243,11 @@ namespace MediaBrowser.Controller.Entities var existingImage = GetImageInfo(image.Type, index); - if (existingImage != null) + if (existingImage == null) + { + AddImage(image); + } + else { existingImage.Path = image.Path; existingImage.DateModified = image.DateModified; @@ -2276,15 +2255,6 @@ namespace MediaBrowser.Controller.Entities existingImage.Height = image.Height; existingImage.BlurHash = image.BlurHash; } - else - { - var current = ImageInfos; - var currentCount = current.Length; - var newArr = new ItemImageInfo[currentCount + 1]; - current.CopyTo(newArr, 0); - newArr[currentCount] = image; - ImageInfos = newArr; - } } public void SetImagePath(ImageType type, int index, FileSystemMetadata file) @@ -2298,7 +2268,7 @@ namespace MediaBrowser.Controller.Entities if (image == null) { - ImageInfos = ImageInfos.Concat(new[] { GetImageInfo(file, type) }).ToArray(); + AddImage(GetImageInfo(file, type)); } else { @@ -2342,7 +2312,7 @@ namespace MediaBrowser.Controller.Entities public void RemoveImage(ItemImageInfo image) { - RemoveImages(new List { image }); + RemoveImages(new[] { image }); } public void RemoveImages(IEnumerable deletedImages) @@ -2350,6 +2320,16 @@ namespace MediaBrowser.Controller.Entities ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } + public void AddImage(ItemImageInfo image) + { + var current = ImageInfos; + var currentCount = current.Length; + var newArr = new ItemImageInfo[currentCount + 1]; + current.CopyTo(newArr, 0); + newArr[currentCount] = image; + ImageInfos = newArr; + } + public virtual Task UpdateToRepositoryAsync(ItemUpdateType updateReason, CancellationToken cancellationToken) => LibraryManager.UpdateItemAsync(this, GetParent(), updateReason, cancellationToken); @@ -2373,7 +2353,7 @@ namespace MediaBrowser.Controller.Entities if (deletedImages.Count > 0) { - ImageInfos = ImageInfos.Except(deletedImages).ToArray(); + RemoveImages(deletedImages); } return deletedImages.Count > 0; @@ -2715,7 +2695,7 @@ namespace MediaBrowser.Controller.Entities protected static string GetMappedPath(BaseItem item, string path, MediaProtocol? protocol) { - if (protocol.HasValue && protocol.Value == MediaProtocol.File) + if (protocol == MediaProtocol.File) { return LibraryManager.GetPathAfterNetworkSubstitution(path, item); } @@ -2743,8 +2723,10 @@ namespace MediaBrowser.Controller.Entities protected Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken) { - var newOptions = new MetadataRefreshOptions(options); - newOptions.SearchResult = null; + var newOptions = new MetadataRefreshOptions(options) + { + SearchResult = null + }; var item = this; @@ -2805,8 +2787,10 @@ namespace MediaBrowser.Controller.Entities protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken) { - var newOptions = new MetadataRefreshOptions(options); - newOptions.SearchResult = null; + var newOptions = new MetadataRefreshOptions(options) + { + SearchResult = null + }; var id = LibraryManager.GetNewItemId(path, typeof(Video)); @@ -2820,14 +2804,6 @@ namespace MediaBrowser.Controller.Entities newOptions.ForceSave = true; } - // var parentId = Id; - // if (!video.IsOwnedItem || video.ParentId != parentId) - // { - // video.IsOwnedItem = true; - // video.ParentId = parentId; - // newOptions.ForceSave = true; - // } - if (video == null) { return Task.FromResult(true); @@ -2911,7 +2887,7 @@ namespace MediaBrowser.Controller.Entities .Select(i => i.OfficialRating) .Where(i => !string.IsNullOrEmpty(i)) .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(i => new Tuple(i, LocalizationManager.GetRatingLevel(i))) + .Select(i => (i, LocalizationManager.GetRatingLevel(i))) .OrderBy(i => i.Item2 ?? 1000) .Select(i => i.Item1); @@ -2958,18 +2934,6 @@ namespace MediaBrowser.Controller.Entities .Where(i => i.ExtraType.HasValue && extraTypes.Contains(i.ExtraType.Value)); } - public IEnumerable GetTrailers() - { - if (this is IHasTrailers) - { - return ((IHasTrailers)this).LocalTrailerIds.Select(LibraryManager.GetItemById).Where(i => i != null).OrderBy(i => i.SortName); - } - else - { - return Array.Empty(); - } - } - public virtual long GetRunTimeTicksForPlayState() { return RunTimeTicks ?? 0; diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 6d65ba2d7..f9ac8f46b 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -28,13 +28,13 @@ namespace Jellyfin.Providers.Tests.Manager { public class ItemImageProviderTests { - private static readonly string TestDataImagePath = "Test Data/Images/blank{0}.jpg"; + private const string TestDataImagePath = "Test Data/Images/blank{0}.jpg"; [Fact] public void ValidateImages_PhotoEmptyProviders_NoChange() { var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.ValidateImages(new Photo(), new List(), null); + var changed = itemImageProvider.ValidateImages(new Photo(), Enumerable.Empty(), null); Assert.False(changed); } @@ -43,7 +43,7 @@ namespace Jellyfin.Providers.Tests.Manager public void ValidateImages_EmptyItemEmptyProviders_NoChange() { var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.ValidateImages(new MovieWithScreenshots(), new List(), null); + var changed = itemImageProvider.ValidateImages(new MovieWithScreenshots(), Enumerable.Empty(), null); Assert.False(changed); } @@ -73,7 +73,7 @@ namespace Jellyfin.Providers.Tests.Manager var imageProvider = GetImageProvider(imageType, imageCount, true); var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.ValidateImages(item, new List { imageProvider }, null); + var changed = itemImageProvider.ValidateImages(item, new[] { imageProvider }, null); Assert.True(changed); Assert.Equal(imageCount, item.GetImages(imageType).Count()); @@ -86,7 +86,7 @@ namespace Jellyfin.Providers.Tests.Manager var item = GetItemWithImages(imageType, imageCount, true); var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.ValidateImages(item, new List(), null); + var changed = itemImageProvider.ValidateImages(item, Enumerable.Empty(), null); Assert.False(changed); Assert.Equal(imageCount, item.GetImages(imageType).Count()); @@ -99,7 +99,7 @@ namespace Jellyfin.Providers.Tests.Manager var item = GetItemWithImages(imageType, imageCount, false); var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.ValidateImages(item, new List(), null); + var changed = itemImageProvider.ValidateImages(item, Enumerable.Empty(), null); Assert.True(changed); Assert.Empty(item.GetImages(imageType)); @@ -109,7 +109,7 @@ namespace Jellyfin.Providers.Tests.Manager public void MergeImages_EmptyItemNewImagesEmpty_NoChange() { var itemImageProvider = GetItemImageProvider(null, null); - var changed = itemImageProvider.MergeImages(new MovieWithScreenshots(), new List()); + var changed = itemImageProvider.MergeImages(new MovieWithScreenshots(), Array.Empty()); Assert.False(changed); } @@ -237,7 +237,8 @@ namespace Jellyfin.Providers.Tests.Manager var refreshOptions = forceRefresh ? new ImageRefreshOptions(null) { - ImageRefreshMode = MetadataRefreshMode.FullRefresh, ReplaceAllImages = true + ImageRefreshMode = MetadataRefreshMode.FullRefresh, + ReplaceAllImages = true } : new ImageRefreshOptions(null); @@ -330,19 +331,20 @@ namespace Jellyfin.Providers.Tests.Manager var refreshOptions = forceRefresh ? new ImageRefreshOptions(null) { - ImageRefreshMode = MetadataRefreshMode.FullRefresh, ReplaceAllImages = true + ImageRefreshMode = MetadataRefreshMode.FullRefresh, + ReplaceAllImages = true } : new ImageRefreshOptions(null); - var remoteInfo = new List(); + var remoteInfo = new RemoteImageInfo[imageCount]; for (int i = 0; i < imageCount; i++) { - remoteInfo.Add(new RemoteImageInfo + remoteInfo[i] = new RemoteImageInfo { Type = imageType, Url = "image url " + i, Width = 1 // min width is set to 0, this will always pass - }); + }; } var providerManager = new Mock(MockBehavior.Strict); @@ -383,7 +385,7 @@ namespace Jellyfin.Providers.Tests.Manager // seek 2 so it won't short-circuit out of downloading when populated var libraryOptions = GetLibraryOptions(item, imageType, 2); - var content = "Content"; + const string Content = "Content"; var remoteProvider = new Mock(MockBehavior.Strict); remoteProvider.Setup(rp => rp.Name).Returns("MockRemoteProvider"); remoteProvider.Setup(rp => rp.GetSupportedImages(item)) @@ -393,7 +395,7 @@ namespace Jellyfin.Providers.Tests.Manager { ReasonPhrase = url, StatusCode = HttpStatusCode.OK, - Content = new StringContent(content, Encoding.UTF8, "image/jpeg") + Content = new StringContent(Content, Encoding.UTF8, "image/jpeg") }); var refreshOptions = fullRefresh @@ -404,15 +406,15 @@ namespace Jellyfin.Providers.Tests.Manager } : new ImageRefreshOptions(null); - var remoteInfo = new List(); + var remoteInfo = new RemoteImageInfo[targetImageCount]; for (int i = 0; i < targetImageCount; i++) { - remoteInfo.Add(new RemoteImageInfo + remoteInfo[i] = new RemoteImageInfo() { Type = imageType, Url = "image url " + i, Width = 1 // min width is set to 0, this will always pass - }); + }; } var providerManager = new Mock(MockBehavior.Strict); @@ -425,7 +427,7 @@ namespace Jellyfin.Providers.Tests.Manager var fileSystem = new Mock(); // match reported file size to image content length - condition for skipping already downloaded multi-images fileSystem.Setup(fs => fs.GetFileInfo(It.IsAny())) - .Returns(new FileSystemMetadata { Length = content.Length }); + .Returns(new FileSystemMetadata { Length = Content.Length }); var itemImageProvider = GetItemImageProvider(providerManager.Object, fileSystem); var result = await itemImageProvider.RefreshImages(item, libraryOptions, new List { remoteProvider.Object }, refreshOptions, CancellationToken.None); @@ -449,15 +451,16 @@ namespace Jellyfin.Providers.Tests.Manager var refreshOptions = new ImageRefreshOptions(null); // populate remote with double the required images to verify count is trimmed to the library option count - var remoteInfo = new List(); - for (int i = 0; i < imageCount * 2; i++) + var remoteInfoCount = imageCount * 2; + var remoteInfo = new RemoteImageInfo[remoteInfoCount]; + for (int i = 0; i < remoteInfoCount; i++) { - remoteInfo.Add(new RemoteImageInfo + remoteInfo[i] = new RemoteImageInfo() { Type = imageType, Url = "image url " + i, Width = 1 // min width is set to 0, this will always pass - }); + }; } var providerManager = new Mock(MockBehavior.Strict); @@ -552,20 +555,20 @@ namespace Jellyfin.Providers.Tests.Manager /// /// Creates a list of references of the specified type and size, optionally pointing to files that exist. /// - private static List GetImages(ImageType type, int count, bool validPaths) + private static LocalImageInfo[] GetImages(ImageType type, int count, bool validPaths) { var path = validPaths ? TestDataImagePath : "invalid path {0}"; - var images = new List(count); + var images = new LocalImageInfo[count]; for (int i = 0; i < count; i++) { - images.Add(new LocalImageInfo + images[i] = new LocalImageInfo { Type = type, FileInfo = new FileSystemMetadata { FullName = string.Format(CultureInfo.InvariantCulture, path, i) } - }); + }; } return images; -- cgit v1.2.3 From b4bf5af7c8b169c616ca5a9bc83248a80636bedb Mon Sep 17 00:00:00 2001 From: Joe Rogers <1337joe@gmail.com> Date: Fri, 5 Nov 2021 21:31:12 +0100 Subject: Remove ImageType.Screenshot and ItemFields.Screenshot --- Emby.Server.Implementations/Dto/DtoService.cs | 9 -------- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Model/Entities/ImageType.cs | 3 +++ MediaBrowser.Model/Querying/ItemFields.cs | 3 +++ MediaBrowser.Providers/Manager/ImageSaver.cs | 3 --- .../Manager/ItemImageProvider.cs | 26 +++------------------- .../Manager/ItemImageProviderTests.cs | 2 -- 7 files changed, 10 insertions(+), 38 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index ad76f3d6d..9287f5272 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -755,15 +755,6 @@ namespace Emby.Server.Implementations.Dto dto.BackdropImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Backdrop, backdropLimit); } - if (options.ContainsField(ItemFields.ScreenshotImageTags)) - { - var screenshotLimit = options.GetImageLimit(ImageType.Screenshot); - if (screenshotLimit > 0) - { - dto.ScreenshotImageTags = GetTagsAndFillBlurhashes(dto, item, ImageType.Screenshot, screenshotLimit); - } - } - if (options.ContainsField(ItemFields.Genres)) { dto.Genres = item.Genres; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 0df70705e..63749b1f3 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2577,7 +2577,7 @@ namespace MediaBrowser.Controller.Entities public bool AllowsMultipleImages(ImageType type) { - return type == ImageType.Backdrop || type == ImageType.Screenshot || type == ImageType.Chapter; + return type == ImageType.Backdrop || type == ImageType.Chapter; } public Task SwapImagesAsync(ImageType type, int index1, int index2) diff --git a/MediaBrowser.Model/Entities/ImageType.cs b/MediaBrowser.Model/Entities/ImageType.cs index 6ea9ee419..ee7410632 100644 --- a/MediaBrowser.Model/Entities/ImageType.cs +++ b/MediaBrowser.Model/Entities/ImageType.cs @@ -1,3 +1,5 @@ +using System; + namespace MediaBrowser.Model.Entities { /// @@ -48,6 +50,7 @@ namespace MediaBrowser.Model.Entities /// /// The screenshot. /// + [Obsolete("Screenshot image type is no longer used.")] Screenshot = 8, /// diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index ef4698f3f..e6c3a6c26 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -1,5 +1,7 @@ #pragma warning disable CS1591 +using System; + namespace MediaBrowser.Model.Querying { /// @@ -143,6 +145,7 @@ namespace MediaBrowser.Model.Querying /// /// The screenshot image tags. /// + [Obsolete("Screenshot image type is no longer used.")] ScreenshotImageTags, SeriesPrimaryImage, diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 8ded2d144..d2a3344be 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -439,9 +439,6 @@ namespace MediaBrowser.Providers.Manager case ImageType.Backdrop: filename = GetBackdropSaveFilename(item.GetImages(type), "backdrop", "backdrop", imageIndex); break; - case ImageType.Screenshot: - filename = GetBackdropSaveFilename(item.GetImages(type), "screenshot", "screenshot", imageIndex); - break; default: filename = type.ToString().ToLowerInvariant(); break; diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index d5959db77..1022a3fae 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -109,12 +109,6 @@ namespace MediaBrowser.Providers.Manager oldBackdropImages = item.GetImages(ImageType.Backdrop).ToArray(); } - var oldScreenshotImages = Array.Empty(); - if (refreshOptions.IsReplacingImage(ImageType.Screenshot)) - { - oldScreenshotImages = item.GetImages(ImageType.Screenshot).ToArray(); - } - var result = new RefreshResult { UpdateType = ItemUpdateType.None }; var typeName = item.GetType().Name; @@ -122,14 +116,13 @@ namespace MediaBrowser.Providers.Manager // track library limits, adding buffer to allow lazy replacing of current images var backdropLimit = typeOptions.GetLimit(ImageType.Backdrop) + oldBackdropImages.Length; - var screenshotLimit = typeOptions.GetLimit(ImageType.Screenshot) + oldScreenshotImages.Length; var downloadedImages = new List(); foreach (var provider in providers) { if (provider is IRemoteImageProvider remoteProvider) { - await RefreshFromProvider(item, remoteProvider, refreshOptions, typeOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false); + await RefreshFromProvider(item, remoteProvider, refreshOptions, typeOptions, backdropLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false); continue; } @@ -145,11 +138,6 @@ namespace MediaBrowser.Providers.Manager PruneImages(item, oldBackdropImages); } - if (oldScreenshotImages.Length > 0 && oldScreenshotImages.Length < item.GetImages(ImageType.Screenshot).Count()) - { - PruneImages(item, oldScreenshotImages); - } - return result; } @@ -243,9 +231,8 @@ namespace MediaBrowser.Providers.Manager /// The images. /// The saved options. /// The backdrop limit. - /// The screenshot limit. /// true if the specified item contains images; otherwise, false. - private bool ContainsImages(BaseItem item, List images, TypeOptions savedOptions, int backdropLimit, int screenshotLimit) + private bool ContainsImages(BaseItem item, List images, TypeOptions savedOptions, int backdropLimit) { // Using .Any causes the creation of a DisplayClass aka. variable capture for (var i = 0; i < _singularImages.Length; i++) @@ -262,11 +249,6 @@ namespace MediaBrowser.Providers.Manager return false; } - if (images.Contains(ImageType.Screenshot) && item.GetImages(ImageType.Screenshot).Count() < screenshotLimit) - { - return false; - } - return true; } @@ -278,7 +260,6 @@ namespace MediaBrowser.Providers.Manager /// The refresh options. /// The saved options. /// The backdrop limit. - /// The screenshot limit. /// The downloaded images. /// The result. /// The cancellation token. @@ -289,7 +270,6 @@ namespace MediaBrowser.Providers.Manager ImageRefreshOptions refreshOptions, TypeOptions savedOptions, int backdropLimit, - int screenshotLimit, ICollection downloadedImages, RefreshResult result, CancellationToken cancellationToken) @@ -303,7 +283,7 @@ namespace MediaBrowser.Providers.Manager if (!refreshOptions.ReplaceAllImages && refreshOptions.ReplaceImages.Length == 0 && - ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit, screenshotLimit)) + ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit)) { return; } diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 6011c8dd5..9f73ed7fc 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -207,10 +207,8 @@ namespace Jellyfin.Providers.Tests.Manager [Theory] [InlineData(ImageType.Primary, 1, false)] [InlineData(ImageType.Backdrop, 2, false)] - [InlineData(ImageType.Screenshot, 2, false)] [InlineData(ImageType.Primary, 1, true)] [InlineData(ImageType.Backdrop, 2, true)] - [InlineData(ImageType.Screenshot, 2, true)] public async void RefreshImages_PopulatedItemPopulatedProviderDynamic_UpdatesImagesIfForced(ImageType imageType, int imageCount, bool forceRefresh) { var item = GetItemWithImages(imageType, imageCount, false); -- cgit v1.2.3 From 5726535a262ce5f671bb0b74dd00c485d17633f0 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 9 Nov 2021 13:14:31 +0100 Subject: Fix some warnings 609 left --- Emby.Naming/Common/NamingOptions.cs | 2 ++ Emby.Server.Implementations/Dto/DtoService.cs | 2 +- Emby.Server.Implementations/IO/LibraryMonitor.cs | 2 +- Emby.Server.Implementations/Library/LibraryManager.cs | 14 +++++++------- .../Library/Validators/PeopleValidator.cs | 2 +- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 8 ++++---- .../LiveTv/EmbyTV/EncodedRecorder.cs | 12 ++++++------ Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs | 2 +- Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 6 +++--- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../ScheduledTasks/Tasks/DeleteCacheFileTask.cs | 8 ++++---- .../ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs | 8 ++++---- Jellyfin.Api/Controllers/DynamicHlsController.cs | 6 +++--- Jellyfin.Api/Controllers/SubtitleController.cs | 2 +- Jellyfin.Server.Implementations/Events/EventManager.cs | 2 +- Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs | 2 +- Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs | 2 +- Jellyfin.Server/Program.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 2 +- MediaBrowser.Controller/IO/FileData.cs | 4 ++-- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 2 +- MediaBrowser.Providers/Manager/ItemImageProvider.cs | 4 ++-- MediaBrowser.Providers/Manager/MetadataService.cs | 6 +++--- MediaBrowser.XbmcMetadata/EntryPoint.cs | 2 +- jellyfin.ruleset | 6 ++++++ .../Controllers/DashboardControllerTests.cs | 2 +- 27 files changed, 61 insertions(+), 53 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 5ddcf37fe..7bc9fbce8 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1819 + using System; using System.Linq; using System.Text.RegularExpressions; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 9287f5272..c6b32a52c 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -497,7 +497,7 @@ namespace Emby.Server.Implementations.Dto } catch (Exception ex) { - _logger.LogError(ex, "Error getting {imageType} image info for {path}", image.Type, image.Path); + _logger.LogError(ex, "Error getting {ImageType} image info for {Path}", image.Type, image.Path); return null; } } diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index e9d069cd3..7ebc800b9 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -276,7 +276,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - _logger.LogError(ex, "Error watching path: {path}", path); + _logger.LogError(ex, "Error watching path: {Path}", path); } }); } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 1326f60fe..2dbb569c6 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -492,7 +492,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error in {resolver} resolving {path}", resolver.GetType().Name, args.Path); + _logger.LogError(ex, "Error in {Resolver} resolving {Path}", resolver.GetType().Name, args.Path); return null; } } @@ -799,7 +799,7 @@ namespace Emby.Server.Implementations.Library { var userRootPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath; - _logger.LogDebug("Creating userRootPath at {path}", userRootPath); + _logger.LogDebug("Creating userRootPath at {Path}", userRootPath); Directory.CreateDirectory(userRootPath); var newItemId = GetNewItemId(userRootPath, typeof(UserRootFolder)); @@ -810,7 +810,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error creating UserRootFolder {path}", newItemId); + _logger.LogError(ex, "Error creating UserRootFolder {Path}", newItemId); } if (tmpItem == null) @@ -827,7 +827,7 @@ namespace Emby.Server.Implementations.Library } _userRootFolder = tmpItem; - _logger.LogDebug("Setting userRootFolder: {folder}", _userRootFolder); + _logger.LogDebug("Setting userRootFolder: {Folder}", _userRootFolder); } } } @@ -1213,7 +1213,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error resolving shortcut file {file}", i); + _logger.LogError(ex, "Error resolving shortcut file {File}", i); return null; } }) @@ -1698,7 +1698,7 @@ namespace Emby.Server.Implementations.Library if (video == null) { - _logger.LogError("Intro resolver returned null for {path}.", info.Path); + _logger.LogError("Intro resolver returned null for {Path}.", info.Path); } else { @@ -1717,7 +1717,7 @@ namespace Emby.Server.Implementations.Library } catch (Exception ex) { - _logger.LogError(ex, "Error resolving path {path}.", info.Path); + _logger.LogError(ex, "Error resolving path {Path}.", info.Path); } } else diff --git a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs index 8739a9e1b..8a9a4b865 100644 --- a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -78,7 +78,7 @@ namespace Emby.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.LogError(ex, "Error validating IBN entry {person}", person); + _logger.LogError(ex, "Error validating IBN entry {Person}", person); } // Update progress diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 980b42729..e5abb523c 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1308,16 +1308,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV await recorder.Record(directStreamProvider, mediaStreamInfo, recordPath, duration, onStarted, activeRecordingInfo.CancellationTokenSource.Token).ConfigureAwait(false); recordingStatus = RecordingStatus.Completed; - _logger.LogInformation("Recording completed: {recordPath}", recordPath); + _logger.LogInformation("Recording completed: {RecordPath}", recordPath); } catch (OperationCanceledException) { - _logger.LogInformation("Recording stopped: {recordPath}", recordPath); + _logger.LogInformation("Recording stopped: {RecordPath}", recordPath); recordingStatus = RecordingStatus.Completed; } catch (Exception ex) { - _logger.LogError(ex, "Error recording to {recordPath}", recordPath); + _logger.LogError(ex, "Error recording to {RecordPath}", recordPath); recordingStatus = RecordingStatus.Error; } @@ -1404,7 +1404,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError(ex, "Error deleting 0-byte failed recording file {path}", path); + _logger.LogError(ex, "Error deleting 0-byte failed recording file {Path}", path); } } } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 835028b92..8688688e9 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -225,13 +225,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { try { - _logger.LogInformation("Stopping ffmpeg recording process for {path}", _targetPath); + _logger.LogInformation("Stopping ffmpeg recording process for {Path}", _targetPath); _process.StandardInput.WriteLine("q"); } catch (Exception ex) { - _logger.LogError(ex, "Error stopping recording transcoding job for {path}", _targetPath); + _logger.LogError(ex, "Error stopping recording transcoding job for {Path}", _targetPath); } if (_hasExited) @@ -241,7 +241,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - _logger.LogInformation("Calling recording process.WaitForExit for {path}", _targetPath); + _logger.LogInformation("Calling recording process.WaitForExit for {Path}", _targetPath); if (_process.WaitForExit(10000)) { @@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } catch (Exception ex) { - _logger.LogError(ex, "Error waiting for recording process to exit for {path}", _targetPath); + _logger.LogError(ex, "Error waiting for recording process to exit for {Path}", _targetPath); } if (_hasExited) @@ -260,13 +260,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV try { - _logger.LogInformation("Killing ffmpeg recording process for {path}", _targetPath); + _logger.LogInformation("Killing ffmpeg recording process for {Path}", _targetPath); _process.Kill(); } catch (Exception ex) { - _logger.LogError(ex, "Error killing recording transcoding job for {path}", _targetPath); + _logger.LogError(ex, "Error killing recording transcoding job for {Path}", _targetPath); } } } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 21e1409ac..598e3f88a 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -393,7 +393,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError(ex, "Error getting image info for {name}", info.Name); + _logger.LogError(ex, "Error getting image info for {Name}", info.Name); } return null; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index ea1a28fe8..a41b63f28 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1054,7 +1054,7 @@ namespace Emby.Server.Implementations.LiveTv { cancellationToken.ThrowIfCancellationRequested(); - _logger.LogDebug("Refreshing guide from {name}", service.Name); + _logger.LogDebug("Refreshing guide from {Name}", service.Name); try { @@ -1135,7 +1135,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError(ex, "Error getting channel information for {name}", channelInfo.Item2.Name); + _logger.LogError(ex, "Error getting channel information for {Name}", channelInfo.Item2.Name); } numComplete++; @@ -1248,7 +1248,7 @@ namespace Emby.Server.Implementations.LiveTv } catch (Exception ex) { - _logger.LogError(ex, "Error getting programs for channel {name}", currentChannel.Name); + _logger.LogError(ex, "Error getting programs for channel {Name}", currentChannel.Name); } numComplete++; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 31445e1ec..b621055d8 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -82,7 +82,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun Directory.CreateDirectory(Path.GetDirectoryName(TempFilePath)); - Logger.LogInformation("Opening HDHR UDP Live stream from {host}", uri.Host); + Logger.LogInformation("Opening HDHR UDP Live stream from {Host}", uri.Host); var remoteAddress = IPAddress.Parse(uri.Host); IPAddress localAddress = null; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index a575b260c..0941902fc 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -161,11 +161,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } } } @@ -179,11 +179,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs index b13fc7fc6..099d781cd 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs @@ -141,11 +141,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting directory {path}", directory); + _logger.LogError(ex, "Error deleting directory {Path}", directory); } } } @@ -159,11 +159,11 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } catch (UnauthorizedAccessException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } catch (IOException ex) { - _logger.LogError(ex, "Error deleting file {path}", path); + _logger.LogError(ex, "Error deleting file {Path}", path); } } } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 475b80464..049fd503b 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1794,7 +1794,7 @@ namespace Jellyfin.Api.Controllers return; } - _logger.LogDebug("Deleting partial HLS file {path}", path); + _logger.LogDebug("Deleting partial HLS file {Path}", path); try { @@ -1802,7 +1802,7 @@ namespace Jellyfin.Api.Controllers } catch (IOException ex) { - _logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); + _logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path); var task = Task.Delay(100); task.Wait(); @@ -1810,7 +1810,7 @@ namespace Jellyfin.Api.Controllers } catch (Exception ex) { - _logger.LogError(ex, "Error deleting partial stream file(s) {path}", path); + _logger.LogError(ex, "Error deleting partial stream file(s) {Path}", path); } } diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index db8307f28..16acedcf3 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -528,7 +528,7 @@ namespace Jellyfin.Api.Controllers if (fontFile != null && fileSize != null && fileSize > 0) { - _logger.LogDebug("Fallback font size is {fileSize} Bytes", fileSize); + _logger.LogDebug("Fallback font size is {FileSize} Bytes", fileSize); return PhysicalFile(fontFile.FullName, MimeTypes.GetMimeType(fontFile.FullName)); } else diff --git a/Jellyfin.Server.Implementations/Events/EventManager.cs b/Jellyfin.Server.Implementations/Events/EventManager.cs index 8c5d8f2ce..7f7c4750d 100644 --- a/Jellyfin.Server.Implementations/Events/EventManager.cs +++ b/Jellyfin.Server.Implementations/Events/EventManager.cs @@ -57,7 +57,7 @@ namespace Jellyfin.Server.Implementations.Events } catch (Exception e) { - _logger.LogError(e, "Uncaught exception in EventConsumer {type}: ", service.GetType()); + _logger.LogError(e, "Uncaught exception in EventConsumer {Type}: ", service.GetType()); } } } diff --git a/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs b/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs index 74874da1b..da9b69136 100644 --- a/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs +++ b/Jellyfin.Server/Middleware/ResponseTimeMiddleware.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Server.Middleware if (_enableWarning && watch.ElapsedMilliseconds > _warningThreshold) { _logger.LogWarning( - "Slow HTTP Response from {url} to {remoteIp} in {elapsed:g} with Status Code {statusCode}", + "Slow HTTP Response from {Url} to {RemoteIp} in {Elapsed:g} with Status Code {StatusCode}", context.Request.GetDisplayUrl(), context.GetNormalizedRemoteIp(), watch.Elapsed, diff --git a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs index e4d2937e7..2f1d79157 100644 --- a/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs +++ b/Jellyfin.Server/Middleware/UrlDecodeQueryFeature.cs @@ -51,7 +51,7 @@ namespace Jellyfin.Server.Middleware return; } - if (!key.Contains('=')) + if (!key.Contains('=', StringComparison.Ordinal)) { _store = value; return; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 5c7012d58..6e4c2280b 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -675,7 +675,7 @@ namespace Jellyfin.Server private static string NormalizeCommandLineArgument(string arg) { - if (!arg.Contains(" ", StringComparison.OrdinalIgnoreCase)) + if (!arg.Contains(' ', StringComparison.Ordinal)) { return arg; } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 63749b1f3..a76ca2305 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1452,7 +1452,7 @@ namespace MediaBrowser.Controller.Entities } catch (Exception ex) { - Logger.LogError(ex, "Error refreshing owned items for {path}", Path ?? Name); + Logger.LogError(ex, "Error refreshing owned items for {Path}", Path ?? Name); } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index fc6380e1a..ffd1c7f0a 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -303,7 +303,7 @@ namespace MediaBrowser.Controller.Entities if (dictionary.ContainsKey(id)) { Logger.LogError( - "Found folder containing items with duplicate id. Path: {path}, Child Name: {ChildName}", + "Found folder containing items with duplicate id. Path: {Path}, Child Name: {ChildName}", Path ?? Name, child.Path ?? child.Name); } diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index b8a0bf331..2429ac42d 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Controller.IO if (string.IsNullOrEmpty(newPath)) { // invalid shortcut - could be old or target could just be unavailable - logger.LogWarning("Encountered invalid shortcut: " + fullName); + logger.LogWarning("Encountered invalid shortcut: {Path}", fullName); continue; } @@ -83,7 +83,7 @@ namespace MediaBrowser.Controller.IO } catch (Exception ex) { - logger.LogError(ex, "Error resolving shortcut from {path}", fullName); + logger.LogError(ex, "Error resolving shortcut from {Path}", fullName); } } else if (flattenFolderDepth > 0 && isDirectory) diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 5e7af23fc..1a8b5bb4e 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -144,7 +144,7 @@ namespace MediaBrowser.LocalMetadata.Savers } catch (Exception ex) { - Logger.LogError(ex, "Error setting hidden attribute on {path}", path); + Logger.LogError(ex, "Error setting hidden attribute on {Path}", path); } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 1022a3fae..5e1985611 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -215,7 +215,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError(ex, "Error in {provider}", provider.Name); + _logger.LogError(ex, "Error in {Provider}", provider.Name); } } @@ -331,7 +331,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { result.ErrorMessage = ex.Message; - _logger.LogError(ex, "Error in {provider}", provider.Name); + _logger.LogError(ex, "Error in {Provider}", provider.Name); } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index ffb3baeb1..90d14a973 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -713,7 +713,7 @@ namespace MediaBrowser.Providers.Manager } catch (Exception ex) { - Logger.LogError(ex, "Error in {provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider}", provider.Name); // If a local provider fails, consider that a failure refreshResult.ErrorMessage = ex.Message; @@ -785,7 +785,7 @@ namespace MediaBrowser.Providers.Manager catch (Exception ex) { refreshResult.ErrorMessage = ex.Message; - Logger.LogError(ex, "Error in {provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider}", provider.Name); } } @@ -837,7 +837,7 @@ namespace MediaBrowser.Providers.Manager { refreshResult.Failures++; refreshResult.ErrorMessage = ex.Message; - Logger.LogError(ex, "Error in {provider}", provider.Name); + Logger.LogError(ex, "Error in {Provider}", provider.Name); } } diff --git a/MediaBrowser.XbmcMetadata/EntryPoint.cs b/MediaBrowser.XbmcMetadata/EntryPoint.cs index d02aea556..935ff5f59 100644 --- a/MediaBrowser.XbmcMetadata/EntryPoint.cs +++ b/MediaBrowser.XbmcMetadata/EntryPoint.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.XbmcMetadata } catch (Exception ex) { - _logger.LogError(ex, "Error saving metadata for {path}", item.Path ?? item.Name); + _logger.LogError(ex, "Error saving metadata for {Path}", item.Path ?? item.Name); } } } diff --git a/jellyfin.ruleset b/jellyfin.ruleset index dfb991170..3bced438c 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -42,6 +42,8 @@ + + @@ -77,6 +79,8 @@ + + @@ -90,6 +94,8 @@ + + diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs index 827365363..3396a94e5 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DashboardControllerTests.cs @@ -40,7 +40,7 @@ namespace Jellyfin.Server.Integration.Tests.Controllers Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(MediaTypeNames.Text.Html, response.Content.Headers.ContentType?.MediaType); StreamReader reader = new StreamReader(typeof(TestPlugin).Assembly.GetManifestResourceStream("Jellyfin.Server.Integration.Tests.TestPage.html")!); - Assert.Equal(await response.Content.ReadAsStringAsync(), reader.ReadToEnd()); + Assert.Equal(await response.Content.ReadAsStringAsync().ConfigureAwait(false), await reader.ReadToEndAsync().ConfigureAwait(false)); } [Fact] -- cgit v1.2.3 From 257e1be95f2b3be629501a95f6a7c5da083697fd Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Tue, 16 Nov 2021 16:31:57 +0100 Subject: Fix some warnings --- .../Channels/ChannelManager.cs | 8 -------- Jellyfin.Api/Attributes/AcceptsFileAttribute.cs | 4 +++- .../Attributes/AcceptsImageFileAttribute.cs | 2 +- Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs | 2 +- .../Attributes/HttpUnsubscribeAttribute.cs | 2 +- .../Attributes/ParameterObsoleteAttribute.cs | 2 +- .../Attributes/ProducesAudioFileAttribute.cs | 2 +- Jellyfin.Api/Attributes/ProducesFileAttribute.cs | 4 +++- .../Attributes/ProducesImageFileAttribute.cs | 2 +- .../Attributes/ProducesPlaylistFileAttribute.cs | 2 +- .../Attributes/ProducesVideoFileAttribute.cs | 2 +- MediaBrowser.Controller/Entities/Audio/Audio.cs | 8 ++------ MediaBrowser.Controller/Entities/BaseItem.cs | 12 ++---------- MediaBrowser.Controller/Entities/Video.cs | 22 +++++++++++----------- MediaBrowser.Model/Net/MimeTypes.cs | 2 +- jellyfin.ruleset | 4 ++++ 16 files changed, 34 insertions(+), 46 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 09aee602a..f65eaec1c 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -1075,14 +1075,6 @@ namespace Emby.Server.Implementations.Channels forceUpdate = true; } - // was used for status - // if (!string.Equals(item.ExternalEtag ?? string.Empty, info.Etag ?? string.Empty, StringComparison.Ordinal)) - // { - // item.ExternalEtag = info.Etag; - // forceUpdate = true; - // _logger.LogDebug("Forcing update due to ExternalEtag {0}", item.Name); - // } - if (!internalChannelId.Equals(item.ChannelId)) { forceUpdate = true; diff --git a/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs b/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs index 49b6689cd..58552d847 100644 --- a/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs +++ b/Jellyfin.Api/Attributes/AcceptsFileAttribute.cs @@ -1,4 +1,6 @@ -using System; +#pragma warning disable CA1813 // Avoid unsealed attributes + +using System; namespace Jellyfin.Api.Attributes { diff --git a/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs b/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs index 001f27409..244a29da4 100644 --- a/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs +++ b/Jellyfin.Api/Attributes/AcceptsImageFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class AcceptsImageFileAttribute : AcceptsFileAttribute + public sealed class AcceptsImageFileAttribute : AcceptsFileAttribute { private const string ContentType = "image/*"; diff --git a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs index 2fdd1e489..af8727552 100644 --- a/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpSubscribeAttribute.cs @@ -7,7 +7,7 @@ namespace Jellyfin.Api.Attributes /// /// Identifies an action that supports the HTTP GET method. /// - public class HttpSubscribeAttribute : HttpMethodAttribute + public sealed class HttpSubscribeAttribute : HttpMethodAttribute { private static readonly IEnumerable _supportedMethods = new[] { "SUBSCRIBE" }; diff --git a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs index d6d7e4563..1c0b70e71 100644 --- a/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs +++ b/Jellyfin.Api/Attributes/HttpUnsubscribeAttribute.cs @@ -7,7 +7,7 @@ namespace Jellyfin.Api.Attributes /// /// Identifies an action that supports the HTTP GET method. /// - public class HttpUnsubscribeAttribute : HttpMethodAttribute + public sealed class HttpUnsubscribeAttribute : HttpMethodAttribute { private static readonly IEnumerable _supportedMethods = new[] { "UNSUBSCRIBE" }; diff --git a/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs b/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs index 56c9772b6..514e7ce97 100644 --- a/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs +++ b/Jellyfin.Api/Attributes/ParameterObsoleteAttribute.cs @@ -6,7 +6,7 @@ namespace Jellyfin.Api.Attributes /// Attribute to mark a parameter as obsolete. /// [AttributeUsage(AttributeTargets.Parameter)] - public class ParameterObsoleteAttribute : Attribute + public sealed class ParameterObsoleteAttribute : Attribute { } } diff --git a/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs index 3adb700eb..9fc25f192 100644 --- a/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class ProducesAudioFileAttribute : ProducesFileAttribute + public sealed class ProducesAudioFileAttribute : ProducesFileAttribute { private const string ContentType = "audio/*"; diff --git a/Jellyfin.Api/Attributes/ProducesFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesFileAttribute.cs index 62a576ede..2bf77d729 100644 --- a/Jellyfin.Api/Attributes/ProducesFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesFileAttribute.cs @@ -1,4 +1,6 @@ -using System; +#pragma warning disable CA1813 // Avoid unsealed attributes + +using System; namespace Jellyfin.Api.Attributes { diff --git a/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs index e15813676..1e5b542e2 100644 --- a/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class ProducesImageFileAttribute : ProducesFileAttribute + public sealed class ProducesImageFileAttribute : ProducesFileAttribute { private const string ContentType = "image/*"; diff --git a/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs index 5d928ab91..5b15cb1a5 100644 --- a/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "image/*". /// - public class ProducesPlaylistFileAttribute : ProducesFileAttribute + public sealed class ProducesPlaylistFileAttribute : ProducesFileAttribute { private const string ContentType = "application/x-mpegURL"; diff --git a/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs index d8b2856dc..6857d45ec 100644 --- a/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs +++ b/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs @@ -3,7 +3,7 @@ /// /// Produces file attribute of "video/*". /// - public class ProducesVideoFileAttribute : ProducesFileAttribute + public sealed class ProducesVideoFileAttribute : ProducesFileAttribute { private const string ContentType = "video/*"; diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 536668e50..30111a9af 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -146,11 +146,7 @@ namespace MediaBrowser.Controller.Entities.Audio return info; } - protected override List> GetAllItemsForMediaSources() - { - var list = new List>(); - list.Add(new Tuple(this, MediaSourceType.Default)); - return list; - } + protected override IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() + => new[] { ((BaseItem)this, MediaSourceType.Default) }; } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index a76ca2305..b1ac2fe8e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Text; using System.Text.Json.Serialization; @@ -333,13 +332,6 @@ namespace MediaBrowser.Controller.Entities [JsonIgnore] public string ExternalSeriesId { get; set; } - /// - /// Gets or sets the etag. - /// - /// The etag. - [JsonIgnore] - public string ExternalEtag { get; set; } - [JsonIgnore] public virtual bool IsHidden => false; @@ -1161,9 +1153,9 @@ namespace MediaBrowser.Controller.Entities .ToList(); } - protected virtual List> GetAllItemsForMediaSources() + protected virtual IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() { - return new List>(); + return Enumerable.Empty<(BaseItem, MediaSourceType)>(); } private MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, BaseItem item, MediaSourceType type) diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 7dd95b85c..de42c67d3 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -509,35 +509,35 @@ namespace MediaBrowser.Controller.Entities }).FirstOrDefault(); } - protected override List> GetAllItemsForMediaSources() + protected override IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() { - var list = new List>(); + var list = new List<(BaseItem, MediaSourceType)> + { + (this, MediaSourceType.Default) + }; - list.Add(new Tuple(this, MediaSourceType.Default)); - list.AddRange(GetLinkedAlternateVersions().Select(i => new Tuple(i, MediaSourceType.Grouping))); + list.AddRange(GetLinkedAlternateVersions().Select(i => ((BaseItem)i, MediaSourceType.Grouping))); if (!string.IsNullOrEmpty(PrimaryVersionId)) { - var primary = LibraryManager.GetItemById(PrimaryVersionId) as Video; - if (primary != null) + if (LibraryManager.GetItemById(PrimaryVersionId) is Video primary) { var existingIds = list.Select(i => i.Item1.Id).ToList(); - list.Add(new Tuple(primary, MediaSourceType.Grouping)); - list.AddRange(primary.GetLinkedAlternateVersions().Where(i => !existingIds.Contains(i.Id)).Select(i => new Tuple(i, MediaSourceType.Grouping))); + list.Add((primary, MediaSourceType.Grouping)); + list.AddRange(primary.GetLinkedAlternateVersions().Where(i => !existingIds.Contains(i.Id)).Select(i => ((BaseItem)i, MediaSourceType.Grouping))); } } var localAlternates = list .SelectMany(i => { - var video = i.Item1 as Video; - return video == null ? new List() : video.GetLocalAlternateVersionIds(); + return i.Item1 is Video video ? video.GetLocalAlternateVersionIds() : Enumerable.Empty(); }) .Select(LibraryManager.GetItemById) .Where(i => i != null) .ToList(); - list.AddRange(localAlternates.Select(i => new Tuple(i, MediaSourceType.Default))); + list.AddRange(localAlternates.Select(i => (i, MediaSourceType.Default))); return list; } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index 748170a0e..043cee2a2 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -191,7 +191,7 @@ namespace MediaBrowser.Model.Net // Catch-all for all video types that don't require specific mime types if (_videoFileExtensions.Contains(ext)) { - return "video/" + ext.Substring(1); + return string.Concat("video/", ext.AsSpan(1)); } // Type text diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 469f61021..7adc35087 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -50,8 +50,12 @@ + + + + -- cgit v1.2.3 From fde84a1e00b0c781ce10acc73a9103db51aab67b Mon Sep 17 00:00:00 2001 From: cvium Date: Tue, 7 Dec 2021 15:18:17 +0100 Subject: Refactor extras parsing --- Emby.Naming/AudioBook/AudioBookListResolver.cs | 10 +- Emby.Naming/Common/NamingOptions.cs | 12 +- Emby.Naming/Video/ExtraResolver.cs | 103 ++++++--- Emby.Naming/Video/FileStack.cs | 5 + Emby.Naming/Video/StackResolver.cs | 77 +++---- Emby.Naming/Video/VideoInfo.cs | 13 +- Emby.Naming/Video/VideoListResolver.cs | 169 +++------------ Emby.Naming/Video/VideoResolver.cs | 7 +- .../Library/LibraryManager.cs | 122 ++++------- .../Library/Resolvers/BaseVideoResolver.cs | 121 ++++------- .../Library/Resolvers/Movies/MovieResolver.cs | 103 +++++---- .../Library/Resolvers/TV/EpisodeResolver.cs | 44 ++-- Jellyfin.Api/Controllers/UserLibraryController.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 235 ++------------------- MediaBrowser.Controller/Entities/IHasTrailers.cs | 68 +----- MediaBrowser.Controller/Entities/Movies/BoxSet.cs | 12 +- MediaBrowser.Controller/Entities/Movies/Movie.cs | 80 ++----- MediaBrowser.Controller/Entities/TV/Episode.cs | 14 +- MediaBrowser.Controller/Entities/TV/Series.cs | 10 +- .../Entities/UserViewBuilder.cs | 9 +- MediaBrowser.Controller/Library/ILibraryManager.cs | 17 +- .../Images/LocalImageProvider.cs | 23 +- tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs | 11 +- .../Video/MultiVersionTests.cs | 20 +- tests/Jellyfin.Naming.Tests/Video/StackTests.cs | 93 ++------ .../Video/VideoListResolverTests.cs | 107 ++++++---- .../Library/EpisodeResolverTest.cs | 13 +- .../Library/LibraryManager/FindExtrasTests.cs | 178 ++++++++++++++++ 28 files changed, 681 insertions(+), 997 deletions(-) create mode 100644 tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Naming/AudioBook/AudioBookListResolver.cs b/Emby.Naming/AudioBook/AudioBookListResolver.cs index 1e4a8d2ed..dd8a05bb3 100644 --- a/Emby.Naming/AudioBook/AudioBookListResolver.cs +++ b/Emby.Naming/AudioBook/AudioBookListResolver.cs @@ -14,6 +14,7 @@ namespace Emby.Naming.AudioBook public class AudioBookListResolver { private readonly NamingOptions _options; + private readonly AudioBookResolver _audioBookResolver; /// /// Initializes a new instance of the class. @@ -22,6 +23,7 @@ namespace Emby.Naming.AudioBook public AudioBookListResolver(NamingOptions options) { _options = options; + _audioBookResolver = new AudioBookResolver(_options); } /// @@ -31,21 +33,19 @@ namespace Emby.Naming.AudioBook /// Returns IEnumerable of . public IEnumerable Resolve(IEnumerable files) { - var audioBookResolver = new AudioBookResolver(_options); // File with empty fullname will be sorted out here. var audiobookFileInfos = files - .Select(i => audioBookResolver.Resolve(i.FullName)) + .Select(i => _audioBookResolver.Resolve(i.FullName)) .OfType() .ToList(); - var stackResult = new StackResolver(_options) - .ResolveAudioBooks(audiobookFileInfos); + var stackResult = StackResolver.ResolveAudioBooks(audiobookFileInfos); foreach (var stack in stackResult) { var stackFiles = stack.Files - .Select(i => audioBookResolver.Resolve(i)) + .Select(i => _audioBookResolver.Resolve(i)) .OfType() .ToList(); diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index 7bc9fbce8..86c79166d 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -126,9 +126,9 @@ namespace Emby.Naming.Common VideoFileStackingExpressions = new[] { - "(?.*?)(?<volume>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[0-9]+)(?<ignore>.*?)(?<extension>\\.[^.]+)$", - "(?<title>.*?)(?<volume>[ _.-]*(?:cd|dvd|p(?:ar)?t|dis[ck])[ _.-]*[a-d])(?<ignore>.*?)(?<extension>\\.[^.]+)$", - "(?<title>.*?)(?<volume>[ ._-]*[a-d])(?<ignore>.*?)(?<extension>\\.[^.]+)$" + "^(?<title>.*?)(?<volume>[ _.-]*(?:cd|dvd|part|pt|dis[ck])[ _.-]*[0-9]+)(?<ignore>.*?)(?<extension>\\.[^.]+)$", + "^(?<title>.*?)(?<volume>[ _.-]*(?:cd|dvd|part|pt|dis[ck])[ _.-]*[a-d])(?<ignore>.*?)(?<extension>\\.[^.]+)$", + "^(?<title>.*?)(?<volume>[ ._-]*[a-d])(?<ignore>.*?)(?<extension>\\.[^.]+)$" }; CleanDateTimes = new[] @@ -403,6 +403,12 @@ namespace Emby.Naming.Common VideoExtraRules = new[] { + new ExtraRule( + ExtraType.Trailer, + ExtraRuleType.DirectoryName, + "trailers", + MediaType.Video), + new ExtraRule( ExtraType.Trailer, ExtraRuleType.Filename, diff --git a/Emby.Naming/Video/ExtraResolver.cs b/Emby.Naming/Video/ExtraResolver.cs index 7bc226614..cd7a6c0d7 100644 --- a/Emby.Naming/Video/ExtraResolver.cs +++ b/Emby.Naming/Video/ExtraResolver.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Audio; using Emby.Naming.Common; @@ -9,45 +11,27 @@ namespace Emby.Naming.Video /// <summary> /// Resolve if file is extra for video. /// </summary> - public class ExtraResolver + public static class ExtraResolver { - private static readonly char[] _digits = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; - private readonly NamingOptions _options; - - /// <summary> - /// Initializes a new instance of the <see cref="ExtraResolver"/> class. - /// </summary> - /// <param name="options"><see cref="NamingOptions"/> object containing VideoExtraRules and passed to <see cref="AudioFileParser"/> and <see cref="VideoResolver"/>.</param> - public ExtraResolver(NamingOptions options) - { - _options = options; - } + private static readonly char[] _digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; /// <summary> /// Attempts to resolve if file is extra. /// </summary> /// <param name="path">Path to file.</param> + /// <param name="namingOptions">The naming options.</param> /// <returns>Returns <see cref="ExtraResult"/> object.</returns> - public ExtraResult GetExtraInfo(string path) + public static ExtraResult GetExtraInfo(string path, NamingOptions namingOptions) { var result = new ExtraResult(); - for (var i = 0; i < _options.VideoExtraRules.Length; i++) + for (var i = 0; i < namingOptions.VideoExtraRules.Length; i++) { - var rule = _options.VideoExtraRules[i]; - if (rule.MediaType == MediaType.Audio) + var rule = namingOptions.VideoExtraRules[i]; + if ((rule.MediaType == MediaType.Audio && !AudioFileParser.IsAudioFile(path, namingOptions)) + || (rule.MediaType == MediaType.Video && !VideoResolver.IsVideoFile(path, namingOptions))) { - if (!AudioFileParser.IsAudioFile(path, _options)) - { - continue; - } - } - else if (rule.MediaType == MediaType.Video) - { - if (!VideoResolver.IsVideoFile(path, _options)) - { - continue; - } + continue; } var pathSpan = path.AsSpan(); @@ -76,7 +60,7 @@ namespace Emby.Naming.Video { var filename = Path.GetFileName(path); - var regex = new Regex(rule.Token, RegexOptions.IgnoreCase); + var regex = new Regex(rule.Token, RegexOptions.IgnoreCase | RegexOptions.Compiled); if (regex.IsMatch(filename)) { @@ -102,5 +86,68 @@ namespace Emby.Naming.Video return result; } + + /// <summary> + /// Finds extras matching the video info. + /// </summary> + /// <param name="files">The list of file video infos.</param> + /// <param name="videoInfo">The video to compare against.</param> + /// <param name="videoFlagDelimiters">The video flag delimiters.</param> + /// <returns>A list of video extras for [videoInfo].</returns> + public static IReadOnlyList<VideoFileInfo> GetExtras(IReadOnlyList<VideoInfo> files, VideoFileInfo videoInfo, ReadOnlySpan<char> videoFlagDelimiters) + { + var parentDir = videoInfo.IsDirectory ? videoInfo.Path : Path.GetDirectoryName(videoInfo.Path.AsSpan()); + + var trimmedFileName = TrimFilenameDelimiters(videoInfo.Name, videoFlagDelimiters); + var trimmedFileNameWithoutExtension = TrimFilenameDelimiters(videoInfo.FileNameWithoutExtension, videoFlagDelimiters); + var trimmedVideoInfoName = TrimFilenameDelimiters(videoInfo.Name, videoFlagDelimiters); + + var result = new List<VideoFileInfo>(); + for (var pos = files.Count - 1; pos >= 0; pos--) + { + var current = files[pos]; + // ignore non-extras and multi-file (can this happen?) + if (current.ExtraType == null || current.Files.Count > 1) + { + continue; + } + + var currentFile = files[pos].Files[0]; + var trimmedCurrentFileName = TrimFilenameDelimiters(currentFile.Name, videoFlagDelimiters); + + // first check filenames + bool isValid = StartsWith(trimmedCurrentFileName, trimmedFileNameWithoutExtension) + || (StartsWith(trimmedCurrentFileName, trimmedFileName) && currentFile.Year == videoInfo.Year) + || (StartsWith(trimmedCurrentFileName, trimmedVideoInfoName) && currentFile.Year == videoInfo.Year); + + // then by directory + if (!isValid) + { + // When the extra rule type is DirectoryName we must go one level higher to get the "real" dir name + var currentParentDir = currentFile.ExtraRule?.RuleType == ExtraRuleType.DirectoryName + ? Path.GetDirectoryName(Path.GetDirectoryName(currentFile.Path.AsSpan())) + : Path.GetDirectoryName(currentFile.Path.AsSpan()); + + isValid = !currentParentDir.IsEmpty && !parentDir.IsEmpty && currentParentDir.Equals(parentDir, StringComparison.OrdinalIgnoreCase); + } + + if (isValid) + { + result.Add(currentFile); + } + } + + return result.OrderBy(r => r.Path).ToArray(); + } + + private static ReadOnlySpan<char> TrimFilenameDelimiters(ReadOnlySpan<char> name, ReadOnlySpan<char> videoFlagDelimiters) + { + return name.IsEmpty ? name : name.TrimEnd().TrimEnd(videoFlagDelimiters).TrimEnd(); + } + + private static bool StartsWith(ReadOnlySpan<char> fileName, ReadOnlySpan<char> baseName) + { + return !baseName.IsEmpty && fileName.StartsWith(baseName, StringComparison.OrdinalIgnoreCase); + } } } diff --git a/Emby.Naming/Video/FileStack.cs b/Emby.Naming/Video/FileStack.cs index 6519db57c..a4a4716ca 100644 --- a/Emby.Naming/Video/FileStack.cs +++ b/Emby.Naming/Video/FileStack.cs @@ -40,6 +40,11 @@ namespace Emby.Naming.Video /// <returns>True if file is in the stack.</returns> public bool ContainsFile(string file, bool isDirectory) { + if (string.IsNullOrEmpty(file)) + { + return false; + } + if (IsDirectoryStack == isDirectory) { return Files.Contains(file, StringComparer.OrdinalIgnoreCase); diff --git a/Emby.Naming/Video/StackResolver.cs b/Emby.Naming/Video/StackResolver.cs index 36f65a562..be73f69db 100644 --- a/Emby.Naming/Video/StackResolver.cs +++ b/Emby.Naming/Video/StackResolver.cs @@ -12,37 +12,28 @@ namespace Emby.Naming.Video /// <summary> /// Resolve <see cref="FileStack"/> from list of paths. /// </summary> - public class StackResolver + public static class StackResolver { - private readonly NamingOptions _options; - - /// <summary> - /// Initializes a new instance of the <see cref="StackResolver"/> class. - /// </summary> - /// <param name="options"><see cref="NamingOptions"/> object containing VideoFileStackingRegexes and passes options to <see cref="VideoResolver"/>.</param> - public StackResolver(NamingOptions options) - { - _options = options; - } - /// <summary> /// Resolves only directories from paths. /// </summary> /// <param name="files">List of paths.</param> + /// <param name="namingOptions">The naming options.</param> /// <returns>Enumerable <see cref="FileStack"/> of directories.</returns> - public IEnumerable<FileStack> ResolveDirectories(IEnumerable<string> files) + public static IEnumerable<FileStack> ResolveDirectories(IEnumerable<string> files, NamingOptions namingOptions) { - return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = true })); + return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = true }), namingOptions); } /// <summary> /// Resolves only files from paths. /// </summary> /// <param name="files">List of paths.</param> + /// <param name="namingOptions">The naming options.</param> /// <returns>Enumerable <see cref="FileStack"/> of files.</returns> - public IEnumerable<FileStack> ResolveFiles(IEnumerable<string> files) + public static IEnumerable<FileStack> ResolveFiles(IEnumerable<string> files, NamingOptions namingOptions) { - return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = false })); + return Resolve(files.Select(i => new FileSystemMetadata { FullName = i, IsDirectory = false }), namingOptions); } /// <summary> @@ -50,7 +41,7 @@ namespace Emby.Naming.Video /// </summary> /// <param name="files">List of paths.</param> /// <returns>Enumerable <see cref="FileStack"/> of directories.</returns> - public IEnumerable<FileStack> ResolveAudioBooks(IEnumerable<AudioBookFileInfo> files) + public static IEnumerable<FileStack> ResolveAudioBooks(IEnumerable<AudioBookFileInfo> files) { var groupedDirectoryFiles = files.GroupBy(file => Path.GetDirectoryName(file.Path)); @@ -82,15 +73,20 @@ namespace Emby.Naming.Video /// Resolves videos from paths. /// </summary> /// <param name="files">List of paths.</param> + /// <param name="namingOptions">The naming options.</param> /// <returns>Enumerable <see cref="FileStack"/> of videos.</returns> - public IEnumerable<FileStack> Resolve(IEnumerable<FileSystemMetadata> files) + public static IEnumerable<FileStack> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions) { var list = files - .Where(i => i.IsDirectory || VideoResolver.IsVideoFile(i.FullName, _options) || VideoResolver.IsStubFile(i.FullName, _options)) + .Where(i => i.IsDirectory || VideoResolver.IsVideoFile(i.FullName, namingOptions) || VideoResolver.IsStubFile(i.FullName, namingOptions)) .OrderBy(i => i.FullName) + .Select(f => (f.IsDirectory, FileName: GetFileNameWithExtension(f), f.FullName)) .ToList(); - var expressions = _options.VideoFileStackingRegexes; + // TODO is there a "nicer" way? + var cache = new Dictionary<(string, Regex, int), Match>(); + + var expressions = namingOptions.VideoFileStackingRegexes; for (var i = 0; i < list.Count; i++) { @@ -102,17 +98,17 @@ namespace Emby.Naming.Video while (expressionIndex < expressions.Length) { var exp = expressions[expressionIndex]; - var stack = new FileStack(); + FileStack? stack = null; // (Title)(Volume)(Ignore)(Extension) - var match1 = FindMatch(file1, exp, offset); + var match1 = FindMatch(file1.FileName, exp, offset, cache); if (match1.Success) { - var title1 = match1.Groups["title"].Value; - var volume1 = match1.Groups["volume"].Value; - var ignore1 = match1.Groups["ignore"].Value; - var extension1 = match1.Groups["extension"].Value; + var title1 = match1.Groups[1].Value; + var volume1 = match1.Groups[2].Value; + var ignore1 = match1.Groups[3].Value; + var extension1 = match1.Groups[4].Value; var j = i + 1; while (j < list.Count) @@ -126,7 +122,7 @@ namespace Emby.Naming.Video } // (Title)(Volume)(Ignore)(Extension) - var match2 = FindMatch(file2, exp, offset); + var match2 = FindMatch(file2.FileName, exp, offset, cache); if (match2.Success) { @@ -142,6 +138,7 @@ namespace Emby.Naming.Video if (string.Equals(ignore1, ignore2, StringComparison.OrdinalIgnoreCase) && string.Equals(extension1, extension2, StringComparison.OrdinalIgnoreCase)) { + stack ??= new FileStack(); if (stack.Files.Count == 0) { stack.Name = title1 + ignore1; @@ -204,7 +201,7 @@ namespace Emby.Naming.Video expressionIndex++; } - if (stack.Files.Count > 1) + if (stack?.Files.Count > 1) { yield return stack; i += stack.Files.Count - 1; @@ -214,26 +211,32 @@ namespace Emby.Naming.Video } } - private static string GetRegexInput(FileSystemMetadata file) + private static string GetFileNameWithExtension(FileSystemMetadata file) { // For directories, dummy up an extension otherwise the expressions will fail - var input = !file.IsDirectory - ? file.FullName - : file.FullName + ".mkv"; + var input = file.FullName; + if (file.IsDirectory) + { + input = Path.ChangeExtension(input, "mkv"); + } return Path.GetFileName(input); } - private static Match FindMatch(FileSystemMetadata input, Regex regex, int offset) + private static Match FindMatch(string input, Regex regex, int offset, Dictionary<(string, Regex, int), Match> cache) { - var regexInput = GetRegexInput(input); - - if (offset < 0 || offset >= regexInput.Length) + if (offset < 0 || offset >= input.Length) { return Match.Empty; } - return regex.Match(regexInput, offset); + if (!cache.TryGetValue((input, regex, offset), out var result)) + { + result = regex.Match(input, offset, input.Length - offset); + cache.Add((input, regex, offset), result); + } + + return result; } } } diff --git a/Emby.Naming/Video/VideoInfo.cs b/Emby.Naming/Video/VideoInfo.cs index 930fdb33f..8847ee9bc 100644 --- a/Emby.Naming/Video/VideoInfo.cs +++ b/Emby.Naming/Video/VideoInfo.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using MediaBrowser.Model.Entities; namespace Emby.Naming.Video { @@ -17,7 +18,6 @@ namespace Emby.Naming.Video Name = name; Files = Array.Empty<VideoFileInfo>(); - Extras = Array.Empty<VideoFileInfo>(); AlternateVersions = Array.Empty<VideoFileInfo>(); } @@ -39,16 +39,15 @@ namespace Emby.Naming.Video /// <value>The files.</value> public IReadOnlyList<VideoFileInfo> Files { get; set; } - /// <summary> - /// Gets or sets the extras. - /// </summary> - /// <value>The extras.</value> - public IReadOnlyList<VideoFileInfo> Extras { get; set; } - /// <summary> /// Gets or sets the alternate versions. /// </summary> /// <value>The alternate versions.</value> public IReadOnlyList<VideoFileInfo> AlternateVersions { get; set; } + + /// <summary> + /// Gets or sets the extra type. + /// </summary> + public ExtraType? ExtraType { get; set; } } } diff --git a/Emby.Naming/Video/VideoListResolver.cs b/Emby.Naming/Video/VideoListResolver.cs index ed7d511a3..bce7cb47f 100644 --- a/Emby.Naming/Video/VideoListResolver.cs +++ b/Emby.Naming/Video/VideoListResolver.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Common; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; namespace Emby.Naming.Video @@ -20,11 +19,12 @@ namespace Emby.Naming.Video /// <param name="files">List of related video files.</param> /// <param name="namingOptions">The naming options.</param> /// <param name="supportMultiVersion">Indication we should consider multi-versions of content.</param> + /// <param name="parseName">Whether to parse the name or use the filename.</param> /// <returns>Returns enumerable of <see cref="VideoInfo"/> which groups files together when related.</returns> - public static IEnumerable<VideoInfo> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions, bool supportMultiVersion = true) + public static IReadOnlyList<VideoInfo> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions, bool supportMultiVersion = true, bool parseName = true) { var videoInfos = files - .Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, namingOptions)) + .Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, namingOptions, parseName)) .OfType<VideoFileInfo>() .ToList(); @@ -34,12 +34,25 @@ namespace Emby.Naming.Video .Where(i => i.ExtraType == null) .Select(i => new FileSystemMetadata { FullName = i.Path, IsDirectory = i.IsDirectory }); - var stackResult = new StackResolver(namingOptions) - .Resolve(nonExtras).ToList(); + var stackResult = StackResolver.Resolve(nonExtras, namingOptions).ToList(); - var remainingFiles = videoInfos - .Where(i => !stackResult.Any(s => i.Path != null && s.ContainsFile(i.Path, i.IsDirectory))) - .ToList(); + var remainingFiles = new List<VideoFileInfo>(); + var standaloneMedia = new List<VideoFileInfo>(); + + for (var i = 0; i < videoInfos.Count; i++) + { + var current = videoInfos[i]; + if (stackResult.Any(s => s.ContainsFile(current.Path, current.IsDirectory))) + { + continue; + } + + remainingFiles.Add(current); + if (current.ExtraType == null) + { + standaloneMedia.Add(current); + } + } var list = new List<VideoInfo>(); @@ -47,27 +60,15 @@ namespace Emby.Naming.Video { var info = new VideoInfo(stack.Name) { - Files = stack.Files.Select(i => VideoResolver.Resolve(i, stack.IsDirectoryStack, namingOptions)) + Files = stack.Files.Select(i => VideoResolver.Resolve(i, stack.IsDirectoryStack, namingOptions, parseName)) .OfType<VideoFileInfo>() .ToList() }; info.Year = info.Files[0].Year; - - var extras = ExtractExtras(remainingFiles, stack.Name, Path.GetFileNameWithoutExtension(stack.Files[0].AsSpan()), namingOptions.VideoFlagDelimiters); - - if (extras.Count > 0) - { - info.Extras = extras; - } - list.Add(info); } - var standaloneMedia = remainingFiles - .Where(i => i.ExtraType == null) - .ToList(); - foreach (var media in standaloneMedia) { var info = new VideoInfo(media.Name) { Files = new[] { media } }; @@ -75,10 +76,6 @@ namespace Emby.Naming.Video info.Year = info.Files[0].Year; remainingFiles.Remove(media); - var extras = ExtractExtras(remainingFiles, media.FileNameWithoutExtension, namingOptions.VideoFlagDelimiters); - - info.Extras = extras; - list.Add(info); } @@ -87,58 +84,12 @@ namespace Emby.Naming.Video list = GetVideosGroupedByVersion(list, namingOptions); } - // If there's only one resolved video, use the folder name as well to find extras - if (list.Count == 1) - { - var info = list[0]; - var videoPath = list[0].Files[0].Path; - var parentPath = Path.GetDirectoryName(videoPath.AsSpan()); - - if (!parentPath.IsEmpty) - { - var folderName = Path.GetFileName(parentPath); - if (!folderName.IsEmpty) - { - var extras = ExtractExtras(remainingFiles, folderName, namingOptions.VideoFlagDelimiters); - extras.AddRange(info.Extras); - info.Extras = extras; - } - } - - // Add the extras that are just based on file name as well - var extrasByFileName = remainingFiles - .Where(i => i.ExtraRule != null && i.ExtraRule.RuleType == ExtraRuleType.Filename) - .ToList(); - - remainingFiles = remainingFiles - .Except(extrasByFileName) - .ToList(); - - extrasByFileName.AddRange(info.Extras); - info.Extras = extrasByFileName; - } - - // If there's only one video, accept all trailers - // Be lenient because people use all kinds of mishmash conventions with trailers. - if (list.Count == 1) - { - var trailers = remainingFiles - .Where(i => i.ExtraType == ExtraType.Trailer) - .ToList(); - - trailers.AddRange(list[0].Extras); - list[0].Extras = trailers; - - remainingFiles = remainingFiles - .Except(trailers) - .ToList(); - } - // Whatever files are left, just add them list.AddRange(remainingFiles.Select(i => new VideoInfo(i.Name) { Files = new[] { i }, - Year = i.Year + Year = i.Year, + ExtraType = i.ExtraType })); return list; @@ -162,6 +113,11 @@ namespace Emby.Naming.Video for (var i = 0; i < videos.Count; i++) { var video = videos[i]; + if (video.ExtraType != null) + { + continue; + } + if (!IsEligibleForMultiVersion(folderName, video.Files[0].Path, namingOptions)) { return videos; @@ -178,17 +134,14 @@ namespace Emby.Naming.Video var alternateVersionsLen = videos.Count - 1; var alternateVersions = new VideoFileInfo[alternateVersionsLen]; - var extras = new List<VideoFileInfo>(list[0].Extras); for (int i = 0; i < alternateVersionsLen; i++) { var video = videos[i + 1]; alternateVersions[i] = video.Files[0]; - extras.AddRange(video.Extras); } list[0].AlternateVersions = alternateVersions; list[0].Name = folderName.ToString(); - list[0].Extras = extras; return list; } @@ -230,7 +183,7 @@ namespace Emby.Naming.Video var tmpTestFilename = testFilename.ToString(); if (CleanStringParser.TryClean(tmpTestFilename, namingOptions.CleanStringRegexes, out var cleanName)) { - tmpTestFilename = cleanName.Trim().ToString(); + tmpTestFilename = cleanName.Trim(); } // The CleanStringParser should have removed common keywords etc. @@ -238,67 +191,5 @@ namespace Emby.Naming.Video || testFilename[0] == '-' || Regex.IsMatch(tmpTestFilename, @"^\[([^]]*)\]", RegexOptions.Compiled); } - - private static ReadOnlySpan<char> TrimFilenameDelimiters(ReadOnlySpan<char> name, ReadOnlySpan<char> videoFlagDelimiters) - { - return name.IsEmpty ? name : name.TrimEnd().TrimEnd(videoFlagDelimiters).TrimEnd(); - } - - private static bool StartsWith(ReadOnlySpan<char> fileName, ReadOnlySpan<char> baseName, ReadOnlySpan<char> trimmedBaseName) - { - if (baseName.IsEmpty) - { - return false; - } - - return fileName.StartsWith(baseName, StringComparison.OrdinalIgnoreCase) - || (!trimmedBaseName.IsEmpty && fileName.StartsWith(trimmedBaseName, StringComparison.OrdinalIgnoreCase)); - } - - /// <summary> - /// Finds similar filenames to that of [baseName] and removes any matches from [remainingFiles]. - /// </summary> - /// <param name="remainingFiles">The list of remaining filenames.</param> - /// <param name="baseName">The base name to use for the comparison.</param> - /// <param name="videoFlagDelimiters">The video flag delimiters.</param> - /// <returns>A list of video extras for [baseName].</returns> - private static List<VideoFileInfo> ExtractExtras(IList<VideoFileInfo> remainingFiles, ReadOnlySpan<char> baseName, ReadOnlySpan<char> videoFlagDelimiters) - { - return ExtractExtras(remainingFiles, baseName, ReadOnlySpan<char>.Empty, videoFlagDelimiters); - } - - /// <summary> - /// Finds similar filenames to that of [firstBaseName] and [secondBaseName] and removes any matches from [remainingFiles]. - /// </summary> - /// <param name="remainingFiles">The list of remaining filenames.</param> - /// <param name="firstBaseName">The first base name to use for the comparison.</param> - /// <param name="secondBaseName">The second base name to use for the comparison.</param> - /// <param name="videoFlagDelimiters">The video flag delimiters.</param> - /// <returns>A list of video extras for [firstBaseName] and [secondBaseName].</returns> - private static List<VideoFileInfo> ExtractExtras(IList<VideoFileInfo> remainingFiles, ReadOnlySpan<char> firstBaseName, ReadOnlySpan<char> secondBaseName, ReadOnlySpan<char> videoFlagDelimiters) - { - var trimmedFirstBaseName = TrimFilenameDelimiters(firstBaseName, videoFlagDelimiters); - var trimmedSecondBaseName = TrimFilenameDelimiters(secondBaseName, videoFlagDelimiters); - - var result = new List<VideoFileInfo>(); - for (var pos = remainingFiles.Count - 1; pos >= 0; pos--) - { - var file = remainingFiles[pos]; - if (file.ExtraType == null) - { - continue; - } - - var filename = file.FileNameWithoutExtension; - if (StartsWith(filename, firstBaseName, trimmedFirstBaseName) - || StartsWith(filename, secondBaseName, trimmedSecondBaseName)) - { - result.Add(file); - remainingFiles.RemoveAt(pos); - } - } - - return result; - } } } diff --git a/Emby.Naming/Video/VideoResolver.cs b/Emby.Naming/Video/VideoResolver.cs index 4c9df27f5..9cadc1465 100644 --- a/Emby.Naming/Video/VideoResolver.cs +++ b/Emby.Naming/Video/VideoResolver.cs @@ -16,10 +16,11 @@ namespace Emby.Naming.Video /// </summary> /// <param name="path">The path.</param> /// <param name="namingOptions">The naming options.</param> + /// <param name="parseName">Whether to parse the name or use the filename.</param> /// <returns>VideoFileInfo.</returns> - public static VideoFileInfo? ResolveDirectory(string? path, NamingOptions namingOptions) + public static VideoFileInfo? ResolveDirectory(string? path, NamingOptions namingOptions, bool parseName = true) { - return Resolve(path, true, namingOptions); + return Resolve(path, true, namingOptions, parseName); } /// <summary> @@ -74,7 +75,7 @@ namespace Emby.Naming.Video var format3DResult = Format3DParser.Parse(path, namingOptions); - var extraResult = new ExtraResolver(namingOptions).GetExtraInfo(path); + var extraResult = ExtraResolver.GetExtraInfo(path, namingOptions); var name = Path.GetFileNameWithoutExtension(path); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 778b6225e..01749242f 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -11,11 +11,9 @@ using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using Emby.Naming.Audio; using Emby.Naming.Common; using Emby.Naming.TV; using Emby.Naming.Video; -using Emby.Server.Implementations.Library.Resolvers; using Emby.Server.Implementations.Library.Validators; using Emby.Server.Implementations.Playlists; using Emby.Server.Implementations.ScheduledTasks; @@ -677,7 +675,7 @@ namespace Emby.Server.Implementations.Library { var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService); - if (result != null && result.Items.Count > 0) + if (result?.Items.Count > 0) { var items = new List<BaseItem>(); items.AddRange(result.Items); @@ -2685,89 +2683,58 @@ namespace Emby.Server.Implementations.Library }; } - public IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) + public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren) { - var namingOptions = _namingOptions; - - var files = owner.IsInMixedFolder ? new List<FileSystemMetadata>() : fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, BaseItem.TrailersFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => _fileSystem.GetFiles(i.FullName, namingOptions.VideoFileExtensions, false, false)) - .ToList(); - - var videos = VideoListResolver.Resolve(fileSystemChildren, namingOptions); - - var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files[0].Path, StringComparison.OrdinalIgnoreCase)); - - if (currentVideo != null) + var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions); + if (ownerVideoInfo == null) { - files.AddRange(currentVideo.Extras.Where(i => i.ExtraType == ExtraType.Trailer).Select(i => _fileSystem.GetFileInfo(i.Path))); + yield break; } - var resolvers = new IItemResolver[] + var count = fileSystemChildren.Count; + var files = new List<FileSystemMetadata>(); + for (var i = 0; i < count; i++) { - new GenericVideoResolver<Trailer>(_namingOptions) - }; - - return ResolvePaths(files, directoryService, null, new LibraryOptions(), null, resolvers) - .OfType<Trailer>() - .Select(video => + var current = fileSystemChildren[i]; + if (current.IsDirectory && BaseItem.AllExtrasTypesFolderNames.ContainsKey(current.Name)) { - // Try to retrieve it from the db. If we don't find it, use the resolved version - if (GetItemById(video.Id) is Trailer dbItem) - { - video = dbItem; - } - - video.ParentId = Guid.Empty; - video.OwnerId = owner.Id; - video.ExtraType = ExtraType.Trailer; - video.TrailerTypes = new[] { TrailerType.LocalTrailer }; - - return video; - - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path); - } - - public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - var namingOptions = _namingOptions; - - var files = owner.IsInMixedFolder ? new List<FileSystemMetadata>() : fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => BaseItem.AllExtrasTypesFolderNames.ContainsKey(i.Name ?? string.Empty)) - .SelectMany(i => _fileSystem.GetFiles(i.FullName, namingOptions.VideoFileExtensions, false, false)) - .ToList(); - - var videos = VideoListResolver.Resolve(fileSystemChildren, namingOptions); - - var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files[0].Path, StringComparison.OrdinalIgnoreCase)); + files.AddRange(_fileSystem.GetFiles(current.FullName, _namingOptions.VideoFileExtensions, false, false)); + } + else if (!current.IsDirectory) + { + files.Add(current); + } + } - if (currentVideo != null) + if (files.Count == 0) { - files.AddRange(currentVideo.Extras.Where(i => i.ExtraType != ExtraType.Trailer).Select(i => _fileSystem.GetFileInfo(i.Path))); + yield break; } - return ResolvePaths(files, directoryService, null, new LibraryOptions(), null) - .OfType<Video>() - .Select(video => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = GetItemById(video.Id) as Video; + var videos = VideoListResolver.Resolve(files, _namingOptions); + // owner video info cannot be null as that implies it has no path + var extras = ExtraResolver.GetExtras(videos, ownerVideoInfo, _namingOptions.VideoFlagDelimiters); - if (dbItem != null) - { - video = dbItem; - } - - video.ParentId = Guid.Empty; - video.OwnerId = owner.Id; - - SetExtraTypeFromFilename(video); + for (var i = 0; i < extras.Count; i++) + { + var currentExtra = extras[i]; + var resolved = ResolvePath(_fileSystem.GetFileInfo(currentExtra.Path)); + if (resolved is not Video video) + { + continue; + } - return video; + // Try to retrieve it from the db. If we don't find it, use the resolved version + if (GetItemById(resolved.Id) is Video dbItem) + { + video = dbItem; + } - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path); + video.ExtraType = currentExtra.ExtraType; + video.ParentId = Guid.Empty; + video.OwnerId = owner.Id; + yield return video; + } } public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem) @@ -2817,15 +2784,6 @@ namespace Emby.Server.Implementations.Library return path; } - private void SetExtraTypeFromFilename(Video item) - { - var resolver = new ExtraResolver(_namingOptions); - - var result = resolver.GetExtraInfo(item.Path); - - item.ExtraType = result.ExtraType; - } - public List<PersonInfo> GetPeople(InternalPeopleQuery query) { return _itemRepository.GetPeople(query); diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 0ebf0e530..9222a9479 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -49,120 +49,71 @@ namespace Emby.Server.Implementations.Library.Resolvers protected virtual TVideoType ResolveVideo<TVideoType>(ItemResolveArgs args, bool parseName) where TVideoType : Video, new() { - var namingOptions = NamingOptions; + VideoFileInfo videoInfo = null; + VideoType? videoType = null; // If the path is a file check for a matching extensions if (args.IsDirectory) { - TVideoType video = null; - VideoFileInfo videoInfo = null; - // Loop through each child file/folder and see if we find a video foreach (var child in args.FileSystemChildren) { var filename = child.Name; - if (child.IsDirectory) { if (IsDvdDirectory(child.FullName, filename, args.DirectoryService)) { - videoInfo = VideoResolver.ResolveDirectory(args.Path, namingOptions); - - if (videoInfo == null) - { - return null; - } - - video = new TVideoType - { - Path = args.Path, - VideoType = VideoType.Dvd, - ProductionYear = videoInfo.Year - }; - break; + videoType = VideoType.Dvd; } - - if (IsBluRayDirectory(filename)) + else if (IsBluRayDirectory(filename)) { - videoInfo = VideoResolver.ResolveDirectory(args.Path, namingOptions); - - if (videoInfo == null) - { - return null; - } - - video = new TVideoType - { - Path = args.Path, - VideoType = VideoType.BluRay, - ProductionYear = videoInfo.Year - }; - break; + videoType = VideoType.BluRay; } } else if (IsDvdFile(filename)) { - videoInfo = VideoResolver.ResolveDirectory(args.Path, namingOptions); - - if (videoInfo == null) - { - return null; - } - - video = new TVideoType - { - Path = args.Path, - VideoType = VideoType.Dvd, - ProductionYear = videoInfo.Year - }; - break; + videoType = VideoType.Dvd; } - } - if (video != null) - { - video.Name = parseName ? - videoInfo.Name : - Path.GetFileName(args.Path); + if (videoType == null) + { + continue; + } - Set3DFormat(video, videoInfo); + videoInfo = VideoResolver.ResolveDirectory(args.Path, NamingOptions, parseName); + break; } - - return video; } else { - var videoInfo = VideoResolver.Resolve(args.Path, false, namingOptions, false); - - if (videoInfo == null) - { - return null; - } - - if (VideoResolver.IsVideoFile(args.Path, NamingOptions) || videoInfo.IsStub) - { - var path = args.Path; - - var video = new TVideoType - { - Path = path, - IsInMixedFolder = true, - ProductionYear = videoInfo.Year - }; - - SetVideoType(video, videoInfo); + videoInfo = VideoResolver.Resolve(args.Path, false, NamingOptions, parseName); + } - video.Name = parseName ? - videoInfo.Name : - Path.GetFileNameWithoutExtension(args.Path); + if (videoInfo == null || (!videoInfo.IsStub && !VideoResolver.IsVideoFile(args.Path, NamingOptions))) + { + return null; + } - Set3DFormat(video, videoInfo); + var video = new TVideoType + { + Name = videoInfo.Name, + Path = args.Path, + ProductionYear = videoInfo.Year, + ExtraType = videoInfo.ExtraType + }; - return video; - } + if (videoType.HasValue) + { + video.VideoType = videoType.Value; } + else + { + SetVideoType(video, videoInfo); + } + + Set3DFormat(video, videoInfo); - return null; + return video; } protected void SetVideoType(Video video, VideoFileInfo videoInfo) @@ -207,8 +158,8 @@ namespace Emby.Server.Implementations.Library.Resolvers { // use disc-utils, both DVDs and BDs use UDF filesystem using (var videoFileStream = File.Open(video.Path, FileMode.Open, FileAccess.Read)) + using (UdfReader udfReader = new UdfReader(videoFileStream)) { - UdfReader udfReader = new UdfReader(videoFileStream); if (udfReader.DirectoryExists("VIDEO_TS")) { video.IsoType = IsoType.Dvd; diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 732be0fe5..58279af9e 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -26,7 +26,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver { private readonly IImageProcessor _imageProcessor; - private readonly StackResolver _stackResolver; private string[] _validCollectionTypes = new[] { @@ -46,7 +45,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies : base(namingOptions) { _imageProcessor = imageProcessor; - _stackResolver = new StackResolver(NamingOptions); } /// <summary> @@ -62,7 +60,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies string collectionType, IDirectoryService directoryService) { - var result = ResolveMultipleInternal(parent, files, collectionType, directoryService); + var result = ResolveMultipleInternal(parent, files, collectionType); if (result != null) { @@ -92,16 +90,17 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } + Video movie = null; var files = args.GetActualFileSystemChildren().ToList(); if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie<MusicVideo>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); + movie = FindMovie<MusicVideo>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { - return FindMovie<Video>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); + movie = FindMovie<Video>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); } if (string.IsNullOrEmpty(collectionType)) @@ -118,17 +117,16 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } - { - return FindMovie<Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true); - } + movie = FindMovie<Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true); } if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { - return FindMovie<Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true); + movie = FindMovie<Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true); } - return null; + // ignore extras + return movie?.ExtraType == null ? movie : null; } // Handle owned items @@ -169,6 +167,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies item = ResolveVideo<Video>(args, false); } + // Ignore extras + if (item?.ExtraType != null) + { + return null; + } + if (item != null) { item.IsInMixedFolder = true; @@ -180,8 +184,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies private MultiItemResolverResult ResolveMultipleInternal( Folder parent, List<FileSystemMetadata> files, - string collectionType, - IDirectoryService directoryService) + string collectionType) { if (IsInvalid(parent, collectionType)) { @@ -190,13 +193,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { - return ResolveVideos<MusicVideo>(parent, files, directoryService, true, collectionType, false); + return ResolveVideos<MusicVideo>(parent, files, true, collectionType, false); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) { - return ResolveVideos<Video>(parent, files, directoryService, false, collectionType, false); + return ResolveVideos<Video>(parent, files, false, collectionType, false); } if (string.IsNullOrEmpty(collectionType)) @@ -204,7 +207,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies // Owned items should just use the plain video type if (parent == null) { - return ResolveVideos<Video>(parent, files, directoryService, false, collectionType, false); + return ResolveVideos<Video>(parent, files, false, collectionType, false); } if (parent is Series || parent.GetParents().OfType<Series>().Any()) @@ -212,12 +215,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } - return ResolveVideos<Movie>(parent, files, directoryService, false, collectionType, true); + return ResolveVideos<Movie>(parent, files, false, collectionType, true); } if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { - return ResolveVideos<Movie>(parent, files, directoryService, true, collectionType, true); + return ResolveVideos<Movie>(parent, files, true, collectionType, true); } return null; @@ -226,21 +229,20 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies private MultiItemResolverResult ResolveVideos<T>( Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, - IDirectoryService directoryService, - bool suppportMultiEditions, + bool supportMultiEditions, string collectionType, bool parseName) where T : Video, new() { var files = new List<FileSystemMetadata>(); - var videos = new List<BaseItem>(); var leftOver = new List<FileSystemMetadata>(); + var hasCollectionType = !string.IsNullOrEmpty(collectionType); // Loop through each child file/folder and see if we find a video foreach (var child in fileSystemEntries) { // This is a hack but currently no better way to resolve a sometimes ambiguous situation - if (string.IsNullOrEmpty(collectionType)) + if (!hasCollectionType) { if (string.Equals(child.Name, "tvshow.nfo", StringComparison.OrdinalIgnoreCase) || string.Equals(child.Name, "season.nfo", StringComparison.OrdinalIgnoreCase)) @@ -259,29 +261,35 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } } - var resolverResult = VideoListResolver.Resolve(files, NamingOptions, suppportMultiEditions).ToList(); + var resolverResult = VideoListResolver.Resolve(files, NamingOptions, supportMultiEditions, parseName); var result = new MultiItemResolverResult { - ExtraFiles = leftOver, - Items = videos + ExtraFiles = leftOver }; - var isInMixedFolder = resolverResult.Count > 1 || (parent != null && parent.IsTopParent); + var isInMixedFolder = resolverResult.Count > 1 || parent?.IsTopParent == true; foreach (var video in resolverResult) { var firstVideo = video.Files[0]; + var path = firstVideo.Path; + if (video.ExtraType != null) + { + // TODO + result.ExtraFiles.Add(files.First(f => string.Equals(f.FullName, path, StringComparison.OrdinalIgnoreCase))); + continue; + } + + var additionalParts = video.Files.Count > 1 ? video.Files.Skip(1).Select(i => i.Path).ToArray() : Array.Empty<string>(); var videoItem = new T { - Path = video.Files[0].Path, + Path = path, IsInMixedFolder = isInMixedFolder, ProductionYear = video.Year, - Name = parseName ? - video.Name : - Path.GetFileNameWithoutExtension(video.Files[0].Path), - AdditionalParts = video.Files.Skip(1).Select(i => i.Path).ToArray(), + Name = parseName ? video.Name : firstVideo.Name, + AdditionalParts = additionalParts, LocalAlternateVersions = video.AlternateVersions.Select(i => i.Path).ToArray() }; @@ -299,21 +307,34 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies private static bool IsIgnored(string filename) { // Ignore samples - Match m = Regex.Match(filename, @"\bsample\b", RegexOptions.IgnoreCase); + Match m = Regex.Match(filename, @"\bsample\b", RegexOptions.IgnoreCase | RegexOptions.Compiled); return m.Success; } - private bool ContainsFile(List<VideoInfo> result, FileSystemMetadata file) + private static bool ContainsFile(IReadOnlyList<VideoInfo> result, FileSystemMetadata file) { - return result.Any(i => ContainsFile(i, file)); - } + for (var i = 0; i < result.Count; i++) + { + var current = result[i]; + for (var j = 0; j < current.Files.Count; j++) + { + if (ContainsFile(current.Files[j], file)) + { + return true; + } + } - private bool ContainsFile(VideoInfo result, FileSystemMetadata file) - { - return result.Files.Any(i => ContainsFile(i, file)) || - result.AlternateVersions.Any(i => ContainsFile(i, file)) || - result.Extras.Any(i => ContainsFile(i, file)); + for (var j = 0; j < current.AlternateVersions.Count; j++) + { + if (ContainsFile(current.AlternateVersions[j], file)) + { + return true; + } + } + } + + return false; } private static bool ContainsFile(VideoFileInfo result, FileSystemMetadata file) @@ -431,7 +452,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies // TODO: Allow GetMultiDiscMovie in here const bool SupportsMultiVersion = true; - var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, SupportsMultiVersion, collectionType, parseName) ?? + var result = ResolveVideos<T>(parent, fileSystemEntries, SupportsMultiVersion, collectionType, parseName) ?? new MultiItemResolverResult(); if (result.Items.Count == 1) @@ -510,7 +531,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } - var result = _stackResolver.ResolveDirectories(folderPaths).ToList(); + var result = StackResolver.ResolveDirectories(folderPaths, NamingOptions).ToList(); if (result.Count != 1) { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index f72da3617..928cd42dd 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -45,34 +45,36 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV // If the parent is a Season or Series and the parent is not an extras folder, then this is an Episode if the VideoResolver returns something // Also handle flat tv folders - if ((season != null || - string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || - args.HasParent<Series>()) - && (parent is Series || !BaseItem.AllExtrasTypesFolderNames.ContainsKey(parent.Name))) + if (season != null || + string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || + args.HasParent<Series>()) { var episode = ResolveVideo<Episode>(args, false); - if (episode != null) + // Ignore extras + if (episode == null || episode.ExtraType != null) { - var series = parent as Series ?? parent.GetParents().OfType<Series>().FirstOrDefault(); + return null; + } - if (series != null) - { - episode.SeriesId = series.Id; - episode.SeriesName = series.Name; - } + var series = parent as Series ?? parent.GetParents().OfType<Series>().FirstOrDefault(); - if (season != null) - { - episode.SeasonId = season.Id; - episode.SeasonName = season.Name; - } + if (series != null) + { + episode.SeriesId = series.Id; + episode.SeriesName = series.Name; + } - // Assume season 1 if there's no season folder and a season number could not be determined - if (season == null && !episode.ParentIndexNumber.HasValue && (episode.IndexNumber.HasValue || episode.PremiereDate.HasValue)) - { - episode.ParentIndexNumber = 1; - } + if (season != null) + { + episode.SeasonId = season.Id; + episode.SeasonName = season.Name; + } + + // Assume season 1 if there's no season folder and a season number could not be determined + if (season == null && !episode.ParentIndexNumber.HasValue && (episode.IndexNumber.HasValue || episode.PremiereDate.HasValue)) + { + episode.ParentIndexNumber = 1; } return episode; diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index a33a0826c..249379619 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -213,7 +213,7 @@ namespace Jellyfin.Api.Controllers if (item is IHasTrailers hasTrailers) { - var trailers = hasTrailers.GetTrailers(); + var trailers = hasTrailers.LocalTrailers; var dtosTrailers = _dtoService.GetBaseItemDtos(trailers, dtoOptions, user, item); var allTrailers = new BaseItemDto[dtosExtras.Length + dtosTrailers.Count]; dtosExtras.CopyTo(allTrailers, 0); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index b1ac2fe8e..ad20ea334 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -40,9 +40,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> public abstract class BaseItem : IHasProviderIds, IHasLookupInfo<ItemLookupInfo>, IEquatable<BaseItem> { - /// <summary> - /// The trailer folder name. - /// </summary> + public const string TrailerFileName = "trailer"; public const string TrailersFolderName = "trailers"; public const string ThemeSongsFolderName = "theme-music"; public const string ThemeSongFileName = "theme"; @@ -99,8 +97,6 @@ namespace MediaBrowser.Controller.Entities }; private string _sortName; - private Guid[] _themeSongIds; - private Guid[] _themeVideoIds; private string _forcedSortName; @@ -121,40 +117,6 @@ namespace MediaBrowser.Controller.Entities ExtraIds = Array.Empty<Guid>(); } - [JsonIgnore] - public Guid[] ThemeSongIds - { - get - { - return _themeSongIds ??= GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeSong) - .Select(song => song.Id) - .ToArray(); - } - - private set - { - _themeSongIds = value; - } - } - - [JsonIgnore] - public Guid[] ThemeVideoIds - { - get - { - return _themeVideoIds ??= GetExtras() - .Where(extra => extra.ExtraType == Model.Entities.ExtraType.ThemeVideo) - .Select(song => song.Id) - .ToArray(); - } - - private set - { - _themeVideoIds = value; - } - } - [JsonIgnore] public string PreferredMetadataCountryCode { get; set; } @@ -1379,28 +1341,6 @@ namespace MediaBrowser.Controller.Entities }).OrderBy(i => i.Path).ToArray(); } - protected virtual BaseItem[] LoadExtras(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - return fileSystemChildren - .Where(child => child.IsDirectory && AllExtrasTypesFolderNames.ContainsKey(child.Name)) - .SelectMany(folder => LibraryManager - .ResolvePaths(FileSystem.GetFiles(folder.FullName), directoryService, null, new LibraryOptions()) - .OfType<Video>() - .Select(video => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - if (LibraryManager.GetItemById(video.Id) is Video dbItem) - { - video = dbItem; - } - - video.ExtraType = AllExtrasTypesFolderNames[folder.Name]; - return video; - }) - .OrderBy(video => video.Path)) // Sort them so that the list can be easily compared for changes - .ToArray(); - } - public Task RefreshMetadata(CancellationToken cancellationToken) { return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken); @@ -1434,13 +1374,8 @@ namespace MediaBrowser.Controller.Entities GetFileSystemChildren(options.DirectoryService).ToList() : new List<FileSystemMetadata>(); - var ownedItemsChanged = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false); + requiresSave = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false); await LibraryManager.UpdateImagesAsync(this).ConfigureAwait(false); // ensure all image properties in DB are fresh - - if (ownedItemsChanged) - { - requiresSave = true; - } } catch (Exception ex) { @@ -1516,35 +1451,12 @@ namespace MediaBrowser.Controller.Entities /// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns> protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { - var themeSongsChanged = false; - - var themeVideosChanged = false; - - var extrasChanged = false; - - var localTrailersChanged = false; - - if (IsFileProtocol && SupportsOwnedItems) + if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder) { - if (SupportsThemeMedia) - { - if (!IsInMixedFolder) - { - themeSongsChanged = await RefreshThemeSongs(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - themeVideosChanged = await RefreshThemeVideos(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - extrasChanged = await RefreshExtras(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - } - } - - if (this is IHasTrailers hasTrailers) - { - localTrailersChanged = await RefreshLocalTrailers(hasTrailers, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - } + return false; } - return themeSongsChanged || themeVideosChanged || extrasChanged || localTrailersChanged; + return await RefreshExtras(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); } protected virtual FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) @@ -1554,98 +1466,24 @@ namespace MediaBrowser.Controller.Entities return directoryService.GetFileSystemEntries(path); } - private async Task<bool> RefreshLocalTrailers(IHasTrailers item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newItems = LibraryManager.FindTrailers(this, fileSystemChildren, options.DirectoryService); - - var newItemIds = newItems.Select(i => i.Id); - - var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds); - var ownerId = item.Id; - - var tasks = newItems.Select(i => - { - var subOptions = new MetadataRefreshOptions(options); - - if (i.ExtraType != Model.Entities.ExtraType.Trailer || - i.OwnerId != ownerId || - !i.ParentId.Equals(Guid.Empty)) - { - i.ExtraType = Model.Entities.ExtraType.Trailer; - i.OwnerId = ownerId; - i.ParentId = Guid.Empty; - subOptions.ForceSave = true; - } - - return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); - }); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - item.LocalTrailerIds = newItemIds.ToArray(); - - return itemsChanged; - } - private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { - var extras = LoadExtras(fileSystemChildren, options.DirectoryService); - var themeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService); - var themeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService); - var newExtras = new BaseItem[extras.Length + themeVideos.Length + themeSongs.Length]; - extras.CopyTo(newExtras, 0); - themeVideos.CopyTo(newExtras, extras.Length); - themeSongs.CopyTo(newExtras, extras.Length + themeVideos.Length); - - var newExtraIds = newExtras.Select(i => i.Id).ToArray(); - + var extras = LibraryManager.FindExtras(item, fileSystemChildren).ToArray(); + var newExtraIds = extras.Select(i => i.Id).ToArray(); var extrasChanged = !item.ExtraIds.SequenceEqual(newExtraIds); - if (extrasChanged) + if (!extrasChanged) { - var ownerId = item.Id; - - var tasks = newExtras.Select(i => - { - var subOptions = new MetadataRefreshOptions(options); - if (i.OwnerId != ownerId || i.ParentId != Guid.Empty) - { - i.OwnerId = ownerId; - i.ParentId = Guid.Empty; - subOptions.ForceSave = true; - } - - return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); - }); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - item.ExtraIds = newExtraIds; + return false; } - return extrasChanged; - } - - private async Task<bool> RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService); - - var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToArray(); - - var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds); - var ownerId = item.Id; - var tasks = newThemeVideos.Select(i => + var tasks = extras.Select(i => { var subOptions = new MetadataRefreshOptions(options); - - if (!i.ExtraType.HasValue || - i.ExtraType.Value != Model.Entities.ExtraType.ThemeVideo || - i.OwnerId != ownerId || - !i.ParentId.Equals(Guid.Empty)) + if (i.OwnerId != ownerId || i.ParentId != Guid.Empty) { - i.ExtraType = Model.Entities.ExtraType.ThemeVideo; i.OwnerId = ownerId; i.ParentId = Guid.Empty; subOptions.ForceSave = true; @@ -1656,48 +1494,9 @@ namespace MediaBrowser.Controller.Entities await Task.WhenAll(tasks).ConfigureAwait(false); - // They are expected to be sorted by SortName - item.ThemeVideoIds = newThemeVideos.OrderBy(i => i.SortName).Select(i => i.Id).ToArray(); - - return themeVideosChanged; - } - - /// <summary> - /// Refreshes the theme songs. - /// </summary> - private async Task<bool> RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService); - var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToArray(); - - var themeSongsChanged = !item.ThemeSongIds.SequenceEqual(newThemeSongIds); - - var ownerId = item.Id; - - var tasks = newThemeSongs.Select(i => - { - var subOptions = new MetadataRefreshOptions(options); + item.ExtraIds = newExtraIds; - if (!i.ExtraType.HasValue || - i.ExtraType.Value != Model.Entities.ExtraType.ThemeSong || - i.OwnerId != ownerId || - !i.ParentId.Equals(Guid.Empty)) - { - i.ExtraType = Model.Entities.ExtraType.ThemeSong; - i.OwnerId = ownerId; - i.ParentId = Guid.Empty; - subOptions.ForceSave = true; - } - - return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); - }); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - // They are expected to be sorted by SortName - item.ThemeSongIds = newThemeSongs.OrderBy(i => i.SortName).Select(i => i.Id).ToArray(); - - return themeSongsChanged; + return true; } public string GetPresentationUniqueKey() @@ -2891,14 +2690,14 @@ namespace MediaBrowser.Controller.Entities StringComparison.OrdinalIgnoreCase); } - public IEnumerable<BaseItem> GetThemeSongs() + public IReadOnlyList<BaseItem> GetThemeSongs() { - return ThemeSongIds.Select(LibraryManager.GetItemById); + return GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeSong).ToArray(); } - public IEnumerable<BaseItem> GetThemeVideos() + public IReadOnlyList<BaseItem> GetThemeVideos() { - return ThemeVideoIds.Select(LibraryManager.GetItemById); + return GetExtras().Where(e => e.ExtraType == Model.Entities.ExtraType.ThemeVideo).ToArray(); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs index f4271678d..bb4a6ea94 100644 --- a/MediaBrowser.Controller/Entities/IHasTrailers.cs +++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs @@ -2,7 +2,6 @@ #pragma warning disable CS1591 -using System; using System.Collections.Generic; using MediaBrowser.Model.Entities; @@ -17,18 +16,10 @@ namespace MediaBrowser.Controller.Entities IReadOnlyList<MediaUrl> RemoteTrailers { get; set; } /// <summary> - /// Gets or sets the local trailer ids. + /// Gets the local trailers. /// </summary> - /// <value>The local trailer ids.</value> - IReadOnlyList<Guid> LocalTrailerIds { get; set; } - - /// <summary> - /// Gets or sets the remote trailer ids. - /// </summary> - /// <value>The remote trailer ids.</value> - IReadOnlyList<Guid> RemoteTrailerIds { get; set; } - - Guid Id { get; set; } + /// <value>The local trailers.</value> + IReadOnlyList<BaseItem> LocalTrailers { get; } } /// <summary> @@ -42,57 +33,6 @@ namespace MediaBrowser.Controller.Entities /// <param name="item">Media item.</param> /// <returns><see cref="IReadOnlyList{Guid}" />.</returns> public static int GetTrailerCount(this IHasTrailers item) - => item.LocalTrailerIds.Count + item.RemoteTrailerIds.Count; - - /// <summary> - /// Gets the trailer ids. - /// </summary> - /// <param name="item">Media item.</param> - /// <returns><see cref="IReadOnlyList{Guid}" />.</returns> - public static IReadOnlyList<Guid> GetTrailerIds(this IHasTrailers item) - { - var localIds = item.LocalTrailerIds; - var remoteIds = item.RemoteTrailerIds; - - var all = new Guid[localIds.Count + remoteIds.Count]; - var index = 0; - foreach (var id in localIds) - { - all[index++] = id; - } - - foreach (var id in remoteIds) - { - all[index++] = id; - } - - return all; - } - - /// <summary> - /// Gets the trailers. - /// </summary> - /// <param name="item">Media item.</param> - /// <returns><see cref="IReadOnlyList{BaseItem}" />.</returns> - public static IReadOnlyList<BaseItem> GetTrailers(this IHasTrailers item) - { - var localIds = item.LocalTrailerIds; - var remoteIds = item.RemoteTrailerIds; - var libraryManager = BaseItem.LibraryManager; - - var all = new BaseItem[localIds.Count + remoteIds.Count]; - var index = 0; - foreach (var id in localIds) - { - all[index++] = libraryManager.GetItemById(id); - } - - foreach (var id in remoteIds) - { - all[index++] = libraryManager.GetItemById(id); - } - - return all; - } + => item.LocalTrailers.Count + item.RemoteTrailers.Count; } } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index e46f99cd5..6b93d8d87 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -9,7 +9,6 @@ using System.Text.Json.Serialization; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; namespace MediaBrowser.Controller.Entities.Movies @@ -21,10 +20,6 @@ namespace MediaBrowser.Controller.Entities.Movies { public BoxSet() { - RemoteTrailers = Array.Empty<MediaUrl>(); - LocalTrailerIds = Array.Empty<Guid>(); - RemoteTrailerIds = Array.Empty<Guid>(); - DisplayOrder = ItemSortBy.PremiereDate; } @@ -38,10 +33,9 @@ namespace MediaBrowser.Controller.Entities.Movies public override bool SupportsPeople => true; /// <inheritdoc /> - public IReadOnlyList<Guid> LocalTrailerIds { get; set; } - - /// <inheritdoc /> - public IReadOnlyList<Guid> RemoteTrailerIds { get; set; } + public IReadOnlyList<BaseItem> LocalTrailers => GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.Trailer) + .ToArray(); /// <summary> /// Gets or sets the display order. diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index b54bbf5eb..6f1a0a8cf 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -7,12 +7,9 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text.Json.Serialization; -using System.Threading; -using System.Threading.Tasks; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Entities.Movies @@ -22,22 +19,29 @@ namespace MediaBrowser.Controller.Entities.Movies /// </summary> public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping { - public Movie() - { - SpecialFeatureIds = Array.Empty<Guid>(); - RemoteTrailers = Array.Empty<MediaUrl>(); - LocalTrailerIds = Array.Empty<Guid>(); - RemoteTrailerIds = Array.Empty<Guid>(); - } + private IReadOnlyList<Guid> _specialFeatureIds; /// <inheritdoc /> - public IReadOnlyList<Guid> SpecialFeatureIds { get; set; } + public IReadOnlyList<Guid> SpecialFeatureIds + { + get + { + return _specialFeatureIds ??= GetExtras() + .Where(extra => extra.ExtraType != Model.Entities.ExtraType.Trailer) + .Select(song => song.Id) + .ToArray(); + } - /// <inheritdoc /> - public IReadOnlyList<Guid> LocalTrailerIds { get; set; } + set + { + _specialFeatureIds = value; + } + } /// <inheritdoc /> - public IReadOnlyList<Guid> RemoteTrailerIds { get; set; } + public IReadOnlyList<BaseItem> LocalTrailers => GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.Trailer) + .ToArray(); /// <summary> /// Gets or sets the name of the TMDB collection. @@ -66,54 +70,6 @@ namespace MediaBrowser.Controller.Entities.Movies return 2.0 / 3; } - protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - // Must have a parent to have special features - // In other words, it must be part of the Parent/Child tree - if (IsFileProtocol && SupportsOwnedItems && !IsInMixedFolder) - { - var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - if (specialFeaturesChanged) - { - hasChanges = true; - } - } - - return hasChanges; - } - - private async Task<bool> RefreshSpecialFeatures(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newItems = LibraryManager.FindExtras(this, fileSystemChildren, options.DirectoryService).ToList(); - var newItemIds = newItems.Select(i => i.Id).ToArray(); - - var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds); - - var ownerId = Id; - - var tasks = newItems.Select(i => - { - var subOptions = new MetadataRefreshOptions(options); - - if (i.OwnerId != ownerId) - { - i.OwnerId = ownerId; - subOptions.ForceSave = true; - } - - return RefreshMetadataForOwnedItem(i, false, subOptions, cancellationToken); - }); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - SpecialFeatureIds = newItemIds; - - return itemsChanged; - } - /// <inheritdoc /> public override UnratedItem GetBlockUnratedType() { diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 27c3ff81b..dcc752f8c 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -20,18 +20,10 @@ namespace MediaBrowser.Controller.Entities.TV /// </summary> public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries { - public Episode() - { - RemoteTrailers = Array.Empty<MediaUrl>(); - LocalTrailerIds = Array.Empty<Guid>(); - RemoteTrailerIds = Array.Empty<Guid>(); - } - - /// <inheritdoc /> - public IReadOnlyList<Guid> LocalTrailerIds { get; set; } - /// <inheritdoc /> - public IReadOnlyList<Guid> RemoteTrailerIds { get; set; } + public IReadOnlyList<BaseItem> LocalTrailers => GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.Trailer) + .ToArray(); /// <summary> /// Gets or sets the season in which it aired. diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index e4933e968..90fcffe32 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -27,9 +27,6 @@ namespace MediaBrowser.Controller.Entities.TV { public Series() { - RemoteTrailers = Array.Empty<MediaUrl>(); - LocalTrailerIds = Array.Empty<Guid>(); - RemoteTrailerIds = Array.Empty<Guid>(); AirDays = Array.Empty<DayOfWeek>(); } @@ -53,10 +50,9 @@ namespace MediaBrowser.Controller.Entities.TV public override bool SupportsPeople => true; /// <inheritdoc /> - public IReadOnlyList<Guid> LocalTrailerIds { get; set; } - - /// <inheritdoc /> - public IReadOnlyList<Guid> RemoteTrailerIds { get; set; } + public IReadOnlyList<BaseItem> LocalTrailers => GetExtras() + .Where(extra => extra.ExtraType == Model.Entities.ExtraType.Trailer) + .ToArray(); /// <summary> /// Gets or sets the display order. diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 1cff72037..25511f9d9 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -745,10 +745,9 @@ namespace MediaBrowser.Controller.Entities var val = query.HasTrailer.Value; var trailerCount = 0; - var hasTrailers = item as IHasTrailers; - if (hasTrailers != null) + if (item is IHasTrailers hasTrailers) { - trailerCount = hasTrailers.GetTrailerIds().Count; + trailerCount = hasTrailers.GetTrailerCount(); } var ok = val ? trailerCount > 0 : trailerCount == 0; @@ -763,7 +762,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasThemeSong.Value; - var themeCount = item.ThemeSongIds.Length; + var themeCount = item.GetThemeSongs().Count; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok) @@ -776,7 +775,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasThemeVideo.Value; - var themeCount = item.ThemeVideoIds.Length; + var themeCount = item.GetThemeVideos().Count; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 1e1e2adb8..1ae28abde 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -using Emby.Naming.Common; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; @@ -426,29 +425,15 @@ namespace MediaBrowser.Controller.Library /// <returns>Guid.</returns> Guid GetNewItemId(string key, Type type); - /// <summary> - /// Finds the trailers. - /// </summary> - /// <param name="owner">The owner.</param> - /// <param name="fileSystemChildren">The file system children.</param> - /// <param name="directoryService">The directory service.</param> - /// <returns>IEnumerable<Trailer>.</returns> - IEnumerable<Video> FindTrailers( - BaseItem owner, - List<FileSystemMetadata> fileSystemChildren, - IDirectoryService directoryService); - /// <summary> /// Finds the extras. /// </summary> /// <param name="owner">The owner.</param> /// <param name="fileSystemChildren">The file system children.</param> - /// <param name="directoryService">The directory service.</param> /// <returns>IEnumerable<Video>.</returns> IEnumerable<Video> FindExtras( BaseItem owner, - List<FileSystemMetadata> fileSystemChildren, - IDirectoryService directoryService); + List<FileSystemMetadata> fileSystemChildren); /// <summary> /// Gets the collection folders. diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index f79147803..46f1fede3 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -106,7 +106,7 @@ namespace MediaBrowser.LocalMetadata.Images { if (!item.IsFileProtocol) { - return Enumerable.Empty<FileSystemMetadata>(); + yield break; } var path = item.ContainingFolderPath; @@ -114,20 +114,21 @@ namespace MediaBrowser.LocalMetadata.Images // Exit if the cache dir does not exist, alternative solution is to create it, but that's a lot of empty dirs... if (!Directory.Exists(path)) { - return Enumerable.Empty<FileSystemMetadata>(); + yield break; } - if (includeDirectories) + var files = directoryService.GetFileSystemEntries(path).OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty)); + var count = BaseItem.SupportedImageExtensions.Length; + foreach (var file in files) { - return directoryService.GetFileSystemEntries(path) - .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase) || i.IsDirectory) - - .OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty)); + for (var i = 0; i < count; i++) + { + if ((includeDirectories && file.IsDirectory) || string.Equals(BaseItem.SupportedImageExtensions[i], file.Extension, StringComparison.OrdinalIgnoreCase)) + { + yield return file; + } + } } - - return directoryService.GetFiles(path) - .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)) - .OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty)); } /// <inheritdoc /> diff --git a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs index d13e89cee..8dd637559 100644 --- a/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/ExtraTests.cs @@ -81,9 +81,7 @@ namespace Jellyfin.Naming.Tests.Video private void Test(string input, ExtraType? expectedType) { - var parser = GetExtraTypeParser(_videoOptions); - - var extraType = parser.GetExtraInfo(input).ExtraType; + var extraType = ExtraResolver.GetExtraInfo(input, _videoOptions).ExtraType; Assert.Equal(expectedType, extraType); } @@ -93,14 +91,9 @@ namespace Jellyfin.Naming.Tests.Video { var rule = new ExtraRule(ExtraType.Unknown, ExtraRuleType.Regex, @"([eE]x(tra)?\.\w+)", MediaType.Video); var options = new NamingOptions { VideoExtraRules = new[] { rule } }; - var res = GetExtraTypeParser(options).GetExtraInfo("extra.mp4"); + var res = ExtraResolver.GetExtraInfo("extra.mp4", options); Assert.Equal(rule, res.Rule); } - - private ExtraResolver GetExtraTypeParser(NamingOptions videoOptions) - { - return new ExtraResolver(videoOptions); - } } } diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs index d02f8ae92..323457d09 100644 --- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -30,8 +30,8 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); - Assert.Single(result[0].Extras); + Assert.Single(result.Where(v => v.ExtraType == null)); + Assert.Single(result.Where(v => v.ExtraType != null)); } [Fact] @@ -53,8 +53,8 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); - Assert.Single(result[0].Extras); + Assert.Single(result.Where(v => v.ExtraType == null)); + Assert.Single(result.Where(v => v.ExtraType != null)); Assert.Equal(2, result[0].AlternateVersions.Count); } @@ -102,7 +102,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Equal(7, result.Count); - Assert.Empty(result[0].Extras); Assert.Empty(result[0].AlternateVersions); } @@ -130,7 +129,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Single(result); - Assert.Empty(result[0].Extras); Assert.Equal(7, result[0].AlternateVersions.Count); } @@ -159,7 +157,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Equal(9, result.Count); - Assert.Empty(result[0].Extras); Assert.Empty(result[0].AlternateVersions); } @@ -184,7 +181,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Equal(5, result.Count); - Assert.Empty(result[0].Extras); Assert.Empty(result[0].AlternateVersions); } @@ -211,7 +207,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Equal(5, result.Count); - Assert.Empty(result[0].Extras); Assert.Empty(result[0].AlternateVersions); } @@ -239,7 +234,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Single(result); - Assert.Empty(result[0].Extras); Assert.Equal(7, result[0].AlternateVersions.Count); Assert.False(result[0].AlternateVersions[2].Is3D); Assert.True(result[0].AlternateVersions[3].Is3D); @@ -270,7 +264,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Single(result); - Assert.Empty(result[0].Extras); Assert.Equal(7, result[0].AlternateVersions.Count); Assert.False(result[0].AlternateVersions[3].Is3D); Assert.True(result[0].AlternateVersions[4].Is3D); @@ -320,7 +313,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Equal(7, result.Count); - Assert.Empty(result[0].Extras); Assert.Empty(result[0].AlternateVersions); } @@ -347,7 +339,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Equal(5, result.Count); - Assert.Empty(result[0].Extras); Assert.Empty(result[0].AlternateVersions); } @@ -369,7 +360,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Single(result); - Assert.Empty(result[0].Extras); Assert.Single(result[0].AlternateVersions); } @@ -391,7 +381,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Single(result); - Assert.Empty(result[0].Extras); Assert.Single(result[0].AlternateVersions); } @@ -413,7 +402,6 @@ namespace Jellyfin.Naming.Tests.Video _namingOptions).ToList(); Assert.Single(result); - Assert.Empty(result[0].Extras); Assert.Single(result[0].AlternateVersions); } diff --git a/tests/Jellyfin.Naming.Tests/Video/StackTests.cs b/tests/Jellyfin.Naming.Tests/Video/StackTests.cs index 8794d3ebe..41da0e077 100644 --- a/tests/Jellyfin.Naming.Tests/Video/StackTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/StackTests.cs @@ -22,9 +22,7 @@ namespace Jellyfin.Naming.Tests.Video "Bad Boys (2006)-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); TestStackInfo(result[0], "Bad Boys (2006)", 4); @@ -39,9 +37,7 @@ namespace Jellyfin.Naming.Tests.Video "Bad Boys (2007).mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -55,9 +51,7 @@ namespace Jellyfin.Naming.Tests.Video "Bad Boys 2007.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -71,9 +65,7 @@ namespace Jellyfin.Naming.Tests.Video "300 (2007).mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -87,9 +79,7 @@ namespace Jellyfin.Naming.Tests.Video "300 2007.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -103,9 +93,7 @@ namespace Jellyfin.Naming.Tests.Video "Star Trek 2- The wrath of khan.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -119,9 +107,7 @@ namespace Jellyfin.Naming.Tests.Video "Red Riding in the Year of Our Lord 1974 (2009).mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -135,9 +121,7 @@ namespace Jellyfin.Naming.Tests.Video "d:/movies/300 2006 part2.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); TestStackInfo(result[0], "300 2006", 2); @@ -155,9 +139,7 @@ namespace Jellyfin.Naming.Tests.Video "Bad Boys (2006)-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); TestStackInfo(result[0], "Bad Boys (2006).stv.unrated.multi.1080p.bluray.x264-rough", 4); @@ -175,9 +157,7 @@ namespace Jellyfin.Naming.Tests.Video "Bad Boys (2006)-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -194,9 +174,7 @@ namespace Jellyfin.Naming.Tests.Video "300 (2006)-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); TestStackInfo(result[0], "300 (2006)", 4); @@ -214,9 +192,7 @@ namespace Jellyfin.Naming.Tests.Video "Bad Boys (2006)-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); TestStackInfo(result[0], "Bad Boys (2006)", 3); @@ -238,9 +214,7 @@ namespace Jellyfin.Naming.Tests.Video "300 (2006)-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Equal(2, result.Count); TestStackInfo(result[1], "Bad Boys (2006)", 4); @@ -256,9 +230,7 @@ namespace Jellyfin.Naming.Tests.Video "blah blah - cd 2" }; - var resolver = GetResolver(); - - var result = resolver.ResolveDirectories(files).ToList(); + var result = StackResolver.ResolveDirectories(files, _namingOptions).ToList(); Assert.Single(result); TestStackInfo(result[0], "blah blah", 2); @@ -275,9 +247,7 @@ namespace Jellyfin.Naming.Tests.Video "300-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); @@ -297,9 +267,7 @@ namespace Jellyfin.Naming.Tests.Video "Avengers part3.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -328,9 +296,7 @@ namespace Jellyfin.Naming.Tests.Video "300-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Equal(3, result.Count); @@ -354,9 +320,7 @@ namespace Jellyfin.Naming.Tests.Video "300 (2006)-trailer.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); @@ -375,9 +339,7 @@ namespace Jellyfin.Naming.Tests.Video new FileSystemMetadata { FullName = "300 (2006) part1", IsDirectory = true } }; - var resolver = GetResolver(); - - var result = resolver.Resolve(files).ToList(); + var result = StackResolver.Resolve(files, _namingOptions).ToList(); Assert.Equal(2, result.Count); TestStackInfo(result[0], "300 (2006)", 3); @@ -397,9 +359,7 @@ namespace Jellyfin.Naming.Tests.Video "Harry Potter and the Deathly Hallows 4.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Empty(result); } @@ -414,9 +374,7 @@ namespace Jellyfin.Naming.Tests.Video "Neverland (2011)[720p][PG][Voted 6.5][Family-Fantasy]part2.mkv" }; - var resolver = GetResolver(); - - var result = resolver.ResolveFiles(files).ToList(); + var result = StackResolver.ResolveFiles(files, _namingOptions).ToList(); Assert.Single(result); Assert.Equal(2, result[0].Files.Count); @@ -432,9 +390,7 @@ namespace Jellyfin.Naming.Tests.Video @"M:/Movies (DVD)/Movies (Musical)/The Sound of Music/The Sound of Music (1965) (Disc 02)" }; - var resolver = GetResolver(); - - var result = resolver.ResolveDirectories(files).ToList(); + var result = StackResolver.ResolveDirectories(files, _namingOptions).ToList(); Assert.Single(result); Assert.Equal(2, result[0].Files.Count); @@ -445,10 +401,5 @@ namespace Jellyfin.Naming.Tests.Video Assert.Equal(fileCount, stack.Files.Count); Assert.Equal(name, stack.Name); } - - private StackResolver GetResolver() - { - return new StackResolver(_namingOptions); - } } } diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs index 9e0776c3c..5d9ef1340 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs @@ -2,6 +2,7 @@ using System; using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using Xunit; @@ -48,16 +49,25 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Equal(5, result.Count); + Assert.Equal(11, result.Count); var batman = result.FirstOrDefault(x => string.Equals(x.Name, "Batman", StringComparison.Ordinal)); Assert.NotNull(batman); Assert.Equal(3, batman!.Files.Count); - Assert.Equal(3, batman!.Extras.Count); var harry = result.FirstOrDefault(x => string.Equals(x.Name, "Harry Potter and the Deathly Hallows", StringComparison.Ordinal)); Assert.NotNull(harry); Assert.Equal(4, harry!.Files.Count); - Assert.Equal(2, harry!.Extras.Count); + + Assert.False(result[2].ExtraType.HasValue); + + Assert.Equal(ExtraType.Trailer, result[3].ExtraType); + Assert.Equal(ExtraType.Trailer, result[4].ExtraType); + Assert.Equal(ExtraType.DeletedScene, result[5].ExtraType); + Assert.Equal(ExtraType.Sample, result[6].ExtraType); + Assert.Equal(ExtraType.Trailer, result[7].ExtraType); + Assert.Equal(ExtraType.Trailer, result[8].ExtraType); + Assert.Equal(ExtraType.Trailer, result[9].ExtraType); + Assert.Equal(ExtraType.Trailer, result[10].ExtraType); } [Fact] @@ -97,7 +107,8 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); } [Fact] @@ -117,7 +128,8 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); } [Fact] @@ -138,15 +150,18 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); + Assert.Equal(ExtraType.Trailer, result[2].ExtraType); } [Fact] - public void TestDifferentNames() + public void Resolve_SameNameAndYear_ReturnsSingleItem() { var files = new[] { "Looper (2012)-trailer.mkv", + "Looper 2012-trailer.mkv", "Looper.2012.bluray.720p.x264.mkv" }; @@ -158,7 +173,30 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); + Assert.Equal(ExtraType.Trailer, result[2].ExtraType); + } + + [Fact] + public void Resolve_TrailerMatchesFolderName_ReturnsSingleItem() + { + var files = new[] + { + "/movies/Looper (2012)/Looper (2012)-trailer.mkv", + "/movies/Looper (2012)/Looper.bluray.720p.x264.mkv" + }; + + var result = VideoListResolver.Resolve( + files.Select(i => new FileSystemMetadata + { + IsDirectory = false, + FullName = i + }).ToList(), + _namingOptions).ToList(); + + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); } [Fact] @@ -233,27 +271,7 @@ namespace Jellyfin.Naming.Tests.Video { @"No (2012) part1.mp4", @"No (2012) part2.mp4", - @"No (2012) part1-trailer.mp4" - }; - - var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), - _namingOptions).ToList(); - - Assert.Single(result); - } - - [Fact] - public void TestStackedWithTrailer2() - { - var files = new[] - { - @"No (2012) part1.mp4", - @"No (2012) part2.mp4", + @"No (2012) part1-trailer.mp4", @"No (2012)-trailer.mp4" }; @@ -265,7 +283,10 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.Equal(3, result.Count); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); + Assert.Equal(ExtraType.Trailer, result[2].ExtraType); } [Fact] @@ -276,7 +297,7 @@ namespace Jellyfin.Naming.Tests.Video @"/Movies/Top Gun (1984)/movie.mp4", @"/Movies/Top Gun (1984)/Top Gun (1984)-trailer.mp4", @"/Movies/Top Gun (1984)/Top Gun (1984)-trailer2.mp4", - @"trailer.mp4" + @"/Movies/trailer.mp4" }; var result = VideoListResolver.Resolve( @@ -287,7 +308,10 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); + Assert.Equal(ExtraType.Trailer, result[2].ExtraType); + Assert.Equal(ExtraType.Trailer, result[3].ExtraType); } [Fact] @@ -396,7 +420,7 @@ namespace Jellyfin.Naming.Tests.Video var files = new[] { @"/Server/Despicable Me/Despicable Me (2010).mkv", - @"/Server/Despicable Me/movie-trailer.mkv" + @"/Server/Despicable Me/trailer.mkv" }; var result = VideoListResolver.Resolve( @@ -407,18 +431,17 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); } [Fact] - public void TestTrailerFalsePositives() + public void Resolve_TrailerInTrailersFolder_ReturnsCorrectExtraType() { var files = new[] { - @"/Server/Despicable Me/Skyscraper (2018) - Big Game Spot.mkv", - @"/Server/Despicable Me/Skyscraper (2018) - Trailer.mkv", - @"/Server/Despicable Me/Baywatch (2017) - Big Game Spot.mkv", - @"/Server/Despicable Me/Baywatch (2017) - Trailer.mkv" + @"/Server/Despicable Me/Despicable Me (2010).mkv", + @"/Server/Despicable Me/trailers/some title.mkv" }; var result = VideoListResolver.Resolve( @@ -429,7 +452,8 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Equal(4, result.Count); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); } [Fact] @@ -449,7 +473,8 @@ namespace Jellyfin.Naming.Tests.Video }).ToList(), _namingOptions).ToList(); - Assert.Single(result); + Assert.False(result[0].ExtraType.HasValue); + Assert.Equal(ExtraType.Trailer, result[1].ExtraType); } [Fact] diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs index a0fe4a5cf..362c3216f 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs @@ -1,4 +1,5 @@ -using Emby.Server.Implementations.Library.Resolvers.TV; +using Emby.Naming.Common; +using Emby.Server.Implementations.Library.Resolvers.TV; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -13,12 +14,14 @@ namespace Jellyfin.Server.Implementations.Tests.Library { public class EpisodeResolverTest { + private static readonly NamingOptions _namingOptions = new (); + [Fact] public void Resolve_GivenVideoInExtrasFolder_DoesNotResolveToEpisode() { var parent = new Folder { Name = "extras" }; - var episodeResolver = new EpisodeResolver(null); + var episodeResolver = new EpisodeResolver(_namingOptions); var itemResolveArgs = new ItemResolveArgs( Mock.Of<IServerApplicationPaths>(), Mock.Of<IDirectoryService>()) @@ -41,14 +44,14 @@ namespace Jellyfin.Server.Implementations.Tests.Library // Have to create a mock because of moq proxies not being castable to a concrete implementation // https://github.com/jellyfin/jellyfin/blob/ab0cff8556403e123642dc9717ba778329554634/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs#L48 - var episodeResolver = new EpisodeResolverMock(); + var episodeResolver = new EpisodeResolverMock(_namingOptions); var itemResolveArgs = new ItemResolveArgs( Mock.Of<IServerApplicationPaths>(), Mock.Of<IDirectoryService>()) { Parent = series, CollectionType = CollectionType.TvShows, - FileInfo = new FileSystemMetadata() + FileInfo = new FileSystemMetadata { FullName = "Extras/Extras S01E01.mkv" } @@ -58,7 +61,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library private class EpisodeResolverMock : EpisodeResolver { - public EpisodeResolverMock() : base(null) + public EpisodeResolverMock(NamingOptions namingOptions) : base(namingOptions) { } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs new file mode 100644 index 000000000..10afadbef --- /dev/null +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs @@ -0,0 +1,178 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AutoFixture; +using AutoFixture.AutoMoq; +using Emby.Naming.Common; +using Emby.Server.Implementations.Library.Resolvers; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Controller.Sorting; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; +using Moq; +using Xunit; + +namespace Jellyfin.Server.Implementations.Tests.Library.LibraryManager; + +public class FindExtrasTests +{ + private readonly Emby.Server.Implementations.Library.LibraryManager _libraryManager; + + public FindExtrasTests() + { + var fixture = new Fixture().Customize(new AutoMoqCustomization()); + fixture.Register(() => new NamingOptions()); + var configMock = fixture.Freeze<Mock<IServerConfigurationManager>>(); + configMock.Setup(c => c.ApplicationPaths.ProgramDataPath).Returns("/data"); + var fileSystemMock = fixture.Freeze<Mock<IFileSystem>>(); + fileSystemMock.Setup(f => f.GetFileInfo(It.IsAny<string>())).Returns<string>(path => new FileSystemMetadata { FullName = path }); + _libraryManager = fixture.Build<Emby.Server.Implementations.Library.LibraryManager>().Do(s => s.AddParts( + fixture.Create<IEnumerable<IResolverIgnoreRule>>(), + new List<IItemResolver> { new GenericVideoResolver<Video>(fixture.Create<NamingOptions>()) }, + fixture.Create<IEnumerable<IIntroProvider>>(), + fixture.Create<IEnumerable<IBaseItemComparer>>(), + fixture.Create<IEnumerable<ILibraryPostScanTask>>())) + .Create(); + + // This is pretty terrible but unavoidable + BaseItem.FileSystem ??= fixture.Create<IFileSystem>(); + BaseItem.MediaSourceManager ??= fixture.Create<IMediaSourceManager>(); + } + + [Fact] + public void FindExtras_SeparateMovieFolder_FindsCorrectExtras() + { + var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" }; + var paths = new List<string> + { + "/movies/Up/Up.mkv", + "/movies/Up/Up - trailer.mkv", + "/movies/Up/Up - sample.mkv", + "/movies/Up/Up something else.mkv" + }; + + var files = paths.Select(p => new FileSystemMetadata + { + FullName = p, + IsDirectory = false + }).ToList(); + + var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + + Assert.Equal(2, extras.Count); + Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); + Assert.Equal(ExtraType.Sample, extras[1].ExtraType); + } + + [Fact] + public void FindExtras_SeparateMovieFolderWithMixedExtras_FindsCorrectExtras() + { + var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" }; + var paths = new List<string> + { + "/movies/Up/Up.mkv", + "/movies/Up/Up - trailer.mkv", + "/movies/Up/trailers/some trailer.mkv", + "/movies/Up/behind the scenes/the making of Up.mkv", + "/movies/Up/behind the scenes.mkv", + "/movies/Up/Up - sample.mkv", + "/movies/Up/Up something else.mkv" + }; + + var files = paths.Select(p => new FileSystemMetadata + { + FullName = p, + IsDirectory = false + }).ToList(); + + var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + + Assert.Equal(4, extras.Count); + Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); + Assert.Equal(ExtraType.Trailer, extras[1].ExtraType); + Assert.Equal(ExtraType.BehindTheScenes, extras[2].ExtraType); + Assert.Equal(ExtraType.Sample, extras[3].ExtraType); + } + + [Fact] + public void FindExtras_SeparateMovieFolderWithMixedExtras_FindsOnlyExtrasInMovieFolder() + { + var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" }; + var paths = new List<string> + { + "/movies/Up/Up.mkv", + "/movies/Up/trailer.mkv", + "/movies/Another Movie/trailer.mkv" + }; + + var files = paths.Select(p => new FileSystemMetadata + { + FullName = p, + IsDirectory = false + }).ToList(); + + var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + + Assert.Single(extras); + Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); + Assert.Equal("trailer", extras[0].FileNameWithoutExtension); + Assert.Equal("/movies/Up/trailer.mkv", extras[0].Path); + } + + [Fact] + public void FindExtras_SeparateMovieFolderWithParts_FindsCorrectExtras() + { + var owner = new Movie { Name = "Up", Path = "/movies/Up/Up - part1.mkv" }; + var paths = new List<string> + { + "/movies/Up/Up - part1.mkv", + "/movies/Up/Up - part2.mkv", + "/movies/Up/trailer.mkv", + "/movies/Another Movie/trailer.mkv" + }; + + var files = paths.Select(p => new FileSystemMetadata + { + FullName = p, + IsDirectory = false + }).ToList(); + + var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + + Assert.Single(extras); + Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); + Assert.Equal("trailer", extras[0].FileNameWithoutExtension); + Assert.Equal("/movies/Up/trailer.mkv", extras[0].Path); + } + + [Fact] + public void FindExtras_SeriesWithTrailers_FindsCorrectExtras() + { + var owner = new Series { Name = "Dexter", Path = "/series/Dexter" }; + var paths = new List<string> + { + "/series/Dexter/Season 1/S01E01.mkv", + "/series/Dexter/trailer.mkv", + "/series/Dexter/trailers/trailer2.mkv", + }; + + var files = paths.Select(p => new FileSystemMetadata + { + FullName = p, + IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p)) + }).ToList(); + + var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + + Assert.Equal(2, extras.Count); + Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); + Assert.Equal("trailer", extras[0].FileNameWithoutExtension); + Assert.Equal("/series/Dexter/trailer.mkv", extras[0].Path); + Assert.Equal("/series/Dexter/trailers/trailer2.mkv", extras[1].Path); + } +} -- cgit v1.2.3 From c5569c701c8aaaa70b17c0cf5ce8d425d5e69b5c Mon Sep 17 00:00:00 2001 From: cvium <clausvium@gmail.com> Date: Sun, 12 Dec 2021 19:04:22 +0100 Subject: Folder can't have extras --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index ad20ea334..200f98cc9 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1451,7 +1451,7 @@ namespace MediaBrowser.Controller.Entities /// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns> protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { - if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder) + if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder || this.GetType() == typeof(Folder)) { return false; } -- cgit v1.2.3 From 0edf77994ac7f1890b22d828c54f91b8f4ca1486 Mon Sep 17 00:00:00 2001 From: Cody Robibero <cody@robibe.ro> Date: Tue, 14 Dec 2021 07:41:29 -0700 Subject: Cache BaseItemKind --- MediaBrowser.Controller/Entities/BaseItem.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index b1ac2fe8e..ce37c7937 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -40,6 +40,8 @@ namespace MediaBrowser.Controller.Entities /// </summary> public abstract class BaseItem : IHasProviderIds, IHasLookupInfo<ItemLookupInfo>, IEquatable<BaseItem> { + private BaseItemKind? _baseItemKind; + /// <summary> /// The trailer folder name. /// </summary> @@ -2009,7 +2011,7 @@ namespace MediaBrowser.Controller.Entities public BaseItemKind GetBaseItemKind() { - return Enum.Parse<BaseItemKind>(GetClientTypeName()); + return _baseItemKind ??= Enum.Parse<BaseItemKind>(GetClientTypeName()); } /// <summary> -- cgit v1.2.3 From 91f3ce31096070fa21409aedcbd45e2a530833fe Mon Sep 17 00:00:00 2001 From: cvium <clausvium@gmail.com> Date: Sun, 19 Dec 2021 18:24:05 +0100 Subject: Use == instead of Object.Equals to avoid closure allocation --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 4114ff7b0..82d11c523 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2739,7 +2739,7 @@ namespace MediaBrowser.Controller.Entities } /// <inheritdoc /> - public bool Equals(BaseItem other) => Equals(Id, other?.Id); + public bool Equals(BaseItem other) => Id == other?.Id; /// <inheritdoc /> public override int GetHashCode() => HashCode.Combine(Id); -- cgit v1.2.3 From 83a94aa612f2451acc1e9ce7fcfc5c88b7989396 Mon Sep 17 00:00:00 2001 From: cvium <clausvium@gmail.com> Date: Mon, 20 Dec 2021 12:15:20 +0100 Subject: Fix extras folders --- Emby.Naming/Common/NamingOptions.cs | 29 ++++- Emby.Naming/Video/VideoListResolver.cs | 7 +- .../Library/CoreResolutionIgnoreRule.cs | 18 +--- .../Library/LibraryManager.cs | 67 ++++++++++-- .../Library/Resolvers/Movies/MovieResolver.cs | 7 +- MediaBrowser.Controller/Entities/BaseItem.cs | 93 +--------------- MediaBrowser.Controller/Library/ILibraryManager.cs | 11 +- .../Images/LocalImageProvider.cs | 3 +- .../Video/MultiVersionTests.cs | 104 ++++-------------- .../Video/VideoListResolverTests.cs | 120 ++++----------------- .../Library/LibraryManager/FindExtrasTests.cs | 78 +++++++++++--- 11 files changed, 210 insertions(+), 327 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Naming/Common/NamingOptions.cs b/Emby.Naming/Common/NamingOptions.cs index b97e9d763..aa62a47f1 100644 --- a/Emby.Naming/Common/NamingOptions.cs +++ b/Emby.Naming/Common/NamingOptions.cs @@ -1,6 +1,7 @@ #pragma warning disable CA1819 using System; +using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using Emby.Naming.Video; @@ -475,6 +476,12 @@ namespace Emby.Naming.Common "theme", MediaType.Audio), + new ExtraRule( + ExtraType.ThemeSong, + ExtraRuleType.DirectoryName, + "theme-music", + MediaType.Audio), + new ExtraRule( ExtraType.Scene, ExtraRuleType.Suffix, @@ -569,7 +576,7 @@ namespace Emby.Naming.Common ExtraType.Unknown, ExtraRuleType.DirectoryName, "extras", - MediaType.Video), + MediaType.Video) }; Format3DRules = new[] @@ -681,9 +688,29 @@ namespace Emby.Naming.Common .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); + AllExtrasTypesFolderNames = new Dictionary<string, ExtraType>(StringComparer.OrdinalIgnoreCase) + { + ["trailers"] = ExtraType.Trailer, + ["theme-music"] = ExtraType.ThemeSong, + ["backdrops"] = ExtraType.ThemeVideo, + ["extras"] = ExtraType.Unknown, + ["behind the scenes"] = ExtraType.BehindTheScenes, + ["deleted scenes"] = ExtraType.DeletedScene, + ["interviews"] = ExtraType.Interview, + ["scenes"] = ExtraType.Scene, + ["samples"] = ExtraType.Sample, + ["shorts"] = ExtraType.Clip, + ["featurettes"] = ExtraType.Clip + }; + Compile(); } + /// <summary> + /// Gets or sets the folder name to extra types mapping. + /// </summary> + public Dictionary<string, ExtraType> AllExtrasTypesFolderNames { get; set; } + /// <summary> /// Gets or sets list of audio file extensions. /// </summary> diff --git a/Emby.Naming/Video/VideoListResolver.cs b/Emby.Naming/Video/VideoListResolver.cs index bce7cb47f..309b18b53 100644 --- a/Emby.Naming/Video/VideoListResolver.cs +++ b/Emby.Naming/Video/VideoListResolver.cs @@ -21,13 +21,8 @@ namespace Emby.Naming.Video /// <param name="supportMultiVersion">Indication we should consider multi-versions of content.</param> /// <param name="parseName">Whether to parse the name or use the filename.</param> /// <returns>Returns enumerable of <see cref="VideoInfo"/> which groups files together when related.</returns> - public static IReadOnlyList<VideoInfo> Resolve(IEnumerable<FileSystemMetadata> files, NamingOptions namingOptions, bool supportMultiVersion = true, bool parseName = true) + public static IReadOnlyList<VideoInfo> Resolve(IReadOnlyList<VideoFileInfo> videoInfos, NamingOptions namingOptions, bool supportMultiVersion = true, bool parseName = true) { - var videoInfos = files - .Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, namingOptions, parseName)) - .OfType<VideoFileInfo>() - .ToList(); - // Filter out all extras, otherwise they could cause stacks to not be resolved // See the unit test TestStackedWithTrailer var nonExtras = videoInfos diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index 29758a078..e558fbe27 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -54,20 +54,10 @@ namespace Emby.Server.Implementations.Library { if (parent != null) { - // Ignore trailer folders but allow it at the collection level - if (string.Equals(filename, BaseItem.TrailersFolderName, StringComparison.OrdinalIgnoreCase) - && !(parent is AggregateFolder) - && !(parent is UserRootFolder)) - { - return true; - } - - if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) + // Ignore extras folders but allow it at the collection level + if (_namingOptions.AllExtrasTypesFolderNames.ContainsKey(filename) + && parent is not AggregateFolder + && parent is not UserRootFolder) { return true; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 8cc9a2fd5..224550f5f 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -531,8 +531,8 @@ namespace Emby.Server.Implementations.Library return key.GetMD5(); } - public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null) - => ResolvePath(fileInfo, new DirectoryService(_fileSystem), null, parent); + public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null, IDirectoryService directoryService = null) + => ResolvePath(fileInfo, directoryService ?? new DirectoryService(_fileSystem), null, parent); private BaseItem ResolvePath( FileSystemMetadata fileInfo, @@ -652,7 +652,7 @@ namespace Emby.Server.Implementations.Library return !args.ContainsFileSystemEntryByName(".ignore"); } - public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType) + public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType = null) { return ResolvePaths(files, directoryService, parent, libraryOptions, collectionType, EntityResolvers); } @@ -2683,7 +2683,7 @@ namespace Emby.Server.Implementations.Library }; } - public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren) + public IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) { var ownerVideoInfo = VideoResolver.Resolve(owner.Path, owner.IsFolder, _namingOptions); if (ownerVideoInfo == null) @@ -2692,17 +2692,36 @@ namespace Emby.Server.Implementations.Library } var count = fileSystemChildren.Count; - var files = new List<FileSystemMetadata>(); + var files = new List<VideoFileInfo>(); + var nonVideoFiles = new List<FileSystemMetadata>(); for (var i = 0; i < count; i++) { var current = fileSystemChildren[i]; - if (current.IsDirectory && BaseItem.AllExtrasTypesFolderNames.ContainsKey(current.Name)) + if (current.IsDirectory && _namingOptions.AllExtrasTypesFolderNames.ContainsKey(current.Name)) { - files.AddRange(_fileSystem.GetFiles(current.FullName, _namingOptions.VideoFileExtensions, false, false)); + var filesInSubFolder = _fileSystem.GetFiles(current.FullName, _namingOptions.VideoFileExtensions, false, false); + foreach (var file in filesInSubFolder) + { + var videoInfo = VideoResolver.Resolve(file.FullName, file.IsDirectory, _namingOptions); + if (videoInfo == null) + { + nonVideoFiles.Add(file); + continue; + } + + files.Add(videoInfo); + } } else if (!current.IsDirectory) { - files.Add(current); + var videoInfo = VideoResolver.Resolve(current.FullName, current.IsDirectory, _namingOptions); + if (videoInfo == null) + { + nonVideoFiles.Add(current); + continue; + } + + files.Add(videoInfo); } } @@ -2714,11 +2733,10 @@ namespace Emby.Server.Implementations.Library var videos = VideoListResolver.Resolve(files, _namingOptions); // owner video info cannot be null as that implies it has no path var extras = ExtraResolver.GetExtras(videos, ownerVideoInfo, _namingOptions.VideoFlagDelimiters); - for (var i = 0; i < extras.Count; i++) { var currentExtra = extras[i]; - var resolved = ResolvePath(_fileSystem.GetFileInfo(currentExtra.Path)); + var resolved = ResolvePath(_fileSystem.GetFileInfo(currentExtra.Path), null, directoryService); if (resolved is not Video video) { continue; @@ -2735,6 +2753,35 @@ namespace Emby.Server.Implementations.Library video.OwnerId = owner.Id; yield return video; } + + // TODO: theme songs must be handled "manually" (but should we?) since they aren't video files + for (var i = 0; i < nonVideoFiles.Count; i++) + { + var current = nonVideoFiles[i]; + var extraInfo = ExtraResolver.GetExtraInfo(current.FullName, _namingOptions); + if (extraInfo.ExtraType != ExtraType.ThemeSong) + { + continue; + } + + var resolved = ResolvePath(current, null, directoryService); + if (resolved is not Audio themeSong) + { + continue; + } + + // Try to retrieve it from the db. If we don't find it, use the resolved version + if (GetItemById(themeSong.Id) is Audio dbItem) + { + themeSong = dbItem; + } + + themeSong.ExtraType = ExtraType.ThemeSong; + themeSong.OwnerId = owner.Id; + themeSong.ParentId = Guid.Empty; + + yield return themeSong; + } } public string GetPathAfterNetworkSubstitution(string path, BaseItem ownerItem) diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 10f42b926..4feaf3fb4 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -261,7 +261,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } } - var resolverResult = VideoListResolver.Resolve(files, NamingOptions, supportMultiEditions, parseName); + var videoInfos = files + .Select(i => VideoResolver.Resolve(i.FullName, i.IsDirectory, NamingOptions, parseName)) + .Where(f => f != null) + .ToList(); + + var resolverResult = VideoListResolver.Resolve(videoInfos, NamingOptions, supportMultiEditions, parseName); var result = new MultiItemResolverResult { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 4114ff7b0..cb21add12 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -13,7 +13,6 @@ using System.Threading.Tasks; using Diacritics.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; -using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; @@ -22,7 +21,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; @@ -42,11 +40,7 @@ namespace MediaBrowser.Controller.Entities { private BaseItemKind? _baseItemKind; - public const string TrailerFileName = "trailer"; - public const string TrailersFolderName = "trailers"; - public const string ThemeSongsFolderName = "theme-music"; public const string ThemeSongFileName = "theme"; - public const string ThemeVideosFolderName = "backdrops"; /// <summary> /// The supported image extensions. @@ -83,21 +77,6 @@ namespace MediaBrowser.Controller.Entities Model.Entities.ExtraType.Scene }; - /// <summary> - /// The supported extra folder names and types. See <see cref="Emby.Naming.Common.NamingOptions" />. - /// </summary> - public static readonly Dictionary<string, ExtraType> AllExtrasTypesFolderNames = new Dictionary<string, ExtraType>(StringComparer.OrdinalIgnoreCase) - { - ["extras"] = MediaBrowser.Model.Entities.ExtraType.Unknown, - ["behind the scenes"] = MediaBrowser.Model.Entities.ExtraType.BehindTheScenes, - ["deleted scenes"] = MediaBrowser.Model.Entities.ExtraType.DeletedScene, - ["interviews"] = MediaBrowser.Model.Entities.ExtraType.Interview, - ["scenes"] = MediaBrowser.Model.Entities.ExtraType.Scene, - ["samples"] = MediaBrowser.Model.Entities.ExtraType.Sample, - ["shorts"] = MediaBrowser.Model.Entities.ExtraType.Clip, - ["featurettes"] = MediaBrowser.Model.Entities.ExtraType.Clip - }; - private string _sortName; private string _forcedSortName; @@ -1275,74 +1254,6 @@ namespace MediaBrowser.Controller.Entities return string.Join('/', terms); } - /// <summary> - /// Loads the theme songs. - /// </summary> - /// <returns>List{Audio.Audio}.</returns> - private static Audio.Audio[] LoadThemeSongs(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - var files = fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => FileSystem.GetFiles(i.FullName)) - .ToList(); - - // Support plex/xbmc convention - files.AddRange(fileSystemChildren - .Where(i => !i.IsDirectory && System.IO.Path.GetFileNameWithoutExtension(i.FullName.AsSpan()).Equals(ThemeSongFileName, StringComparison.OrdinalIgnoreCase))); - - return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions()) - .OfType<Audio.Audio>() - .Select(audio => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - if (LibraryManager.GetItemById(audio.Id) is Audio.Audio dbItem) - { - audio = dbItem; - } - else - { - // item is new - audio.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeSong; - } - - return audio; - - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToArray(); - } - - /// <summary> - /// Loads the video backdrops. - /// </summary> - /// <returns>List{Video}.</returns> - private static Video[] LoadThemeVideos(IEnumerable<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - var files = fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => FileSystem.GetFiles(i.FullName)); - - return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions()) - .OfType<Video>() - .Select(item => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - - if (LibraryManager.GetItemById(item.Id) is Video dbItem) - { - item = dbItem; - } - else - { - // item is new - item.ExtraType = Model.Entities.ExtraType.ThemeVideo; - } - - return item; - - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToArray(); - } - public Task RefreshMetadata(CancellationToken cancellationToken) { return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken); @@ -1453,7 +1364,7 @@ namespace MediaBrowser.Controller.Entities /// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns> protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { - if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder || this.GetType() == typeof(Folder)) + if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder or UserRootFolder or AggregateFolder || this.GetType() == typeof(Folder)) { return false; } @@ -1470,7 +1381,7 @@ namespace MediaBrowser.Controller.Entities private async Task<bool> RefreshExtras(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { - var extras = LibraryManager.FindExtras(item, fileSystemChildren).ToArray(); + var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray(); var newExtraIds = extras.Select(i => i.Id).ToArray(); var extrasChanged = !item.ExtraIds.SequenceEqual(newExtraIds); diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 1ae28abde..eba92695e 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -58,10 +58,12 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="fileInfo">The file information.</param> /// <param name="parent">The parent.</param> + /// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param> /// <returns>BaseItem.</returns> BaseItem ResolvePath( FileSystemMetadata fileInfo, - Folder parent = null); + Folder parent = null, + IDirectoryService directoryService = null); /// <summary> /// Resolves a set of files into a list of BaseItem. @@ -430,10 +432,9 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="owner">The owner.</param> /// <param name="fileSystemChildren">The file system children.</param> - /// <returns>IEnumerable<Video>.</returns> - IEnumerable<Video> FindExtras( - BaseItem owner, - List<FileSystemMetadata> fileSystemChildren); + /// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param> + /// <returns>IEnumerable<BaseItem>.</returns> + IEnumerable<BaseItem> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService); /// <summary> /// Gets the collection folders. diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index efd02aef0..de505b686 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; @@ -120,7 +121,7 @@ namespace MediaBrowser.LocalMetadata.Images return directoryService.GetFileSystemEntries(path) .Where(i => (includeDirectories && i.IsDirectory) - || Array.FindIndex(BaseItem.SupportedImageExtensions, ext => string.Equals(ext, i.Extension, StringComparison.OrdinalIgnoreCase)) != -1) + || BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparison.OrdinalIgnoreCase)) .OrderBy(i => Array.IndexOf(BaseItem.SupportedImageExtensions, i.Extension ?? string.Empty)); } diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs index 323457d09..9a9a57be4 100644 --- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -23,11 +23,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result.Where(v => v.ExtraType == null)); @@ -46,11 +42,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result.Where(v => v.ExtraType == null)); @@ -68,11 +60,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -94,11 +82,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(7, result.Count); @@ -121,11 +105,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -149,11 +129,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(9, result.Count); @@ -173,11 +149,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(5, result.Count); @@ -199,11 +171,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(5, result.Count); @@ -226,11 +194,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -256,11 +220,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -280,11 +240,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -305,11 +261,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(7, result.Count); @@ -331,11 +283,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(5, result.Count); @@ -352,11 +300,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -373,11 +317,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -394,11 +334,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -415,11 +351,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -428,7 +360,7 @@ namespace Jellyfin.Naming.Tests.Video [Fact] public void TestEmptyList() { - var result = VideoListResolver.Resolve(new List<FileSystemMetadata>(), _namingOptions).ToList(); + var result = VideoListResolver.Resolve(new List<VideoFileInfo>(), _namingOptions).ToList(); Assert.Empty(result); } diff --git a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs index cda496761..b76187842 100644 --- a/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/VideoListResolverTests.cs @@ -42,11 +42,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(11, result.Count); @@ -80,11 +76,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -100,11 +92,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -122,11 +110,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -145,11 +129,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(3, result.Count); @@ -169,11 +149,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(3, result.Count); @@ -192,11 +168,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -218,11 +190,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(5, result.Count); @@ -238,11 +206,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = true, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -259,11 +223,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = true, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, true, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -281,11 +241,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(3, result.Count); @@ -306,11 +262,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(4, result.Count); @@ -332,11 +284,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -351,11 +299,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -370,11 +314,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -390,11 +330,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Single(result); @@ -410,11 +346,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -430,11 +362,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -452,11 +380,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); @@ -474,11 +398,7 @@ namespace Jellyfin.Naming.Tests.Video }; var result = VideoListResolver.Resolve( - files.Select(i => new FileSystemMetadata - { - IsDirectory = false, - FullName = i - }).ToList(), + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); Assert.Equal(2, result.Count); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs index 10afadbef..b29426d85 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs @@ -5,11 +5,13 @@ using AutoFixture; using AutoFixture.AutoMoq; using Emby.Naming.Common; using Emby.Server.Implementations.Library.Resolvers; +using Emby.Server.Implementations.Library.Resolvers.Audio; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Entities; @@ -22,6 +24,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library.LibraryManager; public class FindExtrasTests { private readonly Emby.Server.Implementations.Library.LibraryManager _libraryManager; + private readonly Mock<IFileSystem> _fileSystemMock; public FindExtrasTests() { @@ -29,11 +32,11 @@ public class FindExtrasTests fixture.Register(() => new NamingOptions()); var configMock = fixture.Freeze<Mock<IServerConfigurationManager>>(); configMock.Setup(c => c.ApplicationPaths.ProgramDataPath).Returns("/data"); - var fileSystemMock = fixture.Freeze<Mock<IFileSystem>>(); - fileSystemMock.Setup(f => f.GetFileInfo(It.IsAny<string>())).Returns<string>(path => new FileSystemMetadata { FullName = path }); + _fileSystemMock = fixture.Freeze<Mock<IFileSystem>>(); + _fileSystemMock.Setup(f => f.GetFileInfo(It.IsAny<string>())).Returns<string>(path => new FileSystemMetadata { FullName = path }); _libraryManager = fixture.Build<Emby.Server.Implementations.Library.LibraryManager>().Do(s => s.AddParts( fixture.Create<IEnumerable<IResolverIgnoreRule>>(), - new List<IItemResolver> { new GenericVideoResolver<Video>(fixture.Create<NamingOptions>()) }, + new List<IItemResolver> { new GenericVideoResolver<Video>(fixture.Create<NamingOptions>()), new AudioResolver(fixture.Create<NamingOptions>()) }, fixture.Create<IEnumerable<IIntroProvider>>(), fixture.Create<IEnumerable<IBaseItemComparer>>(), fixture.Create<IEnumerable<ILibraryPostScanTask>>())) @@ -62,7 +65,7 @@ public class FindExtrasTests IsDirectory = false }).ToList(); - var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList(); Assert.Equal(2, extras.Count); Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); @@ -77,26 +80,77 @@ public class FindExtrasTests { "/movies/Up/Up.mkv", "/movies/Up/Up - trailer.mkv", - "/movies/Up/trailers/some trailer.mkv", - "/movies/Up/behind the scenes/the making of Up.mkv", + "/movies/Up/trailers", + "/movies/Up/theme-music", + "/movies/Up/theme.mp3", + "/movies/Up/not a theme.mp3", + "/movies/Up/behind the scenes", "/movies/Up/behind the scenes.mkv", "/movies/Up/Up - sample.mkv", "/movies/Up/Up something else.mkv" }; + _fileSystemMock.Setup(f => f.GetFiles( + "/movies/Up/trailers", + It.IsAny<string[]>(), + false, + false)) + .Returns(new List<FileSystemMetadata> + { + new () + { + FullName = "/movies/Up/trailers/some trailer.mkv", + Name = "some trailer.mkv", + IsDirectory = false + } + }); + + _fileSystemMock.Setup(f => f.GetFiles( + "/movies/Up/behind the scenes", + It.IsAny<string[]>(), + false, + false)) + .Returns(new List<FileSystemMetadata> + { + new () + { + FullName = "/movies/Up/behind the scenes/the making of Up.mkv", + Name = "the making of Up.mkv", + IsDirectory = false + } + }); + + _fileSystemMock.Setup(f => f.GetFiles( + "/movies/Up/theme-music", + It.IsAny<string[]>(), + false, + false)) + .Returns(new List<FileSystemMetadata> + { + new () + { + FullName = "/movies/Up/theme-music/theme2.mp3", + Name = "theme2.mp3", + IsDirectory = false + } + }); + var files = paths.Select(p => new FileSystemMetadata { FullName = p, - IsDirectory = false + Name = Path.GetFileName(p), + IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p)) }).ToList(); - var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList(); - Assert.Equal(4, extras.Count); + Assert.Equal(6, extras.Count); Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); Assert.Equal(ExtraType.Trailer, extras[1].ExtraType); Assert.Equal(ExtraType.BehindTheScenes, extras[2].ExtraType); Assert.Equal(ExtraType.Sample, extras[3].ExtraType); + Assert.Equal(ExtraType.ThemeSong, extras[4].ExtraType); + Assert.Equal(ExtraType.ThemeSong, extras[5].ExtraType); } [Fact] @@ -116,7 +170,7 @@ public class FindExtrasTests IsDirectory = false }).ToList(); - var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList(); Assert.Single(extras); Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); @@ -142,7 +196,7 @@ public class FindExtrasTests IsDirectory = false }).ToList(); - var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList(); Assert.Single(extras); Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); @@ -167,7 +221,7 @@ public class FindExtrasTests IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p)) }).ToList(); - var extras = _libraryManager.FindExtras(owner, files).OrderBy(e => e.ExtraType).ToList(); + var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList(); Assert.Equal(2, extras.Count); Assert.Equal(ExtraType.Trailer, extras[0].ExtraType); -- cgit v1.2.3 From b880dc8a4a2d1820c6063f441edce42ab399d79e Mon Sep 17 00:00:00 2001 From: cvium <clausvium@gmail.com> Date: Mon, 20 Dec 2021 13:31:07 +0100 Subject: Use our own Contains extension --- Emby.Dlna/ContentDirectory/ControlHandler.cs | 8 -------- Emby.Dlna/DlnaManager.cs | 1 - Emby.Naming/AudioBook/AudioBookResolver.cs | 4 ++-- Emby.Naming/Subtitles/SubtitleParser.cs | 11 ++++++----- Emby.Naming/TV/EpisodeResolver.cs | 4 ++-- Emby.Naming/TV/SeriesPathParser.cs | 1 - Emby.Naming/Video/CleanStringParser.cs | 1 - Emby.Naming/Video/FileStack.cs | 4 ++-- Emby.Naming/Video/StubResolver.cs | 4 ++-- Emby.Notifications/NotificationEntryPoint.cs | 3 ++- Emby.Photos/PhotoProvider.cs | 3 ++- .../AppBase/ConfigurationHelper.cs | 1 - .../Channels/ChannelManager.cs | 7 ++++--- .../Data/BaseSqliteRepository.cs | 4 ++-- Emby.Server.Implementations/Dto/DtoService.cs | 4 ++-- .../EntryPoints/ExternalPortForwarding.cs | 1 - .../HttpServer/Security/AuthService.cs | 1 - .../Images/DynamicImageProvider.cs | 3 ++- .../Images/GenreImageProvider.cs | 2 -- .../Library/MediaStreamSelector.cs | 15 ++++++++------- .../Library/Resolvers/Audio/MusicArtistResolver.cs | 2 -- .../Library/Resolvers/Books/BookResolver.cs | 3 ++- .../Library/Resolvers/PhotoResolver.cs | 3 ++- .../Library/Resolvers/PlaylistResolver.cs | 5 +++-- .../Library/Resolvers/TV/EpisodeResolver.cs | 1 - .../Library/Resolvers/TV/SeriesResolver.cs | 3 --- Emby.Server.Implementations/Library/SearchEngine.cs | 3 --- .../Library/UserViewManager.cs | 8 +++----- Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 9 +++++---- .../LiveTv/Listings/SchedulesDirect.cs | 19 +++++++++---------- .../LiveTv/Listings/XmlTvListingsProvider.cs | 8 ++++---- .../LiveTv/LiveTvDtoService.cs | 1 - Emby.Server.Implementations/LiveTv/LiveTvManager.cs | 2 -- .../LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 1 - .../LiveTv/TunerHosts/M3UTunerHost.cs | 3 ++- .../MediaEncoder/EncodingManager.cs | 5 +++-- .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 3 ++- .../Updates/InstallationManager.cs | 1 - Jellyfin.Api/Controllers/FilterController.cs | 1 - Jellyfin.Api/Controllers/ItemsController.cs | 1 - Jellyfin.Api/Controllers/LibraryController.cs | 13 ++++++------- Jellyfin.Api/Controllers/MoviesController.cs | 2 -- Jellyfin.Api/Controllers/PluginsController.cs | 1 - Jellyfin.Api/Controllers/RemoteImageController.cs | 5 ----- Jellyfin.Api/Controllers/SearchController.cs | 1 - Jellyfin.Api/Controllers/SystemController.cs | 1 - Jellyfin.Api/Controllers/UserLibraryController.cs | 1 - Jellyfin.Api/Controllers/YearsController.cs | 3 ++- .../Devices/DeviceManager.cs | 3 ++- MediaBrowser.Controller/Entities/Audio/Audio.cs | 2 -- MediaBrowser.Controller/Entities/BaseItem.cs | 16 ++++++++-------- MediaBrowser.Controller/Entities/TagExtensions.cs | 3 ++- MediaBrowser.Controller/Entities/UserView.cs | 5 +++-- MediaBrowser.Controller/Entities/UserViewBuilder.cs | 18 ++++++++---------- MediaBrowser.Controller/Entities/Video.cs | 3 ++- MediaBrowser.Controller/IServerApplicationHost.cs | 1 - MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 4 ++-- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 11 ++++++----- MediaBrowser.Controller/LiveTv/TimerInfo.cs | 12 ++++++------ .../Providers/MetadataRefreshOptions.cs | 3 ++- .../Images/InternalMetadataFolderImageProvider.cs | 1 - .../Probing/ProbeResultNormalizer.cs | 4 ++-- MediaBrowser.Model/Dlna/CodecProfile.cs | 4 ++-- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 4 ++-- MediaBrowser.Model/Dlna/ContainerProfile.cs | 4 ++-- MediaBrowser.Model/Dlna/DeviceProfile.cs | 12 ++++++------ MediaBrowser.Model/Dlna/SubtitleProfile.cs | 4 ++-- MediaBrowser.Model/Entities/ImageType.cs | 2 -- .../Notifications/NotificationOptions.cs | 8 ++++---- MediaBrowser.Providers/Manager/ImageSaver.cs | 5 +++-- MediaBrowser.Providers/Manager/ProviderManager.cs | 7 ++++--- .../Playlists/PlaylistItemsProvider.cs | 3 ++- .../Plugins/Omdb/OmdbImageProvider.cs | 1 - .../Plugins/Tmdb/Movies/TmdbMovieProvider.cs | 5 +++-- .../Plugins/Tmdb/TV/TmdbEpisodeProvider.cs | 5 +++-- .../Plugins/Tmdb/TV/TmdbSeasonProvider.cs | 5 +++-- .../Plugins/Tmdb/TV/TmdbSeriesProvider.cs | 5 +++-- MediaBrowser.Providers/Subtitles/SubtitleManager.cs | 4 ++-- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 3 ++- RSSDP/HttpRequestParser.cs | 4 ++-- RSSDP/HttpResponseParser.cs | 4 ++-- .../Jellyfin.Controller.Tests/BaseItemManagerTests.cs | 1 - .../Updates/InstallationManagerTests.cs | 2 -- tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs | 1 - .../Controllers/DlnaControllerTests.cs | 2 -- .../Controllers/MediaStructureControllerTests.cs | 2 -- .../Controllers/StartupControllerTests.cs | 1 - .../Controllers/UserControllerTests.cs | 2 -- 88 files changed, 169 insertions(+), 208 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index b354421ea..fde3f2f89 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -18,11 +18,8 @@ using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; @@ -30,12 +27,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Querying; using Microsoft.Extensions.Logging; -using Book = MediaBrowser.Controller.Entities.Book; -using Episode = MediaBrowser.Controller.Entities.TV.Episode; using Genre = MediaBrowser.Controller.Entities.Genre; -using Movie = MediaBrowser.Controller.Entities.Movies.Movie; -using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum; -using Series = MediaBrowser.Controller.Entities.TV.Series; namespace Emby.Dlna.ContentDirectory { diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index 93efa4b38..d9d2a345a 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -5,7 +5,6 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; -using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using System.Threading.Tasks; diff --git a/Emby.Naming/AudioBook/AudioBookResolver.cs b/Emby.Naming/AudioBook/AudioBookResolver.cs index f6ad3601d..183b6c3b1 100644 --- a/Emby.Naming/AudioBook/AudioBookResolver.cs +++ b/Emby.Naming/AudioBook/AudioBookResolver.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using System.Linq; using Emby.Naming.Common; +using Jellyfin.Extensions; namespace Emby.Naming.AudioBook { @@ -37,7 +37,7 @@ namespace Emby.Naming.AudioBook var extension = Path.GetExtension(path); // Check supported extensions - if (!_options.AudioFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + if (!_options.AudioFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) { return null; } diff --git a/Emby.Naming/Subtitles/SubtitleParser.cs b/Emby.Naming/Subtitles/SubtitleParser.cs index a19340ef6..5809c512a 100644 --- a/Emby.Naming/Subtitles/SubtitleParser.cs +++ b/Emby.Naming/Subtitles/SubtitleParser.cs @@ -2,6 +2,7 @@ using System; using System.IO; using System.Linq; using Emby.Naming.Common; +using Jellyfin.Extensions; namespace Emby.Naming.Subtitles { @@ -34,7 +35,7 @@ namespace Emby.Naming.Subtitles } var extension = Path.GetExtension(path); - if (!_options.SubtitleFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + if (!_options.SubtitleFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) { return null; } @@ -42,11 +43,11 @@ namespace Emby.Naming.Subtitles var flags = GetFlags(path); var info = new SubtitleInfo( path, - _options.SubtitleDefaultFlags.Any(i => flags.Contains(i, StringComparer.OrdinalIgnoreCase)), - _options.SubtitleForcedFlags.Any(i => flags.Contains(i, StringComparer.OrdinalIgnoreCase))); + _options.SubtitleDefaultFlags.Any(i => flags.Contains(i, StringComparison.OrdinalIgnoreCase)), + _options.SubtitleForcedFlags.Any(i => flags.Contains(i, StringComparison.OrdinalIgnoreCase))); - var parts = flags.Where(i => !_options.SubtitleDefaultFlags.Contains(i, StringComparer.OrdinalIgnoreCase) - && !_options.SubtitleForcedFlags.Contains(i, StringComparer.OrdinalIgnoreCase)) + var parts = flags.Where(i => !_options.SubtitleDefaultFlags.Contains(i, StringComparison.OrdinalIgnoreCase) + && !_options.SubtitleForcedFlags.Contains(i, StringComparison.OrdinalIgnoreCase)) .ToList(); // Should have a name, language and file extension diff --git a/Emby.Naming/TV/EpisodeResolver.cs b/Emby.Naming/TV/EpisodeResolver.cs index 5e952e47b..6cebc40c2 100644 --- a/Emby.Naming/TV/EpisodeResolver.cs +++ b/Emby.Naming/TV/EpisodeResolver.cs @@ -1,8 +1,8 @@ using System; using System.IO; -using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; +using Jellyfin.Extensions; namespace Emby.Naming.TV { @@ -48,7 +48,7 @@ namespace Emby.Naming.TV { var extension = Path.GetExtension(path); // Check supported extensions - if (!_options.VideoFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + if (!_options.VideoFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) { // It's not supported. Check stub extensions if (!StubResolver.TryResolveFile(path, _options, out stubType)) diff --git a/Emby.Naming/TV/SeriesPathParser.cs b/Emby.Naming/TV/SeriesPathParser.cs index a62e5f4d6..4dfbb36a3 100644 --- a/Emby.Naming/TV/SeriesPathParser.cs +++ b/Emby.Naming/TV/SeriesPathParser.cs @@ -1,4 +1,3 @@ -using System.Globalization; using Emby.Naming.Common; namespace Emby.Naming.TV diff --git a/Emby.Naming/Video/CleanStringParser.cs b/Emby.Naming/Video/CleanStringParser.cs index b81333500..a336f8fbd 100644 --- a/Emby.Naming/Video/CleanStringParser.cs +++ b/Emby.Naming/Video/CleanStringParser.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; diff --git a/Emby.Naming/Video/FileStack.cs b/Emby.Naming/Video/FileStack.cs index bd635a9f7..4902e6728 100644 --- a/Emby.Naming/Video/FileStack.cs +++ b/Emby.Naming/Video/FileStack.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; +using Jellyfin.Extensions; namespace Emby.Naming.Video { @@ -50,7 +50,7 @@ namespace Emby.Naming.Video return false; } - return IsDirectoryStack == isDirectory && Files.Contains(file, StringComparer.OrdinalIgnoreCase); + return IsDirectoryStack == isDirectory && Files.Contains(file, StringComparison.OrdinalIgnoreCase); } } } diff --git a/Emby.Naming/Video/StubResolver.cs b/Emby.Naming/Video/StubResolver.cs index 079987fe8..f7ba606e3 100644 --- a/Emby.Naming/Video/StubResolver.cs +++ b/Emby.Naming/Video/StubResolver.cs @@ -1,7 +1,7 @@ using System; using System.IO; -using System.Linq; using Emby.Naming.Common; +using Jellyfin.Extensions; namespace Emby.Naming.Video { @@ -28,7 +28,7 @@ namespace Emby.Naming.Video var extension = Path.GetExtension(path); - if (!options.StubFileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + if (!options.StubFileExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) { return false; } diff --git a/Emby.Notifications/NotificationEntryPoint.cs b/Emby.Notifications/NotificationEntryPoint.cs index e8ae14ff2..a56df7031 100644 --- a/Emby.Notifications/NotificationEntryPoint.cs +++ b/Emby.Notifications/NotificationEntryPoint.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Events; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller; using MediaBrowser.Controller.Entities; @@ -104,7 +105,7 @@ namespace Emby.Notifications var type = entry.Type; - if (string.IsNullOrEmpty(type) || !_coreNotificationTypes.Contains(type, StringComparer.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(type) || !_coreNotificationTypes.Contains(type, StringComparison.OrdinalIgnoreCase)) { return; } diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index 4071e4e54..cef82b4d6 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -60,7 +61,7 @@ namespace Emby.Photos item.SetImagePath(ImageType.Primary, item.Path); // Examples: https://github.com/mono/taglib-sharp/blob/a5f6949a53d09ce63ee7495580d6802921a21f14/tests/fixtures/TagLib.Tests.Images/NullOrientationTest.cs - if (_includeExtensions.Contains(Path.GetExtension(item.Path), StringComparer.OrdinalIgnoreCase)) + if (_includeExtensions.Contains(Path.GetExtension(item.Path), StringComparison.OrdinalIgnoreCase)) { try { diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 3a916e5c0..f923e59ef 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Linq; using MediaBrowser.Model.Serialization; namespace Emby.Server.Implementations.AppBase diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 8c167824e..8702691d1 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using Jellyfin.Extensions.Json; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; @@ -179,7 +180,7 @@ namespace Emby.Server.Implementations.Channels try { return (GetChannelProvider(i) is IHasFolderAttributes hasAttributes - && hasAttributes.Attributes.Contains("Recordings", StringComparer.OrdinalIgnoreCase)) == val; + && hasAttributes.Attributes.Contains("Recordings", StringComparison.OrdinalIgnoreCase)) == val; } catch { @@ -1135,7 +1136,7 @@ namespace Emby.Server.Implementations.Channels if (!info.IsLiveStream) { - if (item.Tags.Contains("livestream", StringComparer.OrdinalIgnoreCase)) + if (item.Tags.Contains("livestream", StringComparison.OrdinalIgnoreCase)) { item.Tags = item.Tags.Except(new[] { "livestream" }, StringComparer.OrdinalIgnoreCase).ToArray(); _logger.LogDebug("Forcing update due to Tags {0}", item.Name); @@ -1144,7 +1145,7 @@ namespace Emby.Server.Implementations.Channels } else { - if (!item.Tags.Contains("livestream", StringComparer.OrdinalIgnoreCase)) + if (!item.Tags.Contains("livestream", StringComparison.OrdinalIgnoreCase)) { item.Tags = item.Tags.Concat(new[] { "livestream" }).ToArray(); _logger.LogDebug("Forcing update due to Tags {0}", item.Name); diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 73c31f49d..5030cbacb 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -4,8 +4,8 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading; +using Jellyfin.Extensions; using Microsoft.Extensions.Logging; using SQLitePCL.pretty; @@ -194,7 +194,7 @@ namespace Emby.Server.Implementations.Data protected void AddColumn(IDatabaseConnection connection, string table, string columnName, string type, List<string> existingColumnNames) { - if (existingColumnNames.Contains(columnName, StringComparer.OrdinalIgnoreCase)) + if (existingColumnNames.Contains(columnName, StringComparison.OrdinalIgnoreCase)) { return; } diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index a34bfdb75..365aa8368 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -7,9 +7,9 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Threading.Tasks; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Drawing; @@ -294,7 +294,7 @@ namespace Emby.Server.Implementations.Dto path = path.TrimStart('.'); } - if (!string.IsNullOrEmpty(path) && containers.Contains(path, StringComparer.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(path) && containers.Contains(path, StringComparison.OrdinalIgnoreCase)) { fileExtensionContainer = path; } diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index d325fa14f..06e57ad12 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -13,7 +13,6 @@ using Jellyfin.Networking.Configuration; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Dlna; using Microsoft.Extensions.Logging; using Mono.Nat; diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs index e7103ec95..1d04f3da3 100644 --- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs +++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs @@ -2,7 +2,6 @@ using System.Threading.Tasks; using Jellyfin.Data.Enums; -using MediaBrowser.Controller.Authentication; using MediaBrowser.Controller.Net; using Microsoft.AspNetCore.Http; diff --git a/Emby.Server.Implementations/Images/DynamicImageProvider.cs b/Emby.Server.Implementations/Images/DynamicImageProvider.cs index 0c3fe33a3..575680653 100644 --- a/Emby.Server.Implementations/Images/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/DynamicImageProvider.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; @@ -35,7 +36,7 @@ namespace Emby.Server.Implementations.Images var view = (UserView)item; var isUsingCollectionStrip = IsUsingCollectionStrip(view); - var recursive = isUsingCollectionStrip && !new[] { CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + var recursive = isUsingCollectionStrip && !new[] { CollectionType.BoxSets, CollectionType.Playlists }.Contains(view.ViewType ?? string.Empty, StringComparison.OrdinalIgnoreCase); var result = view.GetItemList(new InternalItemsQuery { diff --git a/Emby.Server.Implementations/Images/GenreImageProvider.cs b/Emby.Server.Implementations/Images/GenreImageProvider.cs index f8eefad6b..968bf5fa3 100644 --- a/Emby.Server.Implementations/Images/GenreImageProvider.cs +++ b/Emby.Server.Implementations/Images/GenreImageProvider.cs @@ -8,8 +8,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; diff --git a/Emby.Server.Implementations/Library/MediaStreamSelector.cs b/Emby.Server.Implementations/Library/MediaStreamSelector.cs index b3837fedb..da0c89c13 100644 --- a/Emby.Server.Implementations/Library/MediaStreamSelector.cs +++ b/Emby.Server.Implementations/Library/MediaStreamSelector.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Linq; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library @@ -64,18 +65,18 @@ namespace Emby.Server.Implementations.Library stream = sortedStreams.FirstOrDefault(s => s.IsExternal || s.IsForced || s.IsDefault); // if the audio language is not understood by the user, load their preferred subs, if there are any - if (stream == null && !preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) + if (stream == null && !preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) { - stream = sortedStreams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); + stream = sortedStreams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase)); } } else if (mode == SubtitlePlaybackMode.Smart) { // if the audio language is not understood by the user, load their preferred subs, if there are any - if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) + if (!preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) { - stream = streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) ?? - streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)); + stream = streams.FirstOrDefault(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase)) ?? + streams.FirstOrDefault(s => preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase)); } } else if (mode == SubtitlePlaybackMode.Always) @@ -136,9 +137,9 @@ namespace Emby.Server.Implementations.Library else if (mode == SubtitlePlaybackMode.Smart) { // Prefer smart logic over embedded metadata - if (!preferredLanguages.Contains(audioTrackLanguage, StringComparer.OrdinalIgnoreCase)) + if (!preferredLanguages.Contains(audioTrackLanguage, StringComparison.OrdinalIgnoreCase)) { - filteredStreams = streams.Where(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparer.OrdinalIgnoreCase)) + filteredStreams = streams.Where(s => !s.IsForced && preferredLanguages.Contains(s.Language, StringComparison.OrdinalIgnoreCase)) .ToList(); } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs index 27e18be42..210ed0953 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs @@ -4,12 +4,10 @@ using System; using System.Linq; using System.Threading.Tasks; using Emby.Naming.Common; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library.Resolvers.Audio diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index e685c87f1..8f224f547 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; @@ -32,7 +33,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books var extension = Path.GetExtension(args.Path); - if (extension != null && _validExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + if (extension != null && _validExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) { // It's a book return new Book diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index 51d819303..e52b43050 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using Emby.Naming.Common; using Emby.Naming.Video; +using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -109,7 +110,7 @@ namespace Emby.Server.Implementations.Library.Resolvers } string extension = Path.GetExtension(path).TrimStart('.'); - return imageProcessor.SupportedInputFormats.Contains(extension, StringComparer.OrdinalIgnoreCase); + return imageProcessor.SupportedInputFormats.Contains(extension, StringComparison.OrdinalIgnoreCase); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index 8ce59717d..6b0dfe986 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Linq; +using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Resolvers; @@ -57,10 +58,10 @@ namespace Emby.Server.Implementations.Library.Resolvers // Check if this is a music playlist file // It should have the correct collection type and a supported file extension - else if (_musicPlaylistCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + else if (_musicPlaylistCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { var extension = Path.GetExtension(args.Path); - if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return new Playlist { diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index 928cd42dd..be9905647 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -3,7 +3,6 @@ using System; using System.Linq; using Emby.Naming.Common; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 46e36847d..f5ac3c665 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -5,12 +5,9 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using Emby.Naming.Common; using Emby.Naming.TV; using Emby.Naming.Video; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 42374b2a2..4aacf7774 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -10,12 +10,9 @@ using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Search; -using Genre = MediaBrowser.Controller.Entities.Genre; -using Person = MediaBrowser.Controller.Entities.Person; namespace Emby.Server.Implementations.Library { diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index 3593986a9..ab8bc6328 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -8,11 +8,11 @@ using System.Linq; using System.Threading; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Channels; @@ -20,8 +20,6 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Library; using MediaBrowser.Model.Querying; -using Genre = MediaBrowser.Controller.Entities.Genre; -using Person = MediaBrowser.Controller.Entities.Person; namespace Emby.Server.Implementations.Library { @@ -80,7 +78,7 @@ namespace Emby.Server.Implementations.Library continue; } - if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (query.PresetViews.Contains(folderViewType ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { list.Add(GetUserView(folder, folderViewType, string.Empty)); } @@ -180,7 +178,7 @@ namespace Emby.Server.Implementations.Library { if (parents.Count == 1 && parents.All(i => string.Equals(i.CollectionType, viewType, StringComparison.OrdinalIgnoreCase))) { - if (!presetViews.Contains(viewType, StringComparer.OrdinalIgnoreCase)) + if (!presetViews.Contains(viewType, StringComparison.OrdinalIgnoreCase)) { return (Folder)parents[0]; } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index e604000ad..7ef93d166 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -17,6 +17,7 @@ using System.Xml; using Emby.Server.Implementations.Library; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Progress; @@ -227,7 +228,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV foreach (var virtualFolder in virtualFolders) { - if (!virtualFolder.Locations.Contains(path, StringComparer.OrdinalIgnoreCase)) + if (!virtualFolder.Locations.Contains(path, StringComparison.OrdinalIgnoreCase)) { continue; } @@ -891,7 +892,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV throw new ArgumentNullException(nameof(tunerHostId)); } - return info.EnabledTuners.Contains(tunerHostId, StringComparer.OrdinalIgnoreCase); + return info.EnabledTuners.Contains(tunerHostId, StringComparison.OrdinalIgnoreCase); } public async Task<IEnumerable<ProgramInfo>> GetProgramsAsync(string channelId, DateTime startDateUtc, DateTime endDateUtc, CancellationToken cancellationToken) @@ -2332,7 +2333,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV var deletes = _timerProvider.GetAll() .Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase)) - .Where(i => !allTimerIds.Contains(i.Id, StringComparer.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow) + .Where(i => !allTimerIds.Contains(i.Id, StringComparison.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow) .Where(i => deleteStatuses.Contains(i.Status)) .ToList(); @@ -2621,7 +2622,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (newDevicesOnly) { - discoveredDevices = discoveredDevices.Where(d => !configuredDeviceIds.Contains(d.DeviceId, StringComparer.OrdinalIgnoreCase)) + discoveredDevices = discoveredDevices.Where(d => !configuredDeviceIds.Contains(d.DeviceId, StringComparison.OrdinalIgnoreCase)) .ToList(); } diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 93d72dba4..dd0cb6c5d 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -10,7 +10,6 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Json; -using System.Net.Http.Headers; using System.Net.Mime; using System.Security.Cryptography; using System.Text; @@ -242,19 +241,19 @@ namespace Emby.Server.Implementations.LiveTv.Listings if (programInfo.AudioProperties.Count != 0) { - if (programInfo.AudioProperties.Contains("atmos", StringComparer.OrdinalIgnoreCase)) + if (programInfo.AudioProperties.Contains("atmos", StringComparison.OrdinalIgnoreCase)) { audioType = ProgramAudio.Atmos; } - else if (programInfo.AudioProperties.Contains("dd 5.1", StringComparer.OrdinalIgnoreCase)) + else if (programInfo.AudioProperties.Contains("dd 5.1", StringComparison.OrdinalIgnoreCase)) { audioType = ProgramAudio.DolbyDigital; } - else if (programInfo.AudioProperties.Contains("dd", StringComparer.OrdinalIgnoreCase)) + else if (programInfo.AudioProperties.Contains("dd", StringComparison.OrdinalIgnoreCase)) { audioType = ProgramAudio.DolbyDigital; } - else if (programInfo.AudioProperties.Contains("stereo", StringComparer.OrdinalIgnoreCase)) + else if (programInfo.AudioProperties.Contains("stereo", StringComparison.OrdinalIgnoreCase)) { audioType = ProgramAudio.Stereo; } @@ -316,8 +315,8 @@ namespace Emby.Server.Implementations.LiveTv.Listings if (programInfo.VideoProperties != null) { - info.IsHD = programInfo.VideoProperties.Contains("hdtv", StringComparer.OrdinalIgnoreCase); - info.Is3D = programInfo.VideoProperties.Contains("3d", StringComparer.OrdinalIgnoreCase); + info.IsHD = programInfo.VideoProperties.Contains("hdtv", StringComparison.OrdinalIgnoreCase); + info.Is3D = programInfo.VideoProperties.Contains("3d", StringComparison.OrdinalIgnoreCase); } if (details.ContentRating != null && details.ContentRating.Count > 0) @@ -326,7 +325,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings .Replace("--", "-", StringComparison.Ordinal); var invalid = new[] { "N/A", "Approved", "Not Rated", "Passed" }; - if (invalid.Contains(info.OfficialRating, StringComparer.OrdinalIgnoreCase)) + if (invalid.Contains(info.OfficialRating, StringComparison.OrdinalIgnoreCase)) { info.OfficialRating = null; } @@ -388,9 +387,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings if (details.Genres != null) { info.Genres = details.Genres.Where(g => !string.IsNullOrWhiteSpace(g)).ToList(); - info.IsNews = details.Genres.Contains("news", StringComparer.OrdinalIgnoreCase); + info.IsNews = details.Genres.Contains("news", StringComparison.OrdinalIgnoreCase); - if (info.Genres.Contains("children", StringComparer.OrdinalIgnoreCase)) + if (info.Genres.Contains("children", StringComparison.OrdinalIgnoreCase)) { info.IsKids = true; } diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index 0c0ec48d9..3da9d02b8 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -190,10 +190,10 @@ namespace Emby.Server.Implementations.LiveTv.Listings IsSeries = program.Episode != null, IsRepeat = program.IsPreviouslyShown && !program.IsNew, IsPremiere = program.Premiere != null, - IsKids = program.Categories.Any(c => info.KidsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), - IsMovie = program.Categories.Any(c => info.MovieCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), - IsNews = program.Categories.Any(c => info.NewsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), - IsSports = program.Categories.Any(c => info.SportsCategories.Contains(c, StringComparer.OrdinalIgnoreCase)), + IsKids = program.Categories.Any(c => info.KidsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)), + IsMovie = program.Categories.Any(c => info.MovieCategories.Contains(c, StringComparison.OrdinalIgnoreCase)), + IsNews = program.Categories.Any(c => info.NewsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)), + IsSports = program.Categories.Any(c => info.SportsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)), ImageUrl = program.Icon != null && !string.IsNullOrEmpty(program.Icon.Source) ? program.Icon.Source : null, HasImage = program.Icon != null && !string.IsNullOrEmpty(program.Icon.Source), OfficialRating = program.Rating != null && !string.IsNullOrEmpty(program.Rating.Value) ? program.Rating.Value : null, diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 317bcbfdd..323b96021 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -13,7 +13,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Dto; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 2f826c63e..047d8e98c 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -33,8 +33,6 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; -using Episode = MediaBrowser.Controller.Entities.TV.Episode; -using Movie = MediaBrowser.Controller.Entities.Movies.Movie; namespace Emby.Server.Implementations.LiveTv { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index 9fba17ca3..1f02acfa3 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -3,7 +3,6 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 08b9260b9..99486f25c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller; @@ -119,7 +120,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { var extension = Path.GetExtension(mediaSource.Path) ?? string.Empty; - if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase)) + if (!_disallowedSharedStreamExtensions.Contains(extension, StringComparison.OrdinalIgnoreCase)) { return new SharedHttpStream(mediaSource, tunerHost, streamId, FileSystem, _httpClientFactory, Logger, Config, _appHost, _streamHelper); } diff --git a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs index ac6606d39..6e1dc725d 100644 --- a/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs +++ b/Emby.Server.Implementations/MediaEncoder/EncodingManager.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Controller.Chapters; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -120,7 +121,7 @@ namespace Emby.Server.Implementations.MediaEncoder var path = GetChapterImagePath(video, chapter.StartPositionTicks); - if (!currentImages.Contains(path, StringComparer.OrdinalIgnoreCase)) + if (!currentImages.Contains(path, StringComparison.OrdinalIgnoreCase)) { if (extractImages) { @@ -219,7 +220,7 @@ namespace Emby.Server.Implementations.MediaEncoder { var deadImages = images .Except(chapters.Select(i => i.ImagePath).Where(i => !string.IsNullOrEmpty(i)), StringComparer.OrdinalIgnoreCase) - .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparer.OrdinalIgnoreCase)) + .Where(i => BaseItem.SupportedImageExtensions.Contains(Path.GetExtension(i), StringComparison.OrdinalIgnoreCase)) .ToList(); foreach (var image in deadImages) diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 09ea6271d..8b185419f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -143,7 +144,7 @@ namespace Emby.Server.Implementations.ScheduledTasks var key = video.Path + video.DateModified.Ticks; - var extract = !previouslyFailedImages.Contains(key, StringComparer.OrdinalIgnoreCase); + var extract = !previouslyFailedImages.Contains(key, StringComparison.OrdinalIgnoreCase); try { diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 7f7eec7d9..24d592525 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -20,7 +20,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Events.Updates; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Updates; using Microsoft.Extensions.Logging; diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index 02a0785e7..e170436d1 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -1,7 +1,6 @@ using System; using System.Linq; using Jellyfin.Api.Constants; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 22e3fd202..65c0662d2 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -8,7 +8,6 @@ using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Dto; diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index d4cc3810a..c8f3bbc86 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -15,6 +15,7 @@ using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.LibraryDtos; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Progress; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; @@ -23,7 +24,6 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Activity; @@ -37,7 +37,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; -using Book = MediaBrowser.Controller.Entities.Book; namespace Jellyfin.Api.Controllers { @@ -786,7 +785,7 @@ namespace Jellyfin.Api.Controllers var typesList = types.ToList(); var plugins = _providerManager.GetAllMetadataPlugins() - .Where(i => types.Contains(i.ItemType, StringComparer.OrdinalIgnoreCase)) + .Where(i => types.Contains(i.ItemType, StringComparison.OrdinalIgnoreCase)) .OrderBy(i => typesList.IndexOf(i.ItemType)) .ToList(); @@ -941,10 +940,10 @@ namespace Jellyfin.Api.Controllers } var metadataOptions = _serverConfigurationManager.Configuration.MetadataOptions - .Where(i => itemTypes.Contains(i.ItemType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + .Where(i => itemTypes.Contains(i.ItemType ?? string.Empty, StringComparison.OrdinalIgnoreCase)) .ToArray(); - return metadataOptions.Length == 0 || metadataOptions.Any(i => !i.DisabledMetadataSavers.Contains(name, StringComparer.OrdinalIgnoreCase)); + return metadataOptions.Length == 0 || metadataOptions.Any(i => !i.DisabledMetadataSavers.Contains(name, StringComparison.OrdinalIgnoreCase)); } private bool IsMetadataFetcherEnabledByDefault(string name, string type, bool isNewLibrary) @@ -968,7 +967,7 @@ namespace Jellyfin.Api.Controllers .ToArray(); return metadataOptions.Length == 0 - || metadataOptions.Any(i => !i.DisabledMetadataFetchers.Contains(name, StringComparer.OrdinalIgnoreCase)); + || metadataOptions.Any(i => !i.DisabledMetadataFetchers.Contains(name, StringComparison.OrdinalIgnoreCase)); } private bool IsImageFetcherEnabledByDefault(string name, string type, bool isNewLibrary) @@ -998,7 +997,7 @@ namespace Jellyfin.Api.Controllers return true; } - return metadataOptions.Any(i => !i.DisabledImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase)); + return metadataOptions.Any(i => !i.DisabledImageFetchers.Contains(name, StringComparison.OrdinalIgnoreCase)); } } } diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs index def10f0bd..db72ff2f8 100644 --- a/Jellyfin.Api/Controllers/MoviesController.cs +++ b/Jellyfin.Api/Controllers/MoviesController.cs @@ -11,9 +11,7 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 0778ea3fc..b41df1abb 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -9,7 +9,6 @@ using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.PluginDtos; using Jellyfin.Extensions.Json; -using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Model.Net; diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 773cff1ac..9f57a5cdb 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -3,18 +3,13 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; -using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; -using Jellyfin.Extensions; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Providers; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 02ee7860f..26acb4cdc 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Constants; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Drawing; diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index 2ff85fd2a..411c987f3 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; -using System.Net; using System.Net.Mime; using System.Threading.Tasks; using Jellyfin.Api.Attributes; diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index ae7e13f67..f6fbdc302 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; using Jellyfin.Extensions; diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 2bba2b97d..8be6fd1b5 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -8,6 +8,7 @@ using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -209,7 +210,7 @@ namespace Jellyfin.Api.Controllers } // Include MediaTypes - if (mediaTypes.Count > 0 && !mediaTypes.Contains(f.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (mediaTypes.Count > 0 && !mediaTypes.Contains(f.MediaType ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return false; } diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs index 0655c9813..a55949df8 100644 --- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs +++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs @@ -7,6 +7,7 @@ using Jellyfin.Data.Entities.Security; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; using Jellyfin.Data.Queries; +using Jellyfin.Extensions; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Devices; @@ -219,7 +220,7 @@ namespace Jellyfin.Server.Implementations.Devices return true; } - return user.GetPreference(PreferenceKind.EnabledDevices).Contains(deviceId, StringComparer.OrdinalIgnoreCase) + return user.GetPreference(PreferenceKind.EnabledDevices).Contains(deviceId, StringComparison.OrdinalIgnoreCase) || !GetCapabilities(deviceId).SupportsPersistentIdentifier; } diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index e90a2f56a..9d0187c8c 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -8,10 +8,8 @@ using System.Globalization; using System.Linq; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities.Audio { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 82d11c523..357a9b77f 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1372,11 +1372,11 @@ namespace MediaBrowser.Controller.Entities { try { - var files = IsFileProtocol ? - GetFileSystemChildren(options.DirectoryService).ToList() : - new List<FileSystemMetadata>(); + if (IsFileProtocol) + { + requiresSave = await RefreshedOwnedItems(options, GetFileSystemChildren(options.DirectoryService).ToList(), cancellationToken).ConfigureAwait(false); + } - requiresSave = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false); await LibraryManager.UpdateImagesAsync(this).ConfigureAwait(false); // ensure all image properties in DB are fresh } catch (Exception ex) @@ -1731,7 +1731,7 @@ namespace MediaBrowser.Controller.Entities private bool IsVisibleViaTags(User user) { - if (user.GetPreference(PreferenceKind.BlockedTags).Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase))) + if (user.GetPreference(PreferenceKind.BlockedTags).Any(i => Tags.Contains(i, StringComparison.OrdinalIgnoreCase))) { return false; } @@ -1900,7 +1900,7 @@ namespace MediaBrowser.Controller.Entities var current = Studios; - if (!current.Contains(name, StringComparer.OrdinalIgnoreCase)) + if (!current.Contains(name, StringComparison.OrdinalIgnoreCase)) { int curLen = current.Length; if (curLen == 0) @@ -1935,7 +1935,7 @@ namespace MediaBrowser.Controller.Entities } var genres = Genres; - if (!genres.Contains(name, StringComparer.OrdinalIgnoreCase)) + if (!genres.Contains(name, StringComparison.OrdinalIgnoreCase)) { var list = genres.ToList(); list.Add(name); @@ -2141,7 +2141,7 @@ namespace MediaBrowser.Controller.Entities .ToList(); var deletedImages = ImageInfos - .Where(image => image.IsLocalFile && !allFiles.Contains(image.Path, StringComparer.OrdinalIgnoreCase)) + .Where(image => image.IsLocalFile && !allFiles.Contains(image.Path, StringComparison.OrdinalIgnoreCase)) .ToList(); if (deletedImages.Count > 0) diff --git a/MediaBrowser.Controller/Entities/TagExtensions.cs b/MediaBrowser.Controller/Entities/TagExtensions.cs index 2ce396daf..ec3eb0f70 100644 --- a/MediaBrowser.Controller/Entities/TagExtensions.cs +++ b/MediaBrowser.Controller/Entities/TagExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Linq; +using Jellyfin.Extensions; namespace MediaBrowser.Controller.Entities { @@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Entities var current = item.Tags; - if (!current.Contains(name, StringComparer.OrdinalIgnoreCase)) + if (!current.Contains(name, StringComparison.OrdinalIgnoreCase)) { if (current.Length == 0) { diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index a6f107849..5c9be7337 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text.Json.Serialization; using System.Threading.Tasks; using Jellyfin.Data.Entities; +using Jellyfin.Extensions; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Querying; @@ -170,12 +171,12 @@ namespace MediaBrowser.Controller.Entities public static bool IsEligibleForGrouping(string viewType) { - return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparison.OrdinalIgnoreCase); } public static bool EnableOriginalFolder(string viewType) { - return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparison.OrdinalIgnoreCase); } protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index aacf1498f..fe44f1169 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -8,7 +8,7 @@ using System.Globalization; using System.Linq; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; -using MediaBrowser.Controller.Entities.Movies; +using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Entities; @@ -16,8 +16,6 @@ using MediaBrowser.Model.Querying; using Microsoft.Extensions.Logging; using Episode = MediaBrowser.Controller.Entities.TV.Episode; using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider; -using Movie = MediaBrowser.Controller.Entities.Movies.Movie; -using Season = MediaBrowser.Controller.Entities.TV.Season; using Series = MediaBrowser.Controller.Entities.TV.Series; namespace MediaBrowser.Controller.Entities @@ -494,7 +492,7 @@ namespace MediaBrowser.Controller.Entities public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager) { - if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return false; } @@ -785,7 +783,7 @@ namespace MediaBrowser.Controller.Entities } // Apply genre filter - if (query.Genres.Count > 0 && !query.Genres.Any(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))) + if (query.Genres.Count > 0 && !query.Genres.Any(v => item.Genres.Contains(v, StringComparison.OrdinalIgnoreCase))) { return false; } @@ -809,7 +807,7 @@ namespace MediaBrowser.Controller.Entities if (query.StudioIds.Length > 0 && !query.StudioIds.Any(id => { var studioItem = libraryManager.GetItemById(id); - return studioItem != null && item.Studios.Contains(studioItem.Name, StringComparer.OrdinalIgnoreCase); + return studioItem != null && item.Studios.Contains(studioItem.Name, StringComparison.OrdinalIgnoreCase); })) { return false; @@ -819,7 +817,7 @@ namespace MediaBrowser.Controller.Entities if (query.GenreIds.Count > 0 && !query.GenreIds.Any(id => { var genreItem = libraryManager.GetItemById(id); - return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase); + return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparison.OrdinalIgnoreCase); })) { return false; @@ -852,7 +850,7 @@ namespace MediaBrowser.Controller.Entities var tags = query.Tags; if (tags.Length > 0) { - if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))) + if (!tags.Any(v => item.Tags.Contains(v, StringComparison.OrdinalIgnoreCase))) { return false; } @@ -970,7 +968,7 @@ namespace MediaBrowser.Controller.Entities { var folder = i as ICollectionFolder; - return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase); }).ToArray(); } @@ -979,7 +977,7 @@ namespace MediaBrowser.Controller.Entities { var folder = i as ICollectionFolder; - return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparison.OrdinalIgnoreCase); }).ToArray(); } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 8e0593507..4f7614f96 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Persistence; @@ -192,7 +193,7 @@ namespace MediaBrowser.Controller.Entities { if (SourceType == SourceType.Channel) { - return !Tags.Contains("livestream", StringComparer.OrdinalIgnoreCase); + return !Tags.Contains("livestream", StringComparison.OrdinalIgnoreCase); } return !IsActiveRecording(); diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index 8f8cf75a6..75ec5f213 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -2,7 +2,6 @@ #pragma warning disable CS1591 -using System.Collections.Generic; using System.Net; using MediaBrowser.Common; using MediaBrowser.Model.System; diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 074e023e8..299773100 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -5,9 +5,9 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -74,7 +74,7 @@ namespace MediaBrowser.Controller.LiveTv /// </summary> /// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value> [JsonIgnore] - public bool IsKids => Tags.Contains("Kids", StringComparer.OrdinalIgnoreCase); + public bool IsKids => Tags.Contains("Kids", StringComparison.OrdinalIgnoreCase); [JsonIgnore] public bool IsRepeat { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 111dc0d27..6c4a5ea17 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Linq; using System.Text.Json.Serialization; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; @@ -66,7 +67,7 @@ namespace MediaBrowser.Controller.LiveTv /// </summary> /// <value><c>true</c> if this instance is sports; otherwise, <c>false</c>.</value> [JsonIgnore] - public bool IsSports => Tags.Contains("Sports", StringComparer.OrdinalIgnoreCase); + public bool IsSports => Tags.Contains("Sports", StringComparison.OrdinalIgnoreCase); /// <summary> /// Gets or sets a value indicating whether this instance is series. @@ -80,28 +81,28 @@ namespace MediaBrowser.Controller.LiveTv /// </summary> /// <value><c>true</c> if this instance is live; otherwise, <c>false</c>.</value> [JsonIgnore] - public bool IsLive => Tags.Contains("Live", StringComparer.OrdinalIgnoreCase); + public bool IsLive => Tags.Contains("Live", StringComparison.OrdinalIgnoreCase); /// <summary> /// Gets a value indicating whether this instance is news. /// </summary> /// <value><c>true</c> if this instance is news; otherwise, <c>false</c>.</value> [JsonIgnore] - public bool IsNews => Tags.Contains("News", StringComparer.OrdinalIgnoreCase); + public bool IsNews => Tags.Contains("News", StringComparison.OrdinalIgnoreCase); /// <summary> /// Gets a value indicating whether this instance is kids. /// </summary> /// <value><c>true</c> if this instance is kids; otherwise, <c>false</c>.</value> [JsonIgnore] - public bool IsKids => Tags.Contains("Kids", StringComparer.OrdinalIgnoreCase); + public bool IsKids => Tags.Contains("Kids", StringComparison.OrdinalIgnoreCase); /// <summary> /// Gets a value indicating whether this instance is premiere. /// </summary> /// <value><c>true</c> if this instance is premiere; otherwise, <c>false</c>.</value> [JsonIgnore] - public bool IsPremiere => Tags.Contains("Premiere", StringComparer.OrdinalIgnoreCase); + public bool IsPremiere => Tags.Contains("Premiere", StringComparison.OrdinalIgnoreCase); /// <summary> /// Gets the folder containing the item. diff --git a/MediaBrowser.Controller/LiveTv/TimerInfo.cs b/MediaBrowser.Controller/LiveTv/TimerInfo.cs index 1a2e8acb3..62541ea8b 100644 --- a/MediaBrowser.Controller/LiveTv/TimerInfo.cs +++ b/MediaBrowser.Controller/LiveTv/TimerInfo.cs @@ -4,8 +4,8 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text.Json.Serialization; +using Jellyfin.Extensions; using MediaBrowser.Model.LiveTv; namespace MediaBrowser.Controller.LiveTv @@ -123,11 +123,11 @@ namespace MediaBrowser.Controller.LiveTv public bool IsMovie { get; set; } - public bool IsKids => Tags.Contains("Kids", StringComparer.OrdinalIgnoreCase); + public bool IsKids => Tags.Contains("Kids", StringComparison.OrdinalIgnoreCase); - public bool IsSports => Tags.Contains("Sports", StringComparer.OrdinalIgnoreCase); + public bool IsSports => Tags.Contains("Sports", StringComparison.OrdinalIgnoreCase); - public bool IsNews => Tags.Contains("News", StringComparer.OrdinalIgnoreCase); + public bool IsNews => Tags.Contains("News", StringComparison.OrdinalIgnoreCase); public bool IsSeries { get; set; } @@ -136,10 +136,10 @@ namespace MediaBrowser.Controller.LiveTv /// </summary> /// <value><c>true</c> if this instance is live; otherwise, <c>false</c>.</value> [JsonIgnore] - public bool IsLive => Tags.Contains("Live", StringComparer.OrdinalIgnoreCase); + public bool IsLive => Tags.Contains("Live", StringComparison.OrdinalIgnoreCase); [JsonIgnore] - public bool IsPremiere => Tags.Contains("Premiere", StringComparer.OrdinalIgnoreCase); + public bool IsPremiere => Tags.Contains("Premiere", StringComparison.OrdinalIgnoreCase); public int? ProductionYear { get; set; } diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index a42c7f8b5..90fd6e269 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -4,6 +4,7 @@ using System; using System.Linq; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Providers; @@ -58,7 +59,7 @@ namespace MediaBrowser.Controller.Providers { if (RefreshPaths != null && RefreshPaths.Length > 0) { - return RefreshPaths.Contains(item.Path ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return RefreshPaths.Contains(item.Path ?? string.Empty, StringComparison.OrdinalIgnoreCase); } return true; diff --git a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs index 6d076ba27..d3fa41bcd 100644 --- a/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/InternalMetadataFolderImageProvider.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Providers; diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index da76ff0f9..9057a101a 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -1362,8 +1362,8 @@ namespace MediaBrowser.MediaEncoding.Probing } // Don't add artist/album artist name to studios, even if it's listed there - if (info.Artists.Contains(studio, StringComparer.OrdinalIgnoreCase) - || info.AlbumArtists.Contains(studio, StringComparer.OrdinalIgnoreCase)) + if (info.Artists.Contains(studio, StringComparison.OrdinalIgnoreCase) + || info.AlbumArtists.Contains(studio, StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/MediaBrowser.Model/Dlna/CodecProfile.cs b/MediaBrowser.Model/Dlna/CodecProfile.cs index 8343cf028..f857bf3a8 100644 --- a/MediaBrowser.Model/Dlna/CodecProfile.cs +++ b/MediaBrowser.Model/Dlna/CodecProfile.cs @@ -2,8 +2,8 @@ #pragma warning disable CS1591 using System; -using System.Linq; using System.Xml.Serialization; +using Jellyfin.Extensions; namespace MediaBrowser.Model.Dlna { @@ -58,7 +58,7 @@ namespace MediaBrowser.Model.Dlna foreach (var val in codec) { - if (codecs.Contains(val, StringComparer.OrdinalIgnoreCase)) + if (codecs.Contains(val, StringComparison.OrdinalIgnoreCase)) { return true; } diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index 55c4dd074..8d03b4c0b 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -2,7 +2,7 @@ using System; using System.Globalization; -using System.Linq; +using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna @@ -167,7 +167,7 @@ namespace MediaBrowser.Model.Dlna switch (condition.Condition) { case ProfileConditionType.EqualsAny: - return expected.Split('|').Contains(currentValue, StringComparer.OrdinalIgnoreCase); + return expected.Split('|').Contains(currentValue, StringComparison.OrdinalIgnoreCase); case ProfileConditionType.Equals: return string.Equals(currentValue, expected, StringComparison.OrdinalIgnoreCase); case ProfileConditionType.NotEquals: diff --git a/MediaBrowser.Model/Dlna/ContainerProfile.cs b/MediaBrowser.Model/Dlna/ContainerProfile.cs index 740966088..c6befdd85 100644 --- a/MediaBrowser.Model/Dlna/ContainerProfile.cs +++ b/MediaBrowser.Model/Dlna/ContainerProfile.cs @@ -1,8 +1,8 @@ #pragma warning disable CS1591 using System; -using System.Linq; using System.Xml.Serialization; +using Jellyfin.Extensions; namespace MediaBrowser.Model.Dlna { @@ -62,7 +62,7 @@ namespace MediaBrowser.Model.Dlna foreach (var container in allInputContainers) { - if (profileContainers.Contains(container, StringComparer.OrdinalIgnoreCase)) + if (profileContainers.Contains(container, StringComparison.OrdinalIgnoreCase)) { return !isNegativeList; } diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index feb3d880e..6170ff5bd 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -1,8 +1,8 @@ #pragma warning disable CA1819 // Properties should not return arrays using System; using System.ComponentModel; -using System.Linq; using System.Xml.Serialization; +using Jellyfin.Extensions; using MediaBrowser.Model.MediaInfo; namespace MediaBrowser.Model.Dlna @@ -253,7 +253,7 @@ namespace MediaBrowser.Model.Dlna continue; } - if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } @@ -287,7 +287,7 @@ namespace MediaBrowser.Model.Dlna continue; } - if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (!i.GetAudioCodecs().Contains(audioCodec ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } @@ -328,7 +328,7 @@ namespace MediaBrowser.Model.Dlna } var audioCodecs = i.GetAudioCodecs(); - if (audioCodecs.Length > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (audioCodecs.Length > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } @@ -469,13 +469,13 @@ namespace MediaBrowser.Model.Dlna } var audioCodecs = i.GetAudioCodecs(); - if (audioCodecs.Length > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (audioCodecs.Length > 0 && !audioCodecs.Contains(audioCodec ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } var videoCodecs = i.GetVideoCodecs(); - if (videoCodecs.Length > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (videoCodecs.Length > 0 && !videoCodecs.Contains(videoCodec ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/MediaBrowser.Model/Dlna/SubtitleProfile.cs b/MediaBrowser.Model/Dlna/SubtitleProfile.cs index 01e3c696b..9ebde25ff 100644 --- a/MediaBrowser.Model/Dlna/SubtitleProfile.cs +++ b/MediaBrowser.Model/Dlna/SubtitleProfile.cs @@ -2,8 +2,8 @@ #pragma warning disable CS1591 using System; -using System.Linq; using System.Xml.Serialization; +using Jellyfin.Extensions; namespace MediaBrowser.Model.Dlna { @@ -42,7 +42,7 @@ namespace MediaBrowser.Model.Dlna } var languages = GetLanguages(); - return languages.Length == 0 || languages.Contains(subLanguage, StringComparer.OrdinalIgnoreCase); + return languages.Length == 0 || languages.Contains(subLanguage, StringComparison.OrdinalIgnoreCase); } } } diff --git a/MediaBrowser.Model/Entities/ImageType.cs b/MediaBrowser.Model/Entities/ImageType.cs index 684b7390a..1f7e03718 100644 --- a/MediaBrowser.Model/Entities/ImageType.cs +++ b/MediaBrowser.Model/Entities/ImageType.cs @@ -1,5 +1,3 @@ -using System; - namespace MediaBrowser.Model.Entities { /// <summary> diff --git a/MediaBrowser.Model/Notifications/NotificationOptions.cs b/MediaBrowser.Model/Notifications/NotificationOptions.cs index 09beb2ef7..d1b5491bd 100644 --- a/MediaBrowser.Model/Notifications/NotificationOptions.cs +++ b/MediaBrowser.Model/Notifications/NotificationOptions.cs @@ -2,9 +2,9 @@ #pragma warning disable CS1591 using System; -using System.Linq; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; namespace MediaBrowser.Model.Notifications { @@ -94,7 +94,7 @@ namespace MediaBrowser.Model.Notifications NotificationOption opt = GetOptions(notificationType); return opt == null - || !opt.DisabledServices.Contains(service, StringComparer.OrdinalIgnoreCase); + || !opt.DisabledServices.Contains(service, StringComparison.OrdinalIgnoreCase); } public bool IsEnabledToMonitorUser(string type, Guid userId) @@ -103,7 +103,7 @@ namespace MediaBrowser.Model.Notifications return opt != null && opt.Enabled - && !opt.DisabledMonitorUsers.Contains(userId.ToString("N"), StringComparer.OrdinalIgnoreCase); + && !opt.DisabledMonitorUsers.Contains(userId.ToString("N"), StringComparison.OrdinalIgnoreCase); } public bool IsEnabledToSendToUser(string type, string userId, User user) @@ -122,7 +122,7 @@ namespace MediaBrowser.Model.Notifications return true; } - return opt.SendToUsers.Contains(userId, StringComparer.OrdinalIgnoreCase); + return opt.SendToUsers.Contains(userId, StringComparison.OrdinalIgnoreCase); } return false; diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index d2a3344be..4632e1d51 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -173,7 +174,7 @@ namespace MediaBrowser.Providers.Manager // Delete the current path if (currentImageIsLocalFile - && !savedPaths.Contains(currentImagePath, StringComparer.OrdinalIgnoreCase) + && !savedPaths.Contains(currentImagePath, StringComparison.OrdinalIgnoreCase) && (saveLocally || currentImagePath.Contains(_config.ApplicationPaths.InternalMetadataPath, StringComparison.OrdinalIgnoreCase))) { var currentPath = currentImagePath; @@ -494,7 +495,7 @@ namespace MediaBrowser.Providers.Manager var filenames = images.Select(i => Path.GetFileNameWithoutExtension(i.Path)).ToList(); var current = 1; - while (filenames.Contains(numberedIndexPrefix + current.ToString(CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase)) + while (filenames.Contains(numberedIndexPrefix + current.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase)) { current++; } diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 6e5753361..0385ce6a7 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -13,6 +13,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Data.Enums; using Jellyfin.Data.Events; +using Jellyfin.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; @@ -660,7 +661,7 @@ namespace MediaBrowser.Providers.Manager /// <inheritdoc/> public void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<string> savers) { - SaveMetadata(item, updateType, _savers.Where(i => savers.Contains(i.Name, StringComparer.OrdinalIgnoreCase))); + SaveMetadata(item, updateType, _savers.Where(i => savers.Contains(i.Name, StringComparison.OrdinalIgnoreCase))); } /// <summary> @@ -737,7 +738,7 @@ namespace MediaBrowser.Providers.Manager { if (libraryOptions.MetadataSavers == null) { - if (options.DisabledMetadataSavers.Contains(saver.Name, StringComparer.OrdinalIgnoreCase)) + if (options.DisabledMetadataSavers.Contains(saver.Name, StringComparison.OrdinalIgnoreCase)) { return false; } @@ -763,7 +764,7 @@ namespace MediaBrowser.Providers.Manager } else { - if (!libraryOptions.MetadataSavers.Contains(saver.Name, StringComparer.OrdinalIgnoreCase)) + if (!libraryOptions.MetadataSavers.Contains(saver.Name, StringComparison.OrdinalIgnoreCase)) { return false; } diff --git a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs index 8baca30c6..fe9986d42 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs @@ -8,6 +8,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; @@ -44,7 +45,7 @@ namespace MediaBrowser.Providers.Playlists } var extension = Path.GetExtension(path); - if (!Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (!Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { return Task.FromResult(ItemUpdateType.None); } diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs index 4c3fc23b2..60b373483 100644 --- a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs @@ -2,7 +2,6 @@ #pragma warning disable CS1591 -using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs index fcaacc90d..e4a56fde9 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -279,8 +280,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies // Normalize this var type = TmdbUtils.MapCrewToPersonType(person); - if (!keepTypes.Contains(type, StringComparer.OrdinalIgnoreCase) && - !keepTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (!keepTypes.Contains(type, StringComparison.OrdinalIgnoreCase) && + !keepTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs index 8ac9d0cab..f50f15877 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -188,8 +189,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV // Normalize this var type = TmdbUtils.MapCrewToPersonType(person); - if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparer.OrdinalIgnoreCase) - && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparison.OrdinalIgnoreCase) + && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs index 7afaddc24..27c52a5a2 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -87,8 +88,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV // Normalize this var type = TmdbUtils.MapCrewToPersonType(person); - if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparer.OrdinalIgnoreCase) - && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (!TmdbUtils.WantedCrewTypes.Contains(type, StringComparison.OrdinalIgnoreCase) + && !TmdbUtils.WantedCrewTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs index 77e22ffbf..f565b6569 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; @@ -365,8 +366,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV // Normalize this var type = TmdbUtils.MapCrewToPersonType(person); - if (!keepTypes.Contains(type, StringComparer.OrdinalIgnoreCase) - && !keepTypes.Contains(person.Job ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (!keepTypes.Contains(type, StringComparison.OrdinalIgnoreCase) + && !keepTypes.Contains(person.Job ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { continue; } diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs index c2b420c33..34019e582 100644 --- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs +++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs @@ -9,6 +9,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -76,8 +77,7 @@ namespace MediaBrowser.Providers.Subtitles var contentType = request.ContentType; var providers = _subtitleProviders - .Where(i => i.SupportedMediaTypes.Contains(contentType)) - .Where(i => !request.DisabledSubtitleFetchers.Contains(i.Name, StringComparer.OrdinalIgnoreCase)) + .Where(i => i.SupportedMediaTypes.Contains(contentType) && !request.DisabledSubtitleFetchers.Contains(i.Name, StringComparison.OrdinalIgnoreCase)) .OrderBy(i => { var index = request.SubtitleFetcherOrder.ToList().IndexOf(i.Name); diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 594402258..d09981304 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -9,6 +9,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Xml; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; @@ -1003,7 +1004,7 @@ namespace MediaBrowser.XbmcMetadata.Savers var name = reader.Name; if (!_commonTags.Contains(name) - && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase)) + && !xmlTagsUsed.Contains(name, StringComparison.OrdinalIgnoreCase)) { writer.WriteNode(reader, false); } diff --git a/RSSDP/HttpRequestParser.cs b/RSSDP/HttpRequestParser.cs index 4114195a6..a3e100796 100644 --- a/RSSDP/HttpRequestParser.cs +++ b/RSSDP/HttpRequestParser.cs @@ -1,6 +1,6 @@ using System; -using System.Linq; using System.Net.Http; +using Jellyfin.Extensions; namespace Rssdp.Infrastructure { @@ -86,7 +86,7 @@ namespace Rssdp.Infrastructure /// <param name="headerName">A string containing the name of the header to return the type of.</param> protected override bool IsContentHeader(string headerName) { - return ContentHeaderNames.Contains(headerName, StringComparer.OrdinalIgnoreCase); + return ContentHeaderNames.Contains(headerName, StringComparison.OrdinalIgnoreCase); } } } diff --git a/RSSDP/HttpResponseParser.cs b/RSSDP/HttpResponseParser.cs index 0dd4bb45a..3e361465d 100644 --- a/RSSDP/HttpResponseParser.cs +++ b/RSSDP/HttpResponseParser.cs @@ -1,7 +1,7 @@ using System; -using System.Linq; using System.Net; using System.Net.Http; +using Jellyfin.Extensions; namespace Rssdp.Infrastructure { @@ -49,7 +49,7 @@ namespace Rssdp.Infrastructure /// <returns>A boolean, true if th specified header relates to HTTP content, otherwise false.</returns> protected override bool IsContentHeader(string headerName) { - return ContentHeaderNames.Contains(headerName, StringComparer.OrdinalIgnoreCase); + return ContentHeaderNames.Contains(headerName, StringComparison.OrdinalIgnoreCase); } /// <summary> diff --git a/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs b/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs index edceef4a7..463e17ad3 100644 --- a/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs +++ b/tests/Jellyfin.Controller.Tests/BaseItemManagerTests.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller.BaseItemManager; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Model.Configuration; using Moq; using Xunit; diff --git a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs index d18441ac0..7abd2e685 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Updates/InstallationManagerTests.cs @@ -6,9 +6,7 @@ using System.Threading; using System.Threading.Tasks; using AutoFixture; using AutoFixture.AutoMoq; -using Emby.Server.Implementations.Archiving; using Emby.Server.Implementations.Updates; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Updates; using Moq; using Moq.Protected; diff --git a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs index 4c8f64d1e..21131eb97 100644 --- a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs +++ b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs @@ -3,7 +3,6 @@ using System.Net; using System.Net.Http; using System.Net.Http.Json; using System.Net.Http.Headers; -using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.StartupDtos; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs index 4c46933aa..5d7b0e874 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/DlnaControllerTests.cs @@ -1,9 +1,7 @@ using System; using System.Linq; using System.Net; -using System.Net.Http; using System.Net.Http.Json; -using System.Net.Http.Headers; using System.Net.Mime; using System.Text; using System.Text.Json; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs index 2da5237db..24251013c 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/MediaStructureControllerTests.cs @@ -2,8 +2,6 @@ using System; using System.Net; using System.Net.Http; using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.LibraryStructureDto; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs index ed92ce25a..e72dacfe0 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/StartupControllerTests.cs @@ -2,7 +2,6 @@ using System; using System.Net; using System.Net.Http; using System.Net.Http.Json; -using System.Net.Http.Headers; using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs index f11f276f8..588e25a82 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/UserControllerTests.cs @@ -4,8 +4,6 @@ using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Json; -using System.Net.Http.Headers; -using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.UserDtos; -- cgit v1.2.3 From 915851101746ed18a1767fa617c52f174732a6f6 Mon Sep 17 00:00:00 2001 From: cvium <clausvium@gmail.com> Date: Mon, 20 Dec 2021 23:58:09 +0100 Subject: Don't skip extras refresh when replacing metadata or doing a full refresh --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index cb21add12..a216a3b60 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1385,7 +1385,7 @@ namespace MediaBrowser.Controller.Entities var newExtraIds = extras.Select(i => i.Id).ToArray(); var extrasChanged = !item.ExtraIds.SequenceEqual(newExtraIds); - if (!extrasChanged) + if (!extrasChanged && !options.ReplaceAllMetadata && options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh) { return false; } -- cgit v1.2.3 From a8a8ce4e7b1ef137cc176721d32642e085837701 Mon Sep 17 00:00:00 2001 From: Cody Robibero <cody@robibe.ro> Date: Thu, 23 Dec 2021 19:27:51 -0700 Subject: Fix build from PR merging --- MediaBrowser.Controller/Entities/BaseItem.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 3ef2e5192..95d49508f 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using Diacritics.Extensions; using Jellyfin.Data.Entities; using Jellyfin.Data.Enums; +using Jellyfin.Extensions; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Configuration; -- cgit v1.2.3 From cbfa355e31ec7a78ef73bbde5566fb2b3424363e Mon Sep 17 00:00:00 2001 From: Bond_009 <bond.009@outlook.com> Date: Fri, 24 Dec 2021 18:28:27 +0100 Subject: Update StyleCop --- Directory.Build.props | 2 +- Emby.Dlna/ContentDirectory/ControlHandler.cs | 46 +- Emby.Dlna/Emby.Dlna.csproj | 6 +- Emby.Drawing/Emby.Drawing.csproj | 6 +- Emby.Drawing/ImageProcessor.cs | 3 +- Emby.Naming/AudioBook/AudioBookListResolver.cs | 1 - Emby.Naming/Emby.Naming.csproj | 6 +- Emby.Naming/Video/Format3DParser.cs | 2 +- Emby.Notifications/Emby.Notifications.csproj | 2 +- Emby.Photos/Emby.Photos.csproj | 2 +- Emby.Server.Implementations/ApplicationHost.cs | 2 +- .../Data/BaseSqliteRepository.cs | 19 +- .../Data/SqliteItemRepository.cs | 461 +++++++++++---------- .../Data/SqliteUserDataRepository.cs | 83 ++-- .../Emby.Server.Implementations.csproj | 6 +- .../HttpServer/WebSocketConnection.cs | 3 +- .../Library/Resolvers/PhotoResolver.cs | 1 - .../Library/Validators/CollectionPostScanTask.cs | 6 +- .../QuickConnect/QuickConnectManager.cs | 4 +- .../Session/SessionManager.cs | 2 +- Emby.Server.Implementations/TV/TVSeriesManager.cs | 3 +- Jellyfin.Api/Controllers/ItemLookupController.cs | 3 +- Jellyfin.Api/Controllers/LiveTvController.cs | 58 +-- Jellyfin.Api/Controllers/RemoteImageController.cs | 3 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 3 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 3 +- Jellyfin.Api/Jellyfin.Api.csproj | 6 +- .../NullableEnumModelBinderProvider.cs | 2 +- .../Models/LibraryStructureDto/MediaPathDto.cs | 2 +- .../Models/LiveTvDtos/SetChannelMappingDto.cs | 2 +- .../Models/MediaInfoDtos/PlaybackInfoDto.cs | 2 +- .../Models/SubtitleDtos/UploadSubtitleDto.cs | 2 +- Jellyfin.Data/Enums/BaseItemKind.cs | 2 +- Jellyfin.Data/Enums/UnratedItem.cs | 2 +- Jellyfin.Data/Jellyfin.Data.csproj | 2 +- Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj | 2 +- Jellyfin.Networking/Jellyfin.Networking.csproj | 2 +- .../Devices/DeviceManager.cs | 2 +- .../Jellyfin.Server.Implementations.csproj | 6 +- .../ModelBuilderExtensions.cs | 2 +- .../Filters/SecurityRequirementsOperationFilter.cs | 2 +- Jellyfin.Server/Jellyfin.Server.csproj | 6 +- .../Middleware/LegacyEmbyRouteRewriteMiddleware.cs | 2 +- .../Middleware/RobotsRedirectionMiddleware.cs | 2 +- MediaBrowser.Common/MediaBrowser.Common.csproj | 6 +- .../Channels/ChannelLatestMediaSearch.cs | 2 +- .../Channels/IHasFolderAttributes.cs | 2 +- .../Channels/ISupportsDelete.cs | 2 +- .../Channels/ISupportsLatestMedia.cs | 2 +- .../Collections/CollectionCreatedEventArgs.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 4 +- .../Entities/BaseItemExtensions.cs | 11 +- MediaBrowser.Controller/Entities/IHasShares.cs | 2 +- .../Entities/LinkedChildComparer.cs | 2 +- .../Entities/LinkedChildType.cs | 2 +- .../LiveTv/ActiveRecordingInfo.cs | 2 +- .../MediaBrowser.Controller.csproj | 6 +- .../MediaEncoding/BaseEncodingJobOptions.cs | 2 +- .../MediaEncoding/TranscodingJobType.cs | 2 +- .../Net/WebSocketListenerState.cs | 2 +- .../Providers/DirectoryService.cs | 6 +- .../Providers/RefreshPriority.cs | 2 +- .../MediaBrowser.LocalMetadata.csproj | 2 +- .../MediaBrowser.MediaEncoding.csproj | 6 +- .../Probing/ProbeResultNormalizer.cs | 2 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 18 +- MediaBrowser.Model/Entities/MetadataField.cs | 53 +++ MediaBrowser.Model/Entities/MetadataFields.cs | 53 --- MediaBrowser.Model/MediaBrowser.Model.csproj | 6 +- MediaBrowser.Model/Plugins/PluginStatus.cs | 2 +- MediaBrowser.Model/Session/HardwareEncodingType.cs | 16 +- .../MediaBrowser.Providers.csproj | 6 +- .../Plugins/StudioImages/StudiosImageProvider.cs | 2 +- MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs | 2 +- .../MediaBrowser.XbmcMetadata.csproj | 2 +- jellyfin.ruleset | 15 + src/Jellyfin.Extensions/Jellyfin.Extensions.csproj | 2 +- src/Jellyfin.Extensions/Json/JsonDefaults.cs | 6 +- src/Jellyfin.Extensions/SplitStringExtensions.cs | 4 +- tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj | 2 +- .../Jellyfin.Common.Tests.csproj | 2 +- .../DirectoryServiceTests.cs | 12 +- .../Jellyfin.Controller.Tests.csproj | 2 +- tests/Jellyfin.Dlna.Tests/DlnaManagerTests.cs | 6 +- .../Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj | 2 +- .../Jellyfin.Extensions.Tests.csproj | 2 +- .../Json/Converters/JsonStringConverterTests.cs | 2 +- .../Jellyfin.MediaEncoding.Tests.csproj | 2 +- .../Jellyfin.Model.Tests.csproj | 2 +- .../Jellyfin.Naming.Tests.csproj | 2 +- .../Jellyfin.Networking.Tests.csproj | 2 +- .../Jellyfin.Providers.Tests.csproj | 2 +- .../MediaInfo/EmbeddedImageProviderTests.cs | 4 +- .../MediaInfo/SubtitleResolverTests.cs | 2 +- .../MediaInfo/VideoImageProviderTests.cs | 4 +- .../Data/SqliteItemRepositoryTests.cs | 2 +- .../Jellyfin.Server.Implementations.Tests.csproj | 2 +- .../Library/EpisodeResolverTest.cs | 4 +- .../Library/LibraryManager/FindExtrasTests.cs | 6 +- .../AuthHelper.cs | 2 +- .../Jellyfin.Server.Integration.Tests.csproj | 2 +- .../WebSocketTests.cs | 3 +- .../Jellyfin.Server.Tests.csproj | 2 +- .../Jellyfin.XbmcMetadata.Tests.csproj | 2 +- 104 files changed, 600 insertions(+), 515 deletions(-) create mode 100644 MediaBrowser.Model/Entities/MetadataField.cs delete mode 100644 MediaBrowser.Model/Entities/MetadataFields.cs (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Directory.Build.props b/Directory.Build.props index d243cde2b..b27782918 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,7 @@ <CodeAnalysisRuleSet>$(MSBuildThisFileDirectory)/jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)' == 'Release' "> + <PropertyGroup> <TreatWarningsAsErrors>true</TreatWarningsAsErrors> </PropertyGroup> diff --git a/Emby.Dlna/ContentDirectory/ControlHandler.cs b/Emby.Dlna/ContentDirectory/ControlHandler.cs index fde3f2f89..010f90c62 100644 --- a/Emby.Dlna/ContentDirectory/ControlHandler.cs +++ b/Emby.Dlna/ContentDirectory/ControlHandler.cs @@ -690,16 +690,16 @@ namespace Emby.Dlna.ContentDirectory var serverItems = new ServerItem[] { - new (item, StubType.Latest), - new (item, StubType.Playlists), - new (item, StubType.Albums), - new (item, StubType.AlbumArtists), - new (item, StubType.Artists), - new (item, StubType.Songs), - new (item, StubType.Genres), - new (item, StubType.FavoriteArtists), - new (item, StubType.FavoriteAlbums), - new (item, StubType.FavoriteSongs) + new(item, StubType.Latest), + new(item, StubType.Playlists), + new(item, StubType.Albums), + new(item, StubType.AlbumArtists), + new(item, StubType.Artists), + new(item, StubType.Songs), + new(item, StubType.Genres), + new(item, StubType.FavoriteArtists), + new(item, StubType.FavoriteAlbums), + new(item, StubType.FavoriteSongs) }; if (limit < serverItems.Length) @@ -751,12 +751,12 @@ namespace Emby.Dlna.ContentDirectory var array = new ServerItem[] { - new (item, StubType.ContinueWatching), - new (item, StubType.Latest), - new (item, StubType.Movies), - new (item, StubType.Collections), - new (item, StubType.Favorites), - new (item, StubType.Genres) + new(item, StubType.ContinueWatching), + new(item, StubType.Latest), + new(item, StubType.Movies), + new(item, StubType.Collections), + new(item, StubType.Favorites), + new(item, StubType.Genres) }; if (limit < array.Length) @@ -836,13 +836,13 @@ namespace Emby.Dlna.ContentDirectory var serverItems = new ServerItem[] { - new (item, StubType.ContinueWatching), - new (item, StubType.NextUp), - new (item, StubType.Latest), - new (item, StubType.Series), - new (item, StubType.FavoriteSeries), - new (item, StubType.FavoriteEpisodes), - new (item, StubType.Genres) + new(item, StubType.ContinueWatching), + new(item, StubType.NextUp), + new(item, StubType.Latest), + new(item, StubType.Series), + new(item, StubType.FavoriteSeries), + new(item, StubType.FavoriteEpisodes), + new(item, StubType.Genres) }; if (limit < serverItems.Length) diff --git a/Emby.Dlna/Emby.Dlna.csproj b/Emby.Dlna/Emby.Dlna.csproj index 7fdbd44f0..fd95041fe 100644 --- a/Emby.Dlna/Emby.Dlna.csproj +++ b/Emby.Dlna/Emby.Dlna.csproj @@ -22,10 +22,14 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 149e4b5d9..b9a2c5d5d 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -11,6 +11,10 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <ItemGroup> <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" /> @@ -24,7 +28,7 @@ <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 3f75e4fc7..8ea711abe 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -101,8 +101,7 @@ namespace Emby.Drawing public async Task ProcessImage(ImageProcessingOptions options, Stream toStream) { var file = await ProcessImage(options).ConfigureAwait(false); - - using (var fileStream = AsyncFile.OpenRead(file.Item1)) + using (var fileStream = AsyncFile.OpenRead(file.path)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } diff --git a/Emby.Naming/AudioBook/AudioBookListResolver.cs b/Emby.Naming/AudioBook/AudioBookListResolver.cs index dd8a05bb3..2efe7d526 100644 --- a/Emby.Naming/AudioBook/AudioBookListResolver.cs +++ b/Emby.Naming/AudioBook/AudioBookListResolver.cs @@ -33,7 +33,6 @@ namespace Emby.Naming.AudioBook /// <returns>Returns IEnumerable of <see cref="AudioBookInfo"/>.</returns> public IEnumerable<AudioBookInfo> Resolve(IEnumerable<FileSystemMetadata> files) { - // File with empty fullname will be sorted out here. var audiobookFileInfos = files .Select(i => _audioBookResolver.Resolve(i.FullName)) diff --git a/Emby.Naming/Emby.Naming.csproj b/Emby.Naming/Emby.Naming.csproj index 2bf8eacb1..433ad137b 100644 --- a/Emby.Naming/Emby.Naming.csproj +++ b/Emby.Naming/Emby.Naming.csproj @@ -15,6 +15,10 @@ <SymbolPackageFormat>snupkg</SymbolPackageFormat> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> <!-- Include all symbols in the main nupkg until Azure Artifact Feed starts supporting ingesting NuGet symbol packages. --> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> @@ -44,7 +48,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Emby.Naming/Video/Format3DParser.cs b/Emby.Naming/Video/Format3DParser.cs index 089089989..eb5e71d78 100644 --- a/Emby.Naming/Video/Format3DParser.cs +++ b/Emby.Naming/Video/Format3DParser.cs @@ -9,7 +9,7 @@ namespace Emby.Naming.Video public static class Format3DParser { // Static default result to save on allocation costs. - private static readonly Format3DResult _defaultResult = new (false, null); + private static readonly Format3DResult _defaultResult = new(false, null); /// <summary> /// Parse 3D format related flags. diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj index d200682e6..7fd2e9bb4 100644 --- a/Emby.Notifications/Emby.Notifications.csproj +++ b/Emby.Notifications/Emby.Notifications.csproj @@ -24,7 +24,7 @@ <!-- Code analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj index bf6252c19..4964265c9 100644 --- a/Emby.Photos/Emby.Photos.csproj +++ b/Emby.Photos/Emby.Photos.csproj @@ -26,7 +26,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 8892f7f40..8ed51a194 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -120,7 +120,7 @@ namespace Emby.Server.Implementations /// <summary> /// The disposable parts. /// </summary> - private readonly ConcurrentDictionary<IDisposable, byte> _disposableParts = new (); + private readonly ConcurrentDictionary<IDisposable, byte> _disposableParts = new(); private readonly IFileSystem _fileSystemManager; private readonly IConfiguration _startupConfig; diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 5030cbacb..450688491 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -160,21 +160,22 @@ namespace Emby.Server.Implementations.Data protected bool TableExists(ManagedConnection connection, string name) { return connection.RunInTransaction( - db => - { - using (var statement = PrepareStatement(db, "select DISTINCT tbl_name from sqlite_master")) + db => { - foreach (var row in statement.ExecuteQuery()) + using (var statement = PrepareStatement(db, "select DISTINCT tbl_name from sqlite_master")) { - if (string.Equals(name, row.GetString(0), StringComparison.OrdinalIgnoreCase)) + foreach (var row in statement.ExecuteQuery()) { - return true; + if (string.Equals(name, row.GetString(0), StringComparison.OrdinalIgnoreCase)) + { + return true; + } } } - } - return false; - }, ReadTransactionMode); + return false; + }, + ReadTransactionMode); } protected List<string> GetColumnNames(IDatabaseConnection connection, string table) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index beae7e243..7fafbc9be 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -498,109 +498,110 @@ namespace Emby.Server.Implementations.Data connection.RunQueries(queries); connection.RunInTransaction( - db => - { - var existingColumnNames = GetColumnNames(db, "AncestorIds"); - AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames); - - existingColumnNames = GetColumnNames(db, "TypedBaseItems"); - - AddColumn(db, "TypedBaseItems", "Path", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "StartDate", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "EndDate", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ChannelId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsMovie", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CommunityRating", "Float", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CustomRating", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IndexNumber", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsLocked", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Name", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "OfficialRating", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "MediaType", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Overview", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ParentIndexNumber", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PremiereDate", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ProductionYear", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ParentId", "GUID", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateCreated", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "EpisodeTitle", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsRepeat", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PreferredMetadataLanguage", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PreferredMetadataCountryCode", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateLastRefreshed", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateLastSaved", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsInMixedFolder", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "LockedFields", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Studios", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Audio", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExternalServiceId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Tags", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsFolder", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "InheritedParentalRatingValue", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "UnratedType", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "TopParentId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames); - AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "OriginalTitle", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "PrimaryVersionId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "DateLastMediaAdded", "DATETIME", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Album", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "IsVirtualItem", "BIT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeriesName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "UserDataKey", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ProviderIds", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Images", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ProductionLocations", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExtraIds", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "TotalBitrate", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExtraType", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Artists", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "AlbumArtists", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ExternalId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "SeriesPresentationUniqueKey", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "ShowId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "OwnerId", "Text", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Width", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Height", "INT", existingColumnNames); - AddColumn(db, "TypedBaseItems", "Size", "BIGINT", existingColumnNames); - - existingColumnNames = GetColumnNames(db, "ItemValues"); - AddColumn(db, "ItemValues", "CleanValue", "Text", existingColumnNames); - - existingColumnNames = GetColumnNames(db, ChaptersTableName); - AddColumn(db, ChaptersTableName, "ImageDateModified", "DATETIME", existingColumnNames); - - existingColumnNames = GetColumnNames(db, "MediaStreams"); - AddColumn(db, "MediaStreams", "IsAvc", "BIT", existingColumnNames); - AddColumn(db, "MediaStreams", "TimeBase", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "CodecTimeBase", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "Title", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "NalLengthSize", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "Comment", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "CodecTag", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "PixelFormat", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "BitDepth", "INT", existingColumnNames); - AddColumn(db, "MediaStreams", "RefFrames", "INT", existingColumnNames); - AddColumn(db, "MediaStreams", "KeyFrames", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "IsAnamorphic", "BIT", existingColumnNames); - - AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames); - AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames); - }, TransactionMode); + db => + { + var existingColumnNames = GetColumnNames(db, "AncestorIds"); + AddColumn(db, "AncestorIds", "AncestorIdText", "Text", existingColumnNames); + + existingColumnNames = GetColumnNames(db, "TypedBaseItems"); + + AddColumn(db, "TypedBaseItems", "Path", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "StartDate", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "EndDate", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ChannelId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsMovie", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CommunityRating", "Float", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CustomRating", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IndexNumber", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsLocked", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Name", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "OfficialRating", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "MediaType", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Overview", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ParentIndexNumber", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PremiereDate", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ProductionYear", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ParentId", "GUID", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Genres", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SortName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ForcedSortName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "RunTimeTicks", "BIGINT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateCreated", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateModified", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsSeries", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "EpisodeTitle", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsRepeat", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PreferredMetadataLanguage", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PreferredMetadataCountryCode", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateLastRefreshed", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateLastSaved", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsInMixedFolder", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "LockedFields", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Studios", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Audio", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExternalServiceId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Tags", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsFolder", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "InheritedParentalRatingValue", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "UnratedType", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "TopParentId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "TrailerTypes", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CriticRating", "Float", existingColumnNames); + AddColumn(db, "TypedBaseItems", "CleanName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PresentationUniqueKey", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "OriginalTitle", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "PrimaryVersionId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "DateLastMediaAdded", "DATETIME", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Album", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "IsVirtualItem", "BIT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeriesName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "UserDataKey", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeasonName", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeasonId", "GUID", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeriesId", "GUID", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExternalSeriesId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Tagline", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ProviderIds", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Images", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ProductionLocations", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExtraIds", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "TotalBitrate", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExtraType", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Artists", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "AlbumArtists", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ExternalId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "SeriesPresentationUniqueKey", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "ShowId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "OwnerId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Width", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Height", "INT", existingColumnNames); + AddColumn(db, "TypedBaseItems", "Size", "BIGINT", existingColumnNames); + + existingColumnNames = GetColumnNames(db, "ItemValues"); + AddColumn(db, "ItemValues", "CleanValue", "Text", existingColumnNames); + + existingColumnNames = GetColumnNames(db, ChaptersTableName); + AddColumn(db, ChaptersTableName, "ImageDateModified", "DATETIME", existingColumnNames); + + existingColumnNames = GetColumnNames(db, "MediaStreams"); + AddColumn(db, "MediaStreams", "IsAvc", "BIT", existingColumnNames); + AddColumn(db, "MediaStreams", "TimeBase", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "CodecTimeBase", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "Title", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "NalLengthSize", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "Comment", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "CodecTag", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "PixelFormat", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "BitDepth", "INT", existingColumnNames); + AddColumn(db, "MediaStreams", "RefFrames", "INT", existingColumnNames); + AddColumn(db, "MediaStreams", "KeyFrames", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "IsAnamorphic", "BIT", existingColumnNames); + + AddColumn(db, "MediaStreams", "ColorPrimaries", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "ColorSpace", "TEXT", existingColumnNames); + AddColumn(db, "MediaStreams", "ColorTransfer", "TEXT", existingColumnNames); + }, + TransactionMode); connection.RunQueries(postQueries); } @@ -636,16 +637,17 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - using (var saveImagesStatement = PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) + db => { - saveImagesStatement.TryBind("@Id", item.Id.ToByteArray()); - saveImagesStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); + using (var saveImagesStatement = PrepareStatement(db, "Update TypedBaseItems set Images=@Images where guid=@Id")) + { + saveImagesStatement.TryBind("@Id", item.Id.ToByteArray()); + saveImagesStatement.TryBind("@Images", SerializeImages(item.ImageInfos)); - saveImagesStatement.MoveNext(); - } - }, TransactionMode); + saveImagesStatement.MoveNext(); + } + }, + TransactionMode); } } @@ -686,10 +688,11 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - SaveItemsInTranscation(db, tuples); - }, TransactionMode); + db => + { + SaveItemsInTranscation(db, tuples); + }, + TransactionMode); } } @@ -2134,13 +2137,14 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - // First delete chapters - db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob); + db => + { + // First delete chapters + db.Execute("delete from " + ChaptersTableName + " where ItemId=@ItemId", idBlob); - InsertChapters(idBlob, chapters, db); - }, TransactionMode); + InsertChapters(idBlob, chapters, db); + }, + TransactionMode); } } @@ -2944,69 +2948,70 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection(true)) { connection.RunInTransaction( - db => - { - var itemQueryStatement = PrepareStatement(db, itemQuery); - var totalRecordCountQueryStatement = PrepareStatement(db, totalRecordCountQuery); - - if (!isReturningZeroItems) + db => { - using (var statement = itemQueryStatement) + var itemQueryStatement = PrepareStatement(db, itemQuery); + var totalRecordCountQueryStatement = PrepareStatement(db, totalRecordCountQuery); + + if (!isReturningZeroItems) { - if (EnableJoinUserData(query)) + using (var statement = itemQueryStatement) { - statement.TryBind("@UserId", query.User.InternalId); - } + if (EnableJoinUserData(query)) + { + statement.TryBind("@UserId", query.User.InternalId); + } - BindSimilarParams(query, statement); - BindSearchParams(query, statement); + BindSimilarParams(query, statement); + BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); - var hasEpisodeAttributes = HasEpisodeAttributes(query); - var hasServiceName = HasServiceName(query); - var hasProgramAttributes = HasProgramAttributes(query); - var hasStartDate = HasStartDate(query); - var hasTrailerTypes = HasTrailerTypes(query); - var hasArtistFields = HasArtistFields(query); - var hasSeriesFields = HasSeriesFields(query); + var hasEpisodeAttributes = HasEpisodeAttributes(query); + var hasServiceName = HasServiceName(query); + var hasProgramAttributes = HasProgramAttributes(query); + var hasStartDate = HasStartDate(query); + var hasTrailerTypes = HasTrailerTypes(query); + var hasArtistFields = HasArtistFields(query); + var hasSeriesFields = HasSeriesFields(query); - foreach (var row in statement.ExecuteQuery()) - { - var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields); - if (item != null) + foreach (var row in statement.ExecuteQuery()) { - list.Add(item); + var item = GetItem(row, query, hasProgramAttributes, hasEpisodeAttributes, hasServiceName, hasStartDate, hasTrailerTypes, hasArtistFields, hasSeriesFields); + if (item != null) + { + list.Add(item); + } } } - } - LogQueryTime("GetItems.ItemQuery", itemQuery, now); - } + LogQueryTime("GetItems.ItemQuery", itemQuery, now); + } - now = DateTime.UtcNow; - if (query.EnableTotalRecordCount) - { - using (var statement = totalRecordCountQueryStatement) + now = DateTime.UtcNow; + if (query.EnableTotalRecordCount) { - if (EnableJoinUserData(query)) + using (var statement = totalRecordCountQueryStatement) { - statement.TryBind("@UserId", query.User.InternalId); - } + if (EnableJoinUserData(query)) + { + statement.TryBind("@UserId", query.User.InternalId); + } - BindSimilarParams(query, statement); - BindSearchParams(query, statement); + BindSimilarParams(query, statement); + BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); - result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); - } + result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + } - LogQueryTime("GetItems.TotalRecordCount", totalRecordCountQuery, now); - } - }, ReadTransactionMode); + LogQueryTime("GetItems.TotalRecordCount", totalRecordCountQuery, now); + } + }, + ReadTransactionMode); } result.Items = list; @@ -3363,51 +3368,52 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection(true)) { connection.RunInTransaction( - db => - { - var statements = PrepareAll(db, statementTexts); - - if (!isReturningZeroItems) + db => { - using (var statement = statements[0]) + var statements = PrepareAll(db, statementTexts); + + if (!isReturningZeroItems) { - if (EnableJoinUserData(query)) + using (var statement = statements[0]) { - statement.TryBind("@UserId", query.User.InternalId); - } + if (EnableJoinUserData(query)) + { + statement.TryBind("@UserId", query.User.InternalId); + } - BindSimilarParams(query, statement); - BindSearchParams(query, statement); + BindSimilarParams(query, statement); + BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); - foreach (var row in statement.ExecuteQuery()) - { - list.Add(row[0].ReadGuidFromBlob()); + foreach (var row in statement.ExecuteQuery()) + { + list.Add(row[0].ReadGuidFromBlob()); + } } } - } - if (query.EnableTotalRecordCount) - { - using (var statement = statements[statements.Length - 1]) + if (query.EnableTotalRecordCount) { - if (EnableJoinUserData(query)) + using (var statement = statements[statements.Length - 1]) { - statement.TryBind("@UserId", query.User.InternalId); - } + if (EnableJoinUserData(query)) + { + statement.TryBind("@UserId", query.User.InternalId); + } - BindSimilarParams(query, statement); - BindSearchParams(query, statement); + BindSimilarParams(query, statement); + BindSearchParams(query, statement); - // Running this again will bind the params - GetWhereClauses(query, statement); + // Running this again will bind the params + GetWhereClauses(query, statement); - result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + result.TotalRecordCount = statement.ExecuteQuery().SelectScalarInt().First(); + } } - } - }, ReadTransactionMode); + }, + ReadTransactionMode); } LogQueryTime("GetItemIds", commandText, now); @@ -4954,10 +4960,11 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - connection.ExecuteAll(sql); - }, TransactionMode); + db => + { + connection.ExecuteAll(sql); + }, + TransactionMode); } } @@ -4988,28 +4995,29 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - var idBlob = id.ToByteArray(); + db => + { + var idBlob = id.ToByteArray(); - // Delete people - ExecuteWithSingleParam(db, "delete from People where ItemId=@Id", idBlob); + // Delete people + ExecuteWithSingleParam(db, "delete from People where ItemId=@Id", idBlob); - // Delete chapters - ExecuteWithSingleParam(db, "delete from " + ChaptersTableName + " where ItemId=@Id", idBlob); + // Delete chapters + ExecuteWithSingleParam(db, "delete from " + ChaptersTableName + " where ItemId=@Id", idBlob); - // Delete media streams - ExecuteWithSingleParam(db, "delete from mediastreams where ItemId=@Id", idBlob); + // Delete media streams + ExecuteWithSingleParam(db, "delete from mediastreams where ItemId=@Id", idBlob); - // Delete ancestors - ExecuteWithSingleParam(db, "delete from AncestorIds where ItemId=@Id", idBlob); + // Delete ancestors + ExecuteWithSingleParam(db, "delete from AncestorIds where ItemId=@Id", idBlob); - // Delete item values - ExecuteWithSingleParam(db, "delete from ItemValues where ItemId=@Id", idBlob); + // Delete item values + ExecuteWithSingleParam(db, "delete from ItemValues where ItemId=@Id", idBlob); - // Delete the item - ExecuteWithSingleParam(db, "delete from TypedBaseItems where guid=@Id", idBlob); - }, TransactionMode); + // Delete the item + ExecuteWithSingleParam(db, "delete from TypedBaseItems where guid=@Id", idBlob); + }, + TransactionMode); } } @@ -5808,15 +5816,16 @@ AND Type = @InternalPersonType)"); using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - var itemIdBlob = itemId.ToByteArray(); + db => + { + var itemIdBlob = itemId.ToByteArray(); - // First delete chapters - db.Execute("delete from People where ItemId=@ItemId", itemIdBlob); + // First delete chapters + db.Execute("delete from People where ItemId=@ItemId", itemIdBlob); - InsertPeople(itemIdBlob, people, db); - }, TransactionMode); + InsertPeople(itemIdBlob, people, db); + }, + TransactionMode); } } @@ -5974,7 +5983,8 @@ AND Type = @InternalPersonType)"); db.Execute("delete from mediastreams where ItemId=@ItemId", itemIdBlob); InsertMediaStreams(itemIdBlob, streams, db); - }, TransactionMode); + }, + TransactionMode); } } @@ -6308,7 +6318,8 @@ AND Type = @InternalPersonType)"); db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob); InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken); - }, TransactionMode); + }, + TransactionMode); } } diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs index 107096b5f..80b8f9ebf 100644 --- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs @@ -50,41 +50,42 @@ namespace Emby.Server.Implementations.Data var users = userDatasTableExists ? null : userManager.Users; connection.RunInTransaction( - db => - { - db.ExecuteAll(string.Join(';', new[] - { - "create table if not exists UserDatas (key nvarchar not null, userId INT not null, rating float null, played bit not null, playCount int not null, isFavorite bit not null, playbackPositionTicks bigint not null, lastPlayedDate datetime null, AudioStreamIndex INT, SubtitleStreamIndex INT)", - - "drop index if exists idx_userdata", - "drop index if exists idx_userdata1", - "drop index if exists idx_userdata2", - "drop index if exists userdataindex1", - "drop index if exists userdataindex", - "drop index if exists userdataindex3", - "drop index if exists userdataindex4", - "create unique index if not exists UserDatasIndex1 on UserDatas (key, userId)", - "create index if not exists UserDatasIndex2 on UserDatas (key, userId, played)", - "create index if not exists UserDatasIndex3 on UserDatas (key, userId, playbackPositionTicks)", - "create index if not exists UserDatasIndex4 on UserDatas (key, userId, isFavorite)" - })); - - if (userDataTableExists) + db => { - var existingColumnNames = GetColumnNames(db, "userdata"); + db.ExecuteAll(string.Join(';', new[] + { + "create table if not exists UserDatas (key nvarchar not null, userId INT not null, rating float null, played bit not null, playCount int not null, isFavorite bit not null, playbackPositionTicks bigint not null, lastPlayedDate datetime null, AudioStreamIndex INT, SubtitleStreamIndex INT)", + + "drop index if exists idx_userdata", + "drop index if exists idx_userdata1", + "drop index if exists idx_userdata2", + "drop index if exists userdataindex1", + "drop index if exists userdataindex", + "drop index if exists userdataindex3", + "drop index if exists userdataindex4", + "create unique index if not exists UserDatasIndex1 on UserDatas (key, userId)", + "create index if not exists UserDatasIndex2 on UserDatas (key, userId, played)", + "create index if not exists UserDatasIndex3 on UserDatas (key, userId, playbackPositionTicks)", + "create index if not exists UserDatasIndex4 on UserDatas (key, userId, isFavorite)" + })); + + if (userDataTableExists) + { + var existingColumnNames = GetColumnNames(db, "userdata"); - AddColumn(db, "userdata", "InternalUserId", "int", existingColumnNames); - AddColumn(db, "userdata", "AudioStreamIndex", "int", existingColumnNames); - AddColumn(db, "userdata", "SubtitleStreamIndex", "int", existingColumnNames); + AddColumn(db, "userdata", "InternalUserId", "int", existingColumnNames); + AddColumn(db, "userdata", "AudioStreamIndex", "int", existingColumnNames); + AddColumn(db, "userdata", "SubtitleStreamIndex", "int", existingColumnNames); - if (!userDatasTableExists) - { - ImportUserIds(db, users); + if (!userDatasTableExists) + { + ImportUserIds(db, users); - db.ExecuteAll("INSERT INTO UserDatas (key, userId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex) SELECT key, InternalUserId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex from userdata where InternalUserId not null"); + db.ExecuteAll("INSERT INTO UserDatas (key, userId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex) SELECT key, InternalUserId, rating, played, playCount, isFavorite, playbackPositionTicks, lastPlayedDate, AudioStreamIndex, SubtitleStreamIndex from userdata where InternalUserId not null"); + } } - } - }, TransactionMode); + }, + TransactionMode); } } @@ -183,10 +184,11 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - SaveUserData(db, internalUserId, key, userData); - }, TransactionMode); + db => + { + SaveUserData(db, internalUserId, key, userData); + }, + TransactionMode); } } @@ -252,13 +254,14 @@ namespace Emby.Server.Implementations.Data using (var connection = GetConnection()) { connection.RunInTransaction( - db => - { - foreach (var userItemData in userDataList) + db => { - SaveUserData(db, internalUserId, userItemData.Key, userItemData); - } - }, TransactionMode); + foreach (var userItemData in userDataList) + { + SaveUserData(db, internalUserId, userItemData.Key, userItemData); + } + }, + TransactionMode); } } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 329a84acb..1e09a98cf 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -49,10 +49,14 @@ <NoWarn>AD0001</NoWarn> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs index 0eca2a608..b3bd3421a 100644 --- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs +++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs @@ -236,7 +236,8 @@ namespace Emby.Server.Implementations.HttpServer { MessageId = Guid.NewGuid(), MessageType = SessionMessageType.KeepAlive - }, CancellationToken.None); + }, + CancellationToken.None); } /// <inheritdoc /> diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index e52b43050..bc2915db6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -34,7 +34,6 @@ namespace Emby.Server.Implementations.Library.Resolvers "default" }; - public PhotoResolver(IImageProcessor imageProcessor, NamingOptions namingOptions) { _imageProcessor = imageProcessor; diff --git a/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs index 73e58d16c..88b93a211 100644 --- a/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs +++ b/Emby.Server.Implementations/Library/Validators/CollectionPostScanTask.cs @@ -1,16 +1,16 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Collections.Generic; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; -using Jellyfin.Data.Enums; using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Validators { diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs index c81c26994..532c8d1e3 100644 --- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs +++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs @@ -30,8 +30,8 @@ namespace Emby.Server.Implementations.QuickConnect /// </summary> private const int Timeout = 10; - private readonly ConcurrentDictionary<string, QuickConnectResult> _currentRequests = new (); - private readonly ConcurrentDictionary<string, (DateTime Timestamp, AuthenticationResult AuthenticationResult)> _authorizedSecrets = new (); + private readonly ConcurrentDictionary<string, QuickConnectResult> _currentRequests = new(); + private readonly ConcurrentDictionary<string, (DateTime Timestamp, AuthenticationResult AuthenticationResult)> _authorizedSecrets = new(); private readonly IServerConfigurationManager _config; private readonly ILogger<QuickConnectManager> _logger; diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index d10a24bbc..6c679ea20 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.Session /// <summary> /// The active connections. /// </summary> - private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections = new (StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary<string, SessionInfo> _activeConnections = new(StringComparer.OrdinalIgnoreCase); private Timer _idleTimer; diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index a87831294..5dbe9f44d 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -122,7 +122,8 @@ namespace Emby.Server.Implementations.TV Limit = limit, DtoOptions = new DtoOptions { Fields = new[] { ItemFields.SeriesPresentationUniqueKey }, EnableImages = false }, GroupBySeriesPresentationUniqueKey = true - }, parentsFolders.ToList()) + }, + parentsFolders.ToList()) .Cast<Episode>() .Where(episode => !string.IsNullOrEmpty(episode.SeriesPresentationUniqueKey)) .Select(GetUniqueSeriesKey); diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index 8a6f9b8c7..4161e43f6 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -264,7 +264,8 @@ namespace Jellyfin.Api.Controllers ReplaceAllMetadata = true, ReplaceAllImages = replaceAllImages, SearchResult = searchResult - }, CancellationToken.None).ConfigureAwait(false); + }, + CancellationToken.None).ConfigureAwait(false); return NoContent(); } diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index b131530c9..9e2ef8c60 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -278,25 +278,26 @@ namespace Jellyfin.Api.Controllers return _liveTvManager.GetRecordings( new RecordingQuery - { - ChannelId = channelId, - UserId = userId ?? Guid.Empty, - StartIndex = startIndex, - Limit = limit, - Status = status, - SeriesTimerId = seriesTimerId, - IsInProgress = isInProgress, - EnableTotalRecordCount = enableTotalRecordCount, - IsMovie = isMovie, - IsNews = isNews, - IsSeries = isSeries, - IsKids = isKids, - IsSports = isSports, - IsLibraryItem = isLibraryItem, - Fields = fields, - ImageTypeLimit = imageTypeLimit, - EnableImages = enableImages - }, dtoOptions); + { + ChannelId = channelId, + UserId = userId ?? Guid.Empty, + StartIndex = startIndex, + Limit = limit, + Status = status, + SeriesTimerId = seriesTimerId, + IsInProgress = isInProgress, + EnableTotalRecordCount = enableTotalRecordCount, + IsMovie = isMovie, + IsNews = isNews, + IsSeries = isSeries, + IsKids = isKids, + IsSports = isSports, + IsLibraryItem = isLibraryItem, + Fields = fields, + ImageTypeLimit = imageTypeLimit, + EnableImages = enableImages + }, + dtoOptions); } /// <summary> @@ -489,14 +490,14 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool? isScheduled) { return await _liveTvManager.GetTimers( - new TimerQuery - { - ChannelId = channelId, - SeriesTimerId = seriesTimerId, - IsActive = isActive, - IsScheduled = isScheduled - }, CancellationToken.None) - .ConfigureAwait(false); + new TimerQuery + { + ChannelId = channelId, + SeriesTimerId = seriesTimerId, + IsActive = isActive, + IsScheduled = isScheduled + }, + CancellationToken.None).ConfigureAwait(false); } /// <summary> @@ -867,7 +868,8 @@ namespace Jellyfin.Api.Controllers { SortOrder = sortOrder ?? SortOrder.Ascending, SortBy = sortBy - }, CancellationToken.None).ConfigureAwait(false); + }, + CancellationToken.None).ConfigureAwait(false); } /// <summary> diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 9f57a5cdb..dbee56e14 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -80,7 +80,8 @@ namespace Jellyfin.Api.Controllers IncludeAllLanguages = includeAllLanguages, IncludeDisabledProviders = true, ImageType = type - }, CancellationToken.None) + }, + CancellationToken.None) .ConfigureAwait(false); var imageArray = images.ToArray(); diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index f6fbdc302..8b99170d9 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -301,7 +301,8 @@ namespace Jellyfin.Api.Controllers Limit = limit, ParentId = parentId ?? Guid.Empty, UserId = userId, - }, dtoOptions); + }, + dtoOptions); var dtos = list.Select(i => { diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 9d80070eb..3526d56c6 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -218,7 +218,8 @@ namespace Jellyfin.Api.Helpers return KillTranscodingJobs( j => string.IsNullOrWhiteSpace(playSessionId) ? string.Equals(deviceId, j.DeviceId, StringComparison.OrdinalIgnoreCase) - : string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase), deleteFiles); + : string.Equals(playSessionId, j.PlaySessionId, StringComparison.OrdinalIgnoreCase), + deleteFiles); } /// <summary> diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj index ccd647ebe..b5af07408 100644 --- a/Jellyfin.Api/Jellyfin.Api.csproj +++ b/Jellyfin.Api/Jellyfin.Api.csproj @@ -12,6 +12,10 @@ <NoWarn>AD0001</NoWarn> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <ItemGroup> <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.1" /> <PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" /> @@ -27,7 +31,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs b/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs index bc12ad05d..2ccfd0c06 100644 --- a/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs +++ b/Jellyfin.Api/ModelBinders/NullableEnumModelBinderProvider.cs @@ -24,4 +24,4 @@ namespace Jellyfin.Api.ModelBinders return new NullableEnumModelBinder(logger); } } -} \ No newline at end of file +} diff --git a/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs b/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs index f65988259..8b26ec317 100644 --- a/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs +++ b/Jellyfin.Api/Models/LibraryStructureDto/MediaPathDto.cs @@ -24,4 +24,4 @@ namespace Jellyfin.Api.Models.LibraryStructureDto /// </summary> public MediaPathInfo? PathInfo { get; set; } } -} \ No newline at end of file +} diff --git a/Jellyfin.Api/Models/LiveTvDtos/SetChannelMappingDto.cs b/Jellyfin.Api/Models/LiveTvDtos/SetChannelMappingDto.cs index 2ddaa89e8..e7501bd9f 100644 --- a/Jellyfin.Api/Models/LiveTvDtos/SetChannelMappingDto.cs +++ b/Jellyfin.Api/Models/LiveTvDtos/SetChannelMappingDto.cs @@ -25,4 +25,4 @@ namespace Jellyfin.Api.Models.LiveTvDtos [Required] public string ProviderChannelId { get; set; } = string.Empty; } -} \ No newline at end of file +} diff --git a/Jellyfin.Api/Models/MediaInfoDtos/PlaybackInfoDto.cs b/Jellyfin.Api/Models/MediaInfoDtos/PlaybackInfoDto.cs index 2cfdba507..c6bd5e56e 100644 --- a/Jellyfin.Api/Models/MediaInfoDtos/PlaybackInfoDto.cs +++ b/Jellyfin.Api/Models/MediaInfoDtos/PlaybackInfoDto.cs @@ -83,4 +83,4 @@ namespace Jellyfin.Api.Models.MediaInfoDtos /// </summary> public bool? AutoOpenLiveStream { get; set; } } -} \ No newline at end of file +} diff --git a/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs b/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs index 30473255e..be0595798 100644 --- a/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs +++ b/Jellyfin.Api/Models/SubtitleDtos/UploadSubtitleDto.cs @@ -31,4 +31,4 @@ namespace Jellyfin.Api.Models.SubtitleDtos [Required] public string Data { get; set; } = string.Empty; } -} \ No newline at end of file +} diff --git a/Jellyfin.Data/Enums/BaseItemKind.cs b/Jellyfin.Data/Enums/BaseItemKind.cs index 875781746..6fac6c487 100644 --- a/Jellyfin.Data/Enums/BaseItemKind.cs +++ b/Jellyfin.Data/Enums/BaseItemKind.cs @@ -134,7 +134,7 @@ PlaylistsFolder, /// <summary> - /// Item is program + /// Item is program. /// </summary> Program, diff --git a/Jellyfin.Data/Enums/UnratedItem.cs b/Jellyfin.Data/Enums/UnratedItem.cs index 871794086..21ec65af5 100644 --- a/Jellyfin.Data/Enums/UnratedItem.cs +++ b/Jellyfin.Data/Enums/UnratedItem.cs @@ -31,7 +31,7 @@ namespace Jellyfin.Data.Enums Book = 4, /// <summary> - /// A live TV channel + /// A live TV channel. /// </summary> LiveTvChannel = 5, diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 87233d907..f2779d8f2 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -30,7 +30,7 @@ <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj index 5fa386eca..4cc215903 100644 --- a/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj +++ b/Jellyfin.Drawing.Skia/Jellyfin.Drawing.Skia.csproj @@ -31,7 +31,7 @@ <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Jellyfin.Networking/Jellyfin.Networking.csproj b/Jellyfin.Networking/Jellyfin.Networking.csproj index 0cd9a5915..a6af8566c 100644 --- a/Jellyfin.Networking/Jellyfin.Networking.csproj +++ b/Jellyfin.Networking/Jellyfin.Networking.csproj @@ -12,7 +12,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs index a55949df8..54d1a5337 100644 --- a/Jellyfin.Server.Implementations/Devices/DeviceManager.cs +++ b/Jellyfin.Server.Implementations/Devices/DeviceManager.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Server.Implementations.Devices { private readonly JellyfinDbProvider _dbProvider; private readonly IUserManager _userManager; - private readonly ConcurrentDictionary<string, ClientCapabilities> _capabilitiesMap = new (); + private readonly ConcurrentDictionary<string, ClientCapabilities> _capabilitiesMap = new(); /// <summary> /// Initializes a new instance of the <see cref="DeviceManager"/> class. diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index d22757c03..86aec1399 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -6,10 +6,14 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <!-- Code analysers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Jellyfin.Server.Implementations/ModelBuilderExtensions.cs b/Jellyfin.Server.Implementations/ModelBuilderExtensions.cs index 80ad65a42..e73a90cff 100644 --- a/Jellyfin.Server.Implementations/ModelBuilderExtensions.cs +++ b/Jellyfin.Server.Implementations/ModelBuilderExtensions.cs @@ -45,4 +45,4 @@ namespace Jellyfin.Server.Implementations modelBuilder.UseValueConverterForType<DateTime?>(new DateTimeKindValueConverter(kind)); } } -} \ No newline at end of file +} diff --git a/Jellyfin.Server/Filters/SecurityRequirementsOperationFilter.cs b/Jellyfin.Server/Filters/SecurityRequirementsOperationFilter.cs index 802662ce2..077908895 100644 --- a/Jellyfin.Server/Filters/SecurityRequirementsOperationFilter.cs +++ b/Jellyfin.Server/Filters/SecurityRequirementsOperationFilter.cs @@ -75,4 +75,4 @@ namespace Jellyfin.Server.Filters } } } -} \ No newline at end of file +} diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 1638310fd..eb82a9d2b 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -14,6 +14,10 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <ItemGroup> <Compile Include="..\SharedVersion.cs" /> </ItemGroup> @@ -25,7 +29,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/Jellyfin.Server/Middleware/LegacyEmbyRouteRewriteMiddleware.cs b/Jellyfin.Server/Middleware/LegacyEmbyRouteRewriteMiddleware.cs index fdd8974d2..b214299df 100644 --- a/Jellyfin.Server/Middleware/LegacyEmbyRouteRewriteMiddleware.cs +++ b/Jellyfin.Server/Middleware/LegacyEmbyRouteRewriteMiddleware.cs @@ -51,4 +51,4 @@ namespace Jellyfin.Server.Middleware await _next(httpContext).ConfigureAwait(false); } } -} \ No newline at end of file +} diff --git a/Jellyfin.Server/Middleware/RobotsRedirectionMiddleware.cs b/Jellyfin.Server/Middleware/RobotsRedirectionMiddleware.cs index 9d40d74fe..fabcd2da7 100644 --- a/Jellyfin.Server/Middleware/RobotsRedirectionMiddleware.cs +++ b/Jellyfin.Server/Middleware/RobotsRedirectionMiddleware.cs @@ -44,4 +44,4 @@ namespace Jellyfin.Server.Middleware await _next(httpContext).ConfigureAwait(false); } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 4ed44baef..2a2fffce0 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -38,6 +38,10 @@ <SymbolPackageFormat>snupkg</SymbolPackageFormat> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> <!-- Include all symbols in the main nupkg until Azure Artifact Feed starts supporting ingesting NuGet symbol packages. --> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> @@ -46,7 +50,7 @@ <!-- Code analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/MediaBrowser.Controller/Channels/ChannelLatestMediaSearch.cs b/MediaBrowser.Controller/Channels/ChannelLatestMediaSearch.cs index 6f0761e64..e02f42fa4 100644 --- a/MediaBrowser.Controller/Channels/ChannelLatestMediaSearch.cs +++ b/MediaBrowser.Controller/Channels/ChannelLatestMediaSearch.cs @@ -8,4 +8,4 @@ namespace MediaBrowser.Controller.Channels { public string UserId { get; set; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs b/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs index 64af8496c..6c92785d2 100644 --- a/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs +++ b/MediaBrowser.Controller/Channels/IHasFolderAttributes.cs @@ -6,4 +6,4 @@ namespace MediaBrowser.Controller.Channels { string[] Attributes { get; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Channels/ISupportsDelete.cs b/MediaBrowser.Controller/Channels/ISupportsDelete.cs index 204054374..30798a4b2 100644 --- a/MediaBrowser.Controller/Channels/ISupportsDelete.cs +++ b/MediaBrowser.Controller/Channels/ISupportsDelete.cs @@ -12,4 +12,4 @@ namespace MediaBrowser.Controller.Channels Task DeleteItem(string id, CancellationToken cancellationToken); } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Channels/ISupportsLatestMedia.cs b/MediaBrowser.Controller/Channels/ISupportsLatestMedia.cs index dbba7cba2..8ad93387e 100644 --- a/MediaBrowser.Controller/Channels/ISupportsLatestMedia.cs +++ b/MediaBrowser.Controller/Channels/ISupportsLatestMedia.cs @@ -18,4 +18,4 @@ namespace MediaBrowser.Controller.Channels /// <returns>The latest media.</returns> Task<IEnumerable<ChannelItemInfo>> GetLatestMedia(ChannelLatestMediaSearch request, CancellationToken cancellationToken); } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Collections/CollectionCreatedEventArgs.cs b/MediaBrowser.Controller/Collections/CollectionCreatedEventArgs.cs index 82b3a4977..1797d15ea 100644 --- a/MediaBrowser.Controller/Collections/CollectionCreatedEventArgs.cs +++ b/MediaBrowser.Controller/Collections/CollectionCreatedEventArgs.cs @@ -21,4 +21,4 @@ namespace MediaBrowser.Controller.Collections /// <value>The options.</value> public CollectionCreationOptions Options { get; set; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 95d49508f..f5dd82548 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2592,9 +2592,9 @@ namespace MediaBrowser.Controller.Entities .Select(i => i.OfficialRating) .Where(i => !string.IsNullOrEmpty(i)) .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(i => (i, LocalizationManager.GetRatingLevel(i))) + .Select(rating => (rating, LocalizationManager.GetRatingLevel(rating))) .OrderBy(i => i.Item2 ?? 1000) - .Select(i => i.Item1); + .Select(i => i.rating); OfficialRating = ratings.FirstOrDefault() ?? currentOfficialRating; diff --git a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs index 33870e2fb..e0583e630 100644 --- a/MediaBrowser.Controller/Entities/BaseItemExtensions.cs +++ b/MediaBrowser.Controller/Entities/BaseItemExtensions.cs @@ -47,11 +47,12 @@ namespace MediaBrowser.Controller.Entities if (file.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { item.SetImage( - new ItemImageInfo - { - Path = file, - Type = imageType - }, 0); + new ItemImageInfo + { + Path = file, + Type = imageType + }, + 0); } else { diff --git a/MediaBrowser.Controller/Entities/IHasShares.cs b/MediaBrowser.Controller/Entities/IHasShares.cs index dca5af873..e6fa27703 100644 --- a/MediaBrowser.Controller/Entities/IHasShares.cs +++ b/MediaBrowser.Controller/Entities/IHasShares.cs @@ -8,4 +8,4 @@ namespace MediaBrowser.Controller.Entities { Share[] Shares { get; set; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Entities/LinkedChildComparer.cs b/MediaBrowser.Controller/Entities/LinkedChildComparer.cs index 4e58e2942..de8b16808 100644 --- a/MediaBrowser.Controller/Entities/LinkedChildComparer.cs +++ b/MediaBrowser.Controller/Entities/LinkedChildComparer.cs @@ -32,4 +32,4 @@ namespace MediaBrowser.Controller.Entities return ((obj.Path ?? string.Empty) + (obj.LibraryItemId ?? string.Empty) + obj.Type).GetHashCode(StringComparison.Ordinal); } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Entities/LinkedChildType.cs b/MediaBrowser.Controller/Entities/LinkedChildType.cs index 9ddb7b620..d39e36ff2 100644 --- a/MediaBrowser.Controller/Entities/LinkedChildType.cs +++ b/MediaBrowser.Controller/Entities/LinkedChildType.cs @@ -15,4 +15,4 @@ /// </summary> Shortcut = 1 } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/LiveTv/ActiveRecordingInfo.cs b/MediaBrowser.Controller/LiveTv/ActiveRecordingInfo.cs index 463061e68..1a81a8a31 100644 --- a/MediaBrowser.Controller/LiveTv/ActiveRecordingInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ActiveRecordingInfo.cs @@ -16,4 +16,4 @@ namespace MediaBrowser.Controller.LiveTv public CancellationTokenSource CancellationTokenSource { get; set; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index cf3b7bc7a..432159d5d 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -13,6 +13,10 @@ <PackageLicenseExpression>GPL-3.0-only</PackageLicenseExpression> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <ItemGroup> <PackageReference Include="Diacritics" Version="3.3.10" /> <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" /> @@ -49,7 +53,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs index dd6f468da..462585ce3 100644 --- a/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/BaseEncodingJobOptions.cs @@ -201,4 +201,4 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/MediaEncoding/TranscodingJobType.cs b/MediaBrowser.Controller/MediaEncoding/TranscodingJobType.cs index 66b628371..c1bb387e1 100644 --- a/MediaBrowser.Controller/MediaEncoding/TranscodingJobType.cs +++ b/MediaBrowser.Controller/MediaEncoding/TranscodingJobType.cs @@ -20,4 +20,4 @@ /// </summary> Dash } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Net/WebSocketListenerState.cs b/MediaBrowser.Controller/Net/WebSocketListenerState.cs index 70604d60a..2410801d6 100644 --- a/MediaBrowser.Controller/Net/WebSocketListenerState.cs +++ b/MediaBrowser.Controller/Net/WebSocketListenerState.cs @@ -14,4 +14,4 @@ namespace MediaBrowser.Controller.Net public long IntervalMs { get; set; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs index e6d975ffe..d4de97651 100644 --- a/MediaBrowser.Controller/Providers/DirectoryService.cs +++ b/MediaBrowser.Controller/Providers/DirectoryService.cs @@ -12,11 +12,11 @@ namespace MediaBrowser.Controller.Providers { private readonly IFileSystem _fileSystem; - private readonly ConcurrentDictionary<string, FileSystemMetadata[]> _cache = new (StringComparer.Ordinal); + private readonly ConcurrentDictionary<string, FileSystemMetadata[]> _cache = new(StringComparer.Ordinal); - private readonly ConcurrentDictionary<string, FileSystemMetadata> _fileCache = new (StringComparer.Ordinal); + private readonly ConcurrentDictionary<string, FileSystemMetadata> _fileCache = new(StringComparer.Ordinal); - private readonly ConcurrentDictionary<string, List<string>> _filePathCache = new (StringComparer.Ordinal); + private readonly ConcurrentDictionary<string, List<string>> _filePathCache = new(StringComparer.Ordinal); public DirectoryService(IFileSystem fileSystem) { diff --git a/MediaBrowser.Controller/Providers/RefreshPriority.cs b/MediaBrowser.Controller/Providers/RefreshPriority.cs index 3619f679d..e4c39cea1 100644 --- a/MediaBrowser.Controller/Providers/RefreshPriority.cs +++ b/MediaBrowser.Controller/Providers/RefreshPriority.cs @@ -20,4 +20,4 @@ /// </summary> Low = 2 } -} \ No newline at end of file +} diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index a3db717b9..41c79651d 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -23,7 +23,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj index 9f6d8e7fe..b60ccd2ca 100644 --- a/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj +++ b/MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj @@ -11,6 +11,10 @@ <GenerateDocumentationFile>true</GenerateDocumentationFile> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <ItemGroup> <Compile Include="..\SharedVersion.cs" /> </ItemGroup> @@ -32,7 +36,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 9057a101a..4e4957ef7 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.MediaEncoding.Probing private readonly char[] _nameDelimiters = { '/', '|', ';', '\\' }; - private static readonly Regex _performerPattern = new (@"(?<name>.*) \((?<instrument>.*)\)"); + private static readonly Regex _performerPattern = new(@"(?<name>.*) \((?<instrument>.*)\)"); private readonly ILogger _logger; private readonly ILocalizationManager _localization; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index c6ce45788..a19017215 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -679,8 +679,8 @@ namespace MediaBrowser.Model.Dlna // TODO: This doesn't account for situations where the device is able to handle the media's bitrate, but the connection isn't fast enough var directPlayEligibilityResult = IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true) ?? 0, subtitleStream, audioStream, options, PlayMethod.DirectPlay); var directStreamEligibilityResult = IsEligibleForDirectPlay(item, options.GetMaxBitrate(false) ?? 0, subtitleStream, audioStream, options, PlayMethod.DirectStream); - bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayEligibilityResult.Item1); - bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directStreamEligibilityResult.Item1); + bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayEligibilityResult.directPlay); + bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directStreamEligibilityResult.directPlay); _logger.LogDebug( "Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}", @@ -695,7 +695,7 @@ namespace MediaBrowser.Model.Dlna { // See if it can be direct played var directPlayInfo = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectStream); - var directPlay = directPlayInfo.Item1; + var directPlay = directPlayInfo.playMethod; if (directPlay != null) { @@ -713,17 +713,17 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } - transcodeReasons.AddRange(directPlayInfo.Item2); + transcodeReasons.AddRange(directPlayInfo.transcodeReasons); } - if (directPlayEligibilityResult.Item2.HasValue) + if (directPlayEligibilityResult.reason.HasValue) { - transcodeReasons.Add(directPlayEligibilityResult.Item2.Value); + transcodeReasons.Add(directPlayEligibilityResult.reason.Value); } - if (directStreamEligibilityResult.Item2.HasValue) + if (directStreamEligibilityResult.reason.HasValue) { - transcodeReasons.Add(directStreamEligibilityResult.Item2.Value); + transcodeReasons.Add(directStreamEligibilityResult.reason.Value); } // Can't direct play, find the transcoding profile @@ -1000,7 +1000,7 @@ namespace MediaBrowser.Model.Dlna return 7168000; } - private (PlayMethod?, List<TranscodeReason>) GetVideoDirectPlayProfile( + private (PlayMethod? playMethod, List<TranscodeReason> transcodeReasons) GetVideoDirectPlayProfile( VideoOptions options, MediaSourceInfo mediaSource, MediaStream videoStream, diff --git a/MediaBrowser.Model/Entities/MetadataField.cs b/MediaBrowser.Model/Entities/MetadataField.cs new file mode 100644 index 000000000..2cc6c8e33 --- /dev/null +++ b/MediaBrowser.Model/Entities/MetadataField.cs @@ -0,0 +1,53 @@ +namespace MediaBrowser.Model.Entities +{ + /// <summary> + /// Enum MetadataFields. + /// </summary> + public enum MetadataField + { + /// <summary> + /// The cast. + /// </summary> + Cast, + + /// <summary> + /// The genres. + /// </summary> + Genres, + + /// <summary> + /// The production locations. + /// </summary> + ProductionLocations, + + /// <summary> + /// The studios. + /// </summary> + Studios, + + /// <summary> + /// The tags. + /// </summary> + Tags, + + /// <summary> + /// The name. + /// </summary> + Name, + + /// <summary> + /// The overview. + /// </summary> + Overview, + + /// <summary> + /// The runtime. + /// </summary> + Runtime, + + /// <summary> + /// The official rating. + /// </summary> + OfficialRating + } +} diff --git a/MediaBrowser.Model/Entities/MetadataFields.cs b/MediaBrowser.Model/Entities/MetadataFields.cs deleted file mode 100644 index 2cc6c8e33..000000000 --- a/MediaBrowser.Model/Entities/MetadataFields.cs +++ /dev/null @@ -1,53 +0,0 @@ -namespace MediaBrowser.Model.Entities -{ - /// <summary> - /// Enum MetadataFields. - /// </summary> - public enum MetadataField - { - /// <summary> - /// The cast. - /// </summary> - Cast, - - /// <summary> - /// The genres. - /// </summary> - Genres, - - /// <summary> - /// The production locations. - /// </summary> - ProductionLocations, - - /// <summary> - /// The studios. - /// </summary> - Studios, - - /// <summary> - /// The tags. - /// </summary> - Tags, - - /// <summary> - /// The name. - /// </summary> - Name, - - /// <summary> - /// The overview. - /// </summary> - Overview, - - /// <summary> - /// The runtime. - /// </summary> - Runtime, - - /// <summary> - /// The official rating. - /// </summary> - OfficialRating - } -} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index a161b99fd..63f7ada5c 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -23,6 +23,10 @@ <SymbolPackageFormat>snupkg</SymbolPackageFormat> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <PropertyGroup Condition=" '$(Stability)'=='Unstable'"> <!-- Include all symbols in the main nupkg until Azure Artifact Feed starts supporting ingesting NuGet symbol packages. --> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> @@ -46,7 +50,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.Model/Plugins/PluginStatus.cs b/MediaBrowser.Model/Plugins/PluginStatus.cs index 4b9b9bbee..bd420d7b4 100644 --- a/MediaBrowser.Model/Plugins/PluginStatus.cs +++ b/MediaBrowser.Model/Plugins/PluginStatus.cs @@ -29,7 +29,7 @@ namespace MediaBrowser.Model.Plugins NotSupported = -2, /// <summary> - /// This plugin caused an error when instantiated. (Either DI loop, or exception) + /// This plugin caused an error when instantiated (either DI loop, or exception). /// </summary> Malfunctioned = -3, diff --git a/MediaBrowser.Model/Session/HardwareEncodingType.cs b/MediaBrowser.Model/Session/HardwareEncodingType.cs index 0e172f35f..0db5697d3 100644 --- a/MediaBrowser.Model/Session/HardwareEncodingType.cs +++ b/MediaBrowser.Model/Session/HardwareEncodingType.cs @@ -6,42 +6,42 @@ public enum HardwareEncodingType { /// <summary> - /// AMD AMF + /// AMD AMF. /// </summary> AMF = 0, /// <summary> - /// Intel Quick Sync Video + /// Intel Quick Sync Video. /// </summary> QSV = 1, /// <summary> - /// NVIDIA NVENC + /// NVIDIA NVENC. /// </summary> NVENC = 2, /// <summary> - /// OpenMax OMX + /// OpenMax OMX. /// </summary> OMX = 3, /// <summary> - /// Exynos V4L2 MFC + /// Exynos V4L2 MFC. /// </summary> V4L2M2M = 4, /// <summary> - /// MediaCodec Android + /// MediaCodec Android. /// </summary> MediaCodec = 5, /// <summary> - /// Video Acceleration API (VAAPI) + /// Video Acceleration API (VAAPI). /// </summary> VAAPI = 6, /// <summary> - /// Video ToolBox + /// Video ToolBox. /// </summary> VideoToolBox = 7 } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index dac5aaf56..43cf621cd 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -32,10 +32,14 @@ <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet> </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> + <TreatWarningsAsErrors>false</TreatWarningsAsErrors> + </PropertyGroup> + <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs b/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs index 6fa34b985..3a3048cec 100644 --- a/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Plugins/StudioImages/StudiosImageProvider.cs @@ -27,7 +27,7 @@ namespace MediaBrowser.Providers.Studios private readonly IServerConfigurationManager _config; private readonly IHttpClientFactory _httpClientFactory; private readonly IFileSystem _fileSystem; - private readonly String repositoryUrl; + private readonly string repositoryUrl; public StudiosImageProvider(IServerConfigurationManager config, IHttpClientFactory httpClientFactory, IFileSystem fileSystem) { diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs index a3a78103e..234d717bf 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbUtils.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb /// </summary> public static class TmdbUtils { - private static readonly Regex _nonWords = new (@"[\W_]+", RegexOptions.Compiled); + private static readonly Regex _nonWords = new(@"[\W_]+", RegexOptions.Compiled); /// <summary> /// URL of the TMDB instance to use. diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index 926be5a92..ad06688fb 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -23,7 +23,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 7adc35087..e9293588c 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -1,6 +1,21 @@ <?xml version="1.0" encoding="utf-8"?> <RuleSet Name="Rules for Jellyfin.Server" Description="Code analysis rules for Jellyfin.Server.csproj" ToolsVersion="14.0"> <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers"> + <!-- error on SA1000: The keyword 'new' should be followed by a space --> + <Rule Id="SA1000" Action="Error" /> + <!-- error on SA1001: Commas should not be preceded by whitespace --> + <Rule Id="SA1001" Action="Error" /> + <!-- error on SA1117: The parameters should all be placed on the same line or each parameter should be placed on its own line --> + <Rule Id="SA1117" Action="Error" /> + <!-- error on SA1142: Refer to tuple fields by name --> + <Rule Id="SA1142" Action="Error" /> + <!-- error on SA1210: Using directives should be ordered alphabetically by the namespaces --> + <Rule Id="SA1210" Action="Error" /> + <!-- error on SA1518: File is required to end with a single newline character --> + <Rule Id="SA1518" Action="Error" /> + <!-- error on SA1629: Documentation text should end with a period --> + <Rule Id="SA1629" Action="Error" /> + <!-- disable warning SA1009: Closing parenthesis should be followed by a space. --> <Rule Id="SA1009" Action="None" /> <!-- disable warning SA1011: Closing square bracket should be followed by a space. --> diff --git a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj index 3d9538d1b..90d2a0da6 100644 --- a/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj +++ b/src/Jellyfin.Extensions/Jellyfin.Extensions.csproj @@ -30,7 +30,7 @@ <!-- Code Analyzers--> <ItemGroup> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/src/Jellyfin.Extensions/Json/JsonDefaults.cs b/src/Jellyfin.Extensions/Json/JsonDefaults.cs index f4ec91123..2cd89dc3b 100644 --- a/src/Jellyfin.Extensions/Json/JsonDefaults.cs +++ b/src/Jellyfin.Extensions/Json/JsonDefaults.cs @@ -25,7 +25,7 @@ namespace Jellyfin.Extensions.Json /// -> AddJellyfinApi /// -> AddJsonOptions. /// </summary> - private static readonly JsonSerializerOptions _jsonSerializerOptions = new () + private static readonly JsonSerializerOptions _jsonSerializerOptions = new() { ReadCommentHandling = JsonCommentHandling.Disallow, WriteIndented = false, @@ -44,12 +44,12 @@ namespace Jellyfin.Extensions.Json } }; - private static readonly JsonSerializerOptions _pascalCaseJsonSerializerOptions = new (_jsonSerializerOptions) + private static readonly JsonSerializerOptions _pascalCaseJsonSerializerOptions = new(_jsonSerializerOptions) { PropertyNamingPolicy = null }; - private static readonly JsonSerializerOptions _camelCaseJsonSerializerOptions = new (_jsonSerializerOptions) + private static readonly JsonSerializerOptions _camelCaseJsonSerializerOptions = new(_jsonSerializerOptions) { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; diff --git a/src/Jellyfin.Extensions/SplitStringExtensions.cs b/src/Jellyfin.Extensions/SplitStringExtensions.cs index 5fa5c0123..1d1c377f5 100644 --- a/src/Jellyfin.Extensions/SplitStringExtensions.cs +++ b/src/Jellyfin.Extensions/SplitStringExtensions.cs @@ -43,7 +43,7 @@ namespace Jellyfin.Extensions /// <param name="separator">The separator to split on.</param> /// <returns>The enumerator struct.</returns> [Pure] - public static Enumerator SpanSplit(this string str, char separator) => new (str.AsSpan(), separator); + public static Enumerator SpanSplit(this string str, char separator) => new(str.AsSpan(), separator); /// <summary> /// Creates a new span split enumerator. @@ -52,7 +52,7 @@ namespace Jellyfin.Extensions /// <param name="separator">The separator to split on.</param> /// <returns>The enumerator struct.</returns> [Pure] - public static Enumerator Split(this ReadOnlySpan<char> str, char separator) => new (str, separator); + public static Enumerator Split(this ReadOnlySpan<char> str, char separator) => new(str, separator); /// <summary> /// Provides an enumerator for the substrings seperated by the separator. diff --git a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj index bcbe9c1be..6e0474dbf 100644 --- a/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj +++ b/tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj @@ -27,7 +27,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj index ce607b2ec..8476c935e 100644 --- a/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj +++ b/tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj @@ -22,7 +22,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs b/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs index feffb50e8..46439aecb 100644 --- a/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs +++ b/tests/Jellyfin.Controller.Tests/DirectoryServiceTests.cs @@ -13,22 +13,22 @@ namespace Jellyfin.Controller.Tests private static readonly FileSystemMetadata[] _lowerCaseFileSystemMetadata = { - new () + new() { FullName = LowerCasePath + "/Artwork", IsDirectory = true }, - new () + new() { FullName = LowerCasePath + "/Some Other Folder", IsDirectory = true }, - new () + new() { FullName = LowerCasePath + "/Song 2.mp3", IsDirectory = false }, - new () + new() { FullName = LowerCasePath + "/Song 3.mp3", IsDirectory = false @@ -37,12 +37,12 @@ namespace Jellyfin.Controller.Tests private static readonly FileSystemMetadata[] _upperCaseFileSystemMetadata = { - new () + new() { FullName = UpperCasePath + "/Lyrics", IsDirectory = true }, - new () + new() { FullName = UpperCasePath + "/Song 1.mp3", IsDirectory = false diff --git a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj index 0ffc19833..981c7e9c9 100644 --- a/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj +++ b/tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj @@ -22,7 +22,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Dlna.Tests/DlnaManagerTests.cs b/tests/Jellyfin.Dlna.Tests/DlnaManagerTests.cs index 668bd8f87..78a956f5f 100644 --- a/tests/Jellyfin.Dlna.Tests/DlnaManagerTests.cs +++ b/tests/Jellyfin.Dlna.Tests/DlnaManagerTests.cs @@ -46,7 +46,7 @@ namespace Jellyfin.Dlna.Tests ModelDescription = "LG WebOSTV DMRplus", ModelName = "LG TV", ModelNumber = "1.0", - Identification = new () + Identification = new() { FriendlyName = "My Device", Manufacturer = "LG Electronics", @@ -92,7 +92,7 @@ namespace Jellyfin.Dlna.Tests ModelDescription = "LG WebOSTV DMRplus", ModelName = "LG TV", ModelNumber = "1.0", - Identification = new () + Identification = new() { FriendlyName = "My Device", Manufacturer = "LG Electronics", @@ -120,7 +120,7 @@ namespace Jellyfin.Dlna.Tests { Name = "Test Profile", FriendlyName = "My .*", - Identification = new () + Identification = new() }; var deviceMatch = GetManager().IsMatch(device.ToDeviceIdentification(), profile.Identification); diff --git a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj index 098166001..6200a148b 100644 --- a/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj +++ b/tests/Jellyfin.Dlna.Tests/Jellyfin.Dlna.Tests.csproj @@ -17,7 +17,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj index ee3af7559..3dcc00ff0 100644 --- a/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj +++ b/tests/Jellyfin.Extensions.Tests/Jellyfin.Extensions.Tests.csproj @@ -23,7 +23,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs index 655e07074..345f37cbe 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonStringConverterTests.cs @@ -6,7 +6,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { public class JsonStringConverterTests { - private readonly JsonSerializerOptions _jsonSerializerOptions = new () + private readonly JsonSerializerOptions _jsonSerializerOptions = new() { Converters = { diff --git a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj index dc4a42c19..f366f553a 100644 --- a/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj +++ b/tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj @@ -31,7 +31,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj index 7e8397d9f..d4a1a30c3 100644 --- a/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj +++ b/tests/Jellyfin.Model.Tests/Jellyfin.Model.Tests.csproj @@ -17,7 +17,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj index 4096873a3..4c95e78b1 100644 --- a/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj +++ b/tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj @@ -25,7 +25,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj index 78556ee67..87acc7f68 100644 --- a/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj +++ b/tests/Jellyfin.Networking.Tests/Jellyfin.Networking.Tests.csproj @@ -23,7 +23,7 @@ <!-- Code Analyzers--> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj index 10767ae23..4338c812d 100644 --- a/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj +++ b/tests/Jellyfin.Providers.Tests/Jellyfin.Providers.Tests.csproj @@ -29,7 +29,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs index 558321810..98ac1dd64 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/EmbeddedImageProviderTests.cs @@ -62,7 +62,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo for (int i = 1; i <= targetIndex; i++) { var name = i == targetIndex ? filename : "unmatched"; - attachments.Add(new () + attachments.Add(new() { FileName = name, MimeType = mimetype, @@ -107,7 +107,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo for (int i = 1; i <= targetIndex; i++) { var comment = i == targetIndex ? label : "unmatched"; - streams.Add(new () + streams.Add(new() { Type = MediaStreamType.EmbeddedImage, Index = i, diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs index 33da277e3..040ea5d1d 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/SubtitleResolverTests.cs @@ -113,7 +113,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo private static MediaStream CreateMediaStream(string path, string codec, string? language, int index, bool isForced = false, bool isDefault = false) { - return new () + return new() { Index = index, Codec = codec, diff --git a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs index 839925dd1..1503a3392 100644 --- a/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/MediaInfo/VideoImageProviderTests.cs @@ -21,7 +21,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo { private static TheoryData<Video> GetImage_UnsupportedInput_ReturnsNoImage_TestData() { - return new () + return new() { new Movie { IsPlaceHolder = true }, @@ -82,7 +82,7 @@ namespace Jellyfin.Providers.Tests.MediaInfo [InlineData(500, 50)] // calculated time public async void GetImage_TimeSpan_SelectsCorrectTime(int? runTimeSeconds, long expectedSeconds) { - MediaStream targetStream = new () { Type = MediaStreamType.Video, Index = 0 }; + MediaStream targetStream = new() { Type = MediaStreamType.Video, Index = 0 }; var input = new Movie { DefaultVideoStreamIndex = 0, diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs index 6337dea41..4c7c56311 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs @@ -173,7 +173,7 @@ namespace Jellyfin.Server.Implementations.Tests.Data "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg*637452096478512963*Primary*1920*1080*WjQbtJtSO8nhNZ%L_Io#R/oaS6o}-;adXAoIn7j[%hW9s:WGw[nN|test|1234||ss", new ItemImageInfo[] { - new () + new() { Path = "/mnt/series/Family Guy/Season 1/Family Guy - S01E01-thumb.jpg", Type = ImageType.Primary, diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 028ebdf55..f9228b1a7 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -32,7 +32,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs index 362c3216f..5c7c983c2 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs @@ -14,7 +14,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library { public class EpisodeResolverTest { - private static readonly NamingOptions _namingOptions = new (); + private static readonly NamingOptions _namingOptions = new(); [Fact] public void Resolve_GivenVideoInExtrasFolder_DoesNotResolveToEpisode() @@ -65,7 +65,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library { } - protected override TVideoType ResolveVideo<TVideoType>(ItemResolveArgs args, bool parseName) => new (); + protected override TVideoType ResolveVideo<TVideoType>(ItemResolveArgs args, bool parseName) => new(); } } } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs index b29426d85..ccff95313 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs @@ -97,7 +97,7 @@ public class FindExtrasTests false)) .Returns(new List<FileSystemMetadata> { - new () + new() { FullName = "/movies/Up/trailers/some trailer.mkv", Name = "some trailer.mkv", @@ -112,7 +112,7 @@ public class FindExtrasTests false)) .Returns(new List<FileSystemMetadata> { - new () + new() { FullName = "/movies/Up/behind the scenes/the making of Up.mkv", Name = "the making of Up.mkv", @@ -127,7 +127,7 @@ public class FindExtrasTests false)) .Returns(new List<FileSystemMetadata> { - new () + new() { FullName = "/movies/Up/theme-music/theme2.mp3", Name = "theme2.mp3", diff --git a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs index 21131eb97..79c11a865 100644 --- a/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs +++ b/tests/Jellyfin.Server.Integration.Tests/AuthHelper.cs @@ -1,8 +1,8 @@ using System; using System.Net; using System.Net.Http; -using System.Net.Http.Json; using System.Net.Http.Headers; +using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Models.StartupDtos; diff --git a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj index a59900b02..e8fc495f9 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj +++ b/tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj @@ -29,7 +29,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.Server.Integration.Tests/WebSocketTests.cs b/tests/Jellyfin.Server.Integration.Tests/WebSocketTests.cs index ffdc04eba..1a1033443 100644 --- a/tests/Jellyfin.Server.Integration.Tests/WebSocketTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/WebSocketTests.cs @@ -26,7 +26,8 @@ namespace Jellyfin.Server.Integration.Tests { Scheme = "ws", Path = "websocket" - }.Uri, CancellationToken.None)); + }.Uri, + CancellationToken.None)); } } } diff --git a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj index ada9034df..b25b06c7b 100644 --- a/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj +++ b/tests/Jellyfin.Server.Tests/Jellyfin.Server.Tests.csproj @@ -22,7 +22,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj index edf9e0fef..55cdfa2e0 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj +++ b/tests/Jellyfin.XbmcMetadata.Tests/Jellyfin.XbmcMetadata.Tests.csproj @@ -23,7 +23,7 @@ <!-- Code Analyzers --> <ItemGroup Condition=" '$(Configuration)' == 'Debug' "> <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" /> - <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" /> + <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" /> <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" /> </ItemGroup> -- cgit v1.2.3 From 7bfc6b5679308d3ec816e6f34b0dd54cf0cbd07c Mon Sep 17 00:00:00 2001 From: Cody Robibero <cody@robibe.ro> Date: Fri, 24 Dec 2021 14:18:24 -0700 Subject: Remove more warnings --- Emby.Drawing/ImageProcessor.cs | 10 +- Emby.Naming/TV/SeasonPathParser.cs | 6 +- .../Channels/ChannelManager.cs | 8 +- .../Collections/CollectionManager.cs | 2 +- .../Data/SqliteItemRepository.cs | 118 +++++++-------------- .../EntryPoints/LibraryChangedNotifier.cs | 1 + Emby.Server.Implementations/IO/StreamHelper.cs | 20 ++-- .../Images/CollectionFolderImageProvider.cs | 4 +- .../Library/LibraryManager.cs | 14 +-- .../Library/MediaSourceManager.cs | 7 +- .../Library/SearchEngine.cs | 2 +- .../LiveTv/Listings/SchedulesDirect.cs | 2 + .../LiveTv/LiveTvManager.cs | 37 +++---- .../HdHomerun/HdHomerunChannelCommands.cs | 2 +- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 4 +- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 2 +- .../HdHomerun/IHdHomerunChannelCommands.cs | 2 +- .../HdHomerun/LegacyHdHomerunChannelCommands.cs | 2 +- .../Playlists/PlaylistManager.cs | 2 +- Emby.Server.Implementations/TV/TVSeriesManager.cs | 6 +- .../Updates/InstallationManager.cs | 6 +- Jellyfin.Api/Controllers/FilterController.cs | 8 +- Jellyfin.Api/Controllers/ItemsController.cs | 2 +- Jellyfin.Api/Helpers/RequestHelpers.cs | 2 +- .../Users/UserManager.cs | 14 +-- .../CreateNetworkConfiguration.cs | 4 +- MediaBrowser.Common/Net/IPNetAddress.cs | 2 +- MediaBrowser.Common/Net/IPObject.cs | 2 +- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 2 +- MediaBrowser.Controller/Entities/Audio/Audio.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 4 +- .../Entities/InternalItemsQuery.cs | 4 +- MediaBrowser.Controller/Entities/Video.cs | 2 +- MediaBrowser.Controller/Library/ILibraryManager.cs | 14 +-- MediaBrowser.Controller/LiveTv/ILiveTvManager.cs | 4 +- .../MediaEncoding/EncodingHelper.cs | 50 ++++----- .../MediaEncoding/IAttachmentExtractor.cs | 2 +- .../MediaEncoding/IMediaEncoder.cs | 6 +- MediaBrowser.Controller/MediaEncoding/JobLogger.cs | 2 +- .../Persistence/IItemRepository.cs | 12 +-- .../Providers/MetadataResult.cs | 6 +- .../Attachments/AttachmentExtractor.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 4 + .../Subtitles/SubtitleEncoder.cs | 10 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 26 ++--- MediaBrowser.Model/Session/GeneralCommandType.cs | 4 +- MediaBrowser.Providers/Manager/MetadataService.cs | 4 +- .../MusicBrainz/MusicBrainzAlbumProvider.cs | 10 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 2 +- .../Parsers/MovieNfoParserTests.cs | 33 +++--- 50 files changed, 231 insertions(+), 265 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index c9847aa2d..b530c6942 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -101,7 +101,7 @@ namespace Emby.Drawing public async Task ProcessImage(ImageProcessingOptions options, Stream toStream) { var file = await ProcessImage(options).ConfigureAwait(false); - using (var fileStream = AsyncFile.OpenRead(file.path)) + using (var fileStream = AsyncFile.OpenRead(file.Path)) { await fileStream.CopyToAsync(toStream).ConfigureAwait(false); } @@ -116,7 +116,7 @@ namespace Emby.Drawing => _transparentImageTypes.Contains(Path.GetExtension(path)); /// <inheritdoc /> - public async Task<(string path, string? mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options) + public async Task<(string Path, string? MimeType, DateTime DateModified)> ProcessImage(ImageProcessingOptions options) { ItemImageInfo originalImage = options.Image; BaseItem item = options.Item; @@ -135,14 +135,14 @@ namespace Emby.Drawing } var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false); - originalImagePath = supportedImageInfo.path; + originalImagePath = supportedImageInfo.Path; if (!File.Exists(originalImagePath)) { return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); } - dateModified = supportedImageInfo.dateModified; + dateModified = supportedImageInfo.DateModified; bool requiresTransparency = _transparentImageTypes.Contains(Path.GetExtension(originalImagePath)); bool autoOrient = false; @@ -436,7 +436,7 @@ namespace Emby.Drawing .ToString("N", CultureInfo.InvariantCulture); } - private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified) + private async Task<(string Path, DateTime DateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified) { var inputFormat = Path.GetExtension(originalImagePath) .TrimStart('.') diff --git a/Emby.Naming/TV/SeasonPathParser.cs b/Emby.Naming/TV/SeasonPathParser.cs index 6236f86c4..fc9ee8e56 100644 --- a/Emby.Naming/TV/SeasonPathParser.cs +++ b/Emby.Naming/TV/SeasonPathParser.cs @@ -55,7 +55,7 @@ namespace Emby.Naming.TV /// <param name="supportSpecialAliases">if set to <c>true</c> [support special aliases].</param> /// <param name="supportNumericSeasonFolders">if set to <c>true</c> [support numeric season folders].</param> /// <returns>System.Nullable{System.Int32}.</returns> - private static (int? seasonNumber, bool isSeasonFolder) GetSeasonNumberFromPath( + private static (int? SeasonNumber, bool IsSeasonFolder) GetSeasonNumberFromPath( string path, bool supportSpecialAliases, bool supportNumericSeasonFolders) @@ -99,7 +99,7 @@ namespace Emby.Naming.TV if (filename.Contains(name, StringComparison.OrdinalIgnoreCase)) { var result = GetSeasonNumberFromPathSubstring(filename.Replace(name, " ", StringComparison.OrdinalIgnoreCase)); - if (result.seasonNumber.HasValue) + if (result.SeasonNumber.HasValue) { return result; } @@ -142,7 +142,7 @@ namespace Emby.Naming.TV /// </summary> /// <param name="path">The path.</param> /// <returns>System.Nullable{System.Int32}.</returns> - private static (int? seasonNumber, bool isSeasonFolder) GetSeasonNumberFromPathSubstring(ReadOnlySpan<char> path) + private static (int? SeasonNumber, bool IsSeasonFolder) GetSeasonNumberFromPathSubstring(ReadOnlySpan<char> path) { var numericStart = -1; var length = 0; diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 8702691d1..43c8a451b 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -130,16 +130,14 @@ namespace Emby.Server.Implementations.Channels var internalChannel = _libraryManager.GetItemById(item.ChannelId); if (internalChannel == null) { - throw new ArgumentException(); + throw new ArgumentException(nameof(item.ChannelId)); } var channel = Channels.FirstOrDefault(i => GetInternalChannelId(i.Name).Equals(internalChannel.Id)); - var supportsDelete = channel as ISupportsDelete; - - if (supportsDelete == null) + if (channel is not ISupportsDelete supportsDelete) { - throw new ArgumentException(); + throw new ArgumentException(nameof(channel)); } return supportsDelete.DeleteItem(item.ExternalId, CancellationToken.None); diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 79ef70fff..b5b8fea65 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -140,7 +140,7 @@ namespace Emby.Server.Implementations.Collections if (parentFolder == null) { - throw new ArgumentException(); + throw new ArgumentException(nameof(parentFolder)); } var path = Path.Combine(parentFolder.Path, folderName); diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index a6b48b212..47d10b0ac 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -248,40 +248,6 @@ namespace Emby.Server.Implementations.Data BaseItemKind.AudioBook }; - private static readonly Type[] _knownTypes = - { - typeof(LiveTvProgram), - typeof(LiveTvChannel), - typeof(Series), - typeof(Audio), - typeof(MusicAlbum), - typeof(MusicArtist), - typeof(MusicGenre), - typeof(MusicVideo), - typeof(Movie), - typeof(Playlist), - typeof(AudioBook), - typeof(Trailer), - typeof(BoxSet), - typeof(Episode), - typeof(Season), - typeof(Series), - typeof(Book), - typeof(CollectionFolder), - typeof(Folder), - typeof(Genre), - typeof(Person), - typeof(Photo), - typeof(PhotoAlbum), - typeof(Studio), - typeof(UserRootFolder), - typeof(UserView), - typeof(Video), - typeof(Year), - typeof(Channel), - typeof(AggregateFolder) - }; - private static readonly Dictionary<BaseItemKind, string> _baseItemKindNames = new() { { BaseItemKind.AggregateFolder, typeof(AggregateFolder).FullName }, @@ -688,13 +654,13 @@ namespace Emby.Server.Implementations.Data connection.RunInTransaction( db => { - SaveItemsInTranscation(db, tuples); + SaveItemsInTransaction(db, tuples); }, TransactionMode); } } - private void SaveItemsInTranscation(IDatabaseConnection db, IEnumerable<(BaseItem, List<Guid>, BaseItem, string, List<string>)> tuples) + private void SaveItemsInTransaction(IDatabaseConnection db, IEnumerable<(BaseItem Item, List<Guid> AncestorIds, BaseItem TopParent, string UserDataKey, List<string> InheritedTags)> tuples) { var statements = PrepareAll(db, new string[] { @@ -713,17 +679,17 @@ namespace Emby.Server.Implementations.Data saveItemStatement.Reset(); } - var item = tuple.Item1; - var topParent = tuple.Item3; - var userDataKey = tuple.Item4; + var item = tuple.Item; + var topParent = tuple.TopParent; + var userDataKey = tuple.UserDataKey; SaveItem(item, topParent, userDataKey, saveItemStatement); - var inheritedTags = tuple.Item5; + var inheritedTags = tuple.InheritedTags; if (item.SupportsAncestors) { - UpdateAncestors(item.Id, tuple.Item2, db, deleteAncestorsStatement); + UpdateAncestors(item.Id, tuple.AncestorIds, db, deleteAncestorsStatement); } UpdateItemValues(item.Id, GetItemValuesToSave(item, inheritedTags), db); @@ -2201,7 +2167,7 @@ namespace Emby.Server.Implementations.Data return false; } - var sortingFields = new HashSet<string>(query.OrderBy.Select(i => i.Item1), StringComparer.OrdinalIgnoreCase); + var sortingFields = new HashSet<string>(query.OrderBy.Select(i => i.OrderBy), StringComparer.OrdinalIgnoreCase); return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked) || sortingFields.Contains(ItemSortBy.IsPlayed) @@ -3049,88 +3015,86 @@ namespace Emby.Server.Implementations.Data return " ORDER BY " + string.Join(',', orderBy.Select(i => { - var columnMap = MapOrderByField(i.Item1, query); - - var sortOrder = i.Item2 == SortOrder.Ascending ? "ASC" : "DESC"; + var columnMap = MapOrderByField(i.OrderBy, query); - return columnMap.Item1 + " " + sortOrder; + return columnMap.SortBy + " " + columnMap.SortOrder; })); } - private (string, bool) MapOrderByField(string name, InternalItemsQuery query) + private (string SortBy, SortOrder SortOrder) MapOrderByField(string name, InternalItemsQuery query) { if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) { // TODO - return ("SortName", false); + return ("SortName", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.Runtime, StringComparison.OrdinalIgnoreCase)) { - return ("RuntimeTicks", false); + return ("RuntimeTicks", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) { - return ("RANDOM()", false); + return ("RANDOM()", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.DatePlayed, StringComparison.OrdinalIgnoreCase)) { if (query.GroupBySeriesPresentationUniqueKey) { - return ("MAX(LastPlayedDate)", false); + return ("MAX(LastPlayedDate)", SortOrder.Descending); } - return ("LastPlayedDate", false); + return ("LastPlayedDate", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.PlayCount, StringComparison.OrdinalIgnoreCase)) { - return ("PlayCount", false); + return ("PlayCount", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.IsFavoriteOrLiked, StringComparison.OrdinalIgnoreCase)) { - return ("(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", true); + return ("(Select Case When IsFavorite is null Then 0 Else IsFavorite End )", SortOrder.Ascending); } else if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) { - return ("IsFolder", true); + return ("IsFolder", SortOrder.Ascending); } else if (string.Equals(name, ItemSortBy.IsPlayed, StringComparison.OrdinalIgnoreCase)) { - return ("played", true); + return ("played", SortOrder.Ascending); } else if (string.Equals(name, ItemSortBy.IsUnplayed, StringComparison.OrdinalIgnoreCase)) { - return ("played", false); + return ("played", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.DateLastContentAdded, StringComparison.OrdinalIgnoreCase)) { - return ("DateLastMediaAdded", false); + return ("DateLastMediaAdded", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.Artist, StringComparison.OrdinalIgnoreCase)) { - return ("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=0 LIMIT 1)", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.AlbumArtist, StringComparison.OrdinalIgnoreCase)) { - return ("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=1 LIMIT 1)", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.OfficialRating, StringComparison.OrdinalIgnoreCase)) { - return ("InheritedParentalRatingValue", false); + return ("InheritedParentalRatingValue", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.Studio, StringComparison.OrdinalIgnoreCase)) { - return ("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", false); + return ("(select CleanValue from itemvalues where ItemId=Guid and Type=3 LIMIT 1)", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.SeriesDatePlayed, StringComparison.OrdinalIgnoreCase)) { - return ("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", false); + return ("(Select MAX(LastPlayedDate) from TypedBaseItems B" + GetJoinUserDataText(query) + " where Played=1 and B.SeriesPresentationUniqueKey=A.PresentationUniqueKey)", SortOrder.Descending); } else if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase)) { - return ("SeriesName", false); + return ("SeriesName", SortOrder.Descending); } - return (name, false); + return (name, SortOrder.Descending); } public List<Guid> GetItemIdsList(InternalItemsQuery query) @@ -5230,32 +5194,32 @@ AND Type = @InternalPersonType)"); } } - public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 0, 1 }, typeof(MusicArtist).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 0 }, typeof(MusicArtist).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 1 }, typeof(MusicArtist).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query) { return GetItemValues(query, new[] { 3 }, typeof(Studio).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query) { return GetItemValues(query, new[] { 2 }, typeof(Genre).FullName); } - public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query) { return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName); } @@ -5351,7 +5315,7 @@ AND Type = @InternalPersonType)"); return list; } - private QueryResult<(BaseItem, ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) + private QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) { if (query == null) { @@ -5676,7 +5640,7 @@ AND Type = @InternalPersonType)"); return counts; } - private List<(int, string)> GetItemValuesToSave(BaseItem item, List<string> inheritedTags) + private List<(int MagicNumber, string Value)> GetItemValuesToSave(BaseItem item, List<string> inheritedTags) { var list = new List<(int, string)>(); @@ -5701,7 +5665,7 @@ AND Type = @InternalPersonType)"); return list; } - private void UpdateItemValues(Guid itemId, List<(int, string)> values, IDatabaseConnection db) + private void UpdateItemValues(Guid itemId, List<(int MagicNumber, string Value)> values, IDatabaseConnection db) { if (itemId.Equals(Guid.Empty)) { @@ -5723,7 +5687,7 @@ AND Type = @InternalPersonType)"); InsertItemValues(guidBlob, values, db); } - private void InsertItemValues(byte[] idBlob, List<(int, string)> values, IDatabaseConnection db) + private void InsertItemValues(byte[] idBlob, List<(int MagicNumber, string Value)> values, IDatabaseConnection db) { const int Limit = 100; var startIndex = 0; @@ -5755,7 +5719,7 @@ AND Type = @InternalPersonType)"); var currentValueInfo = values[i]; - var itemValue = currentValueInfo.Item2; + var itemValue = currentValueInfo.Value; // Don't save if invalid if (string.IsNullOrWhiteSpace(itemValue)) @@ -5763,7 +5727,7 @@ AND Type = @InternalPersonType)"); continue; } - statement.TryBind("@Type" + index, currentValueInfo.Item1); + statement.TryBind("@Type" + index, currentValueInfo.MagicNumber); statement.TryBind("@Value" + index, itemValue); statement.TryBind("@CleanValue" + index, GetCleanValue(itemValue)); } diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 4a5f72327..d43996c69 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -464,6 +464,7 @@ namespace Emby.Server.Implementations.EntryPoints public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// <summary> diff --git a/Emby.Server.Implementations/IO/StreamHelper.cs b/Emby.Server.Implementations/IO/StreamHelper.cs index e4f5f4cf0..f55c16d6d 100644 --- a/Emby.Server.Implementations/IO/StreamHelper.cs +++ b/Emby.Server.Implementations/IO/StreamHelper.cs @@ -17,11 +17,11 @@ namespace Emby.Server.Implementations.IO try { int read; - while ((read = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + while ((read = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0) { cancellationToken.ThrowIfCancellationRequested(); - await destination.WriteAsync(buffer, 0, read, cancellationToken).ConfigureAwait(false); + await destination.WriteAsync(buffer.AsMemory(0, read), cancellationToken).ConfigureAwait(false); if (onStarted != null) { @@ -44,11 +44,11 @@ namespace Emby.Server.Implementations.IO if (emptyReadLimit <= 0) { int read; - while ((read = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + while ((read = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0) { cancellationToken.ThrowIfCancellationRequested(); - await destination.WriteAsync(buffer, 0, read, cancellationToken).ConfigureAwait(false); + await destination.WriteAsync(buffer.AsMemory(0, read), cancellationToken).ConfigureAwait(false); } return; @@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.IO { cancellationToken.ThrowIfCancellationRequested(); - var bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + var bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); if (bytesRead == 0) { @@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.IO { eofCount = 0; - await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); + await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); } } } @@ -88,13 +88,13 @@ namespace Emby.Server.Implementations.IO { int bytesRead; - while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0) { var bytesToWrite = Math.Min(bytesRead, copyLength); if (bytesToWrite > 0) { - await destination.WriteAsync(buffer, 0, Convert.ToInt32(bytesToWrite), cancellationToken).ConfigureAwait(false); + await destination.WriteAsync(buffer.AsMemory(0, Convert.ToInt32(bytesToWrite)), cancellationToken).ConfigureAwait(false); } copyLength -= bytesToWrite; @@ -137,9 +137,9 @@ namespace Emby.Server.Implementations.IO int bytesRead; int totalBytesRead = 0; - while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + while ((bytesRead = await source.ReadAsync(buffer, cancellationToken).ConfigureAwait(false)) != 0) { - await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); + await destination.WriteAsync(buffer.AsMemory(0, bytesRead), cancellationToken).ConfigureAwait(false); totalBytesRead += bytesRead; } diff --git a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs index 7e12ebb08..7958eb8f5 100644 --- a/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/Images/CollectionFolderImageProvider.cs @@ -68,9 +68,9 @@ namespace Emby.Server.Implementations.Images DtoOptions = new DtoOptions(false), ImageTypes = new ImageType[] { ImageType.Primary }, Limit = 8, - OrderBy = new ValueTuple<string, SortOrder>[] + OrderBy = new[] { - new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) + (ItemSortBy.Random, SortOrder.Ascending) }, IncludeItemTypes = includeItemTypes }); diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index e30fa7097..0fa779a0a 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1373,7 +1373,7 @@ namespace Emby.Server.Implementations.Library return _itemRepository.GetItemIdsList(query); } - public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query) { if (query.User != null) { @@ -1384,7 +1384,7 @@ namespace Emby.Server.Implementations.Library return _itemRepository.GetStudios(query); } - public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query) { if (query.User != null) { @@ -1395,7 +1395,7 @@ namespace Emby.Server.Implementations.Library return _itemRepository.GetGenres(query); } - public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query) { if (query.User != null) { @@ -1406,7 +1406,7 @@ namespace Emby.Server.Implementations.Library return _itemRepository.GetMusicGenres(query); } - public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query) { if (query.User != null) { @@ -1417,7 +1417,7 @@ namespace Emby.Server.Implementations.Library return _itemRepository.GetAllArtists(query); } - public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query) { if (query.User != null) { @@ -1458,7 +1458,7 @@ namespace Emby.Server.Implementations.Library } } - public QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query) + public QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query) { if (query.User != null) { @@ -1757,7 +1757,7 @@ namespace Emby.Server.Implementations.Library return orderedItems ?? items; } - public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ValueTuple<string, SortOrder>> orderBy) + public IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy) { var isFirst = true; diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index 972d4ebbb..a414e7e16 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -464,12 +464,11 @@ namespace Emby.Server.Implementations.Library try { - var tuple = GetProvider(request.OpenToken); - var provider = tuple.Item1; + var (provider, keyId) = GetProvider(request.OpenToken); var currentLiveStreams = _openStreams.Values.ToList(); - liveStream = await provider.OpenMediaSource(tuple.Item2, currentLiveStreams, cancellationToken).ConfigureAwait(false); + liveStream = await provider.OpenMediaSource(keyId, currentLiveStreams, cancellationToken).ConfigureAwait(false); mediaSource = liveStream.MediaSource; @@ -829,7 +828,7 @@ namespace Emby.Server.Implementations.Library } } - private (IMediaSourceProvider, string) GetProvider(string key) + private (IMediaSourceProvider MediaSourceProvider, string KeyId) GetProvider(string key) { if (string.IsNullOrEmpty(key)) { diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 4aacf7774..55911933a 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -190,7 +190,7 @@ namespace Emby.Server.Implementations.Library searchQuery.ParentId = Guid.Empty; searchQuery.IncludeItemsByName = true; searchQuery.IncludeItemTypes = Array.Empty<BaseItemKind>(); - mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item1).ToList(); + mediaItems = _libraryManager.GetAllArtists(searchQuery).Items.Select(i => i.Item).ToList(); } else { diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs index 2fbd47bc7..a8440102d 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs @@ -643,7 +643,9 @@ namespace Emby.Server.Implementations.LiveTv.Listings CancellationToken cancellationToken) { using var options = new HttpRequestMessage(HttpMethod.Post, ApiUrl + "/token"); +#pragma warning disable CA5350 // SchedulesDirect is always SHA1. var hashedPasswordBytes = SHA1.HashData(Encoding.ASCII.GetBytes(password)); +#pragma warning restore CA5350 // TODO: remove ToLower when Convert.ToHexString supports lowercase // Schedules Direct requires the hex to be lowercase string hashedPassword = Convert.ToHexString(hashedPasswordBytes).ToLowerInvariant(); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 047d8e98c..aa3598c8b 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -207,7 +207,7 @@ namespace Emby.Server.Implementations.LiveTv orderBy.Insert(0, (ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending)); } - if (!internalQuery.OrderBy.Any(i => string.Equals(i.Item1, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))) + if (!internalQuery.OrderBy.Any(i => string.Equals(i.OrderBy, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase))) { orderBy.Add((ItemSortBy.SortName, SortOrder.Ascending)); } @@ -520,7 +520,7 @@ namespace Emby.Server.Implementations.LiveTv return item; } - private (LiveTvProgram item, bool isNew, bool isUpdated) GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel) + private (LiveTvProgram Item, bool IsNew, bool IsUpdated) GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel) { var id = _tvDtoService.GetInternalProgramId(info.Id); @@ -779,9 +779,9 @@ namespace Emby.Server.Implementations.LiveTv var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user); - var list = new List<Tuple<BaseItemDto, string, string>> + var list = new List<(BaseItemDto ItemDto, string ExternalId, string ExternalSeriesId)> { - new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId) + (dto, program.ExternalId, program.ExternalSeriesId) }; await AddRecordingInfo(list, cancellationToken).ConfigureAwait(false); @@ -976,16 +976,16 @@ namespace Emby.Server.Implementations.LiveTv return score; } - private async Task AddRecordingInfo(IEnumerable<Tuple<BaseItemDto, string, string>> programs, CancellationToken cancellationToken) + private async Task AddRecordingInfo(IEnumerable<(BaseItemDto ItemDto, string ExternalId, string ExternalSeriesId)> programs, CancellationToken cancellationToken) { IReadOnlyList<TimerInfo> timerList = null; IReadOnlyList<SeriesTimerInfo> seriesTimerList = null; foreach (var programTuple in programs) { - var program = programTuple.Item1; - var externalProgramId = programTuple.Item2; - string externalSeriesId = programTuple.Item3; + var program = programTuple.ItemDto; + var externalProgramId = programTuple.ExternalId; + string externalSeriesId = programTuple.ExternalSeriesId; timerList ??= (await GetTimersInternal(new TimerQuery(), cancellationToken).ConfigureAwait(false)).Items; @@ -1186,13 +1186,13 @@ namespace Emby.Server.Implementations.LiveTv foreach (var program in channelPrograms) { var programTuple = GetProgram(program, existingPrograms, currentChannel); - var programItem = programTuple.item; + var programItem = programTuple.Item; - if (programTuple.isNew) + if (programTuple.IsNew) { newPrograms.Add(programItem); } - else if (programTuple.isUpdated) + else if (programTuple.IsUpdated) { updatedPrograms.Add(programItem); } @@ -1423,9 +1423,9 @@ namespace Emby.Server.Implementations.LiveTv return result; } - public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null) + public Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem Item, BaseItemDto ItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null) { - var programTuples = new List<Tuple<BaseItemDto, string, string>>(); + var programTuples = new List<(BaseItemDto Dto, string ExternalId, string ExternalSeriesId)>(); var hasChannelImage = fields.Contains(ItemFields.ChannelImage); var hasChannelInfo = fields.Contains(ItemFields.ChannelInfo); @@ -1461,7 +1461,7 @@ namespace Emby.Server.Implementations.LiveTv } } - programTuples.Add(new Tuple<BaseItemDto, string, string>(dto, program.ExternalId, program.ExternalSeriesId)); + programTuples.Add((dto, program.ExternalId, program.ExternalSeriesId)); } return AddRecordingInfo(programTuples, CancellationToken.None); @@ -1868,11 +1868,11 @@ namespace Emby.Server.Implementations.LiveTv return _libraryManager.GetItemById(internalChannelId); } - public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> items, DtoOptions options, User user) + public void AddChannelInfo(IReadOnlyCollection<(BaseItemDto ItemDto, LiveTvChannel Channel)> items, DtoOptions options, User user) { var now = DateTime.UtcNow; - var channelIds = items.Select(i => i.Item2.Id).Distinct().ToArray(); + var channelIds = items.Select(i => i.Channel.Id).Distinct().ToArray(); var programs = options.AddCurrentProgram ? _libraryManager.GetItemList(new InternalItemsQuery(user) { @@ -1893,11 +1893,8 @@ namespace Emby.Server.Implementations.LiveTv var addCurrentProgram = options.AddCurrentProgram; - foreach (var tuple in items) + foreach (var (dto, channel) in items) { - var dto = tuple.Item1; - var channel = tuple.Item2; - dto.Number = channel.Number; dto.ChannelNumber = channel.Number; dto.ChannelType = channel.ChannelType; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs index 069b4fab6..aae33503f 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunChannelCommands.cs @@ -16,7 +16,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun _profile = profile; } - public IEnumerable<(string, string)> GetCommands() + public IEnumerable<(string CommandName, string CommandValue)> GetCommands() { if (!string.IsNullOrEmpty(_channel)) { diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index f009c77cf..f1a6ef344 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -114,7 +114,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun foreach (var command in commands.GetCommands()) { - var channelMsgLen = WriteSetMessage(buffer, i, command.Item1, command.Item2, lockKeyValue); + var channelMsgLen = WriteSetMessage(buffer, i, command.CommandName, command.CommandValue, lockKeyValue); await stream.WriteAsync(buffer.AsMemory(0, channelMsgLen), cancellationToken).ConfigureAwait(false); receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); @@ -167,7 +167,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { foreach (var command in commandList) { - var channelMsgLen = WriteSetMessage(buffer, _activeTuner, command.Item1, command.Item2, _lockkey); + var channelMsgLen = WriteSetMessage(buffer, _activeTuner, command.CommandName, command.CommandValue, _lockkey); await stream.WriteAsync(buffer.AsMemory(0, channelMsgLen), cancellationToken).ConfigureAwait(false); int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index d2f033439..9ed0d8d73 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -212,7 +212,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (read > 0) { - fileStream.Write(buffer, RtpHeaderBytes, read); + await fileStream.WriteAsync(buffer.AsMemory(RtpHeaderBytes, read), linkedSource.Token).ConfigureAwait(false); } if (!resolved) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs index 153354932..11bd40ab1 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/IHdHomerunChannelCommands.cs @@ -6,6 +6,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { public interface IHdHomerunChannelCommands { - IEnumerable<(string, string)> GetCommands(); + IEnumerable<(string CommandName, string CommandValue)> GetCommands(); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs index 26627b8aa..80d9d0724 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/LegacyHdHomerunChannelCommands.cs @@ -22,7 +22,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } - public IEnumerable<(string, string)> GetCommands() + public IEnumerable<(string CommandName, string CommandValue)> GetCommands() { if (!string.IsNullOrEmpty(_channel)) { diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs index 9481e26f7..02df2fffe 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs @@ -72,7 +72,7 @@ namespace Emby.Server.Implementations.Playlists var parentFolder = GetPlaylistsFolder(Guid.Empty); if (parentFolder == null) { - throw new ArgumentException(); + throw new ArgumentException(nameof(parentFolder)); } if (string.IsNullOrEmpty(options.MediaType)) diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs index 5dbe9f44d..c994ffc90 100644 --- a/Emby.Server.Implementations/TV/TVSeriesManager.cs +++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs @@ -117,7 +117,7 @@ namespace Emby.Server.Implementations.TV new InternalItemsQuery(user) { IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.DatePlayed, SortOrder.Descending) }, + OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending) }, SeriesPresentationUniqueKey = presentationUniqueKey, Limit = limit, DtoOptions = new DtoOptions { Fields = new[] { ItemFields.SeriesPresentationUniqueKey }, EnableImages = false }, @@ -193,7 +193,7 @@ namespace Emby.Server.Implementations.TV AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Descending) }, + OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Descending) }, IsPlayed = true, Limit = 1, ParentIndexNumberNotEquals = 0, @@ -211,7 +211,7 @@ namespace Emby.Server.Implementations.TV AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { BaseItemKind.Episode }, - OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) }, + OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }, Limit = 1, IsPlayed = false, IsVirtualItem = false, diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 24d592525..5eb4c9ffa 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -52,7 +52,7 @@ namespace Emby.Server.Implementations.Updates /// <summary> /// The current installations. /// </summary> - private readonly List<(InstallationInfo info, CancellationTokenSource token)> _currentInstallations; + private readonly List<(InstallationInfo Info, CancellationTokenSource Token)> _currentInstallations; /// <summary> /// The completed installations. @@ -399,13 +399,13 @@ namespace Emby.Server.Implementations.Updates { lock (_currentInstallationsLock) { - var install = _currentInstallations.Find(x => x.info.Id == id); + var install = _currentInstallations.Find(x => x.Info.Id == id); if (install == default((InstallationInfo, CancellationTokenSource))) { return false; } - install.token.Cancel(); + install.Token.Cancel(); _currentInstallations.Remove(install); return true; } diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index e170436d1..a4f12666d 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -197,16 +197,16 @@ namespace Jellyfin.Api.Controllers { filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair { - Name = i.Item1.Name, - Id = i.Item1.Id + Name = i.Item.Name, + Id = i.Item.Id }).ToArray(); } else { filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameGuidPair { - Name = i.Item1.Name, - Id = i.Item1.Id + Name = i.Item.Name, + Id = i.Item.Id }).ToArray(); } diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 65c0662d2..1b938f4d5 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -484,7 +484,7 @@ namespace Jellyfin.Api.Controllers // Albums by artist if (query.ArtistIds.Length > 0 && query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes[0] == BaseItemKind.MusicAlbum) { - query.OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.ProductionYear, SortOrder.Descending), new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) }; + query.OrderBy = new[] { (ItemSortBy.ProductionYear, SortOrder.Descending), (ItemSortBy.SortName, SortOrder.Ascending) }; } } diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index ca8bc0bdd..1471f5a24 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -30,7 +30,7 @@ namespace Jellyfin.Api.Helpers { if (sortBy.Count == 0) { - return Array.Empty<ValueTuple<string, SortOrder>>(); + return Array.Empty<(string, SortOrder)>(); } var result = new (string, SortOrder)[sortBy.Count]; diff --git a/Jellyfin.Server.Implementations/Users/UserManager.cs b/Jellyfin.Server.Implementations/Users/UserManager.cs index 3d0a51ff6..c41b343c7 100644 --- a/Jellyfin.Server.Implementations/Users/UserManager.cs +++ b/Jellyfin.Server.Implementations/Users/UserManager.cs @@ -394,12 +394,12 @@ namespace Jellyfin.Server.Implementations.Users var user = Users.FirstOrDefault(i => string.Equals(username, i.Username, StringComparison.OrdinalIgnoreCase)); var authResult = await AuthenticateLocalUser(username, password, user, remoteEndPoint) .ConfigureAwait(false); - var authenticationProvider = authResult.authenticationProvider; - var success = authResult.success; + var authenticationProvider = authResult.AuthenticationProvider; + var success = authResult.Success; if (user == null) { - string updatedUsername = authResult.username; + string updatedUsername = authResult.Username; if (success && authenticationProvider != null @@ -785,7 +785,7 @@ namespace Jellyfin.Server.Implementations.Users return providers; } - private async Task<(IAuthenticationProvider? authenticationProvider, string username, bool success)> AuthenticateLocalUser( + private async Task<(IAuthenticationProvider? AuthenticationProvider, string Username, bool Success)> AuthenticateLocalUser( string username, string password, User? user, @@ -798,8 +798,8 @@ namespace Jellyfin.Server.Implementations.Users { var providerAuthResult = await AuthenticateWithProvider(provider, username, password, user).ConfigureAwait(false); - var updatedUsername = providerAuthResult.username; - success = providerAuthResult.success; + var updatedUsername = providerAuthResult.Username; + success = providerAuthResult.Success; if (success) { @@ -822,7 +822,7 @@ namespace Jellyfin.Server.Implementations.Users return (authenticationProvider, username, success); } - private async Task<(string username, bool success)> AuthenticateWithProvider( + private async Task<(string Username, bool Success)> AuthenticateWithProvider( IAuthenticationProvider provider, string username, string password, diff --git a/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs b/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs index a951f751e..5e601ca84 100644 --- a/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs +++ b/Jellyfin.Server/Migrations/PreStartupRoutines/CreateNetworkConfiguration.cs @@ -53,7 +53,7 @@ public class CreateNetworkConfiguration : IMigrationRoutine networkConfigSerializer.Serialize(xmlWriter, networkSettings); } -#pragma warning disable CS1591 +#pragma warning disable public sealed class OldNetworkConfiguration { public const int DefaultHttpPort = 8096; @@ -134,5 +134,5 @@ public class CreateNetworkConfiguration : IMigrationRoutine public string[] KnownProxies { get; set; } = Array.Empty<string>(); } -#pragma warning restore CS1591 +#pragma warning restore } diff --git a/MediaBrowser.Common/Net/IPNetAddress.cs b/MediaBrowser.Common/Net/IPNetAddress.cs index f6e3971bf..f1428d4be 100644 --- a/MediaBrowser.Common/Net/IPNetAddress.cs +++ b/MediaBrowser.Common/Net/IPNetAddress.cs @@ -195,7 +195,7 @@ namespace MediaBrowser.Common.Net return NetworkAddress.PrefixLength <= netaddrObj.PrefixLength; } - var altAddress = NetworkAddressOf(netaddrObj.Address, PrefixLength).address; + var altAddress = NetworkAddressOf(netaddrObj.Address, PrefixLength).Address; return NetworkAddress.Address.Equals(altAddress); } diff --git a/MediaBrowser.Common/Net/IPObject.cs b/MediaBrowser.Common/Net/IPObject.cs index 2612268fd..bd5368882 100644 --- a/MediaBrowser.Common/Net/IPObject.cs +++ b/MediaBrowser.Common/Net/IPObject.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.Common.Net /// <param name="address">IP Address to convert.</param> /// <param name="prefixLength">Subnet prefix.</param> /// <returns>IPAddress.</returns> - public static (IPAddress address, byte prefixLength) NetworkAddressOf(IPAddress address, byte prefixLength) + public static (IPAddress Address, byte PrefixLength) NetworkAddressOf(IPAddress address, byte prefixLength) { if (address == null) { diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 7ca0e851b..03882a0b9 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -75,7 +75,7 @@ namespace MediaBrowser.Controller.Drawing /// </summary> /// <param name="options">The options.</param> /// <returns>Task.</returns> - Task<(string path, string? mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options); + Task<(string Path, string? MimeType, DateTime DateModified)> ProcessImage(ImageProcessingOptions options); /// <summary> /// Gets the supported image output formats. diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 9d0187c8c..29f7bf92b 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -135,7 +135,7 @@ namespace MediaBrowser.Controller.Entities.Audio return info; } - protected override IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() + protected override IEnumerable<(BaseItem Item, MediaSourceType MediaSourceType)> GetAllItemsForMediaSources() => new[] { ((BaseItem)this, MediaSourceType.Default) }; } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f5dd82548..915971adc 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1069,7 +1069,7 @@ namespace MediaBrowser.Controller.Entities } var list = GetAllItemsForMediaSources(); - var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList(); + var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item, i.MediaSourceType)).ToList(); if (IsActiveRecording()) { @@ -1097,7 +1097,7 @@ namespace MediaBrowser.Controller.Entities .ToList(); } - protected virtual IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() + protected virtual IEnumerable<(BaseItem Item, MediaSourceType MediaSourceType)> GetAllItemsForMediaSources() { return Enumerable.Empty<(BaseItem, MediaSourceType)>(); } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index f06b5c787..db1697c79 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.Entities MediaTypes = Array.Empty<string>(); MinSimilarityScore = 20; OfficialRatings = Array.Empty<string>(); - OrderBy = Array.Empty<ValueTuple<string, SortOrder>>(); + OrderBy = Array.Empty<(string, SortOrder)>(); PersonIds = Array.Empty<Guid>(); PersonTypes = Array.Empty<string>(); PresetViews = Array.Empty<string>(); @@ -271,7 +271,7 @@ namespace MediaBrowser.Controller.Entities public bool? HasChapterImages { get; set; } - public IReadOnlyList<(string, SortOrder)> OrderBy { get; set; } + public IReadOnlyList<(string OrderBy, SortOrder SortOrder)> OrderBy { get; set; } public DateTime? MinDateCreated { get; set; } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 4f7614f96..3e125602a 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -517,7 +517,7 @@ namespace MediaBrowser.Controller.Entities }).FirstOrDefault(); } - protected override IEnumerable<(BaseItem, MediaSourceType)> GetAllItemsForMediaSources() + protected override IEnumerable<(BaseItem Item, MediaSourceType MediaSourceType)> GetAllItemsForMediaSources() { var list = new List<(BaseItem, MediaSourceType)> { diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index eba92695e..8db528330 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -212,7 +212,7 @@ namespace MediaBrowser.Controller.Library /// <returns>IEnumerable{BaseItem}.</returns> IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<string> sortBy, SortOrder sortOrder); - IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<ValueTuple<string, SortOrder>> orderBy); + IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User user, IEnumerable<(string OrderBy, SortOrder SortOrder)> orderBy); /// <summary> /// Gets the user root folder. @@ -573,17 +573,17 @@ namespace MediaBrowser.Controller.Library void RemoveMediaPath(string virtualFolderName, string mediaPath); - QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query); int GetCount(InternalItemsQuery query); diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index dbd18165d..6dc5665b2 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -251,7 +251,7 @@ namespace MediaBrowser.Controller.LiveTv /// <param name="fields">The fields.</param> /// <param name="user">The user.</param> /// <returns>Task.</returns> - Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null); + Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem Item, BaseItemDto ItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null); /// <summary> /// Saves the tuner host. @@ -292,7 +292,7 @@ namespace MediaBrowser.Controller.LiveTv /// <param name="items">The items.</param> /// <param name="options">The options.</param> /// <param name="user">The user.</param> - void AddChannelInfo(IReadOnlyCollection<(BaseItemDto, LiveTvChannel)> items, DtoOptions options, User user); + void AddChannelInfo(IReadOnlyCollection<(BaseItemDto ItemDto, LiveTvChannel Channel)> items, DtoOptions options, User user); Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken); diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 8c5474539..d6f69a150 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -21,6 +21,13 @@ namespace MediaBrowser.Controller.MediaEncoding { public class EncodingHelper { + private const string QsvAlias = "qs"; + private const string VaapiAlias = "va"; + private const string D3d11vaAlias = "dx11"; + private const string VideotoolboxAlias = "vt"; + private const string OpenclAlias = "ocl"; + private const string CudaAlias = "cu"; + private readonly IMediaEncoder _mediaEncoder; private readonly ISubtitleEncoder _subtitleEncoder; @@ -42,13 +49,6 @@ namespace MediaBrowser.Controller.MediaEncoding "Main10" }; - private const string QsvAlias = "qs"; - private const string VaapiAlias = "va"; - private const string D3d11vaAlias = "dx11"; - private const string VideotoolboxAlias = "vt"; - private const string OpenclAlias = "ocl"; - private const string CudaAlias = "cu"; - public EncodingHelper( IMediaEncoder mediaEncoder, ISubtitleEncoder subtitleEncoder) @@ -2290,7 +2290,7 @@ namespace MediaBrowser.Controller.MediaEncoding return returnFirstIfNoIndex ? streams.FirstOrDefault() : null; } - public static (int? width, int? height) GetFixedOutputSize( + public static (int? Width, int? Height) GetFixedOutputSize( int? videoWidth, int? videoHeight, int? requestedWidth, @@ -2671,7 +2671,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="options">Encoding options.</param> /// <param name="vidEncoder">Video encoder to use.</param> /// <returns>The tuple contains three lists: main, sub and overlay filters.</returns> - public (List<string>, List<string>, List<string>) GetSwVidFilterChain( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetSwVidFilterChain( EncodingJobInfo state, EncodingOptions options, string vidEncoder) @@ -2751,7 +2751,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="options">Encoding options.</param> /// <param name="vidEncoder">Video encoder to use.</param> /// <returns>The tuple contains three lists: main, sub and overlay filters.</returns> - public (List<string>, List<string>, List<string>) GetNvidiaVidFilterChain( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetNvidiaVidFilterChain( EncodingJobInfo state, EncodingOptions options, string vidEncoder) @@ -2778,7 +2778,7 @@ namespace MediaBrowser.Controller.MediaEncoding return GetNvidiaVidFiltersPrefered(state, options, vidDecoder, vidEncoder); } - public (List<string>, List<string>, List<string>) GetNvidiaVidFiltersPrefered( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetNvidiaVidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, string vidDecoder, @@ -2838,6 +2838,7 @@ namespace MediaBrowser.Controller.MediaEncoding mainFilters.Add("hwupload"); } } + if (isNvdecDecoder) { // INPUT cuda surface(vram) @@ -2938,7 +2939,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="options">Encoding options.</param> /// <param name="vidEncoder">Video encoder to use.</param> /// <returns>The tuple contains three lists: main, sub and overlay filters.</returns> - public (List<string>, List<string>, List<string>) GetAmdVidFilterChain( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetAmdVidFilterChain( EncodingJobInfo state, EncodingOptions options, string vidEncoder) @@ -2966,7 +2967,7 @@ namespace MediaBrowser.Controller.MediaEncoding return GetAmdDx11VidFiltersPrefered(state, options, vidDecoder, vidEncoder); } - public (List<string>, List<string>, List<string>) GetAmdDx11VidFiltersPrefered( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetAmdDx11VidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, string vidDecoder, @@ -3136,7 +3137,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="options">Encoding options.</param> /// <param name="vidEncoder">Video encoder to use.</param> /// <returns>The tuple contains three lists: main, sub and overlay filters.</returns> - public (List<string>, List<string>, List<string>) GetIntelVidFilterChain( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetIntelVidFilterChain( EncodingJobInfo state, EncodingOptions options, string vidEncoder) @@ -3182,7 +3183,7 @@ namespace MediaBrowser.Controller.MediaEncoding return (null, null, null); } - public (List<string>, List<string>, List<string>) GetIntelQsvDx11VidFiltersPrefered( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetIntelQsvDx11VidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, string vidDecoder, @@ -3374,7 +3375,7 @@ namespace MediaBrowser.Controller.MediaEncoding return (mainFilters, subFilters, overlayFilters); } - public (List<string>, List<string>, List<string>) GetIntelQsvVaapiVidFiltersPrefered( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetIntelQsvVaapiVidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, string vidDecoder, @@ -3589,7 +3590,7 @@ namespace MediaBrowser.Controller.MediaEncoding /// <param name="options">Encoding options.</param> /// <param name="vidEncoder">Video encoder to use.</param> /// <returns>The tuple contains three lists: main, sub and overlay filters.</returns> - public (List<string>, List<string>, List<string>) GetVaapiVidFilterChain( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetVaapiVidFilterChain( EncodingJobInfo state, EncodingOptions options, string vidEncoder) @@ -3615,13 +3616,13 @@ namespace MediaBrowser.Controller.MediaEncoding if (!isSwEncoder) { var newfilters = new List<string>(); - var noOverlay = swFilterChain.Item3.Count == 0; - newfilters.AddRange(noOverlay ? swFilterChain.Item1 : swFilterChain.Item3); + var noOverlay = swFilterChain.OverlayFilters.Count == 0; + newfilters.AddRange(noOverlay ? swFilterChain.MainFilters : swFilterChain.OverlayFilters); newfilters.Add("hwupload"); - var mainFilters = noOverlay ? newfilters : swFilterChain.Item1; - var overlayFilters = noOverlay ? swFilterChain.Item3 : newfilters; - return (mainFilters, swFilterChain.Item2, overlayFilters); + var mainFilters = noOverlay ? newfilters : swFilterChain.MainFilters; + var overlayFilters = noOverlay ? swFilterChain.OverlayFilters : newfilters; + return (mainFilters, swFilterChain.SubFilters, overlayFilters); } return swFilterChain; @@ -3638,7 +3639,7 @@ namespace MediaBrowser.Controller.MediaEncoding return GetVaapiLimitedVidFiltersPrefered(state, options, vidDecoder, vidEncoder); } - public (List<string>, List<string>, List<string>) GetVaapiFullVidFiltersPrefered( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetVaapiFullVidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, string vidDecoder, @@ -3834,7 +3835,7 @@ namespace MediaBrowser.Controller.MediaEncoding return (mainFilters, subFilters, overlayFilters); } - public (List<string>, List<string>, List<string>) GetVaapiLimitedVidFiltersPrefered( + public (List<string> MainFilters, List<string> SubFilters, List<string> OverlayFilters) GetVaapiLimitedVidFiltersPrefered( EncodingJobInfo state, EncodingOptions options, string vidDecoder, @@ -4090,7 +4091,6 @@ namespace MediaBrowser.Controller.MediaEncoding "{0}", string.Join(',', overlayFilters)); - var mapPrefix = Convert.ToInt32(state.SubtitleStream.IsExternal); var subtitleStreamIndex = state.SubtitleStream.IsExternal ? 0 diff --git a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs index c38e7ec3b..4e7e26624 100644 --- a/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs +++ b/MediaBrowser.Controller/MediaEncoding/IAttachmentExtractor.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.MediaEncoding { public interface IAttachmentExtractor { - Task<(MediaAttachment attachment, Stream stream)> GetAttachment( + Task<(MediaAttachment Attachment, Stream Stream)> GetAttachment( BaseItem item, string mediaSourceId, int attachmentStreamIndex, diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 27d618a3f..fd3eb8105 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -32,19 +32,19 @@ namespace MediaBrowser.Controller.MediaEncoding Version EncoderVersion { get; } /// <summary> - /// Whether the configured Vaapi device is from AMD(radeonsi/r600 Mesa driver). + /// Gets a value indicating whether the configured Vaapi device is from AMD(radeonsi/r600 Mesa driver). /// </summary> /// <value><c>true</c> if the Vaapi device is an AMD(radeonsi/r600 Mesa driver) GPU, <c>false</c> otherwise.</value> bool IsVaapiDeviceAmd { get; } /// <summary> - /// Whether the configured Vaapi device is from Intel(iHD driver). + /// Gets a value indicating whether the configured Vaapi device is from Intel(iHD driver). /// </summary> /// <value><c>true</c> if the Vaapi device is an Intel(iHD driver) GPU, <c>false</c> otherwise.</value> bool IsVaapiDeviceInteliHD { get; } /// <summary> - /// Whether the configured Vaapi device is from Intel(legacy i965 driver). + /// Gets a value indicating whether the configured Vaapi device is from Intel(legacy i965 driver). /// </summary> /// <value><c>true</c> if the Vaapi device is an Intel(legacy i965 driver) GPU, <c>false</c> otherwise.</value> bool IsVaapiDeviceInteli965 { get; } diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs index 933f440ac..8b2837ee3 100644 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.Controller.MediaEncoding break; } - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); + await target.WriteAsync(bytes).ConfigureAwait(false); // Check again, the stream could have been closed if (!target.CanWrite) diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index a084f9196..837bf0bb2 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -161,17 +161,17 @@ namespace MediaBrowser.Controller.Persistence int GetCount(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query); - QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query); + QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query); List<string> GetMusicGenreNames(); diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 2085ae4ad..58a0fa2a9 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Providers { // Images aren't always used so the allocation is a waste a lot of the time private List<LocalImageInfo> _images; - private List<(string url, ImageType type)> _remoteImages; + private List<(string Url, ImageType Type)> _remoteImages; public MetadataResult() { @@ -27,9 +27,9 @@ namespace MediaBrowser.Controller.Providers set => _images = value; } - public List<(string url, ImageType type)> RemoteImages + public List<(string Url, ImageType Type)> RemoteImages { - get => _remoteImages ??= new List<(string url, ImageType type)>(); + get => _remoteImages ??= new List<(string Url, ImageType Type)>(); set => _remoteImages = value; } diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index 9ebc0d0cf..3fd4cd731 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.MediaEncoding.Attachments } /// <inheritdoc /> - public async Task<(MediaAttachment attachment, Stream stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken) + public async Task<(MediaAttachment Attachment, Stream Stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken) { if (item == null) { diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index fce71bf1a..e1643ea43 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -91,9 +91,13 @@ namespace MediaBrowser.MediaEncoding.Encoder /// <inheritdoc /> public string EncoderPath => _ffmpegPath; + public Version EncoderVersion => _ffmpegVersion; + public bool IsVaapiDeviceAmd => _isVaapiDeviceAmd; + public bool IsVaapiDeviceInteliHD => _isVaapiDeviceInteliHD; + public bool IsVaapiDeviceInteli965 => _isVaapiDeviceInteli965; /// <summary> diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 89365a516..5b1ec8041 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -139,28 +139,28 @@ namespace MediaBrowser.MediaEncoding.Subtitles var subtitle = await GetSubtitleStream(mediaSource, subtitleStream, cancellationToken) .ConfigureAwait(false); - var inputFormat = subtitle.format; + var inputFormat = subtitle.Format; // Return the original if we don't have any way of converting it if (!TryGetWriter(outputFormat, out var writer)) { - return subtitle.stream; + return subtitle.Stream; } // Return the original if the same format is being requested // Character encoding was already handled in GetSubtitleStream if (string.Equals(inputFormat, outputFormat, StringComparison.OrdinalIgnoreCase)) { - return subtitle.stream; + return subtitle.Stream; } - using (var stream = subtitle.stream) + using (var stream = subtitle.Stream) { return ConvertSubtitles(stream, inputFormat, outputFormat, startTimeTicks, endTimeTicks, preserveOriginalTimestamps, cancellationToken); } } - private async Task<(Stream stream, string format)> GetSubtitleStream( + private async Task<(Stream Stream, string Format)> GetSubtitleStream( MediaSourceInfo mediaSource, MediaStream subtitleStream, CancellationToken cancellationToken) diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a19017215..84a6f6abe 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -289,8 +289,8 @@ namespace MediaBrowser.Model.Dlna var directPlayInfo = GetAudioDirectPlayMethods(item, audioStream, options); - var directPlayMethods = directPlayInfo.Item1; - var transcodeReasons = directPlayInfo.Item2.ToList(); + var directPlayMethods = directPlayInfo.PlayMethods; + var transcodeReasons = directPlayInfo.TranscodeReasons.ToList(); int? inputAudioChannels = audioStream?.Channels; int? inputAudioBitrate = audioStream?.BitDepth; @@ -448,7 +448,7 @@ namespace MediaBrowser.Model.Dlna return options.GetMaxBitrate(isAudio); } - private (IEnumerable<PlayMethod>, IEnumerable<TranscodeReason>) GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options) + private (IEnumerable<PlayMethod> PlayMethods, IEnumerable<TranscodeReason> TranscodeReasons) GetAudioDirectPlayMethods(MediaSourceInfo item, MediaStream audioStream, AudioOptions options) { DirectPlayProfile directPlayProfile = options.Profile.DirectPlayProfiles .FirstOrDefault(x => x.Type == DlnaProfileType.Audio && IsAudioDirectPlaySupported(x, item, audioStream)); @@ -679,8 +679,8 @@ namespace MediaBrowser.Model.Dlna // TODO: This doesn't account for situations where the device is able to handle the media's bitrate, but the connection isn't fast enough var directPlayEligibilityResult = IsEligibleForDirectPlay(item, GetBitrateForDirectPlayCheck(item, options, true) ?? 0, subtitleStream, audioStream, options, PlayMethod.DirectPlay); var directStreamEligibilityResult = IsEligibleForDirectPlay(item, options.GetMaxBitrate(false) ?? 0, subtitleStream, audioStream, options, PlayMethod.DirectStream); - bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayEligibilityResult.directPlay); - bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directStreamEligibilityResult.directPlay); + bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayEligibilityResult.DirectPlay); + bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directStreamEligibilityResult.DirectPlay); _logger.LogDebug( "Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}", @@ -695,7 +695,7 @@ namespace MediaBrowser.Model.Dlna { // See if it can be direct played var directPlayInfo = GetVideoDirectPlayProfile(options, item, videoStream, audioStream, isEligibleForDirectStream); - var directPlay = directPlayInfo.playMethod; + var directPlay = directPlayInfo.PlayMethod; if (directPlay != null) { @@ -713,17 +713,17 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } - transcodeReasons.AddRange(directPlayInfo.transcodeReasons); + transcodeReasons.AddRange(directPlayInfo.TranscodeReasons); } - if (directPlayEligibilityResult.reason.HasValue) + if (directPlayEligibilityResult.Reason.HasValue) { - transcodeReasons.Add(directPlayEligibilityResult.reason.Value); + transcodeReasons.Add(directPlayEligibilityResult.Reason.Value); } - if (directStreamEligibilityResult.reason.HasValue) + if (directStreamEligibilityResult.Reason.HasValue) { - transcodeReasons.Add(directStreamEligibilityResult.reason.Value); + transcodeReasons.Add(directStreamEligibilityResult.Reason.Value); } // Can't direct play, find the transcoding profile @@ -1000,7 +1000,7 @@ namespace MediaBrowser.Model.Dlna return 7168000; } - private (PlayMethod? playMethod, List<TranscodeReason> transcodeReasons) GetVideoDirectPlayProfile( + private (PlayMethod? PlayMethod, List<TranscodeReason> TranscodeReasons) GetVideoDirectPlayProfile( VideoOptions options, MediaSourceInfo mediaSource, MediaStream videoStream, @@ -1209,7 +1209,7 @@ namespace MediaBrowser.Model.Dlna mediaSource.Path ?? "Unknown path"); } - private (bool directPlay, TranscodeReason? reason) IsEligibleForDirectPlay( + private (bool DirectPlay, TranscodeReason? Reason) IsEligibleForDirectPlay( MediaSourceInfo item, long maxBitrate, MediaStream subtitleStream, diff --git a/MediaBrowser.Model/Session/GeneralCommandType.cs b/MediaBrowser.Model/Session/GeneralCommandType.cs index c58fa9a6b..166a6b441 100644 --- a/MediaBrowser.Model/Session/GeneralCommandType.cs +++ b/MediaBrowser.Model/Session/GeneralCommandType.cs @@ -39,7 +39,6 @@ namespace MediaBrowser.Model.Session SetRepeatMode = 29, ChannelUp = 30, ChannelDown = 31, - SetMaxStreamingBitrate = 31, Guide = 32, ToggleStats = 33, PlayMediaSource = 34, @@ -48,6 +47,7 @@ namespace MediaBrowser.Model.Session PlayState = 37, PlayNext = 38, ToggleOsdMenu = 39, - Play = 40 + Play = 40, + SetMaxStreamingBitrate = 41 } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 0af76f75a..94045b38b 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -682,12 +682,12 @@ namespace MediaBrowser.Providers.Manager { try { - await ProviderManager.SaveImage(item, remoteImage.url, remoteImage.type, null, cancellationToken).ConfigureAwait(false); + await ProviderManager.SaveImage(item, remoteImage.Url, remoteImage.Type, null, cancellationToken).ConfigureAwait(false); refreshResult.UpdateType |= ItemUpdateType.ImageUpdate; } catch (HttpRequestException ex) { - Logger.LogError(ex, "Could not save {ImageType} image: {Url}", Enum.GetName(remoteImage.type), remoteImage.url); + Logger.LogError(ex, "Could not save {ImageType} image: {Url}", Enum.GetName(remoteImage.Type), remoteImage.Url); } } diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs index 8a32cb07c..5ae5ff3be 100644 --- a/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs @@ -303,7 +303,7 @@ namespace MediaBrowser.Providers.Music return ReleaseResult.Parse(reader).FirstOrDefault(); } - private static (string, string) ParseArtistCredit(XmlReader reader) + private static (string Name, string ArtistId) ParseArtistCredit(XmlReader reader) { reader.MoveToContent(); reader.Read(); @@ -345,7 +345,7 @@ namespace MediaBrowser.Providers.Music return default; } - private static (string, string) ParseArtistNameCredit(XmlReader reader) + private static (string Name, string ArtistId) ParseArtistNameCredit(XmlReader reader) { reader.MoveToContent(); reader.Read(); @@ -388,7 +388,7 @@ namespace MediaBrowser.Providers.Music return (null, null); } - private static (string name, string id) ParseArtistArtistCredit(XmlReader reader, string artistId) + private static (string Name, string ArtistId) ParseArtistArtistCredit(XmlReader reader, string artistId) { reader.MoveToContent(); reader.Read(); @@ -628,7 +628,7 @@ namespace MediaBrowser.Providers.Music public string Overview; public int? Year; - public List<ValueTuple<string, string>> Artists = new List<ValueTuple<string, string>>(); + public List<(string, string)> Artists = new(); public static IEnumerable<ReleaseResult> Parse(XmlReader reader) { @@ -776,7 +776,7 @@ namespace MediaBrowser.Providers.Music using var subReader = reader.ReadSubtree(); var artist = ParseArtistCredit(subReader); - if (!string.IsNullOrEmpty(artist.Item1)) + if (!string.IsNullOrEmpty(artist.Name)) { result.Artists.Add(artist); } diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index bcf9a8366..007101868 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -872,7 +872,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers else { // only allow one item of each type - if (itemResult.RemoteImages.Any(x => x.type == imageType)) + if (itemResult.RemoteImages.Any(x => x.Type == imageType)) { return; } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 7ea45d14d..7c9952030 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using Jellyfin.Data.Entities; @@ -157,33 +158,33 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers // Images Assert.Equal(7, result.RemoteImages.Count); - var posters = result.RemoteImages.Where(x => x.type == ImageType.Primary).ToList(); + var posters = result.RemoteImages.Where(x => x.Type == ImageType.Primary).ToList(); Assert.Single(posters); - Assert.Equal("http://image.tmdb.org/t/p/original/9rtrRGeRnL0JKtu9IMBWsmlmmZz.jpg", posters[0].url); + Assert.Equal("http://image.tmdb.org/t/p/original/9rtrRGeRnL0JKtu9IMBWsmlmmZz.jpg", posters[0].Url); - var logos = result.RemoteImages.Where(x => x.type == ImageType.Logo).ToList(); + var logos = result.RemoteImages.Where(x => x.Type == ImageType.Logo).ToList(); Assert.Single(logos); - Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5865bf95cbadb.png", logos[0].url); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/hdmovielogo/justice-league-5865bf95cbadb.png", logos[0].Url); - var banners = result.RemoteImages.Where(x => x.type == ImageType.Banner).ToList(); + var banners = result.RemoteImages.Where(x => x.Type == ImageType.Banner).ToList(); Assert.Single(banners); - Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebanner/justice-league-586017e95adbd.jpg", banners[0].url); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebanner/justice-league-586017e95adbd.jpg", banners[0].Url); - var thumbs = result.RemoteImages.Where(x => x.type == ImageType.Thumb).ToList(); + var thumbs = result.RemoteImages.Where(x => x.Type == ImageType.Thumb).ToList(); Assert.Single(thumbs); - Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviethumb/justice-league-585fb155c3743.jpg", thumbs[0].url); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviethumb/justice-league-585fb155c3743.jpg", thumbs[0].Url); - var art = result.RemoteImages.Where(x => x.type == ImageType.Art).ToList(); + var art = result.RemoteImages.Where(x => x.Type == ImageType.Art).ToList(); Assert.Single(art); - Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/hdmovieclearart/justice-league-5865c23193041.png", art[0].url); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/hdmovieclearart/justice-league-5865c23193041.png", art[0].Url); - var discArt = result.RemoteImages.Where(x => x.type == ImageType.Disc).ToList(); + var discArt = result.RemoteImages.Where(x => x.Type == ImageType.Disc).ToList(); Assert.Single(discArt); - Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-5a3af26360617.png", discArt[0].url); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviedisc/justice-league-5a3af26360617.png", discArt[0].Url); - var backdrop = result.RemoteImages.Where(x => x.type == ImageType.Backdrop).ToList(); + var backdrop = result.RemoteImages.Where(x => x.Type == ImageType.Backdrop).ToList(); Assert.Single(backdrop); - Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5793f518c6d6e.jpg", backdrop[0].url); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5793f518c6d6e.jpg", backdrop[0].Url); // Local Image - contains only one item depending on operating system Assert.Single(result.Images); @@ -216,8 +217,8 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _parser.Fetch(result, "Test Data/Fanart.nfo", CancellationToken.None); - Assert.Single(result.RemoteImages.Where(x => x.type == ImageType.Backdrop)); - Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a5332c7b5e77.jpg", result.RemoteImages.First(x => x.type == ImageType.Backdrop).url); + Assert.Single(result.RemoteImages.Where(x => x.Type == ImageType.Backdrop)); + Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a5332c7b5e77.jpg", result.RemoteImages.First(x => x.Type == ImageType.Backdrop).Url); } [Fact] -- cgit v1.2.3