Browse Source

referenced core plugins, fixed some dashboard issues, extracted library manager

LukePulverenti 12 năm trước cách đây
mục cha
commit
af7aa597c3
52 tập tin đã thay đổi với 557 bổ sung337 xóa
  1. 0 1
      BDInfo/BDInfo.csproj
  2. 12 8
      MediaBrowser.Api/EnvironmentService.cs
  3. 12 14
      MediaBrowser.Api/Images/ImageService.cs
  4. 13 23
      MediaBrowser.Api/Library/LibraryService.cs
  5. 9 5
      MediaBrowser.Api/Library/LibraryStructureService.cs
  6. 2 1
      MediaBrowser.Api/MediaBrowser.Api.csproj
  7. 10 2
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  8. 2 1
      MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
  9. 3 3
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  10. 2 2
      MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
  11. 2 2
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  12. 2 2
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  13. 2 2
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  14. 5 3
      MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs
  15. 4 7
      MediaBrowser.Api/UserLibrary/GenresService.cs
  16. 9 3
      MediaBrowser.Api/UserLibrary/ItemsService.cs
  17. 3 4
      MediaBrowser.Api/UserLibrary/PersonsService.cs
  18. 4 7
      MediaBrowser.Api/UserLibrary/StudiosService.cs
  19. 21 20
      MediaBrowser.Api/UserLibrary/UserLibraryService.cs
  20. 5 8
      MediaBrowser.Api/UserLibrary/YearsService.cs
  21. 19 13
      MediaBrowser.Common.Implementations/NetworkManagement/NetworkManager.cs
  22. 39 5
      MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
  23. 2 1
      MediaBrowser.Controller/Entities/BaseItem.cs
  24. 1 1
      MediaBrowser.Controller/Entities/CollectionFolder.cs
  25. 6 6
      MediaBrowser.Controller/Entities/Folder.cs
  26. 1 1
      MediaBrowser.Controller/Entities/Movies/Movie.cs
  27. 1 1
      MediaBrowser.Controller/Entities/User.cs
  28. 1 1
      MediaBrowser.Controller/Entities/UserRootFolder.cs
  29. 11 8
      MediaBrowser.Controller/IO/DirectoryWatchers.cs
  30. 4 2
      MediaBrowser.Controller/IO/FileSystemManager.cs
  31. 5 91
      MediaBrowser.Controller/Kernel.cs
  32. 18 16
      MediaBrowser.Controller/Library/DtoBuilder.cs
  33. 145 0
      MediaBrowser.Controller/Library/ILibraryManager.cs
  34. 1 1
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  35. 9 5
      MediaBrowser.Controller/ScheduledTasks/PeopleValidationTask.cs
  36. 7 6
      MediaBrowser.Controller/ScheduledTasks/RefreshMediaLibraryTask.cs
  37. 3 2
      MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs
  38. 98 16
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  39. 9 0
      MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
  40. 6 2
      MediaBrowser.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs
  41. 7 4
      MediaBrowser.Server.Implementations/ScheduledTasks/Tasks/ImageCleanupTask.cs
  42. 1 0
      MediaBrowser.Server.Implementations/packages.config
  43. 12 14
      MediaBrowser.ServerApplication/ApplicationHost.cs
  44. 6 3
      MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs
  45. 6 3
      MediaBrowser.ServerApplication/MainWindow.xaml.cs
  46. 7 9
      MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj
  47. 2 1
      MediaBrowser.WebDashboard/Html/scripts/site.js
  48. 2 1
      MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
  49. 1 1
      Nuget/MediaBrowser.ApiClient.nuspec
  50. 2 2
      Nuget/MediaBrowser.Common.Internal.nuspec
  51. 1 1
      Nuget/MediaBrowser.Common.nuspec
  52. 2 2
      Nuget/MediaBrowser.Server.Core.nuspec

+ 0 - 1
BDInfo/BDInfo.csproj

@@ -35,7 +35,6 @@
     <Reference Include="Microsoft.CSharp" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="BdInfoExaminer.cs" />
     <Compile Include="BDInfoSettings.cs" />
     <Compile Include="BDROM.cs" />
     <Compile Include="LanguageCodes.cs" />

+ 12 - 8
MediaBrowser.Api/EnvironmentService.cs

@@ -97,18 +97,18 @@ namespace MediaBrowser.Api
                 throw new ArgumentNullException("Path");
             }
 
-            // Reject invalid input
-            if (!Path.IsPathRooted(path))
+            if (path.StartsWith(NetworkPrefix, StringComparison.OrdinalIgnoreCase) && path.LastIndexOf('\\') == 1)
             {
-                throw new ArgumentException(string.Format("Invalid path: {0}", path));
+                return ToOptimizedResult(GetNetworkShares(path).ToList());
             }
 
-            if (path.StartsWith(NetworkPrefix, StringComparison.OrdinalIgnoreCase) && path.LastIndexOf('\\') == 1)
+            // Reject invalid input
+            if (!Path.IsPathRooted(path))
             {
-                return GetNetworkShares(path).ToList();
+                throw new ArgumentException(string.Format("Invalid path: {0}", path));
             }
 
-            return GetFileSystemEntries(request).ToList();
+            return ToOptimizedResult(GetFileSystemEntries(request).ToList());
         }
 
         /// <summary>
@@ -118,7 +118,9 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetDrives request)
         {
-            return GetDrives().ToList();
+            var result = GetDrives().ToList();
+
+            return ToOptimizedResult(result);
         }
 
         /// <summary>
@@ -128,7 +130,9 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetNetworkComputers request)
         {
-            return GetNetworkComputers().ToList();
+            var result = GetNetworkComputers().ToList();
+
+            return ToOptimizedResult(result);
         }
 
         /// <summary>

+ 12 - 14
MediaBrowser.Api/Images/ImageService.cs

@@ -141,13 +141,19 @@ namespace MediaBrowser.Api.Images
         /// </summary>
         private readonly IUserManager _userManager;
 
+        /// <summary>
+        /// The _library manager
+        /// </summary>
+        private readonly ILibraryManager _libraryManager;
+        
         /// <summary>
         /// Initializes a new instance of the <see cref="ImageService" /> class.
         /// </summary>
         /// <param name="userManager">The user manager.</param>
-        public ImageService(IUserManager userManager)
+        public ImageService(IUserManager userManager, ILibraryManager libraryManager)
         {
             _userManager = userManager;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -157,7 +163,7 @@ namespace MediaBrowser.Api.Images
         /// <returns>System.Object.</returns>
         public object Get(GetItemImage request)
         {
-            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager);
+            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager);
 
             return GetImage(request, item);
         }
@@ -181,9 +187,7 @@ namespace MediaBrowser.Api.Images
         /// <returns>System.Object.</returns>
         public object Get(GetYearImage request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetYear(request.Year).Result;
+            var item = _libraryManager.GetYear(request.Year).Result;
 
             return GetImage(request, item);
         }
@@ -195,9 +199,7 @@ namespace MediaBrowser.Api.Images
         /// <returns>System.Object.</returns>
         public object Get(GetStudioImage request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetStudio(request.Name).Result;
+            var item = _libraryManager.GetStudio(request.Name).Result;
 
             return GetImage(request, item);
         }
@@ -209,9 +211,7 @@ namespace MediaBrowser.Api.Images
         /// <returns>System.Object.</returns>
         public object Get(GetPersonImage request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetPerson(request.Name).Result;
+            var item = _libraryManager.GetPerson(request.Name).Result;
 
             return GetImage(request, item);
         }
@@ -223,9 +223,7 @@ namespace MediaBrowser.Api.Images
         /// <returns>System.Object.</returns>
         public object Get(GetGenreImage request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetGenre(request.Name).Result;
+            var item = _libraryManager.GetGenre(request.Name).Result;
 
             return GetImage(request, item);
         }

+ 13 - 23
MediaBrowser.Api/Library/LibraryService.cs

@@ -93,13 +93,14 @@ namespace MediaBrowser.Api.Library
         /// The _app host
         /// </summary>
         private readonly IApplicationHost _appHost;
+        private readonly ILibraryManager _libraryManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="LibraryService" /> class.
         /// </summary>
         /// <param name="appHost">The app host.</param>
         /// <exception cref="System.ArgumentNullException">appHost</exception>
-        public LibraryService(IApplicationHost appHost)
+        public LibraryService(IApplicationHost appHost, ILibraryManager libraryManager)
         {
             if (appHost == null)
             {
@@ -107,6 +108,7 @@ namespace MediaBrowser.Api.Library
             }
 
             _appHost = appHost;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -116,14 +118,12 @@ namespace MediaBrowser.Api.Library
         /// <returns>System.Object.</returns>
         public object Get(GetPerson request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetPerson(request.Name).Result;
+            var item = _libraryManager.GetPerson(request.Name).Result;
 
             // Get everything
             var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
-            
-            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList()).Result;
+
+            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList(), _libraryManager).Result;
 
             return ToOptimizedResult(result);
         }
@@ -135,14 +135,12 @@ namespace MediaBrowser.Api.Library
         /// <returns>System.Object.</returns>
         public object Get(GetGenre request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetGenre(request.Name).Result;
+            var item = _libraryManager.GetGenre(request.Name).Result;
 
             // Get everything
             var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
 
-            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList()).Result;
+            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList(), _libraryManager).Result;
 
             return ToOptimizedResult(result);
         }
@@ -154,14 +152,12 @@ namespace MediaBrowser.Api.Library
         /// <returns>System.Object.</returns>
         public object Get(GetStudio request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetStudio(request.Name).Result;
+            var item = _libraryManager.GetStudio(request.Name).Result;
 
             // Get everything
             var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
 
-            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList()).Result;
+            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList(), _libraryManager).Result;
 
             return ToOptimizedResult(result);
         }
@@ -173,14 +169,12 @@ namespace MediaBrowser.Api.Library
         /// <returns>System.Object.</returns>
         public object Get(GetYear request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var item = kernel.LibraryManager.GetYear(request.Year).Result;
+            var item = _libraryManager.GetYear(request.Year).Result;
 
             // Get everything
             var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true));
 
-            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList()).Result;
+            var result = new DtoBuilder(Logger).GetDtoBaseItem(item, fields.ToList(), _libraryManager).Result;
 
             return ToOptimizedResult(result);
         }
@@ -192,9 +186,7 @@ namespace MediaBrowser.Api.Library
         /// <returns>System.Object.</returns>
         public object Get(GetPhyscialPaths request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var result = kernel.RootFolder.Children.SelectMany(c => c.ResolveArgs.PhysicalLocations).ToList();
+            var result = _libraryManager.RootFolder.Children.SelectMany(c => c.ResolveArgs.PhysicalLocations).ToList();
 
             return ToOptimizedResult(result);
         }
@@ -206,8 +198,6 @@ namespace MediaBrowser.Api.Library
         /// <returns>System.Object.</returns>
         public object Get(GetItemTypes request)
         {
-            var kernel = (Kernel)Kernel;
-
             var allTypes = _appHost.AllConcreteTypes.Where(t => t.IsSubclassOf(typeof(BaseItem)));
 
             if (request.HasInternetProvider)

+ 9 - 5
MediaBrowser.Api/Library/LibraryStructureService.cs

@@ -141,13 +141,18 @@ namespace MediaBrowser.Api.Library
         /// </summary>
         private readonly IUserManager _userManager;
 
+        /// <summary>
+        /// The _library manager
+        /// </summary>
+        private readonly ILibraryManager _libraryManager;
+        
         /// <summary>
         /// Initializes a new instance of the <see cref="LibraryService" /> class.
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
         /// <param name="userManager">The user manager.</param>
         /// <exception cref="System.ArgumentNullException">appHost</exception>
-        public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager)
+        public LibraryStructureService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
         {
             if (appPaths == null)
             {
@@ -156,6 +161,7 @@ namespace MediaBrowser.Api.Library
 
             _userManager = userManager;
             _appPaths = appPaths;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -165,11 +171,9 @@ namespace MediaBrowser.Api.Library
         /// <returns>System.Object.</returns>
         public object Get(GetVirtualFolders request)
         {
-            var kernel = (Kernel)Kernel;
-
             if (string.IsNullOrEmpty(request.UserId))
             {
-                var result = kernel.LibraryManager.GetDefaultVirtualFolders().ToList();
+                var result = _libraryManager.GetDefaultVirtualFolders().ToList();
 
                 return ToOptimizedResult(result);
             }
@@ -177,7 +181,7 @@ namespace MediaBrowser.Api.Library
             {
                 var user = _userManager.GetUserById(new Guid(request.UserId));
 
-                var result = kernel.LibraryManager.GetVirtualFolders(user).ToList();
+                var result = _libraryManager.GetVirtualFolders(user).ToList();
 
                 return ToOptimizedResult(result);
             }

+ 2 - 1
MediaBrowser.Api/MediaBrowser.Api.csproj

@@ -140,7 +140,8 @@
   <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
-    <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\MediaBrowser.ServerApplication\CorePlugins\" /y</PostBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 10 - 2
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -34,6 +34,12 @@ namespace MediaBrowser.Api.Playback
         /// </summary>
         /// <value>The user manager.</value>
         protected IUserManager UserManager { get; set; }
+
+        /// <summary>
+        /// Gets or sets the library manager.
+        /// </summary>
+        /// <value>The library manager.</value>
+        protected ILibraryManager LibraryManager { get; set; }
         
         /// <summary>
         /// Gets the server kernel.
@@ -49,10 +55,12 @@ namespace MediaBrowser.Api.Playback
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
         /// <param name="userManager">The user manager.</param>
-        protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager)
+        /// <param name="libraryManager">The library manager.</param>
+        protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
         {
             ApplicationPaths = appPaths;
             UserManager = userManager;
+            LibraryManager = libraryManager;
         }
 
         /// <summary>
@@ -614,7 +622,7 @@ namespace MediaBrowser.Api.Playback
         /// <returns>StreamState.</returns>
         protected StreamState GetState(StreamRequest request)
         {
-            var item = DtoBuilder.GetItemByClientId(request.Id, UserManager);
+            var item = DtoBuilder.GetItemByClientId(request.Id, UserManager, LibraryManager);
 
             var media = (IHasMediaStreams)item;
 

+ 2 - 1
MediaBrowser.Api/Playback/Hls/AudioHlsService.cs

@@ -15,7 +15,8 @@ namespace MediaBrowser.Api.Playback.Hls
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
         /// <param name="userManager">The user manager.</param>
-        public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager) : base(appPaths, userManager)
+        public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
+            : base(appPaths, userManager, libraryManager)
         {
         }
 

+ 3 - 3
MediaBrowser.Api/Playback/Hls/BaseHlsService.cs

@@ -16,9 +16,9 @@ namespace MediaBrowser.Api.Playback.Hls
         /// The segment file prefix
         /// </summary>
         public const string SegmentFilePrefix = "segment-";
-        
-        protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager)
-            : base(appPaths, userManager)
+
+        protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
+            : base(appPaths, userManager, libraryManager)
         {
         }
 

+ 2 - 2
MediaBrowser.Api/Playback/Hls/VideoHlsService.cs

@@ -11,8 +11,8 @@ namespace MediaBrowser.Api.Playback.Hls
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
         /// <param name="userManager">The user manager.</param>
-        public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager)
-            : base(appPaths, userManager)
+        public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
+            : base(appPaths, userManager, libraryManager)
         {
         }
 

+ 2 - 2
MediaBrowser.Api/Playback/Progressive/AudioService.cs

@@ -28,8 +28,8 @@ namespace MediaBrowser.Api.Playback.Progressive
         /// Initializes a new instance of the <see cref="BaseProgressiveStreamingService" /> class.
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
-        public AudioService(IServerApplicationPaths appPaths, IUserManager userManager)
-            : base(appPaths, userManager)
+        public AudioService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
+            : base(appPaths, userManager, libraryManager)
         {
         }
 

+ 2 - 2
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -18,8 +18,8 @@ namespace MediaBrowser.Api.Playback.Progressive
         /// Initializes a new instance of the <see cref="BaseProgressiveStreamingService" /> class.
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
-        protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager)
-            : base(appPaths, userManager)
+        protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
+            : base(appPaths, userManager, libraryManager)
         {
         }
 

+ 2 - 2
MediaBrowser.Api/Playback/Progressive/VideoService.cs

@@ -34,8 +34,8 @@ namespace MediaBrowser.Api.Playback.Progressive
         /// Initializes a new instance of the <see cref="BaseProgressiveStreamingService" /> class.
         /// </summary>
         /// <param name="appPaths">The app paths.</param>
-        public VideoService(IServerApplicationPaths appPaths, IUserManager userManager)
-            : base(appPaths, userManager)
+        public VideoService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
+            : base(appPaths, userManager, libraryManager)
         {
         }
 

+ 5 - 3
MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs

@@ -24,14 +24,16 @@ namespace MediaBrowser.Api.UserLibrary
         /// The _user manager
         /// </summary>
         protected readonly IUserManager UserManager;
+        protected readonly ILibraryManager LibraryManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseItemsByNameService{TItemType}" /> class.
         /// </summary>
         /// <param name="userManager">The user manager.</param>
-        protected BaseItemsByNameService(IUserManager userManager)
+        protected BaseItemsByNameService(IUserManager userManager, ILibraryManager libraryManager)
         {
             UserManager = userManager;
+            LibraryManager = libraryManager;
         }
 
         /// <summary>
@@ -43,7 +45,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = UserManager.GetUserById(request.UserId);
 
-            var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, UserManager, user.Id);
+            var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, UserManager, LibraryManager, user.Id);
 
             IEnumerable<BaseItem> items;
 
@@ -126,7 +128,7 @@ namespace MediaBrowser.Api.UserLibrary
                 return null;
             }
 
-            var dto = await new DtoBuilder(Logger).GetDtoBaseItem(item, user, fields).ConfigureAwait(false);
+            var dto = await new DtoBuilder(Logger).GetDtoBaseItem(item, user, fields, LibraryManager).ConfigureAwait(false);
 
             dto.ChildCount = stub.Item2();
 

+ 4 - 7
MediaBrowser.Api/UserLibrary/GenresService.cs

@@ -1,6 +1,4 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using ServiceStack.ServiceHost;
 using System;
@@ -24,7 +22,8 @@ namespace MediaBrowser.Api.UserLibrary
     /// </summary>
     public class GenresService : BaseItemsByNameService<Genre>
     {
-        public GenresService(IUserManager userManager) : base(userManager)
+        public GenresService(IUserManager userManager, ILibraryManager libraryManager)
+            : base(userManager, libraryManager)
         {
         }
 
@@ -64,9 +63,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>Task{Genre}.</returns>
         protected override Task<Genre> GetEntity(string name)
         {
-            var kernel = (Kernel)Kernel;
-
-            return kernel.LibraryManager.GetGenre(name);
+            return LibraryManager.GetGenre(name);
         }
     }
 }

+ 9 - 3
MediaBrowser.Api/UserLibrary/ItemsService.cs

@@ -150,13 +150,19 @@ namespace MediaBrowser.Api.UserLibrary
         /// </summary>
         private readonly IUserManager _userManager;
 
+        /// <summary>
+        /// The _library manager
+        /// </summary>
+        private readonly ILibraryManager _libraryManager;
+        
         /// <summary>
         /// Initializes a new instance of the <see cref="ItemsService" /> class.
         /// </summary>
         /// <param name="userManager">The user manager.</param>
-        public ItemsService(IUserManager userManager)
+        public ItemsService(IUserManager userManager, ILibraryManager libraryManager)
         {
             _userManager = userManager;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -203,7 +209,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var dtoBuilder = new DtoBuilder(Logger);
 
-            var returnItems = await Task.WhenAll(pagedItems.Select(i => dtoBuilder.GetDtoBaseItem(i, user, fields))).ConfigureAwait(false);
+            var returnItems = await Task.WhenAll(pagedItems.Select(i => dtoBuilder.GetDtoBaseItem(i, user, fields, _libraryManager))).ConfigureAwait(false);
 
             return new ItemsResult
             {
@@ -221,7 +227,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <exception cref="System.InvalidOperationException"></exception>
         private IEnumerable<BaseItem> GetItemsToSerialize(GetItems request, User user)
         {
-            var item = string.IsNullOrEmpty(request.ParentId) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.ParentId, _userManager, user.Id);
+            var item = string.IsNullOrEmpty(request.ParentId) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.ParentId, _userManager, _libraryManager, user.Id);
 
             // Default list type = children
 

+ 3 - 4
MediaBrowser.Api/UserLibrary/PersonsService.cs

@@ -29,7 +29,8 @@ namespace MediaBrowser.Api.UserLibrary
     /// </summary>
     public class PersonsService : BaseItemsByNameService<Person>
     {
-        public PersonsService(IUserManager userManager) : base(userManager)
+        public PersonsService(IUserManager userManager, ILibraryManager libraryManager)
+            : base(userManager, libraryManager)
         {
         }
 
@@ -98,9 +99,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>Task{Genre}.</returns>
         protected override Task<Person> GetEntity(string name)
         {
-            var kernel = (Kernel)Kernel;
-
-            return kernel.LibraryManager.GetPerson(name);
+            return LibraryManager.GetPerson(name);
         }
     }
 }

+ 4 - 7
MediaBrowser.Api/UserLibrary/StudiosService.cs

@@ -1,5 +1,4 @@
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using ServiceStack.ServiceHost;
 using System;
@@ -23,8 +22,8 @@ namespace MediaBrowser.Api.UserLibrary
     /// </summary>
     public class StudiosService : BaseItemsByNameService<Studio>
     {
-        public StudiosService(IUserManager userManager)
-            : base(userManager)
+        public StudiosService(IUserManager userManager, ILibraryManager libraryManager)
+            : base(userManager, libraryManager)
         {
         }
 
@@ -64,9 +63,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>Task{Studio}.</returns>
         protected override Task<Studio> GetEntity(string name)
         {
-            var kernel = (Kernel)Kernel;
-
-            return kernel.LibraryManager.GetStudio(name);
+            return LibraryManager.GetStudio(name);
         }
     }
 }

+ 21 - 20
MediaBrowser.Api/UserLibrary/UserLibraryService.cs

@@ -316,13 +316,15 @@ namespace MediaBrowser.Api.UserLibrary
         /// The _user manager
         /// </summary>
         private readonly IUserManager _userManager;
+
+        private readonly ILibraryManager _libraryManager;
         
         /// <summary>
         /// Initializes a new instance of the <see cref="UserLibraryService" /> class.
         /// </summary>
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
-        public UserLibraryService(IJsonSerializer jsonSerializer, IUserManager userManager)
+        public UserLibraryService(IJsonSerializer jsonSerializer, IUserManager userManager, ILibraryManager libraryManager)
             : base()
         {
             if (jsonSerializer == null)
@@ -332,6 +334,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             _jsonSerializer = jsonSerializer;
             _userManager = userManager;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -343,7 +346,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             // Get everything
             var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
@@ -352,7 +355,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var dtoBuilder = new DtoBuilder(Logger);
 
-            var items = movie.SpecialFeatures.Select(i => dtoBuilder.GetDtoBaseItem(item, user, fields)).AsParallel().Select(t => t.Result).ToList();
+            var items = movie.SpecialFeatures.Select(i => dtoBuilder.GetDtoBaseItem(item, user, fields, _libraryManager)).AsParallel().Select(t => t.Result).ToList();
 
             return ToOptimizedResult(items);
         }
@@ -366,14 +369,14 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             // Get everything
             var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
 
             var dtoBuilder = new DtoBuilder(Logger);
 
-            var items = item.LocalTrailers.Select(i => dtoBuilder.GetDtoBaseItem(item, user, fields)).AsParallel().Select(t => t.Result).ToList();
+            var items = item.LocalTrailers.Select(i => dtoBuilder.GetDtoBaseItem(item, user, fields, _libraryManager)).AsParallel().Select(t => t.Result).ToList();
 
             return ToOptimizedResult(items);
         }
@@ -387,14 +390,14 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = string.IsNullOrEmpty(request.Id) ? user.RootFolder : DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             // Get everything
             var fields = Enum.GetNames(typeof(ItemFields)).Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)).ToList();
 
             var dtoBuilder = new DtoBuilder(Logger);
 
-            var result = dtoBuilder.GetDtoBaseItem(item, user, fields).Result;
+            var result = dtoBuilder.GetDtoBaseItem(item, user, fields, _libraryManager).Result;
 
             return ToOptimizedResult(result);
         }
@@ -410,7 +413,7 @@ namespace MediaBrowser.Api.UserLibrary
 
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             var result = kernel.IntroProviders.SelectMany(i => i.GetIntros(item, user));
 
@@ -429,15 +432,13 @@ namespace MediaBrowser.Api.UserLibrary
             var userId = new Guid(pathInfo.GetArgumentValue<string>(1));
             var itemId = pathInfo.GetArgumentValue<string>(3);
 
-            var kernel = (Kernel)Kernel;
-
             var user = _userManager.GetUserById(userId);
 
-            var item = (Folder)DtoBuilder.GetItemByClientId(itemId, _userManager, user.Id);
+            var item = (Folder)DtoBuilder.GetItemByClientId(itemId, _userManager, _libraryManager, user.Id);
 
             var displayPreferences = _jsonSerializer.DeserializeFromStream<DisplayPreferences>(request.RequestStream);
 
-            var task = kernel.LibraryManager.SaveDisplayPreferencesForFolder(user, item, displayPreferences);
+            var task = _libraryManager.SaveDisplayPreferencesForFolder(user, item, displayPreferences);
 
             Task.WaitAll(task);
         }
@@ -450,7 +451,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             // Get the user data for this item
             var data = item.GetUserData(user, true);
@@ -471,7 +472,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             // Get the user data for this item
             var data = item.GetUserData(user, true);
@@ -492,7 +493,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             // Get the user data for this item
             var data = item.GetUserData(user, true);
@@ -512,7 +513,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = (Folder)DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             // Get the user data for this item
             var data = item.GetUserData(user, true);
@@ -545,7 +546,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             _userManager.OnPlaybackStart(user, item, ClientType.Other, string.Empty);
         }
@@ -558,7 +559,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             var task = _userManager.OnPlaybackProgress(user, item, request.PositionTicks, ClientType.Other, string.Empty);
 
@@ -573,7 +574,7 @@ namespace MediaBrowser.Api.UserLibrary
         {
             var user = _userManager.GetUserById(request.UserId);
 
-            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, user.Id);
+            var item = DtoBuilder.GetItemByClientId(request.Id, _userManager, _libraryManager, user.Id);
 
             var task = _userManager.OnPlaybackStopped(user, item, request.PositionTicks, ClientType.Other, string.Empty);
 
@@ -602,7 +603,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>Task.</returns>
         private Task UpdatePlayedStatus(User user, string itemId, bool wasPlayed)
         {
-            var item = DtoBuilder.GetItemByClientId(itemId, _userManager, user.Id);
+            var item = DtoBuilder.GetItemByClientId(itemId, _userManager, _libraryManager, user.Id);
 
             return item.SetPlayedStatus(user, wasPlayed, _userManager);
         }

+ 5 - 8
MediaBrowser.Api/UserLibrary/YearsService.cs

@@ -1,6 +1,4 @@
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using ServiceStack.ServiceHost;
 using System;
@@ -29,8 +27,9 @@ namespace MediaBrowser.Api.UserLibrary
         /// The us culture
         /// </summary>
         private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
-
-        public YearsService(IUserManager userManager) : base(userManager)
+        
+        public YearsService(IUserManager userManager, ILibraryManager libraryManager)
+            : base(userManager, libraryManager)
         {
         }
 
@@ -70,9 +69,7 @@ namespace MediaBrowser.Api.UserLibrary
         /// <returns>Task{Studio}.</returns>
         protected override Task<Year> GetEntity(string name)
         {
-            var kernel = (Kernel)Kernel;
-
-            return kernel.LibraryManager.GetYear(int.Parse(name, UsCulture));
+            return LibraryManager.GetYear(int.Parse(name, UsCulture));
         }
     }
 }

+ 19 - 13
MediaBrowser.Common.Implementations/NetworkManagement/NetworkManager.cs

@@ -244,21 +244,27 @@ namespace MediaBrowser.Common.Implementations.NetworkManagement
         /// <exception cref="System.ArgumentException">Unknown share type</exception>
         private NetworkShareType ToNetworkShareType(ShareType shareType)
         {
-            switch (shareType)
+            if (shareType.HasFlag(ShareType.Special))
             {
-                case ShareType.Device:
-                    return NetworkShareType.Device;
-                case ShareType.Disk :
-                    return NetworkShareType.Disk;
-                case ShareType.IPC :
-                    return NetworkShareType.Ipc;
-                case ShareType.Printer :
-                    return NetworkShareType.Printer;
-                case ShareType.Special:
-                    return NetworkShareType.Special;
-                default:
-                    throw new ArgumentException("Unknown share type");
+                return NetworkShareType.Special;
             }
+            if (shareType.HasFlag(ShareType.Device))
+            {
+                return NetworkShareType.Device;
+            }
+            if (shareType.HasFlag(ShareType.Disk))
+            {
+                return NetworkShareType.Disk;
+            }
+            if (shareType.HasFlag(ShareType.IPC))
+            {
+                return NetworkShareType.Ipc;
+            }
+            if (shareType.HasFlag(ShareType.Printer))
+            {
+                return NetworkShareType.Printer;
+            }
+            throw new ArgumentException("Unknown share type");
         }
 
         /// <summary>

+ 39 - 5
MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs

@@ -65,6 +65,31 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         /// <param name="serverManager">The server manager.</param>
         public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IServerManager serverManager)
         {
+            if (scheduledTask == null)
+            {
+                throw new ArgumentNullException("scheduledTask");
+            }
+            if (applicationPaths == null)
+            {
+                throw new ArgumentNullException("applicationPaths");
+            }
+            if (taskManager == null)
+            {
+                throw new ArgumentNullException("taskManager");
+            }
+            if (jsonSerializer == null)
+            {
+                throw new ArgumentNullException("jsonSerializer");
+            }
+            if (logger == null)
+            {
+                throw new ArgumentNullException("logger");
+            }
+            if (serverManager == null)
+            {
+                throw new ArgumentNullException("serverManager");
+            }
+
             ScheduledTask = scheduledTask;
             ApplicationPaths = applicationPaths;
             TaskManager = taskManager;
@@ -316,7 +341,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
 
             try
             {
-                await System.Threading.Tasks.Task.Run(async () => await ScheduledTask.Execute(CurrentCancellationTokenSource.Token, progress).ConfigureAwait(false)).ConfigureAwait(false);
+                await ExecuteTask(CurrentCancellationTokenSource.Token, progress).ConfigureAwait(false);
 
                 status = TaskCompletionStatus.Completed;
             }
@@ -334,8 +359,6 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
             var startTime = CurrentExecutionStartTime;
             var endTime = DateTime.UtcNow;
 
-            ServerManager.SendWebSocketMessage("ScheduledTaskEndExecute", LastExecutionResult);
-
             progress.ProgressChanged -= progress_ProgressChanged;
             CurrentCancellationTokenSource.Dispose();
             CurrentCancellationTokenSource = null;
@@ -344,6 +367,11 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
             OnTaskCompleted(startTime, endTime, status);
         }
 
+        private Task ExecuteTask(CancellationToken cancellationToken, IProgress<double> progress)
+        {
+            return Task.Run(async () => await ScheduledTask.Execute(cancellationToken, progress).ConfigureAwait(false));
+        }
+
         /// <summary>
         /// Progress_s the progress changed.
         /// </summary>
@@ -482,7 +510,8 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
         /// <param name="startTime">The start time.</param>
         /// <param name="endTime">The end time.</param>
         /// <param name="status">The status.</param>
-        private void OnTaskCompleted(DateTime startTime, DateTime endTime, TaskCompletionStatus status)
+        /// <param name="sendNotification">if set to <c>true</c> [send notification].</param>
+        private void OnTaskCompleted(DateTime startTime, DateTime endTime, TaskCompletionStatus status, bool sendNotification = true)
         {
             var elapsedTime = endTime - startTime;
 
@@ -500,6 +529,11 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
             JsonSerializer.SerializeToFile(result, GetHistoryFilePath());
 
             LastExecutionResult = result;
+
+            if (sendNotification)
+            {
+                ServerManager.SendWebSocketMessage("ScheduledTaskEndExecute", result);
+            }
         }
 
         /// <summary>
@@ -523,7 +557,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks
 
                 if (State == TaskState.Running)
                 {
-                    OnTaskCompleted(CurrentExecutionStartTime, DateTime.UtcNow, TaskCompletionStatus.Aborted);
+                    OnTaskCompleted(CurrentExecutionStartTime, DateTime.UtcNow, TaskCompletionStatus.Aborted, false);
                 }
 
                 if (CurrentCancellationTokenSource != null)

+ 2 - 1
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -95,6 +95,7 @@ namespace MediaBrowser.Controller.Entities
         /// The logger
         /// </summary>
         protected static internal ILogger Logger { get; internal set; }
+        protected static internal ILibraryManager LibraryManager { get; internal set; }
 
         /// <summary>
         /// Returns a <see cref="System.String" /> that represents this instance.
@@ -613,7 +614,7 @@ namespace MediaBrowser.Controller.Entities
                 return new List<Video> { };
             }
 
-            return Kernel.Instance.LibraryManager.GetItems<Video>(files, null).Select(video =>
+            return LibraryManager.ResolvePaths<Video>(files, null).Select(video =>
             {
                 // Try to retrieve it from the db. If we don't find it, use the resolved version
                 var dbItem = Kernel.Instance.ItemRepository.RetrieveItem(video.Id) as Video;

+ 1 - 1
MediaBrowser.Controller/Entities/CollectionFolder.cs

@@ -88,7 +88,7 @@ namespace MediaBrowser.Controller.Entities
                 }
 
                 var ourChildren =
-                    Kernel.Instance.RootFolder.Children.OfType<Folder>()
+                    LibraryManager.RootFolder.Children.OfType<Folder>()
                           .Where(i => folderIds.Contains(i.Id))
                           .SelectMany(c => c.Children);
 

+ 6 - 6
MediaBrowser.Controller/Entities/Folder.cs

@@ -317,7 +317,7 @@ namespace MediaBrowser.Controller.Entities
                     {
                         try
                         {
-                            return Kernel.Instance.LibraryManager.GetPerson(i).Result;
+                            return LibraryManager.GetPerson(i).Result;
                         }
                         catch (IOException ex)
                         {
@@ -359,7 +359,7 @@ namespace MediaBrowser.Controller.Entities
                     {
                         try
                         {
-                            return Kernel.Instance.LibraryManager.GetStudio(i).Result;
+                            return LibraryManager.GetStudio(i).Result;
                         }
                         catch (IOException ex)
                         {
@@ -399,7 +399,7 @@ namespace MediaBrowser.Controller.Entities
                         {
                             try
                             {
-                                return Kernel.Instance.LibraryManager.GetGenre(i).Result;
+                                return LibraryManager.GetGenre(i).Result;
                             }
                             catch (IOException ex)
                             {
@@ -440,7 +440,7 @@ namespace MediaBrowser.Controller.Entities
                     {
                         try
                         {
-                            return Kernel.Instance.LibraryManager.GetYear(i).Result;
+                            return LibraryManager.GetYear(i).Result;
                         }
                         catch (IOException ex)
                         {
@@ -768,7 +768,7 @@ namespace MediaBrowser.Controller.Entities
                 IndexCache.Clear();
 
                 //and fire event
-                Kernel.Instance.LibraryManager.OnLibraryChanged(changedArgs);
+                LibraryManager.ReportLibraryChanged(changedArgs);
             }
 
             progress.Report(15);
@@ -860,7 +860,7 @@ namespace MediaBrowser.Controller.Entities
                 return new List<BaseItem> { };
             }
 
-            return Kernel.Instance.LibraryManager.GetItems<BaseItem>(fileSystemChildren, this);
+            return LibraryManager.ResolvePaths<BaseItem>(fileSystemChildren, this);
         }
 
         /// <summary>

+ 1 - 1
MediaBrowser.Controller/Entities/Movies/Movie.cs

@@ -181,7 +181,7 @@ namespace MediaBrowser.Controller.Entities.Movies
                 return new List<Video> { };
             }
 
-            return Kernel.Instance.LibraryManager.GetItems<Video>(files, null).Select(video =>
+            return LibraryManager.ResolvePaths<Video>(files, null).Select(video =>
             {
                 // Try to retrieve it from the db. If we don't find it, use the resolved version
                 var dbItem = Kernel.Instance.ItemRepository.RetrieveItem(video.Id) as Video;

+ 1 - 1
MediaBrowser.Controller/Entities/User.cs

@@ -124,7 +124,7 @@ namespace MediaBrowser.Controller.Entities
         {
             get
             {
-                LazyInitializer.EnsureInitialized(ref _rootFolder, ref _userRootFolderInitialized, ref _userRootFolderSyncLock, () => (UserRootFolder)Kernel.Instance.LibraryManager.GetItem(RootFolderPath));
+                LazyInitializer.EnsureInitialized(ref _rootFolder, ref _userRootFolderInitialized, ref _userRootFolderSyncLock, () => (UserRootFolder)LibraryManager.ResolvePath(RootFolderPath));
                 return _rootFolder;
             }
             private set

+ 1 - 1
MediaBrowser.Controller/Entities/UserRootFolder.cs

@@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{BaseItem}.</returns>
         protected override IEnumerable<BaseItem> GetNonCachedChildren()
         {
-            return base.GetNonCachedChildren().Concat(Kernel.Instance.RootFolder.VirtualChildren);
+            return base.GetNonCachedChildren().Concat(LibraryManager.RootFolder.VirtualChildren);
         }
     }
 }

+ 11 - 8
MediaBrowser.Controller/IO/DirectoryWatchers.cs

@@ -72,11 +72,13 @@ namespace MediaBrowser.Controller.IO
         /// </summary>
         /// <value>The task manager.</value>
         private ITaskManager TaskManager { get; set; }
-        
+
+        private ILibraryManager LibraryManager { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="DirectoryWatchers" /> class.
         /// </summary>
-        public DirectoryWatchers(ILogger logger, ITaskManager taskManager)
+        public DirectoryWatchers(ILogger logger, ITaskManager taskManager, ILibraryManager libraryManager)
         {
             if (logger == null)
             {
@@ -87,6 +89,7 @@ namespace MediaBrowser.Controller.IO
                 throw new ArgumentNullException("taskManager");
             }
 
+            LibraryManager = libraryManager;
             TaskManager = taskManager;
             Logger = logger;
         }
@@ -96,11 +99,11 @@ namespace MediaBrowser.Controller.IO
         /// </summary>
         internal void Start()
         {
-            Kernel.Instance.LibraryManager.LibraryChanged += Instance_LibraryChanged;
-          
-            var pathsToWatch = new List<string> { Kernel.Instance.RootFolder.Path };
+            LibraryManager.LibraryChanged += Instance_LibraryChanged;
+
+            var pathsToWatch = new List<string> { LibraryManager.RootFolder.Path };
 
-            var paths = Kernel.Instance.RootFolder.Children.OfType<Folder>()
+            var paths = LibraryManager.RootFolder.Children.OfType<Folder>()
                 .SelectMany(f =>
                     {
                         try
@@ -467,7 +470,7 @@ namespace MediaBrowser.Controller.IO
 
             while (item == null && !string.IsNullOrEmpty(path))
             {
-                item = Kernel.Instance.RootFolder.FindByPath(path);
+                item = LibraryManager.RootFolder.FindByPath(path);
 
                 path = Path.GetDirectoryName(path);
             }
@@ -494,7 +497,7 @@ namespace MediaBrowser.Controller.IO
         /// </summary>
         private void Stop()
         {
-            Kernel.Instance.LibraryManager.LibraryChanged -= Instance_LibraryChanged;
+            LibraryManager.LibraryChanged -= Instance_LibraryChanged;
 
             FileSystemWatcher watcher;
 

+ 4 - 2
MediaBrowser.Controller/IO/FileSystemManager.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Logging;
 using System;
 using System.IO;
@@ -34,11 +35,12 @@ namespace MediaBrowser.Controller.IO
         /// <param name="kernel">The kernel.</param>
         /// <param name="logger">The logger.</param>
         /// <param name="taskManager">The task manager.</param>
-        public FileSystemManager(Kernel kernel, ILogger logger, ITaskManager taskManager)
+        /// <param name="libraryManager">The library manager.</param>
+        public FileSystemManager(Kernel kernel, ILogger logger, ITaskManager taskManager, ILibraryManager libraryManager)
             : base(kernel)
         {
             _logger = logger;
-            DirectoryWatchers = new DirectoryWatchers(logger, taskManager);
+            DirectoryWatchers = new DirectoryWatchers(logger, taskManager, libraryManager);
         }
 
         /// <summary>

+ 5 - 91
MediaBrowser.Controller/Kernel.cs

@@ -36,12 +36,6 @@ namespace MediaBrowser.Controller
         /// <value>The instance.</value>
         public static Kernel Instance { get; private set; }
 
-        /// <summary>
-        /// Gets the library manager.
-        /// </summary>
-        /// <value>The library manager.</value>
-        public LibraryManager LibraryManager { get; private set; }
-
         /// <summary>
         /// Gets the image manager.
         /// </summary>
@@ -72,40 +66,6 @@ namespace MediaBrowser.Controller
         /// <value>The provider manager.</value>
         public ProviderManager ProviderManager { get; private set; }
 
-        /// <summary>
-        /// The _root folder
-        /// </summary>
-        private AggregateFolder _rootFolder;
-        /// <summary>
-        /// The _root folder sync lock
-        /// </summary>
-        private object _rootFolderSyncLock = new object();
-        /// <summary>
-        /// The _root folder initialized
-        /// </summary>
-        private bool _rootFolderInitialized;
-        /// <summary>
-        /// Gets the root folder.
-        /// </summary>
-        /// <value>The root folder.</value>
-        public AggregateFolder RootFolder
-        {
-            get
-            {
-                LazyInitializer.EnsureInitialized(ref _rootFolder, ref _rootFolderInitialized, ref _rootFolderSyncLock, LibraryManager.CreateRootFolder);
-                return _rootFolder;
-            }
-            private set
-            {
-                _rootFolder = value;
-
-                if (value == null)
-                {
-                    _rootFolderInitialized = false;
-                }
-            }
-        }
-
         /// <summary>
         /// Gets the kernel context.
         /// </summary>
@@ -156,13 +116,13 @@ namespace MediaBrowser.Controller
         /// Gets the list of currently registered entity resolvers
         /// </summary>
         /// <value>The entity resolvers enumerable.</value>
-        internal IEnumerable<IBaseItemResolver> EntityResolvers { get; private set; }
+        public IEnumerable<IBaseItemResolver> EntityResolvers { get; private set; }
 
         /// <summary>
         /// Gets the list of BasePluginFolders added by plugins
         /// </summary>
         /// <value>The plugin folders.</value>
-        internal IEnumerable<IVirtualFolderCreator> PluginFolderCreators { get; private set; }
+        public IEnumerable<IVirtualFolderCreator> PluginFolderCreators { get; private set; }
 
         /// <summary>
         /// Gets the list of available user repositories
@@ -210,7 +170,7 @@ namespace MediaBrowser.Controller
         /// Gets the list of entity resolution ignore rules
         /// </summary>
         /// <value>The entity resolution ignore rules.</value>
-        internal IEnumerable<IResolutionIgnoreRule> EntityResolutionIgnoreRules { get; private set; }
+        public IEnumerable<IResolutionIgnoreRule> EntityResolutionIgnoreRules { get; private set; }
 
         /// <summary>
         /// Gets the active user data repository
@@ -233,7 +193,6 @@ namespace MediaBrowser.Controller
         /// <param name="appHost">The app host.</param>
         /// <param name="appPaths">The app paths.</param>
         /// <param name="xmlSerializer">The XML serializer.</param>
-        /// <param name="taskManager">The task manager.</param>
         /// <param name="logger">The logger.</param>
         /// <exception cref="System.ArgumentNullException">isoManager</exception>
         public Kernel(IApplicationHost appHost, IServerApplicationPaths appPaths, IXmlSerializer xmlSerializer, ILogger logger)
@@ -255,11 +214,11 @@ namespace MediaBrowser.Controller
         protected override void FindParts()
         {
             // For now there's no real way to inject this properly
+            BaseItem.LibraryManager = ApplicationHost.Resolve<ILibraryManager>();
             User.UserManager = ApplicationHost.Resolve<IUserManager>();
 
             InstallationManager = (InstallationManager)ApplicationHost.CreateInstance(typeof(InstallationManager));
             FFMpegManager = (FFMpegManager)ApplicationHost.CreateInstance(typeof(FFMpegManager));
-            LibraryManager = (LibraryManager)ApplicationHost.CreateInstance(typeof(LibraryManager));
             ImageManager = (ImageManager)ApplicationHost.CreateInstance(typeof(ImageManager));
             ProviderManager = (ProviderManager)ApplicationHost.CreateInstance(typeof(ProviderManager));
             SecurityManager = (PluginSecurityManager)ApplicationHost.CreateInstance(typeof(PluginSecurityManager));
@@ -287,9 +246,6 @@ namespace MediaBrowser.Controller
         /// <returns>Task.</returns>
         protected override async Task ReloadInternal()
         {
-            // Reset these so that they can be lazy loaded again
-            RootFolder = null;
-
             await base.ReloadInternal().ConfigureAwait(false);
 
             ReloadResourcePools();
@@ -399,52 +355,10 @@ namespace MediaBrowser.Controller
         {
             DisposeFileSystemManager();
 
-            FileSystemManager = new FileSystemManager(this, Logger, ApplicationHost.Resolve<ITaskManager>());
+            FileSystemManager = new FileSystemManager(this, Logger, ApplicationHost.Resolve<ITaskManager>(), ApplicationHost.Resolve<ILibraryManager>());
             FileSystemManager.StartWatchers();
         }
 
-        /// <summary>
-        /// Finds a library item by Id and UserId.
-        /// </summary>
-        /// <param name="id">The id.</param>
-        /// <param name="userId">The user id.</param>
-        /// <param name="userManager">The user manager.</param>
-        /// <returns>BaseItem.</returns>
-        /// <exception cref="System.ArgumentNullException">id</exception>
-        public BaseItem GetItemById(Guid id, Guid userId, IUserManager userManager)
-        {
-            if (id == Guid.Empty)
-            {
-                throw new ArgumentNullException("id");
-            }
-
-            if (userId == Guid.Empty)
-            {
-                throw new ArgumentNullException("userId");
-            }
-
-            var user = userManager.GetUserById(userId);
-            var userRoot = user.RootFolder;
-
-            return userRoot.FindItemById(id, user);
-        }
-
-        /// <summary>
-        /// Gets the item by id.
-        /// </summary>
-        /// <param name="id">The id.</param>
-        /// <returns>BaseItem.</returns>
-        /// <exception cref="System.ArgumentNullException">id</exception>
-        public BaseItem GetItemById(Guid id)
-        {
-            if (id == Guid.Empty)
-            {
-                throw new ArgumentNullException("id");
-            }
-
-            return RootFolder.FindItemById(id, null);
-        }
-
         /// <summary>
         /// Completely overwrites the current configuration with a new copy
         /// </summary>

+ 18 - 16
MediaBrowser.Controller/Library/DtoBuilder.cs

@@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="fields">The fields.</param>
         /// <returns>Task{DtoBaseItem}.</returns>
         /// <exception cref="System.ArgumentNullException">item</exception>
-        public async Task<BaseItemDto> GetDtoBaseItem(BaseItem item, List<ItemFields> fields)
+        public async Task<BaseItemDto> GetDtoBaseItem(BaseItem item, List<ItemFields> fields, ILibraryManager libraryManager)
         {
             if (item == null)
             {
@@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Library
 
             if (fields.Contains(ItemFields.People))
             {
-                tasks.Add(AttachPeople(dto, item));
+                tasks.Add(AttachPeople(dto, item, libraryManager));
             }
 
             AttachBasicFields(dto, item, fields);
@@ -86,16 +86,17 @@ namespace MediaBrowser.Controller.Library
 
             return dto;
         }
-        
+
         /// <summary>
         /// Converts a BaseItem to a DTOBaseItem
         /// </summary>
         /// <param name="item">The item.</param>
         /// <param name="user">The user.</param>
         /// <param name="fields">The fields.</param>
+        /// <param name="libraryManager">The library manager.</param>
         /// <returns>Task{DtoBaseItem}.</returns>
-        /// <exception cref="System.ArgumentNullException"></exception>
-        public async Task<BaseItemDto> GetDtoBaseItem(BaseItem item, User user, List<ItemFields> fields)
+        /// <exception cref="System.ArgumentNullException">item</exception>
+        public async Task<BaseItemDto> GetDtoBaseItem(BaseItem item, User user, List<ItemFields> fields, ILibraryManager libraryManager)
         {
             if (item == null)
             {
@@ -134,7 +135,7 @@ namespace MediaBrowser.Controller.Library
 
             if (fields.Contains(ItemFields.People))
             {
-                tasks.Add(AttachPeople(dto, item));
+                tasks.Add(AttachPeople(dto, item, libraryManager));
             }
 
             AttachBasicFields(dto, item, fields);
@@ -558,8 +559,9 @@ namespace MediaBrowser.Controller.Library
         /// </summary>
         /// <param name="dto">The dto.</param>
         /// <param name="item">The item.</param>
+        /// <param name="libraryManager">The library manager.</param>
         /// <returns>Task.</returns>
-        private async Task AttachPeople(BaseItemDto dto, BaseItem item)
+        private async Task AttachPeople(BaseItemDto dto, BaseItem item, ILibraryManager libraryManager)
         {
             if (item.People == null)
             {
@@ -575,7 +577,7 @@ namespace MediaBrowser.Controller.Library
                     {
                         try
                         {
-                            return await Kernel.Instance.LibraryManager.GetPerson(c.Name).ConfigureAwait(false);
+                            return await libraryManager.GetPerson(c.Name).ConfigureAwait(false);
                         }
                         catch (IOException ex)
                         {
@@ -662,7 +664,7 @@ namespace MediaBrowser.Controller.Library
         /// </summary>
         /// <param name="changeEvent">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
         /// <returns>LibraryUpdateInfo.</returns>
-        internal static LibraryUpdateInfo GetLibraryUpdateInfo(ChildrenChangedEventArgs changeEvent)
+        public static LibraryUpdateInfo GetLibraryUpdateInfo(ChildrenChangedEventArgs changeEvent)
         {
             return new LibraryUpdateInfo
             {
@@ -823,7 +825,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="id">The id.</param>
         /// <param name="userId">The user id.</param>
         /// <returns>BaseItem.</returns>
-        public static BaseItem GetItemByClientId(string id, IUserManager userManager, Guid? userId = null)
+        public static BaseItem GetItemByClientId(string id, IUserManager userManager, ILibraryManager libraryManager, Guid? userId = null)
         {
             var isIdEmpty = string.IsNullOrEmpty(id);
 
@@ -835,7 +837,7 @@ namespace MediaBrowser.Controller.Library
             {
                 if (userId.HasValue)
                 {
-                    return GetIndexFolder(id, userId.Value, userManager);
+                    return GetIndexFolder(id, userId.Value, userManager, libraryManager);
                 }
             }
 
@@ -845,11 +847,11 @@ namespace MediaBrowser.Controller.Library
             {
                 item = isIdEmpty
                            ? userManager.GetUserById(userId.Value).RootFolder
-                           : Kernel.Instance.GetItemById(new Guid(id), userId.Value, userManager);
+                           : libraryManager.GetItemById(new Guid(id), userId.Value);
             }
             else if (!isIndexFolder)
             {
-                item = Kernel.Instance.GetItemById(new Guid(id));
+                item = libraryManager.GetItemById(new Guid(id));
             }
 
             // If we still don't find it, look within individual user views
@@ -857,7 +859,7 @@ namespace MediaBrowser.Controller.Library
             {
                 foreach (var user in userManager.Users)
                 {
-                    item = GetItemByClientId(id, userManager, user.Id);
+                    item = GetItemByClientId(id, userManager, libraryManager, user.Id);
 
                     if (item != null)
                     {
@@ -875,7 +877,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="id">The id.</param>
         /// <param name="userId">The user id.</param>
         /// <returns>BaseItem.</returns>
-        private static BaseItem GetIndexFolder(string id, Guid userId, IUserManager userManager)
+        private static BaseItem GetIndexFolder(string id, Guid userId, IUserManager userManager, ILibraryManager libraryManager)
         {
             var user = userManager.GetUserById(userId);
 
@@ -885,7 +887,7 @@ namespace MediaBrowser.Controller.Library
             var values = id.Split(stringSeparators, StringSplitOptions.None).ToList();
 
             // Get the top folder normally using the first id
-            var folder = GetItemByClientId(values[0], userManager, userId) as Folder;
+            var folder = GetItemByClientId(values[0], userManager, libraryManager, userId) as Folder;
 
             values.RemoveAt(0);
 

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

@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Controller.Library
+{
+    public interface ILibraryManager
+    {
+        /// <summary>
+        /// Fires whenever any validation routine adds or removes items.  The added and removed items are properties of the args.
+        /// *** Will fire asynchronously. ***
+        /// </summary>
+        event EventHandler<ChildrenChangedEventArgs> LibraryChanged;
+
+        /// <summary>
+        /// Raises the <see cref="E:LibraryChanged" /> event.
+        /// </summary>
+        /// <param name="args">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
+        void ReportLibraryChanged(ChildrenChangedEventArgs args);
+
+        /// <summary>
+        /// Resolves the item.
+        /// </summary>
+        /// <param name="args">The args.</param>
+        /// <returns>BaseItem.</returns>
+        BaseItem ResolveItem(ItemResolveArgs args);
+
+        /// <summary>
+        /// Resolves a path into a BaseItem
+        /// </summary>
+        /// <param name="path">The path.</param>
+        /// <param name="parent">The parent.</param>
+        /// <param name="fileInfo">The file info.</param>
+        /// <returns>BaseItem.</returns>
+        /// <exception cref="System.ArgumentNullException"></exception>
+        BaseItem ResolvePath(string path, Folder parent = null, WIN32_FIND_DATA? fileInfo = null);
+
+        /// <summary>
+        /// Resolves a set of files into a list of BaseItem
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="files">The files.</param>
+        /// <param name="parent">The parent.</param>
+        /// <returns>List{``0}.</returns>
+        List<T> ResolvePaths<T>(IEnumerable<WIN32_FIND_DATA> files, Folder parent) 
+            where T : BaseItem;
+
+        /// <summary>
+        /// Gets the root folder.
+        /// </summary>
+        /// <value>The root folder.</value>
+        AggregateFolder RootFolder { get; }
+
+        /// <summary>
+        /// Gets a Person
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
+        /// <returns>Task{Person}.</returns>
+        Task<Person> GetPerson(string name, bool allowSlowProviders = false);
+
+        /// <summary>
+        /// Gets a Studio
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
+        /// <returns>Task{Studio}.</returns>
+        Task<Studio> GetStudio(string name, bool allowSlowProviders = false);
+
+        /// <summary>
+        /// Gets a Genre
+        /// </summary>
+        /// <param name="name">The name.</param>
+        /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
+        /// <returns>Task{Genre}.</returns>
+        Task<Genre> GetGenre(string name, bool allowSlowProviders = false);
+
+        /// <summary>
+        /// Gets a Year
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <param name="allowSlowProviders">if set to <c>true</c> [allow slow providers].</param>
+        /// <returns>Task{Year}.</returns>
+        /// <exception cref="System.ArgumentOutOfRangeException"></exception>
+        Task<Year> GetYear(int value, bool allowSlowProviders = false);
+
+        /// <summary>
+        /// Validate and refresh the People sub-set of the IBN.
+        /// The items are stored in the db but not loaded into memory until actually requested by an operation.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="progress">The progress.</param>
+        /// <returns>Task.</returns>
+        Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress);
+
+        /// <summary>
+        /// Reloads the root media folder
+        /// </summary>
+        /// <param name="progress">The progress.</param>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <returns>Task.</returns>
+        Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken);
+
+        /// <summary>
+        /// Saves display preferences for a Folder
+        /// </summary>
+        /// <param name="user">The user.</param>
+        /// <param name="folder">The folder.</param>
+        /// <param name="data">The data.</param>
+        /// <returns>Task.</returns>
+        Task SaveDisplayPreferencesForFolder(User user, Folder folder, DisplayPreferences data);
+
+        /// <summary>
+        /// Gets the default view.
+        /// </summary>
+        /// <returns>IEnumerable{VirtualFolderInfo}.</returns>
+        IEnumerable<VirtualFolderInfo> GetDefaultVirtualFolders();
+
+        /// <summary>
+        /// Gets the view.
+        /// </summary>
+        /// <param name="user">The user.</param>
+        /// <returns>IEnumerable{VirtualFolderInfo}.</returns>
+        IEnumerable<VirtualFolderInfo> GetVirtualFolders(User user);
+
+        /// <summary>
+        /// Gets the item by id.
+        /// </summary>
+        /// <param name="id">The id.</param>
+        /// <returns>BaseItem.</returns>
+        BaseItem GetItemById(Guid id);
+
+        /// <summary>
+        /// Gets the item by id.
+        /// </summary>
+        /// <param name="id">The id.</param>
+        /// <param name="userId">The user id.</param>
+        /// <returns>BaseItem.</returns>
+        BaseItem GetItemById(Guid id, Guid userId);
+    }
+}

+ 1 - 1
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -113,6 +113,7 @@
     <Compile Include="IServerApplicationPaths.cs" />
     <Compile Include="Library\ChildrenChangedEventArgs.cs" />
     <Compile Include="Library\DtoBuilder.cs" />
+    <Compile Include="Library\ILibraryManager.cs" />
     <Compile Include="Library\IUserManager.cs" />
     <Compile Include="Library\Profiler.cs" />
     <Compile Include="Localization\AURatingsDictionary.cs" />
@@ -181,7 +182,6 @@
     <Compile Include="Library\ItemResolveArgs.cs" />
     <Compile Include="IO\DirectoryWatchers.cs" />
     <Compile Include="IO\FileData.cs" />
-    <Compile Include="Library\LibraryManager.cs" />
     <Compile Include="Kernel.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Providers\BaseMetadataProvider.cs" />

+ 9 - 5
MediaBrowser.Controller/ScheduledTasks/PeopleValidationTask.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Library;
 using System;
 using System.Collections.Generic;
 using System.Threading;
@@ -11,15 +12,18 @@ namespace MediaBrowser.Controller.ScheduledTasks
     /// </summary>
     public class PeopleValidationTask : IScheduledTask
     {
-        private readonly Kernel _kernel;
+        /// <summary>
+        /// The _library manager
+        /// </summary>
+        private readonly ILibraryManager _libraryManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="PeopleValidationTask" /> class.
         /// </summary>
-        /// <param name="kernel">The kernel.</param>
-        public PeopleValidationTask(Kernel kernel)
+        /// <param name="libraryManager">The library manager.</param>
+        public PeopleValidationTask(ILibraryManager libraryManager)
         {
-            _kernel = kernel;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -44,7 +48,7 @@ namespace MediaBrowser.Controller.ScheduledTasks
         /// <returns>Task.</returns>
         public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
         {
-            return _kernel.LibraryManager.ValidatePeople(cancellationToken, progress);
+            return _libraryManager.ValidatePeople(cancellationToken, progress);
         }
 
         /// <summary>

+ 7 - 6
MediaBrowser.Controller/ScheduledTasks/RefreshMediaLibraryTask.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Tasks;
 using System;
 using System.Collections.Generic;
@@ -13,17 +14,17 @@ namespace MediaBrowser.Controller.ScheduledTasks
     public class RefreshMediaLibraryTask : IScheduledTask
     {
         /// <summary>
-        /// The _kernel
+        /// The _library manager
         /// </summary>
-        private readonly Kernel _kernel;
+        private readonly ILibraryManager _libraryManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="RefreshMediaLibraryTask" /> class.
         /// </summary>
-        /// <param name="kernel">The kernel.</param>
-        public RefreshMediaLibraryTask(Kernel kernel)
+        /// <param name="libraryManager">The library manager.</param>
+        public RefreshMediaLibraryTask(ILibraryManager libraryManager)
         {
-            _kernel = kernel;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -54,7 +55,7 @@ namespace MediaBrowser.Controller.ScheduledTasks
 
             progress.Report(0);
 
-            return _kernel.LibraryManager.ValidateMediaLibrary(progress, cancellationToken);
+            return _libraryManager.ValidateMediaLibrary(progress, cancellationToken);
         }
 
         /// <summary>

+ 3 - 2
BDInfo/BdInfoExaminer.cs → MediaBrowser.Server.Implementations/BdInfo/BdInfoExaminer.cs

@@ -1,10 +1,11 @@
-using MediaBrowser.Model.Entities;
+using BDInfo;
+using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.MediaInfo;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 
-namespace BDInfo
+namespace MediaBrowser.Server.Implementations.BdInfo
 {
     /// <summary>
     /// Class BdInfoExaminer

+ 98 - 16
MediaBrowser.Controller/Library/LibraryManager.cs → MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -1,8 +1,10 @@
 using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.IO;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Controller.ScheduledTasks;
 using MediaBrowser.Model.Entities;
@@ -17,12 +19,12 @@ using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 
-namespace MediaBrowser.Controller.Library
+namespace MediaBrowser.Server.Implementations.Library
 {
     /// <summary>
     /// Class LibraryManager
     /// </summary>
-    public class LibraryManager
+    public class LibraryManager : ILibraryManager
     {
         #region LibraryChanged Event
         /// <summary>
@@ -35,7 +37,7 @@ namespace MediaBrowser.Controller.Library
         /// Raises the <see cref="E:LibraryChanged" /> event.
         /// </summary>
         /// <param name="args">The <see cref="ChildrenChangedEventArgs" /> instance containing the event data.</param>
-        internal void OnLibraryChanged(ChildrenChangedEventArgs args)
+        public void ReportLibraryChanged(ChildrenChangedEventArgs args)
         {
             EventHelper.QueueEventIfNotNull(LibraryChanged, this, args, _logger);
 
@@ -64,8 +66,11 @@ namespace MediaBrowser.Controller.Library
         /// </summary>
         private readonly ITaskManager _taskManager;
 
+        /// <summary>
+        /// The _user manager
+        /// </summary>
         private readonly IUserManager _userManager;
-        
+
         /// <summary>
         /// Gets or sets the kernel.
         /// </summary>
@@ -78,6 +83,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="kernel">The kernel.</param>
         /// <param name="logger">The logger.</param>
         /// <param name="taskManager">The task manager.</param>
+        /// <param name="userManager">The user manager.</param>
         public LibraryManager(Kernel kernel, ILogger logger, ITaskManager taskManager, IUserManager userManager)
         {
             Kernel = kernel;
@@ -88,6 +94,40 @@ namespace MediaBrowser.Controller.Library
             kernel.ConfigurationUpdated += kernel_ConfigurationUpdated;
         }
 
+        /// <summary>
+        /// The _root folder
+        /// </summary>
+        private AggregateFolder _rootFolder;
+        /// <summary>
+        /// The _root folder sync lock
+        /// </summary>
+        private object _rootFolderSyncLock = new object();
+        /// <summary>
+        /// The _root folder initialized
+        /// </summary>
+        private bool _rootFolderInitialized;
+        /// <summary>
+        /// Gets the root folder.
+        /// </summary>
+        /// <value>The root folder.</value>
+        public AggregateFolder RootFolder
+        {
+            get
+            {
+                LazyInitializer.EnsureInitialized(ref _rootFolder, ref _rootFolderInitialized, ref _rootFolderSyncLock, CreateRootFolder);
+                return _rootFolder;
+            }
+            private set
+            {
+                _rootFolder = value;
+
+                if (value == null)
+                {
+                    _rootFolderInitialized = false;
+                }
+            }
+        }
+
         /// <summary>
         /// Handles the ConfigurationUpdated event of the kernel control.
         /// </summary>
@@ -133,7 +173,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="fileInfo">The file info.</param>
         /// <returns>BaseItem.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public BaseItem GetItem(string path, Folder parent = null, WIN32_FIND_DATA? fileInfo = null)
+        public BaseItem ResolvePath(string path, Folder parent = null, WIN32_FIND_DATA? fileInfo = null)
         {
             if (string.IsNullOrEmpty(path))
             {
@@ -185,7 +225,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="files">The files.</param>
         /// <param name="parent">The parent.</param>
         /// <returns>List{``0}.</returns>
-        public List<T> GetItems<T>(IEnumerable<WIN32_FIND_DATA> files, Folder parent)
+        public List<T> ResolvePaths<T>(IEnumerable<WIN32_FIND_DATA> files, Folder parent)
             where T : BaseItem
         {
             var list = new List<T>();
@@ -194,7 +234,7 @@ namespace MediaBrowser.Controller.Library
             {
                 try
                 {
-                    var item = GetItem(f.Path, parent, f) as T;
+                    var item = ResolvePath(f.Path, parent, f) as T;
 
                     if (item != null)
                     {
@@ -218,7 +258,7 @@ namespace MediaBrowser.Controller.Library
         /// </summary>
         /// <returns>AggregateFolder.</returns>
         /// <exception cref="System.InvalidOperationException">Cannot create the root folder until plugins have loaded</exception>
-        internal AggregateFolder CreateRootFolder()
+        public AggregateFolder CreateRootFolder()
         {
             if (Kernel.Plugins == null)
             {
@@ -226,7 +266,7 @@ namespace MediaBrowser.Controller.Library
             }
 
             var rootFolderPath = Kernel.ApplicationPaths.RootFolderPath;
-            var rootFolder = Kernel.ItemRepository.RetrieveItem(rootFolderPath.GetMBId(typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)GetItem(rootFolderPath);
+            var rootFolder = Kernel.ItemRepository.RetrieveItem(rootFolderPath.GetMBId(typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(rootFolderPath);
 
             // Add in the plug-in folders
             foreach (var child in Kernel.PluginFolderCreators)
@@ -412,7 +452,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="progress">The progress.</param>
         /// <returns>Task.</returns>
-        internal async Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
+        public async Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
         {
             // Clear the IBN cache
             ImagesByNameItemCache.Clear();
@@ -423,7 +463,7 @@ namespace MediaBrowser.Controller.Library
 
             var includedPersonTypes = new[] { PersonType.Actor, PersonType.Director };
 
-            var people = Kernel.RootFolder.RecursiveChildren
+            var people = RootFolder.RecursiveChildren
                 .Where(c => c.People != null)
                 .SelectMany(c => c.People.Where(p => includedPersonTypes.Contains(p.Type)))
                 .DistinctBy(p => p.Name, StringComparer.OrdinalIgnoreCase)
@@ -483,21 +523,21 @@ namespace MediaBrowser.Controller.Library
         /// <param name="progress">The progress.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        internal async Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken)
+        public async Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken)
         {
             _logger.Info("Validating media library");
 
-            await Kernel.RootFolder.RefreshMetadata(cancellationToken).ConfigureAwait(false);
+            await RootFolder.RefreshMetadata(cancellationToken).ConfigureAwait(false);
 
             // Start by just validating the children of the root, but go no further
-            await Kernel.RootFolder.ValidateChildren(new Progress<double> { }, cancellationToken, recursive: false);
+            await RootFolder.ValidateChildren(new Progress<double> { }, cancellationToken, recursive: false);
 
             // Validate only the collection folders for each user, just to make them available as quickly as possible
             var userCollectionFolderTasks = _userManager.Users.AsParallel().Select(user => user.ValidateCollectionFolders(new Progress<double> { }, cancellationToken));
             await Task.WhenAll(userCollectionFolderTasks).ConfigureAwait(false);
 
             // Now validate the entire media library
-            await Kernel.RootFolder.ValidateChildren(progress, cancellationToken, recursive: true).ConfigureAwait(false);
+            await RootFolder.ValidateChildren(progress, cancellationToken, recursive: true).ConfigureAwait(false);
 
             foreach (var user in _userManager.Users)
             {
@@ -515,7 +555,7 @@ namespace MediaBrowser.Controller.Library
         public Task SaveDisplayPreferencesForFolder(User user, Folder folder, DisplayPreferences data)
         {
             // Need to update all items with the same DisplayPrefsId
-            foreach (var child in Kernel.RootFolder.GetRecursiveChildren(user)
+            foreach (var child in RootFolder.GetRecursiveChildren(user)
                 .OfType<Folder>()
                 .Where(i => i.DisplayPrefsId == folder.DisplayPrefsId))
             {
@@ -558,5 +598,47 @@ namespace MediaBrowser.Controller.Library
                     Locations = Directory.EnumerateFiles(dir, "*.lnk", SearchOption.TopDirectoryOnly).Select(FileSystem.ResolveShortcut).ToList()
                 });
         }
+
+        /// <summary>
+        /// Finds a library item by Id and UserId.
+        /// </summary>
+        /// <param name="id">The id.</param>
+        /// <param name="userId">The user id.</param>
+        /// <param name="userManager">The user manager.</param>
+        /// <returns>BaseItem.</returns>
+        /// <exception cref="System.ArgumentNullException">id</exception>
+        public BaseItem GetItemById(Guid id, Guid userId)
+        {
+            if (id == Guid.Empty)
+            {
+                throw new ArgumentNullException("id");
+            }
+
+            if (userId == Guid.Empty)
+            {
+                throw new ArgumentNullException("userId");
+            }
+
+            var user = _userManager.GetUserById(userId);
+            var userRoot = user.RootFolder;
+
+            return userRoot.FindItemById(id, user);
+        }
+
+        /// <summary>
+        /// Gets the item by id.
+        /// </summary>
+        /// <param name="id">The id.</param>
+        /// <returns>BaseItem.</returns>
+        /// <exception cref="System.ArgumentNullException">id</exception>
+        public BaseItem GetItemById(Guid id)
+        {
+            if (id == Guid.Empty)
+            {
+                throw new ArgumentNullException("id");
+            }
+            return null;
+            //return RootFolder.FindItemById(id, null);
+        }
     }
 }

+ 9 - 0
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -32,6 +32,9 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="MoreLinq">
+      <HintPath>..\packages\morelinq.1.0.15631-beta\lib\net35\MoreLinq.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Data.SQLite">
@@ -50,6 +53,8 @@
     <Compile Include="..\SharedVersion.cs">
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
+    <Compile Include="BdInfo\BdInfoExaminer.cs" />
+    <Compile Include="Library\LibraryManager.cs" />
     <Compile Include="Library\UserManager.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Reflection\TypeMapper.cs" />
@@ -66,6 +71,10 @@
     <Compile Include="WorldWeatherOnline\WeatherProvider.cs" />
   </ItemGroup>
   <ItemGroup>
+    <ProjectReference Include="..\BDInfo\BDInfo.csproj">
+      <Project>{07b509c0-0c28-4f3f-8963-5263281f7e3d}</Project>
+      <Name>BDInfo</Name>
+    </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Common.Implementations\MediaBrowser.Common.Implementations.csproj">
       <Project>{c4d2573a-3fd3-441f-81af-174ac4cd4e1d}</Project>
       <Name>MediaBrowser.Common.Implementations</Name>

+ 6 - 2
MediaBrowser.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;
@@ -23,16 +24,19 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks.Tasks
         /// The _logger
         /// </summary>
         private readonly ILogger _logger;
+        private readonly ILibraryManager _libraryManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ChapterImagesTask" /> class.
         /// </summary>
         /// <param name="kernel">The kernel.</param>
         /// <param name="logger">The logger.</param>
-        public ChapterImagesTask(Kernel kernel, ILogger logger)
+        /// <param name="libraryManager">The library manager.</param>
+        public ChapterImagesTask(Kernel kernel, ILogger logger, ILibraryManager libraryManager)
         {
             _kernel = kernel;
             _logger = logger;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -55,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks.Tasks
         /// <returns>Task.</returns>
         public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
         {
-            var videos = _kernel.RootFolder.RecursiveChildren.OfType<Video>().Where(v => v.Chapters != null).ToList();
+            var videos = _libraryManager.RootFolder.RecursiveChildren.OfType<Video>().Where(v => v.Chapters != null).ToList();
 
             var numComplete = 0;
 

+ 7 - 4
MediaBrowser.Server.Implementations/ScheduledTasks/Tasks/ImageCleanupTask.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;
@@ -25,16 +26,18 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks.Tasks
         /// The _logger
         /// </summary>
         private readonly ILogger _logger;
+        private readonly ILibraryManager _libraryManager;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ImageCleanupTask" /> class.
         /// </summary>
         /// <param name="kernel">The kernel.</param>
         /// <param name="logger">The logger.</param>
-        public ImageCleanupTask(Kernel kernel, ILogger logger)
+        public ImageCleanupTask(Kernel kernel, ILogger logger, ILibraryManager libraryManager)
         {
             _kernel = kernel;
             _logger = logger;
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -66,8 +69,8 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks.Tasks
                 .ToList();
 
             // Now gather all items
-            var items = _kernel.RootFolder.RecursiveChildren.ToList();
-            items.Add(_kernel.RootFolder);
+            var items = _libraryManager.RootFolder.RecursiveChildren.ToList();
+            items.Add(_libraryManager.RootFolder);
 
             // Determine all possible image paths
             var pathsInUse = items.SelectMany(GetPathsInUse)
@@ -115,7 +118,7 @@ namespace MediaBrowser.Server.Implementations.ScheduledTasks.Tasks
         /// <returns>Task.</returns>
         private Task EnsureChapterImages(CancellationToken cancellationToken)
         {
-            var videos = _kernel.RootFolder.RecursiveChildren.OfType<Video>().Where(v => v.Chapters != null).ToList();
+            var videos = _libraryManager.RootFolder.RecursiveChildren.OfType<Video>().Where(v => v.Chapters != null).ToList();
 
             var tasks = videos.Select(v => Task.Run(async () =>
             {

+ 1 - 0
MediaBrowser.Server.Implementations/packages.config

@@ -1,4 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
+  <package id="morelinq" version="1.0.15631-beta" targetFramework="net45" />
   <package id="System.Data.SQLite" version="1.0.84.0" targetFramework="net45" />
 </packages>

+ 12 - 14
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -1,14 +1,12 @@
-using BDInfo;
+using MediaBrowser.Api;
 using MediaBrowser.ClickOnce;
 using MediaBrowser.Common.Implementations;
-using MediaBrowser.Common.Implementations.HttpClientManager;
 using MediaBrowser.Common.Implementations.HttpServer;
 using MediaBrowser.Common.Implementations.Logging;
 using MediaBrowser.Common.Implementations.NetworkManagement;
 using MediaBrowser.Common.Implementations.ScheduledTasks;
 using MediaBrowser.Common.Implementations.Serialization;
 using MediaBrowser.Common.Implementations.ServerManager;
-using MediaBrowser.Common.Implementations.Udp;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Net;
@@ -23,11 +21,12 @@ using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.System;
 using MediaBrowser.Model.Updates;
 using MediaBrowser.Server.Implementations;
+using MediaBrowser.Server.Implementations.BdInfo;
 using MediaBrowser.Server.Implementations.Library;
 using MediaBrowser.ServerApplication.Implementations;
+using MediaBrowser.WebDashboard.Api;
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.IO;
 using System.Linq;
 using System.Reflection;
@@ -120,7 +119,6 @@ namespace MediaBrowser.ServerApplication
 
             RegisterSingleInstance<IApplicationHost>(this);
 
-            RegisterSingleInstance<IUserManager>(new UserManager(Kernel, Logger));
 
             RegisterSingleInstance(ServerApplicationPaths);
             RegisterSingleInstance<IIsoManager>(new PismoIsoManager(Logger));
@@ -129,6 +127,11 @@ namespace MediaBrowser.ServerApplication
             RegisterSingleInstance(_jsonSerializer);
             RegisterSingleInstance(_xmlSerializer);
             RegisterSingleInstance(ServerFactory.CreateServer(this, ProtobufSerializer, Logger, "Media Browser", "index.html"), false);
+
+            var userManager = new UserManager(Kernel, Logger);
+            RegisterSingleInstance<IUserManager>(userManager);
+
+            RegisterSingleInstance<ILibraryManager>(new LibraryManager(Kernel, Logger, taskManager, userManager));
         }
 
         /// <summary>
@@ -186,16 +189,11 @@ namespace MediaBrowser.ServerApplication
                 yield return pluginAssembly;
             }
 
-            var runningDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
-            var corePluginDirectory = Path.Combine(runningDirectory, "CorePlugins");
+            // Include composable parts in the Api assembly 
+            yield return typeof(ApiService).Assembly;
 
-            // This will prevent the .dll file from getting locked, and allow us to replace it when needed
-            foreach (var pluginAssembly in Directory
-                .EnumerateFiles(corePluginDirectory, "*.dll", SearchOption.TopDirectoryOnly)
-                .Select(LoadAssembly).Where(a => a != null))
-            {
-                yield return pluginAssembly;
-            }
+            // Include composable parts in the Dashboard assembly 
+            yield return typeof(DashboardInfo).Assembly;
 
             // Include composable parts in the Model assembly 
             yield return typeof(SystemInfo).Assembly;

+ 6 - 3
MediaBrowser.ServerApplication/LibraryExplorer.xaml.cs

@@ -31,7 +31,8 @@ namespace MediaBrowser.ServerApplication
         private readonly ILogger _logger;
 
         private readonly IJsonSerializer _jsonSerializer;
-        
+        private readonly ILibraryManager _libraryManager;
+  
         /// <summary>
         /// The current user
         /// </summary>
@@ -39,7 +40,7 @@ namespace MediaBrowser.ServerApplication
         /// <summary>
         /// Initializes a new instance of the <see cref="LibraryExplorer" /> class.
         /// </summary>
-        public LibraryExplorer(IJsonSerializer jsonSerializer, ILogger logger, IApplicationHost appHost, IUserManager userManager)
+        public LibraryExplorer(IJsonSerializer jsonSerializer, ILogger logger, IApplicationHost appHost, IUserManager userManager, ILibraryManager libraryManager)
         {
             _logger = logger;
             _jsonSerializer = jsonSerializer;
@@ -51,6 +52,8 @@ namespace MediaBrowser.ServerApplication
             ddlProfile.Items.Insert(0,new User {Name = "Physical"});
             ddlProfile.SelectedIndex = 0;
             ddlIndexBy.Visibility = ddlSortBy.Visibility = lblIndexBy.Visibility = lblSortBy.Visibility = Visibility.Hidden;
+
+            _libraryManager = libraryManager;
         }
 
         /// <summary>
@@ -77,7 +80,7 @@ namespace MediaBrowser.ServerApplication
             await Task.Run(() =>
                                {
                                    IEnumerable<BaseItem> children;
-                                   children = CurrentUser.Name == "Physical" ? Kernel.Instance.RootFolder.Children.OrderBy(i => i.SortName) : Kernel.Instance.RootFolder.GetChildren(CurrentUser, sortBy: LocalizedStrings.Instance.GetString("NameDispPref"));
+                                   children = CurrentUser.Name == "Physical" ? _libraryManager.RootFolder.Children.OrderBy(i => i.SortName) : _libraryManager.RootFolder.GetChildren(CurrentUser, sortBy: LocalizedStrings.Instance.GetString("NameDispPref"));
 
                                    foreach (Folder folder in children)
                                    {

+ 6 - 3
MediaBrowser.ServerApplication/MainWindow.xaml.cs

@@ -54,6 +54,8 @@ namespace MediaBrowser.ServerApplication
         /// The _log manager
         /// </summary>
         private readonly ILogManager _logManager;
+
+        private readonly ILibraryManager _libraryManager;
         
         /// <summary>
         /// Initializes a new instance of the <see cref="MainWindow" /> class.
@@ -62,7 +64,7 @@ namespace MediaBrowser.ServerApplication
         /// <param name="logger">The logger.</param>
         /// <param name="appHost">The app host.</param>
         /// <exception cref="System.ArgumentNullException">logger</exception>
-        public MainWindow(ILogManager logManager, IApplicationHost appHost)
+        public MainWindow(ILogManager logManager, IApplicationHost appHost, ILibraryManager libraryManager)
         {
             if (logManager == null)
             {
@@ -72,6 +74,7 @@ namespace MediaBrowser.ServerApplication
             _logger = logManager.GetLogger("MainWindow");
             _appHost = appHost;
             _logManager = logManager;
+            _libraryManager = libraryManager;
 
             InitializeComponent();
 
@@ -231,8 +234,8 @@ namespace MediaBrowser.ServerApplication
         /// <param name="e">The e.</param>
         void KernelReloadCompleted(object sender, EventArgs e)
         {
-            Kernel.Instance.LibraryManager.LibraryChanged -= Instance_LibraryChanged;
-            Kernel.Instance.LibraryManager.LibraryChanged += Instance_LibraryChanged;
+            _libraryManager.LibraryChanged -= Instance_LibraryChanged;
+            _libraryManager.LibraryChanged += Instance_LibraryChanged;
 
             if (_appHost.IsFirstRun)
             {

+ 7 - 9
MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj

@@ -254,9 +254,9 @@
     </None>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\BDInfo\BDInfo.csproj">
-      <Project>{07b509c0-0c28-4f3f-8963-5263281f7e3d}</Project>
-      <Name>BDInfo</Name>
+    <ProjectReference Include="..\MediaBrowser.Api\MediaBrowser.Api.csproj">
+      <Project>{4fd51ac5-2c16-4308-a993-c3a84f3b4582}</Project>
+      <Name>MediaBrowser.Api</Name>
     </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.ClickOnce\MediaBrowser.ClickOnce.csproj">
       <Project>{cc96bf3e-0bda-4809-bc4b-bb6d418f4a84}</Project>
@@ -286,6 +286,10 @@
       <Project>{2e781478-814d-4a48-9d80-bff206441a65}</Project>
       <Name>MediaBrowser.Server.Implementations</Name>
     </ProjectReference>
+    <ProjectReference Include="..\MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj">
+      <Project>{5624b7b5-b5a7-41d8-9f10-cc5611109619}</Project>
+      <Name>MediaBrowser.WebDashboard</Name>
+    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <Resource Include="Resources\Images\icon.ico" />
@@ -364,12 +368,6 @@
     </BootstrapperPackage>
   </ItemGroup>
   <ItemGroup>
-    <Content Include="CorePlugins\MediaBrowser.Api.dll">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
-    <Content Include="CorePlugins\MediaBrowser.WebDashboard.dll">
-      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
-    </Content>
     <Content Include="x64\SQLite.Interop.dll">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>

+ 2 - 1
MediaBrowser.WebDashboard/Html/scripts/site.js

@@ -1099,7 +1099,8 @@ var Dashboard = {
             if (item.PrimaryImageTag) {
                 data.icon = ApiClient.getImageUrl(item.Id, {
                     width: 100,
-                    tag: item.PrimaryImageTag
+                    tag: item.PrimaryImageTag,
+                    type: "Primary"
                 });
             }
 

+ 2 - 1
MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj

@@ -405,7 +405,8 @@
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
-    <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\MediaBrowser.ServerApplication\CorePlugins\" /y</PostBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
   </PropertyGroup>
   <Import Project="$(SolutionDir)\.nuget\nuget.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 1 - 1
Nuget/MediaBrowser.ApiClient.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.ApiClient</id>
-        <version>3.0.0.15-beta</version>
+        <version>3.0.0.17-beta</version>
         <title>MediaBrowser.ApiClient</title>
         <authors>Media Browser Team</authors>
         <owners>scottisafool,Luke</owners>

+ 2 - 2
Nuget/MediaBrowser.Common.Internal.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common.Internal</id>
-        <version>3.0.15</version>
+        <version>3.0.17</version>
         <title />
         <authors>Luke</authors>
         <owners>Media Browser Team</owners>
@@ -10,7 +10,7 @@
         <requireLicenseAcceptance>false</requireLicenseAcceptance>
         <description>Contains common components shared by Media Browser Theatre and Media Browser Server. Not intended for plugin developer consumption.</description>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.15" />
+            <dependency id="MediaBrowser.Common" version="3.0.17" />
             <dependency id="NLog" version="2.0.0.2000" />
             <dependency id="ServiceStack" version="3.9.37" />
             <dependency id="ServiceStack.Api.Swagger" version="3.9.35" />

+ 1 - 1
Nuget/MediaBrowser.Common.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Common</id>
-        <version>3.0.15</version>
+        <version>3.0.17</version>
         <title>MediaBrowser.Common</title>
         <authors>Media Browser Team</authors>
         <owners />

+ 2 - 2
Nuget/MediaBrowser.Server.Core.nuspec

@@ -2,7 +2,7 @@
 <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
     <metadata>
         <id>MediaBrowser.Server.Core</id>
-        <version>3.0.15</version>
+        <version>3.0.17</version>
         <title>Media Browser.Server.Core</title>
         <authors>Media Browser Team</authors>
         <owners />
@@ -10,7 +10,7 @@
         <requireLicenseAcceptance>false</requireLicenseAcceptance>
         <description>Contains core components required to build plugins for Media Browser Server.</description>
         <dependencies>
-            <dependency id="MediaBrowser.Common" version="3.0.15" />
+            <dependency id="MediaBrowser.Common" version="3.0.17" />
         </dependencies>
     </metadata>
     <files>