aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.UI/Controller
diff options
context:
space:
mode:
authorLukePulverenti <luke.pulverenti@gmail.com>2013-02-20 20:33:05 -0500
committerLukePulverenti <luke.pulverenti@gmail.com>2013-02-20 20:33:05 -0500
commit767cdc1f6f6a63ce997fc9476911e2c361f9d402 (patch)
tree49add55976f895441167c66cfa95e5c7688d18ce /MediaBrowser.UI/Controller
parent845554722efaed872948a9e0f7202e3ef52f1b6e (diff)
Pushing missing changes
Diffstat (limited to 'MediaBrowser.UI/Controller')
-rw-r--r--MediaBrowser.UI/Controller/BaseTheme.cs60
-rw-r--r--MediaBrowser.UI/Controller/PluginUpdater.cs537
-rw-r--r--MediaBrowser.UI/Controller/UIKernel.cs298
3 files changed, 567 insertions, 328 deletions
diff --git a/MediaBrowser.UI/Controller/BaseTheme.cs b/MediaBrowser.UI/Controller/BaseTheme.cs
new file mode 100644
index 0000000000..7d88f93a04
--- /dev/null
+++ b/MediaBrowser.UI/Controller/BaseTheme.cs
@@ -0,0 +1,60 @@
+using MediaBrowser.Model.DTO;
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace MediaBrowser.UI.Controller
+{
+ /// <summary>
+ /// Class BaseTheme
+ /// </summary>
+ public abstract class BaseTheme : IDisposable
+ {
+ /// <summary>
+ /// Gets the global resources.
+ /// </summary>
+ /// <returns>IEnumerable{ResourceDictionary}.</returns>
+ public abstract IEnumerable<ResourceDictionary> GetGlobalResources();
+
+ /// <summary>
+ /// Gets the list page.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>Page.</returns>
+ public abstract Page GetListPage(DtoBaseItem item);
+ /// <summary>
+ /// Gets the detail page.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>Page.</returns>
+ public abstract Page GetDetailPage(DtoBaseItem item);
+ /// <summary>
+ /// Gets the home page.
+ /// </summary>
+ /// <returns>Page.</returns>
+ public abstract Page GetHomePage();
+ /// <summary>
+ /// Gets the login page.
+ /// </summary>
+ /// <returns>Page.</returns>
+ public abstract Page GetLoginPage();
+ /// <summary>
+ /// Gets the internal player page.
+ /// </summary>
+ /// <returns>Page.</returns>
+ public abstract Page GetInternalPlayerPage();
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public virtual void Dispose()
+ {
+ }
+
+ /// <summary>
+ /// Displays the weather.
+ /// </summary>
+ public abstract void DisplayWeather();
+ }
+}
diff --git a/MediaBrowser.UI/Controller/PluginUpdater.cs b/MediaBrowser.UI/Controller/PluginUpdater.cs
index d9fa48749a..55a82dc277 100644
--- a/MediaBrowser.UI/Controller/PluginUpdater.cs
+++ b/MediaBrowser.UI/Controller/PluginUpdater.cs
@@ -1,231 +1,306 @@
-using MediaBrowser.Common.Logging;
-using MediaBrowser.Common.Plugins;
-using MediaBrowser.Common.Serialization;
-using MediaBrowser.Model.DTO;
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.Composition;
-using System.ComponentModel.Composition.Hosting;
-using System.IO;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.UI.Controller
-{
- /// <summary>
- /// This keeps ui plugin assemblies in sync with plugins installed on the server
- /// </summary>
- public class PluginUpdater
- {
- /// <summary>
- /// Gets the list of currently installed UI plugins
- /// </summary>
- [ImportMany(typeof(BasePlugin))]
- private IEnumerable<BasePlugin> CurrentPlugins { get; set; }
-
- private CompositionContainer CompositionContainer { get; set; }
-
- public async Task<PluginUpdateResult> UpdatePlugins()
- {
- // First load the plugins that are currently installed
- ReloadComposableParts();
-
- Logger.LogInfo("Downloading list of installed plugins");
- PluginInfo[] allInstalledPlugins = await UIKernel.Instance.ApiClient.GetInstalledPluginsAsync().ConfigureAwait(false);
-
- IEnumerable<PluginInfo> uiPlugins = allInstalledPlugins.Where(p => p.DownloadToUI);
-
- PluginUpdateResult result = new PluginUpdateResult();
-
- result.DeletedPlugins = DeleteUninstalledPlugins(uiPlugins);
-
- await DownloadPluginAssemblies(uiPlugins, result).ConfigureAwait(false);
-
- // If any new assemblies were downloaded we'll have to reload the CurrentPlugins list
- if (result.NewlyInstalledPlugins.Any())
- {
- ReloadComposableParts();
- }
-
- result.UpdatedConfigurations = await DownloadPluginConfigurations(uiPlugins).ConfigureAwait(false);
-
- CompositionContainer.Dispose();
-
- return result;
- }
-
- /// <summary>
- /// Downloads plugin assemblies from the server, if they need to be installed or updated.
- /// </summary>
- private async Task DownloadPluginAssemblies(IEnumerable<PluginInfo> uiPlugins, PluginUpdateResult result)
- {
- List<PluginInfo> newlyInstalledPlugins = new List<PluginInfo>();
- List<PluginInfo> updatedPlugins = new List<PluginInfo>();
-
- // Loop through the list of plugins that are on the server
- foreach (PluginInfo pluginInfo in uiPlugins)
- {
- // See if it is already installed in the UI
- BasePlugin installedPlugin = CurrentPlugins.FirstOrDefault(p => p.AssemblyFileName.Equals(pluginInfo.AssemblyFileName, StringComparison.OrdinalIgnoreCase));
-
- // Download the plugin if it is not present, or if the current version is out of date
- bool downloadPlugin = installedPlugin == null;
-
- if (installedPlugin != null)
- {
- Version serverVersion = Version.Parse(pluginInfo.Version);
-
- downloadPlugin = serverVersion > installedPlugin.Version;
- }
-
- if (downloadPlugin)
- {
- await DownloadPlugin(pluginInfo).ConfigureAwait(false);
-
- if (installedPlugin == null)
- {
- newlyInstalledPlugins.Add(pluginInfo);
- }
- else
- {
- updatedPlugins.Add(pluginInfo);
- }
- }
- }
-
- result.NewlyInstalledPlugins = newlyInstalledPlugins;
- result.UpdatedPlugins = updatedPlugins;
- }
-
- /// <summary>
- /// Downloads plugin configurations from the server.
- /// </summary>
- private async Task<List<PluginInfo>> DownloadPluginConfigurations(IEnumerable<PluginInfo> uiPlugins)
- {
- List<PluginInfo> updatedPlugins = new List<PluginInfo>();
-
- // Loop through the list of plugins that are on the server
- foreach (PluginInfo pluginInfo in uiPlugins)
- {
- // See if it is already installed in the UI
- BasePlugin installedPlugin = CurrentPlugins.First(p => p.AssemblyFileName.Equals(pluginInfo.AssemblyFileName, StringComparison.OrdinalIgnoreCase));
-
- if (installedPlugin.ConfigurationDateLastModified < pluginInfo.ConfigurationDateLastModified)
- {
- await DownloadPluginConfiguration(installedPlugin, pluginInfo).ConfigureAwait(false);
-
- updatedPlugins.Add(pluginInfo);
- }
- }
-
- return updatedPlugins;
- }
-
- /// <summary>
- /// Downloads a plugin assembly from the server
- /// </summary>
- private async Task DownloadPlugin(PluginInfo plugin)
- {
- Logger.LogInfo("Downloading {0} Plugin", plugin.Name);
-
- string path = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginsPath, plugin.AssemblyFileName);
-
- // First download to a MemoryStream. This way if the download is cut off, we won't be left with a partial file
- using (MemoryStream memoryStream = new MemoryStream())
- {
- Stream assemblyStream = await UIKernel.Instance.ApiClient.GetPluginAssemblyAsync(plugin).ConfigureAwait(false);
-
- await assemblyStream.CopyToAsync(memoryStream).ConfigureAwait(false);
-
- memoryStream.Position = 0;
-
- using (FileStream fileStream = new FileStream(path, FileMode.Create))
- {
- await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
- }
- }
- }
-
- /// <summary>
- /// Downloads the latest configuration for a plugin
- /// </summary>
- private async Task DownloadPluginConfiguration(BasePlugin plugin, PluginInfo pluginInfo)
- {
- Logger.LogInfo("Downloading {0} Configuration", plugin.Name);
-
- object config = await UIKernel.Instance.ApiClient.GetPluginConfigurationAsync(pluginInfo, plugin.ConfigurationType).ConfigureAwait(false);
-
- XmlSerializer.SerializeToFile(config, plugin.ConfigurationFilePath);
-
- File.SetLastWriteTimeUtc(plugin.ConfigurationFilePath, pluginInfo.ConfigurationDateLastModified);
- }
-
- /// <summary>
- /// Deletes any plugins that have been uninstalled from the server
- /// </summary>
- private IEnumerable<string> DeleteUninstalledPlugins(IEnumerable<PluginInfo> uiPlugins)
- {
- var deletedPlugins = new List<string>();
-
- foreach (BasePlugin plugin in CurrentPlugins)
- {
- PluginInfo latest = uiPlugins.FirstOrDefault(p => p.AssemblyFileName.Equals(plugin.AssemblyFileName, StringComparison.OrdinalIgnoreCase));
-
- if (latest == null)
- {
- DeletePlugin(plugin);
-
- deletedPlugins.Add(plugin.Name);
- }
- }
-
- return deletedPlugins;
- }
-
- /// <summary>
- /// Deletes an installed ui plugin.
- /// Leaves config and data behind in the event it is later re-installed
- /// </summary>
- private void DeletePlugin(BasePlugin plugin)
- {
- Logger.LogInfo("Deleting {0} Plugin", plugin.Name);
-
- string path = plugin.AssemblyFilePath;
-
- if (File.Exists(path))
- {
- File.Delete(path);
- }
- }
-
- /// <summary>
- /// Re-uses MEF within the kernel to discover installed plugins
- /// </summary>
- private void ReloadComposableParts()
- {
- if (CompositionContainer != null)
- {
- CompositionContainer.Dispose();
- }
-
- CompositionContainer = UIKernel.Instance.GetCompositionContainer();
-
- CompositionContainer.ComposeParts(this);
-
- CompositionContainer.Catalog.Dispose();
-
- foreach (BasePlugin plugin in CurrentPlugins)
- {
- plugin.Initialize(UIKernel.Instance, false);
- }
- }
- }
-
- public class PluginUpdateResult
- {
- public IEnumerable<string> DeletedPlugins { get; set; }
- public IEnumerable<PluginInfo> NewlyInstalledPlugins { get; set; }
- public IEnumerable<PluginInfo> UpdatedPlugins { get; set; }
- public IEnumerable<PluginInfo> UpdatedConfigurations { get; set; }
- }
-}
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Logging;
+using MediaBrowser.Model.Net;
+using MediaBrowser.Model.Plugins;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.UI.Controller
+{
+ /// <summary>
+ /// This keeps ui plugin assemblies in sync with plugins installed on the server
+ /// </summary>
+ public class PluginUpdater
+ {
+ /// <summary>
+ /// Updates the plugins.
+ /// </summary>
+ /// <returns>Task{PluginUpdateResult}.</returns>
+ public async Task<PluginUpdateResult> UpdatePlugins()
+ {
+ Logger.LogInfo("Downloading list of installed plugins");
+ var allInstalledPlugins = await UIKernel.Instance.ApiClient.GetInstalledPluginsAsync().ConfigureAwait(false);
+
+ var uiPlugins = allInstalledPlugins.Where(p => p.DownloadToUI).ToList();
+
+ var result = new PluginUpdateResult { };
+
+ result.DeletedPlugins = DeleteUninstalledPlugins(uiPlugins);
+
+ await DownloadPluginAssemblies(uiPlugins, result).ConfigureAwait(false);
+
+ result.UpdatedConfigurations = await DownloadPluginConfigurations(uiPlugins).ConfigureAwait(false);
+
+ return result;
+ }
+
+ /// <summary>
+ /// Downloads plugin assemblies from the server, if they need to be installed or updated.
+ /// </summary>
+ /// <param name="uiPlugins">The UI plugins.</param>
+ /// <param name="result">The result.</param>
+ /// <returns>Task.</returns>
+ private async Task DownloadPluginAssemblies(IEnumerable<PluginInfo> uiPlugins, PluginUpdateResult result)
+ {
+ var newlyInstalledPlugins = new List<PluginInfo>();
+ var updatedPlugins = new List<PluginInfo>();
+
+ // Loop through the list of plugins that are on the server
+ foreach (var pluginInfo in uiPlugins)
+ {
+ // See if it is already installed in the UI
+ var currentAssemblyPath = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginsPath, pluginInfo.AssemblyFileName);
+
+ var isPluginInstalled = File.Exists(currentAssemblyPath);
+
+ // Download the plugin if it is not present, or if the current version is out of date
+ bool downloadPlugin;
+
+ if (!isPluginInstalled)
+ {
+ downloadPlugin = true;
+ Logger.LogInfo("{0} is not installed and needs to be downloaded.", pluginInfo.Name);
+ }
+ else
+ {
+ var serverVersion = Version.Parse(pluginInfo.Version);
+
+ var fileVersion = FileVersionInfo.GetVersionInfo(currentAssemblyPath).FileVersion ?? string.Empty;
+
+ downloadPlugin = string.IsNullOrEmpty(fileVersion) || Version.Parse(fileVersion) < serverVersion;
+
+ if (downloadPlugin)
+ {
+ Logger.LogInfo("{0} has an updated version on the server and needs to be downloaded. Server version: {1}, UI version: {2}", pluginInfo.Name, serverVersion, fileVersion);
+ }
+ }
+
+ if (downloadPlugin)
+ {
+ if (UIKernel.Instance.ApplicationVersion < Version.Parse(pluginInfo.MinimumRequiredUIVersion))
+ {
+ Logger.LogWarning("Can't download new version of {0} because the application needs to be updated first.", pluginInfo.Name);
+ continue;
+ }
+
+ try
+ {
+ await DownloadPlugin(pluginInfo).ConfigureAwait(false);
+
+ if (isPluginInstalled)
+ {
+ updatedPlugins.Add(pluginInfo);
+ }
+ else
+ {
+ newlyInstalledPlugins.Add(pluginInfo);
+ }
+ }
+ catch (HttpException ex)
+ {
+ Logger.LogException("Error downloading {0} configuration", ex, pluginInfo.Name);
+ }
+ catch (IOException ex)
+ {
+ Logger.LogException("Error saving plugin assembly for {0}", ex, pluginInfo.Name);
+ }
+ }
+ }
+
+ result.NewlyInstalledPlugins = newlyInstalledPlugins;
+ result.UpdatedPlugins = updatedPlugins;
+ }
+
+ /// <summary>
+ /// Downloads plugin configurations from the server.
+ /// </summary>
+ /// <param name="uiPlugins">The UI plugins.</param>
+ /// <returns>Task{List{PluginInfo}}.</returns>
+ private async Task<List<PluginInfo>> DownloadPluginConfigurations(IEnumerable<PluginInfo> uiPlugins)
+ {
+ var updatedPlugins = new List<PluginInfo>();
+
+ // Loop through the list of plugins that are on the server
+ foreach (var pluginInfo in uiPlugins
+ .Where(p => UIKernel.Instance.ApplicationVersion >= Version.Parse(p.MinimumRequiredUIVersion)))
+ {
+ // See if it is already installed in the UI
+ var path = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginConfigurationsPath, pluginInfo.ConfigurationFileName);
+
+ var download = false;
+
+ if (!File.Exists(path))
+ {
+ download = true;
+ Logger.LogInfo("{0} configuration was not found needs to be downloaded.", pluginInfo.Name);
+ }
+ else if (File.GetLastWriteTimeUtc(path) < pluginInfo.ConfigurationDateLastModified)
+ {
+ download = true;
+ Logger.LogInfo("{0} has an updated configuration on the server and needs to be downloaded.", pluginInfo.Name);
+ }
+
+ if (download)
+ {
+ if (UIKernel.Instance.ApplicationVersion < Version.Parse(pluginInfo.MinimumRequiredUIVersion))
+ {
+ Logger.LogWarning("Can't download updated configuration of {0} because the application needs to be updated first.", pluginInfo.Name);
+ continue;
+ }
+
+ try
+ {
+ await DownloadPluginConfiguration(pluginInfo, path).ConfigureAwait(false);
+
+ updatedPlugins.Add(pluginInfo);
+ }
+ catch (HttpException ex)
+ {
+ Logger.LogException("Error downloading {0} configuration", ex, pluginInfo.Name);
+ }
+ catch (IOException ex)
+ {
+ Logger.LogException("Error saving plugin configuration to {0}", ex, path);
+ }
+ }
+ }
+
+ return updatedPlugins;
+ }
+
+ /// <summary>
+ /// Downloads a plugin assembly from the server
+ /// </summary>
+ /// <param name="plugin">The plugin.</param>
+ /// <returns>Task.</returns>
+ private async Task DownloadPlugin(PluginInfo plugin)
+ {
+ Logger.LogInfo("Downloading {0} Plugin", plugin.Name);
+
+ var path = Path.Combine(UIKernel.Instance.ApplicationPaths.PluginsPath, plugin.AssemblyFileName);
+
+ // First download to a MemoryStream. This way if the download is cut off, we won't be left with a partial file
+ using (var memoryStream = new MemoryStream())
+ {
+ var assemblyStream = await UIKernel.Instance.ApiClient.GetPluginAssemblyAsync(plugin).ConfigureAwait(false);
+
+ await assemblyStream.CopyToAsync(memoryStream).ConfigureAwait(false);
+
+ memoryStream.Position = 0;
+
+ using (var fileStream = new FileStream(path, FileMode.Create))
+ {
+ await memoryStream.CopyToAsync(fileStream).ConfigureAwait(false);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Downloads the latest configuration for a plugin
+ /// </summary>
+ /// <param name="pluginInfo">The plugin info.</param>
+ /// <param name="path">The path.</param>
+ /// <returns>Task.</returns>
+ private async Task DownloadPluginConfiguration(PluginInfo pluginInfo, string path)
+ {
+ Logger.LogInfo("Downloading {0} Configuration", pluginInfo.Name);
+
+ // First download to a MemoryStream. This way if the download is cut off, we won't be left with a partial file
+ using (var stream = await UIKernel.Instance.ApiClient.GetPluginConfigurationFileAsync(pluginInfo.UniqueId).ConfigureAwait(false))
+ {
+ using (var memoryStream = new MemoryStream())
+ {
+ await stream.CopyToAsync(memoryStream).ConfigureAwait(false);
+
+ memoryStream.Position = 0;
+
+ using (var fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, true))
+ {
+ await memoryStream.CopyToAsync(fs).ConfigureAwait(false);
+ }
+ }
+ }
+
+ File.SetLastWriteTimeUtc(path, pluginInfo.ConfigurationDateLastModified);
+ }
+
+ /// <summary>
+ /// Deletes any plugins that have been uninstalled from the server
+ /// </summary>
+ /// <param name="uiPlugins">The UI plugins.</param>
+ /// <returns>IEnumerable{System.String}.</returns>
+ private IEnumerable<string> DeleteUninstalledPlugins(IEnumerable<PluginInfo> uiPlugins)
+ {
+ var deletedPlugins = new List<string>();
+
+ foreach (var plugin in Directory.EnumerateFiles(UIKernel.Instance.ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly)
+ .Select(Path.GetFileName)
+ .ToList())
+ {
+ var serverPlugin = uiPlugins.FirstOrDefault(p => p.AssemblyFileName.Equals(plugin, StringComparison.OrdinalIgnoreCase));
+
+ if (serverPlugin == null)
+ {
+ try
+ {
+ DeletePlugin(plugin);
+
+ deletedPlugins.Add(plugin);
+ }
+ catch (IOException ex)
+ {
+ Logger.LogException("Error deleting plugin assembly {0}", ex, plugin);
+ }
+ }
+ }
+
+ return deletedPlugins;
+ }
+
+ /// <summary>
+ /// Deletes an installed ui plugin.
+ /// Leaves config and data behind in the event it is later re-installed
+ /// </summary>
+ /// <param name="plugin">The plugin.</param>
+ private void DeletePlugin(string plugin)
+ {
+ Logger.LogInfo("Deleting {0} Plugin", plugin);
+
+ if (File.Exists(plugin))
+ {
+ File.Delete(plugin);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Class PluginUpdateResult
+ /// </summary>
+ public class PluginUpdateResult
+ {
+ /// <summary>
+ /// Gets or sets the deleted plugins.
+ /// </summary>
+ /// <value>The deleted plugins.</value>
+ public IEnumerable<string> DeletedPlugins { get; set; }
+ /// <summary>
+ /// Gets or sets the newly installed plugins.
+ /// </summary>
+ /// <value>The newly installed plugins.</value>
+ public IEnumerable<PluginInfo> NewlyInstalledPlugins { get; set; }
+ /// <summary>
+ /// Gets or sets the updated plugins.
+ /// </summary>
+ /// <value>The updated plugins.</value>
+ public IEnumerable<PluginInfo> UpdatedPlugins { get; set; }
+ /// <summary>
+ /// Gets or sets the updated configurations.
+ /// </summary>
+ /// <value>The updated configurations.</value>
+ public IEnumerable<PluginInfo> UpdatedConfigurations { get; set; }
+ }
+}
diff --git a/MediaBrowser.UI/Controller/UIKernel.cs b/MediaBrowser.UI/Controller/UIKernel.cs
index ca24b7852a..be313e1536 100644
--- a/MediaBrowser.UI/Controller/UIKernel.cs
+++ b/MediaBrowser.UI/Controller/UIKernel.cs
@@ -1,97 +1,201 @@
-using MediaBrowser.ApiInteraction;
-using MediaBrowser.Common.Kernel;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.DTO;
-using MediaBrowser.Model.Progress;
-using MediaBrowser.UI.Configuration;
-using System;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.UI.Controller
-{
- /// <summary>
- /// This controls application logic as well as server interaction within the UI.
- /// </summary>
- public class UIKernel : BaseKernel<UIApplicationConfiguration, UIApplicationPaths>
- {
- public static UIKernel Instance { get; private set; }
-
- public ApiClient ApiClient { get; private set; }
- public DtoUser CurrentUser { get; set; }
- public ServerConfiguration ServerConfiguration { get; set; }
-
- public UIKernel()
- : base()
- {
- Instance = this;
- }
-
- public override KernelContext KernelContext
- {
- get { return KernelContext.Ui; }
- }
-
- /// <summary>
- /// Give the UI a different url prefix so that they can share the same port, in case they are installed on the same machine.
- /// </summary>
- protected override string HttpServerUrlPrefix
- {
- get
- {
- return "http://+:" + Configuration.HttpServerPortNumber + "/mediabrowser/ui/";
- }
- }
-
- /// <summary>
- /// Performs initializations that can be reloaded at anytime
- /// </summary>
- protected override async Task ReloadInternal(IProgress<TaskProgress> progress)
- {
- ReloadApiClient();
-
- await new PluginUpdater().UpdatePlugins().ConfigureAwait(false);
-
- await base.ReloadInternal(progress).ConfigureAwait(false);
- }
-
- /// <summary>
- /// Updates and installs new plugin assemblies and configurations from the server
- /// </summary>
- protected async Task<PluginUpdateResult> UpdatePlugins()
- {
- return await new PluginUpdater().UpdatePlugins().ConfigureAwait(false);
- }
-
- /// <summary>
- /// Disposes the current ApiClient and creates a new one
- /// </summary>
- private void ReloadApiClient()
- {
- DisposeApiClient();
-
- ApiClient = new ApiClient
- {
- ServerHostName = Configuration.ServerHostName,
- ServerApiPort = Configuration.ServerApiPort
- };
- }
-
- /// <summary>
- /// Disposes the current ApiClient
- /// </summary>
- private void DisposeApiClient()
- {
- if (ApiClient != null)
- {
- ApiClient.Dispose();
- }
- }
-
- public override void Dispose()
- {
- base.Dispose();
-
- DisposeApiClient();
- }
- }
-}
+using System.Net;
+using System.Net.Cache;
+using System.Net.Http;
+using MediaBrowser.ApiInteraction;
+using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Logging;
+using MediaBrowser.Model.Connectivity;
+using MediaBrowser.Model.Net;
+using MediaBrowser.UI.Configuration;
+using MediaBrowser.UI.Playback;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.Composition;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.UI.Controller
+{
+ /// <summary>
+ /// This controls application logic as well as server interaction within the UI.
+ /// </summary>
+ public class UIKernel : BaseKernel<UIApplicationConfiguration, UIApplicationPaths>
+ {
+ /// <summary>
+ /// Gets the instance.
+ /// </summary>
+ /// <value>The instance.</value>
+ public static UIKernel Instance { get; private set; }
+
+ /// <summary>
+ /// Gets the API client.
+ /// </summary>
+ /// <value>The API client.</value>
+ public ApiClient ApiClient { get; private set; }
+
+ /// <summary>
+ /// Gets the playback manager.
+ /// </summary>
+ /// <value>The playback manager.</value>
+ public PlaybackManager PlaybackManager { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UIKernel" /> class.
+ /// </summary>
+ public UIKernel()
+ : base()
+ {
+ Instance = this;
+ }
+
+ /// <summary>
+ /// Gets the media players.
+ /// </summary>
+ /// <value>The media players.</value>
+ [ImportMany(typeof(BaseMediaPlayer))]
+ public IEnumerable<BaseMediaPlayer> MediaPlayers { get; private set; }
+
+ /// <summary>
+ /// Gets the list of currently loaded themes
+ /// </summary>
+ /// <value>The themes.</value>
+ [ImportMany(typeof(BaseTheme))]
+ public IEnumerable<BaseTheme> Themes { get; private set; }
+
+ /// <summary>
+ /// Gets the kernel context.
+ /// </summary>
+ /// <value>The kernel context.</value>
+ public override KernelContext KernelContext
+ {
+ get { return KernelContext.Ui; }
+ }
+
+ /// <summary>
+ /// Gets the UDP server port number.
+ /// </summary>
+ /// <value>The UDP server port number.</value>
+ public override int UdpServerPortNumber
+ {
+ get { return 7360; }
+ }
+
+ /// <summary>
+ /// Give the UI a different url prefix so that they can share the same port, in case they are installed on the same machine.
+ /// </summary>
+ /// <value>The HTTP server URL prefix.</value>
+ public override string HttpServerUrlPrefix
+ {
+ get
+ {
+ return "http://+:" + Configuration.HttpServerPortNumber + "/mediabrowserui/";
+ }
+ }
+
+ /// <summary>
+ /// Reload api client and update plugins after loading configuration
+ /// </summary>
+ /// <returns>Task.</returns>
+ protected override async Task OnConfigurationLoaded()
+ {
+ ReloadApiClient();
+
+ try
+ {
+ await new PluginUpdater().UpdatePlugins().ConfigureAwait(false);
+ }
+ catch (HttpException ex)
+ {
+ Logger.ErrorException("Error updating plugins from the server", ex);
+ }
+ }
+
+ /// <summary>
+ /// Disposes the current ApiClient and creates a new one
+ /// </summary>
+ private void ReloadApiClient()
+ {
+ DisposeApiClient();
+
+ var logger = LogManager.GetLogger("ApiClient");
+
+ ApiClient = new ApiClient(logger, new AsyncHttpClient(new WebRequestHandler
+ {
+ AutomaticDecompression = DecompressionMethods.Deflate,
+ CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate)
+ }))
+ {
+ ServerHostName = Configuration.ServerHostName,
+ ServerApiPort = Configuration.ServerApiPort,
+ ClientType = ClientType.Pc,
+ DeviceName = Environment.MachineName,
+ SerializationFormat = SerializationFormats.Json
+ };
+ }
+
+ /// <summary>
+ /// Reloads the internal.
+ /// </summary>
+ /// <returns>Task.</returns>
+ protected override Task ReloadInternal()
+ {
+ PlaybackManager = new PlaybackManager(this);
+
+ return base.ReloadInternal();
+ }
+
+ /// <summary>
+ /// Gets the composable part assemblies.
+ /// </summary>
+ /// <returns>IEnumerable{Assembly}.</returns>
+ protected override IEnumerable<Assembly> GetComposablePartAssemblies()
+ {
+ var runningDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
+
+ return base.GetComposablePartAssemblies().Concat(new[] {
+
+ Assembly.Load(File.ReadAllBytes(Path.Combine(runningDirectory, "MediaBrowser.Plugins.DefaultTheme.dll")))
+ });
+ }
+
+ /// <summary>
+ /// Called when [composable parts loaded].
+ /// </summary>
+ /// <returns>Task.</returns>
+ protected override async Task OnComposablePartsLoaded()
+ {
+ await base.OnComposablePartsLoaded().ConfigureAwait(false);
+
+ // Once plugins have loaded give the api a reference to our protobuf serializer
+ DataSerializer.DynamicSerializer = ProtobufSerializer.TypeModel;
+ }
+
+ /// <summary>
+ /// Disposes the current ApiClient
+ /// </summary>
+ private void DisposeApiClient()
+ {
+ if (ApiClient != null)
+ {
+ ApiClient.Dispose();
+ }
+ }
+
+ /// <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)
+ {
+ DisposeApiClient();
+ }
+
+ base.Dispose(dispose);
+ }
+ }
+}