diff --git a/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs b/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs
index 9e5657e3c2..5f5203dae0 100644
--- a/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs
+++ b/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs
@@ -12,7 +12,7 @@ namespace MediaBrowser.Api.HttpHandlers
{
string pluginName = QueryString["name"];
- return Kernel.Instance.PluginController.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
+ return Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
}
}
}
diff --git a/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs b/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs
index a558da163d..63797026d7 100644
--- a/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs
+++ b/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs
@@ -13,7 +13,7 @@ namespace MediaBrowser.Api.HttpHandlers
{
get
{
- var plugins = Kernel.Instance.PluginController.Plugins.Select(p =>
+ var plugins = Kernel.Instance.Plugins.Select(p =>
{
return new PluginInfo()
{
diff --git a/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs b/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs
index faace9c31a..06c3ea86dd 100644
--- a/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs
+++ b/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs
@@ -11,7 +11,7 @@ namespace MediaBrowser.Api.HttpHandlers
{
Guid userId = Guid.Parse(QueryString["userid"]);
- return Kernel.Instance.ConfigurationController.GetUserConfiguration(userId);
+ return Kernel.Instance.GetUserConfiguration(userId);
}
}
}
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 25889f9837..4560f70a15 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -31,6 +31,7 @@
+
diff --git a/MediaBrowser.Api/Plugin.cs b/MediaBrowser.Api/Plugin.cs
index 6ced7a704a..ebc2ffcae8 100644
--- a/MediaBrowser.Api/Plugin.cs
+++ b/MediaBrowser.Api/Plugin.cs
@@ -1,4 +1,5 @@
using System;
+using System.ComponentModel.Composition;
using System.Reactive.Linq;
using MediaBrowser.Api.HttpHandlers;
using MediaBrowser.Common.Net;
@@ -9,6 +10,7 @@ using MediaBrowser.Model.Plugins;
namespace MediaBrowser.Api
{
+ [Export(typeof(BasePlugin))]
public class Plugin : BaseGenericPlugin
{
public override string Name
diff --git a/MediaBrowser.Common/Configuration/ConfigurationController.cs b/MediaBrowser.Common/Configuration/ConfigurationController.cs
deleted file mode 100644
index 547d195f5a..0000000000
--- a/MediaBrowser.Common/Configuration/ConfigurationController.cs
+++ /dev/null
@@ -1,37 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.IO;
-using MediaBrowser.Common.Json;
-
-namespace MediaBrowser.Common.Configuration
-{
- public class ConfigurationController
- where TConfigurationType : BaseConfiguration, new ()
- {
- ///
- /// The path to the configuration file
- ///
- public string Path { get; set; }
-
- public TConfigurationType Configuration { get; set; }
-
- public void Reload()
- {
- if (!File.Exists(Path))
- {
- Configuration = new TConfigurationType();
- }
- else
- {
- Configuration = JsonSerializer.DeserializeFromFile(Path);
- }
- }
-
- public void Save()
- {
- }
- }
-}
diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs
index 47e5d2c942..0edfeab25f 100644
--- a/MediaBrowser.Common/Kernel/BaseKernel.cs
+++ b/MediaBrowser.Common/Kernel/BaseKernel.cs
@@ -1,6 +1,11 @@
-using System.Configuration;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.ComponentModel.Composition.Hosting;
+using System.Configuration;
using System.IO;
+using System.Linq;
using System.Reflection;
+using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Json;
using MediaBrowser.Common.Logging;
@@ -12,8 +17,7 @@ namespace MediaBrowser.Common.Kernel
///
/// Represents a shared base kernel for both the UI and server apps
///
- public abstract class BaseKernel
- where TConfigurationContorllerType : ConfigurationController, new()
+ public abstract class BaseKernel
where TConfigurationType : BaseConfiguration, new()
{
///
@@ -21,19 +25,39 @@ namespace MediaBrowser.Common.Kernel
///
public string ProgramDataPath { get; private set; }
+ protected string PluginsPath
+ {
+ get
+ {
+ return Path.Combine(ProgramDataPath, "plugins");
+ }
+ }
+
+ protected string ConfigurationPath
+ {
+ get
+ {
+ return Path.Combine(ProgramDataPath, "config.js");
+ }
+ }
+
///
/// Gets the current configuration
///
- public TConfigurationContorllerType ConfigurationController { get; private set; }
+ public TConfigurationType Configuration { get; private set; }
+ ///
+ /// Gets the list of currently loaded plugins
+ ///
+ [ImportMany(typeof(BasePlugin))]
+ public IEnumerable Plugins { get; private set; }
+
///
/// Both the UI and server will have a built-in HttpServer.
/// People will inevitably want remote control apps so it's needed in the UI too.
///
public HttpServer HttpServer { get; private set; }
- public PluginController PluginController { get; private set; }
-
///
/// Gets the kernel context. The UI kernel will have to override this.
///
@@ -43,9 +67,6 @@ namespace MediaBrowser.Common.Kernel
{
ProgramDataPath = GetProgramDataPath();
- PluginController = new PluginController() { PluginsPath = Path.Combine(ProgramDataPath, "Plugins") };
- ConfigurationController = new TConfigurationContorllerType() { Path = Path.Combine(ProgramDataPath, "config.js") };
-
Logger.LoggerInstance = new FileLogger(Path.Combine(ProgramDataPath, "Logs"));
}
@@ -55,7 +76,51 @@ namespace MediaBrowser.Common.Kernel
ReloadHttpServer();
- ReloadPlugins();
+ ReloadComposableParts();
+ }
+
+ protected void ReloadComposableParts()
+ {
+ if (!Directory.Exists(PluginsPath))
+ {
+ Directory.CreateDirectory(PluginsPath);
+ }
+
+ var catalog = new AggregateCatalog(Directory.GetDirectories(PluginsPath, "*", SearchOption.TopDirectoryOnly).Select(f => new DirectoryCatalog(f)));
+
+ //catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
+ //catalog.Catalogs.Add(new AssemblyCatalog(GetType().Assembly));
+
+ new CompositionContainer(catalog).ComposeParts(this);
+
+ OnComposablePartsLoaded();
+ }
+
+ protected virtual void OnComposablePartsLoaded()
+ {
+ StartPlugins();
+ }
+
+ private void StartPlugins()
+ {
+ Parallel.For(0, Plugins.Count(), i =>
+ {
+ var plugin = Plugins.ElementAt(i);
+
+ plugin.ReloadConfiguration();
+
+ if (plugin.Enabled)
+ {
+ if (KernelContext == KernelContext.Server)
+ {
+ plugin.InitInServer();
+ }
+ else
+ {
+ plugin.InitInUI();
+ }
+ }
+ });
}
///
@@ -87,9 +152,21 @@ namespace MediaBrowser.Common.Kernel
private void ReloadConfiguration()
{
// Deserialize config
- ConfigurationController.Reload();
+ if (!File.Exists(ConfigurationPath))
+ {
+ Configuration = new TConfigurationType();
+ }
+ else
+ {
+ Configuration = JsonSerializer.DeserializeFromFile(ConfigurationPath);
+ }
- Logger.LoggerInstance.LogSeverity = ConfigurationController.Configuration.LogSeverity;
+ Logger.LoggerInstance.LogSeverity = Configuration.LogSeverity;
+ }
+
+ public void SaveConfiguration()
+ {
+ JsonSerializer.SerializeToFile(Configuration, ConfigurationPath);
}
private void ReloadHttpServer()
@@ -99,13 +176,7 @@ namespace MediaBrowser.Common.Kernel
HttpServer.Dispose();
}
- HttpServer = new HttpServer("http://+:" + ConfigurationController.Configuration.HttpServerPortNumber + "/mediabrowser/");
- }
-
- protected virtual void ReloadPlugins()
- {
- // Find plugins
- PluginController.Init(KernelContext);
+ HttpServer = new HttpServer("http://+:" + Configuration.HttpServerPortNumber + "/mediabrowser/");
}
private static TConfigurationType GetConfiguration(string directory)
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj
index f7a223f1f5..26c850d5f3 100644
--- a/MediaBrowser.Common/MediaBrowser.Common.csproj
+++ b/MediaBrowser.Common/MediaBrowser.Common.csproj
@@ -34,6 +34,7 @@
..\packages\ServiceStack.Text.3.8.5\lib\net35\ServiceStack.Text.dll
+
@@ -48,7 +49,6 @@
-
@@ -67,7 +67,6 @@
-
diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs
index 7fdb2583ee..44f880fd2b 100644
--- a/MediaBrowser.Common/Plugins/BasePlugin.cs
+++ b/MediaBrowser.Common/Plugins/BasePlugin.cs
@@ -43,8 +43,22 @@ namespace MediaBrowser.Common.Plugins
public abstract class BasePlugin
{
public abstract string Name { get; }
- public string Path { get; set; }
- public Version Version { get; set; }
+
+ public string Path
+ {
+ get
+ {
+ return System.IO.Path.GetDirectoryName(GetType().Assembly.Location);
+ }
+ }
+
+ public Version Version
+ {
+ get
+ {
+ return GetType().Assembly.GetName().Version;
+ }
+ }
public BasePluginConfiguration Configuration { get; protected set; }
diff --git a/MediaBrowser.Common/Plugins/PluginController.cs b/MediaBrowser.Common/Plugins/PluginController.cs
deleted file mode 100644
index c26275436b..0000000000
--- a/MediaBrowser.Common/Plugins/PluginController.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-using System.Threading.Tasks;
-using MediaBrowser.Common.Kernel;
-
-namespace MediaBrowser.Common.Plugins
-{
- ///
- /// Manages Plugins within the PluginsPath directory
- ///
- public class PluginController
- {
- public string PluginsPath { get; set; }
-
- ///
- /// Gets the list of currently loaded plugins
- ///
- public IEnumerable Plugins { get; private set; }
-
- ///
- /// Initializes the controller
- ///
- public void Init(KernelContext context)
- {
- AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(CurrentDomain_AssemblyResolve);
- AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
-
- Plugins = GetAllPlugins();
-
- Parallel.For(0, Plugins.Count(), i =>
- {
- var plugin = Plugins.ElementAt(i);
-
- plugin.ReloadConfiguration();
-
- if (plugin.Enabled)
- {
- if (context == KernelContext.Server)
- {
- plugin.InitInServer();
- }
- else
- {
- plugin.InitInUI();
- }
- }
- });
- }
-
- ///
- /// Gets all plugins within PluginsPath
- ///
- ///
- private IEnumerable GetAllPlugins()
- {
- if (!Directory.Exists(PluginsPath))
- {
- Directory.CreateDirectory(PluginsPath);
- }
-
- List plugins = new List();
-
- foreach (string folder in Directory.GetDirectories(PluginsPath, "*", SearchOption.TopDirectoryOnly))
- {
- BasePlugin plugin = GetPluginFromDirectory(folder);
-
- plugin.Path = folder;
-
- if (plugin != null)
- {
- plugins.Add(plugin);
- }
- }
-
- return plugins;
- }
-
- private BasePlugin GetPluginFromDirectory(string path)
- {
- string dll = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly).FirstOrDefault();
-
- if (!string.IsNullOrEmpty(dll))
- {
- return GetPluginFromDll(dll);
- }
-
- return null;
- }
-
- private BasePlugin GetPluginFromDll(string path)
- {
- return GetPluginFromDll(Assembly.Load(File.ReadAllBytes(path)));
- }
-
- private BasePlugin GetPluginFromDll(Assembly assembly)
- {
- var plugin = assembly.GetTypes().Where(type => typeof(BasePlugin).IsAssignableFrom(type)).FirstOrDefault();
-
- if (plugin != null)
- {
- BasePlugin instance = plugin.GetConstructor(Type.EmptyTypes).Invoke(null) as BasePlugin;
-
- instance.Version = assembly.GetName().Version;
-
- return instance;
- }
-
- return null;
- }
-
- Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
- {
- AssemblyName assemblyName = new AssemblyName(args.Name);
-
- IEnumerable dllPaths = Directory.GetFiles(PluginsPath, "*.dll", SearchOption.AllDirectories);
-
- string dll = dllPaths.FirstOrDefault(f => Path.GetFileNameWithoutExtension(f) == assemblyName.Name);
-
- if (!string.IsNullOrEmpty(dll))
- {
- return Assembly.Load(File.ReadAllBytes(dll));
- }
-
- return null;
- }
- }
-}
diff --git a/MediaBrowser.Configuration/MediaBrowser.Configuration.csproj b/MediaBrowser.Configuration/MediaBrowser.Configuration.csproj
index 98b179f355..ff3cd25577 100644
--- a/MediaBrowser.Configuration/MediaBrowser.Configuration.csproj
+++ b/MediaBrowser.Configuration/MediaBrowser.Configuration.csproj
@@ -31,6 +31,7 @@
+
False
diff --git a/MediaBrowser.Configuration/Plugin.cs b/MediaBrowser.Configuration/Plugin.cs
index f88dc7a4ca..ffa3e38d0d 100644
--- a/MediaBrowser.Configuration/Plugin.cs
+++ b/MediaBrowser.Configuration/Plugin.cs
@@ -1,8 +1,10 @@
-using MediaBrowser.Common.Plugins;
+using System.ComponentModel.Composition;
+using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Plugins;
namespace MediaBrowser.Configuration
{
+ [Export(typeof(BasePlugin))]
public class Plugin : BaseGenericPlugin
{
public override string Name
diff --git a/MediaBrowser.Controller/Configuration/ServerConfigurationController.cs b/MediaBrowser.Controller/Configuration/ServerConfigurationController.cs
deleted file mode 100644
index 76c3cc43ce..0000000000
--- a/MediaBrowser.Controller/Configuration/ServerConfigurationController.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-using System;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Model.Configuration;
-
-namespace MediaBrowser.Controller.Configuration
-{
- ///
- /// Extends BaseConfigurationController by adding methods to get and set UIConfiguration data
- ///
- public class ServerConfigurationController : ConfigurationController
- {
- private string GetDictionaryKey(Guid userId, string deviceName)
- {
- string guidString = userId == Guid.Empty ? string.Empty : userId.ToString();
-
- return deviceName + "-" + guidString;
- }
-
- public UserConfiguration GetUserConfiguration(Guid userId)
- {
- return Configuration.DefaultUserConfiguration;
- }
- }
-}
diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs
index 8b2688da74..7cf12ff3f4 100644
--- a/MediaBrowser.Controller/Kernel.cs
+++ b/MediaBrowser.Controller/Kernel.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
@@ -17,7 +18,7 @@ using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller
{
- public class Kernel : BaseKernel
+ public class Kernel : BaseKernel
{
public static Kernel Instance { get; private set; }
@@ -37,6 +38,12 @@ namespace MediaBrowser.Controller
}
}
+ ///
+ /// Gets the list of currently registered entity resolvers
+ ///
+ [ImportMany(typeof(IBaseItemResolver))]
+ public IEnumerable EntityResolvers { get; private set; }
+
///
/// Creates a kernal based on a Data path, which is akin to our current programdata path
///
@@ -51,35 +58,27 @@ namespace MediaBrowser.Controller
ItemController.PreBeginResolvePath += ItemController_PreBeginResolvePath;
ItemController.BeginResolvePath += ItemController_BeginResolvePath;
-
- // Add support for core media types - audio, video, etc
- AddBaseItemType();
- AddBaseItemType