From 68d1b609647d0a592afc7d994fad2dedcb135f6b Mon Sep 17 00:00:00 2001
From: Luke Pulverenti <luke.pulverenti@gmail.com>
Date: Sat, 13 Aug 2016 01:49:00 -0400
Subject: [PATCH] stub out objects for per library settings

---
 .../Library/LibraryStructureService.cs        |  7 +-
 .../Playback/BaseStreamingService.cs          |  6 +-
 .../Configuration/LibraryOptions.cs           | 14 ++++
 .../Entities/Audio/Audio.cs                   |  2 +-
 MediaBrowser.Controller/Entities/BaseItem.cs  |  6 +-
 MediaBrowser.Controller/Entities/Book.cs      |  2 +-
 .../Entities/CollectionFolder.cs              | 60 ++++++++++++++
 MediaBrowser.Controller/Entities/Folder.cs    |  4 +-
 MediaBrowser.Controller/Entities/Game.cs      |  2 +-
 .../Entities/IHasMetadata.cs                  |  2 +-
 .../Entities/Movies/BoxSet.cs                 | 13 ++++
 MediaBrowser.Controller/Entities/Photo.cs     |  2 +-
 MediaBrowser.Controller/Entities/Video.cs     |  7 +-
 .../Library/ILibraryManager.cs                | 18 +++--
 .../Library/ItemResolveArgs.cs                |  8 ++
 .../MediaBrowser.Controller.csproj            |  1 +
 MediaBrowser.Controller/Playlists/Playlist.cs |  6 ++
 .../Configuration/ServerConfiguration.cs      |  2 -
 .../Manager/MetadataService.cs                |  2 +-
 .../MediaInfo/FFProbeProvider.cs              |  2 +-
 .../MediaInfo/VideoImageProvider.cs           |  9 ++-
 .../Library/LibraryManager.cs                 | 78 ++++++++++++++-----
 .../Library/Resolvers/Audio/AudioResolver.cs  |  6 +-
 .../Resolvers/Audio/MusicAlbumResolver.cs     | 30 +++----
 .../Resolvers/Audio/MusicArtistResolver.cs    |  2 +-
 .../Library/Resolvers/BaseVideoResolver.cs    |  2 +-
 .../Library/Resolvers/PhotoResolver.cs        |  7 +-
 .../Library/Resolvers/TV/SeriesResolver.cs    |  6 +-
 .../LiveTv/EmbyTV/EmbyTV.cs                   |  2 +-
 .../Persistence/SqliteItemRepository.cs       |  2 +-
 .../Playlists/ManualPlaylistsFolder.cs        |  2 +-
 .../ApplicationHost.cs                        |  1 +
 32 files changed, 234 insertions(+), 79 deletions(-)
 create mode 100644 MediaBrowser.Controller/Configuration/LibraryOptions.cs

diff --git a/MediaBrowser.Api/Library/LibraryStructureService.cs b/MediaBrowser.Api/Library/LibraryStructureService.cs
index 3cf0d5d937..3af2134937 100644
--- a/MediaBrowser.Api/Library/LibraryStructureService.cs
+++ b/MediaBrowser.Api/Library/LibraryStructureService.cs
@@ -10,6 +10,7 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using CommonIO;
+using MediaBrowser.Controller.Configuration;
 
 namespace MediaBrowser.Api.Library
 {
@@ -52,6 +53,8 @@ namespace MediaBrowser.Api.Library
         /// </summary>
         /// <value>The path.</value>
         public string[] Paths { get; set; }
+
+        public LibraryOptions LibraryOptions { get; set; }
     }
 
     [Route("/Library/VirtualFolders", "DELETE")]
@@ -190,7 +193,9 @@ namespace MediaBrowser.Api.Library
         /// <param name="request">The request.</param>
         public void Post(AddVirtualFolder request)
         {
-            _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, request.Paths, request.RefreshLibrary);
+            var libraryOptions = request.LibraryOptions ?? new LibraryOptions();
+
+            _libraryManager.AddVirtualFolder(request.Name, request.CollectionType, request.Paths, libraryOptions, request.RefreshLibrary);
         }
 
         /// <summary>
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 59dfd87ecd..a9489cecce 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1055,14 +1055,14 @@ namespace MediaBrowser.Api.Playback
             var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments;
             Logger.Info(commandLineLogMessage);
 
-            var logFilePrefix = "transcode";
+            var logFilePrefix = "ffmpeg-transcode";
             if (state.VideoRequest != null && string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase))
             {
-                logFilePrefix = "directstream";
+                logFilePrefix = "ffmpeg-directstream";
             }
             else if (state.VideoRequest != null && string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase))
             {
-                logFilePrefix = "remux";
+                logFilePrefix = "ffmpeg-remux";
             }
 
             var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt");
diff --git a/MediaBrowser.Controller/Configuration/LibraryOptions.cs b/MediaBrowser.Controller/Configuration/LibraryOptions.cs
new file mode 100644
index 0000000000..1a824c08bf
--- /dev/null
+++ b/MediaBrowser.Controller/Configuration/LibraryOptions.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Configuration
+{
+    public class LibraryOptions
+    {
+        public bool EnableAudioArchiveFiles { get; set; }
+        public bool EnableVideoArchiveFiles { get; set; }
+    }
+}
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 1897511af7..6326bbd4f4 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Entities.Audio
         }
 
         [IgnoreDataMember]
-        public override bool EnableForceSaveOnDateModifiedChange
+        public override bool EnableRefreshOnDateModifiedChange
         {
             get { return true; }
         }
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 1d623c3acc..cc3646cdcb 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -455,7 +455,7 @@ namespace MediaBrowser.Controller.Entities
         public DateTime DateLastRefreshed { get; set; }
 
         [IgnoreDataMember]
-        public virtual bool EnableForceSaveOnDateModifiedChange
+        public virtual bool EnableRefreshOnDateModifiedChange
         {
             get { return false; }
         }
@@ -951,7 +951,7 @@ namespace MediaBrowser.Controller.Entities
                 .Where(i => !i.IsDirectory && string.Equals(FileSystem.GetFileNameWithoutExtension(i), ThemeSongFilename, StringComparison.OrdinalIgnoreCase))
                 );
 
-            return LibraryManager.ResolvePaths(files, directoryService, null)
+            return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions())
                 .OfType<Audio.Audio>()
                 .Select(audio =>
                 {
@@ -981,7 +981,7 @@ namespace MediaBrowser.Controller.Entities
                 .Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase))
                 .SelectMany(i => directoryService.GetFiles(i.FullName));
 
-            return LibraryManager.ResolvePaths(files, directoryService, null)
+            return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions())
                 .OfType<Video>()
                 .Select(item =>
                 {
diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs
index 59ab954378..56f9fa784a 100644
--- a/MediaBrowser.Controller/Entities/Book.cs
+++ b/MediaBrowser.Controller/Entities/Book.cs
@@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.Entities
         }
 
         [IgnoreDataMember]
-        public override bool EnableForceSaveOnDateModifiedChange
+        public override bool EnableRefreshOnDateModifiedChange
         {
             get { return true; }
         }
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 8bf9919f25..68ba22356c 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -3,11 +3,14 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Runtime.Serialization;
 using System.Threading;
 using System.Threading.Tasks;
 using CommonIO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Serialization;
 using MoreLinq;
 
 namespace MediaBrowser.Controller.Entities
@@ -18,6 +21,8 @@ namespace MediaBrowser.Controller.Entities
     /// </summary>
     public class CollectionFolder : Folder, ICollectionFolder
     {
+        public static IXmlSerializer XmlSerializer { get; set; }
+
         public CollectionFolder()
         {
             PhysicalLocationsList = new List<string>();
@@ -39,6 +44,61 @@ namespace MediaBrowser.Controller.Entities
 
         public string CollectionType { get; set; }
 
+        private readonly Dictionary<string, LibraryOptions> _libraryOptions = new Dictionary<string, LibraryOptions>();
+        public LibraryOptions GetLibraryOptions()
+        {
+            lock (_libraryOptions)
+            {
+                LibraryOptions options;
+                if (!_libraryOptions.TryGetValue(Path, out options))
+                {
+                    options = LoadLibraryOptions();
+                    _libraryOptions[Path] = options;
+                }
+
+                return options;
+            }
+        }
+
+        private LibraryOptions LoadLibraryOptions()
+        {
+            try
+            {
+                var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(Path)) as LibraryOptions;
+
+                if (result == null)
+                {
+                    return new LibraryOptions();
+                }
+
+                return result;
+            }
+            catch (FileNotFoundException)
+            {
+                return new LibraryOptions();
+            }
+            catch (DirectoryNotFoundException)
+            {
+                return new LibraryOptions();
+            }
+            catch (Exception ex)
+            {
+                Logger.ErrorException("Error loading library options", ex);
+
+                return new LibraryOptions();
+            }
+        }
+
+        private static string GetLibraryOptionsPath(string path)
+        {
+            return System.IO.Path.Combine(path, "options.xml");
+        }
+
+        public static void SaveLibraryOptions(string path, LibraryOptions options)
+        {
+            XmlSerializer.SerializeToFile(options, GetLibraryOptionsPath(path));
+        }
+
         /// <summary>
         /// Allow different display preferences for each collection folder
         /// </summary>
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index c1728ce389..bf04c643ce 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -273,6 +273,7 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         protected virtual IEnumerable<BaseItem> LoadChildren()
         {
+            //Logger.Debug("Loading children from {0} {1}", Id, Path);
             //just load our children from the repo - the library will be validated and maintained in other processes
             return GetCachedChildren();
         }
@@ -643,8 +644,9 @@ namespace MediaBrowser.Controller.Entities
         protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
         {
             var collectionType = LibraryManager.GetContentType(this);
+            var libraryOptions = LibraryManager.GetLibraryOptions(this);
 
-            return LibraryManager.ResolvePaths(GetFileSystemChildren(directoryService), directoryService, this, collectionType);
+            return LibraryManager.ResolvePaths(GetFileSystemChildren(directoryService), directoryService, this, libraryOptions, collectionType);
         }
 
         /// <summary>
diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs
index 54386a1795..24910498f5 100644
--- a/MediaBrowser.Controller/Entities/Game.cs
+++ b/MediaBrowser.Controller/Entities/Game.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Entities
         }
 
         [IgnoreDataMember]
-        public override bool EnableForceSaveOnDateModifiedChange
+        public override bool EnableRefreshOnDateModifiedChange
         {
             get { return true; }
         }
diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs
index c7a3c7778e..d5891c6552 100644
--- a/MediaBrowser.Controller/Entities/IHasMetadata.cs
+++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs
@@ -52,7 +52,7 @@ namespace MediaBrowser.Controller.Entities
 
         bool RequiresRefresh();
 
-        bool EnableForceSaveOnDateModifiedChange { get; }
+        bool EnableRefreshOnDateModifiedChange { get; }
 
         string PresentationUniqueKey { get; set; }
 
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index 4effc162e4..ba50a1e0de 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -62,6 +62,19 @@ namespace MediaBrowser.Controller.Entities.Movies
             return UnratedItem.Movie;
         }
 
+        protected override IEnumerable<BaseItem> LoadChildren()
+        {
+            var first = LinkedChildren.FirstOrDefault();
+
+            if (first != null && first.Type == LinkedChildType.Shortcut)
+            {
+                return base.LoadChildren();
+            }
+
+            // Save a trip to the database
+            return new List<BaseItem>();
+        }
+
         [IgnoreDataMember]
         public override bool IsPreSorted
         {
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 804ea04a59..965616eb53 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -52,7 +52,7 @@ namespace MediaBrowser.Controller.Entities
         }
 
         [IgnoreDataMember]
-        public override bool EnableForceSaveOnDateModifiedChange
+        public override bool EnableRefreshOnDateModifiedChange
         {
             get { return true; }
         }
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 7110b76cc6..830747d3c9 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -55,9 +55,12 @@ namespace MediaBrowser.Controller.Entities
         }
 
         [IgnoreDataMember]
-        public override bool EnableForceSaveOnDateModifiedChange
+        public override bool EnableRefreshOnDateModifiedChange
         {
-            get { return true; }
+            get
+            {
+                return VideoType == VideoType.VideoFile || VideoType == VideoType.Iso;
+            }
         }
 
         public int? TotalBitrate { get; set; }
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index ff7f2fe678..edbacb5e70 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
 using CommonIO;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Dto;
 
 namespace MediaBrowser.Controller.Library
@@ -32,15 +33,11 @@ namespace MediaBrowser.Controller.Library
         /// <summary>
         /// Resolves a set of files into a list of BaseItem
         /// </summary>
-        /// <param name="files">The files.</param>
-        /// <param name="directoryService">The directory service.</param>
-        /// <param name="parent">The parent.</param>
-        /// <param name="collectionType">Type of the collection.</param>
-        /// <returns>List{``0}.</returns>
         IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
             IDirectoryService directoryService,
-            Folder parent, string
-            collectionType = null);
+            Folder parent,
+            LibraryOptions libraryOptions,
+            string collectionType = null);
 
         /// <summary>
         /// Gets the root folder.
@@ -397,6 +394,9 @@ namespace MediaBrowser.Controller.Library
         /// <returns><c>true</c> if [is audio file] [the specified path]; otherwise, <c>false</c>.</returns>
         bool IsAudioFile(string path);
 
+        bool IsAudioFile(string path, LibraryOptions libraryOptions);
+        bool IsVideoFile(string path, LibraryOptions libraryOptions);
+
         /// <summary>
         /// Gets the season number from path.
         /// </summary>
@@ -453,6 +453,8 @@ namespace MediaBrowser.Controller.Library
         /// <returns>IEnumerable&lt;Folder&gt;.</returns>
         IEnumerable<Folder> GetCollectionFolders(BaseItem item);
 
+        LibraryOptions GetLibraryOptions(BaseItem item);
+
         /// <summary>
         /// Gets the people.
         /// </summary>
@@ -551,7 +553,7 @@ namespace MediaBrowser.Controller.Library
         /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
         bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
 
-        void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, bool refreshLibrary);
+        void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary);
         void RemoveVirtualFolder(string name, bool refreshLibrary);
         void AddMediaPath(string virtualFolderName, string path);
         void RemoveMediaPath(string virtualFolderName, string path);
diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
index ea3199b318..56ec0a2138 100644
--- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs
+++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs
@@ -5,6 +5,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using CommonIO;
+using MediaBrowser.Controller.Configuration;
 
 namespace MediaBrowser.Controller.Library
 {
@@ -51,6 +52,13 @@ namespace MediaBrowser.Controller.Library
             }
         }
 
+        public LibraryOptions LibraryOptions { get; set; }
+
+        public LibraryOptions GetLibraryOptions()
+        {
+            return LibraryOptions ?? (LibraryOptions = (Parent == null ? new LibraryOptions() : BaseItem.LibraryManager.GetLibraryOptions(Parent)));
+        }
+
         /// <summary>
         /// Gets or sets the file system dictionary.
         /// </summary>
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 0462117cb5..e621eafded 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -98,6 +98,7 @@
     <Compile Include="Collections\CollectionCreationOptions.cs" />
     <Compile Include="Collections\CollectionEvents.cs" />
     <Compile Include="Collections\ICollectionManager.cs" />
+    <Compile Include="Configuration\LibraryOptions.cs" />
     <Compile Include="Connect\ConnectSupporterSummary.cs" />
     <Compile Include="Connect\IConnectManager.cs" />
     <Compile Include="Connect\UserLinkResult.cs" />
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index 5ffe3d5daf..3e706f1fa7 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -58,6 +58,12 @@ namespace MediaBrowser.Controller.Playlists
             return true;
         }
 
+        protected override IEnumerable<BaseItem> LoadChildren()
+        {
+            // Save a trip to the database
+            return new List<BaseItem>();
+        }
+
         public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
         {
             return GetPlayableItems(user).Result;
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 58b74ba64a..303ba1acf7 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -180,8 +180,6 @@ namespace MediaBrowser.Model.Configuration
 
         public NameValuePair[] ContentTypes { get; set; }
 
-        public bool EnableAudioArchiveFiles { get; set; }
-        public bool EnableVideoArchiveFiles { get; set; }
         public int RemoteClientBitrateLimit { get; set; }
 
         public AutoOnOff EnableLibraryMonitor { get; set; }
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index 0a70a2cc43..0483a74ed1 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -149,7 +149,7 @@ namespace MediaBrowser.Providers.Manager
                 if (file != null)
                 {
                     var fileLastWriteTime = file.LastWriteTimeUtc;
-                    if (item.EnableForceSaveOnDateModifiedChange && fileLastWriteTime != item.DateModified)
+                    if (item.EnableRefreshOnDateModifiedChange && fileLastWriteTime != item.DateModified)
                     {
                         Logger.Debug("Date modified for {0}. Old date {1} new date {2} Id {3}", item.Path, item.DateModified, fileLastWriteTime, item.Id);
                         requiresRefresh = true;
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index e36be54191..0df8b6c4b7 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -171,7 +171,7 @@ namespace MediaBrowser.Providers.MediaInfo
 
         public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
         {
-            if (!string.IsNullOrWhiteSpace(item.Path))
+            if (item.EnableRefreshOnDateModifiedChange && !string.IsNullOrWhiteSpace(item.Path))
             {
                 var file = directoryService.GetFile(item.Path);
                 if (file != null && file.LastWriteTimeUtc != item.DateModified)
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index fb08f00c19..280e92beb9 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -194,10 +194,13 @@ namespace MediaBrowser.Providers.MediaInfo
 
         public bool HasChanged(IHasMetadata item, IDirectoryService directoryService)
         {
-            var file = directoryService.GetFile(item.Path);
-            if (file != null && file.LastWriteTimeUtc != item.DateModified)
+            if (item.EnableRefreshOnDateModifiedChange)
             {
-                return true;
+                var file = directoryService.GetFile(item.Path);
+                if (file != null && file.LastWriteTimeUtc != item.DateModified)
+                {
+                    return true;
+                }
             }
 
             return false;
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 055fde504b..b00303f295 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -556,7 +556,12 @@ namespace MediaBrowser.Server.Implementations.Library
             return ResolvePath(fileInfo, new DirectoryService(_logger, _fileSystem), null, parent);
         }
 
-        private BaseItem ResolvePath(FileSystemMetadata fileInfo, IDirectoryService directoryService, IItemResolver[] resolvers, Folder parent = null, string collectionType = null)
+        private BaseItem ResolvePath(FileSystemMetadata fileInfo,
+            IDirectoryService directoryService,
+            IItemResolver[] resolvers,
+            Folder parent = null,
+            string collectionType = null,
+            LibraryOptions libraryOptions = null)
         {
             if (fileInfo == null)
             {
@@ -575,7 +580,8 @@ namespace MediaBrowser.Server.Implementations.Library
                 Parent = parent,
                 Path = fullPath,
                 FileInfo = fileInfo,
-                CollectionType = collectionType
+                CollectionType = collectionType,
+                LibraryOptions = libraryOptions
             };
 
             // Return null if ignore rules deem that we should do so
@@ -653,12 +659,17 @@ namespace MediaBrowser.Server.Implementations.Library
             return !args.ContainsFileSystemEntryByName(".ignore");
         }
 
-        public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType)
+        public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, LibraryOptions libraryOptions, string collectionType)
         {
-            return ResolvePaths(files, directoryService, parent, collectionType, EntityResolvers);
+            return ResolvePaths(files, directoryService, parent, libraryOptions, collectionType, EntityResolvers);
         }
 
-        public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType, IItemResolver[] resolvers)
+        public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
+            IDirectoryService directoryService,
+            Folder parent, 
+            LibraryOptions libraryOptions,
+            string collectionType,
+            IItemResolver[] resolvers)
         {
             var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList();
 
@@ -679,22 +690,27 @@ namespace MediaBrowser.Server.Implementations.Library
                         {
                             ResolverHelper.SetInitialItemValues(item, parent, _fileSystem, this, directoryService);
                         }
-                        items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType, resolvers));
+                        items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType, resolvers, libraryOptions));
                         return items;
                     }
                 }
             }
 
-            return ResolveFileList(fileList, directoryService, parent, collectionType, resolvers);
+            return ResolveFileList(fileList, directoryService, parent, collectionType, resolvers, libraryOptions);
         }
 
-        private IEnumerable<BaseItem> ResolveFileList(IEnumerable<FileSystemMetadata> fileList, IDirectoryService directoryService, Folder parent, string collectionType, IItemResolver[] resolvers)
+        private IEnumerable<BaseItem> ResolveFileList(IEnumerable<FileSystemMetadata> fileList,
+            IDirectoryService directoryService,
+            Folder parent,
+            string collectionType,
+            IItemResolver[] resolvers,
+            LibraryOptions libraryOptions)
         {
             return fileList.Select(f =>
             {
                 try
                 {
-                    return ResolvePath(f, directoryService, resolvers, parent, collectionType);
+                    return ResolvePath(f, directoryService, resolvers, parent, collectionType, libraryOptions);
                 }
                 catch (Exception ex)
                 {
@@ -1891,6 +1907,15 @@ namespace MediaBrowser.Server.Implementations.Library
                 .Where(i => string.Equals(i.Path, item.Path, StringComparison.OrdinalIgnoreCase) || i.PhysicalLocations.Contains(item.Path, StringComparer.OrdinalIgnoreCase));
         }
 
+        public LibraryOptions GetLibraryOptions(BaseItem item)
+        {
+            var collectionFolder = GetCollectionFolders(item)
+                .OfType<CollectionFolder>()
+                .FirstOrDefault();
+
+            return collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions();
+        }
+
         public string GetContentType(BaseItem item)
         {
             string configuredContentType = GetConfiguredContentType(item, false);
@@ -2242,18 +2267,28 @@ namespace MediaBrowser.Server.Implementations.Library
             return item;
         }
 
-        public bool IsVideoFile(string path)
+        public bool IsVideoFile(string path, LibraryOptions libraryOptions)
         {
-            var resolver = new VideoResolver(GetNamingOptions(), new PatternsLogger());
+            var resolver = new VideoResolver(GetNamingOptions(libraryOptions), new PatternsLogger());
             return resolver.IsVideoFile(path);
         }
 
-        public bool IsAudioFile(string path)
+        public bool IsVideoFile(string path)
+        {
+            return IsVideoFile(path, new LibraryOptions());
+        }
+
+        public bool IsAudioFile(string path, LibraryOptions libraryOptions)
         {
-            var parser = new AudioFileParser(GetNamingOptions());
+            var parser = new AudioFileParser(GetNamingOptions(libraryOptions));
             return parser.IsAudioFile(path);
         }
 
+        public bool IsAudioFile(string path)
+        {
+            return IsAudioFile(path, new LibraryOptions());
+        }
+
         public int? GetSeasonNumberFromPath(string path)
         {
             return new SeasonPathParser(GetNamingOptions(), new RegexProvider()).Parse(path, true, true).SeasonNumber;
@@ -2379,6 +2414,11 @@ namespace MediaBrowser.Server.Implementations.Library
         }
 
         public NamingOptions GetNamingOptions()
+        {
+            return GetNamingOptions(new LibraryOptions());
+        }
+
+        public NamingOptions GetNamingOptions(LibraryOptions libraryOptions)
         {
             var options = new ExtendedNamingOptions();
 
@@ -2386,13 +2426,13 @@ namespace MediaBrowser.Server.Implementations.Library
             options.AudioFileExtensions.Remove(".m3u");
             options.AudioFileExtensions.Remove(".wpl");
 
-            if (!ConfigurationManager.Configuration.EnableAudioArchiveFiles)
+            if (!libraryOptions.EnableAudioArchiveFiles)
             {
                 options.AudioFileExtensions.Remove(".rar");
                 options.AudioFileExtensions.Remove(".zip");
             }
 
-            if (!ConfigurationManager.Configuration.EnableVideoArchiveFiles)
+            if (!libraryOptions.EnableVideoArchiveFiles)
             {
                 options.VideoFileExtensions.Remove(".rar");
                 options.VideoFileExtensions.Remove(".zip");
@@ -2443,7 +2483,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 new GenericVideoResolver<Trailer>(this)
             };
 
-            return ResolvePaths(files, directoryService, null, null, resolvers)
+            return ResolvePaths(files, directoryService, null, new LibraryOptions(), null, resolvers)
                 .OfType<Trailer>()
                 .Select(video =>
                 {
@@ -2487,7 +2527,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 files.AddRange(currentVideo.Extras.Where(i => !string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => _fileSystem.GetFileInfo(i.Path)));
             }
 
-            return ResolvePaths(files, directoryService, null, null)
+            return ResolvePaths(files, directoryService, null, new LibraryOptions(), null)
                 .OfType<Video>()
                 .Select(video =>
                 {
@@ -2665,7 +2705,7 @@ namespace MediaBrowser.Server.Implementations.Library
             throw new InvalidOperationException();
         }
 
-        public void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, bool refreshLibrary)
+        public void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, LibraryOptions options, bool refreshLibrary)
         {
             if (string.IsNullOrWhiteSpace(name))
             {
@@ -2708,6 +2748,8 @@ namespace MediaBrowser.Server.Implementations.Library
                     }
                 }
 
+                CollectionFolder.SaveLibraryOptions(virtualFolderPath, options);
+
                 if (mediaPaths != null)
                 {
                     foreach (var path in mediaPaths)
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
index b4cda39cd2..039a17100a 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
@@ -37,14 +37,16 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
 
             if (!args.IsDirectory)
             {
-                if (_libraryManager.IsAudioFile(args.Path))
+                var libraryOptions = args.GetLibraryOptions();
+
+                if (_libraryManager.IsAudioFile(args.Path, libraryOptions))
                 {
                     var collectionType = args.GetCollectionType();
 
                     var isMixed = string.IsNullOrWhiteSpace(collectionType);
 
                     // For conflicting extensions, give priority to videos
-                    if (isMixed && _libraryManager.IsVideoFile(args.Path))
+                    if (isMixed && _libraryManager.IsVideoFile(args.Path, libraryOptions))
                     {
                         return null;
                     }
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index 9f8293cb5b..546f64d3c3 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -10,6 +10,7 @@ using System;
 using System.Collections.Generic;
 using System.IO;
 using CommonIO;
+using MediaBrowser.Controller.Configuration;
 
 namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
 {
@@ -72,12 +73,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
         /// <summary>
         /// Determine if the supplied file data points to a music album
         /// </summary>
-        /// <param name="path">The path.</param>
-        /// <param name="directoryService">The directory service.</param>
-        /// <returns><c>true</c> if [is music album] [the specified data]; otherwise, <c>false</c>.</returns>
-        public bool IsMusicAlbum(string path, IDirectoryService directoryService)
+        public bool IsMusicAlbum(string path, IDirectoryService directoryService, LibraryOptions libraryOptions)
         {
-            return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, _libraryManager);
+            return ContainsMusic(directoryService.GetFileSystemEntries(path), true, directoryService, _logger, _fileSystem, libraryOptions, _libraryManager);
         }
 
         /// <summary>
@@ -91,7 +89,7 @@ namespace MediaBrowser.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)) return true;
+                if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager)) return true;
             }
 
             return false;
@@ -100,18 +98,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
         /// <summary>
         /// Determine if the supplied list contains what we should consider music
         /// </summary>
-        /// <param name="list">The list.</param>
-        /// <param name="allowSubfolders">if set to <c>true</c> [allow subfolders].</param>
-        /// <param name="directoryService">The directory service.</param>
-        /// <param name="logger">The logger.</param>
-        /// <param name="fileSystem">The file system.</param>
-        /// <param name="libraryManager">The library manager.</param>
-        /// <returns><c>true</c> if the specified list contains music; otherwise, <c>false</c>.</returns>
         private bool ContainsMusic(IEnumerable<FileSystemMetadata> list,
             bool allowSubfolders,
             IDirectoryService directoryService,
             ILogger logger,
             IFileSystem fileSystem,
+            LibraryOptions libraryOptions,
             ILibraryManager libraryManager)
         {
             var discSubfolderCount = 0;
@@ -124,11 +116,11 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
                     if (allowSubfolders)
                     {
                         var path = fileSystemInfo.FullName;
-                        var isMultiDisc = IsMultiDiscFolder(path);
+                        var isMultiDisc = IsMultiDiscFolder(path, libraryOptions);
 
                         if (isMultiDisc)
                         {
-                            var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
+                            var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryOptions, libraryManager);
 
                             if (hasMusic)
                             {
@@ -138,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
                         }
                         else
                         {
-                            var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
+                            var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryOptions, libraryManager);
 
                             if (hasMusic)
                             {
@@ -151,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
 
                 var fullName = fileSystemInfo.FullName;
 
-                if (libraryManager.IsAudioFile(fullName))
+                if (libraryManager.IsAudioFile(fullName, libraryOptions))
                 {
                     return true;
                 }
@@ -165,9 +157,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
             return discSubfolderCount > 0;
         }
 
-        private bool IsMultiDiscFolder(string path)
+        private bool IsMultiDiscFolder(string path, LibraryOptions libraryOptions)
         {
-            var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
+            var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions(libraryOptions);
 
             var parser = new AlbumParser(namingOptions, new PatternsLogger());
             var result = parser.ParseMultiPart(path);
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
index e3c991e7ea..e819af06fd 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
@@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
             var albumResolver = new MusicAlbumResolver(_logger, _fileSystem, _libraryManager);
 
             // If we contain an album assume we are an artist folder
-            return args.FileSystemChildren.Where(i => (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService)) ? new MusicArtist() : null;
+            return args.FileSystemChildren.Where(i => (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService, args.GetLibraryOptions())) ? new MusicArtist() : null;
         }
 
     }
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
index 703a338568..d0042a9907 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
@@ -133,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
                     return null;
                 }
 
-                if (LibraryManager.IsVideoFile(args.Path) || videoInfo.IsStub)
+                if (LibraryManager.IsVideoFile(args.Path, args.GetLibraryOptions()) || videoInfo.IsStub)
                 {
                     var path = args.Path;
 
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index 9dd30eddee..09a9a3b4e9 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -6,6 +6,7 @@ using System;
 using System.IO;
 using System.Linq;
 using CommonIO;
+using MediaBrowser.Controller.Configuration;
 
 namespace MediaBrowser.Server.Implementations.Library.Resolvers
 {
@@ -40,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
                         var filename = Path.GetFileNameWithoutExtension(args.Path);
 
                         // Make sure the image doesn't belong to a video file
-                        if (args.DirectoryService.GetFiles(Path.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(i, filename)))
+                        if (args.DirectoryService.GetFiles(Path.GetDirectoryName(args.Path)).Any(i => IsOwnedByMedia(args.GetLibraryOptions(), i, filename)))
                         {
                             return null;
                         }
@@ -56,9 +57,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
             return null;
         }
 
-        private bool IsOwnedByMedia(FileSystemMetadata file, string imageFilename)
+        private bool IsOwnedByMedia(LibraryOptions libraryOptions, FileSystemMetadata file, string imageFilename)
         {
-            if (_libraryManager.IsVideoFile(file.FullName) && imageFilename.StartsWith(Path.GetFileNameWithoutExtension(file.Name), StringComparison.OrdinalIgnoreCase))
+            if (_libraryManager.IsVideoFile(file.FullName, libraryOptions) && imageFilename.StartsWith(Path.GetFileNameWithoutExtension(file.Name), StringComparison.OrdinalIgnoreCase))
             {
                 return true;
             }
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
index 45ba2ddbb3..f1bbc1f327 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -12,6 +12,7 @@ using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using CommonIO;
+using MediaBrowser.Controller.Configuration;
 
 namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
 {
@@ -83,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
                         {
                             return null;
                         }
-                        if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, false))
+                        if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false))
                         {
                             return new Series
                             {
@@ -104,6 +105,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
             IFileSystem fileSystem,
             ILogger logger,
             ILibraryManager libraryManager,
+            LibraryOptions libraryOptions,
             bool isTvContentType)
         {
             foreach (var child in fileSystemChildren)
@@ -134,7 +136,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
                 else
                 {
                     string fullName = child.FullName;
-                    if (libraryManager.IsVideoFile(fullName))
+                    if (libraryManager.IsVideoFile(fullName, libraryOptions))
                     {
                         if (isTvContentType)
                         {
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index ee8ab7c254..4c9b2a4d97 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
 
                 try
                 {
-                    _libraryManager.AddVirtualFolder(recordingFolder.Name, recordingFolder.CollectionType, pathsToCreate.ToArray(), true);
+                    _libraryManager.AddVirtualFolder(recordingFolder.Name, recordingFolder.CollectionType, pathsToCreate.ToArray(), new LibraryOptions(), true);
                 }
                 catch (Exception ex)
                 {
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index c01261d738..bbb36b46e1 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -4041,7 +4041,7 @@ namespace MediaBrowser.Server.Implementations.Persistence
                     ? (CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)
                     : CommandBehavior.SequentialAccess;
 
-                Logger.Debug("GetItemValues: " + cmd.CommandText);
+                //Logger.Debug("GetItemValues: " + cmd.CommandText);
 
                 using (var reader = cmd.ExecuteReader(commandBehavior))
                 {
diff --git a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
index 20324215b8..ff0e4a0e01 100644
--- a/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
+++ b/MediaBrowser.Server.Implementations/Playlists/ManualPlaylistsFolder.cs
@@ -22,7 +22,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
 
         protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
         {
-            return GetRecursiveChildren(i => i is Playlist);
+            return base.GetEligibleChildrenForRecursiveChildren(user).OfType<Playlist>();
         }
 
         public override bool IsHidden
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index ce99f0a240..74438abbcf 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -765,6 +765,7 @@ namespace MediaBrowser.Server.Startup.Common
             UserView.PlaylistManager = PlaylistManager;
             BaseItem.CollectionManager = CollectionManager;
             BaseItem.MediaSourceManager = MediaSourceManager;
+            CollectionFolder.XmlSerializer = XmlSerializer;
         }
 
         /// <summary>