diff options
Diffstat (limited to 'Emby.Server.Implementations/Library/Resolvers')
18 files changed, 596 insertions, 542 deletions
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs index e39192d28..fd9747b4b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs @@ -1,3 +1,7 @@ +#nullable disable + +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.IO; @@ -13,24 +17,25 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers.Audio { /// <summary> - /// Class AudioResolver + /// Class AudioResolver. /// </summary> public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver { - private readonly ILibraryManager LibraryManager; + private readonly ILibraryManager _libraryManager; public AudioResolver(ILibraryManager libraryManager) { - LibraryManager = libraryManager; + _libraryManager = libraryManager; } /// <summary> /// Gets the priority. /// </summary> /// <value>The priority.</value> - public override ResolverPriority Priority => ResolverPriority.Fourth; + public override ResolverPriority Priority => ResolverPriority.Fifth; - public MultiItemResolverResult ResolveMultiple(Folder parent, + public MultiItemResolverResult ResolveMultiple( + Folder parent, List<FileSystemMetadata> files, string collectionType, IDirectoryService directoryService) @@ -48,7 +53,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio return result; } - private MultiItemResolverResult ResolveMultipleInternal(Folder parent, + private MultiItemResolverResult ResolveMultipleInternal( + Folder parent, List<FileSystemMetadata> files, string collectionType, IDirectoryService directoryService) @@ -70,7 +76,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio { // Return audio if the path is a file and has a matching extension - var libraryOptions = args.GetLibraryOptions(); var collectionType = args.GetCollectionType(); var isBooksCollectionType = string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase); @@ -83,13 +88,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio } var files = args.FileSystemChildren - .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .Where(i => !_libraryManager.IgnoreFile(i, args.Parent)) .ToList(); return FindAudio<AudioBook>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); } - if (LibraryManager.IsAudioFile(args.Path, libraryOptions)) + if (_libraryManager.IsAudioFile(args.Path)) { var extension = Path.GetExtension(args.Path); @@ -102,7 +107,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio var isMixedCollectionType = string.IsNullOrEmpty(collectionType); // For conflicting extensions, give priority to videos - if (isMixedCollectionType && LibraryManager.IsVideoFile(args.Path, libraryOptions)) + if (isMixedCollectionType && _libraryManager.IsVideoFile(args.Path)) { return null; } @@ -118,7 +123,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio { item = new MediaBrowser.Controller.Entities.Audio.Audio(); } - else if (isBooksCollectionType) { item = new AudioBook(); @@ -178,7 +182,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio } } - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); + var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); var resolver = new AudioBookListResolver(namingOptions); var resolverResult = resolver.Resolve(files).ToList(); @@ -199,7 +203,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio continue; } - var firstMedia = resolvedItem.Files.First(); + if (resolvedItem.Files.Count == 0) + { + continue; + } + + var firstMedia = resolvedItem.Files[0]; var libraryItem = new T { @@ -209,8 +218,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio Name = parseName ? resolvedItem.Name : Path.GetFileNameWithoutExtension(firstMedia.Path), - //AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(), - //LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray() + // AdditionalParts = resolvedItem.Files.Skip(1).Select(i => i.Path).ToArray(), + // LocalAlternateVersions = resolvedItem.AlternateVersions.Select(i => i.Path).ToArray() }; result.Items.Add(libraryItem); diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs index 3ce1da81a..60720dd2f 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs @@ -1,11 +1,15 @@ +#nullable disable + using System; using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; using Emby.Naming.Audio; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; @@ -13,15 +17,21 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library.Resolvers.Audio { /// <summary> - /// Class MusicAlbumResolver + /// Class MusicAlbumResolver. /// </summary> public class MusicAlbumResolver : ItemResolver<MusicAlbum> { - private readonly ILogger _logger; + private readonly ILogger<MusicAlbumResolver> _logger; private readonly IFileSystem _fileSystem; private readonly ILibraryManager _libraryManager; - public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager) + /// <summary> + /// Initializes a new instance of the <see cref="MusicAlbumResolver"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + /// <param name="fileSystem">The file system.</param> + /// <param name="libraryManager">The library manager.</param> + public MusicAlbumResolver(ILogger<MusicAlbumResolver> logger, IFileSystem fileSystem, ILibraryManager libraryManager) { _logger = logger; _fileSystem = fileSystem; @@ -32,7 +42,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio /// Gets the priority. /// </summary> /// <value>The priority.</value> - public override ResolverPriority Priority => ResolverPriority.Second; + public override ResolverPriority Priority => ResolverPriority.Third; /// <summary> /// Resolves the specified args. @@ -50,26 +60,38 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio return null; } - if (!args.IsDirectory) return null; + if (!args.IsDirectory) + { + return null; + } // Avoid mis-identifying top folders - if (args.HasParent<MusicAlbum>()) return null; - if (args.Parent.IsRoot) return null; + if (args.HasParent<MusicAlbum>()) + { + return null; + } + + if (args.Parent.IsRoot) + { + return null; + } return IsMusicAlbum(args) ? new MusicAlbum() : null; } - /// <summary> - /// Determine if the supplied file data points to a music album + /// Determine if the supplied file data points to a music album. /// </summary> - public bool IsMusicAlbum(string path, IDirectoryService directoryService, LibraryOptions libraryOptions) + /// <param name="path">The path to check.</param> + /// <param name="directoryService">The directory service.</param> + /// <returns><c>true</c> if the provided path points to a music album, <c>false</c> otherwise.</returns> + public bool IsMusicAlbum(string path, IDirectoryService directoryService) { - return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, libraryOptions, _libraryManager); + return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, _libraryManager); } /// <summary> - /// Determine if the supplied resolve args should be considered a music album + /// Determine if the supplied resolve args should be considered a music album. /// </summary> /// <param name="args">The args.</param> /// <returns><c>true</c> if [is music album] [the specified args]; otherwise, <c>false</c>.</returns> @@ -78,83 +100,74 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio // Args points to an album if parent is an Artist folder or it directly contains music if (args.IsDirectory) { - //if (args.Parent is MusicArtist) return true; //saves us from testing children twice - if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager)) return true; + // if (args.Parent is MusicArtist) return true; // saves us from testing children twice + if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, _libraryManager)) + { + return true; + } } return false; } /// <summary> - /// Determine if the supplied list contains what we should consider music + /// Determine if the supplied list contains what we should consider music. /// </summary> - private bool ContainsMusic(IEnumerable<FileSystemMetadata> list, + private bool ContainsMusic( + IEnumerable<FileSystemMetadata> list, bool allowSubfolders, IDirectoryService directoryService, - ILogger logger, + ILogger<MusicAlbumResolver> logger, IFileSystem fileSystem, - LibraryOptions libraryOptions, ILibraryManager libraryManager) { + // check for audio files before digging down into directories + var foundAudioFile = list.Any(fileSystemInfo => !fileSystemInfo.IsDirectory && libraryManager.IsAudioFile(fileSystemInfo.FullName)); + if (foundAudioFile) + { + // at least one audio file exists + return true; + } + + if (!allowSubfolders) + { + // not music since no audio file exists and we're not looking into subfolders + return false; + } + var discSubfolderCount = 0; - var notMultiDisc = false; - foreach (var fileSystemInfo in list) + var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); + var parser = new AlbumParser(namingOptions); + + var directories = list.Where(fileSystemInfo => fileSystemInfo.IsDirectory); + + var result = Parallel.ForEach(directories, (fileSystemInfo, state) => { - if (fileSystemInfo.IsDirectory) + var path = fileSystemInfo.FullName; + var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager); + + if (hasMusic) { - if (allowSubfolders) + if (parser.IsMultiPart(path)) { - if (notMultiDisc) - { - continue; - } - - var path = fileSystemInfo.FullName; - var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryOptions, libraryManager); - - if (hasMusic) - { - if (IsMultiDiscFolder(path, libraryOptions)) - { - logger.LogDebug("Found multi-disc folder: " + path); - discSubfolderCount++; - } - else - { - // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album - notMultiDisc = true; - } - } + logger.LogDebug("Found multi-disc folder: " + path); + Interlocked.Increment(ref discSubfolderCount); } - } - else - { - var fullName = fileSystemInfo.FullName; - - if (libraryManager.IsAudioFile(fullName, libraryOptions)) + else { - return true; + // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album + state.Stop(); } } - } + }); - if (notMultiDisc) + if (!result.IsCompleted) { return false; } return discSubfolderCount > 0; } - - private bool IsMultiDiscFolder(string path, LibraryOptions libraryOptions) - { - var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); - - var parser = new AlbumParser(namingOptions); - var result = parser.ParseMultiPart(path); - - return result.IsMultiPart; - } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs index 74e9b8304..3d2ae95d2 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs @@ -1,5 +1,8 @@ +#nullable disable + using System; using System.Linq; +using System.Threading.Tasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; @@ -11,16 +14,27 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library.Resolvers.Audio { /// <summary> - /// Class MusicArtistResolver + /// Class MusicArtistResolver. /// </summary> public class MusicArtistResolver : ItemResolver<MusicArtist> { - private readonly ILogger _logger; + private readonly ILogger<MusicAlbumResolver> _logger; private readonly IFileSystem _fileSystem; private readonly ILibraryManager _libraryManager; private readonly IServerConfigurationManager _config; - public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager, IServerConfigurationManager config) + /// <summary> + /// Initializes a new instance of the <see cref="MusicArtistResolver"/> class. + /// </summary> + /// <param name="logger">The logger for the created <see cref="MusicAlbumResolver"/> instances.</param> + /// <param name="fileSystem">The file system.</param> + /// <param name="libraryManager">The library manager.</param> + /// <param name="config">The configuration manager.</param> + public MusicArtistResolver( + ILogger<MusicAlbumResolver> logger, + IFileSystem fileSystem, + ILibraryManager libraryManager, + IServerConfigurationManager config) { _logger = logger; _fileSystem = fileSystem; @@ -41,7 +55,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio /// <returns>MusicArtist.</returns> protected override MusicArtist Resolve(ItemResolveArgs args) { - if (!args.IsDirectory) return null; + if (!args.IsDirectory) + { + return null; + } // Don't allow nested artists if (args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>()) @@ -64,21 +81,29 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio return new MusicArtist(); } - if (_config.Configuration.EnableSimpleArtistDetection) + // Avoid mis-identifying top folders + if (args.Parent.IsRoot) { return null; } - // Avoid mis-identifying top folders - if (args.Parent.IsRoot) return null; - var directoryService = args.DirectoryService; var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager); // If we contain an album assume we are an artist folder - return args.FileSystemChildren.Where(i => i.IsDirectory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService, args.GetLibraryOptions())) ? new MusicArtist() : null; - } + var directories = args.FileSystemChildren.Where(i => i.IsDirectory); + var result = Parallel.ForEach(directories, (fileSystemInfo, state) => + { + if (albumResolver.IsMusicAlbum(fileSystemInfo.FullName, directoryService)) + { + // stop once we see a music album + state.Stop(); + } + }); + + return !result.IsCompleted ? new MusicArtist() : null; + } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index 541b13cbe..9ff99fa43 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -1,6 +1,11 @@ +#nullable disable + +#pragma warning disable CS1591 + using System; using System.IO; using System.Linq; +using DiscUtils.Udf; using Emby.Naming.Video; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -10,25 +15,25 @@ using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Resolvers { /// <summary> - /// Resolves a Path into a Video or Video subclass + /// Resolves a Path into a Video or Video subclass. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">The type of item to resolve.</typeparam> public abstract class BaseVideoResolver<T> : MediaBrowser.Controller.Resolvers.ItemResolver<T> where T : Video, new() { - protected readonly ILibraryManager LibraryManager; - protected BaseVideoResolver(ILibraryManager libraryManager) { LibraryManager = libraryManager; } + protected ILibraryManager LibraryManager { get; } + /// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>`0.</returns> - protected override T Resolve(ItemResolveArgs args) + public override T Resolve(ItemResolveArgs args) { return ResolveVideo<T>(args, false); } @@ -40,14 +45,12 @@ namespace Emby.Server.Implementations.Library.Resolvers /// <param name="args">The args.</param> /// <param name="parseName">if set to <c>true</c> [parse name].</param> /// <returns>``0.</returns> - protected TVideoType ResolveVideo<TVideoType>(ItemResolveArgs args, bool parseName) + protected virtual TVideoType ResolveVideo<TVideoType>(ItemResolveArgs args, bool parseName) where TVideoType : Video, new() { - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); + var namingOptions = LibraryManager.GetNamingOptions(); // If the path is a file check for a matching extensions - var parser = new VideoResolver(namingOptions); - if (args.IsDirectory) { TVideoType video = null; @@ -62,7 +65,7 @@ namespace Emby.Server.Implementations.Library.Resolvers { if (IsDvdDirectory(child.FullName, filename, args.DirectoryService)) { - videoInfo = parser.ResolveDirectory(args.Path); + videoInfo = VideoResolver.ResolveDirectory(args.Path, namingOptions); if (videoInfo == null) { @@ -77,9 +80,10 @@ namespace Emby.Server.Implementations.Library.Resolvers }; break; } - if (IsBluRayDirectory(child.FullName, filename, args.DirectoryService)) + + if (IsBluRayDirectory(filename)) { - videoInfo = parser.ResolveDirectory(args.Path); + videoInfo = VideoResolver.ResolveDirectory(args.Path, namingOptions); if (videoInfo == null) { @@ -97,7 +101,7 @@ namespace Emby.Server.Implementations.Library.Resolvers } else if (IsDvdFile(filename)) { - videoInfo = parser.ResolveDirectory(args.Path); + videoInfo = VideoResolver.ResolveDirectory(args.Path, namingOptions); if (videoInfo == null) { @@ -127,14 +131,14 @@ namespace Emby.Server.Implementations.Library.Resolvers } else { - var videoInfo = parser.Resolve(args.Path, false, false); + var videoInfo = VideoResolver.Resolve(args.Path, false, namingOptions, false); if (videoInfo == null) { return null; } - if (LibraryManager.IsVideoFile(args.Path, args.GetLibraryOptions()) || videoInfo.IsStub) + if (LibraryManager.IsVideoFile(args.Path) || videoInfo.IsStub) { var path = args.Path; @@ -162,13 +166,13 @@ namespace Emby.Server.Implementations.Library.Resolvers protected void SetVideoType(Video video, VideoFileInfo videoInfo) { - var extension = Path.GetExtension(video.Path); - video.VideoType = string.Equals(extension, ".iso", StringComparison.OrdinalIgnoreCase) || - string.Equals(extension, ".img", StringComparison.OrdinalIgnoreCase) ? - VideoType.Iso : - VideoType.VideoFile; + var extension = Path.GetExtension(video.Path.AsSpan()); + video.VideoType = extension.Equals(".iso", StringComparison.OrdinalIgnoreCase) + || extension.Equals(".img", StringComparison.OrdinalIgnoreCase) + ? VideoType.Iso + : VideoType.VideoFile; - video.IsShortcut = string.Equals(extension, ".strm", StringComparison.OrdinalIgnoreCase); + video.IsShortcut = extension.Equals(".strm", StringComparison.OrdinalIgnoreCase); video.IsPlaceHolder = videoInfo.IsStub; if (videoInfo.IsStub) @@ -190,14 +194,30 @@ namespace Emby.Server.Implementations.Library.Resolvers { if (video.VideoType == VideoType.Iso) { - if (video.Path.IndexOf("dvd", StringComparison.OrdinalIgnoreCase) != -1) + if (video.Path.Contains("dvd", StringComparison.OrdinalIgnoreCase)) { video.IsoType = IsoType.Dvd; } - else if (video.Path.IndexOf("bluray", StringComparison.OrdinalIgnoreCase) != -1) + else if (video.Path.Contains("bluray", StringComparison.OrdinalIgnoreCase)) { video.IsoType = IsoType.BluRay; } + else + { + // use disc-utils, both DVDs and BDs use UDF filesystem + using (var videoFileStream = File.Open(video.Path, FileMode.Open, FileAccess.Read)) + { + UdfReader udfReader = new UdfReader(videoFileStream); + if (udfReader.DirectoryExists("VIDEO_TS")) + { + video.IsoType = IsoType.Dvd; + } + else if (udfReader.DirectoryExists("BDMV")) + { + video.IsoType = IsoType.BluRay; + } + } + } } } @@ -247,10 +267,7 @@ namespace Emby.Server.Implementations.Library.Resolvers protected void Set3DFormat(Video video) { - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - - var resolver = new Format3DParser(namingOptions); - var result = resolver.Parse(video.Path); + var result = Format3DParser.Parse(video.Path, LibraryManager.GetNamingOptions()); Set3DFormat(video, result.Is3D, result.Format3D); } @@ -258,6 +275,10 @@ namespace Emby.Server.Implementations.Library.Resolvers /// <summary> /// Determines whether [is DVD directory] [the specified directory name]. /// </summary> + /// <param name="fullPath">The full path of the directory.</param> + /// <param name="directoryName">The name of the directory.</param> + /// <param name="directoryService">The directory service.</param> + /// <returns><c>true</c> if the provided directory is a DVD directory, <c>false</c> otherwise.</returns> protected bool IsDvdDirectory(string fullPath, string directoryName, IDirectoryService directoryService) { if (!string.Equals(directoryName, "video_ts", StringComparison.OrdinalIgnoreCase)) @@ -279,25 +300,13 @@ namespace Emby.Server.Implementations.Library.Resolvers } /// <summary> - /// Determines whether [is blu ray directory] [the specified directory name]. + /// Determines whether [is bluray directory] [the specified directory name]. /// </summary> - protected bool IsBluRayDirectory(string fullPath, string directoryName, IDirectoryService directoryService) + /// <param name="directoryName">The directory name.</param> + /// <returns>Whether the directory is a bluray directory.</returns> + protected bool IsBluRayDirectory(string directoryName) { - if (!string.Equals(directoryName, "bdmv", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - return true; - //var blurayExtensions = new[] - //{ - // ".mts", - // ".m2ts", - // ".bdmv", - // ".mpls" - //}; - - //return directoryService.GetFiles(fullPath).Any(i => blurayExtensions.Contains(i.Extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)); + return string.Equals(directoryName, "bdmv", StringComparison.OrdinalIgnoreCase); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs index f22554ee5..e685c87f1 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs @@ -1,3 +1,7 @@ +#nullable disable + +#pragma warning disable CS1591 + using System; using System.IO; using System.Linq; @@ -7,25 +11,19 @@ using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Resolvers.Books { - /// <summary> - /// - /// </summary> public class BookResolver : MediaBrowser.Controller.Resolvers.ItemResolver<Book> { - private readonly string[] _validExtensions = { ".pdf", ".epub", ".mobi", ".cbr", ".cbz", ".azw3" }; + private readonly string[] _validExtensions = { ".azw", ".azw3", ".cb7", ".cbr", ".cbt", ".cbz", ".epub", ".mobi", ".pdf" }; - /// <summary> - /// - /// </summary> - /// <param name="args"></param> - /// <returns></returns> - protected override Book Resolve(ItemResolveArgs args) + public override Book Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); // Only process items that are in a collection folder containing books if (!string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase)) + { return null; + } if (args.IsDirectory) { @@ -47,26 +45,23 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books return null; } - /// <summary> - /// - /// </summary> - /// <param name="args"></param> - /// <returns></returns> private Book GetBook(ItemResolveArgs args) { var bookFiles = args.FileSystemChildren.Where(f => { - var fileExtension = Path.GetExtension(f.FullName) ?? - string.Empty; + var fileExtension = Path.GetExtension(f.FullName) + ?? string.Empty; - return _validExtensions.Contains(fileExtension, - StringComparer - .OrdinalIgnoreCase); + return _validExtensions.Contains( + fileExtension, + StringComparer.OrdinalIgnoreCase); }).ToList(); // Don't return a Book if there is more (or less) than one document in the directory if (bookFiles.Count != 1) + { return null; + } return new Book { diff --git a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs index e48b6c967..db7703cd6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; @@ -5,9 +7,9 @@ using MediaBrowser.Controller.Resolvers; namespace Emby.Server.Implementations.Library.Resolvers { /// <summary> - /// Class FolderResolver + /// Class FolderResolver. /// </summary> - public class FolderResolver : FolderResolver<Folder> + public class FolderResolver : GenericFolderResolver<Folder> { /// <summary> /// Gets the priority. @@ -30,24 +32,4 @@ namespace Emby.Server.Implementations.Library.Resolvers return null; } } - - /// <summary> - /// Class FolderResolver - /// </summary> - /// <typeparam name="TItemType">The type of the T item type.</typeparam> - public abstract class FolderResolver<TItemType> : ItemResolver<TItemType> - where TItemType : Folder, new() - { - /// <summary> - /// Sets the initial item values. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="args">The args.</param> - protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args) - { - base.SetInitialItemValues(item, args); - - item.IsRoot = args.Parent == null; - } - } } diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs new file mode 100644 index 000000000..f109a5e9a --- /dev/null +++ b/Emby.Server.Implementations/Library/Resolvers/GenericFolderResolver.cs @@ -0,0 +1,27 @@ +#nullable disable + +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; + +namespace Emby.Server.Implementations.Library.Resolvers +{ + /// <summary> + /// Class FolderResolver. + /// </summary> + /// <typeparam name="TItemType">The type of the T item type.</typeparam> + public abstract class GenericFolderResolver<TItemType> : ItemResolver<TItemType> + where TItemType : Folder, new() + { + /// <summary> + /// Sets the initial item values. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="args">The args.</param> + protected override void SetInitialItemValues(TItemType item, ItemResolveArgs args) + { + base.SetInitialItemValues(item, args); + + item.IsRoot = args.Parent == null; + } + } +} diff --git a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs index 68d5d8b2d..9599faea4 100644 --- a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs @@ -1,3 +1,7 @@ +#nullable disable + +#pragma warning disable CS1591 + using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; diff --git a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs index a6db40714..3f29ab191 100644 --- a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; @@ -5,13 +7,19 @@ using MediaBrowser.Controller.Resolvers; namespace Emby.Server.Implementations.Library.Resolvers { /// <summary> - /// Class ItemResolver + /// Class ItemResolver. /// </summary> - /// <typeparam name="T"></typeparam> + /// <typeparam name="T">The type of BaseItem.</typeparam> public abstract class ItemResolver<T> : IItemResolver where T : BaseItem, new() { /// <summary> + /// Gets the priority. + /// </summary> + /// <value>The priority.</value> + public virtual ResolverPriority Priority => ResolverPriority.First; + + /// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> @@ -22,13 +30,7 @@ namespace Emby.Server.Implementations.Library.Resolvers } /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public virtual ResolverPriority Priority => ResolverPriority.First; - - /// <summary> - /// Sets initial values on the newly resolved item + /// Sets initial values on the newly resolved item. /// </summary> /// <param name="item">The item.</param> /// <param name="args">The args.</param> diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs index 922bd4bbb..e7abe1e6d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs @@ -1,17 +1,18 @@ +#nullable disable + using System; using System.IO; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; namespace Emby.Server.Implementations.Library.Resolvers.Movies { /// <summary> - /// Class BoxSetResolver + /// Class BoxSetResolver. /// </summary> - public class BoxSetResolver : FolderResolver<BoxSet> + public class BoxSetResolver : GenericFolderResolver<BoxSet> { /// <summary> /// Resolves the specified args. @@ -63,14 +64,14 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// <param name="item">The item.</param> private static void SetProviderIdFromPath(BaseItem item) { - //we need to only look at the name of this actual item (not parents) + // we need to only look at the name of this actual item (not parents) var justName = Path.GetFileName(item.Path); var id = justName.GetAttributeValue("tmdbid"); if (!string.IsNullOrEmpty(id)) { - item.SetProviderId(MetadataProviders.Tmdb, id); + item.SetProviderId(MetadataProvider.Tmdb, id); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 848563679..f3b6ef0a2 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -1,8 +1,12 @@ +#nullable disable + using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using Emby.Naming.Video; +using Jellyfin.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -11,23 +15,46 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers.Movies { /// <summary> - /// Class MovieResolver + /// Class MovieResolver. /// </summary> public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver { + private readonly IImageProcessor _imageProcessor; + + private string[] _validCollectionTypes = new[] + { + CollectionType.Movies, + CollectionType.HomeVideos, + CollectionType.MusicVideos, + CollectionType.Movies, + CollectionType.Photos + }; + + /// <summary> + /// Initializes a new instance of the <see cref="MovieResolver"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + /// <param name="imageProcessor">The image processor.</param> + public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor) + : base(libraryManager) + { + _imageProcessor = imageProcessor; + } + /// <summary> /// Gets the priority. /// </summary> /// <value>The priority.</value> - public override ResolverPriority Priority => ResolverPriority.Third; + public override ResolverPriority Priority => ResolverPriority.Fourth; - public MultiItemResolverResult ResolveMultiple(Folder parent, + /// <inheritdoc /> + public MultiItemResolverResult ResolveMultiple( + Folder parent, List<FileSystemMetadata> files, string collectionType, IDirectoryService directoryService) @@ -45,7 +72,112 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return result; } - private MultiItemResolverResult ResolveMultipleInternal(Folder parent, + /// <summary> + /// Resolves the specified args. + /// </summary> + /// <param name="args">The args.</param> + /// <returns>Video.</returns> + public override Video Resolve(ItemResolveArgs args) + { + var collectionType = args.GetCollectionType(); + + // Find movies with their own folders + if (args.IsDirectory) + { + if (IsInvalid(args.Parent, collectionType)) + { + return null; + } + + var files = args.FileSystemChildren + .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) + .ToList(); + + if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) + { + return 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); + } + + if (string.IsNullOrEmpty(collectionType)) + { + // Owned items will be caught by the plain video resolver + if (args.Parent == null) + { + // return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType); + return null; + } + + if (args.HasParent<Series>()) + { + return null; + } + + { + return 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); + } + + return null; + } + + // Handle owned items + if (args.Parent == null) + { + return base.Resolve(args); + } + + if (IsInvalid(args.Parent, collectionType)) + { + return null; + } + + Video item = null; + + if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) + { + item = ResolveVideo<MusicVideo>(args, false); + } + + // To find a movie file, the collection type must be movies or boxsets + else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) + { + item = ResolveVideo<Movie>(args, true); + } + else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || + string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) + { + item = ResolveVideo<Video>(args, false); + } + else if (string.IsNullOrEmpty(collectionType)) + { + if (args.HasParent<Series>()) + { + return null; + } + + item = ResolveVideo<Video>(args, false); + } + + if (item != null) + { + item.IsInMixedFolder = true; + } + + return item; + } + + private MultiItemResolverResult ResolveMultipleInternal( + Folder parent, List<FileSystemMetadata> files, string collectionType, IDirectoryService directoryService) @@ -90,7 +222,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return null; } - private MultiItemResolverResult ResolveVideos<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType, bool parseName) + private MultiItemResolverResult ResolveVideos<T>( + Folder parent, + IEnumerable<FileSystemMetadata> fileSystemEntries, + IDirectoryService directoryService, + bool suppportMultiEditions, + string collectionType, + bool parseName) where T : Video, new() { var files = new List<FileSystemMetadata>(); @@ -103,8 +241,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies // This is a hack but currently no better way to resolve a sometimes ambiguous situation if (string.IsNullOrEmpty(collectionType)) { - if (string.Equals(child.Name, "tvshow.nfo", StringComparison.OrdinalIgnoreCase) || - string.Equals(child.Name, "season.nfo", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(child.Name, "tvshow.nfo", StringComparison.OrdinalIgnoreCase) + || string.Equals(child.Name, "season.nfo", StringComparison.OrdinalIgnoreCase)) { return null; } @@ -114,20 +252,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies { leftOver.Add(child); } - else if (IsIgnored(child.Name)) - { - - } - else + else if (!IsIgnored(child.Name)) { files.Add(child); } } - var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); + var namingOptions = LibraryManager.GetNamingOptions(); - var resolver = new VideoListResolver(namingOptions); - var resolverResult = resolver.Resolve(files, suppportMultiEditions).ToList(); + var resolverResult = VideoListResolver.Resolve(files, namingOptions, suppportMultiEditions).ToList(); var result = new MultiItemResolverResult { @@ -139,7 +272,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies foreach (var video in resolverResult) { - var firstVideo = video.Files.First(); + var firstVideo = video.Files[0]; var videoItem = new T { @@ -167,17 +300,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies private static bool IsIgnored(string filename) { // Ignore samples - var sampleFilename = " " + filename.Replace(".", " ", StringComparison.OrdinalIgnoreCase) - .Replace("-", " ", StringComparison.OrdinalIgnoreCase) - .Replace("_", " ", StringComparison.OrdinalIgnoreCase) - .Replace("!", " ", StringComparison.OrdinalIgnoreCase); - - if (sampleFilename.IndexOf(" sample ", StringComparison.OrdinalIgnoreCase) != -1) - { - return true; - } + Match m = Regex.Match(filename, @"\bsample\b", RegexOptions.IgnoreCase); - return false; + return m.Success; } private bool ContainsFile(List<VideoInfo> result, FileSystemMetadata file) @@ -198,111 +323,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>Video.</returns> - protected override Video Resolve(ItemResolveArgs args) - { - var collectionType = args.GetCollectionType(); - - // Find movies with their own folders - if (args.IsDirectory) - { - if (IsInvalid(args.Parent, collectionType)) - { - return null; - } - - var files = args.FileSystemChildren - .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) - .ToList(); - - if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) - { - return 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); - } - - if (string.IsNullOrEmpty(collectionType)) - { - // Owned items will be caught by the plain video resolver - if (args.Parent == null) - { - //return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType); - return null; - } - - if (args.HasParent<Series>()) - { - return null; - } - - { - return 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); - } - - return null; - } - - // Handle owned items - if (args.Parent == null) - { - return base.Resolve(args); - } - - if (IsInvalid(args.Parent, collectionType)) - { - return null; - } - - Video item = null; - - if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) - { - item = ResolveVideo<MusicVideo>(args, false); - } - - // To find a movie file, the collection type must be movies or boxsets - else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) - { - item = ResolveVideo<Movie>(args, true); - } - - else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || - string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) - { - item = ResolveVideo<Video>(args, false); - } - else if (string.IsNullOrEmpty(collectionType)) - { - if (args.HasParent<Series>()) - { - return null; - } - - item = ResolveVideo<Video>(args, false); - } - - if (item != null) - { - item.IsInMixedFolder = true; - } - - return item; - } - - /// <summary> /// Sets the initial item values. /// </summary> /// <param name="item">The item.</param> @@ -322,7 +342,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies { if (item is Movie || item is MusicVideo) { - //we need to only look at the name of this actual item (not parents) + // We need to only look at the name of this actual item (not parents) var justName = item.IsInMixedFolder ? Path.GetFileName(item.Path) : Path.GetFileName(item.ContainingFolderPath); if (!string.IsNullOrEmpty(justName)) @@ -332,7 +352,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (!string.IsNullOrWhiteSpace(tmdbid)) { - item.SetProviderId(MetadataProviders.Tmdb, tmdbid); + item.SetProviderId(MetadataProvider.Tmdb, tmdbid); } } @@ -343,23 +363,22 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies if (!string.IsNullOrWhiteSpace(imdbid)) { - item.SetProviderId(MetadataProviders.Imdb, imdbid); + item.SetProviderId(MetadataProvider.Imdb, imdbid); } } } } /// <summary> - /// Finds a movie based on a child file system entries + /// Finds a movie based on a child file system entries. /// </summary> - /// <typeparam name="T"></typeparam> /// <returns>Movie.</returns> private T FindMovie<T>(ItemResolveArgs args, string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName) where T : Video, new() { var multiDiscFolders = new List<FileSystemMetadata>(); - var libraryOptions = args.GetLibraryOptions(); + var libraryOptions = args.LibraryOptions; var supportPhotos = string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && libraryOptions.EnablePhotos; var photos = new List<FileSystemMetadata>(); @@ -380,7 +399,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies Set3DFormat(movie); return movie; } - if (IsBluRayDirectory(child.FullName, filename, directoryService)) + + if (IsBluRayDirectory(filename)) { var movie = new T { @@ -410,15 +430,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } // TODO: Allow GetMultiDiscMovie in here - const bool supportsMultiVersion = true; + const bool SupportsMultiVersion = true; - var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ?? + var result = ResolveVideos<T>(parent, fileSystemEntries, directoryService, SupportsMultiVersion, collectionType, parseName) ?? new MultiItemResolverResult(); if (result.Items.Count == 1) { var videoPath = result.Items[0].Path; - var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(LibraryManager, libraryOptions, videoPath, i.Name)); + var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(LibraryManager, videoPath, i.Name)); if (!hasPhotos) { @@ -428,8 +448,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return movie; } } - - if (result.Items.Count == 0 && multiDiscFolders.Count > 0) + else if (result.Items.Count == 0 && multiDiscFolders.Count > 0) { return GetMultiDiscMovie<T>(multiDiscFolders, directoryService); } @@ -440,7 +459,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies /// <summary> /// Gets the multi disc movie. /// </summary> - /// <typeparam name="T"></typeparam> /// <param name="multiDiscFolders">The folders.</param> /// <param name="directoryService">The directory service.</param> /// <returns>``0.</returns> @@ -454,7 +472,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies var subFileEntries = directoryService.GetFileSystemEntries(i); var subfolders = subFileEntries - .Where(e => e.IsDirectory) + .Where(e => e.IsDirectory) .ToList(); if (subfolders.Any(s => IsDvdDirectory(s.FullName, s.Name, directoryService))) @@ -462,7 +480,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies videoTypes.Add(VideoType.Dvd); return true; } - if (subfolders.Any(s => IsBluRayDirectory(s.FullName, s.Name, directoryService))) + + if (subfolders.Any(s => IsBluRayDirectory(s.Name))) { videoTypes.Add(VideoType.BluRay); return true; @@ -479,7 +498,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } return false; - }).OrderBy(i => i).ToList(); // If different video types were found, don't allow this @@ -494,24 +512,24 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); - var resolver = new StackResolver(namingOptions); - var result = resolver.ResolveDirectories(folderPaths); + var result = new StackResolver(namingOptions).ResolveDirectories(folderPaths).ToList(); - if (result.Stacks.Count != 1) + if (result.Count != 1) { return null; } + int additionalPartsLen = folderPaths.Count - 1; + var additionalParts = new string[additionalPartsLen]; + folderPaths.CopyTo(1, additionalParts, 0, additionalPartsLen); + var returnVideo = new T { Path = folderPaths[0], - - AdditionalParts = folderPaths.Skip(1).ToArray(), - + AdditionalParts = additionalParts, VideoType = videoTypes[0], - - Name = result.Stacks[0].Name + Name = result[0].Name }; SetIsoType(returnVideo); @@ -519,16 +537,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies return returnVideo; } - private string[] ValidCollectionTypes = new[] - { - CollectionType.Movies, - CollectionType.HomeVideos, - CollectionType.MusicVideos, - CollectionType.Movies, - CollectionType.Photos - }; - - private bool IsInvalid(Folder parent, string collectionType) + private bool IsInvalid(Folder parent, ReadOnlySpan<char> collectionType) { if (parent != null) { @@ -538,20 +547,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies } } - if (string.IsNullOrEmpty(collectionType)) + if (collectionType.IsEmpty) { return false; } - return !ValidCollectionTypes.Contains(collectionType, StringComparer.OrdinalIgnoreCase); - } - - private IImageProcessor _imageProcessor; - - public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor) - : base(libraryManager) - { - _imageProcessor = imageProcessor; + return !_validCollectionTypes.Contains(collectionType, StringComparison.OrdinalIgnoreCase); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs index 82779f8d3..1c560e8a6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs @@ -1,3 +1,5 @@ +#nullable disable + using System; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; @@ -7,17 +9,28 @@ using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Resolvers { - public class PhotoAlbumResolver : FolderResolver<PhotoAlbum> + /// <summary> + /// Class PhotoAlbumResolver. + /// </summary> + public class PhotoAlbumResolver : GenericFolderResolver<PhotoAlbum> { private readonly IImageProcessor _imageProcessor; - private ILibraryManager _libraryManager; + private readonly ILibraryManager _libraryManager; + /// <summary> + /// Initializes a new instance of the <see cref="PhotoAlbumResolver"/> class. + /// </summary> + /// <param name="imageProcessor">The image processor.</param> + /// <param name="libraryManager">The library manager.</param> public PhotoAlbumResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager) { _imageProcessor = imageProcessor; _libraryManager = libraryManager; } + /// <inheritdoc /> + public override ResolverPriority Priority => ResolverPriority.Second; + /// <summary> /// Resolves the specified args. /// </summary> @@ -31,8 +44,8 @@ namespace Emby.Server.Implementations.Library.Resolvers // Must be an image file within a photo collection var collectionType = args.GetCollectionType(); - if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) || - (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.GetLibraryOptions().EnablePhotos)) + if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) + || (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.LibraryOptions.EnablePhotos)) { if (HasPhotos(args)) { @@ -55,13 +68,12 @@ namespace Emby.Server.Implementations.Library.Resolvers { if (!file.IsDirectory && PhotoResolver.IsImageFile(file.FullName, _imageProcessor)) { - var libraryOptions = args.GetLibraryOptions(); var filename = file.Name; var ownedByMedia = false; foreach (var siblingFile in files) { - if (PhotoResolver.IsOwnedByMedia(_libraryManager, libraryOptions, siblingFile.FullName, filename)) + if (PhotoResolver.IsOwnedByMedia(_libraryManager, siblingFile.FullName, filename)) { ownedByMedia = true; break; @@ -74,9 +86,8 @@ namespace Emby.Server.Implementations.Library.Resolvers } } } + return false; } - - public override ResolverPriority Priority => ResolverPriority.Second; } } diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index db270c398..57bf40e9e 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -1,3 +1,7 @@ +#nullable disable + +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.IO; @@ -5,7 +9,6 @@ using System.Linq; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Resolvers @@ -14,6 +17,18 @@ namespace Emby.Server.Implementations.Library.Resolvers { private readonly IImageProcessor _imageProcessor; private readonly ILibraryManager _libraryManager; + private static readonly HashSet<string> _ignoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase) + { + "folder", + "thumb", + "landscape", + "fanart", + "backdrop", + "poster", + "cover", + "logo", + "default" + }; public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager) { @@ -31,10 +46,10 @@ namespace Emby.Server.Implementations.Library.Resolvers if (!args.IsDirectory) { // Must be an image file within a photo collection - var collectionType = args.GetCollectionType(); + var collectionType = args.CollectionType; - if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) || - (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.GetLibraryOptions().EnablePhotos)) + if (string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase) + || (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && args.LibraryOptions.EnablePhotos)) { if (IsImageFile(args.Path, _imageProcessor)) { @@ -42,11 +57,10 @@ namespace Emby.Server.Implementations.Library.Resolvers // Make sure the image doesn't belong to a video file var files = args.DirectoryService.GetFiles(Path.GetDirectoryName(args.Path)); - var libraryOptions = args.GetLibraryOptions(); foreach (var file in files) { - if (IsOwnedByMedia(_libraryManager, libraryOptions, file.FullName, filename)) + if (IsOwnedByMedia(_libraryManager, file.FullName, filename)) { return null; } @@ -63,54 +77,40 @@ namespace Emby.Server.Implementations.Library.Resolvers return null; } - internal static bool IsOwnedByMedia(ILibraryManager libraryManager, LibraryOptions libraryOptions, string file, string imageFilename) + internal static bool IsOwnedByMedia(ILibraryManager libraryManager, string file, string imageFilename) { - if (libraryManager.IsVideoFile(file, libraryOptions)) + if (libraryManager.IsVideoFile(file)) { - return IsOwnedByResolvedMedia(libraryManager, libraryOptions, file, imageFilename); + return IsOwnedByResolvedMedia(libraryManager, file, imageFilename); } return false; } - internal static bool IsOwnedByResolvedMedia(ILibraryManager libraryManager, LibraryOptions libraryOptions, string file, string imageFilename) + internal static bool IsOwnedByResolvedMedia(ILibraryManager libraryManager, string file, string imageFilename) + => imageFilename.StartsWith(Path.GetFileNameWithoutExtension(file), StringComparison.OrdinalIgnoreCase); + + internal static bool IsImageFile(string path, IImageProcessor imageProcessor) { - if (imageFilename.StartsWith(Path.GetFileNameWithoutExtension(file), StringComparison.OrdinalIgnoreCase)) + if (path == null) { - return true; + throw new ArgumentNullException(nameof(path)); } - return false; - } - - private static readonly HashSet<string> IgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase) - { - "folder", - "thumb", - "landscape", - "fanart", - "backdrop", - "poster", - "cover", - "logo", - "default" - }; - - internal static bool IsImageFile(string path, IImageProcessor imageProcessor) - { - var filename = Path.GetFileNameWithoutExtension(path) ?? string.Empty; + var filename = Path.GetFileNameWithoutExtension(path); - if (IgnoreFiles.Contains(filename)) + if (_ignoreFiles.Contains(filename)) { return false; } - if (IgnoreFiles.Any(i => filename.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1)) + if (_ignoreFiles.Any(i => filename.IndexOf(i, StringComparison.OrdinalIgnoreCase) != -1)) { return false; } - return imageProcessor.SupportedInputFormats.Contains(Path.GetExtension(path).TrimStart('.'), StringComparer.Ordinal); + string extension = Path.GetExtension(path).TrimStart('.'); + return imageProcessor.SupportedInputFormats.Contains(extension, StringComparer.OrdinalIgnoreCase); } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs index c295894d3..8ce59717d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs @@ -1,63 +1,74 @@ +#nullable disable + +#pragma warning disable CS1591 + using System; using System.IO; using System.Linq; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; +using MediaBrowser.Controller.Resolvers; +using MediaBrowser.LocalMetadata.Savers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; namespace Emby.Server.Implementations.Library.Resolvers { - public class PlaylistResolver : FolderResolver<Playlist> + /// <summary> + /// <see cref="IItemResolver"/> for <see cref="Playlist"/> library items. + /// </summary> + public class PlaylistResolver : GenericFolderResolver<Playlist> { - private string[] SupportedCollectionTypes = new string[] { - + private string[] _musicPlaylistCollectionTypes = + { string.Empty, CollectionType.Music }; - /// <summary> - /// Resolves the specified args. - /// </summary> - /// <param name="args">The args.</param> - /// <returns>BoxSet.</returns> + /// <inheritdoc/> protected override Playlist Resolve(ItemResolveArgs args) { - // It's a boxset if all of the following conditions are met: - // Is a Directory - // Contains [playlist] in the path if (args.IsDirectory) { - var filename = Path.GetFileName(args.Path); - - if (string.IsNullOrEmpty(filename)) + // It's a boxset if the path is a directory with [playlist] in it's the name + // TODO: Should this use Path.GetDirectoryName() instead? + bool isBoxSet = Path.GetFileName(args.Path) + ?.Contains("[playlist]", StringComparison.OrdinalIgnoreCase) + ?? false; + if (isBoxSet) { - return null; + return new Playlist + { + Path = args.Path, + Name = Path.GetFileName(args.Path).Replace("[playlist]", string.Empty, StringComparison.OrdinalIgnoreCase).Trim() + }; } - if (filename.IndexOf("[playlist]", StringComparison.OrdinalIgnoreCase) != -1) + // It's a directory-based playlist if the directory contains a playlist file + var filePaths = Directory.EnumerateFiles(args.Path, "*", new EnumerationOptions { IgnoreInaccessible = true }); + if (filePaths.Any(f => f.EndsWith(PlaylistXmlSaver.DefaultPlaylistFilename, StringComparison.OrdinalIgnoreCase))) { return new Playlist { Path = args.Path, - Name = Path.GetFileName(args.Path).Replace("[playlist]", string.Empty, StringComparison.OrdinalIgnoreCase).Trim() + Name = Path.GetFileName(args.Path) }; } } - else + + // 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)) { - if (SupportedCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + var extension = Path.GetExtension(args.Path); + if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { - var extension = Path.GetExtension(args.Path); - if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + return new Playlist { - return new Playlist - { - Path = args.Path, - Name = Path.GetFileNameWithoutExtension(args.Path), - IsInMixedFolder = true - }; - } + Path = args.Path, + Name = Path.GetFileNameWithoutExtension(args.Path), + IsInMixedFolder = true, + PlaylistMediaType = MediaType.Audio + }; } } diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index 7e4b38b4c..6bb999641 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -1,3 +1,7 @@ +#nullable disable + +#pragma warning disable CS1591 + using System; using System.IO; using System.Linq; @@ -9,7 +13,7 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { - public class SpecialFolderResolver : FolderResolver<Folder> + public class SpecialFolderResolver : GenericFolderResolver<Folder> { private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; @@ -39,10 +43,12 @@ namespace Emby.Server.Implementations.Library.Resolvers { return new AggregateFolder(); } + if (string.Equals(args.Path, _appPaths.DefaultUserViewsPath, StringComparison.OrdinalIgnoreCase)) { - return new UserRootFolder(); //if we got here and still a root - must be user root + return new UserRootFolder(); // if we got here and still a root - must be user root } + if (args.IsVf) { return new CollectionFolder @@ -61,7 +67,6 @@ namespace Emby.Server.Implementations.Library.Resolvers return args.FileSystemChildren .Where(i => { - try { return !i.IsDirectory && @@ -71,7 +76,6 @@ namespace Emby.Server.Implementations.Library.Resolvers { return false; } - }) .Select(i => _fileSystem.GetFileNameWithoutExtension(i)) .FirstOrDefault(); diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index a6d18c9b5..cf2d22f4d 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -1,5 +1,8 @@ +#nullable disable + using System; using System.Linq; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; @@ -7,16 +10,25 @@ using MediaBrowser.Model.Entities; namespace Emby.Server.Implementations.Library.Resolvers.TV { /// <summary> - /// Class EpisodeResolver + /// Class EpisodeResolver. /// </summary> public class EpisodeResolver : BaseVideoResolver<Episode> { /// <summary> + /// Initializes a new instance of the <see cref="EpisodeResolver"/> class. + /// </summary> + /// <param name="libraryManager">The library manager.</param> + public EpisodeResolver(ILibraryManager libraryManager) + : base(libraryManager) + { + } + + /// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>Episode.</returns> - protected override Episode Resolve(ItemResolveArgs args) + public override Episode Resolve(ItemResolveArgs args) { var parent = args.Parent; @@ -25,35 +37,30 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - var season = parent as Season; // Just in case the user decided to nest episodes. // Not officially supported but in some cases we can handle it. - if (season == null) - { - season = parent.GetParents().OfType<Season>().FirstOrDefault(); - } - // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something + var season = parent as Season ?? parent.GetParents().OfType<Season>().FirstOrDefault(); + + // 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>()) + if ((season != null || + string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || + args.HasParent<Series>()) + && (parent is Series || !BaseItem.AllExtrasTypesFolderNames.ContainsKey(parent.Name))) { var episode = ResolveVideo<Episode>(args, false); if (episode != null) { - var series = parent as Series; - if (series == null) - { - series = parent.GetParents().OfType<Series>().FirstOrDefault(); - } + var series = parent as Series ?? parent.GetParents().OfType<Series>().FirstOrDefault(); if (series != null) { episode.SeriesId = series.Id; episode.SeriesName = series.Name; } + if (season != null) { episode.SeasonId = season.Id; @@ -72,10 +79,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - - public EpisodeResolver(ILibraryManager libraryManager) - : base(libraryManager) - { - } } } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs index ce1386e91..063f67543 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs @@ -1,6 +1,7 @@ +#nullable disable + using System.Globalization; using Emby.Naming.TV; -using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Globalization; @@ -9,30 +10,25 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library.Resolvers.TV { /// <summary> - /// Class SeasonResolver + /// Class SeasonResolver. /// </summary> - public class SeasonResolver : FolderResolver<Season> + public class SeasonResolver : GenericFolderResolver<Season> { - /// <summary> - /// The _config - /// </summary> - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); private readonly ILocalizationManager _localization; - private readonly ILogger _logger; + private readonly ILogger<SeasonResolver> _logger; /// <summary> /// Initializes a new instance of the <see cref="SeasonResolver"/> class. /// </summary> - /// <param name="config">The config.</param> /// <param name="libraryManager">The library manager.</param> - /// <param name="localization">The localization</param> - /// <param name="logger">The logger</param> - public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, ILogger logger) + /// <param name="localization">The localization.</param> + /// <param name="logger">The logger.</param> + public SeasonResolver( + ILibraryManager libraryManager, + ILocalizationManager localization, + ILogger<SeasonResolver> logger) { - _config = config; _libraryManager = libraryManager; _localization = localization; _logger = logger; @@ -45,14 +41,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV /// <returns>Season.</returns> protected override Season Resolve(ItemResolveArgs args) { - if (args.Parent is Series && args.IsDirectory) + if (args.Parent is Series series && args.IsDirectory) { var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(); - var series = ((Series)args.Parent); var path = args.Path; - var seasonParserResult = new SeasonPathParser(namingOptions).Parse(path, true, true); + var seasonParserResult = SeasonPathParser.Parse(path, true, true); var season = new Season { @@ -74,7 +69,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV { if (episodeInfo.EpisodeNumber.HasValue && episodeInfo.SeasonNumber.HasValue) { - _logger.LogDebug("Found folder underneath series with episode number: {0}. Season {1}. Episode {2}", + _logger.LogDebug( + "Found folder underneath series with episode number: {0}. Season {1}. Episode {2}", path, episodeInfo.SeasonNumber.Value, episodeInfo.EpisodeNumber.Value); @@ -90,8 +86,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV season.Name = seasonNumber == 0 ? args.LibraryOptions.SeasonZeroDisplayName : - string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.ToString(UsCulture), args.GetLibraryOptions().PreferredMetadataLanguage); - + string.Format( + CultureInfo.InvariantCulture, + _localization.GetLocalizedString("NameSeasonNumber"), + seasonNumber, + args.LibraryOptions.PreferredMetadataLanguage); } return season; diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 5c95534ec..b7fbe01c5 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -1,12 +1,14 @@ +#nullable disable + +#pragma warning disable CS1591 + using System; using System.Collections.Generic; using System.IO; using Emby.Naming.TV; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; @@ -14,17 +16,20 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library.Resolvers.TV { /// <summary> - /// Class SeriesResolver + /// Class SeriesResolver. /// </summary> - public class SeriesResolver : FolderResolver<Series> + public class SeriesResolver : GenericFolderResolver<Series> { - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; + private readonly ILogger<SeriesResolver> _logger; private readonly ILibraryManager _libraryManager; - public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager) + /// <summary> + /// Initializes a new instance of the <see cref="SeriesResolver"/> class. + /// </summary> + /// <param name="logger">The logger.</param> + /// <param name="libraryManager">The library manager.</param> + public SeriesResolver(ILogger<SeriesResolver> logger, ILibraryManager libraryManager) { - _fileSystem = fileSystem; _logger = logger; _libraryManager = libraryManager; } @@ -52,15 +57,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV var collectionType = args.GetCollectionType(); if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { - //if (args.ContainsFileSystemEntryByName("tvshow.nfo")) - //{ - // return new Series - // { - // Path = args.Path, - // Name = Path.GetFileName(args.Path) - // }; - //} - var configuredContentType = _libraryManager.GetConfiguredContentType(args.Path); if (!string.Equals(configuredContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { @@ -93,7 +89,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false)) + if (IsSeriesFolder(args.Path, args.FileSystemChildren, _logger, _libraryManager, false)) { return new Series { @@ -110,31 +106,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV public static bool IsSeriesFolder( string path, IEnumerable<FileSystemMetadata> fileSystemChildren, - IDirectoryService directoryService, - IFileSystem fileSystem, - ILogger logger, + ILogger<SeriesResolver> logger, ILibraryManager libraryManager, - LibraryOptions libraryOptions, bool isTvContentType) { foreach (var child in fileSystemChildren) { - //if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden) - //{ - // //logger.LogDebug("Igoring series file or folder marked hidden: {0}", child.FullName); - // continue; - //} - - // Can't enforce this because files saved by Bitcasa are always marked System - //if ((attributes & FileAttributes.System) == FileAttributes.System) - //{ - // logger.LogDebug("Igoring series subfolder marked system: {0}", child.FullName); - // continue; - //} - if (child.IsDirectory) { - if (IsSeasonFolder(child.FullName, isTvContentType, libraryManager)) + if (IsSeasonFolder(child.FullName, isTvContentType)) { logger.LogDebug("{Path} is a series because of season folder {Dir}.", path, child.FullName); return true; @@ -143,7 +123,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV else { string fullName = child.FullName; - if (libraryManager.IsVideoFile(fullName, libraryOptions)) + if (libraryManager.IsVideoFile(fullName)) { if (isTvContentType) { @@ -168,35 +148,14 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV } /// <summary> - /// Determines whether [is place holder] [the specified path]. - /// </summary> - /// <param name="path">The path.</param> - /// <returns><c>true</c> if [is place holder] [the specified path]; otherwise, <c>false</c>.</returns> - /// <exception cref="ArgumentNullException">path</exception> - private static bool IsVideoPlaceHolder(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException(nameof(path)); - } - - var extension = Path.GetExtension(path); - - return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase); - } - - /// <summary> /// Determines whether [is season folder] [the specified path]. /// </summary> /// <param name="path">The path.</param> /// <param name="isTvContentType">if set to <c>true</c> [is tv content type].</param> - /// <param name="libraryManager">The library manager.</param> /// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns> - private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager) + private static bool IsSeasonFolder(string path, bool isTvContentType) { - var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions(); - - var seasonNumber = new SeasonPathParser(namingOptions).Parse(path, isTvContentType, isTvContentType).SeasonNumber; + var seasonNumber = SeasonPathParser.Parse(path, isTvContentType, isTvContentType).SeasonNumber; return seasonNumber.HasValue; } @@ -226,7 +185,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV if (!string.IsNullOrEmpty(id)) { - item.SetProviderId(MetadataProviders.Tvdb, id); + item.SetProviderId(MetadataProvider.Tvdb, id); } } } |
