Browse Source

Merge pull request #6851 from cvium/remove_references_to_ilibrarymanager

Cody Robibero 3 years ago
parent
commit
c32a421ea7

+ 2 - 0
Emby.Server.Implementations/ApplicationHost.cs

@@ -19,6 +19,7 @@ using Emby.Dlna;
 using Emby.Dlna.Main;
 using Emby.Dlna.Ssdp;
 using Emby.Drawing;
+using Emby.Naming.Common;
 using Emby.Notifications;
 using Emby.Photos;
 using Emby.Server.Implementations.Archiving;
@@ -596,6 +597,7 @@ namespace Emby.Server.Implementations
             serviceCollection.AddTransient(provider => new Lazy<IProviderManager>(provider.GetRequiredService<IProviderManager>));
             serviceCollection.AddTransient(provider => new Lazy<IUserViewManager>(provider.GetRequiredService<IUserViewManager>));
             serviceCollection.AddSingleton<ILibraryManager, LibraryManager>();
+            serviceCollection.AddSingleton<NamingOptions>();
 
             serviceCollection.AddSingleton<IMusicManager, MusicManager>();
 

+ 7 - 6
Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs

@@ -1,8 +1,9 @@
 using System;
 using System.IO;
+using Emby.Naming.Audio;
+using Emby.Naming.Common;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.IO;
 
@@ -13,17 +14,17 @@ namespace Emby.Server.Implementations.Library
     /// </summary>
     public class CoreResolutionIgnoreRule : IResolverIgnoreRule
     {
-        private readonly ILibraryManager _libraryManager;
+        private readonly NamingOptions _namingOptions;
         private readonly IServerApplicationPaths _serverApplicationPaths;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="CoreResolutionIgnoreRule"/> class.
         /// </summary>
-        /// <param name="libraryManager">The library manager.</param>
+        /// <param name="namingOptions">The naming options.</param>
         /// <param name="serverApplicationPaths">The server application paths.</param>
-        public CoreResolutionIgnoreRule(ILibraryManager libraryManager, IServerApplicationPaths serverApplicationPaths)
+        public CoreResolutionIgnoreRule(NamingOptions namingOptions, IServerApplicationPaths serverApplicationPaths)
         {
-            _libraryManager = libraryManager;
+            _namingOptions = namingOptions;
             _serverApplicationPaths = serverApplicationPaths;
         }
 
@@ -78,7 +79,7 @@ namespace Emby.Server.Implementations.Library
                 {
                     // Don't resolve these into audio files
                     if (Path.GetFileNameWithoutExtension(filename.AsSpan()).Equals(BaseItem.ThemeSongFileName, StringComparison.Ordinal)
-                        && _libraryManager.IsAudioFile(filename))
+                        && AudioFileParser.IsAudioFile(filename, _namingOptions))
                     {
                         return true;
                     }

+ 13 - 34
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -79,6 +79,7 @@ namespace Emby.Server.Implementations.Library
         private readonly IFileSystem _fileSystem;
         private readonly IItemRepository _itemRepository;
         private readonly IImageProcessor _imageProcessor;
+        private readonly NamingOptions _namingOptions;
 
         /// <summary>
         /// The _root folder sync lock.
@@ -88,9 +89,6 @@ namespace Emby.Server.Implementations.Library
 
         private readonly TimeSpan _viewRefreshInterval = TimeSpan.FromHours(24);
 
-        private NamingOptions _namingOptions;
-        private string[] _videoFileExtensions;
-
         /// <summary>
         /// The _root folder.
         /// </summary>
@@ -116,6 +114,7 @@ namespace Emby.Server.Implementations.Library
         /// <param name="itemRepository">The item repository.</param>
         /// <param name="imageProcessor">The image processor.</param>
         /// <param name="memoryCache">The memory cache.</param>
+        /// <param name="namingOptions">The naming options.</param>
         public LibraryManager(
             IServerApplicationHost appHost,
             ILogger<LibraryManager> logger,
@@ -130,7 +129,8 @@ namespace Emby.Server.Implementations.Library
             IMediaEncoder mediaEncoder,
             IItemRepository itemRepository,
             IImageProcessor imageProcessor,
-            IMemoryCache memoryCache)
+            IMemoryCache memoryCache,
+            NamingOptions namingOptions)
         {
             _appHost = appHost;
             _logger = logger;
@@ -146,6 +146,7 @@ namespace Emby.Server.Implementations.Library
             _itemRepository = itemRepository;
             _imageProcessor = imageProcessor;
             _memoryCache = memoryCache;
+            _namingOptions = namingOptions;
 
             _configurationManager.ConfigurationUpdated += ConfigurationUpdated;
 
@@ -2500,16 +2501,6 @@ namespace Emby.Server.Implementations.Library
             return RootFolder;
         }
 
-        /// <inheritdoc />
-        public bool IsVideoFile(string path)
-        {
-            return VideoResolver.IsVideoFile(path, GetNamingOptions());
-        }
-
-        /// <inheritdoc />
-        public bool IsAudioFile(string path)
-            => AudioFileParser.IsAudioFile(path, GetNamingOptions());
-
         /// <inheritdoc />
         public int? GetSeasonNumberFromPath(string path)
             => SeasonPathParser.Parse(path, true, true).SeasonNumber;
@@ -2525,7 +2516,7 @@ namespace Emby.Server.Implementations.Library
                 isAbsoluteNaming = null;
             }
 
-            var resolver = new EpisodeResolver(GetNamingOptions());
+            var resolver = new EpisodeResolver(_namingOptions);
 
             var isFolder = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd;
 
@@ -2682,21 +2673,9 @@ namespace Emby.Server.Implementations.Library
             return changed;
         }
 
-        /// <inheritdoc />
-        public NamingOptions GetNamingOptions()
-        {
-            if (_namingOptions == null)
-            {
-                _namingOptions = new NamingOptions();
-                _videoFileExtensions = _namingOptions.VideoFileExtensions;
-            }
-
-            return _namingOptions;
-        }
-
         public ItemLookupInfo ParseName(string name)
         {
-            var namingOptions = GetNamingOptions();
+            var namingOptions = _namingOptions;
             var result = VideoResolver.CleanDateTime(name, namingOptions);
 
             return new ItemLookupInfo
@@ -2708,11 +2687,11 @@ namespace Emby.Server.Implementations.Library
 
         public IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
         {
-            var namingOptions = GetNamingOptions();
+            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, _videoFileExtensions, false, false))
+                .SelectMany(i => _fileSystem.GetFiles(i.FullName, namingOptions.VideoFileExtensions, false, false))
                 .ToList();
 
             var videos = VideoListResolver.Resolve(fileSystemChildren, namingOptions);
@@ -2726,7 +2705,7 @@ namespace Emby.Server.Implementations.Library
 
             var resolvers = new IItemResolver[]
             {
-                new GenericVideoResolver<Trailer>(this)
+                new GenericVideoResolver<Trailer>(_namingOptions)
             };
 
             return ResolvePaths(files, directoryService, null, new LibraryOptions(), null, resolvers)
@@ -2752,11 +2731,11 @@ namespace Emby.Server.Implementations.Library
 
         public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService)
         {
-            var namingOptions = GetNamingOptions();
+            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, _videoFileExtensions, false, false))
+                .SelectMany(i => _fileSystem.GetFiles(i.FullName, namingOptions.VideoFileExtensions, false, false))
                 .ToList();
 
             var videos = VideoListResolver.Resolve(fileSystemChildren, namingOptions);
@@ -2840,7 +2819,7 @@ namespace Emby.Server.Implementations.Library
 
         private void SetExtraTypeFromFilename(Video item)
         {
-            var resolver = new ExtraResolver(GetNamingOptions());
+            var resolver = new ExtraResolver(_namingOptions);
 
             var result = resolver.GetExtraInfo(item.Path);
 

+ 26 - 41
Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs

@@ -6,7 +6,10 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using Emby.Naming.Audio;
 using Emby.Naming.AudioBook;
+using Emby.Naming.Common;
+using Emby.Naming.Video;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
@@ -21,11 +24,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
     /// </summary>
     public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver
     {
-        private readonly ILibraryManager _libraryManager;
+        private readonly NamingOptions _namingOptions;
 
-        public AudioResolver(ILibraryManager libraryManager)
+        public AudioResolver(NamingOptions namingOptions)
         {
-            _libraryManager = libraryManager;
+            _namingOptions = namingOptions;
         }
 
         /// <summary>
@@ -40,7 +43,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
             string collectionType,
             IDirectoryService directoryService)
         {
-            var result = ResolveMultipleInternal(parent, files, collectionType, directoryService);
+            var result = ResolveMultipleInternal(parent, files, collectionType);
 
             if (result != null)
             {
@@ -56,12 +59,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
         private MultiItemResolverResult ResolveMultipleInternal(
             Folder parent,
             List<FileSystemMetadata> files,
-            string collectionType,
-            IDirectoryService directoryService)
+            string collectionType)
         {
             if (string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase))
             {
-                return ResolveMultipleAudio<AudioBook>(parent, files, directoryService, false, collectionType, true);
+                return ResolveMultipleAudio(parent, files, true);
             }
 
             return null;
@@ -87,14 +89,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
                     return null;
                 }
 
-                var files = args.FileSystemChildren
-                    .Where(i => !_libraryManager.IgnoreFile(i, args.Parent))
-                    .ToList();
-
-                return FindAudio<AudioBook>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false);
+                return FindAudioBook(args, false);
             }
 
-            if (_libraryManager.IsAudioFile(args.Path))
+            if (AudioFileParser.IsAudioFile(args.Path, _namingOptions))
             {
                 var extension = Path.GetExtension(args.Path);
 
@@ -107,7 +105,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))
+                if (isMixedCollectionType && VideoResolver.IsVideoFile(args.Path, _namingOptions))
                 {
                     return null;
                 }
@@ -141,29 +139,23 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
             return null;
         }
 
-        private T FindAudio<T>(ItemResolveArgs args, string path, Folder parent, List<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName)
-            where T : MediaBrowser.Controller.Entities.Audio.Audio, new()
+        private AudioBook FindAudioBook(ItemResolveArgs args, bool parseName)
         {
             // TODO: Allow GetMultiDiscMovie in here
-            const bool supportsMultiVersion = false;
+            var result = ResolveMultipleAudio(args.Parent, args.GetActualFileSystemChildren(), parseName);
 
-            var result = ResolveMultipleAudio<T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ??
-                new MultiItemResolverResult();
-
-            if (result.Items.Count == 1)
+            if (result == null || result.Items.Count != 1 || result.Items[0] is not AudioBook item)
             {
-                // If we were supporting this we'd be checking filesFromOtherItems
-                var item = (T)result.Items[0];
-                item.IsInMixedFolder = false;
-                item.Name = Path.GetFileName(item.ContainingFolderPath);
-                return item;
+                return null;
             }
 
-            return null;
+            // If we were supporting this we'd be checking filesFromOtherItems
+            item.IsInMixedFolder = false;
+            item.Name = Path.GetFileName(item.ContainingFolderPath);
+            return item;
         }
 
-        private MultiItemResolverResult ResolveMultipleAudio<T>(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, bool suppportMultiEditions, string collectionType, bool parseName)
-            where T : MediaBrowser.Controller.Entities.Audio.Audio, new()
+        private MultiItemResolverResult ResolveMultipleAudio(Folder parent, IEnumerable<FileSystemMetadata> fileSystemEntries, bool parseName)
         {
             var files = new List<FileSystemMetadata>();
             var items = new List<BaseItem>();
@@ -176,15 +168,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
                 {
                     leftOver.Add(child);
                 }
-                else if (!IsIgnored(child.Name))
+                else
                 {
                     files.Add(child);
                 }
             }
 
-            var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
-
-            var resolver = new AudioBookListResolver(namingOptions);
+            var resolver = new AudioBookListResolver(_namingOptions);
             var resolverResult = resolver.Resolve(files).ToList();
 
             var result = new MultiItemResolverResult
@@ -210,7 +200,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 
                 var firstMedia = resolvedItem.Files[0];
 
-                var libraryItem = new T
+                var libraryItem = new AudioBook
                 {
                     Path = firstMedia.Path,
                     IsInMixedFolder = isInMixedFolder,
@@ -230,12 +220,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
             return result;
         }
 
-        private bool ContainsFile(List<AudioBookInfo> result, FileSystemMetadata file)
+        private static bool ContainsFile(IEnumerable<AudioBookInfo> result, FileSystemMetadata file)
         {
             return result.Any(i => ContainsFile(i, file));
         }
 
-        private bool ContainsFile(AudioBookInfo result, FileSystemMetadata file)
+        private static bool ContainsFile(AudioBookInfo result, FileSystemMetadata file)
         {
             return result.Files.Any(i => ContainsFile(i, file)) ||
                 result.AlternateVersions.Any(i => ContainsFile(i, file)) ||
@@ -246,10 +236,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
         {
             return string.Equals(result.Path, file.FullName, StringComparison.OrdinalIgnoreCase);
         }
-
-        private static bool IsIgnored(string filename)
-        {
-            return false;
-        }
     }
 }

+ 12 - 18
Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs

@@ -6,6 +6,7 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using Emby.Naming.Audio;
+using Emby.Naming.Common;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
@@ -22,20 +23,17 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
     public class MusicAlbumResolver : ItemResolver<MusicAlbum>
     {
         private readonly ILogger<MusicAlbumResolver> _logger;
-        private readonly IFileSystem _fileSystem;
-        private readonly ILibraryManager _libraryManager;
+        private readonly NamingOptions _namingOptions;
 
         /// <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)
+        /// <param name="namingOptions">The naming options.</param>
+        public MusicAlbumResolver(ILogger<MusicAlbumResolver> logger, NamingOptions namingOptions)
         {
             _logger = logger;
-            _fileSystem = fileSystem;
-            _libraryManager = libraryManager;
+            _namingOptions = namingOptions;
         }
 
         /// <summary>
@@ -87,7 +85,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
         /// <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, _libraryManager);
+            return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService);
         }
 
         /// <summary>
@@ -101,7 +99,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
             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, _libraryManager))
+                if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService))
                 {
                     return true;
                 }
@@ -116,13 +114,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
         private bool ContainsMusic(
             IEnumerable<FileSystemMetadata> list,
             bool allowSubfolders,
-            IDirectoryService directoryService,
-            ILogger<MusicAlbumResolver> logger,
-            IFileSystem fileSystem,
-            ILibraryManager libraryManager)
+            IDirectoryService directoryService)
         {
             // check for audio files before digging down into directories
-            var foundAudioFile = list.Any(fileSystemInfo => !fileSystemInfo.IsDirectory && libraryManager.IsAudioFile(fileSystemInfo.FullName));
+            var foundAudioFile = list.Any(fileSystemInfo => !fileSystemInfo.IsDirectory && AudioFileParser.IsAudioFile(fileSystemInfo.FullName, _namingOptions));
             if (foundAudioFile)
             {
                 // at least one audio file exists
@@ -137,21 +132,20 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 
             var discSubfolderCount = 0;
 
-            var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
-            var parser = new AlbumParser(namingOptions);
+            var parser = new AlbumParser(_namingOptions);
 
             var directories = list.Where(fileSystemInfo => fileSystemInfo.IsDirectory);
 
             var result = Parallel.ForEach(directories, (fileSystemInfo, state) =>
             {
                 var path = fileSystemInfo.FullName;
-                var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
+                var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService);
 
                 if (hasMusic)
                 {
                     if (parser.IsMultiPart(path))
                     {
-                        logger.LogDebug("Found multi-disc folder: {Path}", path);
+                        _logger.LogDebug("Found multi-disc folder: {Path}", path);
                         Interlocked.Increment(ref discSubfolderCount);
                     }
                     else

+ 6 - 13
Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs

@@ -3,6 +3,7 @@
 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;
@@ -19,27 +20,19 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
     public class MusicArtistResolver : ItemResolver<MusicArtist>
     {
         private readonly ILogger<MusicAlbumResolver> _logger;
-        private readonly IFileSystem _fileSystem;
-        private readonly ILibraryManager _libraryManager;
-        private readonly IServerConfigurationManager _config;
+        private NamingOptions _namingOptions;
 
         /// <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>
+        /// <param name="namingOptions">The naming options.</param>
         public MusicArtistResolver(
             ILogger<MusicAlbumResolver> logger,
-            IFileSystem fileSystem,
-            ILibraryManager libraryManager,
-            IServerConfigurationManager config)
+            NamingOptions namingOptions)
         {
             _logger = logger;
-            _fileSystem = fileSystem;
-            _libraryManager = libraryManager;
-            _config = config;
+            _namingOptions = namingOptions;
         }
 
         /// <summary>
@@ -89,7 +82,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
 
             var directoryService = args.DirectoryService;
 
-            var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager);
+            var albumResolver = new MusicAlbumResolver(_logger, _namingOptions);
 
             // If we contain an album assume we are an artist folder
             var directories = args.FileSystemChildren.Where(i => i.IsDirectory);

+ 7 - 6
Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs

@@ -6,6 +6,7 @@ using System;
 using System.IO;
 using System.Linq;
 using DiscUtils.Udf;
+using Emby.Naming.Common;
 using Emby.Naming.Video;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
@@ -21,12 +22,12 @@ namespace Emby.Server.Implementations.Library.Resolvers
     public abstract class BaseVideoResolver<T> : MediaBrowser.Controller.Resolvers.ItemResolver<T>
         where T : Video, new()
     {
-        protected BaseVideoResolver(ILibraryManager libraryManager)
+        protected BaseVideoResolver(NamingOptions namingOptions)
         {
-            LibraryManager = libraryManager;
+            NamingOptions = namingOptions;
         }
 
-        protected ILibraryManager LibraryManager { get; }
+        protected NamingOptions NamingOptions { get; }
 
         /// <summary>
         /// Resolves the specified args.
@@ -48,7 +49,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
         protected virtual TVideoType ResolveVideo<TVideoType>(ItemResolveArgs args, bool parseName)
               where TVideoType : Video, new()
         {
-            var namingOptions = LibraryManager.GetNamingOptions();
+            var namingOptions = NamingOptions;
 
             // If the path is a file check for a matching extensions
             if (args.IsDirectory)
@@ -138,7 +139,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
                     return null;
                 }
 
-                if (LibraryManager.IsVideoFile(args.Path) || videoInfo.IsStub)
+                if (VideoResolver.IsVideoFile(args.Path, NamingOptions) || videoInfo.IsStub)
                 {
                     var path = args.Path;
 
@@ -267,7 +268,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
 
         protected void Set3DFormat(Video video)
         {
-            var result = Format3DParser.Parse(video.Path, LibraryManager.GetNamingOptions());
+            var result = Format3DParser.Parse(video.Path, NamingOptions);
 
             Set3DFormat(video, result.Is3D, result.Format3D);
         }

+ 3 - 3
Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs

@@ -2,16 +2,16 @@
 
 #pragma warning disable CS1591
 
+using Emby.Naming.Common;
 using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
 
 namespace Emby.Server.Implementations.Library.Resolvers
 {
     public class GenericVideoResolver<T> : BaseVideoResolver<T>
         where T : Video, new()
     {
-        public GenericVideoResolver(ILibraryManager libraryManager)
-            : base(libraryManager)
+        public GenericVideoResolver(NamingOptions namingOptions)
+            : base(namingOptions)
         {
         }
     }

+ 10 - 13
Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

@@ -5,6 +5,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Text.RegularExpressions;
+using Emby.Naming.Common;
 using Emby.Naming.Video;
 using Jellyfin.Extensions;
 using MediaBrowser.Controller.Drawing;
@@ -25,6 +26,7 @@ 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[]
         {
@@ -38,12 +40,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
         /// <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)
+        /// <param name="namingOptions">The naming options.</param>
+        public MovieResolver(IImageProcessor imageProcessor, NamingOptions namingOptions)
+            : base(namingOptions)
         {
             _imageProcessor = imageProcessor;
+            _stackResolver = new StackResolver(NamingOptions);
         }
 
         /// <summary>
@@ -89,9 +92,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
                     return null;
                 }
 
-                var files = args.FileSystemChildren
-                    .Where(i => !LibraryManager.IgnoreFile(i, args.Parent))
-                    .ToList();
+                var files = args.GetActualFileSystemChildren().ToList();
 
                 if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase))
                 {
@@ -258,9 +259,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
                 }
             }
 
-            var namingOptions = LibraryManager.GetNamingOptions();
-
-            var resolverResult = VideoListResolver.Resolve(files, namingOptions, suppportMultiEditions).ToList();
+            var resolverResult = VideoListResolver.Resolve(files, NamingOptions, suppportMultiEditions).ToList();
 
             var result = new MultiItemResolverResult
             {
@@ -438,7 +437,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
             if (result.Items.Count == 1)
             {
                 var videoPath = result.Items[0].Path;
-                var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(LibraryManager, videoPath, i.Name));
+                var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(videoPath, i.Name));
 
                 if (!hasPhotos)
                 {
@@ -511,9 +510,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
                 return null;
             }
 
-            var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions();
-
-            var result = new StackResolver(namingOptions).ResolveDirectories(folderPaths).ToList();
+            var result = _stackResolver.ResolveDirectories(folderPaths).ToList();
 
             if (result.Count != 1)
             {

+ 6 - 5
Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs

@@ -1,6 +1,7 @@
 #nullable disable
 
 using System;
+using Emby.Naming.Common;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
@@ -15,17 +16,17 @@ namespace Emby.Server.Implementations.Library.Resolvers
     public class PhotoAlbumResolver : GenericFolderResolver<PhotoAlbum>
     {
         private readonly IImageProcessor _imageProcessor;
-        private readonly ILibraryManager _libraryManager;
+        private readonly NamingOptions _namingOptions;
 
         /// <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)
+        /// <param name="namingOptions">The naming options.</param>
+        public PhotoAlbumResolver(IImageProcessor imageProcessor, NamingOptions namingOptions)
         {
             _imageProcessor = imageProcessor;
-            _libraryManager = libraryManager;
+            _namingOptions = namingOptions;
         }
 
         /// <inheritdoc />
@@ -73,7 +74,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
 
                     foreach (var siblingFile in files)
                     {
-                        if (PhotoResolver.IsOwnedByMedia(_libraryManager, siblingFile.FullName, filename))
+                        if (PhotoResolver.IsOwnedByMedia(_namingOptions, siblingFile.FullName, filename))
                         {
                             ownedByMedia = true;
                             break;

+ 11 - 12
Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs

@@ -6,6 +6,8 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
+using Emby.Naming.Common;
+using Emby.Naming.Video;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
@@ -16,7 +18,8 @@ namespace Emby.Server.Implementations.Library.Resolvers
     public class PhotoResolver : ItemResolver<Photo>
     {
         private readonly IImageProcessor _imageProcessor;
-        private readonly ILibraryManager _libraryManager;
+        private readonly NamingOptions _namingOptions;
+
         private static readonly HashSet<string> _ignoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
         {
             "folder",
@@ -30,10 +33,11 @@ namespace Emby.Server.Implementations.Library.Resolvers
             "default"
         };
 
-        public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager)
+
+        public PhotoResolver(IImageProcessor imageProcessor, NamingOptions namingOptions)
         {
             _imageProcessor = imageProcessor;
-            _libraryManager = libraryManager;
+            _namingOptions = namingOptions;
         }
 
         /// <summary>
@@ -60,7 +64,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
 
                         foreach (var file in files)
                         {
-                            if (IsOwnedByMedia(_libraryManager, file.FullName, filename))
+                            if (IsOwnedByMedia(_namingOptions, file.FullName, filename))
                             {
                                 return null;
                             }
@@ -77,17 +81,12 @@ namespace Emby.Server.Implementations.Library.Resolvers
             return null;
         }
 
-        internal static bool IsOwnedByMedia(ILibraryManager libraryManager, string file, string imageFilename)
+        internal static bool IsOwnedByMedia(NamingOptions namingOptions, string file, string imageFilename)
         {
-            if (libraryManager.IsVideoFile(file))
-            {
-                return IsOwnedByResolvedMedia(libraryManager, file, imageFilename);
-            }
-
-            return false;
+            return VideoResolver.IsVideoFile(file, namingOptions) && IsOwnedByResolvedMedia(file, imageFilename);
         }
 
-        internal static bool IsOwnedByResolvedMedia(ILibraryManager libraryManager, string file, string imageFilename)
+        internal static bool IsOwnedByResolvedMedia(string file, string imageFilename)
             => imageFilename.StartsWith(Path.GetFileNameWithoutExtension(file), StringComparison.OrdinalIgnoreCase);
 
         internal static bool IsImageFile(string path, IImageProcessor imageProcessor)

+ 4 - 3
Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs

@@ -2,6 +2,7 @@
 
 using System;
 using System.Linq;
+using Emby.Naming.Common;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
@@ -17,9 +18,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
         /// <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)
+        /// <param name="namingOptions">The naming options.</param>
+        public EpisodeResolver(NamingOptions namingOptions)
+            : base(namingOptions)
         {
         }
 

+ 14 - 16
Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs

@@ -1,6 +1,7 @@
 #nullable disable
 
 using System.Globalization;
+using Emby.Naming.Common;
 using Emby.Naming.TV;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
@@ -14,22 +15,22 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
     /// </summary>
     public class SeasonResolver : GenericFolderResolver<Season>
     {
-        private readonly ILibraryManager _libraryManager;
         private readonly ILocalizationManager _localization;
         private readonly ILogger<SeasonResolver> _logger;
+        private readonly NamingOptions _namingOptions;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="SeasonResolver"/> class.
         /// </summary>
-        /// <param name="libraryManager">The library manager.</param>
+        /// <param name="namingOptions">The naming options.</param>
         /// <param name="localization">The localization.</param>
         /// <param name="logger">The logger.</param>
         public SeasonResolver(
-            ILibraryManager libraryManager,
+            NamingOptions namingOptions,
             ILocalizationManager localization,
             ILogger<SeasonResolver> logger)
         {
-            _libraryManager = libraryManager;
+            _namingOptions = namingOptions;
             _localization = localization;
             _logger = logger;
         }
@@ -43,7 +44,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
         {
             if (args.Parent is Series series && args.IsDirectory)
             {
-                var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
+                var namingOptions = _namingOptions;
 
                 var path = args.Path;
 
@@ -65,18 +66,15 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
 
                     var episodeInfo = resolver.Resolve(testPath, true);
 
-                    if (episodeInfo != null)
+                    if (episodeInfo?.EpisodeNumber != null && episodeInfo.SeasonNumber.HasValue)
                     {
-                        if (episodeInfo.EpisodeNumber.HasValue && episodeInfo.SeasonNumber.HasValue)
-                        {
-                            _logger.LogDebug(
-                                "Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
-                                path,
-                                episodeInfo.SeasonNumber.Value,
-                                episodeInfo.EpisodeNumber.Value);
-
-                            return null;
-                        }
+                        _logger.LogDebug(
+                            "Found folder underneath series with episode number: {0}. Season {1}. Episode {2}",
+                            path,
+                            episodeInfo.SeasonNumber.Value,
+                            episodeInfo.EpisodeNumber.Value);
+
+                        return null;
                     }
                 }
 

+ 24 - 14
Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs

@@ -5,7 +5,12 @@
 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;
@@ -21,17 +26,23 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
     public class SeriesResolver : GenericFolderResolver<Series>
     {
         private readonly ILogger<SeriesResolver> _logger;
-        private readonly ILibraryManager _libraryManager;
+        private readonly NamingOptions _namingOptions;
+        private readonly IFileSystem _fileSystem;
+        private readonly IServerConfigurationManager _configurationManager;
 
         /// <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)
+        /// <param name="namingOptions">The naming options.</param>
+        /// <param name="fileSystem">The file system.</param>
+        /// <param name="configurationManager">The server configuration manager.</param>
+        public SeriesResolver(ILogger<SeriesResolver> logger,  NamingOptions namingOptions, IFileSystem fileSystem, IServerConfigurationManager configurationManager)
         {
             _logger = logger;
-            _libraryManager = libraryManager;
+            _namingOptions = namingOptions;
+            _fileSystem = fileSystem;
+            _configurationManager = configurationManager;
         }
 
         /// <summary>
@@ -54,12 +65,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
                     return null;
                 }
 
-                var seriesInfo = Naming.TV.SeriesResolver.Resolve(_libraryManager.GetNamingOptions(), args.Path);
+                var seriesInfo = Naming.TV.SeriesResolver.Resolve(_namingOptions, args.Path);
 
                 var collectionType = args.GetCollectionType();
                 if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
                 {
-                    var configuredContentType = _libraryManager.GetConfiguredContentType(args.Path);
+                    // TODO refactor into separate class or something, this is copied from LibraryManager.GetConfiguredContentType
+                    var configuredContentType = args.GetConfiguredContentType();
                     if (!string.Equals(configuredContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
                     {
                         return new Series
@@ -91,7 +103,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
                         return null;
                     }
 
-                    if (IsSeriesFolder(args.Path, args.FileSystemChildren, _logger, _libraryManager, false))
+                    if (IsSeriesFolder(args.Path, args.FileSystemChildren, false))
                     {
                         return new Series
                         {
@@ -105,11 +117,9 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
             return null;
         }
 
-        public static bool IsSeriesFolder(
+        private bool IsSeriesFolder(
             string path,
             IEnumerable<FileSystemMetadata> fileSystemChildren,
-            ILogger<SeriesResolver> logger,
-            ILibraryManager libraryManager,
             bool isTvContentType)
         {
             foreach (var child in fileSystemChildren)
@@ -118,21 +128,21 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
                 {
                     if (IsSeasonFolder(child.FullName, isTvContentType))
                     {
-                        logger.LogDebug("{Path} is a series because of season folder {Dir}.", path, child.FullName);
+                        _logger.LogDebug("{Path} is a series because of season folder {Dir}.", path, child.FullName);
                         return true;
                     }
                 }
                 else
                 {
                     string fullName = child.FullName;
-                    if (libraryManager.IsVideoFile(fullName))
+                    if (VideoResolver.IsVideoFile(path, _namingOptions))
                     {
                         if (isTvContentType)
                         {
                             return true;
                         }
 
-                        var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions();
+                        var namingOptions = _namingOptions;
 
                         var episodeResolver = new Naming.TV.EpisodeResolver(namingOptions);
 
@@ -145,7 +155,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
                 }
             }
 
-            logger.LogDebug("{Path} is not a series folder.", path);
+            _logger.LogDebug("{Path} is not a series folder.", path);
             return false;
         }
 

+ 0 - 20
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -396,20 +396,6 @@ namespace MediaBrowser.Controller.Library
             string viewType,
             string sortName);
 
-        /// <summary>
-        /// Determines whether [is video file] [the specified path].
-        /// </summary>
-        /// <param name="path">The path.</param>
-        /// <returns><c>true</c> if [is video file] [the specified path]; otherwise, <c>false</c>.</returns>
-        bool IsVideoFile(string path);
-
-        /// <summary>
-        /// Determines whether [is audio file] [the specified path].
-        /// </summary>
-        /// <param name="path">The path.</param>
-        /// <returns><c>true</c> if [is audio file] [the specified path]; otherwise, <c>false</c>.</returns>
-        bool IsAudioFile(string path);
-
         /// <summary>
         /// Gets the season number from path.
         /// </summary>
@@ -625,11 +611,5 @@ namespace MediaBrowser.Controller.Library
         BaseItem GetParentItem(string parentId, Guid? userId);
 
         BaseItem GetParentItem(Guid? parentId, Guid? userId);
-
-        /// <summary>
-        /// Gets or creates a static instance of <see cref="NamingOptions"/>.
-        /// </summary>
-        /// <returns>An instance of the <see cref="NamingOptions"/> class.</returns>
-        NamingOptions GetNamingOptions();
     }
 }

+ 35 - 0
MediaBrowser.Controller/Library/ItemResolveArgs.cs

@@ -36,6 +36,7 @@ namespace MediaBrowser.Controller.Library
             DirectoryService = directoryService;
         }
 
+        // TODO remove dependencies as properties, they should be injected where it makes sense
         public IDirectoryService DirectoryService { get; }
 
         /// <summary>
@@ -236,6 +237,40 @@ namespace MediaBrowser.Controller.Library
             return CollectionType;
         }
 
+        /// <summary>
+        /// Gets the configured content type for the path.
+        /// </summary>
+        /// <remarks>
+        /// This is subject to future refactoring as it relies on a static property in BaseItem.
+        /// </remarks>
+        /// <returns>The configured content type.</returns>
+        public string GetConfiguredContentType()
+        {
+            return BaseItem.LibraryManager.GetConfiguredContentType(Path);
+        }
+
+        /// <summary>
+        /// Gets the file system children that do not hit the ignore file check.
+        /// </summary>
+        /// <remarks>
+        /// This is subject to future refactoring as it relies on a static property in BaseItem.
+        /// </remarks>
+        /// <returns>The file system children that are not ignored.</returns>
+        public IEnumerable<FileSystemMetadata> GetActualFileSystemChildren()
+        {
+            var numberOfChildren = FileSystemChildren.Length;
+            for (var i = 0; i < numberOfChildren; i++)
+            {
+                var child = FileSystemChildren[i];
+                if (BaseItem.LibraryManager.IgnoreFile(child, Parent))
+                {
+                    continue;
+                }
+
+                yield return child;
+            }
+        }
+
         /// <summary>
         /// Returns a hash code for this instance.
         /// </summary>

+ 5 - 9
tests/Jellyfin.Server.Implementations.Tests/Library/EpisodeResolverTest.cs

@@ -1,5 +1,4 @@
-using System;
-using Emby.Server.Implementations.Library.Resolvers.TV;
+using Emby.Server.Implementations.Library.Resolvers.TV;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
@@ -17,19 +16,16 @@ namespace Jellyfin.Server.Implementations.Tests.Library
         [Fact]
         public void Resolve_GivenVideoInExtrasFolder_DoesNotResolveToEpisode()
         {
-            var season = new Season { Name = "Season 1" };
             var parent = new Folder { Name = "extras" };
-            var libraryManagerMock = new Mock<ILibraryManager>();
-            libraryManagerMock.Setup(x => x.GetItemById(It.IsAny<Guid>())).Returns(season);
 
-            var episodeResolver = new EpisodeResolver(libraryManagerMock.Object);
+            var episodeResolver = new EpisodeResolver(null);
             var itemResolveArgs = new ItemResolveArgs(
                 Mock.Of<IServerApplicationPaths>(),
                 Mock.Of<IDirectoryService>())
             {
                 Parent = parent,
                 CollectionType = CollectionType.TvShows,
-                FileInfo = new FileSystemMetadata()
+                FileInfo = new FileSystemMetadata
                 {
                     FullName = "All My Children/Season 01/Extras/All My Children S01E01 - Behind The Scenes.mkv"
                 }
@@ -45,7 +41,7 @@ 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(Mock.Of<ILibraryManager>());
+            var episodeResolver = new EpisodeResolverMock();
             var itemResolveArgs = new ItemResolveArgs(
                 Mock.Of<IServerApplicationPaths>(),
                 Mock.Of<IDirectoryService>())
@@ -62,7 +58,7 @@ namespace Jellyfin.Server.Implementations.Tests.Library
 
         private class EpisodeResolverMock : EpisodeResolver
         {
-            public EpisodeResolverMock(ILibraryManager libraryManager) : base(libraryManager)
+            public EpisodeResolverMock() : base(null)
             {
             }