Parcourir la source

Created IConfigurationManager

LukePulverenti il y a 12 ans
Parent
commit
2ca4b7d03a
100 fichiers modifiés avec 1236 ajouts et 2309 suppressions
  1. 1 1
      MediaBrowser.Api/Images/ImageService.cs
  2. 2 1
      MediaBrowser.Api/Library/LibraryService.cs
  3. 9 18
      MediaBrowser.Api/PackageService.cs
  4. 20 22
      MediaBrowser.Api/Playback/BaseStreamingService.cs
  5. 4 8
      MediaBrowser.Api/Playback/Hls/AudioHlsService.cs
  6. 3 5
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  7. 4 8
      MediaBrowser.Api/Playback/Hls/VideoHlsService.cs
  8. 4 7
      MediaBrowser.Api/Playback/Progressive/AudioService.cs
  9. 4 7
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  10. 5 8
      MediaBrowser.Api/Playback/Progressive/VideoService.cs
  11. 5 3
      MediaBrowser.Api/Plugin.cs
  12. 14 15
      MediaBrowser.Api/PluginService.cs
  13. 17 13
      MediaBrowser.Api/SystemService.cs
  14. 0 4
      MediaBrowser.Api/UserService.cs
  15. 1 5
      MediaBrowser.Api/WeatherService.cs
  16. 98 27
      MediaBrowser.Common.Implementations/BaseApplicationHost.cs
  17. 2 1
      MediaBrowser.Common.Implementations/BaseApplicationPaths.cs
  18. 123 0
      MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs
  19. 2 1
      MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs
  20. 2 9
      MediaBrowser.Common.Implementations/HttpServer/BaseRestService.cs
  21. 5 0
      MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj
  22. 2 1
      MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
  23. 2 1
      MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs
  24. 8 8
      MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs
  25. 10 10
      MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs
  26. 8 8
      MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs
  27. 17 8
      MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/SystemUpdateTask.cs
  28. 4 3
      MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs
  29. 23 14
      MediaBrowser.Common.Implementations/ServerManager/ServerManager.cs
  30. 42 22
      MediaBrowser.Common.Implementations/Updates/PackageManager.cs
  31. 68 0
      MediaBrowser.Common/Configuration/ConfigurationHelper.cs
  32. 1 1
      MediaBrowser.Common/Configuration/IApplicationPaths.cs
  33. 36 0
      MediaBrowser.Common/Configuration/IConfigurationManager.cs
  34. 1 7
      MediaBrowser.Common/IApplicationHost.cs
  35. 12 213
      MediaBrowser.Common/Kernel/BaseKernel.cs
  36. 2 44
      MediaBrowser.Common/Kernel/IKernel.cs
  37. 0 79
      MediaBrowser.Common/Kernel/ResourcePool.cs
  38. 4 6
      MediaBrowser.Common/MediaBrowser.Common.csproj
  39. 0 808
      MediaBrowser.Common/Net/Handlers/BaseHandler.cs
  40. 0 32
      MediaBrowser.Common/Net/Handlers/IHttpServerHandler.cs
  41. 0 264
      MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs
  42. 11 22
      MediaBrowser.Common/Plugins/BasePlugin.cs
  43. 1 0
      MediaBrowser.Common/Updates/ApplicationUpdater.cs
  44. 4 32
      MediaBrowser.Common/Updates/IPackageManager.cs
  45. 23 0
      MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs
  46. 6 6
      MediaBrowser.Controller/Drawing/ImageManager.cs
  47. 8 5
      MediaBrowser.Controller/Entities/BaseItem.cs
  48. 8 6
      MediaBrowser.Controller/Entities/User.cs
  49. 9 11
      MediaBrowser.Controller/IO/DirectoryWatchers.cs
  50. 6 4
      MediaBrowser.Controller/IO/FileSystemManager.cs
  51. 2 1
      MediaBrowser.Controller/IServerApplicationPaths.cs
  52. 38 61
      MediaBrowser.Controller/Kernel.cs
  53. 0 34
      MediaBrowser.Controller/Library/DtoBuilder.cs
  54. 19 5
      MediaBrowser.Controller/Library/ItemResolveArgs.cs
  55. 14 11
      MediaBrowser.Controller/Localization/LocalizedStrings.cs
  56. 7 5
      MediaBrowser.Controller/Localization/Ratings.cs
  57. 6 13
      MediaBrowser.Controller/Localization/RatingsDefinition.cs
  58. 1 4
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  59. 8 10
      MediaBrowser.Controller/MediaInfo/FFMpegManager.cs
  60. 11 2
      MediaBrowser.Controller/Providers/BaseMetadataProvider.cs
  61. 4 3
      MediaBrowser.Controller/Providers/FanartBaseProvider.cs
  62. 3 2
      MediaBrowser.Controller/Providers/FolderProviderFromXml.cs
  63. 3 2
      MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs
  64. 4 3
      MediaBrowser.Controller/Providers/ImagesByNameProvider.cs
  65. 3 2
      MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegImageProvider.cs
  66. 2 1
      MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegProvider.cs
  67. 3 2
      MediaBrowser.Controller/Providers/MediaInfo/BaseFFProbeProvider.cs
  68. 3 2
      MediaBrowser.Controller/Providers/MediaInfo/FFMpegAudioImageProvider.cs
  69. 6 3
      MediaBrowser.Controller/Providers/MediaInfo/FFMpegVideoImageProvider.cs
  70. 2 1
      MediaBrowser.Controller/Providers/MediaInfo/FFProbeAudioInfoProvider.cs
  71. 24 30
      MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs
  72. 46 18
      MediaBrowser.Controller/Providers/Movies/FanArtMovieProvider.cs
  73. 64 50
      MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs
  74. 3 2
      MediaBrowser.Controller/Providers/Movies/MovieProviderFromJson.cs
  75. 3 2
      MediaBrowser.Controller/Providers/Movies/MovieProviderFromXml.cs
  76. 3 2
      MediaBrowser.Controller/Providers/Movies/PersonProviderFromJson.cs
  77. 23 28
      MediaBrowser.Controller/Providers/Movies/TmdbPersonProvider.cs
  78. 28 26
      MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs
  79. 30 9
      MediaBrowser.Controller/Providers/ProviderManager.cs
  80. 9 7
      MediaBrowser.Controller/Providers/SortNameProvider.cs
  81. 3 2
      MediaBrowser.Controller/Providers/TV/EpisodeImageFromMediaLocationProvider.cs
  82. 3 2
      MediaBrowser.Controller/Providers/TV/EpisodeProviderFromXml.cs
  83. 15 13
      MediaBrowser.Controller/Providers/TV/FanArtTVProvider.cs
  84. 18 15
      MediaBrowser.Controller/Providers/TV/RemoteEpisodeProvider.cs
  85. 16 15
      MediaBrowser.Controller/Providers/TV/RemoteSeasonProvider.cs
  86. 49 20
      MediaBrowser.Controller/Providers/TV/RemoteSeriesProvider.cs
  87. 3 2
      MediaBrowser.Controller/Providers/TV/SeriesProviderFromXml.cs
  88. 4 3
      MediaBrowser.Controller/Updates/InstallationManager.cs
  89. 0 28
      MediaBrowser.Model/DTO/BaseItemDto.cs
  90. 55 0
      MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs
  91. 18 9
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  92. 9 1
      MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
  93. 13 4
      MediaBrowser.Server.Implementations/Library/UserManager.cs
  94. 1 0
      MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
  95. 2 1
      MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs
  96. 1 0
      MediaBrowser.Server.Implementations/Sqlite/SQLiteItemRepository.cs
  97. 2 1
      MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs
  98. 2 1
      MediaBrowser.Server.Implementations/Sqlite/SQLiteUserRepository.cs
  99. 0 1
      MediaBrowser.Server.Implementations/WorldWeatherOnline/WeatherProvider.cs
  100. 9 72
      MediaBrowser.ServerApplication/App.xaml.cs

+ 1 - 1
MediaBrowser.Api/Images/ImageService.cs

@@ -268,7 +268,7 @@ namespace MediaBrowser.Api.Images
         /// <exception cref="ResourceNotFoundException"></exception>
         private object GetImage(ImageRequest request, BaseItem item)
         {
-            var kernel = (Kernel)Kernel;
+            var kernel = Kernel.Instance;
 
             var index = request.Index ?? 0;
 

+ 2 - 1
MediaBrowser.Api/Library/LibraryService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Implementations.HttpServer;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Implementations.HttpServer;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;

+ 9 - 18
MediaBrowser.Api/PackageService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Implementations.HttpServer;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Controller;
@@ -108,13 +109,11 @@ namespace MediaBrowser.Api
         /// <exception cref="System.ArgumentException">Unsupported PackageType</exception>
         public object Get(GetPackageVersionUpdates request)
         {
-            var kernel = (Kernel)Kernel;
-
             var result = new List<PackageVersionInfo>();
 
             if (request.PackageType == PackageType.UserInstalled || request.PackageType == PackageType.All)
             {
-                result.AddRange(kernel.InstallationManager.GetAvailablePluginUpdates(false, CancellationToken.None).Result.ToList());
+                result.AddRange(Kernel.Instance.InstallationManager.GetAvailablePluginUpdates(false, CancellationToken.None).Result.ToList());
             }
 
             else if (request.PackageType == PackageType.System || request.PackageType == PackageType.All)
@@ -137,9 +136,7 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetPackage request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var packages = kernel.InstallationManager.GetAvailablePackages(CancellationToken.None, applicationVersion: ApplicationHost.ApplicationVersion).Result;
+            var packages = Kernel.Instance.InstallationManager.GetAvailablePackages(CancellationToken.None, applicationVersion: ApplicationHost.ApplicationVersion).Result;
 
             var result = packages.FirstOrDefault(p => p.name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
 
@@ -153,9 +150,7 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetPackages request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var packages = kernel.InstallationManager.GetAvailablePackages(CancellationToken.None, request.PackageType, ApplicationHost.ApplicationVersion).Result;
+            var packages = Kernel.Instance.InstallationManager.GetAvailablePackages(CancellationToken.None, request.PackageType, ApplicationHost.ApplicationVersion).Result;
 
             return ToOptimizedResult(packages.ToList());
         }
@@ -167,18 +162,16 @@ namespace MediaBrowser.Api
         /// <exception cref="ResourceNotFoundException"></exception>
         public void Post(InstallPackage request)
         {
-            var kernel = (Kernel)Kernel;
-
             var package = string.IsNullOrEmpty(request.Version) ?
-                kernel.InstallationManager.GetLatestCompatibleVersion(request.Name, request.UpdateClass).Result :
-                kernel.InstallationManager.GetPackage(request.Name, request.UpdateClass, Version.Parse(request.Version)).Result;
+                Kernel.Instance.InstallationManager.GetLatestCompatibleVersion(request.Name, request.UpdateClass).Result :
+                Kernel.Instance.InstallationManager.GetPackage(request.Name, request.UpdateClass, Version.Parse(request.Version)).Result;
 
             if (package == null)
             {
                 throw new ResourceNotFoundException(string.Format("Package not found: {0}", request.Name));
             }
 
-            Task.Run(() => kernel.InstallationManager.InstallPackage(package, new Progress<double> { }, CancellationToken.None));
+            Task.Run(() => Kernel.Instance.InstallationManager.InstallPackage(package, new Progress<double> { }, CancellationToken.None));
         }
 
         /// <summary>
@@ -187,9 +180,7 @@ namespace MediaBrowser.Api
         /// <param name="request">The request.</param>
         public void Delete(CancelPackageInstallation request)
         {
-            var kernel = (Kernel)Kernel;
-
-            var info = kernel.InstallationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id == request.Id);
+            var info = Kernel.Instance.InstallationManager.CurrentInstallations.FirstOrDefault(i => i.Item1.Id == request.Id);
 
             if (info != null)
             {

+ 20 - 22
MediaBrowser.Api/Playback/BaseStreamingService.cs

@@ -40,15 +40,12 @@ namespace MediaBrowser.Api.Playback
         /// </summary>
         /// <value>The library manager.</value>
         protected ILibraryManager LibraryManager { get; set; }
-        
+
         /// <summary>
-        /// Gets the server kernel.
+        /// Gets or sets the iso manager.
         /// </summary>
-        /// <value>The server kernel.</value>
-        protected Kernel ServerKernel
-        {
-            get { return Kernel as Kernel; }
-        }
+        /// <value>The iso manager.</value>
+        protected IIsoManager IsoManager { get; set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseStreamingService" /> class.
@@ -56,11 +53,13 @@ namespace MediaBrowser.Api.Playback
         /// <param name="appPaths">The app paths.</param>
         /// <param name="userManager">The user manager.</param>
         /// <param name="libraryManager">The library manager.</param>
-        protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
+        /// <param name="isoManager">The iso manager.</param>
+        protected BaseStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager)
         {
             ApplicationPaths = appPaths;
             UserManager = userManager;
             LibraryManager = libraryManager;
+            IsoManager = isoManager;
         }
 
         /// <summary>
@@ -307,11 +306,11 @@ namespace MediaBrowser.Api.Playback
         /// <returns>System.String.</returns>
         private string GetExtractedAssPath(Video video, MediaStream subtitleStream)
         {
-            var path = ServerKernel.FFMpegManager.GetSubtitleCachePath(video, subtitleStream.Index, ".ass");
+            var path = Kernel.Instance.FFMpegManager.GetSubtitleCachePath(video, subtitleStream.Index, ".ass");
 
             if (!File.Exists(path))
             {
-                var success = ServerKernel.FFMpegManager.ExtractTextSubtitle(video, subtitleStream.Index, path, CancellationToken.None).Result;
+                var success = Kernel.Instance.FFMpegManager.ExtractTextSubtitle(video, subtitleStream.Index, path, CancellationToken.None).Result;
 
                 if (!success)
                 {
@@ -330,11 +329,11 @@ namespace MediaBrowser.Api.Playback
         /// <returns>System.String.</returns>
         private string GetConvertedAssPath(Video video, MediaStream subtitleStream)
         {
-            var path = ServerKernel.FFMpegManager.GetSubtitleCachePath(video, subtitleStream.Index, ".ass");
+            var path = Kernel.Instance.FFMpegManager.GetSubtitleCachePath(video, subtitleStream.Index, ".ass");
 
             if (!File.Exists(path))
             {
-                var success = ServerKernel.FFMpegManager.ConvertTextSubtitle(subtitleStream, path, CancellationToken.None).Result;
+                var success = Kernel.Instance.FFMpegManager.ConvertTextSubtitle(subtitleStream, path, CancellationToken.None).Result;
 
                 if (!success)
                 {
@@ -476,8 +475,8 @@ namespace MediaBrowser.Api.Playback
         protected string GetInputArgument(BaseItem item, IIsoMount isoMount)
         {
             return isoMount == null ?
-                ServerKernel.FFMpegManager.GetInputArgument(item) :
-                ServerKernel.FFMpegManager.GetInputArgument(item as Video, isoMount);
+                Kernel.Instance.FFMpegManager.GetInputArgument(item) :
+                Kernel.Instance.FFMpegManager.GetInputArgument(item as Video, isoMount);
         }
 
         /// <summary>
@@ -490,11 +489,10 @@ namespace MediaBrowser.Api.Playback
         {
             var video = state.Item as Video;
 
-            //if (video != null && video.VideoType == VideoType.Iso &&
-            //    video.IsoType.HasValue && Kernel.IsoManager.CanMount(video.Path))
-            //{
-            //    IsoMount = await Kernel.IsoManager.Mount(video.Path, CancellationToken.None).ConfigureAwait(false);
-            //}
+            if (video != null && video.VideoType == VideoType.Iso && video.IsoType.HasValue && IsoManager.CanMount(video.Path))
+            {
+                state.IsoMount = await IsoManager.Mount(video.Path, CancellationToken.None).ConfigureAwait(false);
+            }
 
             var process = new Process
             {
@@ -507,8 +505,8 @@ namespace MediaBrowser.Api.Playback
                     RedirectStandardOutput = true,
                     RedirectStandardError = true,
 
-                    FileName = ServerKernel.FFMpegManager.FFMpegPath,
-                    WorkingDirectory = Path.GetDirectoryName(ServerKernel.FFMpegManager.FFMpegPath),
+                    FileName = Kernel.Instance.FFMpegManager.FFMpegPath,
+                    WorkingDirectory = Path.GetDirectoryName(Kernel.Instance.FFMpegManager.FFMpegPath),
                     Arguments = GetCommandLineArguments(outputPath, state),
 
                     WindowStyle = ProcessWindowStyle.Hidden,
@@ -522,7 +520,7 @@ namespace MediaBrowser.Api.Playback
 
             //Logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
 
-            var logFilePath = Path.Combine(Kernel.ApplicationPaths.LogDirectoryPath, "ffmpeg-" + Guid.NewGuid() + ".txt");
+            var logFilePath = Path.Combine(ApplicationPaths.LogDirectoryPath, "ffmpeg-" + Guid.NewGuid() + ".txt");
 
             // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory.
             state.LogFileStream = new FileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);

+ 4 - 8
MediaBrowser.Api/Playback/Hls/AudioHlsService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Dto;
 using System;
@@ -10,13 +11,8 @@ namespace MediaBrowser.Api.Playback.Hls
     /// </summary>
     public class AudioHlsService : BaseHlsService
     {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="AudioHlsService" /> class.
-        /// </summary>
-        /// <param name="appPaths">The app paths.</param>
-        /// <param name="userManager">The user manager.</param>
-        public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
-            : base(appPaths, userManager, libraryManager)
+        public AudioHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager)
+            : base(appPaths, userManager, libraryManager, isoManager)
         {
         }
 

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

@@ -17,8 +17,8 @@ namespace MediaBrowser.Api.Playback.Hls
         /// </summary>
         public const string SegmentFilePrefix = "segment-";
 
-        protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
-            : base(appPaths, userManager, libraryManager)
+        protected BaseHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager) 
+            : base(appPaths, userManager, libraryManager, isoManager)
         {
         }
 
@@ -174,9 +174,7 @@ namespace MediaBrowser.Api.Playback.Hls
 
             segmentOutputPath = Path.Combine(segmentOutputPath, segmentOutputName + "%03d." + GetSegmentFileExtension(state).TrimStart('.'));
 
-            var kernel = (Kernel)Kernel;
-
-            var probeSize = kernel.FFMpegManager.GetProbeSizeArgument(state.Item);
+            var probeSize = Kernel.Instance.FFMpegManager.GetProbeSizeArgument(state.Item);
 
             return string.Format("{0} {1} -i {2}{3} -threads 0 {4} {5} {6} -f ssegment -segment_list_flags +live -segment_time 9 -segment_list \"{7}\" \"{8}\"",
                 probeSize,

+ 4 - 8
MediaBrowser.Api/Playback/Hls/VideoHlsService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Library;
 using System;
 
@@ -6,13 +7,8 @@ namespace MediaBrowser.Api.Playback.Hls
 {
     public class VideoHlsService : BaseHlsService
     {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="VideoHlsService" /> class.
-        /// </summary>
-        /// <param name="appPaths">The app paths.</param>
-        /// <param name="userManager">The user manager.</param>
-        public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
-            : base(appPaths, userManager, libraryManager)
+        public VideoHlsService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager)
+            : base(appPaths, userManager, libraryManager, isoManager)
         {
         }
 

+ 4 - 7
MediaBrowser.Api/Playback/Progressive/AudioService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Library;
 using ServiceStack.ServiceHost;
 using System.Collections.Generic;
@@ -24,12 +25,8 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class AudioService : BaseProgressiveStreamingService
     {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BaseProgressiveStreamingService" /> class.
-        /// </summary>
-        /// <param name="appPaths">The app paths.</param>
-        public AudioService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
-            : base(appPaths, userManager, libraryManager)
+        public AudioService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager)
+            : base(appPaths, userManager, libraryManager, isoManager)
         {
         }
 

+ 4 - 7
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
@@ -14,12 +15,8 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public abstract class BaseProgressiveStreamingService : BaseStreamingService
     {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BaseProgressiveStreamingService" /> class.
-        /// </summary>
-        /// <param name="appPaths">The app paths.</param>
-        protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
-            : base(appPaths, userManager, libraryManager)
+        protected BaseProgressiveStreamingService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager) : 
+            base(appPaths, userManager, libraryManager, isoManager)
         {
         }
 

+ 5 - 8
MediaBrowser.Api/Playback/Progressive/VideoService.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
 using System;
 using MediaBrowser.Controller.Library;
@@ -30,12 +31,8 @@ namespace MediaBrowser.Api.Playback.Progressive
     /// </summary>
     public class VideoService : BaseProgressiveStreamingService
     {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="BaseProgressiveStreamingService" /> class.
-        /// </summary>
-        /// <param name="appPaths">The app paths.</param>
-        public VideoService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager)
-            : base(appPaths, userManager, libraryManager)
+        public VideoService(IServerApplicationPaths appPaths, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager) 
+            : base(appPaths, userManager, libraryManager, isoManager)
         {
         }
 
@@ -59,7 +56,7 @@ namespace MediaBrowser.Api.Playback.Progressive
         {
             var video = (Video)state.Item;
 
-            var probeSize = ServerKernel.FFMpegManager.GetProbeSizeArgument(video.VideoType, video.IsoType);
+            var probeSize = Kernel.Instance.FFMpegManager.GetProbeSizeArgument(video.VideoType, video.IsoType);
 
             // Get the output codec name
             var videoCodec = GetVideoCodec(state.Request);

+ 5 - 3
MediaBrowser.Api/Plugin.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Serialization;
@@ -13,9 +14,10 @@ namespace MediaBrowser.Api
         /// <summary>
         /// Initializes a new instance of the <see cref="Plugin" /> class.
         /// </summary>
-        /// <param name="kernel">The kernel.</param>
+        /// <param name="appPaths">The app paths.</param>
         /// <param name="xmlSerializer">The XML serializer.</param>
-        public Plugin(IKernel kernel, IXmlSerializer xmlSerializer) : base(kernel, xmlSerializer)
+        public Plugin(IApplicationPaths appPaths, IXmlSerializer xmlSerializer)
+            : base(appPaths, xmlSerializer)
         {
             Instance = this;
         }

+ 14 - 15
MediaBrowser.Api/PluginService.cs

@@ -1,6 +1,7 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Implementations.HttpServer;
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Security;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Plugins;
@@ -129,13 +130,16 @@ namespace MediaBrowser.Api
         /// </summary>
         private readonly IApplicationHost _appHost;
 
+        private readonly ISecurityManager _securityManager;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="PluginService" /> class.
         /// </summary>
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <param name="appHost">The app host.</param>
+        /// <param name="securityManager">The security manager.</param>
         /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
-        public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost)
+        public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost, ISecurityManager securityManager)
             : base()
         {
             if (jsonSerializer == null)
@@ -144,6 +148,7 @@ namespace MediaBrowser.Api
             }
 
             _appHost = appHost;
+            _securityManager = securityManager;
             _jsonSerializer = jsonSerializer;
         }
 
@@ -206,13 +211,11 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetPluginSecurityInfo request)
         {
-            var kernel = (Kernel)Kernel;
-
             var result = new PluginSecurityInfo
             {
-                IsMBSupporter = kernel.SecurityManager.IsMBSupporter,
-                SupporterKey = kernel.SecurityManager.SupporterKey,
-                LegacyKey = kernel.SecurityManager.LegacyKey
+                IsMBSupporter = _securityManager.IsMBSupporter,
+                SupporterKey = _securityManager.SupporterKey,
+                LegacyKey = _securityManager.LegacyKey
             };
 
             return ToOptimizedResult(result);
@@ -224,12 +227,10 @@ namespace MediaBrowser.Api
         /// <param name="request">The request.</param>
         public void Post(UpdatePluginSecurityInfo request)
         {
-            var kernel = (Kernel)Kernel;
-
             var info = _jsonSerializer.DeserializeFromStream<PluginSecurityInfo>(request.RequestStream);
 
-            kernel.SecurityManager.SupporterKey = info.SupporterKey;
-            kernel.SecurityManager.LegacyKey = info.LegacyKey;
+            _securityManager.SupporterKey = info.SupporterKey;
+            _securityManager.LegacyKey = info.LegacyKey;
         }
 
         /// <summary>
@@ -256,11 +257,9 @@ namespace MediaBrowser.Api
         /// <param name="request">The request.</param>
         public void Delete(UninstallPlugin request)
         {
-            var kernel = (Kernel)Kernel;
-
             var plugin = _appHost.Plugins.First(p => p.Id == request.Id);
 
-            kernel.InstallationManager.UninstallPlugin(plugin);
+            Kernel.Instance.InstallationManager.UninstallPlugin(plugin);
         }
     }
 }

+ 17 - 13
MediaBrowser.Api/SystemService.cs

@@ -1,7 +1,8 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Implementations.HttpServer;
-using MediaBrowser.Common.Kernel;
 using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.System;
@@ -72,13 +73,19 @@ namespace MediaBrowser.Api
         /// </summary>
         private readonly IApplicationHost _appHost;
 
+        /// <summary>
+        /// The _configuration manager
+        /// </summary>
+        private readonly IServerConfigurationManager _configurationManager;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="SystemService" /> class.
         /// </summary>
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <param name="appHost">The app host.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
         /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
-        public SystemService(IJsonSerializer jsonSerializer, IApplicationHost appHost)
+        public SystemService(IJsonSerializer jsonSerializer, IApplicationHost appHost, IServerConfigurationManager configurationManager)
             : base()
         {
             if (jsonSerializer == null)
@@ -91,6 +98,7 @@ namespace MediaBrowser.Api
             }
 
             _appHost = appHost;
+            _configurationManager = configurationManager;
             _jsonSerializer = jsonSerializer;
         }
 
@@ -101,7 +109,7 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetSystemInfo request)
         {
-            var result = Kernel.GetSystemInfo();
+            var result = Kernel.Instance.GetSystemInfo();
 
             return ToOptimizedResult(result);
         }
@@ -113,13 +121,11 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetConfiguration request)
         {
-            var kernel = (Kernel)Kernel;
+            var dateModified = File.GetLastWriteTimeUtc(_configurationManager.ApplicationPaths.SystemConfigurationFilePath);
 
-            var dateModified = File.GetLastWriteTimeUtc(Kernel.ApplicationPaths.SystemConfigurationFilePath);
+            var cacheKey = (_configurationManager.ApplicationPaths.SystemConfigurationFilePath + dateModified.Ticks).GetMD5();
 
-            var cacheKey = (Kernel.ApplicationPaths.SystemConfigurationFilePath + dateModified.Ticks).GetMD5();
-
-            return ToOptimizedResultUsingCache(cacheKey, dateModified, null, () => kernel.Configuration);
+            return ToOptimizedResultUsingCache(cacheKey, dateModified, null, () => _configurationManager.Configuration);
         }
 
         /// <summary>
@@ -131,7 +137,7 @@ namespace MediaBrowser.Api
             Task.Run(async () =>
             {
                 await Task.Delay(100);
-                Kernel.PerformPendingRestart();
+                Kernel.Instance.PerformPendingRestart();
             });
         }
 
@@ -156,9 +162,7 @@ namespace MediaBrowser.Api
         {
             var serverConfig = _jsonSerializer.DeserializeFromStream<ServerConfiguration>(request.RequestStream);
 
-            var kernel = (Kernel)Kernel;
-
-            kernel.UpdateConfiguration(serverConfig);
+            _configurationManager.ReplaceConfiguration(serverConfig);
         }
     }
 }

+ 0 - 4
MediaBrowser.Api/UserService.cs

@@ -181,8 +181,6 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetUsers request)
         {
-            var kernel = (Kernel)Kernel;
-
             var dtoBuilder = new DtoBuilder(Logger);
 
             var result = _userManager.Users.OrderBy(u => u.Name).Select(dtoBuilder.GetDtoUser).ToList();
@@ -312,8 +310,6 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Post(CreateUser request)
         {
-            var kernel = (Kernel)Kernel;
-
             var dtoUser = _jsonSerializer.DeserializeFromStream<UserDto>(request.RequestStream);
 
             var newUser = _userManager.CreateUser(dtoUser.Name).Result;

+ 1 - 5
MediaBrowser.Api/WeatherService.cs

@@ -32,11 +32,7 @@ namespace MediaBrowser.Api
         /// <returns>System.Object.</returns>
         public object Get(GetWeather request)
         {
-            var kernel = (Kernel) Kernel;
-
-            var location = string.IsNullOrWhiteSpace(request.Location) ? kernel.Configuration.WeatherLocation : request.Location;
-
-            var result = kernel.WeatherProviders.First().GetWeatherInfoAsync(location, CancellationToken.None).Result;
+            var result = Kernel.Instance.WeatherProviders.First().GetWeatherInfoAsync(request.Location, CancellationToken.None).Result;
 
             return ToOptimizedResult(result);
         }

+ 98 - 27
MediaBrowser.Common.Implementations/BaseApplicationHost.cs

@@ -1,4 +1,9 @@
-using System.Threading.Tasks;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Implementations.Logging;
+using MediaBrowser.Common.Implementations.NetworkManagement;
+using MediaBrowser.Common.Implementations.ScheduledTasks;
+using MediaBrowser.Common.Implementations.Security;
+using MediaBrowser.Common.Implementations.Serialization;
 using MediaBrowser.Common.Implementations.Udp;
 using MediaBrowser.Common.Implementations.Updates;
 using MediaBrowser.Common.Implementations.WebSocket;
@@ -6,9 +11,11 @@ using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Plugins;
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Common.Security;
 using MediaBrowser.Common.Updates;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
+using MediaBrowser.Model.Updates;
 using SimpleInjector;
 using System;
 using System.Collections.Generic;
@@ -16,16 +23,18 @@ using System.IO;
 using System.Linq;
 using System.Reflection;
 using System.Threading;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Common.Implementations
 {
-    public abstract class BaseApplicationHost
+    public abstract class BaseApplicationHost<TApplicationPathsType> : IApplicationHost
+        where TApplicationPathsType : class, IApplicationPaths, new()
     {
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>
         /// <value>The logger.</value>
-        public ILogger Logger { get; protected set; }
+        protected ILogger Logger { get; private set; }
 
         /// <summary>
         /// Gets or sets the plugins.
@@ -43,13 +52,23 @@ namespace MediaBrowser.Common.Implementations
         /// Gets the application paths.
         /// </summary>
         /// <value>The application paths.</value>
-        protected IApplicationPaths ApplicationPaths { get; private set; }
+        protected TApplicationPathsType ApplicationPaths = new TApplicationPathsType();
 
         /// <summary>
         /// The container
         /// </summary>
         protected readonly Container Container = new Container();
 
+        /// <summary>
+        /// The json serializer
+        /// </summary>
+        protected readonly IJsonSerializer JsonSerializer = new JsonSerializer();
+
+        /// <summary>
+        /// The _XML serializer
+        /// </summary>
+        protected readonly IXmlSerializer XmlSerializer = new XmlSerializer();
+
         /// <summary>
         /// Gets assemblies that failed to load
         /// </summary>
@@ -109,12 +128,26 @@ namespace MediaBrowser.Common.Implementations
             }
         }
 
+        /// <summary>
+        /// Gets the kernel.
+        /// </summary>
+        /// <value>The kernel.</value>
+        protected IKernel Kernel { get; private set; }
+        protected ITaskManager TaskManager { get; private set; }
+        protected ISecurityManager SecurityManager { get; private set; }
+
+        protected IConfigurationManager ConfigurationManager { get; private set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseApplicationHost" /> class.
         /// </summary>
         protected BaseApplicationHost()
         {
             FailedAssemblies = new List<string>();
+
+            LogManager = new NlogManager(ApplicationPaths.LogDirectoryPath, LogFilePrefixName);
+
+            ConfigurationManager = GetConfigurationManager();
         }
 
         /// <summary>
@@ -125,15 +158,25 @@ namespace MediaBrowser.Common.Implementations
         {
             return Task.Run(() =>
             {
-                ApplicationPaths = GetApplicationPaths();
-
-                LogManager = GetLogManager();
-
                 Logger = LogManager.GetLogger("App");
 
                 IsFirstRun = !File.Exists(ApplicationPaths.SystemConfigurationFilePath);
 
                 DiscoverTypes();
+
+                LogManager.ReloadLogger(ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging ? LogSeverity.Debug : LogSeverity.Info);
+
+                Logger.Info("Version {0} initializing", ApplicationVersion);
+
+                Kernel = GetKernel();
+
+                RegisterResources();
+
+                FindParts();
+
+                Task.Run(() => ConfigureAutoRunAtStartup());
+
+                Kernel.Init();
             });
         }
 
@@ -144,16 +187,13 @@ namespace MediaBrowser.Common.Implementations
         protected abstract IEnumerable<Assembly> GetComposablePartAssemblies();
 
         /// <summary>
-        /// Gets the log manager.
+        /// Gets the name of the log file prefix.
         /// </summary>
-        /// <returns>ILogManager.</returns>
-        protected abstract ILogManager GetLogManager();
+        /// <value>The name of the log file prefix.</value>
+        protected abstract string LogFilePrefixName { get; }
 
-        /// <summary>
-        /// Gets the application paths.
-        /// </summary>
-        /// <returns>IApplicationPaths.</returns>
-        protected abstract IApplicationPaths GetApplicationPaths();
+        protected abstract IKernel GetKernel();
+        protected abstract IConfigurationManager GetConfigurationManager();
 
         /// <summary>
         /// Finds the parts.
@@ -184,21 +224,44 @@ namespace MediaBrowser.Common.Implementations
         /// <summary>
         /// Registers resources that classes will depend on
         /// </summary>
-        protected virtual void RegisterResources(ITaskManager taskManager, INetworkManager networkManager, IServerManager serverManager)
+        protected virtual void RegisterResources()
         {
+            RegisterSingleInstance(ConfigurationManager);
+            RegisterSingleInstance<IApplicationHost>(this);
+
+            RegisterSingleInstance<IApplicationPaths>(ApplicationPaths);
+
+            var networkManager = new NetworkManager();
+
+            var serverManager = new ServerManager.ServerManager(this, Kernel, networkManager, JsonSerializer, Logger, ConfigurationManager);
+
+            TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, Logger, serverManager);
+
+            RegisterSingleInstance(JsonSerializer);
+            RegisterSingleInstance(XmlSerializer);
+
             RegisterSingleInstance(LogManager);
             RegisterSingleInstance(Logger);
 
-            RegisterSingleInstance(ApplicationPaths);
-            RegisterSingleInstance(taskManager);
+            RegisterSingleInstance(Kernel);
+
+            RegisterSingleInstance(TaskManager);
             RegisterSingleInstance<IWebSocketServer>(() => new AlchemyServer(Logger));
             RegisterSingleInstance(ProtobufSerializer);
             RegisterSingleInstance<IUdpServer>(new UdpServer(Logger), false);
-            RegisterSingleInstance<IPackageManager>(new PackageManager());
-            RegisterSingleInstance<IHttpClient>(new HttpClientManager.HttpClientManager(ApplicationPaths, Logger));
 
-            RegisterSingleInstance(networkManager);
-            RegisterSingleInstance(serverManager);
+            var httpClient = new HttpClientManager.HttpClientManager(ApplicationPaths, Logger);
+
+            RegisterSingleInstance<IHttpClient>(httpClient);
+
+            RegisterSingleInstance<INetworkManager>(networkManager);
+            RegisterSingleInstance<IServerManager>(serverManager);
+
+            SecurityManager = new PluginSecurityManager(Kernel, httpClient, JsonSerializer, ApplicationPaths);
+
+            RegisterSingleInstance(SecurityManager);
+
+            RegisterSingleInstance<IPackageManager>(new PackageManager(SecurityManager, networkManager, httpClient, ApplicationPaths, JsonSerializer, Logger));
         }
 
         /// <summary>
@@ -336,7 +399,7 @@ namespace MediaBrowser.Common.Implementations
 
             Logger.Info("Composing instances of " + currentType.Name);
 
-            var parts = AllConcreteTypes.Where(currentType.IsAssignableFrom).Select(CreateInstance).Cast<T>().ToArray();
+            var parts = AllConcreteTypes.AsParallel().Where(currentType.IsAssignableFrom).Select(CreateInstance).Cast<T>().ToArray();
 
             if (manageLiftime)
             {
@@ -361,10 +424,8 @@ namespace MediaBrowser.Common.Implementations
         /// <summary>
         /// Configures the auto run at startup.
         /// </summary>
-        /// <param name="autorun">if set to <c>true</c> [autorun].</param>
-        public void ConfigureAutoRunAtStartup(bool autorun)
+        private void ConfigureAutoRunAtStartup()
         {
-
         }
 
         /// <summary>
@@ -409,5 +470,15 @@ namespace MediaBrowser.Common.Implementations
                 }
             }
         }
+
+        public abstract void Restart();
+
+        public abstract bool CanSelfUpdate { get; }
+
+        public abstract Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress);
+
+        public abstract Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress<double> progress);
+
+        public abstract void Shutdown();
     }
 }

+ 2 - 1
MediaBrowser.Common.Implementations/BaseApplicationPaths.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using System;
 using System.Configuration;
 using System.IO;

+ 123 - 0
MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs

@@ -0,0 +1,123 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using System;
+using System.Threading;
+
+namespace MediaBrowser.Common.Implementations.Configuration
+{
+    /// <summary>
+    /// Class BaseConfigurationManager
+    /// </summary>
+    public abstract class BaseConfigurationManager : IConfigurationManager
+    {
+        /// <summary>
+        /// Gets the type of the configuration.
+        /// </summary>
+        /// <value>The type of the configuration.</value>
+        protected abstract Type ConfigurationType { get; }
+
+        /// <summary>
+        /// Occurs when [configuration updated].
+        /// </summary>
+        public event EventHandler<EventArgs> ConfigurationUpdated;
+
+        /// <summary>
+        /// Gets the logger.
+        /// </summary>
+        /// <value>The logger.</value>
+        protected ILogger Logger { get; private set; }
+        /// <summary>
+        /// Gets the XML serializer.
+        /// </summary>
+        /// <value>The XML serializer.</value>
+        protected IXmlSerializer XmlSerializer { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        public IApplicationPaths CommonApplicationPaths { get; private set; }
+
+        /// <summary>
+        /// The _configuration loaded
+        /// </summary>
+        private bool _configurationLoaded;
+        /// <summary>
+        /// The _configuration sync lock
+        /// </summary>
+        private object _configurationSyncLock = new object();
+        /// <summary>
+        /// The _configuration
+        /// </summary>
+        private BaseApplicationConfiguration _configuration;
+        /// <summary>
+        /// Gets the system configuration
+        /// </summary>
+        /// <value>The configuration.</value>
+        public BaseApplicationConfiguration CommonConfiguration
+        {
+            get
+            {
+                // Lazy load
+                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer));
+                return _configuration;
+            }
+            protected set
+            {
+                _configuration = value;
+
+                _configurationLoaded = value != null;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BaseConfigurationManager" /> class.
+        /// </summary>
+        /// <param name="applicationPaths">The application paths.</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="xmlSerializer">The XML serializer.</param>
+        protected BaseConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer)
+        {
+            CommonApplicationPaths = applicationPaths;
+            XmlSerializer = xmlSerializer;
+            Logger = logManager.GetLogger(GetType().Name);
+        }
+
+        /// <summary>
+        /// The _save lock
+        /// </summary>
+        private readonly object _configurationSaveLock = new object();
+
+        /// <summary>
+        /// Saves the configuration.
+        /// </summary>
+        public void SaveConfiguration()
+        {
+            lock (_configurationSaveLock)
+            {
+                XmlSerializer.SerializeToFile(CommonConfiguration, CommonApplicationPaths.SystemConfigurationFilePath);
+            } 
+            
+            EventHelper.QueueEventIfNotNull(ConfigurationUpdated, this, EventArgs.Empty, Logger);
+        }
+
+        /// <summary>
+        /// Replaces the configuration.
+        /// </summary>
+        /// <param name="newConfiguration">The new configuration.</param>
+        /// <exception cref="System.ArgumentNullException">newConfiguration</exception>
+        public void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration)
+        {
+            if (newConfiguration == null)
+            {
+                throw new ArgumentNullException("newConfiguration");
+            }
+
+            CommonConfiguration = newConfiguration;
+            SaveConfiguration();
+        }
+    }
+}

+ 2 - 1
MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Model.Logging;

+ 2 - 9
MediaBrowser.Common.Implementations/HttpServer/BaseRestService.cs

@@ -1,7 +1,5 @@
-using System.Collections.Generic;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Model.Logging;
 using ServiceStack.Common;
@@ -9,6 +7,7 @@ using ServiceStack.Common.Web;
 using ServiceStack.ServiceHost;
 using ServiceStack.ServiceInterface;
 using System;
+using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
@@ -22,12 +21,6 @@ namespace MediaBrowser.Common.Implementations.HttpServer
     /// </summary>
     public class BaseRestService : Service, IRestfulService
     {
-        /// <summary>
-        /// Gets or sets the kernel.
-        /// </summary>
-        /// <value>The kernel.</value>
-        public IKernel Kernel { get; set; }
-
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>

+ 5 - 0
MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj

@@ -38,6 +38,9 @@
     <Reference Include="Alchemy">
       <HintPath>..\packages\Alchemy.2.2.1\lib\net40\Alchemy.dll</HintPath>
     </Reference>
+    <Reference Include="Mediabrowser.PluginSecurity">
+      <HintPath>..\ThirdParty\PluginSecurity\Mediabrowser.PluginSecurity.dll</HintPath>
+    </Reference>
     <Reference Include="NLog">
       <HintPath>..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll</HintPath>
     </Reference>
@@ -104,6 +107,7 @@
     </Compile>
     <Compile Include="BaseApplicationHost.cs" />
     <Compile Include="BaseApplicationPaths.cs" />
+    <Compile Include="Configuration\BaseConfigurationManager.cs" />
     <Compile Include="HttpClientManager\HttpClientManager.cs" />
     <Compile Include="HttpServer\BaseRestService.cs" />
     <Compile Include="HttpServer\HttpServer.cs" />
@@ -123,6 +127,7 @@
     <Compile Include="ScheduledTasks\Tasks\DeleteLogFileTask.cs" />
     <Compile Include="ScheduledTasks\Tasks\ReloadLoggerTask.cs" />
     <Compile Include="ScheduledTasks\Tasks\SystemUpdateTask.cs" />
+    <Compile Include="Security\PluginSecurityManager.cs" />
     <Compile Include="Serialization\JsonSerializer.cs" />
     <Compile Include="Serialization\ProtobufSerializer.cs" />
     <Compile Include="Serialization\XmlSerializer.cs" />

+ 2 - 1
MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Logging;

+ 2 - 1
MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;

+ 8 - 8
MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Logging;
 using System;
@@ -16,10 +16,10 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
     public class DeleteCacheFileTask : IScheduledTask
     {
         /// <summary>
-        /// Gets or sets the kernel.
+        /// Gets or sets the application paths.
         /// </summary>
-        /// <value>The kernel.</value>
-        private IKernel Kernel { get; set; }
+        /// <value>The application paths.</value>
+        private IApplicationPaths ApplicationPaths { get; set; }
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>
@@ -29,11 +29,11 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
         /// <summary>
         /// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
         /// </summary>
-        /// <param name="kernel">The kernel.</param>
+        /// <param name="appPaths">The app paths.</param>
         /// <param name="logger">The logger.</param>
-        public DeleteCacheFileTask(IKernel kernel, ILogger logger)
+        public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger)
         {
-            Kernel = kernel;
+            ApplicationPaths = appPaths;
             Logger = logger;
         }
 
@@ -60,7 +60,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
             {
                 var minDateModified = DateTime.UtcNow.AddMonths(-2);
 
-                DeleteCacheFilesFromDirectory(cancellationToken, Kernel.ApplicationPaths.CachePath, minDateModified, progress);
+                DeleteCacheFilesFromDirectory(cancellationToken, ApplicationPaths.CachePath, minDateModified, progress);
             });
         }
 

+ 10 - 10
MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Logging;
 using System;
@@ -16,10 +16,10 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
     public class DeleteLogFileTask : IScheduledTask
     {
         /// <summary>
-        /// Gets or sets the kernel.
+        /// Gets or sets the configuration manager.
         /// </summary>
-        /// <value>The kernel.</value>
-        private IKernel Kernel { get; set; }
+        /// <value>The configuration manager.</value>
+        private IConfigurationManager ConfigurationManager { get; set; }
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>
@@ -29,11 +29,11 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
         /// <summary>
         /// Initializes a new instance of the <see cref="DeleteLogFileTask" /> class.
         /// </summary>
-        /// <param name="kernel">The kernel.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
         /// <param name="logger">The logger.</param>
-        public DeleteLogFileTask(IKernel kernel, ILogger logger)
+        public DeleteLogFileTask(IConfigurationManager configurationManager, ILogger logger)
         {
-            Kernel = kernel;
+            ConfigurationManager = configurationManager;
             Logger = logger;
         }
 
@@ -59,9 +59,9 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
             return Task.Run(() =>
             {
                 // Delete log files more than n days old
-                var minDateModified = DateTime.UtcNow.AddDays(-(Kernel.Configuration.LogFileRetentionDays));
+                var minDateModified = DateTime.UtcNow.AddDays(-(ConfigurationManager.CommonConfiguration.LogFileRetentionDays));
 
-                var filesToDelete = new DirectoryInfo(Kernel.ApplicationPaths.LogDirectoryPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories)
+                var filesToDelete = new DirectoryInfo(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories)
                               .Where(f => f.LastWriteTimeUtc < minDateModified)
                               .ToList();
 
@@ -100,7 +100,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
         /// <value>The description.</value>
         public string Description
         {
-            get { return string.Format("Deletes log files that are more than {0} days old.", Kernel.Configuration.LogFileRetentionDays); }
+            get { return string.Format("Deletes log files that are more than {0} days old.", ConfigurationManager.CommonConfiguration.LogFileRetentionDays); }
         }
 
         /// <summary>

+ 8 - 8
MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/ReloadLoggerTask.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Logging;
 using System;
@@ -24,22 +24,22 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
         /// <value>The logger.</value>
         private ILogger Logger { get; set; }
         /// <summary>
-        /// Gets or sets the kernel.
+        /// Gets or sets the configuration manager.
         /// </summary>
-        /// <value>The kernel.</value>
-        private IKernel Kernel { get; set; }
+        /// <value>The configuration manager.</value>
+        private IConfigurationManager ConfigurationManager { get; set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ReloadLoggerFileTask" /> class.
         /// </summary>
         /// <param name="logManager">The logManager.</param>
         /// <param name="logger">The logger.</param>
-        /// <param name="kernel">The kernel.</param>
-        public ReloadLoggerFileTask(ILogManager logManager, ILogger logger, IKernel kernel)
+        /// <param name="configurationManager">The configuration manager.</param>
+        public ReloadLoggerFileTask(ILogManager logManager, ILogger logger, IConfigurationManager configurationManager)
         {
             LogManager = logManager;
             Logger = logger;
-            Kernel = kernel;
+            ConfigurationManager = configurationManager;
         }
 
         /// <summary>
@@ -65,7 +65,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
 
             progress.Report(0);
 
-            return Task.Run(() => LogManager.ReloadLogger(Kernel.Configuration.EnableDebugLevelLogging ? LogSeverity.Debug : LogSeverity.Info));
+            return Task.Run(() => LogManager.ReloadLogger(ConfigurationManager.CommonConfiguration.EnableDebugLevelLogging ? LogSeverity.Debug : LogSeverity.Info));
         }
 
         /// <summary>

+ 17 - 8
MediaBrowser.Common.Implementations/ScheduledTasks/Tasks/SystemUpdateTask.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Model.Logging;
 using System;
@@ -19,27 +20,35 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
         private readonly IApplicationHost _appHost;
 
         /// <summary>
-        /// Gets or sets the kernel.
+        /// Gets or sets the configuration manager.
         /// </summary>
-        /// <value>The kernel.</value>
-        private IKernel Kernel { get; set; }
+        /// <value>The configuration manager.</value>
+        private IConfigurationManager ConfigurationManager { get; set; }
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>
         /// <value>The logger.</value>
         private ILogger Logger { get; set; }
 
+        /// <summary>
+        /// Gets or sets the kernel.
+        /// </summary>
+        /// <value>The kernel.</value>
+        private IKernel Kernel { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="SystemUpdateTask" /> class.
         /// </summary>
         /// <param name="appHost">The app host.</param>
-        /// <param name="kernel">The kernel.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
         /// <param name="logger">The logger.</param>
-        public SystemUpdateTask(IApplicationHost appHost, IKernel kernel, ILogger logger)
+        /// <param name="kernel">The kernel.</param>
+        public SystemUpdateTask(IApplicationHost appHost, IConfigurationManager configurationManager, ILogger logger, IKernel kernel)
         {
             _appHost = appHost;
-            Kernel = kernel;
+            ConfigurationManager = configurationManager;
             Logger = logger;
+            Kernel = kernel;
         }
 
         /// <summary>
@@ -88,7 +97,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks.Tasks
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            if (Kernel.Configuration.EnableAutoUpdate)
+            if (ConfigurationManager.CommonConfiguration.EnableAutoUpdate)
             {
                 Logger.Info("Update Revision {0} available.  Updating...", updateInfo.AvailableVersion);
 

+ 4 - 3
MediaBrowser.Controller/Plugins/PluginSecurityManager.cs → MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Security;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Security;
 using MediaBrowser.Model.Serialization;
 using Mediabrowser.Model.Entities;
 using Mediabrowser.PluginSecurity;
@@ -8,7 +9,7 @@ using System;
 using System.Threading;
 using System.Threading.Tasks;
 
-namespace MediaBrowser.Controller.Plugins
+namespace MediaBrowser.Common.Implementations.Security
 {
     /// <summary>
     /// Class PluginSecurityManager
@@ -68,7 +69,7 @@ namespace MediaBrowser.Controller.Plugins
             _kernel = kernel;
             _httpClient = httpClient;
             _jsonSerializer = jsonSerializer;
-            MBRegistration.Init(appPaths);
+            //MBRegistration.Init(appPaths);
         }
 
         /// <summary>

+ 23 - 14
MediaBrowser.Common.Implementations/ServerManager/ServerManager.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
@@ -77,6 +78,12 @@ namespace MediaBrowser.Common.Implementations.ServerManager
         /// </summary>
         private readonly IKernel _kernel;
 
+        /// <summary>
+        /// Gets or sets the configuration manager.
+        /// </summary>
+        /// <value>The configuration manager.</value>
+        private IConfigurationManager ConfigurationManager { get; set; }
+
         /// <summary>
         /// Gets a value indicating whether [supports web socket].
         /// </summary>
@@ -92,14 +99,14 @@ namespace MediaBrowser.Common.Implementations.ServerManager
         /// <value>The web socket port number.</value>
         public int WebSocketPortNumber
         {
-            get { return SupportsNativeWebSocket ? _kernel.Configuration.HttpServerPortNumber : _kernel.Configuration.LegacyWebSocketPortNumber; }
+            get { return SupportsNativeWebSocket ? ConfigurationManager.CommonConfiguration.HttpServerPortNumber : ConfigurationManager.CommonConfiguration.LegacyWebSocketPortNumber; }
         }
 
         /// <summary>
         /// Gets the web socket listeners.
         /// </summary>
         /// <value>The web socket listeners.</value>
-        private List<IWebSocketListener> WebSocketListeners = new List<IWebSocketListener>();
+        private readonly List<IWebSocketListener> _webSocketListeners = new List<IWebSocketListener>();
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ServerManager" /> class.
@@ -109,8 +116,9 @@ namespace MediaBrowser.Common.Implementations.ServerManager
         /// <param name="networkManager">The network manager.</param>
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <param name="logger">The logger.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
         /// <exception cref="System.ArgumentNullException">applicationHost</exception>
-        public ServerManager(IApplicationHost applicationHost, IKernel kernel, INetworkManager networkManager, IJsonSerializer jsonSerializer, ILogger logger)
+        public ServerManager(IApplicationHost applicationHost, IKernel kernel, INetworkManager networkManager, IJsonSerializer jsonSerializer, ILogger logger, IConfigurationManager configurationManager)
         {
             if (applicationHost == null)
             {
@@ -138,6 +146,7 @@ namespace MediaBrowser.Common.Implementations.ServerManager
             _kernel = kernel;
             _applicationHost = applicationHost;
             _networkManager = networkManager;
+            ConfigurationManager = configurationManager;
         }
 
         /// <summary>
@@ -158,7 +167,7 @@ namespace MediaBrowser.Common.Implementations.ServerManager
                 ReloadExternalWebSocketServer();
             }
 
-            _kernel.ConfigurationUpdated += _kernel_ConfigurationUpdated;
+            ConfigurationManager.ConfigurationUpdated += _kernel_ConfigurationUpdated;
         }
 
         /// <summary>
@@ -176,7 +185,7 @@ namespace MediaBrowser.Common.Implementations.ServerManager
 
             ExternalWebSocketServer = _applicationHost.Resolve<IWebSocketServer>();
 
-            ExternalWebSocketServer.Start(_kernel.Configuration.LegacyWebSocketPortNumber);
+            ExternalWebSocketServer.Start(ConfigurationManager.CommonConfiguration.LegacyWebSocketPortNumber);
             ExternalWebSocketServer.WebSocketConnected += HttpServer_WebSocketConnected;
         }
 
@@ -199,7 +208,7 @@ namespace MediaBrowser.Common.Implementations.ServerManager
             try
             {
                 HttpServer = _applicationHost.Resolve<IHttpServer>();
-                HttpServer.EnableHttpRequestLogging = _kernel.Configuration.EnableHttpLevelLogging;
+                HttpServer.EnableHttpRequestLogging = ConfigurationManager.CommonConfiguration.EnableHttpLevelLogging;
                 HttpServer.Start(_kernel.HttpServerUrlPrefix);
             }
             catch (HttpListenerException ex)
@@ -240,7 +249,7 @@ namespace MediaBrowser.Common.Implementations.ServerManager
         /// <param name="result">The result.</param>
         private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result)
         {
-            var tasks = WebSocketListeners.Select(i => Task.Run(async () =>
+            var tasks = _webSocketListeners.Select(i => Task.Run(async () =>
             {
                 try
                 {
@@ -435,7 +444,7 @@ namespace MediaBrowser.Common.Implementations.ServerManager
         private void RegisterServerWithAdministratorAccess()
         {
             // Create a temp file path to extract the bat file to
-            var tmpFile = Path.Combine(_kernel.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".bat");
+            var tmpFile = Path.Combine(ConfigurationManager.CommonApplicationPaths.TempDirectory, Guid.NewGuid() + ".bat");
 
             // Extract the bat file
             using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Common.Implementations.ServerManager.RegisterServer.bat"))
@@ -450,10 +459,10 @@ namespace MediaBrowser.Common.Implementations.ServerManager
             {
                 FileName = tmpFile,
 
-                Arguments = string.Format("{0} {1} {2} {3}", _kernel.Configuration.HttpServerPortNumber,
+                Arguments = string.Format("{0} {1} {2} {3}", ConfigurationManager.CommonConfiguration.HttpServerPortNumber,
                 _kernel.HttpServerUrlPrefix,
                 _kernel.UdpServerPortNumber,
-                _kernel.Configuration.LegacyWebSocketPortNumber),
+                ConfigurationManager.CommonConfiguration.LegacyWebSocketPortNumber),
 
                 CreateNoWindow = true,
                 WindowStyle = ProcessWindowStyle.Hidden,
@@ -508,14 +517,14 @@ namespace MediaBrowser.Common.Implementations.ServerManager
         /// <exception cref="System.NotImplementedException"></exception>
         void _kernel_ConfigurationUpdated(object sender, EventArgs e)
         {
-            HttpServer.EnableHttpRequestLogging = _kernel.Configuration.EnableHttpLevelLogging;
+            HttpServer.EnableHttpRequestLogging = ConfigurationManager.CommonConfiguration.EnableHttpLevelLogging;
 
             if (!string.Equals(HttpServer.UrlPrefix, _kernel.HttpServerUrlPrefix, StringComparison.OrdinalIgnoreCase))
             {
                 ReloadHttpServer();
             }
 
-            if (!SupportsNativeWebSocket && ExternalWebSocketServer != null && ExternalWebSocketServer.Port != _kernel.Configuration.LegacyWebSocketPortNumber)
+            if (!SupportsNativeWebSocket && ExternalWebSocketServer != null && ExternalWebSocketServer.Port != ConfigurationManager.CommonConfiguration.LegacyWebSocketPortNumber)
             {
                 ReloadExternalWebSocketServer();
             }
@@ -527,7 +536,7 @@ namespace MediaBrowser.Common.Implementations.ServerManager
         /// <param name="listeners">The listeners.</param>
         public void AddWebSocketListeners(IEnumerable<IWebSocketListener> listeners)
         {
-            WebSocketListeners.AddRange(listeners);
+            _webSocketListeners.AddRange(listeners);
         }
     }
 }

+ 42 - 22
MediaBrowser.Common.Implementations/Updates/PackageManager.cs

@@ -1,37 +1,57 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Security;
 using MediaBrowser.Common.Updates;
-using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Updates;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Threading;
+using System.Threading.Tasks;
 
 namespace MediaBrowser.Common.Implementations.Updates
 {
     public class PackageManager : IPackageManager
     {
-        public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(IHttpClient client, 
-            INetworkManager networkManager, 
-            ISecurityManager securityManager, 
-            ResourcePool resourcePool, 
-            IJsonSerializer serializer, 
-            CancellationToken cancellationToken)
+        private readonly ISecurityManager _securityManager;
+        private readonly INetworkManager _networkManager;
+        private readonly IHttpClient _httpClient;
+        private readonly IApplicationPaths _appPaths;
+        private readonly IJsonSerializer _jsonSerializer;
+        private readonly ILogger _logger;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PackageManager" /> class.
+        /// </summary>
+        /// <param name="securityManager">The security manager.</param>
+        /// <param name="networkManager">The network manager.</param>
+        /// <param name="httpClient">The HTTP client.</param>
+        /// <param name="applicationPaths">The application paths.</param>
+        /// <param name="jsonSerializer">The json serializer.</param>
+        /// <param name="logger">The logger.</param>
+        public PackageManager(ISecurityManager securityManager, INetworkManager networkManager, IHttpClient httpClient, IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger)
+        {
+            _securityManager = securityManager;
+            _networkManager = networkManager;
+            _httpClient = httpClient;
+            _appPaths = applicationPaths;
+            _jsonSerializer = jsonSerializer;
+            _logger = logger;
+        }
+
+        public async Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken)
         {
-            var data = new Dictionary<string, string> { { "key", securityManager.SupporterKey }, { "mac", networkManager.GetMacAddress() } };
+            var data = new Dictionary<string, string> { { "key", _securityManager.SupporterKey }, { "mac", _networkManager.GetMacAddress() } };
 
-            using (var json = await client.Post(Constants.Constants.MBAdminUrl + "service/package/retrieveall", data, resourcePool.Mb, cancellationToken).ConfigureAwait(false))
+            using (var json = await _httpClient.Post(Constants.Constants.MBAdminUrl + "service/package/retrieveall", data, cancellationToken).ConfigureAwait(false))
             {
                 cancellationToken.ThrowIfCancellationRequested();
 
-                var packages = serializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
+                var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
                 foreach (var package in packages)
                 {
                     package.versions = package.versions.Where(v => !string.IsNullOrWhiteSpace(v.sourceUrl))
@@ -43,15 +63,15 @@ namespace MediaBrowser.Common.Implementations.Updates
 
         }
 
-        public async Task InstallPackage(IHttpClient client, ILogger logger, ResourcePool resourcePool, IProgress<double> progress, IApplicationPaths appPaths, PackageVersionInfo package, CancellationToken cancellationToken)
+        public async Task InstallPackage(IProgress<double> progress, PackageVersionInfo package, CancellationToken cancellationToken)
         {
             // Target based on if it is an archive or single assembly
             //  zip archives are assumed to contain directory structures relative to our ProgramDataPath
             var isArchive = string.Equals(Path.GetExtension(package.targetFilename), ".zip", StringComparison.OrdinalIgnoreCase);
-            var target = Path.Combine(isArchive ? appPaths.TempUpdatePath : appPaths.PluginsPath, package.targetFilename);
+            var target = Path.Combine(isArchive ? _appPaths.TempUpdatePath : _appPaths.PluginsPath, package.targetFilename);
 
             // Download to temporary file so that, if interrupted, it won't destroy the existing installation
-            var tempFile = await client.GetTempFile(package.sourceUrl, resourcePool.Mb, cancellationToken, progress).ConfigureAwait(false);
+            var tempFile = await _httpClient.GetTempFile(package.sourceUrl, cancellationToken, progress).ConfigureAwait(false);
 
             cancellationToken.ThrowIfCancellationRequested();
 
@@ -79,7 +99,7 @@ namespace MediaBrowser.Common.Implementations.Updates
             }
             catch (IOException e)
             {
-                logger.ErrorException("Error attempting to move file from {0} to {1}", e, tempFile, target);
+                _logger.ErrorException("Error attempting to move file from {0} to {1}", e, tempFile, target);
                 throw;
             }
 

+ 68 - 0
MediaBrowser.Common/Configuration/ConfigurationHelper.cs

@@ -0,0 +1,68 @@
+using MediaBrowser.Model.Serialization;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Common.Configuration
+{
+    /// <summary>
+    /// Class ConfigurationHelper
+    /// </summary>
+    public static class ConfigurationHelper
+    {
+        /// <summary>
+        /// Reads an xml configuration file from the file system
+        /// It will immediately re-serialize and save if new serialization data is available due to property changes
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <param name="path">The path.</param>
+        /// <param name="xmlSerializer">The XML serializer.</param>
+        /// <returns>System.Object.</returns>
+        public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer)
+        {
+            object configuration;
+
+            byte[] buffer = null;
+
+            // Use try/catch to avoid the extra file system lookup using File.Exists
+            try
+            {
+                buffer = File.ReadAllBytes(path);
+
+                configuration = xmlSerializer.DeserializeFromBytes(type, buffer);
+            }
+            catch (FileNotFoundException)
+            {
+                configuration = Activator.CreateInstance(type);
+            }
+
+            // Take the object we just got and serialize it back to bytes
+            var newBytes = xmlSerializer.SerializeToBytes(configuration);
+
+            // If the file didn't exist before, or if something has changed, re-save
+            if (buffer == null || !buffer.SequenceEqual(newBytes))
+            {
+                // Save it after load in case we got new items
+                File.WriteAllBytes(path, newBytes);
+            }
+
+            return configuration;
+        }
+
+
+        /// <summary>
+        /// Reads an xml configuration file from the file system
+        /// It will immediately save the configuration after loading it, just
+        /// in case there are new serializable properties
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="path">The path.</param>
+        /// <param name="xmlSerializer">The XML serializer.</param>
+        /// <returns>``0.</returns>
+        public static T GetXmlConfiguration<T>(string path, IXmlSerializer xmlSerializer)
+            where T : class
+        {
+            return GetXmlConfiguration(typeof(T), path, xmlSerializer) as T;
+        }
+    }
+}

+ 1 - 1
MediaBrowser.Common/Kernel/IApplicationPaths.cs → MediaBrowser.Common/Configuration/IApplicationPaths.cs

@@ -1,5 +1,5 @@
 
-namespace MediaBrowser.Common.Kernel
+namespace MediaBrowser.Common.Configuration
 {
     /// <summary>
     /// Interface IApplicationPaths

+ 36 - 0
MediaBrowser.Common/Configuration/IConfigurationManager.cs

@@ -0,0 +1,36 @@
+using MediaBrowser.Model.Configuration;
+using System;
+
+namespace MediaBrowser.Common.Configuration
+{
+    public interface IConfigurationManager
+    {
+        /// <summary>
+        /// Occurs when [configuration updated].
+        /// </summary>
+        event EventHandler<EventArgs> ConfigurationUpdated;
+        
+        /// <summary>
+        /// Gets or sets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        IApplicationPaths CommonApplicationPaths { get; }
+
+        /// <summary>
+        /// Gets the configuration.
+        /// </summary>
+        /// <value>The configuration.</value>
+        BaseApplicationConfiguration CommonConfiguration { get; }
+
+        /// <summary>
+        /// Saves the configuration.
+        /// </summary>
+        void SaveConfiguration();
+
+        /// <summary>
+        /// Replaces the configuration.
+        /// </summary>
+        /// <param name="newConfiguration">The new configuration.</param>
+        void ReplaceConfiguration(BaseApplicationConfiguration newConfiguration);
+    }
+}

+ 1 - 7
MediaBrowser.Common/Kernel/IApplicationHost.cs → MediaBrowser.Common/IApplicationHost.cs

@@ -5,7 +5,7 @@ using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
 
-namespace MediaBrowser.Common.Kernel
+namespace MediaBrowser.Common
 {
     /// <summary>
     /// An interface to be implemented by the applications hosting a kernel
@@ -17,12 +17,6 @@ namespace MediaBrowser.Common.Kernel
         /// </summary>
         void Restart();
 
-        /// <summary>
-        /// Configures the auto run at startup.
-        /// </summary>
-        /// <param name="autorun">if set to <c>true</c> [autorun].</param>
-        void ConfigureAutoRunAtStartup(bool autorun);
-
         /// <summary>
         /// Gets the application version.
         /// </summary>

+ 12 - 213
MediaBrowser.Common/Kernel/BaseKernel.cs

@@ -1,45 +1,21 @@
-using MediaBrowser.Common.Events;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Model.Configuration;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Events;
 using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.System;
 using System;
-using System.IO;
-using System.Linq;
-using System.Threading;
 
 namespace MediaBrowser.Common.Kernel
 {
     /// <summary>
     /// Represents a shared base kernel for both the Ui and server apps
     /// </summary>
-    /// <typeparam name="TConfigurationType">The type of the T configuration type.</typeparam>
-    /// <typeparam name="TApplicationPathsType">The type of the T application paths type.</typeparam>
-    public abstract class BaseKernel<TConfigurationType, TApplicationPathsType> : IDisposable, IKernel
-        where TConfigurationType : BaseApplicationConfiguration, new()
-        where TApplicationPathsType : IApplicationPaths
+    public abstract class BaseKernel : IKernel
     {
         /// <summary>
         /// Occurs when [has pending restart changed].
         /// </summary>
         public event EventHandler HasPendingRestartChanged;
 
-        #region ConfigurationUpdated Event
-        /// <summary>
-        /// Occurs when [configuration updated].
-        /// </summary>
-        public event EventHandler<EventArgs> ConfigurationUpdated;
-
-        /// <summary>
-        /// Called when [configuration updated].
-        /// </summary>
-        internal void OnConfigurationUpdated()
-        {
-            EventHelper.QueueEventIfNotNull(ConfigurationUpdated, this, EventArgs.Empty, Logger);
-        }
-        #endregion
-
         #region ApplicationUpdated Event
         /// <summary>
         /// Occurs when [application updated].
@@ -57,65 +33,12 @@ namespace MediaBrowser.Common.Kernel
         }
         #endregion
 
-        /// <summary>
-        /// The _configuration loaded
-        /// </summary>
-        private bool _configurationLoaded;
-        /// <summary>
-        /// The _configuration sync lock
-        /// </summary>
-        private object _configurationSyncLock = new object();
-        /// <summary>
-        /// The _configuration
-        /// </summary>
-        private TConfigurationType _configuration;
-        /// <summary>
-        /// Gets the system configuration
-        /// </summary>
-        /// <value>The configuration.</value>
-        public TConfigurationType Configuration
-        {
-            get
-            {
-                // Lazy load
-                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => GetXmlConfiguration<TConfigurationType>(ApplicationPaths.SystemConfigurationFilePath));
-                return _configuration;
-            }
-            protected set
-            {
-                _configuration = value;
-
-                if (value == null)
-                {
-                    _configurationLoaded = false;
-                }
-            }
-        }
-
         /// <summary>
         /// Gets or sets a value indicating whether this instance has changes that require the entire application to restart.
         /// </summary>
         /// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value>
         public bool HasPendingRestart { get; private set; }
 
-        /// <summary>
-        /// Gets the application paths.
-        /// </summary>
-        /// <value>The application paths.</value>
-        public TApplicationPathsType ApplicationPaths { get; private set; }
-
-        /// <summary>
-        /// Gets or sets the TCP manager.
-        /// </summary>
-        /// <value>The TCP manager.</value>
-        private IServerManager ServerManager { get; set; }
-
-        /// <summary>
-        /// Gets the plug-in security manager.
-        /// </summary>
-        /// <value>The plug-in security manager.</value>
-        public ISecurityManager SecurityManager { get; set; }
-
         /// <summary>
         /// Gets the UDP server port number.
         /// This can't be configurable because then the user would have to configure their client to discover the server.
@@ -141,7 +64,7 @@ namespace MediaBrowser.Common.Kernel
         {
             get
             {
-                return "http://+:" + Configuration.HttpServerPortNumber + "/" + WebApplicationName + "/";
+                return "http://+:" + _configurationManager.CommonConfiguration.HttpServerPortNumber + "/" + WebApplicationName + "/";
             }
         }
 
@@ -163,25 +86,18 @@ namespace MediaBrowser.Common.Kernel
         /// <value>The application host.</value>
         protected IApplicationHost ApplicationHost { get; private set; }
 
-        /// <summary>
-        /// The _XML serializer
-        /// </summary>
-        private readonly IXmlSerializer _xmlSerializer;
+        private readonly IConfigurationManager _configurationManager;
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="BaseKernel{TApplicationPathsType}" /> class.
+        /// Initializes a new instance of the <see cref="BaseKernel" /> class.
         /// </summary>
         /// <param name="appHost">The app host.</param>
-        /// <param name="appPaths">The app paths.</param>
-        /// <param name="xmlSerializer">The XML serializer.</param>
-        /// <param name="logger">The logger.</param>
-        /// <exception cref="System.ArgumentNullException">isoManager</exception>
-        protected BaseKernel(IApplicationHost appHost, TApplicationPathsType appPaths, IXmlSerializer xmlSerializer, ILogger logger)
+        /// <param name="logManager">The log manager.</param>
+        protected BaseKernel(IApplicationHost appHost, ILogManager logManager, IConfigurationManager configurationManager)
         {
-            ApplicationPaths = appPaths;
             ApplicationHost = appHost;
-            _xmlSerializer = xmlSerializer;
-            Logger = logger;
+            _configurationManager = configurationManager;
+            Logger = logManager.GetLogger("Kernel");
         }
 
         /// <summary>
@@ -201,7 +117,6 @@ namespace MediaBrowser.Common.Kernel
         /// <returns>Task.</returns>
         protected virtual void ReloadInternal()
         {
-            ServerManager = ApplicationHost.Resolve<IServerManager>();
         }
 
         /// <summary>
@@ -214,24 +129,6 @@ namespace MediaBrowser.Common.Kernel
             EventHelper.QueueEventIfNotNull(HasPendingRestartChanged, this, EventArgs.Empty, Logger);
         }
 
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources.
-        /// </summary>
-        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected virtual void Dispose(bool dispose)
-        {
-
-        }
-
         /// <summary>
         /// Performs the pending restart.
         /// </summary>
@@ -261,108 +158,10 @@ namespace MediaBrowser.Common.Kernel
                 HasPendingRestart = HasPendingRestart,
                 Version = ApplicationHost.ApplicationVersion.ToString(),
                 IsNetworkDeployed = ApplicationHost.CanSelfUpdate,
-                WebSocketPortNumber = ServerManager.WebSocketPortNumber,
-                SupportsNativeWebSocket = ServerManager.SupportsNativeWebSocket,
+                WebSocketPortNumber = ApplicationHost.Resolve<IServerManager>().WebSocketPortNumber,
+                SupportsNativeWebSocket = ApplicationHost.Resolve<IServerManager>().SupportsNativeWebSocket,
                 FailedPluginAssemblies = ApplicationHost.FailedAssemblies.ToArray()
             };
         }
-
-        /// <summary>
-        /// The _save lock
-        /// </summary>
-        private readonly object _configurationSaveLock = new object();
-
-        /// <summary>
-        /// Saves the current configuration
-        /// </summary>
-        public void SaveConfiguration()
-        {
-            lock (_configurationSaveLock)
-            {
-                _xmlSerializer.SerializeToFile(Configuration, ApplicationPaths.SystemConfigurationFilePath);
-            }
-
-            OnConfigurationUpdated();
-        }
-
-        /// <summary>
-        /// Gets the application paths.
-        /// </summary>
-        /// <value>The application paths.</value>
-        IApplicationPaths IKernel.ApplicationPaths
-        {
-            get { return ApplicationPaths; }
-        }
-        /// <summary>
-        /// Gets the configuration.
-        /// </summary>
-        /// <value>The configuration.</value>
-        BaseApplicationConfiguration IKernel.Configuration
-        {
-            get { return Configuration; }
-        }		        
-        
-        /// <summary>
-        /// Reads an xml configuration file from the file system
-        /// It will immediately re-serialize and save if new serialization data is available due to property changes
-        /// </summary>
-        /// <param name="type">The type.</param>
-        /// <param name="path">The path.</param>
-        /// <returns>System.Object.</returns>
-        public object GetXmlConfiguration(Type type, string path)
-        {
-            Logger.Info("Loading {0} at {1}", type.Name, path);
-
-            object configuration;
-
-            byte[] buffer = null;
-
-            // Use try/catch to avoid the extra file system lookup using File.Exists
-            try
-            {
-                buffer = File.ReadAllBytes(path);
-
-                configuration = _xmlSerializer.DeserializeFromBytes(type, buffer);
-            }
-            catch (FileNotFoundException)
-            {
-                configuration = Activator.CreateInstance(type);
-            }
-
-            // Take the object we just got and serialize it back to bytes
-            var newBytes = _xmlSerializer.SerializeToBytes(configuration);
-
-            // If the file didn't exist before, or if something has changed, re-save
-            if (buffer == null || !buffer.SequenceEqual(newBytes))
-            {
-                Logger.Info("Saving {0} to {1}", type.Name, path);
-
-                // Save it after load in case we got new items
-                File.WriteAllBytes(path, newBytes);
-            }
-
-            return configuration;
-        }
-
-
-        /// <summary>
-        /// Reads an xml configuration file from the file system
-        /// It will immediately save the configuration after loading it, just
-        /// in case there are new serializable properties
-        /// </summary>
-        /// <typeparam name="T"></typeparam>
-        /// <param name="path">The path.</param>
-        /// <returns>``0.</returns>
-        private T GetXmlConfiguration<T>(string path)
-            where T : class
-        {
-            return GetXmlConfiguration(typeof(T), path) as T;
-        }
-
-        /// <summary>
-        /// Limits simultaneous access to various resources
-        /// </summary>
-        /// <value>The resource pools.</value>
-        public ResourcePool ResourcePools { get; set; }
     }
 }

+ 2 - 44
MediaBrowser.Common/Kernel/IKernel.cs

@@ -1,35 +1,18 @@
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.System;
+using MediaBrowser.Model.System;
 using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
 
 namespace MediaBrowser.Common.Kernel
 {
     /// <summary>
     /// Interface IKernel
     /// </summary>
-    public interface IKernel : IDisposable
+    public interface IKernel
     {
         /// <summary>
         /// Occurs when [has pending restart changed].
         /// </summary>
         event EventHandler HasPendingRestartChanged;
 
-        /// <summary>
-        /// Gets the application paths.
-        /// </summary>
-        /// <value>The application paths.</value>
-        IApplicationPaths ApplicationPaths { get; }
-
-        /// <summary>
-        /// Gets the configuration.
-        /// </summary>
-        /// <value>The configuration.</value>
-        BaseApplicationConfiguration Configuration { get; }
-
         /// <summary>
         /// Gets the kernel context.
         /// </summary>
@@ -83,34 +66,9 @@ namespace MediaBrowser.Common.Kernel
         /// <value>The HTTP server URL prefix.</value>
         string HttpServerUrlPrefix { get; }
 
-        /// <summary>
-        /// Gets the plug-in security manager.
-        /// </summary>
-        /// <value>The plug-in security manager.</value>
-        ISecurityManager SecurityManager { get; set; }
-
-        /// <summary>
-        /// Occurs when [configuration updated].
-        /// </summary>
-        event EventHandler<EventArgs> ConfigurationUpdated;
-
         /// <summary>
         /// Notifies the pending restart.
         /// </summary>
         void NotifyPendingRestart();
-
-        /// <summary>
-        /// Gets the XML configuration.
-        /// </summary>
-        /// <param name="type">The type.</param>
-        /// <param name="path">The path.</param>
-        /// <returns>System.Object.</returns>
-        object GetXmlConfiguration(Type type, string path);
-
-        /// <summary>
-        /// Limits simultaneous access to various resources
-        /// </summary>
-        /// <value>The resource pools.</value>
-        ResourcePool ResourcePools { get; set; }
     }
 }

+ 0 - 79
MediaBrowser.Common/Kernel/ResourcePool.cs

@@ -1,79 +0,0 @@
-using System;
-using System.Threading;
-
-namespace MediaBrowser.Common.Kernel
-{
-    /// <summary>
-    /// This is just a collection of semaphores to control the number of concurrent executions of various resources
-    /// </summary>
-    public class ResourcePool : IDisposable
-    {
-        /// <summary>
-        /// You tube
-        /// </summary>
-        public readonly SemaphoreSlim YouTube = new SemaphoreSlim(5, 5);
-
-        /// <summary>
-        /// The trakt
-        /// </summary>
-        public readonly SemaphoreSlim Trakt = new SemaphoreSlim(5, 5);
-
-        /// <summary>
-        /// The tv db
-        /// </summary>
-        public readonly SemaphoreSlim TvDb = new SemaphoreSlim(5, 5);
-
-        /// <summary>
-        /// The movie db
-        /// </summary>
-        public readonly SemaphoreSlim MovieDb = new SemaphoreSlim(5, 5);
-
-        /// <summary>
-        /// The fan art
-        /// </summary>
-        public readonly SemaphoreSlim FanArt = new SemaphoreSlim(5, 5);
-
-        /// <summary>
-        /// The mb
-        /// </summary>
-        public readonly SemaphoreSlim Mb = new SemaphoreSlim(5, 5);
-
-        /// <summary>
-        /// Apple doesn't seem to like too many simulataneous requests.
-        /// </summary>
-        public readonly SemaphoreSlim AppleTrailerVideos = new SemaphoreSlim(1, 1);
-
-        /// <summary>
-        /// The apple trailer images
-        /// </summary>
-        public readonly SemaphoreSlim AppleTrailerImages = new SemaphoreSlim(1, 1);
-        
-        /// <summary>
-        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-        /// </summary>
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-
-        /// <summary>
-        /// Releases unmanaged and - optionally - managed resources.
-        /// </summary>
-        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected virtual void Dispose(bool dispose)
-        {
-            if (dispose)
-            {
-                YouTube.Dispose();
-                Trakt.Dispose();
-                TvDb.Dispose();
-                MovieDb.Dispose();
-                FanArt.Dispose();
-                Mb.Dispose();
-                AppleTrailerVideos.Dispose();
-                AppleTrailerImages.Dispose();
-            }
-        }
-    }
-}

+ 4 - 6
MediaBrowser.Common/MediaBrowser.Common.csproj

@@ -46,6 +46,8 @@
     <Compile Include="..\SharedVersion.cs">
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
+    <Compile Include="Configuration\ConfigurationHelper.cs" />
+    <Compile Include="Configuration\IConfigurationManager.cs" />
     <Compile Include="Constants\Constants.cs" />
     <Compile Include="Events\EventHelper.cs" />
     <Compile Include="Extensions\BaseExtensions.cs" />
@@ -58,14 +60,11 @@
     <Compile Include="IO\ProgressStream.cs" />
     <Compile Include="IO\StreamDefaults.cs" />
     <Compile Include="Kernel\BasePeriodicWebSocketListener.cs" />
-    <Compile Include="Kernel\IApplicationPaths.cs" />
+    <Compile Include="Configuration\IApplicationPaths.cs" />
     <Compile Include="Kernel\IServerManager.cs" />
     <Compile Include="Kernel\IWebSocketListener.cs" />
-    <Compile Include="Kernel\IApplicationHost.cs" />
+    <Compile Include="IApplicationHost.cs" />
     <Compile Include="Kernel\IKernel.cs" />
-    <Compile Include="Kernel\ResourcePool.cs" />
-    <Compile Include="Net\Handlers\IHttpServerHandler.cs" />
-    <Compile Include="Net\Handlers\StaticFileHandler.cs" />
     <Compile Include="Net\IHttpClient.cs" />
     <Compile Include="Net\IHttpServer.cs" />
     <Compile Include="Net\INetworkManager.cs" />
@@ -97,7 +96,6 @@
     <Compile Include="ScheduledTasks\SystemEventTrigger.cs" />
     <Compile Include="Kernel\BaseKernel.cs" />
     <Compile Include="Kernel\KernelContext.cs" />
-    <Compile Include="Net\Handlers\BaseHandler.cs" />
     <Compile Include="Plugins\BasePlugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="ScheduledTasks\DailyTrigger.cs" />

+ 0 - 808
MediaBrowser.Common/Net/Handlers/BaseHandler.cs

@@ -1,808 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.Kernel;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Globalization;
-using System.IO;
-using System.IO.Compression;
-using System.Linq;
-using System.Net;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Common.Net.Handlers
-{
-    /// <summary>
-    /// Class BaseHandler
-    /// </summary>
-    public abstract class BaseHandler<TKernelType> : IHttpServerHandler
-        where TKernelType : IKernel
-    {
-        /// <summary>
-        /// Initializes the specified kernel.
-        /// </summary>
-        /// <param name="kernel">The kernel.</param>
-        public void Initialize(IKernel kernel)
-        {
-            Kernel = (TKernelType)kernel;
-        }
-
-        /// <summary>
-        /// Gets or sets the kernel.
-        /// </summary>
-        /// <value>The kernel.</value>
-        protected TKernelType Kernel { get; private set; }
-
-        /// <summary>
-        /// Gets the URL suffix used to determine if this handler can process a request.
-        /// </summary>
-        /// <value>The URL suffix.</value>
-        protected virtual string UrlSuffix
-        {
-            get
-            {
-                var name = GetType().Name;
-
-                const string srch = "Handler";
-
-                if (name.EndsWith(srch, StringComparison.OrdinalIgnoreCase))
-                {
-                    name = name.Substring(0, name.Length - srch.Length);
-                }
-
-                return "api/" + name;
-            }
-        }
-
-        /// <summary>
-        /// Handleses the request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        public virtual bool HandlesRequest(HttpListenerRequest request)
-        {
-            var name = '/' + UrlSuffix.TrimStart('/');
-
-            var url = Kernel.WebApplicationName + name;
-
-            return request.Url.LocalPath.EndsWith(url, StringComparison.OrdinalIgnoreCase);
-        }
-
-        /// <summary>
-        /// Gets or sets the compressed stream.
-        /// </summary>
-        /// <value>The compressed stream.</value>
-        private Stream CompressedStream { get; set; }
-
-        /// <summary>
-        /// Gets a value indicating whether [use chunked encoding].
-        /// </summary>
-        /// <value><c>null</c> if [use chunked encoding] contains no value, <c>true</c> if [use chunked encoding]; otherwise, <c>false</c>.</value>
-        public virtual bool? UseChunkedEncoding
-        {
-            get
-            {
-                return null;
-            }
-        }
-
-        /// <summary>
-        /// The original HttpListenerContext
-        /// </summary>
-        /// <value>The HTTP listener context.</value>
-        protected HttpListenerContext HttpListenerContext { get; set; }
-
-        /// <summary>
-        /// The _query string
-        /// </summary>
-        private NameValueCollection _queryString;
-        /// <summary>
-        /// The original QueryString
-        /// </summary>
-        /// <value>The query string.</value>
-        public NameValueCollection QueryString
-        {
-            get
-            {
-                // HttpListenerContext.Request.QueryString is not decoded properly
-                return _queryString;
-            }
-        }
-
-        /// <summary>
-        /// The _requested ranges
-        /// </summary>
-        private List<KeyValuePair<long, long?>> _requestedRanges;
-        /// <summary>
-        /// Gets the requested ranges.
-        /// </summary>
-        /// <value>The requested ranges.</value>
-        protected IEnumerable<KeyValuePair<long, long?>> RequestedRanges
-        {
-            get
-            {
-                if (_requestedRanges == null)
-                {
-                    _requestedRanges = new List<KeyValuePair<long, long?>>();
-
-                    if (IsRangeRequest)
-                    {
-                        // Example: bytes=0-,32-63
-                        var ranges = HttpListenerContext.Request.Headers["Range"].Split('=')[1].Split(',');
-
-                        foreach (var range in ranges)
-                        {
-                            var vals = range.Split('-');
-
-                            long start = 0;
-                            long? end = null;
-
-                            if (!string.IsNullOrEmpty(vals[0]))
-                            {
-                                start = long.Parse(vals[0]);
-                            }
-                            if (!string.IsNullOrEmpty(vals[1]))
-                            {
-                                end = long.Parse(vals[1]);
-                            }
-
-                            _requestedRanges.Add(new KeyValuePair<long, long?>(start, end));
-                        }
-                    }
-                }
-
-                return _requestedRanges;
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance is range request.
-        /// </summary>
-        /// <value><c>true</c> if this instance is range request; otherwise, <c>false</c>.</value>
-        protected bool IsRangeRequest
-        {
-            get
-            {
-                return HttpListenerContext.Request.Headers.AllKeys.Contains("Range");
-            }
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether [client supports compression].
-        /// </summary>
-        /// <value><c>true</c> if [client supports compression]; otherwise, <c>false</c>.</value>
-        protected bool ClientSupportsCompression
-        {
-            get
-            {
-                var enc = HttpListenerContext.Request.Headers["Accept-Encoding"] ?? string.Empty;
-
-                return enc.Equals("*", StringComparison.OrdinalIgnoreCase) ||
-                    enc.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) != -1 ||
-                    enc.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1;
-            }
-        }
-
-        /// <summary>
-        /// Gets the compression method.
-        /// </summary>
-        /// <value>The compression method.</value>
-        private string CompressionMethod
-        {
-            get
-            {
-                var enc = HttpListenerContext.Request.Headers["Accept-Encoding"] ?? string.Empty;
-
-                if (enc.IndexOf("deflate", StringComparison.OrdinalIgnoreCase) != -1 || enc.Equals("*", StringComparison.OrdinalIgnoreCase))
-                {
-                    return "deflate";
-                }
-                if (enc.IndexOf("gzip", StringComparison.OrdinalIgnoreCase) != -1)
-                {
-                    return "gzip";
-                }
-
-                return null;
-            }
-        }
-
-        /// <summary>
-        /// Processes the request.
-        /// </summary>
-        /// <param name="ctx">The CTX.</param>
-        /// <returns>Task.</returns>
-        public virtual async Task ProcessRequest(HttpListenerContext ctx)
-        {
-            HttpListenerContext = ctx;
-
-            ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
-
-            ctx.Response.KeepAlive = true;
-
-            try
-            {
-                await ProcessRequestInternal(ctx).ConfigureAwait(false);
-            }
-            catch (InvalidOperationException ex)
-            {
-                HandleException(ctx.Response, ex, 422);
-
-                throw;
-            }
-            catch (ResourceNotFoundException ex)
-            {
-                HandleException(ctx.Response, ex, 404);
-
-                throw;
-            }
-            catch (FileNotFoundException ex)
-            {
-                HandleException(ctx.Response, ex, 404);
-
-                throw;
-            }
-            catch (DirectoryNotFoundException ex)
-            {
-                HandleException(ctx.Response, ex, 404);
-
-                throw;
-            }
-            catch (UnauthorizedAccessException ex)
-            {
-                HandleException(ctx.Response, ex, 401);
-
-                throw;
-            }
-            catch (ArgumentException ex)
-            {
-                HandleException(ctx.Response, ex, 400);
-
-                throw;
-            }
-            catch (Exception ex)
-            {
-                HandleException(ctx.Response, ex, 500);
-
-                throw;
-            }
-            finally
-            {
-                DisposeResponseStream();
-            }
-        }
-
-        /// <summary>
-        /// Appends the error message.
-        /// </summary>
-        /// <param name="response">The response.</param>
-        /// <param name="ex">The ex.</param>
-        /// <param name="statusCode">The status code.</param>
-        private void HandleException(HttpListenerResponse response, Exception ex, int statusCode)
-        {
-            response.StatusCode = statusCode;
-
-            response.Headers.Add("Status", statusCode.ToString(new CultureInfo("en-US")));
-
-            response.Headers.Remove("Age");
-            response.Headers.Remove("Expires");
-            response.Headers.Remove("Cache-Control");
-            response.Headers.Remove("Etag");
-            response.Headers.Remove("Last-Modified");
-
-            response.ContentType = "text/plain";
-
-            //Logger.ErrorException("Error processing request", ex);
-            
-            if (!string.IsNullOrEmpty(ex.Message))
-            {
-                response.AddHeader("X-Application-Error-Code", ex.Message);
-            }
-
-            var bytes = Encoding.UTF8.GetBytes(ex.Message);
-
-            var stream = CompressedStream ?? response.OutputStream;
-
-            // This could fail, but try to add the stack trace as the body content
-            try
-            {
-                stream.Write(bytes, 0, bytes.Length);
-            }
-            catch (Exception ex1)
-            {
-                //Logger.ErrorException("Error dumping stack trace", ex1);
-            }
-        }
-
-        /// <summary>
-        /// Processes the request internal.
-        /// </summary>
-        /// <param name="ctx">The CTX.</param>
-        /// <returns>Task.</returns>
-        private async Task ProcessRequestInternal(HttpListenerContext ctx)
-        {
-            var responseInfo = await GetResponseInfo().ConfigureAwait(false);
-
-            // Let the client know if byte range requests are supported or not
-            if (responseInfo.SupportsByteRangeRequests)
-            {
-                ctx.Response.Headers["Accept-Ranges"] = "bytes";
-            }
-            else if (!responseInfo.SupportsByteRangeRequests)
-            {
-                ctx.Response.Headers["Accept-Ranges"] = "none";
-            }
-
-            if (responseInfo.IsResponseValid && responseInfo.SupportsByteRangeRequests && IsRangeRequest)
-            {
-                // Set the initial status code
-                // When serving a range request, we need to return status code 206 to indicate a partial response body
-                responseInfo.StatusCode = 206;
-            }
-
-            ctx.Response.ContentType = responseInfo.ContentType;
-
-            if (responseInfo.Etag.HasValue)
-            {
-                ctx.Response.Headers["ETag"] = responseInfo.Etag.Value.ToString("N");
-            }
-
-            var isCacheValid = true;
-
-            // Validate If-Modified-Since
-            if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since"))
-            {
-                DateTime ifModifiedSince;
-
-                if (DateTime.TryParse(ctx.Request.Headers["If-Modified-Since"], out ifModifiedSince))
-                {
-                    isCacheValid = IsCacheValid(ifModifiedSince.ToUniversalTime(), responseInfo.CacheDuration,
-                                                responseInfo.DateLastModified);
-                }
-            }
-
-            // Validate If-None-Match
-            if (isCacheValid &&
-                (responseInfo.Etag.HasValue || !string.IsNullOrEmpty(ctx.Request.Headers["If-None-Match"])))
-            {
-                Guid ifNoneMatch;
-
-                if (Guid.TryParse(ctx.Request.Headers["If-None-Match"] ?? string.Empty, out ifNoneMatch))
-                {
-                    if (responseInfo.Etag.HasValue && responseInfo.Etag.Value == ifNoneMatch)
-                    {
-                        responseInfo.StatusCode = 304;
-                    }
-                }
-            }
-
-            LogResponse(ctx, responseInfo);
-
-            if (responseInfo.IsResponseValid)
-            {
-                await OnProcessingRequest(responseInfo).ConfigureAwait(false);
-            }
-
-            if (responseInfo.IsResponseValid)
-            {
-                await ProcessUncachedRequest(ctx, responseInfo).ConfigureAwait(false);
-            }
-            else
-            {
-                if (responseInfo.StatusCode == 304)
-                {
-                    AddAgeHeader(ctx.Response, responseInfo);
-                    AddExpiresHeader(ctx.Response, responseInfo);
-                }
-
-                ctx.Response.StatusCode = responseInfo.StatusCode;
-                ctx.Response.SendChunked = false;
-            }
-        }
-
-        /// <summary>
-        /// The _null task result
-        /// </summary>
-        private readonly Task<bool> _nullTaskResult = Task.FromResult(true);
-
-        /// <summary>
-        /// Called when [processing request].
-        /// </summary>
-        /// <param name="responseInfo">The response info.</param>
-        /// <returns>Task.</returns>
-        protected virtual Task OnProcessingRequest(ResponseInfo responseInfo)
-        {
-            return _nullTaskResult;
-        }
-
-        /// <summary>
-        /// Logs the response.
-        /// </summary>
-        /// <param name="ctx">The CTX.</param>
-        /// <param name="responseInfo">The response info.</param>
-        private void LogResponse(HttpListenerContext ctx, ResponseInfo responseInfo)
-        {
-            // Don't log normal 200's
-            if (responseInfo.StatusCode == 200)
-            {
-                return;
-            }
-
-            var log = new StringBuilder();
-
-            log.AppendLine(string.Format("Url: {0}", ctx.Request.Url));
-
-            log.AppendLine("Headers: " + string.Join(",", ctx.Response.Headers.AllKeys.Select(k => k + "=" + ctx.Response.Headers[k])));
-
-            var msg = "Http Response Sent (" + responseInfo.StatusCode + ") to " + ctx.Request.RemoteEndPoint;
-
-            if (Kernel.Configuration.EnableHttpLevelLogging)
-            {
-                //Logger.LogMultiline(msg, LogSeverity.Debug, log);
-            }
-        }
-
-        /// <summary>
-        /// Processes the uncached request.
-        /// </summary>
-        /// <param name="ctx">The CTX.</param>
-        /// <param name="responseInfo">The response info.</param>
-        /// <returns>Task.</returns>
-        private async Task ProcessUncachedRequest(HttpListenerContext ctx, ResponseInfo responseInfo)
-        {
-            var totalContentLength = GetTotalContentLength(responseInfo);
-
-            // By default, use chunked encoding if we don't know the content length
-            var useChunkedEncoding = UseChunkedEncoding == null ? (totalContentLength == null) : UseChunkedEncoding.Value;
-
-            // Don't force this to true. HttpListener will default it to true if supported by the client.
-            if (!useChunkedEncoding)
-            {
-                ctx.Response.SendChunked = false;
-            }
-
-            // Set the content length, if we know it
-            if (totalContentLength.HasValue)
-            {
-                ctx.Response.ContentLength64 = totalContentLength.Value;
-            }
-
-            var compressResponse = responseInfo.CompressResponse && ClientSupportsCompression;
-
-            // Add the compression header
-            if (compressResponse)
-            {
-                ctx.Response.AddHeader("Content-Encoding", CompressionMethod);
-                ctx.Response.AddHeader("Vary", "Accept-Encoding");
-            }
-
-            // Don't specify both last modified and Etag, unless caching unconditionally. They are redundant
-            // https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching
-            if (responseInfo.DateLastModified.HasValue && (!responseInfo.Etag.HasValue || responseInfo.CacheDuration.Ticks > 0))
-            {
-                ctx.Response.Headers[HttpResponseHeader.LastModified] = responseInfo.DateLastModified.Value.ToString("r");
-                AddAgeHeader(ctx.Response, responseInfo);
-            }
-
-            // Add caching headers
-            ConfigureCaching(ctx.Response, responseInfo);
-
-            // Set the status code
-            ctx.Response.StatusCode = responseInfo.StatusCode;
-
-            if (responseInfo.IsResponseValid)
-            {
-                // Finally, write the response data
-                var outputStream = ctx.Response.OutputStream;
-
-                if (compressResponse)
-                {
-                    if (CompressionMethod.Equals("deflate", StringComparison.OrdinalIgnoreCase))
-                    {
-                        CompressedStream = new DeflateStream(outputStream, CompressionLevel.Fastest, true);
-                    }
-                    else
-                    {
-                        CompressedStream = new GZipStream(outputStream, CompressionLevel.Fastest, true);
-                    }
-
-                    outputStream = CompressedStream;
-                }
-
-                await WriteResponseToOutputStream(outputStream, responseInfo, totalContentLength).ConfigureAwait(false);
-            }
-            else
-            {
-                ctx.Response.SendChunked = false;
-            }
-        }
-
-        /// <summary>
-        /// Configures the caching.
-        /// </summary>
-        /// <param name="response">The response.</param>
-        /// <param name="responseInfo">The response info.</param>
-        private void ConfigureCaching(HttpListenerResponse response, ResponseInfo responseInfo)
-        {
-            if (responseInfo.CacheDuration.Ticks > 0)
-            {
-                response.Headers[HttpResponseHeader.CacheControl] = "public, max-age=" + Convert.ToInt32(responseInfo.CacheDuration.TotalSeconds);
-            }
-            else if (responseInfo.Etag.HasValue)
-            {
-                response.Headers[HttpResponseHeader.CacheControl] = "public";
-            }
-            else
-            {
-                response.Headers[HttpResponseHeader.CacheControl] = "no-cache, no-store, must-revalidate";
-                response.Headers[HttpResponseHeader.Pragma] = "no-cache, no-store, must-revalidate";
-            }
-
-            AddExpiresHeader(response, responseInfo);
-        }
-
-        /// <summary>
-        /// Adds the expires header.
-        /// </summary>
-        /// <param name="response">The response.</param>
-        /// <param name="responseInfo">The response info.</param>
-        private void AddExpiresHeader(HttpListenerResponse response, ResponseInfo responseInfo)
-        {
-            if (responseInfo.CacheDuration.Ticks > 0)
-            {
-                response.Headers[HttpResponseHeader.Expires] = DateTime.UtcNow.Add(responseInfo.CacheDuration).ToString("r");
-            }
-            else if (!responseInfo.Etag.HasValue)
-            {
-                response.Headers[HttpResponseHeader.Expires] = "-1";
-            }
-        }
-
-        /// <summary>
-        /// Adds the age header.
-        /// </summary>
-        /// <param name="response">The response.</param>
-        /// <param name="responseInfo">The response info.</param>
-        private void AddAgeHeader(HttpListenerResponse response, ResponseInfo responseInfo)
-        {
-            if (responseInfo.DateLastModified.HasValue)
-            {
-                response.Headers[HttpResponseHeader.Age] = Convert.ToInt32((DateTime.UtcNow - responseInfo.DateLastModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture);
-            }
-        }
-
-        /// <summary>
-        /// Writes the response to output stream.
-        /// </summary>
-        /// <param name="stream">The stream.</param>
-        /// <param name="responseInfo">The response info.</param>
-        /// <param name="contentLength">Length of the content.</param>
-        /// <returns>Task.</returns>
-        protected abstract Task WriteResponseToOutputStream(Stream stream, ResponseInfo responseInfo, long? contentLength);
-
-        /// <summary>
-        /// Disposes the response stream.
-        /// </summary>
-        protected virtual void DisposeResponseStream()
-        {
-            if (CompressedStream != null)
-            {
-                try
-                {
-                    CompressedStream.Dispose();
-                }
-                catch (Exception ex)
-                {
-                    //Logger.ErrorException("Error disposing compressed stream", ex);
-                }
-            }
-
-            try
-            {
-                //HttpListenerContext.Response.OutputStream.Dispose();
-                HttpListenerContext.Response.Close();
-            }
-            catch (Exception ex)
-            {
-                //Logger.ErrorException("Error disposing response", ex);
-            }
-        }
-
-        /// <summary>
-        /// Determines whether [is cache valid] [the specified if modified since].
-        /// </summary>
-        /// <param name="ifModifiedSince">If modified since.</param>
-        /// <param name="cacheDuration">Duration of the cache.</param>
-        /// <param name="dateModified">The date modified.</param>
-        /// <returns><c>true</c> if [is cache valid] [the specified if modified since]; otherwise, <c>false</c>.</returns>
-        private bool IsCacheValid(DateTime ifModifiedSince, TimeSpan cacheDuration, DateTime? dateModified)
-        {
-            if (dateModified.HasValue)
-            {
-                DateTime lastModified = NormalizeDateForComparison(dateModified.Value);
-                ifModifiedSince = NormalizeDateForComparison(ifModifiedSince);
-
-                return lastModified <= ifModifiedSince;
-            }
-
-            DateTime cacheExpirationDate = ifModifiedSince.Add(cacheDuration);
-
-            if (DateTime.UtcNow < cacheExpirationDate)
-            {
-                return true;
-            }
-
-            return false;
-        }
-
-        /// <summary>
-        /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that
-        /// </summary>
-        /// <param name="date">The date.</param>
-        /// <returns>DateTime.</returns>
-        private DateTime NormalizeDateForComparison(DateTime date)
-        {
-            return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind);
-        }
-
-        /// <summary>
-        /// Gets the total length of the content.
-        /// </summary>
-        /// <param name="responseInfo">The response info.</param>
-        /// <returns>System.Nullable{System.Int64}.</returns>
-        protected virtual long? GetTotalContentLength(ResponseInfo responseInfo)
-        {
-            return null;
-        }
-
-        /// <summary>
-        /// Gets the response info.
-        /// </summary>
-        /// <returns>Task{ResponseInfo}.</returns>
-        protected abstract Task<ResponseInfo> GetResponseInfo();
-
-        /// <summary>
-        /// Gets a bool query string param.
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        protected bool GetBoolQueryStringParam(string name)
-        {
-            var val = QueryString[name] ?? string.Empty;
-
-            return val.Equals("1", StringComparison.OrdinalIgnoreCase) || val.Equals("true", StringComparison.OrdinalIgnoreCase);
-        }
-
-        /// <summary>
-        /// The _form values
-        /// </summary>
-        private Hashtable _formValues;
-
-        /// <summary>
-        /// Gets a value from form POST data
-        /// </summary>
-        /// <param name="name">The name.</param>
-        /// <returns>Task{System.String}.</returns>
-        protected async Task<string> GetFormValue(string name)
-        {
-            if (_formValues == null)
-            {
-                _formValues = await GetFormValues(HttpListenerContext.Request).ConfigureAwait(false);
-            }
-
-            if (_formValues.ContainsKey(name))
-            {
-                return _formValues[name].ToString();
-            }
-
-            return null;
-        }
-
-        /// <summary>
-        /// Extracts form POST data from a request
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns>Task{Hashtable}.</returns>
-        private async Task<Hashtable> GetFormValues(HttpListenerRequest request)
-        {
-            var formVars = new Hashtable();
-
-            if (request.HasEntityBody)
-            {
-                if (request.ContentType.IndexOf("application/x-www-form-urlencoded", StringComparison.OrdinalIgnoreCase) != -1)
-                {
-                    using (var requestBody = request.InputStream)
-                    {
-                        using (var reader = new StreamReader(requestBody, request.ContentEncoding))
-                        {
-                            var s = await reader.ReadToEndAsync().ConfigureAwait(false);
-
-                            var pairs = s.Split('&');
-
-                            foreach (var pair in pairs)
-                            {
-                                var index = pair.IndexOf('=');
-
-                                if (index != -1)
-                                {
-                                    var name = pair.Substring(0, index);
-                                    var value = pair.Substring(index + 1);
-                                    formVars.Add(name, value);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-
-            return formVars;
-        }
-    }
-
-    /// <summary>
-    /// Class ResponseInfo
-    /// </summary>
-    public class ResponseInfo
-    {
-        /// <summary>
-        /// Gets or sets the type of the content.
-        /// </summary>
-        /// <value>The type of the content.</value>
-        public string ContentType { get; set; }
-        /// <summary>
-        /// Gets or sets the etag.
-        /// </summary>
-        /// <value>The etag.</value>
-        public Guid? Etag { get; set; }
-        /// <summary>
-        /// Gets or sets the date last modified.
-        /// </summary>
-        /// <value>The date last modified.</value>
-        public DateTime? DateLastModified { get; set; }
-        /// <summary>
-        /// Gets or sets the duration of the cache.
-        /// </summary>
-        /// <value>The duration of the cache.</value>
-        public TimeSpan CacheDuration { get; set; }
-        /// <summary>
-        /// Gets or sets a value indicating whether [compress response].
-        /// </summary>
-        /// <value><c>true</c> if [compress response]; otherwise, <c>false</c>.</value>
-        public bool CompressResponse { get; set; }
-        /// <summary>
-        /// Gets or sets the status code.
-        /// </summary>
-        /// <value>The status code.</value>
-        public int StatusCode { get; set; }
-        /// <summary>
-        /// Gets or sets a value indicating whether [supports byte range requests].
-        /// </summary>
-        /// <value><c>true</c> if [supports byte range requests]; otherwise, <c>false</c>.</value>
-        public bool SupportsByteRangeRequests { get; set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="ResponseInfo" /> class.
-        /// </summary>
-        public ResponseInfo()
-        {
-            CacheDuration = TimeSpan.FromTicks(0);
-
-            CompressResponse = true;
-
-            StatusCode = 200;
-        }
-
-        /// <summary>
-        /// Gets a value indicating whether this instance is response valid.
-        /// </summary>
-        /// <value><c>true</c> if this instance is response valid; otherwise, <c>false</c>.</value>
-        public bool IsResponseValid
-        {
-            get
-            {
-                return StatusCode >= 200 && StatusCode < 300;
-            }
-        }
-    }
-}

+ 0 - 32
MediaBrowser.Common/Net/Handlers/IHttpServerHandler.cs

@@ -1,32 +0,0 @@
-using MediaBrowser.Common.Kernel;
-using System.Net;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Common.Net.Handlers
-{
-    /// <summary>
-    /// Interface IHttpServerHandler
-    /// </summary>
-    public interface IHttpServerHandler
-    {
-        /// <summary>
-        /// Initializes the specified kernel.
-        /// </summary>
-        /// <param name="kernel">The kernel.</param>
-        void Initialize(IKernel kernel);
-        
-        /// <summary>
-        /// Handleses the request.
-        /// </summary>
-        /// <param name="request">The request.</param>
-        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        bool HandlesRequest(HttpListenerRequest request);
-
-        /// <summary>
-        /// Processes the request.
-        /// </summary>
-        /// <param name="ctx">The CTX.</param>
-        /// <returns>Task.</returns>
-        Task ProcessRequest(HttpListenerContext ctx);
-    }
-}

+ 0 - 264
MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs

@@ -1,264 +0,0 @@
-using MediaBrowser.Common.Extensions;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Kernel;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Common.Net.Handlers
-{
-    /// <summary>
-    /// Represents an http handler that serves static content
-    /// </summary>
-    public class StaticFileHandler : BaseHandler<IKernel>
-    {
-        /// <summary>
-        /// Initializes a new instance of the <see cref="StaticFileHandler" /> class.
-        /// </summary>
-        /// <param name="kernel">The kernel.</param>
-        public StaticFileHandler(IKernel kernel)
-        {
-            Initialize(kernel);
-        }
-
-        /// <summary>
-        /// The _path
-        /// </summary>
-        private string _path;
-        /// <summary>
-        /// Gets or sets the path to the static resource
-        /// </summary>
-        /// <value>The path.</value>
-        public string Path
-        {
-            get
-            {
-                if (!string.IsNullOrWhiteSpace(_path))
-                {
-                    return _path;
-                }
-
-                return QueryString["path"];
-            }
-            set
-            {
-                _path = value;
-            }
-        }
-
-        /// <summary>
-        /// Gets or sets the last date modified of the resource
-        /// </summary>
-        /// <value>The last date modified.</value>
-        public DateTime? LastDateModified { get; set; }
-
-        /// <summary>
-        /// Gets or sets the content type of the resource
-        /// </summary>
-        /// <value>The type of the content.</value>
-        public string ContentType { get; set; }
-
-        /// <summary>
-        /// Gets or sets the content type of the resource
-        /// </summary>
-        /// <value>The etag.</value>
-        public Guid Etag { get; set; }
-
-        /// <summary>
-        /// Gets or sets the source stream of the resource
-        /// </summary>
-        /// <value>The source stream.</value>
-        public Stream SourceStream { get; set; }
-
-        /// <summary>
-        /// Shoulds the compress response.
-        /// </summary>
-        /// <param name="contentType">Type of the content.</param>
-        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        private bool ShouldCompressResponse(string contentType)
-        {
-            // It will take some work to support compression with byte range requests
-            if (IsRangeRequest)
-            {
-                return false;
-            }
-
-            // Don't compress media
-            if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
-            {
-                return false;
-            }
-
-            // Don't compress images
-            if (contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase))
-            {
-                return false;
-            }
-
-            return true;
-        }
-
-        /// <summary>
-        /// Gets or sets the duration of the cache.
-        /// </summary>
-        /// <value>The duration of the cache.</value>
-        public TimeSpan? CacheDuration { get; set; }
-
-        /// <summary>
-        /// Gets the total length of the content.
-        /// </summary>
-        /// <param name="responseInfo">The response info.</param>
-        /// <returns>System.Nullable{System.Int64}.</returns>
-        protected override long? GetTotalContentLength(ResponseInfo responseInfo)
-        {
-            // If we're compressing the response, content length must be the compressed length, which we don't know
-            if (responseInfo.CompressResponse && ClientSupportsCompression)
-            {
-                return null;
-            }
-
-            return SourceStream.Length;
-        }
-
-        /// <summary>
-        /// Gets the response info.
-        /// </summary>
-        /// <returns>Task{ResponseInfo}.</returns>
-        protected override Task<ResponseInfo> GetResponseInfo()
-        {
-            var info = new ResponseInfo
-            {
-                ContentType = ContentType ?? MimeTypes.GetMimeType(Path),
-                Etag = Etag,
-                DateLastModified = LastDateModified
-            };
-
-            if (SourceStream == null && !string.IsNullOrEmpty(Path))
-            {
-                // FileShare must be ReadWrite in case someone else is currently writing to it.
-                SourceStream = new FileStream(Path, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous);
-            }
-
-            info.CompressResponse = ShouldCompressResponse(info.ContentType);
-
-            info.SupportsByteRangeRequests = !info.CompressResponse || !ClientSupportsCompression;
-
-            if (!info.DateLastModified.HasValue && !string.IsNullOrWhiteSpace(Path))
-            {
-                info.DateLastModified = File.GetLastWriteTimeUtc(Path);
-            }
-
-            if (CacheDuration.HasValue)
-            {
-                info.CacheDuration = CacheDuration.Value;
-            }
-
-            if (SourceStream == null && string.IsNullOrEmpty(Path))
-            {
-                throw new ResourceNotFoundException();
-            }
-
-            return Task.FromResult(info);
-        }
-
-        /// <summary>
-        /// Writes the response to output stream.
-        /// </summary>
-        /// <param name="stream">The stream.</param>
-        /// <param name="responseInfo">The response info.</param>
-        /// <param name="totalContentLength">Total length of the content.</param>
-        /// <returns>Task.</returns>
-        protected override Task WriteResponseToOutputStream(Stream stream, ResponseInfo responseInfo, long? totalContentLength)
-        {
-            if (IsRangeRequest && totalContentLength.HasValue)
-            {
-                var requestedRange = RequestedRanges.First();
-
-                // If the requested range is "0-", we can optimize by just doing a stream copy
-                if (!requestedRange.Value.HasValue)
-                {
-                    return ServeCompleteRangeRequest(requestedRange, stream, totalContentLength.Value);
-                }
-
-                // This will have to buffer a portion of the content into memory
-                return ServePartialRangeRequest(requestedRange.Key, requestedRange.Value.Value, stream, totalContentLength.Value);
-            }
-
-            return SourceStream.CopyToAsync(stream);
-        }
-
-        /// <summary>
-        /// Disposes the response stream.
-        /// </summary>
-        protected override void DisposeResponseStream()
-        {
-            if (SourceStream != null)
-            {
-                SourceStream.Dispose();
-            }
-
-            base.DisposeResponseStream();
-        }
-
-        /// <summary>
-        /// Handles a range request of "bytes=0-"
-        /// This will serve the complete content and add the content-range header
-        /// </summary>
-        /// <param name="requestedRange">The requested range.</param>
-        /// <param name="responseStream">The response stream.</param>
-        /// <param name="totalContentLength">Total length of the content.</param>
-        /// <returns>Task.</returns>
-        private Task ServeCompleteRangeRequest(KeyValuePair<long, long?> requestedRange, Stream responseStream, long totalContentLength)
-        {
-            var rangeStart = requestedRange.Key;
-            var rangeEnd = totalContentLength - 1;
-            var rangeLength = 1 + rangeEnd - rangeStart;
-
-            // Content-Length is the length of what we're serving, not the original content
-            HttpListenerContext.Response.ContentLength64 = rangeLength;
-            HttpListenerContext.Response.Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", rangeStart, rangeEnd, totalContentLength);
-
-            if (rangeStart > 0)
-            {
-                SourceStream.Position = rangeStart;
-            }
-
-            return SourceStream.CopyToAsync(responseStream);
-        }
-
-        /// <summary>
-        /// Serves a partial range request
-        /// </summary>
-        /// <param name="rangeStart">The range start.</param>
-        /// <param name="rangeEnd">The range end.</param>
-        /// <param name="responseStream">The response stream.</param>
-        /// <param name="totalContentLength">Total length of the content.</param>
-        /// <returns>Task.</returns>
-        private async Task ServePartialRangeRequest(long rangeStart, long rangeEnd, Stream responseStream, long totalContentLength)
-        {
-            var rangeLength = 1 + rangeEnd - rangeStart;
-
-            // Content-Length is the length of what we're serving, not the original content
-            HttpListenerContext.Response.ContentLength64 = rangeLength;
-            HttpListenerContext.Response.Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", rangeStart, rangeEnd, totalContentLength);
-
-            SourceStream.Position = rangeStart;
-
-            // Fast track to just copy the stream to the end
-            if (rangeEnd == totalContentLength - 1)
-            {
-                await SourceStream.CopyToAsync(responseStream).ConfigureAwait(false);
-            }
-            else
-            {
-                // Read the bytes we need
-                var buffer = new byte[Convert.ToInt32(rangeLength)];
-                await SourceStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
-
-                await responseStream.WriteAsync(buffer, 0, Convert.ToInt32(rangeLength)).ConfigureAwait(false);
-            }
-        }
-    }
-}

+ 11 - 22
MediaBrowser.Common/Plugins/BasePlugin.cs

@@ -1,4 +1,4 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Model.Plugins;
 using MediaBrowser.Model.Serialization;
 using System;
@@ -17,22 +17,16 @@ namespace MediaBrowser.Common.Plugins
         where TConfigurationType : BasePluginConfiguration
     {
         /// <summary>
-        /// Gets the kernel.
+        /// Gets the application paths.
         /// </summary>
-        /// <value>The kernel.</value>
-        protected IKernel Kernel { get; private set; }
+        /// <value>The application paths.</value>
+        protected IApplicationPaths ApplicationPaths { get; private set; }
 
         /// <summary>
         /// Gets the XML serializer.
         /// </summary>
         /// <value>The XML serializer.</value>
         protected IXmlSerializer XmlSerializer { get; private set; }
-        
-        /// <summary>
-        /// Gets or sets the plugin's current context
-        /// </summary>
-        /// <value>The context.</value>
-        protected KernelContext Context { get { return Kernel.KernelContext; } }
 
         /// <summary>
         /// Gets the name of the plugin
@@ -174,7 +168,7 @@ namespace MediaBrowser.Common.Plugins
         {
             get
             {
-                return Path.Combine(Kernel.ApplicationPaths.PluginsPath, AssemblyFileName);
+                return Path.Combine(ApplicationPaths.PluginsPath, AssemblyFileName);
             }
         }
 
@@ -199,7 +193,7 @@ namespace MediaBrowser.Common.Plugins
             get
             {
                 // Lazy load
-                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => Kernel.GetXmlConfiguration(ConfigurationType, ConfigurationFilePath) as TConfigurationType);
+                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => ConfigurationHelper.GetXmlConfiguration(ConfigurationType, ConfigurationFilePath, XmlSerializer) as TConfigurationType);
                 return _configuration;
             }
             protected set
@@ -230,7 +224,7 @@ namespace MediaBrowser.Common.Plugins
         {
             get
             {
-                return Path.Combine(Kernel.ApplicationPaths.PluginConfigurationsPath, ConfigurationFileName);
+                return Path.Combine(ApplicationPaths.PluginConfigurationsPath, ConfigurationFileName);
             }
         }
 
@@ -250,7 +244,7 @@ namespace MediaBrowser.Common.Plugins
                 {
                     // Give the folder name the same name as the config file name
                     // We can always make this configurable if/when needed
-                    _dataFolderPath = Path.Combine(Kernel.ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(ConfigurationFileName));
+                    _dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(ConfigurationFileName));
 
                     if (!Directory.Exists(_dataFolderPath))
                     {
@@ -265,11 +259,11 @@ namespace MediaBrowser.Common.Plugins
         /// <summary>
         /// Initializes a new instance of the <see cref="BasePlugin{TConfigurationType}" /> class.
         /// </summary>
-        /// <param name="kernel">The kernel.</param>
+        /// <param name="applicationPaths">The application paths.</param>
         /// <param name="xmlSerializer">The XML serializer.</param>
-        protected BasePlugin(IKernel kernel, IXmlSerializer xmlSerializer)
+        protected BasePlugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
         {
-            Kernel = kernel;
+            ApplicationPaths = applicationPaths;
             XmlSerializer = xmlSerializer;
         }
 
@@ -284,11 +278,6 @@ namespace MediaBrowser.Common.Plugins
         /// <exception cref="System.InvalidOperationException">Cannot call Plugin.SaveConfiguration from the UI.</exception>
         public virtual void SaveConfiguration()
         {
-            if (Kernel.KernelContext != KernelContext.Server)
-            {
-                throw new InvalidOperationException("Cannot call Plugin.SaveConfiguration from the UI.");
-            }
-
             lock (_configurationSaveLock)
             {
                 XmlSerializer.SerializeToFile(Configuration, ConfigurationFilePath);

+ 1 - 0
MediaBrowser.Common/Updates/ApplicationUpdater.cs

@@ -5,6 +5,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.IO;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Kernel;
 
 namespace MediaBrowser.Common.Updates

+ 4 - 32
MediaBrowser.Common/Updates/IPackageManager.cs

@@ -1,16 +1,8 @@
-using System;
+using MediaBrowser.Model.Updates;
+using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Common.Security;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Updates;
 
 namespace MediaBrowser.Common.Updates
 {
@@ -19,37 +11,17 @@ namespace MediaBrowser.Common.Updates
         /// <summary>
         /// Gets all available packages.
         /// </summary>
-        /// <param name="client"></param>
-        /// <param name="networkManager"></param>
-        /// <param name="securityManager"></param>
-        /// <param name="resourcePool"></param>
-        /// <param name="serializer"></param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{List{PackageInfo}}.</returns>
-        Task<IEnumerable<PackageInfo>> GetAvailablePackages(IHttpClient client,
-                                                            INetworkManager networkManager,
-                                                            ISecurityManager securityManager,
-                                                            ResourcePool resourcePool,
-                                                            IJsonSerializer serializer,
-                                                            CancellationToken cancellationToken);
+        Task<IEnumerable<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken);
 
         /// <summary>
         /// Installs a package.
         /// </summary>
-        /// <param name="client"></param>
-        /// <param name="logger"></param>
-        /// <param name="resourcePool"></param>
         /// <param name="progress"></param>
-        /// <param name="appPaths"></param>
         /// <param name="package">The package.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
-        Task InstallPackage(IHttpClient client,
-                            ILogger logger,
-                            ResourcePool resourcePool,
-                            IProgress<double> progress,
-                            IApplicationPaths appPaths,
-                            PackageVersionInfo package,
-                            CancellationToken cancellationToken);
+        Task InstallPackage(IProgress<double> progress, PackageVersionInfo package, CancellationToken cancellationToken);
     }
 }

+ 23 - 0
MediaBrowser.Controller/Configuration/IServerConfigurationManager.cs

@@ -0,0 +1,23 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Configuration;
+
+namespace MediaBrowser.Controller.Configuration
+{
+    /// <summary>
+    /// Interface IServerConfigurationManager
+    /// </summary>
+    public interface IServerConfigurationManager : IConfigurationManager
+    {
+        /// <summary>
+        /// Gets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        IServerApplicationPaths ApplicationPaths { get; }
+
+        /// <summary>
+        /// Gets the configuration.
+        /// </summary>
+        /// <value>The configuration.</value>
+        ServerConfiguration Configuration { get; }
+    }
+}

+ 6 - 6
MediaBrowser.Controller/Drawing/ImageManager.cs

@@ -66,23 +66,23 @@ namespace MediaBrowser.Controller.Drawing
         /// The _kernel
         /// </summary>
         private readonly Kernel _kernel;
-        
+
         /// <summary>
         /// Initializes a new instance of the <see cref="ImageManager" /> class.
         /// </summary>
         /// <param name="kernel">The kernel.</param>
         /// <param name="protobufSerializer">The protobuf serializer.</param>
         /// <param name="logger">The logger.</param>
-        public ImageManager(Kernel kernel, IProtobufSerializer protobufSerializer, ILogger logger)
+        public ImageManager(Kernel kernel, IProtobufSerializer protobufSerializer, ILogger logger, IServerApplicationPaths appPaths)
         {
             _protobufSerializer = protobufSerializer;
             _logger = logger;
             _kernel = kernel;
 
-            ImageSizeCache = new FileSystemRepository(Path.Combine(_kernel.ApplicationPaths.ImageCachePath, "image-sizes"));
-            ResizedImageCache = new FileSystemRepository(Path.Combine(_kernel.ApplicationPaths.ImageCachePath, "resized-images"));
-            CroppedImageCache = new FileSystemRepository(Path.Combine(_kernel.ApplicationPaths.ImageCachePath, "cropped-images"));
-            EnhancedImageCache = new FileSystemRepository(Path.Combine(_kernel.ApplicationPaths.ImageCachePath, "enhanced-images"));
+            ImageSizeCache = new FileSystemRepository(Path.Combine(appPaths.ImageCachePath, "image-sizes"));
+            ResizedImageCache = new FileSystemRepository(Path.Combine(appPaths.ImageCachePath, "resized-images"));
+            CroppedImageCache = new FileSystemRepository(Path.Combine(appPaths.ImageCachePath, "cropped-images"));
+            EnhancedImageCache = new FileSystemRepository(Path.Combine(appPaths.ImageCachePath, "enhanced-images"));
         }
 
         /// <summary>

+ 8 - 5
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -1,4 +1,6 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
@@ -96,6 +98,7 @@ namespace MediaBrowser.Controller.Entities
         /// </summary>
         protected static internal ILogger Logger { get; internal set; }
         protected static internal ILibraryManager LibraryManager { get; internal set; }
+        protected static internal IServerConfigurationManager ConfigurationManager { get; internal set; }
 
         /// <summary>
         /// Returns a <see cref="System.String" /> that represents this instance.
@@ -311,7 +314,7 @@ namespace MediaBrowser.Controller.Entities
             // non file-system entries will not have a path
             if (string.IsNullOrEmpty(path))
             {
-                return new ItemResolveArgs
+                return new ItemResolveArgs(ConfigurationManager.ApplicationPaths)
                 {
                     FileInfo = new WIN32_FIND_DATA()
                 };
@@ -329,7 +332,7 @@ namespace MediaBrowser.Controller.Entities
                 throw new IOException("Unable to retrieve file system info for " + path);
             }
 
-            var args = new ItemResolveArgs
+            var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths)
             {
                 FileInfo = pathInfo.Value,
                 Path = path,
@@ -997,7 +1000,7 @@ namespace MediaBrowser.Controller.Entities
                 throw new ArgumentNullException();
             }
 
-            return (DateTime.UtcNow - DateCreated).TotalDays < Kernel.Instance.Configuration.RecentItemDays;
+            return (DateTime.UtcNow - DateCreated).TotalDays < ConfigurationManager.Configuration.RecentItemDays;
         }
 
         /// <summary>
@@ -1020,7 +1023,7 @@ namespace MediaBrowser.Controller.Entities
                 return false;
             }
 
-            return (DateTime.UtcNow - data.LastPlayedDate.Value).TotalDays < Kernel.Instance.Configuration.RecentlyPlayedDays;
+            return (DateTime.UtcNow - data.LastPlayedDate.Value).TotalDays < ConfigurationManager.Configuration.RecentlyPlayedDays;
         }
 
         /// <summary>

+ 8 - 6
MediaBrowser.Controller/Entities/User.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Configuration;
@@ -18,6 +19,7 @@ namespace MediaBrowser.Controller.Entities
     public class User : BaseItem
     {
         internal static IUserManager UserManager { get; set; }
+        internal static IXmlSerializer XmlSerializer { get; set; }
 
         /// <summary>
         /// The _root folder path
@@ -45,7 +47,7 @@ namespace MediaBrowser.Controller.Entities
                     }
                     else
                     {
-                        _rootFolderPath = Kernel.Instance.ApplicationPaths.DefaultUserViewsPath;
+                        _rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
                     }
                 }
                 return _rootFolderPath;
@@ -61,7 +63,7 @@ namespace MediaBrowser.Controller.Entities
         {
             var safeFolderName = FileSystem.GetValidFilename(username);
 
-            return System.IO.Path.Combine(Kernel.Instance.ApplicationPaths.RootFolderPath, safeFolderName);
+            return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.RootFolderPath, safeFolderName);
         }
 
         /// <summary>
@@ -171,7 +173,7 @@ namespace MediaBrowser.Controller.Entities
             get
             {
                 // Lazy load
-                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => (UserConfiguration)Kernel.Instance.GetXmlConfiguration(typeof(UserConfiguration), ConfigurationFilePath));
+                LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationInitialized, ref _configurationSyncLock, () => (UserConfiguration)ConfigurationHelper.GetXmlConfiguration(typeof(UserConfiguration), ConfigurationFilePath, XmlSerializer));
                 return _configuration;
             }
             private set
@@ -321,7 +323,7 @@ namespace MediaBrowser.Controller.Entities
         {
             var safeFolderName = FileSystem.GetValidFilename(username);
 
-            return System.IO.Path.Combine(Kernel.Instance.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName);
+            return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName);
         }
 
         /// <summary>
@@ -411,7 +413,7 @@ namespace MediaBrowser.Controller.Entities
         {
             var userPath = RootFolderPath;
 
-            var defaultPath = Kernel.Instance.ApplicationPaths.DefaultUserViewsPath;
+            var defaultPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath;
 
             if (userPath.Equals(defaultPath, StringComparison.OrdinalIgnoreCase))
             {

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

@@ -1,5 +1,5 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.ScheduledTasks;
@@ -74,16 +74,13 @@ namespace MediaBrowser.Controller.IO
         private ITaskManager TaskManager { get; set; }
 
         private ILibraryManager LibraryManager { get; set; }
+        private IServerConfigurationManager ConfigurationManager { get; set; }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="DirectoryWatchers" /> class.
         /// </summary>
-        public DirectoryWatchers(ILogger logger, ITaskManager taskManager, ILibraryManager libraryManager)
+        public DirectoryWatchers(ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager)
         {
-            if (logger == null)
-            {
-                throw new ArgumentNullException("logger");
-            }
             if (taskManager == null)
             {
                 throw new ArgumentNullException("taskManager");
@@ -91,7 +88,8 @@ namespace MediaBrowser.Controller.IO
 
             LibraryManager = libraryManager;
             TaskManager = taskManager;
-            Logger = logger;
+            Logger = logManager.GetLogger("DirectoryWatchers");
+            ConfigurationManager = configurationManager;
         }
         
         /// <summary>
@@ -335,11 +333,11 @@ namespace MediaBrowser.Controller.IO
             {
                 if (updateTimer == null)
                 {
-                    updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(Kernel.Instance.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1));
+                    updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1));
                 }
                 else
                 {
-                    updateTimer.Change(TimeSpan.FromSeconds(Kernel.Instance.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1));
+                    updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1));
                 }
             }
         }
@@ -356,7 +354,7 @@ namespace MediaBrowser.Controller.IO
                 if (affectedPaths.Any(p => IsFileLocked(p.Key)))
                 {
                     Logger.Info("Timer extended.");
-                    updateTimer.Change(TimeSpan.FromSeconds(Kernel.Instance.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1));
+                    updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.FileWatcherDelay), TimeSpan.FromMilliseconds(-1));
                     return;
                 }
 

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

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Logging;
@@ -33,14 +34,15 @@ namespace MediaBrowser.Controller.IO
         /// Initializes a new instance of the <see cref="FileSystemManager" /> class.
         /// </summary>
         /// <param name="kernel">The kernel.</param>
-        /// <param name="logger">The logger.</param>
+        /// <param name="logManager">The log manager.</param>
         /// <param name="taskManager">The task manager.</param>
         /// <param name="libraryManager">The library manager.</param>
-        public FileSystemManager(Kernel kernel, ILogger logger, ITaskManager taskManager, ILibraryManager libraryManager)
+        /// <param name="configurationManager">The configuration manager.</param>
+        public FileSystemManager(Kernel kernel, ILogManager logManager, ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager)
             : base(kernel)
         {
-            _logger = logger;
-            DirectoryWatchers = new DirectoryWatchers(logger, taskManager, libraryManager);
+            _logger = logManager.GetLogger("FileSystemManager");
+            DirectoryWatchers = new DirectoryWatchers(logManager, taskManager, libraryManager, configurationManager);
         }
 
         /// <summary>

+ 2 - 1
MediaBrowser.Controller/IServerApplicationPaths.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 
 namespace MediaBrowser.Controller
 {

+ 38 - 61
MediaBrowser.Controller/Kernel.cs

@@ -1,5 +1,7 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.ScheduledTasks;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.IO;
@@ -11,7 +13,6 @@ using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Updates;
 using MediaBrowser.Controller.Weather;
-using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.System;
@@ -26,7 +27,7 @@ namespace MediaBrowser.Controller
     /// <summary>
     /// Class Kernel
     /// </summary>
-    public class Kernel : BaseKernel<ServerConfiguration, IServerApplicationPaths>
+    public class Kernel : BaseKernel, IDisposable
     {
         /// <summary>
         /// Gets the instance.
@@ -161,23 +162,34 @@ namespace MediaBrowser.Controller
             get { return 7359; }
         }
 
+        private readonly IXmlSerializer _xmlSerializer;
+
+        private readonly IServerConfigurationManager _configurationManager;
+        private readonly ILogManager _logManager;
+
         /// <summary>
         /// Creates a kernel based on a Data path, which is akin to our current programdata path
         /// </summary>
         /// <param name="appHost">The app host.</param>
-        /// <param name="appPaths">The app paths.</param>
         /// <param name="xmlSerializer">The XML serializer.</param>
-        /// <param name="logger">The logger.</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
         /// <exception cref="System.ArgumentNullException">isoManager</exception>
-        public Kernel(IApplicationHost appHost, IServerApplicationPaths appPaths, IXmlSerializer xmlSerializer, ILogger logger)
-            : base(appHost, appPaths, xmlSerializer, logger)
+        public Kernel(IApplicationHost appHost, IXmlSerializer xmlSerializer, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(appHost, logManager, configurationManager)
         {
             Instance = this;
 
-            // For now there's no real way to inject this properly
-            BaseItem.Logger = logger;
-            Ratings.Logger = logger;
-            LocalizedStrings.Logger = logger;
+            _configurationManager = configurationManager;
+            _xmlSerializer = xmlSerializer;
+            _logManager = logManager;
+            
+            // For now there's no real way to inject these properly
+            BaseItem.Logger = logManager.GetLogger("BaseItem");
+            User.XmlSerializer = _xmlSerializer;
+            Ratings.ConfigurationManager = _configurationManager;
+            LocalizedStrings.ApplicationPaths = _configurationManager.ApplicationPaths;
+            BaseItem.ConfigurationManager = configurationManager;
         }
 
         /// <summary>
@@ -185,14 +197,13 @@ namespace MediaBrowser.Controller
         /// </summary>
         protected void FindParts()
         {
-            // For now there's no real way to inject this properly
+            // For now there's no real way to inject these properly
             BaseItem.LibraryManager = ApplicationHost.Resolve<ILibraryManager>();
             User.UserManager = ApplicationHost.Resolve<IUserManager>();
 
             FFMpegManager = (FFMpegManager)ApplicationHost.CreateInstance(typeof(FFMpegManager));
             ImageManager = (ImageManager)ApplicationHost.CreateInstance(typeof(ImageManager));
             ProviderManager = (ProviderManager)ApplicationHost.CreateInstance(typeof(ProviderManager));
-            SecurityManager = (PluginSecurityManager)ApplicationHost.CreateInstance(typeof(PluginSecurityManager));
             
             UserDataRepositories = ApplicationHost.GetExports<IUserDataRepository>();
             UserRepositories = ApplicationHost.GetExports<IUserRepository>();
@@ -217,8 +228,6 @@ namespace MediaBrowser.Controller
 
             await LoadRepositories().ConfigureAwait(false);
 
-            ReloadResourcePools();
-
             await ApplicationHost.Resolve<IUserManager>().RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false);
 
             foreach (var entryPoint in ApplicationHost.GetExports<IServerEntryPoint>())
@@ -230,42 +239,26 @@ namespace MediaBrowser.Controller
         }
 
         /// <summary>
-        /// Releases unmanaged and - optionally - managed resources.
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
         /// </summary>
-        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
-        protected override void Dispose(bool dispose)
+        public void Dispose()
         {
-            if (dispose)
-            {
-                DisposeResourcePools();
-
-                DisposeFileSystemManager();
-            }
-
-            base.Dispose(dispose);
+            Dispose(true);
+            GC.SuppressFinalize(this);
         }
 
         /// <summary>
-        /// Disposes the resource pools.
+        /// Releases unmanaged and - optionally - managed resources.
         /// </summary>
-        private void DisposeResourcePools()
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool dispose)
         {
-            if (ResourcePools != null)
+            if (dispose)
             {
-                ResourcePools.Dispose();
-                ResourcePools = null;
+                DisposeFileSystemManager();
             }
         }
 
-        /// <summary>
-        /// Reloads the resource pools.
-        /// </summary>
-        private void ReloadResourcePools()
-        {
-            DisposeResourcePools();
-            ResourcePools = new ResourcePool();
-        }
-
         /// <summary>
         /// Called when [composable parts loaded].
         /// </summary>
@@ -273,19 +266,19 @@ namespace MediaBrowser.Controller
         protected Task LoadRepositories()
         {
             // Get the current item repository
-            ItemRepository = GetRepository(ItemRepositories, Configuration.ItemRepository);
+            ItemRepository = GetRepository(ItemRepositories, _configurationManager.Configuration.ItemRepository);
             var itemRepoTask = ItemRepository.Initialize();
 
             // Get the current user repository
-            UserRepository = GetRepository(UserRepositories, Configuration.UserRepository);
+            UserRepository = GetRepository(UserRepositories, _configurationManager.Configuration.UserRepository);
             var userRepoTask = UserRepository.Initialize();
 
             // Get the current item repository
-            UserDataRepository = GetRepository(UserDataRepositories, Configuration.UserDataRepository);
+            UserDataRepository = GetRepository(UserDataRepositories, _configurationManager.Configuration.UserDataRepository);
             var userDataRepoTask = UserDataRepository.Initialize();
 
             // Get the current display preferences repository
-            DisplayPreferencesRepository = GetRepository(DisplayPreferencesRepositories, Configuration.DisplayPreferencesRepository);
+            DisplayPreferencesRepository = GetRepository(DisplayPreferencesRepositories, _configurationManager.Configuration.DisplayPreferencesRepository);
             var displayPreferencesRepoTask = DisplayPreferencesRepository.Initialize();
 
             return Task.WhenAll(itemRepoTask, userRepoTask, userDataRepoTask, displayPreferencesRepoTask);
@@ -326,26 +319,10 @@ namespace MediaBrowser.Controller
         {
             DisposeFileSystemManager();
 
-            FileSystemManager = new FileSystemManager(this, Logger, ApplicationHost.Resolve<ITaskManager>(), ApplicationHost.Resolve<ILibraryManager>());
+            FileSystemManager = new FileSystemManager(this, _logManager, ApplicationHost.Resolve<ITaskManager>(), ApplicationHost.Resolve<ILibraryManager>(), _configurationManager);
             FileSystemManager.StartWatchers();
         }
 
-        /// <summary>
-        /// Completely overwrites the current configuration with a new copy
-        /// </summary>
-        /// <param name="config">The config.</param>
-        public void UpdateConfiguration(ServerConfiguration config)
-        {
-            Configuration = config;
-            SaveConfiguration();
-
-            // Validate currently executing providers, in the background
-            Task.Run(() =>
-            {
-                ProviderManager.ValidateCurrentlyRunningProviders();
-            });
-        }
-
         /// <summary>
         /// Gets the system info.
         /// </summary>

+ 0 - 34
MediaBrowser.Controller/Library/DtoBuilder.cs

@@ -474,14 +474,8 @@ namespace MediaBrowser.Controller.Library
         /// <param name="dto">The dto.</param>
         private static void SetSpecialCounts(Folder folder, User user, BaseItemDto dto)
         {
-            var utcNow = DateTime.UtcNow;
-
             var rcentlyAddedItemCount = 0;
             var recursiveItemCount = 0;
-            var favoriteItemsCount = 0;
-            var recentlyAddedUnPlayedItemCount = 0;
-            var resumableItemCount = 0;
-            var recentlyPlayedItemCount = 0;
 
             double totalPercentPlayed = 0;
 
@@ -498,12 +492,6 @@ namespace MediaBrowser.Controller.Library
                     if (child.IsRecentlyAdded(user))
                     {
                         rcentlyAddedItemCount++;
-
-                        // Check recently added unplayed
-                        if (userdata == null || userdata.PlayCount == 0)
-                        {
-                            recentlyAddedUnPlayedItemCount++;
-                        }
                     }
 
                     // Incrememt totalPercentPlayed
@@ -521,32 +509,10 @@ namespace MediaBrowser.Controller.Library
                         }
                     }
                 }
-
-                if (userdata != null)
-                {
-                    if (userdata.IsFavorite)
-                    {
-                        favoriteItemsCount++;
-                    }
-
-                    if (userdata.PlaybackPositionTicks > 0)
-                    {
-                        resumableItemCount++;
-                    }
-
-                    if (userdata.LastPlayedDate.HasValue && (utcNow - userdata.LastPlayedDate.Value).TotalDays < Kernel.Instance.Configuration.RecentlyPlayedDays)
-                    {
-                        recentlyPlayedItemCount++;
-                    }
-                }
             }
 
             dto.RecursiveItemCount = recursiveItemCount;
             dto.RecentlyAddedItemCount = rcentlyAddedItemCount;
-            dto.RecentlyAddedUnPlayedItemCount = recentlyAddedUnPlayedItemCount;
-            dto.ResumableItemCount = resumableItemCount;
-            dto.FavoriteItemCount = favoriteItemsCount;
-            dto.RecentlyPlayedItemCount = recentlyPlayedItemCount;
 
             if (recursiveItemCount > 0)
             {

+ 19 - 5
MediaBrowser.Controller/Library/ItemResolveArgs.cs

@@ -1,9 +1,9 @@
 using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
 using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
-using MediaBrowser.Controller.IO;
 
 namespace MediaBrowser.Controller.Library
 {
@@ -13,6 +13,20 @@ namespace MediaBrowser.Controller.Library
     /// </summary>
     public class ItemResolveArgs : EventArgs
     {
+        /// <summary>
+        /// The _app paths
+        /// </summary>
+        private readonly IServerApplicationPaths _appPaths;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ItemResolveArgs" /> class.
+        /// </summary>
+        /// <param name="appPaths">The app paths.</param>
+        public ItemResolveArgs(IServerApplicationPaths appPaths)
+        {
+            _appPaths = appPaths;
+        }
+
         /// <summary>
         /// Gets the file system children.
         /// </summary>
@@ -99,9 +113,9 @@ namespace MediaBrowser.Controller.Library
                 }
 
                 var parentDir = FileInfo.Path != null ? System.IO.Path.GetDirectoryName(FileInfo.Path) ?? string.Empty : string.Empty;
-                
-                return (parentDir.Length > Kernel.Instance.ApplicationPaths.RootFolderPath.Length
-                    && parentDir.StartsWith(Kernel.Instance.ApplicationPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase));
+
+                return (parentDir.Length > _appPaths.RootFolderPath.Length
+                    && parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase));
 
             }
         }
@@ -114,7 +128,7 @@ namespace MediaBrowser.Controller.Library
         {
             get
             {
-                return IsDirectory && Path.Equals(Kernel.Instance.ApplicationPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
+                return IsDirectory && Path.Equals(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
             }
         }
 

+ 14 - 11
MediaBrowser.Controller/Localization/LocalizedStrings.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Logging;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Concurrent;
 using System.Globalization;
@@ -14,10 +15,8 @@ namespace MediaBrowser.Controller.Localization
     /// </summary>
     public class LocalizedStrings
     {
-        /// <summary>
-        /// The logger
-        /// </summary>
-        static internal ILogger Logger { get; set; }
+        internal static IServerApplicationPaths ApplicationPaths;
+        
         /// <summary>
         /// The base prefix
         /// </summary>
@@ -31,17 +30,21 @@ namespace MediaBrowser.Controller.Localization
         /// </summary>
         private static LocalizedStrings _instance;
 
+        private IServerApplicationPaths _appPaths;
+
         /// <summary>
         /// Gets the instance.
         /// </summary>
         /// <value>The instance.</value>
-        public static LocalizedStrings Instance { get { return _instance ?? (_instance = new LocalizedStrings()); } }
+        public static LocalizedStrings Instance { get { return _instance ?? (_instance = new LocalizedStrings(ApplicationPaths)); } }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="LocalizedStrings" /> class.
         /// </summary>
-        public LocalizedStrings()
+        public LocalizedStrings(IServerApplicationPaths appPaths)
         {
+            _appPaths = appPaths;
+
             foreach (var stringObject in Kernel.Instance.StringFiles)
             {
                 AddStringData(LoadFromFile(GetFileName(stringObject),stringObject.GetType()));
@@ -55,7 +58,7 @@ namespace MediaBrowser.Controller.Localization
         /// <returns>System.String.</returns>
         protected string GetFileName(LocalizedStringData stringObject)
         {
-            var path = Kernel.Instance.ApplicationPaths.LocalizationPath;
+            var path = _appPaths.LocalizationPath;
             var name = Path.Combine(path, stringObject.Prefix + "strings-" + CultureInfo.CurrentCulture + ".xml");
             if (File.Exists(name))
             {
@@ -125,17 +128,17 @@ namespace MediaBrowser.Controller.Localization
                 }
                 catch (TargetException ex)
                 {
-                    Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
+                    //Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
                     continue;
                 }
                 catch (FieldAccessException ex)
                 {
-                    Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
+                    //Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
                     continue;
                 }
                 catch (NotSupportedException ex)
                 {
-                    Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
+                    //Logger.ErrorException("Error getting value for field: {0}", ex, field.Name);
                     continue;
                 }
 

+ 7 - 5
MediaBrowser.Controller/Localization/Ratings.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Model.Logging;
 using System.Collections.Generic;
 using System.IO;
@@ -11,7 +12,8 @@ namespace MediaBrowser.Controller.Localization
     /// </summary>
     public static class Ratings
     {
-        static internal ILogger Logger { get; set; }
+        internal static IServerConfigurationManager ConfigurationManager;
+
         /// <summary>
         /// The ratings def
         /// </summary>
@@ -26,7 +28,7 @@ namespace MediaBrowser.Controller.Localization
         /// <value>The ratings dict.</value>
         public static Dictionary<string, int> RatingsDict
         {
-            get { return _ratingsDict ?? (_ratingsDict = Initialize(false)); }
+            get { return _ratingsDict ?? (_ratingsDict = Initialize(false, ConfigurationManager)); }
         }
         /// <summary>
         /// The ratings strings
@@ -38,17 +40,17 @@ namespace MediaBrowser.Controller.Localization
         /// </summary>
         /// <param name="blockUnrated">if set to <c>true</c> [block unrated].</param>
         /// <returns>Dictionary{System.StringSystem.Int32}.</returns>
-        public static Dictionary<string, int> Initialize(bool blockUnrated)
+        public static Dictionary<string, int> Initialize(bool blockUnrated, IServerConfigurationManager configurationManager)
         {
             //build our ratings dictionary from the combined local one and us one
-            ratingsDef = new RatingsDefinition(Path.Combine(Kernel.Instance.ApplicationPaths.LocalizationPath, "Ratings-" + Kernel.Instance.Configuration.MetadataCountryCode + ".txt"), Logger);
+            ratingsDef = new RatingsDefinition(Path.Combine(configurationManager.ApplicationPaths.LocalizationPath, "Ratings-" + configurationManager.Configuration.MetadataCountryCode + ".txt"), configurationManager);
             //global value of None
             var dict = new Dictionary<string, int> {{"None", -1}};
             foreach (var pair in ratingsDef.RatingsDict)
             {
                 dict.TryAdd(pair.Key, pair.Value);
             }
-            if (Kernel.Instance.Configuration.MetadataCountryCode.ToUpper() != "US")
+            if (configurationManager.Configuration.MetadataCountryCode.ToUpper() != "US")
             {
                 foreach (var pair in new USRatingsDictionary())
                 {

+ 6 - 13
MediaBrowser.Controller/Localization/RatingsDefinition.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Logging;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;
 using System.IO;
@@ -10,26 +11,18 @@ namespace MediaBrowser.Controller.Localization
     /// </summary>
     public class RatingsDefinition
     {
-        /// <summary>
-        /// Gets or sets the logger.
-        /// </summary>
-        /// <value>The logger.</value>
-        private ILogger Logger { get; set; }
-
         /// <summary>
         /// Initializes a new instance of the <see cref="RatingsDefinition" /> class.
         /// </summary>
         /// <param name="file">The file.</param>
         /// <param name="logger">The logger.</param>
-        public RatingsDefinition(string file, ILogger logger)
+        /// <param name="configurationManager">The configuration manager.</param>
+        public RatingsDefinition(string file, IServerConfigurationManager configurationManager)
         {
-            Logger = logger;
-
-            Logger.Info("Loading Certification Ratings from file " + file);
             this.file = file;
             if (!Load())
             {
-                Init(Kernel.Instance.Configuration.MetadataCountryCode.ToUpper());
+                Init(configurationManager.Configuration.MetadataCountryCode.ToUpper());
             }
         }
 
@@ -108,7 +101,7 @@ namespace MediaBrowser.Controller.Localization
                             }
                             else
                             {
-                                Logger.Error("Invalid line in ratings file " + file + "(" + line + ")");
+                                //Logger.Error("Invalid line in ratings file " + file + "(" + line + ")");
                             }
                         }
                     }

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

@@ -53,9 +53,6 @@
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="Mediabrowser.PluginSecurity">
-      <HintPath>Plugins\Mediabrowser.PluginSecurity.dll</HintPath>
-    </Reference>
     <Reference Include="protobuf-net, Version=2.0.0.621, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\packages\protobuf-net.2.0.0.621\lib\net40\protobuf-net.dll</HintPath>
@@ -74,6 +71,7 @@
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
     <Compile Include="BaseManager.cs" />
+    <Compile Include="Configuration\IServerConfigurationManager.cs" />
     <Compile Include="Drawing\ImageExtensions.cs" />
     <Compile Include="Drawing\ImageHeader.cs" />
     <Compile Include="Drawing\ImageManager.cs" />
@@ -135,7 +133,6 @@
     <Compile Include="Library\IIntroProvider.cs" />
     <Compile Include="Plugins\IPluginConfigurationPage.cs" />
     <Compile Include="Plugins\IServerEntryPoint.cs" />
-    <Compile Include="Plugins\PluginSecurityManager.cs" />
     <Compile Include="Providers\Music\LastfmBaseProvider.cs" />
     <Compile Include="Providers\FanartBaseProvider.cs" />
     <Compile Include="Providers\IImageEnhancer.cs" />

+ 8 - 10
MediaBrowser.Controller/MediaInfo/FFMpegManager.cs

@@ -67,6 +67,7 @@ namespace MediaBrowser.Controller.MediaInfo
         /// The _protobuf serializer
         /// </summary>
         private readonly IProtobufSerializer _protobufSerializer;
+        private readonly IServerApplicationPaths _appPaths;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="FFMpegManager" /> class.
@@ -77,7 +78,7 @@ namespace MediaBrowser.Controller.MediaInfo
         /// <param name="protobufSerializer">The protobuf serializer.</param>
         /// <param name="logger">The logger.</param>
         /// <exception cref="System.ArgumentNullException">zipClient</exception>
-        public FFMpegManager(Kernel kernel, IZipClient zipClient, IJsonSerializer jsonSerializer, IProtobufSerializer protobufSerializer, ILogger logger)
+        public FFMpegManager(Kernel kernel, IZipClient zipClient, IJsonSerializer jsonSerializer, IProtobufSerializer protobufSerializer, ILogManager logManager, IServerApplicationPaths appPaths)
         {
             if (kernel == null)
             {
@@ -95,16 +96,13 @@ namespace MediaBrowser.Controller.MediaInfo
             {
                 throw new ArgumentNullException("protobufSerializer");
             }
-            if (logger == null)
-            {
-                throw new ArgumentNullException("logger");
-            }
 
             _kernel = kernel;
             _zipClient = zipClient;
             _jsonSerializer = jsonSerializer;
             _protobufSerializer = protobufSerializer;
-            _logger = logger;
+            _appPaths = appPaths;
+            _logger = logManager.GetLogger("FFMpegManager");
 
             // Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes
             SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT | ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX);
@@ -223,7 +221,7 @@ namespace MediaBrowser.Controller.MediaInfo
             {
                 if (_videoImagesDataPath == null)
                 {
-                    _videoImagesDataPath = Path.Combine(_kernel.ApplicationPaths.DataPath, "ffmpeg-video-images");
+                    _videoImagesDataPath = Path.Combine(_appPaths.DataPath, "ffmpeg-video-images");
 
                     if (!Directory.Exists(_videoImagesDataPath))
                     {
@@ -249,7 +247,7 @@ namespace MediaBrowser.Controller.MediaInfo
             {
                 if (_audioImagesDataPath == null)
                 {
-                    _audioImagesDataPath = Path.Combine(_kernel.ApplicationPaths.DataPath, "ffmpeg-audio-images");
+                    _audioImagesDataPath = Path.Combine(_appPaths.DataPath, "ffmpeg-audio-images");
 
                     if (!Directory.Exists(_audioImagesDataPath))
                     {
@@ -275,7 +273,7 @@ namespace MediaBrowser.Controller.MediaInfo
             {
                 if (_subtitleCachePath == null)
                 {
-                    _subtitleCachePath = Path.Combine(_kernel.ApplicationPaths.CachePath, "ffmpeg-subtitles");
+                    _subtitleCachePath = Path.Combine(_appPaths.CachePath, "ffmpeg-subtitles");
 
                     if (!Directory.Exists(_subtitleCachePath))
                     {
@@ -302,7 +300,7 @@ namespace MediaBrowser.Controller.MediaInfo
 
             var filename = resource.Substring(resource.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) + prefix.Length);
 
-            var versionedDirectoryPath = Path.Combine(_kernel.ApplicationPaths.MediaToolsPath, Path.GetFileNameWithoutExtension(filename));
+            var versionedDirectoryPath = Path.Combine(_appPaths.MediaToolsPath, Path.GetFileNameWithoutExtension(filename));
 
             if (!Directory.Exists(versionedDirectoryPath))
             {

+ 11 - 2
MediaBrowser.Controller/Providers/BaseMetadataProvider.cs

@@ -1,4 +1,6 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Logging;
 using System;
@@ -19,6 +21,12 @@ namespace MediaBrowser.Controller.Providers
         protected ILogger Logger { get; set; }
         protected ILogManager LogManager { get; set; }
 
+        /// <summary>
+        /// Gets the configuration manager.
+        /// </summary>
+        /// <value>The configuration manager.</value>
+        protected IServerConfigurationManager ConfigurationManager { get; private set; }
+
         // Cache these since they will be used a lot
         /// <summary>
         /// The false task result
@@ -103,10 +111,11 @@ namespace MediaBrowser.Controller.Providers
         /// <summary>
         /// Initializes a new instance of the <see cref="BaseMetadataProvider" /> class.
         /// </summary>
-        protected BaseMetadataProvider(ILogManager logManager)
+        protected BaseMetadataProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
         {
             Logger = logManager.GetLogger(GetType().Name);
             LogManager = logManager;
+            ConfigurationManager = configurationManager;
 
             Initialize();
         }

+ 4 - 3
MediaBrowser.Controller/Providers/FanartBaseProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using System;
 using MediaBrowser.Model.Logging;
 
@@ -35,7 +36,7 @@ namespace MediaBrowser.Controller.Providers
         /// </summary>
         protected const string APIKey = "5c6b04c68e904cfed1e6cbc9a9e683d4";
 
-        protected FanartBaseProvider(ILogManager logManager) : base(logManager)
+        protected FanartBaseProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 
@@ -49,7 +50,7 @@ namespace MediaBrowser.Controller.Providers
         {
             if (item.DontFetchMeta) return false;
 
-            return DateTime.UtcNow > (providerInfo.LastRefreshed.AddDays(Kernel.Instance.Configuration.MetadataRefreshDays)) 
+            return DateTime.UtcNow > (providerInfo.LastRefreshed.AddDays(ConfigurationManager.Configuration.MetadataRefreshDays)) 
                 && ShouldFetch(item, providerInfo);
         }
 

+ 3 - 2
MediaBrowser.Controller/Providers/FolderProviderFromXml.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Entities;
 using System;
 using System.IO;
@@ -13,7 +14,7 @@ namespace MediaBrowser.Controller.Providers
     /// </summary>
     public class FolderProviderFromXml : BaseMetadataProvider
     {
-        public FolderProviderFromXml(ILogManager logManager) : base(logManager)
+        public FolderProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 3 - 2
MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Model.Entities;
 using System;
@@ -16,7 +17,7 @@ namespace MediaBrowser.Controller.Providers
     /// </summary>
     public class ImageFromMediaLocationProvider : BaseMetadataProvider
     {
-        public ImageFromMediaLocationProvider(ILogManager logManager) : base(logManager)
+        public ImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 4 - 3
MediaBrowser.Controller/Providers/ImagesByNameProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.IO;
 using System;
 using System.Globalization;
@@ -13,7 +14,7 @@ namespace MediaBrowser.Controller.Providers
     /// </summary>
     public class ImagesByNameProvider : ImageFromMediaLocationProvider
     {
-        public ImagesByNameProvider(ILogManager logManager) : base(logManager)
+        public ImagesByNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 
@@ -82,7 +83,7 @@ namespace MediaBrowser.Controller.Providers
             var name = item.Name ?? string.Empty;
             name = invalid.Aggregate(name, (current, c) => current.Replace(c.ToString(UsCulture), string.Empty));
 
-            return Path.Combine(Kernel.Instance.ApplicationPaths.GeneralPath, name);
+            return Path.Combine(ConfigurationManager.ApplicationPaths.GeneralPath, name);
         }
 
         /// <summary>

+ 3 - 2
MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Logging;
 
 namespace MediaBrowser.Controller.Providers.MediaInfo
@@ -6,7 +7,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
     public abstract class BaseFFMpegImageProvider<T> : BaseFFMpegProvider<T>
         where T : BaseItem
     {
-        protected BaseFFMpegImageProvider(ILogManager logManager) : base(logManager)
+        protected BaseFFMpegImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 2 - 1
MediaBrowser.Controller/Providers/MediaInfo/BaseFFMpegProvider.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Entities;
 using System;
@@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
     public abstract class BaseFFMpegProvider<T> : BaseMetadataProvider
         where T : BaseItem
     {
-        protected BaseFFMpegProvider(ILogManager logManager) : base(logManager)
+        protected BaseFFMpegProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 3 - 2
MediaBrowser.Controller/Providers/MediaInfo/BaseFFProbeProvider.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.MediaInfo;
 using MediaBrowser.Controller.Persistence;
@@ -19,7 +20,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
     public abstract class BaseFFProbeProvider<T> : BaseFFMpegProvider<T>
         where T : BaseItem
     {
-        protected BaseFFProbeProvider(ILogManager logManager) : base(logManager)
+        protected BaseFFProbeProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 
@@ -35,7 +36,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
         protected override void Initialize()
         {
             base.Initialize();
-            FFProbeCache = new FileSystemRepository(Path.Combine(Kernel.Instance.ApplicationPaths.CachePath, CacheDirectoryName));
+            FFProbeCache = new FileSystemRepository(Path.Combine(ConfigurationManager.ApplicationPaths.CachePath, CacheDirectoryName));
         }
 
         /// <summary>

+ 3 - 2
MediaBrowser.Controller/Providers/MediaInfo/FFMpegAudioImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Model.Entities;
 using System;
@@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
     /// </summary>
     public class FFMpegAudioImageProvider : BaseFFMpegImageProvider<Audio>
     {
-        public FFMpegAudioImageProvider(ILogManager logManager) : base(logManager)
+        public FFMpegAudioImageProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 6 - 3
MediaBrowser.Controller/Providers/MediaInfo/FFMpegVideoImageProvider.cs

@@ -1,10 +1,11 @@
 using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
 using System;
 using System.Threading;
 using System.Threading.Tasks;
-using MediaBrowser.Model.Logging;
 
 namespace MediaBrowser.Controller.Providers.MediaInfo
 {
@@ -22,8 +23,10 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
         /// Initializes a new instance of the <see cref="FfMpegVideoImageProvider" /> class.
         /// </summary>
         /// <param name="isoManager">The iso manager.</param>
-        public FfMpegVideoImageProvider(IIsoManager isoManager, ILogManager logManager)
-            : base(logManager)
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
+        public FfMpegVideoImageProvider(IIsoManager isoManager, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
             _isoManager = isoManager;
         }

+ 2 - 1
MediaBrowser.Controller/Providers/MediaInfo/FFProbeAudioInfoProvider.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.MediaInfo;
@@ -17,7 +18,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
     /// </summary>
     public class FFProbeAudioInfoProvider : BaseFFProbeProvider<Audio>
     {
-        public FFProbeAudioInfoProvider(ILogManager logManager) : base(logManager)
+        public FFProbeAudioInfoProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 24 - 30
MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.MediaInfo;
@@ -20,6 +21,29 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
     /// </summary>
     public class FFProbeVideoInfoProvider : BaseFFProbeProvider<Video>
     {
+        public FFProbeVideoInfoProvider(IIsoManager isoManager, IBlurayExaminer blurayExaminer, IProtobufSerializer protobufSerializer, ILogManager logManager, IServerConfigurationManager configurationManager) 
+            : base(logManager, configurationManager)
+        {
+            if (isoManager == null)
+            {
+                throw new ArgumentNullException("isoManager");
+            }
+            if (blurayExaminer == null)
+            {
+                throw new ArgumentNullException("blurayExaminer");
+            }
+            if (protobufSerializer == null)
+            {
+                throw new ArgumentNullException("protobufSerializer");
+            }
+
+            _blurayExaminer = blurayExaminer;
+            _isoManager = isoManager;
+            _protobufSerializer = protobufSerializer;
+
+            BdInfoCache = new FileSystemRepository(Path.Combine(ConfigurationManager.ApplicationPaths.CachePath, "bdinfo"));
+        }
+
         /// <summary>
         /// Gets or sets the bd info cache.
         /// </summary>
@@ -42,36 +66,6 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
         /// </summary>
         private readonly IProtobufSerializer _protobufSerializer;
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="FFProbeVideoInfoProvider" /> class.
-        /// </summary>
-        /// <param name="isoManager">The iso manager.</param>
-        /// <param name="blurayExaminer">The bluray examiner.</param>
-        /// <param name="protobufSerializer">The protobuf serializer.</param>
-        /// <exception cref="System.ArgumentNullException">blurayExaminer</exception>
-        public FFProbeVideoInfoProvider(IIsoManager isoManager, IBlurayExaminer blurayExaminer, IProtobufSerializer protobufSerializer, ILogManager logManager)
-            : base(logManager)
-        {
-            if (isoManager == null)
-            {
-                throw new ArgumentNullException("isoManager");
-            }
-            if (blurayExaminer == null)
-            {
-                throw new ArgumentNullException("blurayExaminer");
-            }
-            if (protobufSerializer == null)
-            {
-                throw new ArgumentNullException("protobufSerializer");
-            }
-
-            _blurayExaminer = blurayExaminer;
-            _isoManager = isoManager;
-            _protobufSerializer = protobufSerializer;
-
-            BdInfoCache = new FileSystemRepository(Path.Combine(Kernel.Instance.ApplicationPaths.CachePath, "bdinfo"));
-        }
-
         /// <summary>
         /// Returns true or false indicating if the provider should refresh when the contents of it's directory changes
         /// </summary>

+ 46 - 18
MediaBrowser.Controller/Providers/Movies/FanArtMovieProvider.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Model.Entities;
@@ -18,14 +19,28 @@ namespace MediaBrowser.Controller.Providers.Movies
     /// </summary>
     class FanArtMovieProvider : FanartBaseProvider
     {
+        /// <summary>
+        /// The fan art
+        /// </summary>
+        internal readonly SemaphoreSlim FanArtResourcePool = new SemaphoreSlim(5, 5);
+
+        internal static FanArtMovieProvider Current { get; private set; }
+
         /// <summary>
         /// Gets the HTTP client.
         /// </summary>
         /// <value>The HTTP client.</value>
         protected IHttpClient HttpClient { get; private set; }
 
-        public FanArtMovieProvider(IHttpClient httpClient, ILogManager logManager)
-            : base(logManager)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="FanArtMovieProvider" /> class.
+        /// </summary>
+        /// <param name="httpClient">The HTTP client.</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
+        /// <exception cref="System.ArgumentNullException">httpClient</exception>
+        public FanArtMovieProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
             if (httpClient == null)
             {
@@ -34,6 +49,19 @@ namespace MediaBrowser.Controller.Providers.Movies
             HttpClient = httpClient;
         }
 
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected override void Dispose(bool dispose)
+        {
+            if (dispose)
+            {
+                FanArtResourcePool.Dispose();
+            }
+            base.Dispose(dispose);
+        }
+        
         /// <summary>
         /// The fan art base URL
         /// </summary>
@@ -63,9 +91,9 @@ namespace MediaBrowser.Controller.Providers.Movies
             var logoExists = item.ResolveArgs.ContainsMetaFileByName(LOGO_FILE);
             var discExists = item.ResolveArgs.ContainsMetaFileByName(DISC_FILE);
 
-            return (!artExists && Kernel.Instance.Configuration.DownloadMovieArt)
-                || (!logoExists && Kernel.Instance.Configuration.DownloadMovieLogo)
-                || (!discExists && Kernel.Instance.Configuration.DownloadMovieDisc);
+            return (!artExists && ConfigurationManager.Configuration.DownloadMovieArt)
+                || (!logoExists && ConfigurationManager.Configuration.DownloadMovieLogo)
+                || (!discExists && ConfigurationManager.Configuration.DownloadMovieDisc);
         }
 
         /// <summary>
@@ -82,13 +110,13 @@ namespace MediaBrowser.Controller.Providers.Movies
             var movie = item;
             if (ShouldFetch(movie, movie.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo { ProviderId = Id })))
             {
-                var language = Kernel.Instance.Configuration.PreferredMetadataLanguage.ToLower();
+                var language = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower();
                 var url = string.Format(FanArtBaseUrl, APIKey, movie.GetProviderId(MetadataProviders.Tmdb));
                 var doc = new XmlDocument();
 
                 try
                 {
-                    using (var xml = await HttpClient.Get(url, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false))
+                    using (var xml = await HttpClient.Get(url, FanArtResourcePool, cancellationToken).ConfigureAwait(false))
                     {
                         doc.Load(xml);
                     }
@@ -102,8 +130,8 @@ namespace MediaBrowser.Controller.Providers.Movies
                 if (doc.HasChildNodes)
                 {
                     string path;
-                    var hd = Kernel.Instance.Configuration.DownloadHDFanArt ? "hd" : "";
-                    if (Kernel.Instance.Configuration.DownloadMovieLogo && !item.ResolveArgs.ContainsMetaFileByName(LOGO_FILE))
+                    var hd = ConfigurationManager.Configuration.DownloadHDFanArt ? "hd" : "";
+                    if (ConfigurationManager.Configuration.DownloadMovieLogo && !item.ResolveArgs.ContainsMetaFileByName(LOGO_FILE))
                     {
                         var node =
                             doc.SelectSingleNode("//fanart/movie/movielogos/" + hd + "movielogo[@lang = \"" + language + "\"]/@url") ??
@@ -119,7 +147,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                             Logger.Debug("FanArtProvider getting ClearLogo for " + movie.Name);
                             try
                             {
-                                movie.SetImage(ImageType.Logo, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, LOGO_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                movie.SetImage(ImageType.Logo, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, LOGO_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {
@@ -132,7 +160,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                     }
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    if (Kernel.Instance.Configuration.DownloadMovieArt && !item.ResolveArgs.ContainsMetaFileByName(ART_FILE))
+                    if (ConfigurationManager.Configuration.DownloadMovieArt && !item.ResolveArgs.ContainsMetaFileByName(ART_FILE))
                     {
                         var node =
                             doc.SelectSingleNode("//fanart/movie/moviearts/" + hd + "movieart[@lang = \"" + language + "\"]/@url") ??
@@ -145,7 +173,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                             Logger.Debug("FanArtProvider getting ClearArt for " + movie.Name);
                             try
                             {
-                                movie.SetImage(ImageType.Art, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, ART_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                movie.SetImage(ImageType.Art, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, ART_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {
@@ -158,7 +186,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                     }
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    if (Kernel.Instance.Configuration.DownloadMovieDisc && !item.ResolveArgs.ContainsMetaFileByName(DISC_FILE))
+                    if (ConfigurationManager.Configuration.DownloadMovieDisc && !item.ResolveArgs.ContainsMetaFileByName(DISC_FILE))
                     {
                         var node = doc.SelectSingleNode("//fanart/movie/moviediscs/moviedisc[@lang = \"" + language + "\"]/@url") ??
                                    doc.SelectSingleNode("//fanart/movie/moviediscs/moviedisc/@url");
@@ -168,7 +196,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                             Logger.Debug("FanArtProvider getting DiscArt for " + movie.Name);
                             try
                             {
-                                movie.SetImage(ImageType.Disc, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, DISC_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                movie.SetImage(ImageType.Disc, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, DISC_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {
@@ -182,7 +210,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    if (Kernel.Instance.Configuration.DownloadMovieBanner && !item.ResolveArgs.ContainsMetaFileByName(BANNER_FILE))
+                    if (ConfigurationManager.Configuration.DownloadMovieBanner && !item.ResolveArgs.ContainsMetaFileByName(BANNER_FILE))
                     {
                         var node = doc.SelectSingleNode("//fanart/movie/moviebanners/moviebanner[@lang = \"" + language + "\"]/@url") ??
                                    doc.SelectSingleNode("//fanart/movie/moviebanners/moviebanner/@url");
@@ -192,7 +220,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                             Logger.Debug("FanArtProvider getting Banner for " + movie.Name);
                             try
                             {
-                                movie.SetImage(ImageType.Banner, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, BANNER_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                movie.SetImage(ImageType.Banner, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, BANNER_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {
@@ -206,7 +234,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    if (Kernel.Instance.Configuration.DownloadMovieThumb && !item.ResolveArgs.ContainsMetaFileByName(THUMB_FILE))
+                    if (ConfigurationManager.Configuration.DownloadMovieThumb && !item.ResolveArgs.ContainsMetaFileByName(THUMB_FILE))
                     {
                         var node = doc.SelectSingleNode("//fanart/movie/moviethumbs/moviethumb[@lang = \"" + language + "\"]/@url") ??
                                    doc.SelectSingleNode("//fanart/movie/moviethumbs/moviethumb/@url");
@@ -216,7 +244,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                             Logger.Debug("FanArtProvider getting Banner for " + movie.Name);
                             try
                             {
-                                movie.SetImage(ImageType.Thumb, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, THUMB_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                movie.SetImage(ImageType.Thumb, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(movie, path, THUMB_FILE, FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {

+ 64 - 50
MediaBrowser.Controller/Providers/Movies/MovieDbProvider.cs

@@ -1,21 +1,22 @@
-using System.Net;
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Serialization;
 using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Net;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading;
 using System.Threading.Tasks;
-using MediaBrowser.Model.Serialization;
 
 namespace MediaBrowser.Controller.Providers.Movies
 {
@@ -31,6 +32,13 @@ namespace MediaBrowser.Controller.Providers.Movies
     /// </summary>
     public class MovieDbProvider : BaseMetadataProvider
     {
+        /// <summary>
+        /// The movie db
+        /// </summary>
+        internal readonly SemaphoreSlim MovieDbResourcePool = new SemaphoreSlim(5, 5);
+
+        internal static MovieDbProvider Current { get; private set; }
+
         /// <summary>
         /// Gets the json serializer.
         /// </summary>
@@ -46,23 +54,29 @@ namespace MediaBrowser.Controller.Providers.Movies
         /// <summary>
         /// Initializes a new instance of the <see cref="MovieDbProvider" /> class.
         /// </summary>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <param name="httpClient">The HTTP client.</param>
-        /// <param name="logManager">The Log manager</param>
-        /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
-        public MovieDbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager)
-            : base(logManager)
+        public MovieDbProvider(ILogManager logManager, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient)
+            : base(logManager, configurationManager)
         {
-            if (jsonSerializer == null)
-            {
-                throw new ArgumentNullException("jsonSerializer");
-            }
-            if (httpClient == null)
-            {
-                throw new ArgumentNullException("httpClient");
-            }
             JsonSerializer = jsonSerializer;
             HttpClient = httpClient;
+            Current = this;
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected override void Dispose(bool dispose)
+        {
+            if (dispose)
+            {
+                MovieDbResourcePool.Dispose();
+            }
+            base.Dispose(dispose);
         }
 
         /// <summary>
@@ -103,7 +117,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         {
             get
             {
-                return Kernel.Instance.Configuration.SaveLocalMeta;
+                return ConfigurationManager.Configuration.SaveLocalMeta;
             }
         }
 
@@ -141,7 +155,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         {
             try
             {
-                using (var json = await httpClient.Get(String.Format(TmdbConfigUrl, ApiKey), Kernel.Instance.ResourcePools.MovieDb, CancellationToken.None).ConfigureAwait(false))
+                using (var json = await httpClient.Get(String.Format(TmdbConfigUrl, ApiKey), MovieDbProvider.Current.MovieDbResourcePool, CancellationToken.None).ConfigureAwait(false))
                 {
                     return jsonSerializer.DeserializeFromStream<TmdbSettingsResult>(json);
                 }
@@ -200,11 +214,11 @@ namespace MediaBrowser.Controller.Providers.Movies
         {
             base.SetLastRefreshed(item, value, status);
 
-            if (Kernel.Instance.Configuration.SaveLocalMeta)
+            if (ConfigurationManager.Configuration.SaveLocalMeta)
             {
                 //in addition to ours, we need to set the last refreshed time for the local data provider
                 //so it won't see the new files we download and process them all over again
-                if (JsonProvider == null) JsonProvider = new MovieProviderFromJson(HttpClient, JsonSerializer, LogManager);
+                if (JsonProvider == null) JsonProvider = new MovieProviderFromJson(LogManager, ConfigurationManager, JsonSerializer, HttpClient);
                 var data = item.ProviderData.GetValueOrDefault(JsonProvider.Id, new BaseProviderInfo { ProviderId = JsonProvider.Id });
                 data.LastRefreshed = value;
                 item.ProviderData[JsonProvider.Id] = data;
@@ -233,7 +247,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         {
             if (item.DontFetchMeta) return false;
 
-            if (Kernel.Instance.Configuration.SaveLocalMeta && HasFileSystemStampChanged(item, providerInfo))
+            if (ConfigurationManager.Configuration.SaveLocalMeta && HasFileSystemStampChanged(item, providerInfo))
             {
                 //If they deleted something from file system, chances are, this item was mis-identified the first time
                 item.SetProviderId(MetadataProviders.Tmdb, null);
@@ -250,7 +264,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             var downloadDate = providerInfo.LastRefreshed;
 
-            if (Kernel.Instance.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
+            if (ConfigurationManager.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
             {
                 return false;
             }
@@ -258,7 +272,7 @@ namespace MediaBrowser.Controller.Providers.Movies
             if (DateTime.Today.Subtract(item.DateCreated).TotalDays > 180 && downloadDate != DateTime.MinValue)
                 return false; // don't trigger a refresh data for item that are more than 6 months old and have been refreshed before
 
-            if (DateTime.Today.Subtract(downloadDate).TotalDays < Kernel.Instance.Configuration.MetadataRefreshDays) // only refresh every n days
+            if (DateTime.Today.Subtract(downloadDate).TotalDays < ConfigurationManager.Configuration.MetadataRefreshDays) // only refresh every n days
                 return false;
 
             if (HasAltMeta(item))
@@ -266,7 +280,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
 
 
-            Logger.Debug("MovieDbProvider - " + item.Name + " needs refresh.  Download date: " + downloadDate + " item created date: " + item.DateCreated + " Check for Update age: " + Kernel.Instance.Configuration.MetadataRefreshDays);
+            Logger.Debug("MovieDbProvider - " + item.Name + " needs refresh.  Download date: " + downloadDate + " item created date: " + item.DateCreated + " Check for Update age: " + ConfigurationManager.Configuration.MetadataRefreshDays);
             return true;
         }
 
@@ -293,7 +307,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            if (!Kernel.Instance.Configuration.SaveLocalMeta || !HasLocalMeta(item) || (force && !HasLocalMeta(item)))
+            if (!ConfigurationManager.Configuration.SaveLocalMeta || !HasLocalMeta(item) || (force && !HasLocalMeta(item)))
             {
                 try
                 {
@@ -407,7 +421,7 @@ namespace MediaBrowser.Controller.Providers.Movies
             }
 
             Logger.Info("MovieDbProvider: Finding id for movie: " + name);
-            string language = Kernel.Instance.Configuration.PreferredMetadataLanguage.ToLower();
+            string language = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower();
 
             //if we are a boxset - look at our first child
             var boxset = item as BoxSet;
@@ -478,7 +492,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             try
             {
-                using (Stream json = await HttpClient.Get(url3, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (Stream json = await HttpClient.Get(url3, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     searchResult = JsonSerializer.DeserializeFromStream<TmdbMovieSearchResults>(json);
                 }
@@ -510,7 +524,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
                 try
                 {
-                    using (var json = await HttpClient.Get(url3, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                    using (var json = await HttpClient.Get(url3, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                     {
                         searchResult = JsonSerializer.DeserializeFromStream<TmdbMovieSearchResults>(json);
                     }
@@ -545,11 +559,11 @@ namespace MediaBrowser.Controller.Providers.Movies
                     if (matchedName == null)
                     {
                         //that title didn't match - look for alternatives
-                        url3 = string.Format(AltTitleSearch, id, ApiKey, Kernel.Instance.Configuration.MetadataCountryCode);
+                        url3 = string.Format(AltTitleSearch, id, ApiKey, ConfigurationManager.Configuration.MetadataCountryCode);
 
                         try
                         {
-                            using (var json = await HttpClient.Get(url3, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                            using (var json = await HttpClient.Get(url3, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                             {
                                 var response = JsonSerializer.DeserializeFromStream<TmdbAltTitleResults>(json);
 
@@ -630,7 +644,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
                 try
                 {
-                    using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                    using (Stream json = await HttpClient.Get(url, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                     {
                         var movieResult = JsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
 
@@ -703,7 +717,7 @@ namespace MediaBrowser.Controller.Providers.Movies
             }
 
             //and save locally
-            if (Kernel.Instance.Configuration.SaveLocalMeta)
+            if (ConfigurationManager.Configuration.SaveLocalMeta)
             {
                 var ms = new MemoryStream();
                 JsonSerializer.SerializeToStream(mainResult, ms);
@@ -724,14 +738,14 @@ namespace MediaBrowser.Controller.Providers.Movies
         protected async Task<CompleteMovieData> FetchMainResult(BaseItem item, string id, CancellationToken cancellationToken)
         {
             ItemType = item is BoxSet ? "collection" : "movie";
-            string url = string.Format(GetInfo3, id, ApiKey, Kernel.Instance.Configuration.PreferredMetadataLanguage, ItemType);
+            string url = string.Format(GetInfo3, id, ApiKey, ConfigurationManager.Configuration.PreferredMetadataLanguage, ItemType);
             CompleteMovieData mainResult;
 
             cancellationToken.ThrowIfCancellationRequested();
 
             try
             {
-                using (var json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (var json = await HttpClient.Get(url, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     mainResult = JsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
                 }
@@ -756,14 +770,14 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             if (mainResult != null && string.IsNullOrEmpty(mainResult.overview))
             {
-                if (Kernel.Instance.Configuration.PreferredMetadataLanguage.ToLower() != "en")
+                if (ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower() != "en")
                 {
-                    Logger.Info("MovieDbProvider couldn't find meta for language " + Kernel.Instance.Configuration.PreferredMetadataLanguage + ". Trying English...");
+                    Logger.Info("MovieDbProvider couldn't find meta for language " + ConfigurationManager.Configuration.PreferredMetadataLanguage + ". Trying English...");
                     url = string.Format(GetInfo3, id, ApiKey, "en", ItemType);
 
                     try
                     {
-                        using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                        using (Stream json = await HttpClient.Get(url, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                         {
                             mainResult = JsonSerializer.DeserializeFromStream<CompleteMovieData>(json);
                         }
@@ -799,7 +813,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             try
             {
-                using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (Stream json = await HttpClient.Get(url, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     cast = JsonSerializer.DeserializeFromStream<TmdbCastResult>(json);
                 }
@@ -826,7 +840,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             try
             {
-                using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (Stream json = await HttpClient.Get(url, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     releases = JsonSerializer.DeserializeFromStream<TmdbReleasesResult>(json);
                 }
@@ -855,7 +869,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             try
             {
-                using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (Stream json = await HttpClient.Get(url, MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     images = JsonSerializer.DeserializeFromStream<TmdbImages>(json);
                 }
@@ -883,7 +897,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                 movie.SetProviderId(MetadataProviders.Imdb, movieData.imdb_id);
                 float rating;
                 string voteAvg = movieData.vote_average.ToString();
-                string cultureStr = Kernel.Instance.Configuration.PreferredMetadataLanguage + "-" + Kernel.Instance.Configuration.MetadataCountryCode;
+                string cultureStr = ConfigurationManager.Configuration.PreferredMetadataLanguage + "-" + ConfigurationManager.Configuration.MetadataCountryCode;
                 CultureInfo culture;
                 try
                 {
@@ -900,7 +914,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                 //release date and certification are retrieved based on configured country and we fall back on US if not there
                 if (movieData.countries != null)
                 {
-                    var ourRelease = movieData.countries.FirstOrDefault(c => c.iso_3166_1.Equals(Kernel.Instance.Configuration.MetadataCountryCode, StringComparison.OrdinalIgnoreCase)) ?? new Country();
+                    var ourRelease = movieData.countries.FirstOrDefault(c => c.iso_3166_1.Equals(ConfigurationManager.Configuration.MetadataCountryCode, StringComparison.OrdinalIgnoreCase)) ?? new Country();
                     var usRelease = movieData.countries.FirstOrDefault(c => c.iso_3166_1.Equals("US", StringComparison.OrdinalIgnoreCase)) ?? new Country();
 
                     movie.OfficialRating = ourRelease.certification ?? usRelease.certification;
@@ -975,17 +989,17 @@ namespace MediaBrowser.Controller.Providers.Movies
             cancellationToken.ThrowIfCancellationRequested();
 
             //        poster
-            if (images.posters != null && images.posters.Count > 0 && (Kernel.Instance.Configuration.RefreshItemImages || !item.HasLocalImage("folder")))
+            if (images.posters != null && images.posters.Count > 0 && (ConfigurationManager.Configuration.RefreshItemImages || !item.HasLocalImage("folder")))
             {
                 var tmdbSettings = await TmdbSettings.ConfigureAwait(false);
 
-                var tmdbImageUrl = tmdbSettings.images.base_url + Kernel.Instance.Configuration.TmdbFetchedPosterSize;
+                var tmdbImageUrl = tmdbSettings.images.base_url + ConfigurationManager.Configuration.TmdbFetchedPosterSize;
                 // get highest rated poster for our language
 
                 var postersSortedByVote = images.posters.OrderByDescending(i => i.vote_average);
 
-                var poster = postersSortedByVote.FirstOrDefault(p => p.iso_639_1 != null && p.iso_639_1.Equals(Kernel.Instance.Configuration.PreferredMetadataLanguage, StringComparison.OrdinalIgnoreCase));
-                if (poster == null && !Kernel.Instance.Configuration.PreferredMetadataLanguage.Equals("en"))
+                var poster = postersSortedByVote.FirstOrDefault(p => p.iso_639_1 != null && p.iso_639_1.Equals(ConfigurationManager.Configuration.PreferredMetadataLanguage, StringComparison.OrdinalIgnoreCase));
+                if (poster == null && !ConfigurationManager.Configuration.PreferredMetadataLanguage.Equals("en"))
                 {
                     // couldn't find our specific language, find english (if that wasn't our language)
                     poster = postersSortedByVote.FirstOrDefault(p => p.iso_639_1 != null && p.iso_639_1.Equals("en", StringComparison.OrdinalIgnoreCase));
@@ -1004,7 +1018,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                 {
                     try
                     {
-                        item.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + poster.file_path, "folder" + Path.GetExtension(poster.file_path), Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false);
+                        item.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + poster.file_path, "folder" + Path.GetExtension(poster.file_path), MovieDbResourcePool, cancellationToken).ConfigureAwait(false);
                     }
                     catch (HttpException)
                     {
@@ -1025,18 +1039,18 @@ namespace MediaBrowser.Controller.Providers.Movies
 
                 var tmdbSettings = await TmdbSettings.ConfigureAwait(false);
 
-                var tmdbImageUrl = tmdbSettings.images.base_url + Kernel.Instance.Configuration.TmdbFetchedBackdropSize;
+                var tmdbImageUrl = tmdbSettings.images.base_url + ConfigurationManager.Configuration.TmdbFetchedBackdropSize;
                 //backdrops should be in order of rating.  get first n ones
-                var numToFetch = Math.Min(Kernel.Instance.Configuration.MaxBackdrops, images.backdrops.Count);
+                var numToFetch = Math.Min(ConfigurationManager.Configuration.MaxBackdrops, images.backdrops.Count);
                 for (var i = 0; i < numToFetch; i++)
                 {
                     var bdName = "backdrop" + (i == 0 ? "" : i.ToString());
 
-                    if (Kernel.Instance.Configuration.RefreshItemImages || !item.HasLocalImage(bdName))
+                    if (ConfigurationManager.Configuration.RefreshItemImages || !item.HasLocalImage(bdName))
                     {
                         try
                         {
-                            item.BackdropImagePaths.Add(await Kernel.Instance.ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + images.backdrops[i].file_path, bdName + Path.GetExtension(images.backdrops[i].file_path), Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false));
+                            item.BackdropImagePaths.Add(await Kernel.Instance.ProviderManager.DownloadAndSaveImage(item, tmdbImageUrl + images.backdrops[i].file_path, bdName + Path.GetExtension(images.backdrops[i].file_path), MovieDbResourcePool, cancellationToken).ConfigureAwait(false));
                         }
                         catch (HttpException)
                         {

+ 3 - 2
MediaBrowser.Controller/Providers/Movies/MovieProviderFromJson.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
@@ -14,8 +15,8 @@ namespace MediaBrowser.Controller.Providers.Movies
     /// </summary>
     public class MovieProviderFromJson : MovieDbProvider
     {
-        public MovieProviderFromJson(IHttpClient httpClient, IJsonSerializer jsonSerializer, ILogManager logManager)
-            : base(jsonSerializer, httpClient, logManager)
+        public MovieProviderFromJson(ILogManager logManager, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient) : 
+            base(logManager, configurationManager, jsonSerializer, httpClient)
         {
         }
 

+ 3 - 2
MediaBrowser.Controller/Providers/Movies/MovieProviderFromXml.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using System;
 using System.IO;
@@ -13,7 +14,7 @@ namespace MediaBrowser.Controller.Providers.Movies
     /// </summary>
     public class MovieProviderFromXml : BaseMetadataProvider
     {
-        public MovieProviderFromXml(ILogManager logManager) : base(logManager)
+        public MovieProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 3 - 2
MediaBrowser.Controller/Providers/Movies/PersonProviderFromJson.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;
@@ -14,8 +15,8 @@ namespace MediaBrowser.Controller.Providers.Movies
     /// </summary>
     class PersonProviderFromJson : TmdbPersonProvider
     {
-        public PersonProviderFromJson(IHttpClient httpClient, IJsonSerializer jsonSerializer, ILogManager logManager)
-            : base(httpClient, jsonSerializer, logManager)
+        public PersonProviderFromJson(IHttpClient httpClient, IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager) : 
+            base(httpClient, jsonSerializer, logManager, configurationManager)
         {
         }
 

+ 23 - 28
MediaBrowser.Controller/Providers/Movies/TmdbPersonProvider.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
@@ -25,26 +26,8 @@ namespace MediaBrowser.Controller.Providers.Movies
         /// </summary>
         protected const string MetaFileName = "MBPerson.json";
 
-        /// <summary>
-        /// Gets the json serializer.
-        /// </summary>
-        /// <value>The json serializer.</value>
-        protected IJsonSerializer JsonSerializer { get; private set; }
-
-        /// <summary>
-        /// Gets the HTTP client.
-        /// </summary>
-        /// <value>The HTTP client.</value>
-        protected IHttpClient HttpClient { get; private set; }
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="MovieDbProvider" /> class.
-        /// </summary>
-        /// <param name="httpClient">The HTTP client.</param>
-        /// <param name="jsonSerializer">The json serializer.</param>
-        /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
-        public TmdbPersonProvider(IHttpClient httpClient, IJsonSerializer jsonSerializer, ILogManager logManager)
-            : base(logManager)
+        public TmdbPersonProvider(IHttpClient httpClient, IJsonSerializer jsonSerializer, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
             if (jsonSerializer == null)
             {
@@ -58,6 +41,18 @@ namespace MediaBrowser.Controller.Providers.Movies
             JsonSerializer = jsonSerializer;
         }
 
+        /// <summary>
+        /// Gets the json serializer.
+        /// </summary>
+        /// <value>The json serializer.</value>
+        protected IJsonSerializer JsonSerializer { get; private set; }
+
+        /// <summary>
+        /// Gets the HTTP client.
+        /// </summary>
+        /// <value>The HTTP client.</value>
+        protected IHttpClient HttpClient { get; private set; }
+
         /// <summary>
         /// Supportses the specified item.
         /// </summary>
@@ -78,7 +73,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         {
             //we fetch if either info or image needed and haven't already tried recently
             return (string.IsNullOrEmpty(item.PrimaryImagePath) || !item.ResolveArgs.ContainsMetaFileByName(MetaFileName))
-                && DateTime.Today.Subtract(providerInfo.LastRefreshed).TotalDays > Kernel.Instance.Configuration.MetadataRefreshDays;
+                && DateTime.Today.Subtract(providerInfo.LastRefreshed).TotalDays > ConfigurationManager.Configuration.MetadataRefreshDays;
         }
 
         /// <summary>
@@ -165,7 +160,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             try
             {
-                using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (Stream json = await HttpClient.Get(url, MovieDbProvider.Current.MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     searchResult = JsonSerializer.DeserializeFromStream<PersonSearchResults>(json);
                 }
@@ -191,7 +186,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             try
             {
-                using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (Stream json = await HttpClient.Get(url, MovieDbProvider.Current.MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     if (json != null)
                     {
@@ -254,7 +249,7 @@ namespace MediaBrowser.Controller.Providers.Movies
 
             try
             {
-                using (Stream json = await HttpClient.Get(url, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (Stream json = await HttpClient.Get(url, MovieDbProvider.Current.MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     if (json != null)
                     {
@@ -273,7 +268,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                     searchResult.Profiles.FirstOrDefault(
                         p =>
                         !string.IsNullOrEmpty(p.Iso_639_1) &&
-                        p.Iso_639_1.Equals(Kernel.Instance.Configuration.PreferredMetadataLanguage,
+                        p.Iso_639_1.Equals(ConfigurationManager.Configuration.PreferredMetadataLanguage,
                                           StringComparison.OrdinalIgnoreCase));
                 if (profile == null)
                 {
@@ -282,7 +277,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                         searchResult.Profiles.FirstOrDefault(
                             p =>
                                 !string.IsNullOrEmpty(p.Iso_639_1) &&
-                            p.Iso_639_1.Equals(Kernel.Instance.Configuration.PreferredMetadataLanguage,
+                            p.Iso_639_1.Equals(ConfigurationManager.Configuration.PreferredMetadataLanguage,
                                               StringComparison.OrdinalIgnoreCase));
 
                 }
@@ -295,7 +290,7 @@ namespace MediaBrowser.Controller.Providers.Movies
                 {
                     var tmdbSettings = await Kernel.Instance.MetadataProviders.OfType<MovieDbProvider>().First().TmdbSettings.ConfigureAwait(false);
 
-                    var img = await DownloadAndSaveImage(person, tmdbSettings.images.base_url + Kernel.Instance.Configuration.TmdbFetchedProfileSize + profile.File_Path,
+                    var img = await DownloadAndSaveImage(person, tmdbSettings.images.base_url + ConfigurationManager.Configuration.TmdbFetchedProfileSize + profile.File_Path,
                                              "folder" + Path.GetExtension(profile.File_Path), cancellationToken).ConfigureAwait(false);
 
                     if (!string.IsNullOrEmpty(img))
@@ -322,7 +317,7 @@ namespace MediaBrowser.Controller.Providers.Movies
             var localPath = Path.Combine(item.MetaLocation, targetName);
             if (!item.ResolveArgs.ContainsMetaFileByName(targetName))
             {
-                using (var sourceStream = await HttpClient.GetMemoryStream(source, Kernel.Instance.ResourcePools.MovieDb, cancellationToken).ConfigureAwait(false))
+                using (var sourceStream = await HttpClient.GetMemoryStream(source, MovieDbProvider.Current.MovieDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     await Kernel.Instance.FileSystemManager.SaveToLibraryFilesystem(item, localPath, sourceStream, cancellationToken).ConfigureAwait(false);
 

+ 28 - 26
MediaBrowser.Controller/Providers/Music/LastfmBaseProvider.cs

@@ -1,5 +1,6 @@
 using System.Net;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
@@ -23,32 +24,16 @@ namespace MediaBrowser.Controller.Providers.Music
     /// </summary>
     public abstract class LastfmBaseProvider : BaseMetadataProvider
     {
-        /// <summary>
-        /// Gets the json serializer.
-        /// </summary>
-        /// <value>The json serializer.</value>
-        protected IJsonSerializer JsonSerializer { get; private set; }
-
-        /// <summary>
-        /// Gets the HTTP client.
-        /// </summary>
-        /// <value>The HTTP client.</value>
-        protected IHttpClient HttpClient { get; private set; }
-
-        /// <summary>
-        /// The name of the local json meta file for this item type
-        /// </summary>
-        protected string LocalMetaFileName { get; set; }
-
         /// <summary>
         /// Initializes a new instance of the <see cref="LastfmBaseProvider" /> class.
         /// </summary>
         /// <param name="jsonSerializer">The json serializer.</param>
         /// <param name="httpClient">The HTTP client.</param>
-        /// <param name="logManager">The Log manager</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
         /// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
-        public LastfmBaseProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager)
-            : base(logManager)
+        protected LastfmBaseProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
             if (jsonSerializer == null)
             {
@@ -62,6 +47,23 @@ namespace MediaBrowser.Controller.Providers.Music
             HttpClient = httpClient;
         }
 
+        /// <summary>
+        /// Gets the json serializer.
+        /// </summary>
+        /// <value>The json serializer.</value>
+        protected IJsonSerializer JsonSerializer { get; private set; }
+
+        /// <summary>
+        /// Gets the HTTP client.
+        /// </summary>
+        /// <value>The HTTP client.</value>
+        protected IHttpClient HttpClient { get; private set; }
+
+        /// <summary>
+        /// The name of the local json meta file for this item type
+        /// </summary>
+        protected string LocalMetaFileName { get; set; }
+
         /// <summary>
         /// Gets the priority.
         /// </summary>
@@ -90,7 +92,7 @@ namespace MediaBrowser.Controller.Providers.Music
         {
             get
             {
-                return Kernel.Instance.Configuration.SaveLocalMeta;
+                return ConfigurationManager.Configuration.SaveLocalMeta;
             }
         }
 
@@ -101,7 +103,7 @@ namespace MediaBrowser.Controller.Providers.Music
         {
             if (item.DontFetchMeta) return false;
 
-            if (Kernel.Instance.Configuration.SaveLocalMeta && HasFileSystemStampChanged(item, providerInfo))
+            if (ConfigurationManager.Configuration.SaveLocalMeta && HasFileSystemStampChanged(item, providerInfo))
             {
                 //If they deleted something from file system, chances are, this item was mis-identified the first time
                 item.SetProviderId(MetadataProviders.Musicbrainz, null);
@@ -118,7 +120,7 @@ namespace MediaBrowser.Controller.Providers.Music
 
             var downloadDate = providerInfo.LastRefreshed;
 
-            if (Kernel.Instance.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
+            if (ConfigurationManager.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
             {
                 return false;
             }
@@ -126,11 +128,11 @@ namespace MediaBrowser.Controller.Providers.Music
             if (DateTime.Today.Subtract(item.DateCreated).TotalDays > 180 && downloadDate != DateTime.MinValue)
                 return false; // don't trigger a refresh data for item that are more than 6 months old and have been refreshed before
 
-            if (DateTime.Today.Subtract(downloadDate).TotalDays < Kernel.Instance.Configuration.MetadataRefreshDays) // only refresh every n days
+            if (DateTime.Today.Subtract(downloadDate).TotalDays < ConfigurationManager.Configuration.MetadataRefreshDays) // only refresh every n days
                 return false;
 
 
-            Logger.Debug("LastfmProvider - " + item.Name + " needs refresh.  Download date: " + downloadDate + " item created date: " + item.DateCreated + " Check for Update age: " + Kernel.Instance.Configuration.MetadataRefreshDays);
+            Logger.Debug("LastfmProvider - " + item.Name + " needs refresh.  Download date: " + downloadDate + " item created date: " + item.DateCreated + " Check for Update age: " + ConfigurationManager.Configuration.MetadataRefreshDays);
             return true;
         }
 
@@ -151,7 +153,7 @@ namespace MediaBrowser.Controller.Providers.Music
 
             cancellationToken.ThrowIfCancellationRequested();
 
-            if (!Kernel.Instance.Configuration.SaveLocalMeta || !HasLocalMeta(item) || (force && !HasLocalMeta(item)))
+            if (!ConfigurationManager.Configuration.SaveLocalMeta || !HasLocalMeta(item) || (force && !HasLocalMeta(item)))
             {
                 try
                 {

+ 30 - 9
MediaBrowser.Controller/Providers/ProviderManager.cs

@@ -1,6 +1,8 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Logging;
 using System;
@@ -39,18 +41,37 @@ namespace MediaBrowser.Controller.Providers
         /// </summary>
         private readonly IHttpClient _httpClient;
 
+        private IServerConfigurationManager ConfigurationManager { get; set; }
+        
         /// <summary>
         /// Initializes a new instance of the <see cref="ProviderManager" /> class.
         /// </summary>
         /// <param name="kernel">The kernel.</param>
         /// <param name="httpClient">The HTTP client.</param>
         /// <param name="logger">The logger.</param>
-        public ProviderManager(Kernel kernel, IHttpClient httpClient, ILogger logger)
+        public ProviderManager(Kernel kernel, IHttpClient httpClient, ILogger logger, IServerConfigurationManager configurationManager)
             : base(kernel)
         {
             _logger = logger;
             _httpClient = httpClient;
+            ConfigurationManager = configurationManager;
             _remoteImageCache = new FileSystemRepository(ImagesDataPath);
+
+            configurationManager.ConfigurationUpdated += configurationManager_ConfigurationUpdated;
+        }
+
+        /// <summary>
+        /// Handles the ConfigurationUpdated event of the configurationManager control.
+        /// </summary>
+        /// <param name="sender">The source of the event.</param>
+        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
+        void configurationManager_ConfigurationUpdated(object sender, EventArgs e)
+        {
+            // Validate currently executing providers, in the background
+            Task.Run(() =>
+            {
+                ValidateCurrentlyRunningProviders();
+            });
         }
 
         /// <summary>
@@ -67,7 +88,7 @@ namespace MediaBrowser.Controller.Providers
             {
                 if (_imagesDataPath == null)
                 {
-                    _imagesDataPath = Path.Combine(Kernel.ApplicationPaths.DataPath, "remote-images");
+                    _imagesDataPath = Path.Combine(ConfigurationManager.ApplicationPaths.DataPath, "remote-images");
 
                     if (!Directory.Exists(_imagesDataPath))
                     {
@@ -145,7 +166,7 @@ namespace MediaBrowser.Controller.Providers
                 cancellationToken.ThrowIfCancellationRequested();
 
                 // Skip if internet providers are currently disabled
-                if (provider.RequiresInternet && !Kernel.Configuration.EnableInternetProviders)
+                if (provider.RequiresInternet && !ConfigurationManager.Configuration.EnableInternetProviders)
                 {
                     continue;
                 }
@@ -157,7 +178,7 @@ namespace MediaBrowser.Controller.Providers
                 }
 
                 // Skip if internet provider and this type is not allowed
-                if (provider.RequiresInternet && Kernel.Configuration.EnableInternetProviders && Kernel.Configuration.InternetProviderExcludeTypes.Contains(item.GetType().Name, StringComparer.OrdinalIgnoreCase))
+                if (provider.RequiresInternet && ConfigurationManager.Configuration.EnableInternetProviders && ConfigurationManager.Configuration.InternetProviderExcludeTypes.Contains(item.GetType().Name, StringComparer.OrdinalIgnoreCase))
                 {
                     continue;
                 }
@@ -249,8 +270,8 @@ namespace MediaBrowser.Controller.Providers
         {
             _logger.Info("Validing currently running providers");
 
-            var enableInternetProviders = Kernel.Configuration.EnableInternetProviders;
-            var internetProviderExcludeTypes = Kernel.Configuration.InternetProviderExcludeTypes;
+            var enableInternetProviders = ConfigurationManager.Configuration.EnableInternetProviders;
+            var internetProviderExcludeTypes = ConfigurationManager.Configuration.InternetProviderExcludeTypes;
 
             foreach (var tuple in _currentlyRunningProviders.Values
                 .Where(p => p.Item1.RequiresInternet && (!enableInternetProviders || internetProviderExcludeTypes.Contains(p.Item2.GetType().Name, StringComparer.OrdinalIgnoreCase)))
@@ -290,13 +311,13 @@ namespace MediaBrowser.Controller.Providers
             }
 
             //download and save locally
-            var localPath = Kernel.Configuration.SaveLocalMeta ?
+            var localPath = ConfigurationManager.Configuration.SaveLocalMeta ?
                 Path.Combine(item.MetaLocation, targetName) :
                 _remoteImageCache.GetResourcePath(item.GetType().FullName + item.Path.ToLower(), targetName);
 
             var img = await _httpClient.GetMemoryStream(source, resourcePool, cancellationToken).ConfigureAwait(false);
 
-            if (Kernel.Configuration.SaveLocalMeta) // queue to media directories
+            if (ConfigurationManager.Configuration.SaveLocalMeta) // queue to media directories
             {
                 await Kernel.FileSystemManager.SaveToLibraryFilesystem(item, localPath, img, cancellationToken).ConfigureAwait(false);
             }

+ 9 - 7
MediaBrowser.Controller/Providers/SortNameProvider.cs

@@ -1,10 +1,11 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Model.Logging;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
-using MediaBrowser.Model.Logging;
 
 namespace MediaBrowser.Controller.Providers
 {
@@ -13,7 +14,8 @@ namespace MediaBrowser.Controller.Providers
     /// </summary>
     public class SortNameProvider : BaseMetadataProvider
     {
-        public SortNameProvider(ILogManager logManager) : base(logManager)
+        public SortNameProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
         }
 
@@ -99,14 +101,14 @@ namespace MediaBrowser.Controller.Providers
                 if (item.Name == null) return false; //some items may not have name filled in properly
 
                 var sortable = item.Name.Trim().ToLower();
-                sortable = Kernel.Instance.Configuration.SortRemoveCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), string.Empty));
+                sortable = ConfigurationManager.Configuration.SortRemoveCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), string.Empty));
 
-                sortable = Kernel.Instance.Configuration.SortReplaceCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), " "));
+                sortable = ConfigurationManager.Configuration.SortReplaceCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), " "));
 
-                foreach (var search in Kernel.Instance.Configuration.SortRemoveWords)
+                foreach (var search in ConfigurationManager.Configuration.SortRemoveWords)
                 {
                     cancellationToken.ThrowIfCancellationRequested();
-
+                    
                     var searchLower = search.ToLower();
                     // Remove from beginning if a space follows
                     if (sortable.StartsWith(searchLower + " "))

+ 3 - 2
MediaBrowser.Controller/Providers/TV/EpisodeImageFromMediaLocationProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Model.Entities;
 using System;
@@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.Providers.TV
     /// </summary>
     public class EpisodeImageFromMediaLocationProvider : BaseMetadataProvider
     {
-        public EpisodeImageFromMediaLocationProvider(ILogManager logManager) : base(logManager)
+        public EpisodeImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 3 - 2
MediaBrowser.Controller/Providers/TV/EpisodeProviderFromXml.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Model.Entities;
 using System;
@@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.Providers.TV
     /// </summary>
     public class EpisodeProviderFromXml : BaseMetadataProvider
     {
-        public EpisodeProviderFromXml(ILogManager logManager) : base(logManager)
+        public EpisodeProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 15 - 13
MediaBrowser.Controller/Providers/TV/FanArtTVProvider.cs

@@ -1,7 +1,9 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers.Movies;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Net;
@@ -23,8 +25,8 @@ namespace MediaBrowser.Controller.Providers.TV
         /// <value>The HTTP client.</value>
         protected IHttpClient HttpClient { get; private set; }
 
-        public FanArtTvProvider(IHttpClient httpClient, ILogManager logManager)
-            : base(logManager)
+        public FanArtTvProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
             if (httpClient == null)
             {
@@ -46,9 +48,9 @@ namespace MediaBrowser.Controller.Providers.TV
             var thumbExists = item.ResolveArgs.ContainsMetaFileByName(THUMB_FILE);
 
 
-            return (!artExists && Kernel.Instance.Configuration.DownloadTVArt)
-                || (!logoExists && Kernel.Instance.Configuration.DownloadTVLogo)
-                || (!thumbExists && Kernel.Instance.Configuration.DownloadTVThumb);
+            return (!artExists && ConfigurationManager.Configuration.DownloadTVArt)
+                || (!logoExists && ConfigurationManager.Configuration.DownloadTVLogo)
+                || (!thumbExists && ConfigurationManager.Configuration.DownloadTVThumb);
         }
 
         protected override async Task<bool> FetchAsyncInternal(BaseItem item, bool force, CancellationToken cancellationToken)
@@ -58,13 +60,13 @@ namespace MediaBrowser.Controller.Providers.TV
             var series = (Series)item;
             if (ShouldFetch(series, series.ProviderData.GetValueOrDefault(Id, new BaseProviderInfo { ProviderId = Id })))
             {
-                string language = Kernel.Instance.Configuration.PreferredMetadataLanguage.ToLower();
+                string language = ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower();
                 string url = string.Format(FanArtBaseUrl, APIKey, series.GetProviderId(MetadataProviders.Tvdb));
                 var doc = new XmlDocument();
 
                 try
                 {
-                    using (var xml = await HttpClient.Get(url, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false))
+                    using (var xml = await HttpClient.Get(url, FanArtMovieProvider.Current.FanArtResourcePool, cancellationToken).ConfigureAwait(false))
                     {
                         doc.Load(xml);
                     }
@@ -78,7 +80,7 @@ namespace MediaBrowser.Controller.Providers.TV
                 if (doc.HasChildNodes)
                 {
                     string path;
-                    if (Kernel.Instance.Configuration.DownloadTVLogo && !series.ResolveArgs.ContainsMetaFileByName(LOGO_FILE))
+                    if (ConfigurationManager.Configuration.DownloadTVLogo && !series.ResolveArgs.ContainsMetaFileByName(LOGO_FILE))
                     {
                         var node = doc.SelectSingleNode("//fanart/series/clearlogos/clearlogo[@lang = \"" + language + "\"]/@url") ??
                                    doc.SelectSingleNode("//fanart/series/clearlogos/clearlogo/@url");
@@ -88,7 +90,7 @@ namespace MediaBrowser.Controller.Providers.TV
                             Logger.Debug("FanArtProvider getting ClearLogo for " + series.Name);
                             try
                             {
-                                series.SetImage(ImageType.Logo, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, path, LOGO_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                series.SetImage(ImageType.Logo, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, path, LOGO_FILE, FanArtMovieProvider.Current.FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {
@@ -102,7 +104,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    if (Kernel.Instance.Configuration.DownloadTVArt && !series.ResolveArgs.ContainsMetaFileByName(ART_FILE))
+                    if (ConfigurationManager.Configuration.DownloadTVArt && !series.ResolveArgs.ContainsMetaFileByName(ART_FILE))
                     {
                         var node = doc.SelectSingleNode("//fanart/series/cleararts/clearart[@lang = \"" + language + "\"]/@url") ??
                                    doc.SelectSingleNode("//fanart/series/cleararts/clearart/@url");
@@ -112,7 +114,7 @@ namespace MediaBrowser.Controller.Providers.TV
                             Logger.Debug("FanArtProvider getting ClearArt for " + series.Name);
                             try
                             {
-                                series.SetImage(ImageType.Art, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, path, ART_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                series.SetImage(ImageType.Art, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, path, ART_FILE, FanArtMovieProvider.Current.FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {
@@ -126,7 +128,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
                     cancellationToken.ThrowIfCancellationRequested();
 
-                    if (Kernel.Instance.Configuration.DownloadTVThumb && !series.ResolveArgs.ContainsMetaFileByName(THUMB_FILE))
+                    if (ConfigurationManager.Configuration.DownloadTVThumb && !series.ResolveArgs.ContainsMetaFileByName(THUMB_FILE))
                     {
                         var node = doc.SelectSingleNode("//fanart/series/tvthumbs/tvthumb[@lang = \"" + language + "\"]/@url") ??
                                    doc.SelectSingleNode("//fanart/series/tvthumbs/tvthumb/@url");
@@ -136,7 +138,7 @@ namespace MediaBrowser.Controller.Providers.TV
                             Logger.Debug("FanArtProvider getting ThumbArt for " + series.Name);
                             try
                             {
-                                series.SetImage(ImageType.Disc, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, path, THUMB_FILE, Kernel.Instance.ResourcePools.FanArt, cancellationToken).ConfigureAwait(false));
+                                series.SetImage(ImageType.Disc, await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, path, THUMB_FILE, FanArtMovieProvider.Current.FanArtResourcePool, cancellationToken).ConfigureAwait(false));
                             }
                             catch (HttpException)
                             {

+ 18 - 15
MediaBrowser.Controller/Providers/TV/RemoteEpisodeProvider.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Extensions;
@@ -27,13 +28,15 @@ namespace MediaBrowser.Controller.Providers.TV
         /// <value>The HTTP client.</value>
         protected IHttpClient HttpClient { get; private set; }
 
-        public RemoteEpisodeProvider(IHttpClient httpClient, ILogManager logManager)
-            : base(logManager)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RemoteEpisodeProvider" /> class.
+        /// </summary>
+        /// <param name="httpClient">The HTTP client.</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
+        public RemoteEpisodeProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
-            if (httpClient == null)
-            {
-                throw new ArgumentNullException("httpClient");
-            }
             HttpClient = httpClient;
         }
 
@@ -94,15 +97,15 @@ namespace MediaBrowser.Controller.Providers.TV
             var episode = (Episode)item;
             var downloadDate = providerInfo.LastRefreshed;
 
-            if (Kernel.Instance.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
+            if (ConfigurationManager.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
             {
                 return false;
             }
 
             if (!item.DontFetchMeta && !HasLocalMeta(episode))
             {
-                fetch = Kernel.Instance.Configuration.MetadataRefreshDays != -1 &&
-                    DateTime.Today.Subtract(downloadDate).TotalDays > Kernel.Instance.Configuration.MetadataRefreshDays;
+                fetch = ConfigurationManager.Configuration.MetadataRefreshDays != -1 &&
+                    DateTime.Today.Subtract(downloadDate).TotalDays > ConfigurationManager.Configuration.MetadataRefreshDays;
             }
 
             return fetch;
@@ -183,12 +186,12 @@ namespace MediaBrowser.Controller.Providers.TV
                     seasonNumber = "0"; // Specials
                 }
 
-                var url = string.Format(episodeQuery, TVUtils.TVDBApiKey, seriesId, seasonNumber, episodeNumber, Kernel.Instance.Configuration.PreferredMetadataLanguage);
+                var url = string.Format(episodeQuery, TVUtils.TVDBApiKey, seriesId, seasonNumber, episodeNumber, ConfigurationManager.Configuration.PreferredMetadataLanguage);
                 var doc = new XmlDocument();
 
                 try
                 {
-                    using (var result = await HttpClient.Get(url, Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false))
+                    using (var result = await HttpClient.Get(url, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                     {
                         doc.Load(result);
                     }
@@ -202,11 +205,11 @@ namespace MediaBrowser.Controller.Providers.TV
                 //this is basicly just for anime.
                 if (!doc.HasChildNodes && Int32.Parse(seasonNumber) == 1)
                 {
-                    url = string.Format(absEpisodeQuery, TVUtils.TVDBApiKey, seriesId, episodeNumber, Kernel.Instance.Configuration.PreferredMetadataLanguage);
+                    url = string.Format(absEpisodeQuery, TVUtils.TVDBApiKey, seriesId, episodeNumber, ConfigurationManager.Configuration.PreferredMetadataLanguage);
 
                     try
                     {
-                        using (var result = await HttpClient.Get(url, Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false))
+                        using (var result = await HttpClient.Get(url, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                         {
                             if (result != null) doc.Load(result);
                             usingAbsoluteData = true;
@@ -226,7 +229,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
                         try
                         {
-                            episode.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(episode, TVUtils.BannerUrl + p, Path.GetFileName(p), Kernel.Instance.ResourcePools.TvDb, cancellationToken);
+                            episode.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(episode, TVUtils.BannerUrl + p, Path.GetFileName(p), RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken);
                         }
                         catch (HttpException)
                         {
@@ -273,7 +276,7 @@ namespace MediaBrowser.Controller.Providers.TV
                         episode.AddPeople(writers.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(str => new PersonInfo { Type = "Writer", Name = str }));
                     }
 
-                    if (Kernel.Instance.Configuration.SaveLocalMeta)
+                    if (ConfigurationManager.Configuration.SaveLocalMeta)
                     {
                         if (!Directory.Exists(episode.MetaLocation)) Directory.CreateDirectory(episode.MetaLocation);
                         var ms = new MemoryStream();

+ 16 - 15
MediaBrowser.Controller/Providers/TV/RemoteSeasonProvider.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
@@ -24,9 +25,9 @@ namespace MediaBrowser.Controller.Providers.TV
         /// </summary>
         /// <value>The HTTP client.</value>
         protected IHttpClient HttpClient { get; private set; }
-
-        public RemoteSeasonProvider(IHttpClient httpClient, ILogManager logManager)
-            : base(logManager)
+        
+        public RemoteSeasonProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
             if (httpClient == null)
             {
@@ -77,13 +78,13 @@ namespace MediaBrowser.Controller.Providers.TV
             bool fetch = false;
             var downloadDate = providerInfo.LastRefreshed;
 
-            if (Kernel.Instance.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
+            if (ConfigurationManager.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
                 return false;
 
             if (!HasLocalMeta(item))
             {
-                fetch = Kernel.Instance.Configuration.MetadataRefreshDays != -1 &&
-                    DateTime.UtcNow.Subtract(downloadDate).TotalDays > Kernel.Instance.Configuration.MetadataRefreshDays;
+                fetch = ConfigurationManager.Configuration.MetadataRefreshDays != -1 &&
+                    DateTime.UtcNow.Subtract(downloadDate).TotalDays > ConfigurationManager.Configuration.MetadataRefreshDays;
             }
 
             return fetch;
@@ -152,7 +153,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
                     try
                     {
-                        using (var imgs = await HttpClient.Get(url, Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false))
+                        using (var imgs = await HttpClient.Get(url, RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                         {
                             images.Load(imgs);
                         }
@@ -163,7 +164,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
                     if (images.HasChildNodes)
                     {
-                        if (Kernel.Instance.Configuration.RefreshItemImages || !season.HasLocalImage("folder"))
+                        if (ConfigurationManager.Configuration.RefreshItemImages || !season.HasLocalImage("folder"))
                         {
                             var n = images.SelectSingleNode("//Banner[BannerType='season'][BannerType2='season'][Season='" + seasonNumber + "']");
                             if (n != null)
@@ -173,7 +174,7 @@ namespace MediaBrowser.Controller.Providers.TV
                                 try
                                 {
                                     if (n != null)
-                                        season.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false);
+                                        season.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false);
                                 }
                                 catch (HttpException)
                                 {
@@ -185,7 +186,7 @@ namespace MediaBrowser.Controller.Providers.TV
                             }
                         }
 
-                        if (Kernel.Instance.Configuration.DownloadTVSeasonBanner && (Kernel.Instance.Configuration.RefreshItemImages || !season.HasLocalImage("banner")))
+                        if (ConfigurationManager.Configuration.DownloadTVSeasonBanner && (ConfigurationManager.Configuration.RefreshItemImages || !season.HasLocalImage("banner")))
                         {
                             var n = images.SelectSingleNode("//Banner[BannerType='season'][BannerType2='seasonwide'][Season='" + seasonNumber + "']");
                             if (n != null)
@@ -201,7 +202,7 @@ namespace MediaBrowser.Controller.Providers.TV
                                                                                              TVUtils.BannerUrl + n.InnerText,
                                                                                              "banner" +
                                                                                              Path.GetExtension(n.InnerText),
-                                                                                             Kernel.Instance.ResourcePools.TvDb, cancellationToken).
+                                                                                             RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).
                                                                ConfigureAwait(false);
 
                                         season.SetImage(ImageType.Banner, bannerImagePath);
@@ -217,7 +218,7 @@ namespace MediaBrowser.Controller.Providers.TV
                             }
                         }
 
-                        if (Kernel.Instance.Configuration.DownloadTVSeasonBackdrops && (Kernel.Instance.Configuration.RefreshItemImages || !season.HasLocalImage("backdrop")))
+                        if (ConfigurationManager.Configuration.DownloadTVSeasonBackdrops && (ConfigurationManager.Configuration.RefreshItemImages || !season.HasLocalImage("backdrop")))
                         {
                             var n = images.SelectSingleNode("//Banner[BannerType='fanart'][Season='" + seasonNumber + "']");
                             if (n != null)
@@ -228,7 +229,7 @@ namespace MediaBrowser.Controller.Providers.TV
                                     try
                                     {
                                         if (season.BackdropImagePaths == null) season.BackdropImagePaths = new List<string>();
-                                        season.BackdropImagePaths.Add(await Kernel.Instance.ProviderManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "backdrop" + Path.GetExtension(n.InnerText), Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false));
+                                        season.BackdropImagePaths.Add(await Kernel.Instance.ProviderManager.DownloadAndSaveImage(season, TVUtils.BannerUrl + n.InnerText, "backdrop" + Path.GetExtension(n.InnerText), RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken).ConfigureAwait(false));
                                     }
                                     catch (HttpException)
                                     {
@@ -239,7 +240,7 @@ namespace MediaBrowser.Controller.Providers.TV
                                     }
                                 }
                             }
-                            else if (!Kernel.Instance.Configuration.SaveLocalMeta) //if saving local - season will inherit from series
+                            else if (!ConfigurationManager.Configuration.SaveLocalMeta) //if saving local - season will inherit from series
                             {
                                 // not necessarily accurate but will give a different bit of art to each season
                                 var lst = images.SelectNodes("//Banner[BannerType='fanart']");
@@ -263,7 +264,7 @@ namespace MediaBrowser.Controller.Providers.TV
                                                                                                  "backdrop" +
                                                                                                  Path.GetExtension(
                                                                                                      n.InnerText),
-                                                                                                 Kernel.Instance.ResourcePools.TvDb, cancellationToken)
+                                                                                                 RemoteSeriesProvider.Current.TvDbResourcePool, cancellationToken)
                                                                   .ConfigureAwait(false));
                                         }
                                         catch (HttpException)

+ 49 - 20
MediaBrowser.Controller/Providers/TV/RemoteSeriesProvider.cs

@@ -1,5 +1,6 @@
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Extensions;
@@ -23,20 +24,48 @@ namespace MediaBrowser.Controller.Providers.TV
     /// </summary>
     class RemoteSeriesProvider : BaseMetadataProvider
     {
+        /// <summary>
+        /// The tv db
+        /// </summary>
+        internal readonly SemaphoreSlim TvDbResourcePool = new SemaphoreSlim(5, 5);
+
+        internal static RemoteSeriesProvider Current { get; private set; }
+
         /// <summary>
         /// Gets the HTTP client.
         /// </summary>
         /// <value>The HTTP client.</value>
         protected IHttpClient HttpClient { get; private set; }
 
-        public RemoteSeriesProvider(IHttpClient httpClient, ILogManager logManager)
-            : base(logManager)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RemoteSeriesProvider" /> class.
+        /// </summary>
+        /// <param name="httpClient">The HTTP client.</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="configurationManager">The configuration manager.</param>
+        /// <exception cref="System.ArgumentNullException">httpClient</exception>
+        public RemoteSeriesProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
             if (httpClient == null)
             {
                 throw new ArgumentNullException("httpClient");
             }
             HttpClient = httpClient;
+            Current = this;
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected override void Dispose(bool dispose)
+        {
+            if (dispose)
+            {
+                TvDbResourcePool.Dispose();
+            }
+            base.Dispose(dispose);
         }
 
         /// <summary>
@@ -102,15 +131,15 @@ namespace MediaBrowser.Controller.Providers.TV
         {
             var downloadDate = providerInfo.LastRefreshed;
 
-            if (Kernel.Instance.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
+            if (ConfigurationManager.Configuration.MetadataRefreshDays == -1 && downloadDate != DateTime.MinValue)
             {
                 return false;
             }
 
             if (item.DontFetchMeta) return false;
 
-            return !HasLocalMeta(item) && (Kernel.Instance.Configuration.MetadataRefreshDays != -1 &&
-                                       DateTime.UtcNow.Subtract(downloadDate).TotalDays > Kernel.Instance.Configuration.MetadataRefreshDays);
+            return !HasLocalMeta(item) && (ConfigurationManager.Configuration.MetadataRefreshDays != -1 &&
+                                       DateTime.UtcNow.Subtract(downloadDate).TotalDays > ConfigurationManager.Configuration.MetadataRefreshDays);
         }
 
         /// <summary>
@@ -165,12 +194,12 @@ namespace MediaBrowser.Controller.Providers.TV
             if (!string.IsNullOrEmpty(seriesId))
             {
 
-                string url = string.Format(seriesGet, TVUtils.TVDBApiKey, seriesId, Kernel.Instance.Configuration.PreferredMetadataLanguage);
+                string url = string.Format(seriesGet, TVUtils.TVDBApiKey, seriesId, ConfigurationManager.Configuration.PreferredMetadataLanguage);
                 var doc = new XmlDocument();
 
                 try
                 {
-                    using (var xml = await HttpClient.Get(url, Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false))
+                    using (var xml = await HttpClient.Get(url, TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                     {
                         doc.Load(xml);
                     }
@@ -219,7 +248,7 @@ namespace MediaBrowser.Controller.Providers.TV
                     //wait for other tasks
                     await Task.WhenAll(actorTask, imageTask).ConfigureAwait(false);
 
-                    if (Kernel.Instance.Configuration.SaveLocalMeta)
+                    if (ConfigurationManager.Configuration.SaveLocalMeta)
                     {
                         var ms = new MemoryStream();
                         doc.Save(ms);
@@ -249,7 +278,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
             try
             {
-                using (var actors = await HttpClient.Get(urlActors, Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false))
+                using (var actors = await HttpClient.Get(urlActors, TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     docActors.Load(actors);
                 }
@@ -261,7 +290,7 @@ namespace MediaBrowser.Controller.Providers.TV
             if (docActors.HasChildNodes)
             {
                 XmlNode actorsNode = null;
-                if (Kernel.Instance.Configuration.SaveLocalMeta)
+                if (ConfigurationManager.Configuration.SaveLocalMeta)
                 {
                     //add to the main doc for saving
                     var seriesNode = doc.SelectSingleNode("//Series");
@@ -282,7 +311,7 @@ namespace MediaBrowser.Controller.Providers.TV
                         {
                             series.AddPerson(new PersonInfo { Type = PersonType.Actor, Name = actorName, Role = actorRole });
 
-                            if (Kernel.Instance.Configuration.SaveLocalMeta && actorsNode != null)
+                            if (ConfigurationManager.Configuration.SaveLocalMeta && actorsNode != null)
                             {
                                 //create in main doc
                                 var personNode = doc.CreateNode(XmlNodeType.Element, "Person", null);
@@ -316,7 +345,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
                 try
                 {
-                    using (var imgs = await HttpClient.Get(url, Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false))
+                    using (var imgs = await HttpClient.Get(url, TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                     {
                         images.Load(imgs);
                     }
@@ -327,7 +356,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
                 if (images.HasChildNodes)
                 {
-                    if (Kernel.Instance.Configuration.RefreshItemImages || !series.HasLocalImage("folder"))
+                    if (ConfigurationManager.Configuration.RefreshItemImages || !series.HasLocalImage("folder"))
                     {
                         var n = images.SelectSingleNode("//Banner[BannerType='poster']");
                         if (n != null)
@@ -337,7 +366,7 @@ namespace MediaBrowser.Controller.Providers.TV
                             {
                                 try
                                 {
-                                    series.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false);
+                                    series.PrimaryImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "folder" + Path.GetExtension(n.InnerText), TvDbResourcePool, cancellationToken).ConfigureAwait(false);
                                 }
                                 catch (HttpException)
                                 {
@@ -350,7 +379,7 @@ namespace MediaBrowser.Controller.Providers.TV
                         }
                     }
 
-                    if (Kernel.Instance.Configuration.DownloadTVBanner && (Kernel.Instance.Configuration.RefreshItemImages || !series.HasLocalImage("banner")))
+                    if (ConfigurationManager.Configuration.DownloadTVBanner && (ConfigurationManager.Configuration.RefreshItemImages || !series.HasLocalImage("banner")))
                     {
                         var n = images.SelectSingleNode("//Banner[BannerType='series']");
                         if (n != null)
@@ -360,7 +389,7 @@ namespace MediaBrowser.Controller.Providers.TV
                             {
                                 try
                                 {
-                                    var bannerImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), Kernel.Instance.ResourcePools.TvDb, cancellationToken);
+                                    var bannerImagePath = await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + n.InnerText, "banner" + Path.GetExtension(n.InnerText), TvDbResourcePool, cancellationToken);
 
                                     series.SetImage(ImageType.Banner, bannerImagePath);
                                 }
@@ -385,11 +414,11 @@ namespace MediaBrowser.Controller.Providers.TV
                             if (p != null)
                             {
                                 var bdName = "backdrop" + (bdNo > 0 ? bdNo.ToString() : "");
-                                if (Kernel.Instance.Configuration.RefreshItemImages || !series.HasLocalImage(bdName))
+                                if (ConfigurationManager.Configuration.RefreshItemImages || !series.HasLocalImage(bdName))
                                 {
                                     try
                                     {
-                                        series.BackdropImagePaths.Add(await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false));
+                                        series.BackdropImagePaths.Add(await Kernel.Instance.ProviderManager.DownloadAndSaveImage(series, TVUtils.BannerUrl + p.InnerText, bdName + Path.GetExtension(p.InnerText), TvDbResourcePool, cancellationToken).ConfigureAwait(false));
                                     }
                                     catch (HttpException)
                                     {
@@ -400,7 +429,7 @@ namespace MediaBrowser.Controller.Providers.TV
                                     }
                                 }
                                 bdNo++;
-                                if (bdNo >= Kernel.Instance.Configuration.MaxBackdrops) break;
+                                if (bdNo >= ConfigurationManager.Configuration.MaxBackdrops) break;
                             }
                         }
                 }
@@ -463,7 +492,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
             try
             {
-                using (var results = await HttpClient.Get(url, Kernel.Instance.ResourcePools.TvDb, cancellationToken).ConfigureAwait(false))
+                using (var results = await HttpClient.Get(url, TvDbResourcePool, cancellationToken).ConfigureAwait(false))
                 {
                     doc.Load(results);
                 }

+ 3 - 2
MediaBrowser.Controller/Providers/TV/SeriesProviderFromXml.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Model.Entities;
 using System;
@@ -14,7 +15,7 @@ namespace MediaBrowser.Controller.Providers.TV
     /// </summary>
     public class SeriesProviderFromXml : BaseMetadataProvider
     {
-        public SeriesProviderFromXml(ILogManager logManager) : base(logManager)
+        public SeriesProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
         {
         }
 

+ 4 - 3
MediaBrowser.Controller/Updates/InstallationManager.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Events;
+using MediaBrowser.Common;
+using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Plugins;
@@ -182,7 +183,7 @@ namespace MediaBrowser.Controller.Updates
             PackageType? packageType = null,
             Version applicationVersion = null)
         {
-            var packages = (await _packageManager.GetAvailablePackages(HttpClient, _networkManager, Kernel.SecurityManager, Kernel.ResourcePools, JsonSerializer, cancellationToken).ConfigureAwait(false)).ToList();
+            var packages = (await _packageManager.GetAvailablePackages(cancellationToken).ConfigureAwait(false)).ToList();
 
             if (packageType.HasValue)
             {
@@ -418,7 +419,7 @@ namespace MediaBrowser.Controller.Updates
         private async Task InstallPackageInternal(PackageVersionInfo package, IProgress<double> progress, CancellationToken cancellationToken)
         {
             // Do the install
-            await _packageManager.InstallPackage(HttpClient, _logger, Kernel.ResourcePools, progress, Kernel.ApplicationPaths, package, cancellationToken).ConfigureAwait(false);
+            await _packageManager.InstallPackage(progress, package, cancellationToken).ConfigureAwait(false);
 
             // Do plugin-specific processing
             if (!(Path.GetExtension(package.targetFilename) ?? "").Equals(".zip", StringComparison.OrdinalIgnoreCase))

+ 0 - 28
MediaBrowser.Model/DTO/BaseItemDto.cs

@@ -245,20 +245,6 @@ namespace MediaBrowser.Model.Dto
         [ProtoMember(38)]
         public int? RecentlyAddedItemCount { get; set; }
 
-        /// <summary>
-        /// Gets or sets the recently added un played item count.
-        /// </summary>
-        /// <value>The recently added un played item count.</value>
-        [ProtoMember(39)]
-        public int? RecentlyAddedUnPlayedItemCount { get; set; }
-
-        /// <summary>
-        /// Gets or sets the resumable item count.
-        /// </summary>
-        /// <value>The resumable item count.</value>
-        [ProtoMember(40)]
-        public int? ResumableItemCount { get; set; }
-
         /// <summary>
         /// Gets or sets the played percentage.
         /// </summary>
@@ -273,13 +259,6 @@ namespace MediaBrowser.Model.Dto
         [ProtoMember(42)]
         public int? RecursiveItemCount { get; set; }
 
-        /// <summary>
-        /// Gets or sets the favorite item count.
-        /// </summary>
-        /// <value>The favorite item count.</value>
-        [ProtoMember(43)]
-        public int? FavoriteItemCount { get; set; }
-
         /// <summary>
         /// Gets or sets the child count.
         /// </summary>
@@ -301,13 +280,6 @@ namespace MediaBrowser.Model.Dto
         [ProtoMember(46)]
         public string SeriesId { get; set; }
 
-        /// <summary>
-        /// Gets or sets the recently played item count.
-        /// </summary>
-        /// <value>The recently played item count.</value>
-        [ProtoMember(47)]
-        public int? RecentlyPlayedItemCount { get; set; }
-
         /// <summary>
         /// Gets or sets the special feature count.
         /// </summary>

+ 55 - 0
MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs

@@ -0,0 +1,55 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Implementations.Configuration;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Serialization;
+using System;
+
+namespace MediaBrowser.Server.Implementations.Configuration
+{
+    /// <summary>
+    /// Class ServerConfigurationManager
+    /// </summary>
+    public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class.
+        /// </summary>
+        /// <param name="applicationPaths">The application paths.</param>
+        /// <param name="logManager">The log manager.</param>
+        /// <param name="xmlSerializer">The XML serializer.</param>
+        public ServerConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer)
+            : base(applicationPaths, logManager, xmlSerializer)
+        {
+        }
+
+        /// <summary>
+        /// Gets the type of the configuration.
+        /// </summary>
+        /// <value>The type of the configuration.</value>
+        protected override Type ConfigurationType
+        {
+            get { return typeof(ServerConfiguration); }
+        }
+
+        /// <summary>
+        /// Gets the application paths.
+        /// </summary>
+        /// <value>The application paths.</value>
+        public IServerApplicationPaths ApplicationPaths
+        {
+            get { return (IServerApplicationPaths)CommonApplicationPaths; }
+        }
+
+        /// <summary>
+        /// Gets the configuration.
+        /// </summary>
+        /// <value>The configuration.</value>
+        public ServerConfiguration Configuration
+        {
+            get { return (ServerConfiguration)CommonConfiguration; }
+        }
+    }
+}

+ 18 - 9
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.ScheduledTasks;
 using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
@@ -90,6 +91,12 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <value>The kernel.</value>
         private Kernel Kernel { get; set; }
 
+        /// <summary>
+        /// Gets or sets the configuration manager.
+        /// </summary>
+        /// <value>The configuration manager.</value>
+        private IServerConfigurationManager ConfigurationManager { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="LibraryManager" /> class.
         /// </summary>
@@ -97,14 +104,16 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <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)
+        /// <param name="configurationManager">The configuration manager.</param>
+        public LibraryManager(Kernel kernel, ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager)
         {
             Kernel = kernel;
             _logger = logger;
             _taskManager = taskManager;
             _userManager = userManager;
+            ConfigurationManager = configurationManager;
 
-            kernel.ConfigurationUpdated += kernel_ConfigurationUpdated;
+            ConfigurationManager.ConfigurationUpdated += kernel_ConfigurationUpdated;
         }
 
         /// <summary>
@@ -222,7 +231,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 return null;
             }
 
-            var args = new ItemResolveArgs
+            var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths)
             {
                 Parent = parent,
                 Path = path,
@@ -306,7 +315,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <exception cref="System.InvalidOperationException">Cannot create the root folder until plugins have loaded</exception>
         public AggregateFolder CreateRootFolder()
         {
-            var rootFolderPath = Kernel.ApplicationPaths.RootFolderPath;
+            var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath;
             var rootFolder = Kernel.ItemRepository.RetrieveItem(rootFolderPath.GetMBId(typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(rootFolderPath);
 
             // Add in the plug-in folders
@@ -338,7 +347,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>Task{Person}.</returns>
         private Task<Person> GetPerson(string name, CancellationToken cancellationToken, bool allowSlowProviders = false)
         {
-            return GetImagesByNameItem<Person>(Kernel.ApplicationPaths.PeoplePath, name, cancellationToken, allowSlowProviders);
+            return GetImagesByNameItem<Person>(ConfigurationManager.ApplicationPaths.PeoplePath, name, cancellationToken, allowSlowProviders);
         }
 
         /// <summary>
@@ -349,7 +358,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>Task{Studio}.</returns>
         public Task<Studio> GetStudio(string name, bool allowSlowProviders = false)
         {
-            return GetImagesByNameItem<Studio>(Kernel.ApplicationPaths.StudioPath, name, CancellationToken.None, allowSlowProviders);
+            return GetImagesByNameItem<Studio>(ConfigurationManager.ApplicationPaths.StudioPath, name, CancellationToken.None, allowSlowProviders);
         }
 
         /// <summary>
@@ -360,7 +369,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>Task{Genre}.</returns>
         public Task<Genre> GetGenre(string name, bool allowSlowProviders = false)
         {
-            return GetImagesByNameItem<Genre>(Kernel.ApplicationPaths.GenrePath, name, CancellationToken.None, allowSlowProviders);
+            return GetImagesByNameItem<Genre>(ConfigurationManager.ApplicationPaths.GenrePath, name, CancellationToken.None, allowSlowProviders);
         }
 
         /// <summary>
@@ -382,7 +391,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 throw new ArgumentOutOfRangeException();
             }
 
-            return GetImagesByNameItem<Year>(Kernel.ApplicationPaths.YearPath, value.ToString(UsCulture), CancellationToken.None, allowSlowProviders);
+            return GetImagesByNameItem<Year>(ConfigurationManager.ApplicationPaths.YearPath, value.ToString(UsCulture), CancellationToken.None, allowSlowProviders);
         }
 
         /// <summary>
@@ -612,7 +621,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <returns>IEnumerable{VirtualFolderInfo}.</returns>
         public IEnumerable<VirtualFolderInfo> GetDefaultVirtualFolders()
         {
-            return GetView(Kernel.ApplicationPaths.DefaultUserViewsPath);
+            return GetView(ConfigurationManager.ApplicationPaths.DefaultUserViewsPath);
         }
 
         /// <summary>

+ 9 - 1
MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Library;
@@ -16,6 +17,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
     /// </summary>
     public class MovieResolver : BaseVideoResolver<Movie>
     {
+        private IServerApplicationPaths ApplicationPaths { get; set; }
+        
+        public MovieResolver(IServerApplicationPaths appPaths)
+        {
+            ApplicationPaths = appPaths;
+        }
+
         /// <summary>
         /// Gets the priority.
         /// </summary>
@@ -149,7 +157,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                     continue;
                 }
 
-                var childArgs = new ItemResolveArgs
+                var childArgs = new ItemResolveArgs(ApplicationPaths)
                 {
                     FileInfo = child,
                     Path = child.Path

+ 13 - 4
MediaBrowser.Server.Implementations/Library/UserManager.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Common.Events;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Model.Connectivity;
@@ -89,15 +90,23 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <value>The kernel.</value>
         private Kernel Kernel { get; set; }
 
+        /// <summary>
+        /// Gets or sets the configuration manager.
+        /// </summary>
+        /// <value>The configuration manager.</value>
+        private IServerConfigurationManager ConfigurationManager { get; set; }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="UserManager" /> class.
         /// </summary>
         /// <param name="kernel">The kernel.</param>
         /// <param name="logger">The logger.</param>
-        public UserManager(Kernel kernel, ILogger logger)
+        /// <param name="configurationManager">The configuration manager.</param>
+        public UserManager(Kernel kernel, ILogger logger, IServerConfigurationManager configurationManager)
         {
             _logger = logger;
             Kernel = kernel;
+            ConfigurationManager = configurationManager;
         }
 
         #region Events
@@ -596,14 +605,14 @@ namespace MediaBrowser.Server.Implementations.Library
                 var pctIn = Decimal.Divide(positionTicks, item.RunTimeTicks.Value) * 100;
 
                 // Don't track in very beginning
-                if (pctIn < Kernel.Configuration.MinResumePct)
+                if (pctIn < ConfigurationManager.Configuration.MinResumePct)
                 {
                     positionTicks = 0;
                     incrementPlayCount = false;
                 }
 
                 // If we're at the end, assume completed
-                else if (pctIn > Kernel.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value)
+                else if (pctIn > ConfigurationManager.Configuration.MaxResumePct || positionTicks >= item.RunTimeTicks.Value)
                 {
                     positionTicks = 0;
                     data.Played = true;
@@ -614,7 +623,7 @@ namespace MediaBrowser.Server.Implementations.Library
                     // Enforce MinResumeDuration
                     var durationSeconds = TimeSpan.FromTicks(item.RunTimeTicks.Value).TotalSeconds;
 
-                    if (durationSeconds < Kernel.Configuration.MinResumeDurationSeconds)
+                    if (durationSeconds < ConfigurationManager.Configuration.MinResumeDurationSeconds)
                     {
                         positionTicks = 0;
                         data.Played = true;

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

@@ -58,6 +58,7 @@
       <Link>Properties\SharedVersion.cs</Link>
     </Compile>
     <Compile Include="BdInfo\BdInfoExaminer.cs" />
+    <Compile Include="Configuration\ServerConfigurationManager.cs" />
     <Compile Include="Library\CoreResolutionIgnoreRule.cs" />
     <Compile Include="Library\LibraryManager.cs" />
     <Compile Include="Library\ResolverHelper.cs" />

+ 2 - 1
MediaBrowser.Server.Implementations/Sqlite/SQLiteDisplayPreferencesRepository.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.Entities;

+ 1 - 0
MediaBrowser.Server.Implementations/Sqlite/SQLiteItemRepository.cs

@@ -1,3 +1,4 @@
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Persistence;

+ 2 - 1
MediaBrowser.Server.Implementations/Sqlite/SQLiteUserDataRepository.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.Logging;

+ 2 - 1
MediaBrowser.Server.Implementations/Sqlite/SQLiteUserRepository.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Kernel;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Model.Logging;

+ 0 - 1
MediaBrowser.Server.Implementations/WorldWeatherOnline/WeatherProvider.cs

@@ -1,5 +1,4 @@
 using MediaBrowser.Common.Net;
-using MediaBrowser.Controller;
 using MediaBrowser.Controller.Weather;
 using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.Serialization;

+ 9 - 72
MediaBrowser.ServerApplication/App.xaml.cs

@@ -1,4 +1,5 @@
 using System.IO;
+using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Constants;
 using MediaBrowser.Common.Kernel;
 using MediaBrowser.Common.Updates;
@@ -71,12 +72,6 @@ namespace MediaBrowser.ServerApplication
         /// </summary>
         private Mutex SingleInstanceMutex;
 
-        /// <summary>
-        /// Gets or sets the kernel.
-        /// </summary>
-        /// <value>The kernel.</value>
-        protected IKernel Kernel { get; set; }
-
         /// <summary>
         /// Gets or sets the logger.
         /// </summary>
@@ -107,12 +102,6 @@ namespace MediaBrowser.ServerApplication
             get { return "MediaBrowser.Server.Uninstall.exe"; }
         }
 
-        /// <summary>
-        /// Gets or sets a value indicating whether [last run at startup value].
-        /// </summary>
-        /// <value><c>null</c> if [last run at startup value] contains no value, <c>true</c> if [last run at startup value]; otherwise, <c>false</c>.</value>
-        private bool? LastRunAtStartupValue { get; set; }
-
         /// <summary>
         /// Raises the <see cref="E:System.Windows.Application.Startup" /> event.
         /// </summary>
@@ -164,26 +153,17 @@ namespace MediaBrowser.ServerApplication
         /// </summary>
         protected async void LoadKernel()
         {
-            CompositionRoot = new ApplicationHost();
-            await CompositionRoot.Init();
-
-            Logger = CompositionRoot.Logger;
-            Kernel = CompositionRoot.Kernel;
-
             try
             {
-                var win = (MainWindow)CompositionRoot.CreateInstance(typeof(MainWindow));
-
-                win.Show();
+                CompositionRoot = new ApplicationHost();
 
-                var now = DateTime.UtcNow;
+                var win = new MainWindow(CompositionRoot.LogManager, CompositionRoot, CompositionRoot.ServerConfigurationManager);
 
-                Kernel.Init();
+                Logger = CompositionRoot.LogManager.GetLogger("App");
 
-                var done = (DateTime.UtcNow - now);
-                Logger.Info("Kernel.Init completed in {0}{1} minutes and {2} seconds.", done.Hours > 0 ? done.Hours + " Hours " : "", done.Minutes, done.Seconds);
+                win.Show();
 
-                await OnKernelLoaded();
+                await CompositionRoot.Init();
             }
             catch (Exception ex)
             {
@@ -196,41 +176,6 @@ namespace MediaBrowser.ServerApplication
             }
         }
 
-        /// <summary>
-        /// Called when [kernel loaded].
-        /// </summary>
-        /// <returns>Task.</returns>
-        protected Task OnKernelLoaded()
-        {
-            return Task.Run(() =>
-            {
-                Kernel.ConfigurationUpdated += Kernel_ConfigurationUpdated;
-
-                ConfigureAutoRun();
-            });
-        }
-
-        /// <summary>
-        /// Handles the ConfigurationUpdated event of the Kernel control.
-        /// </summary>
-        /// <param name="sender">The source of the event.</param>
-        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
-        void Kernel_ConfigurationUpdated(object sender, EventArgs e)
-        {
-            if (!LastRunAtStartupValue.HasValue || LastRunAtStartupValue.Value != Kernel.Configuration.RunAtStartup)
-            {
-                ConfigureAutoRun();
-            }
-        }
-
-        /// <summary>
-        /// Configures the click once startup.
-        /// </summary>
-        private void ConfigureAutoRun()
-        {
-            CompositionRoot.ConfigureAutoRunAtStartup(Kernel.Configuration.RunAtStartup);
-        }
-
         /// <summary>
         /// Raises the <see cref="E:System.Windows.Application.Exit" /> event.
         /// </summary>
@@ -260,22 +205,14 @@ namespace MediaBrowser.ServerApplication
             SingleInstanceMutex = null;
         }
 
-        /// <summary>
-        /// Opens the dashboard.
-        /// </summary>
-        public static void OpenDashboard(User loggedInUser)
-        {
-            OpenDashboardPage("dashboard.html", loggedInUser);
-        }
-
         /// <summary>
         /// Opens the dashboard page.
         /// </summary>
         /// <param name="page">The page.</param>
-        public static void OpenDashboardPage(string page, User loggedInUser)
+        public static void OpenDashboardPage(string page, User loggedInUser, IConfigurationManager configurationManager)
         {
-            var url = "http://localhost:" + Controller.Kernel.Instance.Configuration.HttpServerPortNumber + "/" +
-                      Controller.Kernel.Instance.WebApplicationName + "/dashboard/" + page;
+            var url = "http://localhost:" + configurationManager.CommonConfiguration.HttpServerPortNumber + "/" +
+                      Kernel.Instance.WebApplicationName + "/dashboard/" + page;
 
             if (loggedInUser != null)
             {

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff