From 6efd22a3d22f8d87ad17da3a1e47ca26c5bb09f2 Mon Sep 17 00:00:00 2001 From: LukePulverenti Date: Tue, 26 Feb 2013 11:10:55 -0500 Subject: [PATCH] added a shutdown api method, font size fix and other decouplings --- MediaBrowser.Api/SystemService.cs | 32 ++++++- .../WebSocket/LogFileWebSocketListener.cs | 13 +-- .../BaseApplicationHost.cs | 43 +++++----- ...MediaBrowser.Common.Implementations.csproj | 6 +- .../ScheduledTasks/ScheduledTaskWorker.cs | 14 ++- .../ScheduledTasks/TaskManager.cs | 12 ++- .../Server}/RegisterServer.bat | 0 .../Server/ServerManager.cs | 45 ++++++---- .../Server}/WebSocketConnection.cs | 39 ++------- MediaBrowser.Common/Kernel/BaseKernel.cs | 54 ++---------- .../Kernel/BasePeriodicWebSocketListener.cs | 12 +-- .../Kernel/IApplicationHost.cs | 5 ++ MediaBrowser.Common/Kernel/IKernel.cs | 11 +-- MediaBrowser.Common/Kernel/IServerManager.cs | 54 ++++++++++++ .../MediaBrowser.Common.csproj | 5 +- .../Net/IWebSocketConnection.cs | 85 +++++++++++++++++++ MediaBrowser.Common/Net/IWebSocketServer.cs | 6 ++ MediaBrowser.Controller/Kernel.cs | 31 +------ .../Library/LibraryManager.cs | 52 +++++++++++- .../Library/UserManager.cs | 4 +- .../Updates/InstallationManager.cs | 10 +-- MediaBrowser.Networking/Udp/UdpServer.cs | 40 ++++++++- .../WebSocket/AlchemyServer.cs | 8 ++ MediaBrowser.ServerApplication/App.xaml.cs | 3 +- .../ApplicationHost.cs | 55 ++++++------ MediaBrowser.WebDashboard/Html/css/site.css | 4 - Nuget/MediaBrowser.ApiClient.nuspec | 2 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 30 files changed, 420 insertions(+), 235 deletions(-) rename {MediaBrowser.Common/Kernel => MediaBrowser.Common.Implementations/Server}/RegisterServer.bat (100%) rename MediaBrowser.Common/Kernel/TcpManager.cs => MediaBrowser.Common.Implementations/Server/ServerManager.cs (90%) rename {MediaBrowser.Common/Net => MediaBrowser.Common.Implementations/Server}/WebSocketConnection.cs (87%) create mode 100644 MediaBrowser.Common/Kernel/IServerManager.cs create mode 100644 MediaBrowser.Common/Net/IWebSocketConnection.cs diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs index cf0be35a2b..55e8ee693d 100644 --- a/MediaBrowser.Api/SystemService.cs +++ b/MediaBrowser.Api/SystemService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Kernel; using MediaBrowser.Controller; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Serialization; @@ -29,6 +30,11 @@ namespace MediaBrowser.Api { } + [Route("/System/Shutdown", "POST")] + public class ShutdownApplication + { + } + /// /// Class GetConfiguration /// @@ -61,19 +67,30 @@ namespace MediaBrowser.Api /// private readonly IJsonSerializer _jsonSerializer; + /// + /// The _app host + /// + private readonly IApplicationHost _appHost; + /// /// Initializes a new instance of the class. /// /// The json serializer. + /// The app host. /// jsonSerializer - public SystemService(IJsonSerializer jsonSerializer) + public SystemService(IJsonSerializer jsonSerializer, IApplicationHost appHost) : base() { if (jsonSerializer == null) { throw new ArgumentNullException("jsonSerializer"); } + if (appHost == null) + { + throw new ArgumentNullException("appHost"); + } + _appHost = appHost; _jsonSerializer = jsonSerializer; } @@ -118,6 +135,19 @@ namespace MediaBrowser.Api }); } + /// + /// Posts the specified request. + /// + /// The request. + public void Post(ShutdownApplication request) + { + Task.Run(async () => + { + await Task.Delay(100); + _appHost.Shutdown(); + }); + } + /// /// Posts the specified configuraiton. /// diff --git a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs index 6e3e103615..e0879d9241 100644 --- a/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs +++ b/MediaBrowser.Api/WebSocket/LogFileWebSocketListener.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.IO; using MediaBrowser.Common.Kernel; -using MediaBrowser.Controller; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -27,18 +26,20 @@ namespace MediaBrowser.Api.WebSocket /// /// The _kernel /// + private readonly IApplicationHost _appHost; private readonly IKernel _kernel; - + /// /// Initializes a new instance of the class. /// /// The logger. /// The kernel. - public LogFileWebSocketListener(ILogger logger, Kernel kernel) + public LogFileWebSocketListener(ILogger logger, IApplicationHost host, IKernel kernel) : base(logger) { + _appHost = host; _kernel = kernel; - _kernel.LoggerLoaded += kernel_LoggerLoaded; + kernel.LoggerLoaded += kernel_LoggerLoaded; } /// @@ -48,9 +49,9 @@ namespace MediaBrowser.Api.WebSocket /// IEnumerable{System.String}. protected override async Task> GetDataToSend(LogFileWebSocketState state) { - if (!string.Equals(_kernel.LogFilePath, state.LastLogFilePath)) + if (!string.Equals(_appHost.LogFilePath, state.LastLogFilePath)) { - state.LastLogFilePath = _kernel.LogFilePath; + state.LastLogFilePath = _appHost.LogFilePath; state.StartLine = 0; } diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index c5af5059f3..f5855bf753 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -151,21 +151,22 @@ namespace MediaBrowser.Common.Implementations /// /// /// The obj. - protected void RegisterSingleInstance(T obj) + /// if set to true [manage lifetime]. + protected void RegisterSingleInstance(T obj, bool manageLifetime = true) where T : class { Container.RegisterSingle(obj); - } - /// - /// Registers the specified func. - /// - /// - /// The func. - protected void Register(Func func) - where T : class - { - Container.Register(func); + if (manageLifetime) + { + var disposable = obj as IDisposable; + + if (disposable != null) + { + Logger.Info("Registering " + disposable.GetType().Name); + DisposableParts.Add(disposable); + } + } } /// @@ -205,16 +206,6 @@ namespace MediaBrowser.Common.Implementations return (T)result.GetInstance(); } - /// - /// Registers the specified service type. - /// - /// Type of the service. - /// Type of the concrete. - protected void Register(Type serviceType, Type implementation) - { - Container.Register(serviceType, implementation); - } - /// /// Loads the assembly. /// @@ -282,13 +273,17 @@ namespace MediaBrowser.Common.Implementations /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { - foreach (var part in DisposableParts) + var type = GetType(); + + Logger.Info("Disposing " + type.Name); + + foreach (var part in DisposableParts.Distinct().Where(i => i.GetType() != type).ToList()) { + Logger.Info("Disposing " + part.GetType().Name); + part.Dispose(); } - var b = Container.GetCurrentRegistrations(); - DisposableParts.Clear(); } } diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index acd798d733..59ec01aaf1 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -47,10 +47,7 @@ - - - @@ -69,6 +66,8 @@ + + @@ -82,6 +81,7 @@ + diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 7fa30f4ae0..320f440fc1 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -48,6 +48,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// The task manager. private ITaskManager TaskManager { get; set; } + /// + /// Gets or sets the server manager. + /// + /// The server manager. + private IServerManager ServerManager { get; set; } + /// /// Initializes a new instance of the class. /// @@ -56,13 +62,15 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// The task manager. /// The json serializer. /// The logger. - public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger) + /// The server manager. + public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger, IServerManager serverManager) { ScheduledTask = scheduledTask; ApplicationPaths = applicationPaths; TaskManager = taskManager; JsonSerializer = jsonSerializer; Logger = logger; + ServerManager = serverManager; } /// @@ -302,7 +310,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks TaskCompletionStatus status; CurrentExecutionStartTime = DateTime.UtcNow; - //Kernel.TcpManager.SendWebSocketMessage("ScheduledTaskBeginExecute", Name); + ServerManager.SendWebSocketMessage("ScheduledTaskBeginExecute", Name); try { @@ -324,7 +332,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks var startTime = CurrentExecutionStartTime; var endTime = DateTime.UtcNow; - //Kernel.TcpManager.SendWebSocketMessage("ScheduledTaskEndExecute", LastExecutionResult); + ServerManager.SendWebSocketMessage("ScheduledTaskEndExecute", LastExecutionResult); progress.ProgressChanged -= progress_ProgressChanged; CurrentCancellationTokenSource.Dispose(); diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs index 4b61492d66..335820e1cd 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs @@ -43,18 +43,26 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// The logger. private ILogger Logger { get; set; } + /// + /// Gets or sets the server manager. + /// + /// The server manager. + private IServerManager ServerManager { get; set; } + /// /// Initializes a new instance of the class. /// /// The application paths. /// The json serializer. /// The logger. + /// The server manager. /// kernel - public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger) + public TaskManager(IApplicationPaths applicationPaths, IJsonSerializer jsonSerializer, ILogger logger, IServerManager serverManager) { ApplicationPaths = applicationPaths; JsonSerializer = jsonSerializer; Logger = logger; + ServerManager = serverManager; ScheduledTasks = new IScheduledTaskWorker[] { }; } @@ -155,7 +163,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks { var myTasks = ScheduledTasks.ToList(); - myTasks.AddRange(tasks.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger))); + myTasks.AddRange(tasks.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, ServerManager))); ScheduledTasks = myTasks.ToArray(); } diff --git a/MediaBrowser.Common/Kernel/RegisterServer.bat b/MediaBrowser.Common.Implementations/Server/RegisterServer.bat similarity index 100% rename from MediaBrowser.Common/Kernel/RegisterServer.bat rename to MediaBrowser.Common.Implementations/Server/RegisterServer.bat diff --git a/MediaBrowser.Common/Kernel/TcpManager.cs b/MediaBrowser.Common.Implementations/Server/ServerManager.cs similarity index 90% rename from MediaBrowser.Common/Kernel/TcpManager.cs rename to MediaBrowser.Common.Implementations/Server/ServerManager.cs index 2dfed501af..04747bad6f 100644 --- a/MediaBrowser.Common/Kernel/TcpManager.cs +++ b/MediaBrowser.Common.Implementations/Server/ServerManager.cs @@ -1,5 +1,5 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Configuration; +using MediaBrowser.Common.Kernel; +using MediaBrowser.Common.Net; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; @@ -14,12 +14,12 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -namespace MediaBrowser.Common.Kernel +namespace MediaBrowser.Common.Implementations.Server { /// /// Manages the Http Server, Udp Server and WebSocket connections /// - public class TcpManager : IDisposable + public class ServerManager : IServerManager, IDisposable { /// /// This is the udp server used for server discovery by clients @@ -49,7 +49,7 @@ namespace MediaBrowser.Common.Kernel /// /// The web socket connections /// - private readonly List _webSocketConnections = new List(); + private readonly List _webSocketConnections = new List(); /// /// Gets or sets the external web socket server. @@ -81,7 +81,7 @@ namespace MediaBrowser.Common.Kernel /// Gets a value indicating whether [supports web socket]. /// /// true if [supports web socket]; otherwise, false. - internal bool SupportsNativeWebSocket + public bool SupportsNativeWebSocket { get { return HttpServer != null && HttpServer.SupportsWebSockets; } } @@ -96,7 +96,7 @@ namespace MediaBrowser.Common.Kernel } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The application host. /// The kernel. @@ -104,7 +104,7 @@ namespace MediaBrowser.Common.Kernel /// The json serializer. /// The logger. /// applicationHost - public TcpManager(IApplicationHost applicationHost, IKernel kernel, INetworkManager networkManager, IJsonSerializer jsonSerializer, ILogger logger) + public ServerManager(IApplicationHost applicationHost, IKernel kernel, INetworkManager networkManager, IJsonSerializer jsonSerializer, ILogger logger) { if (applicationHost == null) { @@ -132,8 +132,14 @@ namespace MediaBrowser.Common.Kernel _kernel = kernel; _applicationHost = applicationHost; _networkManager = networkManager; + } - if (applicationHost.IsFirstRun) + /// + /// Starts this instance. + /// + public void Start() + { + if (_applicationHost.IsFirstRun) { RegisterServerWithAdministratorAccess(); } @@ -145,6 +151,8 @@ namespace MediaBrowser.Common.Kernel { ReloadExternalWebSocketServer(); } + + _kernel.ConfigurationUpdated += _kernel_ConfigurationUpdated; } /// @@ -170,7 +178,7 @@ namespace MediaBrowser.Common.Kernel /// Restarts the Http Server, or starts it if not currently running /// /// if set to true [register server on failure]. - public void ReloadHttpServer(bool registerServerOnFailure = true) + private void ReloadHttpServer(bool registerServerOnFailure = true) { // Only reload if the port has changed, so that we don't disconnect any active users if (HttpServer != null && HttpServer.UrlPrefix.Equals(_kernel.HttpServerUrlPrefix, StringComparison.OrdinalIgnoreCase)) @@ -426,7 +434,7 @@ namespace MediaBrowser.Common.Kernel var tmpFile = Path.Combine(_kernel.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".bat"); // Extract the bat file - using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Common.Kernel.RegisterServer.bat")) + using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Common.Implementations.Server.bat")) { using (var fileStream = File.Create(tmpFile)) { @@ -489,20 +497,21 @@ namespace MediaBrowser.Common.Kernel } /// - /// Called when [application configuration changed]. + /// Handles the ConfigurationUpdated event of the _kernel control. /// - /// The old config. - /// The new config. - public void OnApplicationConfigurationChanged(BaseApplicationConfiguration oldConfig, BaseApplicationConfiguration newConfig) + /// The source of the event. + /// The instance containing the event data. + /// + void _kernel_ConfigurationUpdated(object sender, EventArgs e) { - HttpServer.EnableHttpRequestLogging = newConfig.EnableHttpLevelLogging; + HttpServer.EnableHttpRequestLogging = _kernel.Configuration.EnableHttpLevelLogging; - if (oldConfig.HttpServerPortNumber != newConfig.HttpServerPortNumber) + if (!string.Equals(HttpServer.UrlPrefix, _kernel.HttpServerUrlPrefix, StringComparison.OrdinalIgnoreCase)) { ReloadHttpServer(); } - if (!SupportsNativeWebSocket && oldConfig.LegacyWebSocketPortNumber != newConfig.LegacyWebSocketPortNumber) + if (!SupportsNativeWebSocket && ExternalWebSocketServer != null && ExternalWebSocketServer.Port != _kernel.Configuration.LegacyWebSocketPortNumber) { ReloadExternalWebSocketServer(); } diff --git a/MediaBrowser.Common/Net/WebSocketConnection.cs b/MediaBrowser.Common.Implementations/Server/WebSocketConnection.cs similarity index 87% rename from MediaBrowser.Common/Net/WebSocketConnection.cs rename to MediaBrowser.Common.Implementations/Server/WebSocketConnection.cs index 1ad0e8f06f..b8766523cd 100644 --- a/MediaBrowser.Common/Net/WebSocketConnection.cs +++ b/MediaBrowser.Common.Implementations/Server/WebSocketConnection.cs @@ -1,16 +1,17 @@ -using MediaBrowser.Model.Logging; +using MediaBrowser.Common.Net; +using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; using System.IO; using System.Threading; using System.Threading.Tasks; -namespace MediaBrowser.Common.Net +namespace MediaBrowser.Common.Implementations.Server { /// /// Class WebSocketConnection /// - public class WebSocketConnection : IDisposable + public class WebSocketConnection : IWebSocketConnection { /// /// The _socket @@ -20,7 +21,7 @@ namespace MediaBrowser.Common.Net /// /// The _remote end point /// - public readonly string RemoteEndPoint; + public string RemoteEndPoint { get; private set; } /// /// The _cancellation token source @@ -221,34 +222,4 @@ namespace MediaBrowser.Common.Net } } } - - /// - /// Class WebSocketMessage - /// - /// - public class WebSocketMessage - { - /// - /// Gets or sets the type of the message. - /// - /// The type of the message. - public string MessageType { get; set; } - /// - /// Gets or sets the data. - /// - /// The data. - public T Data { get; set; } - } - - /// - /// Class WebSocketMessageInfo - /// - public class WebSocketMessageInfo : WebSocketMessage - { - /// - /// Gets or sets the connection. - /// - /// The connection. - public WebSocketConnection Connection { get; set; } - } } diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 5b8da5d094..2ec1dd829d 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Events; -using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; @@ -165,7 +164,7 @@ namespace MediaBrowser.Common.Kernel /// Gets or sets the TCP manager. /// /// The TCP manager. - public TcpManager TcpManager { get; private set; } + public IServerManager ServerManager { get; private set; } /// /// Gets the UDP server port number. @@ -202,15 +201,6 @@ namespace MediaBrowser.Common.Kernel /// The kernel context. public abstract KernelContext KernelContext { get; } - /// - /// Gets the log file path. - /// - /// The log file path. - public string LogFilePath - { - get { return ApplicationHost.LogFilePath; } - } - /// /// Gets the logger. /// @@ -238,23 +228,6 @@ namespace MediaBrowser.Common.Kernel /// isoManager protected BaseKernel(IApplicationHost appHost, TApplicationPathsType appPaths, IXmlSerializer xmlSerializer, ILogger logger) { - if (appHost == null) - { - throw new ArgumentNullException("appHost"); - } - if (appPaths == null) - { - throw new ArgumentNullException("appPaths"); - } - if (xmlSerializer == null) - { - throw new ArgumentNullException("xmlSerializer"); - } - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - ApplicationPaths = appPaths; ApplicationHost = appHost; _xmlSerializer = xmlSerializer; @@ -291,8 +264,8 @@ namespace MediaBrowser.Common.Kernel await OnComposablePartsLoaded().ConfigureAwait(false); - DisposeTcpManager(); - TcpManager = (TcpManager)ApplicationHost.CreateInstance(typeof(TcpManager)); + ServerManager = ApplicationHost.Resolve(); + ServerManager.Start(); } /// @@ -357,7 +330,7 @@ namespace MediaBrowser.Common.Kernel { HasPendingRestart = true; - TcpManager.SendWebSocketMessage("HasPendingRestartChanged", GetSystemInfo()); + ServerManager.SendWebSocketMessage("HasPendingRestartChanged", GetSystemInfo()); EventHelper.QueueEventIfNotNull(HasPendingRestartChanged, this, EventArgs.Empty, Logger); } @@ -377,22 +350,7 @@ namespace MediaBrowser.Common.Kernel /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { - if (dispose) - { - DisposeTcpManager(); - } - } - /// - /// Disposes the TCP manager. - /// - private void DisposeTcpManager() - { - if (TcpManager != null) - { - TcpManager.Dispose(); - TcpManager = null; - } } /// @@ -424,8 +382,8 @@ namespace MediaBrowser.Common.Kernel HasPendingRestart = HasPendingRestart, Version = ApplicationHost.ApplicationVersion.ToString(), IsNetworkDeployed = ApplicationHost.CanSelfUpdate, - WebSocketPortNumber = TcpManager.WebSocketPortNumber, - SupportsNativeWebSocket = TcpManager.SupportsNativeWebSocket, + WebSocketPortNumber = ServerManager.WebSocketPortNumber, + SupportsNativeWebSocket = ServerManager.SupportsNativeWebSocket, FailedPluginAssemblies = ApplicationHost.FailedAssemblies.ToArray() }; } diff --git a/MediaBrowser.Common/Kernel/BasePeriodicWebSocketListener.cs b/MediaBrowser.Common/Kernel/BasePeriodicWebSocketListener.cs index 5374bb7140..6a44cf3728 100644 --- a/MediaBrowser.Common/Kernel/BasePeriodicWebSocketListener.cs +++ b/MediaBrowser.Common/Kernel/BasePeriodicWebSocketListener.cs @@ -19,8 +19,8 @@ namespace MediaBrowser.Common.Kernel /// /// The _active connections /// - protected readonly List> ActiveConnections = - new List>(); + protected readonly List> ActiveConnections = + new List>(); /// /// Gets the name. @@ -103,7 +103,7 @@ namespace MediaBrowser.Common.Kernel lock (ActiveConnections) { - ActiveConnections.Add(new Tuple(message.Connection, cancellationTokenSource, timer, state, semaphore)); + ActiveConnections.Add(new Tuple(message.Connection, cancellationTokenSource, timer, state, semaphore)); } timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs)); @@ -115,9 +115,9 @@ namespace MediaBrowser.Common.Kernel /// The state. private async void TimerCallback(object state) { - var connection = (WebSocketConnection)state; + var connection = (IWebSocketConnection)state; - Tuple tuple; + Tuple tuple; lock (ActiveConnections) { @@ -187,7 +187,7 @@ namespace MediaBrowser.Common.Kernel /// Disposes the connection. /// /// The connection. - private void DisposeConnection(Tuple connection) + private void DisposeConnection(Tuple connection) { Logger.Info("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name); diff --git a/MediaBrowser.Common/Kernel/IApplicationHost.cs b/MediaBrowser.Common/Kernel/IApplicationHost.cs index af9b039bc0..1f99d10dbc 100644 --- a/MediaBrowser.Common/Kernel/IApplicationHost.cs +++ b/MediaBrowser.Common/Kernel/IApplicationHost.cs @@ -97,5 +97,10 @@ namespace MediaBrowser.Common.Kernel /// /// ``0. T TryResolve(); + + /// + /// Shuts down. + /// + void Shutdown(); } } diff --git a/MediaBrowser.Common/Kernel/IKernel.cs b/MediaBrowser.Common/Kernel/IKernel.cs index 06c2e7b64c..a28500eca7 100644 --- a/MediaBrowser.Common/Kernel/IKernel.cs +++ b/MediaBrowser.Common/Kernel/IKernel.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Plugins; +using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.System; using System; @@ -71,12 +70,6 @@ namespace MediaBrowser.Common.Kernel /// The name of the web application. string WebApplicationName { get; } - /// - /// Gets the log file path. - /// - /// The log file path. - string LogFilePath { get; } - /// /// Performs the pending restart. /// @@ -104,7 +97,7 @@ namespace MediaBrowser.Common.Kernel /// Gets the TCP manager. /// /// The TCP manager. - TcpManager TcpManager { get; } + IServerManager ServerManager { get; } /// /// Gets the web socket listeners. diff --git a/MediaBrowser.Common/Kernel/IServerManager.cs b/MediaBrowser.Common/Kernel/IServerManager.cs new file mode 100644 index 0000000000..cfea6eee11 --- /dev/null +++ b/MediaBrowser.Common/Kernel/IServerManager.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Common.Kernel +{ + public interface IServerManager : IDisposable + { + /// + /// Gets a value indicating whether [supports web socket]. + /// + /// true if [supports web socket]; otherwise, false. + bool SupportsNativeWebSocket { get; } + + /// + /// Gets the web socket port number. + /// + /// The web socket port number. + int WebSocketPortNumber { get; } + + /// + /// Starts this instance. + /// + void Start(); + + /// + /// Sends a message to all clients currently connected via a web socket + /// + /// + /// Type of the message. + /// The data. + /// Task. + void SendWebSocketMessage(string messageType, T data); + + /// + /// Sends a message to all clients currently connected via a web socket + /// + /// + /// Type of the message. + /// The function that generates the data to send, if there are any connected clients + void SendWebSocketMessage(string messageType, Func dataFunction); + + /// + /// Sends a message to all clients currently connected via a web socket + /// + /// + /// Type of the message. + /// The function that generates the data to send, if there are any connected clients + /// The cancellation token. + /// Task. + /// messageType + Task SendWebSocketMessageAsync(string messageType, Func dataFunction, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 333c20beb7..b136eb43c5 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -91,10 +91,10 @@ + - @@ -103,12 +103,12 @@ + - @@ -138,7 +138,6 @@ - diff --git a/MediaBrowser.Common/Net/IWebSocketConnection.cs b/MediaBrowser.Common/Net/IWebSocketConnection.cs new file mode 100644 index 0000000000..8e1b13ceb9 --- /dev/null +++ b/MediaBrowser.Common/Net/IWebSocketConnection.cs @@ -0,0 +1,85 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Common.Net +{ + public interface IWebSocketConnection : IDisposable + { + /// + /// Gets or sets the receive action. + /// + /// The receive action. + Action OnReceive { get; set; } + + /// + /// Gets the state. + /// + /// The state. + WebSocketState State { get; } + + /// + /// Gets the remote end point. + /// + /// The remote end point. + string RemoteEndPoint { get; } + + /// + /// Sends a message asynchronously. + /// + /// + /// The message. + /// The cancellation token. + /// Task. + /// message + Task SendAsync(WebSocketMessage message, CancellationToken cancellationToken); + + /// + /// Sends a message asynchronously. + /// + /// The buffer. + /// The cancellation token. + /// Task. + Task SendAsync(byte[] buffer, CancellationToken cancellationToken); + + /// + /// Sends a message asynchronously. + /// + /// The buffer. + /// The type. + /// The cancellation token. + /// Task. + /// buffer + Task SendAsync(byte[] buffer, WebSocketMessageType type, CancellationToken cancellationToken); + } + + /// + /// Class WebSocketMessage + /// + /// + public class WebSocketMessage + { + /// + /// Gets or sets the type of the message. + /// + /// The type of the message. + public string MessageType { get; set; } + /// + /// Gets or sets the data. + /// + /// The data. + public T Data { get; set; } + } + + /// + /// Class WebSocketMessageInfo + /// + public class WebSocketMessageInfo : WebSocketMessage + { + /// + /// Gets or sets the connection. + /// + /// The connection. + public IWebSocketConnection Connection { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Common/Net/IWebSocketServer.cs b/MediaBrowser.Common/Net/IWebSocketServer.cs index 5ce571fbb8..187e03e09f 100644 --- a/MediaBrowser.Common/Net/IWebSocketServer.cs +++ b/MediaBrowser.Common/Net/IWebSocketServer.cs @@ -22,5 +22,11 @@ namespace MediaBrowser.Common.Net /// Occurs when [web socket connected]. /// event EventHandler WebSocketConnected; + + /// + /// Gets the port. + /// + /// The port. + int Port { get; } } } diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index d879b888b5..ed49d26d86 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Playback; using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Controller.ScheduledTasks; using MediaBrowser.Controller.Updates; using MediaBrowser.Controller.Weather; using MediaBrowser.Model.Configuration; @@ -293,8 +292,6 @@ namespace MediaBrowser.Controller get { return 7359; } } - private readonly ITaskManager _taskManager; - /// /// Creates a kernel based on a Data path, which is akin to our current programdata path /// @@ -304,13 +301,11 @@ namespace MediaBrowser.Controller /// The task manager. /// The logger. /// isoManager - public Kernel(IApplicationHost appHost, IServerApplicationPaths appPaths, IXmlSerializer xmlSerializer, ITaskManager taskManager, ILogger logger) + public Kernel(IApplicationHost appHost, IServerApplicationPaths appPaths, IXmlSerializer xmlSerializer, ILogger logger) : base(appHost, appPaths, xmlSerializer, logger) { Instance = this; - _taskManager = taskManager; - // For now there's no real way to inject this properly BaseItem.Logger = logger; Ratings.Logger = logger; @@ -469,7 +464,7 @@ namespace MediaBrowser.Controller { DisposeFileSystemManager(); - FileSystemManager = new FileSystemManager(this, Logger, _taskManager); + FileSystemManager = new FileSystemManager(this, Logger, ApplicationHost.Resolve()); FileSystemManager.StartWatchers(); } @@ -540,18 +535,6 @@ namespace MediaBrowser.Controller var reloadLogger = config.ShowLogWindow != oldConfiguration.ShowLogWindow; - // Figure out whether or not we should refresh people after the update is finished - var refreshPeopleAfterUpdate = !oldConfiguration.EnableInternetProviders && config.EnableInternetProviders; - - // This is true if internet providers has just been turned on, or if People have just been removed from InternetProviderExcludeTypes - if (!refreshPeopleAfterUpdate) - { - var oldConfigurationFetchesPeopleImages = oldConfiguration.InternetProviderExcludeTypes == null || !oldConfiguration.InternetProviderExcludeTypes.Contains(typeof(Person).Name, StringComparer.OrdinalIgnoreCase); - var newConfigurationFetchesPeopleImages = config.InternetProviderExcludeTypes == null || !config.InternetProviderExcludeTypes.Contains(typeof(Person).Name, StringComparer.OrdinalIgnoreCase); - - refreshPeopleAfterUpdate = newConfigurationFetchesPeopleImages && !oldConfigurationFetchesPeopleImages; - } - Configuration = config; SaveConfiguration(); @@ -560,20 +543,10 @@ namespace MediaBrowser.Controller ReloadLogger(); } - TcpManager.OnApplicationConfigurationChanged(oldConfiguration, config); - // Validate currently executing providers, in the background Task.Run(() => { ProviderManager.ValidateCurrentlyRunningProviders(); - - // Any number of configuration settings could change the way the library is refreshed, so do that now - _taskManager.CancelIfRunningAndQueue(); - - if (refreshPeopleAfterUpdate) - { - _taskManager.CancelIfRunningAndQueue(); - } }); } diff --git a/MediaBrowser.Controller/Library/LibraryManager.cs b/MediaBrowser.Controller/Library/LibraryManager.cs index c0c1fe1d6e..53f4af4b22 100644 --- a/MediaBrowser.Controller/Library/LibraryManager.cs +++ b/MediaBrowser.Controller/Library/LibraryManager.cs @@ -1,8 +1,10 @@ using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Resolvers; +using MediaBrowser.Controller.ScheduledTasks; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MoreLinq; @@ -20,7 +22,7 @@ namespace MediaBrowser.Controller.Library /// /// Class LibraryManager /// - public class LibraryManager : BaseManager + public class LibraryManager { #region LibraryChanged Event /// @@ -48,7 +50,7 @@ namespace MediaBrowser.Controller.Library private void SendLibraryChangedWebSocketMessage(ChildrenChangedEventArgs args) { // Notify connected ui's - Kernel.TcpManager.SendWebSocketMessage("LibraryChanged", () => DtoBuilder.GetLibraryUpdateInfo(args)); + Kernel.ServerManager.SendWebSocketMessage("LibraryChanged", () => DtoBuilder.GetLibraryUpdateInfo(args)); } #endregion @@ -57,15 +59,57 @@ namespace MediaBrowser.Controller.Library /// private readonly ILogger _logger; + /// + /// The _task manager + /// + private readonly ITaskManager _taskManager; + + /// + /// Gets or sets the kernel. + /// + /// The kernel. + private Kernel Kernel { get; set; } + /// /// Initializes a new instance of the class. /// /// The kernel. /// The logger. - public LibraryManager(Kernel kernel, ILogger logger) - : base(kernel) + /// The task manager. + public LibraryManager(Kernel kernel, ILogger logger, ITaskManager taskManager) { + Kernel = kernel; _logger = logger; + _taskManager = taskManager; + + kernel.ConfigurationUpdated += kernel_ConfigurationUpdated; + } + + /// + /// Handles the ConfigurationUpdated event of the kernel control. + /// + /// The source of the event. + /// The instance containing the event data. + void kernel_ConfigurationUpdated(object sender, EventArgs e) + { + //// Figure out whether or not we should refresh people after the update is finished + //var refreshPeopleAfterUpdate = !oldConfiguration.EnableInternetProviders && config.EnableInternetProviders; + + //// This is true if internet providers has just been turned on, or if People have just been removed from InternetProviderExcludeTypes + //if (!refreshPeopleAfterUpdate) + //{ + // var oldConfigurationFetchesPeopleImages = oldConfiguration.InternetProviderExcludeTypes == null || !oldConfiguration.InternetProviderExcludeTypes.Contains(typeof(Person).Name, StringComparer.OrdinalIgnoreCase); + // var newConfigurationFetchesPeopleImages = config.InternetProviderExcludeTypes == null || !config.InternetProviderExcludeTypes.Contains(typeof(Person).Name, StringComparer.OrdinalIgnoreCase); + + // refreshPeopleAfterUpdate = newConfigurationFetchesPeopleImages && !oldConfigurationFetchesPeopleImages; + //} + + Task.Run(() => + { + // Any number of configuration settings could change the way the library is refreshed, so do that now + _taskManager.CancelIfRunningAndQueue(); + _taskManager.CancelIfRunningAndQueue(); + }); } /// diff --git a/MediaBrowser.Controller/Library/UserManager.cs b/MediaBrowser.Controller/Library/UserManager.cs index 8084366b7e..5340e70bef 100644 --- a/MediaBrowser.Controller/Library/UserManager.cs +++ b/MediaBrowser.Controller/Library/UserManager.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Library EventHelper.QueueEventIfNotNull(UserUpdated, this, new GenericEventArgs { Argument = user }, _logger); // Notify connected ui's - Kernel.TcpManager.SendWebSocketMessage("UserUpdated", new DtoBuilder(_logger).GetDtoUser(user)); + Kernel.ServerManager.SendWebSocketMessage("UserUpdated", new DtoBuilder(_logger).GetDtoUser(user)); } #endregion @@ -91,7 +91,7 @@ namespace MediaBrowser.Controller.Library EventHelper.QueueEventIfNotNull(UserDeleted, this, new GenericEventArgs { Argument = user }, _logger); // Notify connected ui's - Kernel.TcpManager.SendWebSocketMessage("UserDeleted", user.Id.ToString()); + Kernel.ServerManager.SendWebSocketMessage("UserDeleted", user.Id.ToString()); } #endregion diff --git a/MediaBrowser.Controller/Updates/InstallationManager.cs b/MediaBrowser.Controller/Updates/InstallationManager.cs index 8751bd4274..efef87f863 100644 --- a/MediaBrowser.Controller/Updates/InstallationManager.cs +++ b/MediaBrowser.Controller/Updates/InstallationManager.cs @@ -49,7 +49,7 @@ namespace MediaBrowser.Controller.Updates EventHelper.QueueEventIfNotNull(PluginUninstalled, this, new GenericEventArgs { Argument = plugin }, _logger); // Notify connected ui's - Kernel.TcpManager.SendWebSocketMessage("PluginUninstalled", plugin.GetPluginInfo()); + Kernel.ServerManager.SendWebSocketMessage("PluginUninstalled", plugin.GetPluginInfo()); } #endregion @@ -371,7 +371,7 @@ namespace MediaBrowser.Controller.Updates var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, innerCancellationTokenSource.Token).Token; - Kernel.TcpManager.SendWebSocketMessage("PackageInstalling", installationInfo); + Kernel.ServerManager.SendWebSocketMessage("PackageInstalling", installationInfo); try { @@ -384,7 +384,7 @@ namespace MediaBrowser.Controller.Updates CompletedInstallations.Add(installationInfo); - Kernel.TcpManager.SendWebSocketMessage("PackageInstallationCompleted", installationInfo); + Kernel.ServerManager.SendWebSocketMessage("PackageInstallationCompleted", installationInfo); } catch (OperationCanceledException) { @@ -395,7 +395,7 @@ namespace MediaBrowser.Controller.Updates _logger.Info("Package installation cancelled: {0} {1}", package.name, package.versionStr); - Kernel.TcpManager.SendWebSocketMessage("PackageInstallationCancelled", installationInfo); + Kernel.ServerManager.SendWebSocketMessage("PackageInstallationCancelled", installationInfo); throw; } @@ -406,7 +406,7 @@ namespace MediaBrowser.Controller.Updates CurrentInstallations.Remove(tuple); } - Kernel.TcpManager.SendWebSocketMessage("PackageInstallationFailed", installationInfo); + Kernel.ServerManager.SendWebSocketMessage("PackageInstallationFailed", installationInfo); throw; } diff --git a/MediaBrowser.Networking/Udp/UdpServer.cs b/MediaBrowser.Networking/Udp/UdpServer.cs index 9b1c254cfe..00eb2a0d13 100644 --- a/MediaBrowser.Networking/Udp/UdpServer.cs +++ b/MediaBrowser.Networking/Udp/UdpServer.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Net; +using MediaBrowser.Model.Logging; using MediaBrowser.Networking.Management; using System; using System.Net; @@ -19,6 +20,21 @@ namespace MediaBrowser.Networking.Udp /// public event EventHandler MessageReceived; + /// + /// Gets or sets the logger. + /// + /// The logger. + private ILogger Logger { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + public UdpServer(ILogger logger) + { + Logger = logger; + } + /// /// Raises the event. /// @@ -54,8 +70,24 @@ namespace MediaBrowser.Networking.Udp private IObservable CreateObservable() { return Observable.Create(obs => - Observable.FromAsync(() => _udpClient.ReceiveAsync()) - .Subscribe(obs)) + Observable.FromAsync(() => + { + try + { + return _udpClient.ReceiveAsync(); + } + catch (ObjectDisposedException) + { + return Task.FromResult(new UdpReceiveResult(new byte[]{}, new IPEndPoint(IPAddress.Any, 0))); + } + catch (Exception ex) + { + Logger.ErrorException("Error receiving udp message", ex); + return Task.FromResult(new UdpReceiveResult(new byte[] { }, new IPEndPoint(IPAddress.Any, 0))); + } + }) + + .Subscribe(obs)) .Repeat() .Retry() .Publish() @@ -68,6 +100,10 @@ namespace MediaBrowser.Networking.Udp /// The message. private void OnMessageReceived(UdpReceiveResult message) { + if (message.RemoteEndPoint.Port == 0) + { + return; + } var bytes = message.Buffer; OnMessageReceived(new UdpMessageReceivedEventArgs diff --git a/MediaBrowser.Networking/WebSocket/AlchemyServer.cs b/MediaBrowser.Networking/WebSocket/AlchemyServer.cs index 1a3971c7fc..b3d5d710ec 100644 --- a/MediaBrowser.Networking/WebSocket/AlchemyServer.cs +++ b/MediaBrowser.Networking/WebSocket/AlchemyServer.cs @@ -42,6 +42,12 @@ namespace MediaBrowser.Networking.WebSocket _logger = logger; } + /// + /// Gets the port. + /// + /// The port. + public int Port { get; private set; } + /// /// Starts the specified port number. /// @@ -56,6 +62,8 @@ namespace MediaBrowser.Networking.WebSocket WebSocketServer.Start(); + Port = portNumber; + _logger.Info("Alchemy Web Socket Server started"); } diff --git a/MediaBrowser.ServerApplication/App.xaml.cs b/MediaBrowser.ServerApplication/App.xaml.cs index f6f70b382e..1199aeaf12 100644 --- a/MediaBrowser.ServerApplication/App.xaml.cs +++ b/MediaBrowser.ServerApplication/App.xaml.cs @@ -255,7 +255,6 @@ namespace MediaBrowser.ServerApplication base.OnExit(e); - Kernel.Dispose(); CompositionRoot.Dispose(); } @@ -360,7 +359,7 @@ namespace MediaBrowser.ServerApplication { Dispatcher.Invoke(ReleaseMutex); - Kernel.Dispose(); + CompositionRoot.Dispose(); System.Windows.Forms.Application.Restart(); diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index e862a394e5..07246eded6 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -4,6 +4,7 @@ using MediaBrowser.Common.Implementations; using MediaBrowser.Common.Implementations.ScheduledTasks; using MediaBrowser.Common.Implementations.Serialization; using MediaBrowser.Common.IO; +using MediaBrowser.Common.Implementations.Server; using MediaBrowser.Common.Kernel; using MediaBrowser.Common.Net; using MediaBrowser.Common.ScheduledTasks; @@ -65,16 +66,6 @@ namespace MediaBrowser.ServerApplication /// private readonly IServerApplicationPaths _applicationPaths = new ServerApplicationPaths(); - /// - /// The _task manager - /// - private readonly ITaskManager _taskManager; - - /// - /// The _task manager - /// - private readonly IHttpServer _httpServer; - /// /// Gets a value indicating whether this instance is first run. /// @@ -89,29 +80,34 @@ namespace MediaBrowser.ServerApplication : base() { IsFirstRun = !File.Exists(_applicationPaths.SystemConfigurationFilePath); - + Logger = new NLogger("App"); DiscoverTypes(); - _taskManager = new TaskManager(_applicationPaths, _jsonSerializer, Logger); + Kernel = new Kernel(this, _applicationPaths, _xmlSerializer, Logger); + + var networkManager = new NetworkManager(); + + var serverManager = new ServerManager(this, Kernel, networkManager, _jsonSerializer, Logger); + + var taskManager = new TaskManager(_applicationPaths, _jsonSerializer, Logger, serverManager); - Kernel = new Kernel(this, _applicationPaths, _xmlSerializer, _taskManager, Logger); ReloadLogger(); Logger.Info("Version {0} initializing", ApplicationVersion); - _httpServer = ServerFactory.CreateServer(this, ProtobufSerializer, Logger, "Media Browser", "index.html"); + var httpServer = ServerFactory.CreateServer(this, ProtobufSerializer, Logger, "Media Browser", "index.html"); - RegisterResources(); + RegisterResources(taskManager, httpServer, networkManager, serverManager); - FindParts(); + FindParts(taskManager, httpServer); } /// /// Registers resources that classes will depend on /// - private void RegisterResources() + private void RegisterResources(ITaskManager taskManager, IHttpServer httpServer, INetworkManager networkManager, IServerManager serverManager) { RegisterSingleInstance(Kernel); RegisterSingleInstance(Kernel); @@ -121,28 +117,31 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance(_applicationPaths); RegisterSingleInstance(_applicationPaths); - RegisterSingleInstance(_taskManager); + RegisterSingleInstance(taskManager); RegisterSingleInstance(new PismoIsoManager(Logger)); RegisterSingleInstance(new BdInfoExaminer()); RegisterSingleInstance(new HttpManager(_applicationPaths, Logger)); - RegisterSingleInstance(new NetworkManager()); RegisterSingleInstance(new DotNetZipClient()); RegisterSingleInstance(() => new AlchemyServer(Logger)); RegisterSingleInstance(_jsonSerializer); RegisterSingleInstance(_xmlSerializer); RegisterSingleInstance(ProtobufSerializer); - RegisterSingleInstance(new UdpServer()); - RegisterSingleInstance(_httpServer); + RegisterSingleInstance(new UdpServer(Logger), false); + RegisterSingleInstance(httpServer, false); + + RegisterSingleInstance(networkManager); + + RegisterSingleInstance(serverManager); } /// /// Finds the parts. /// - private void FindParts() + private void FindParts(ITaskManager taskManager, IHttpServer httpServer) { - _taskManager.AddTasks(GetExports(false)); + taskManager.AddTasks(GetExports(false)); - _httpServer.Init(GetExports(false)); + httpServer.Init(GetExports(false)); } /// @@ -240,5 +239,13 @@ namespace MediaBrowser.ServerApplication // Include composable parts in the running assembly yield return GetType().Assembly; } + + /// + /// Shuts down. + /// + public void Shutdown() + { + App.Instance.Shutdown(); + } } } diff --git a/MediaBrowser.WebDashboard/Html/css/site.css b/MediaBrowser.WebDashboard/Html/css/site.css index 32818e3ccc..3e32d4e1fc 100644 --- a/MediaBrowser.WebDashboard/Html/css/site.css +++ b/MediaBrowser.WebDashboard/Html/css/site.css @@ -293,10 +293,6 @@ form, .readOnlyContent { right: 30px; } - .localnav .ui-btn-inner { - font-size: 16px; - } - .libraryPage .ui-content { padding-right: 50px; padding-left: 50px; diff --git a/Nuget/MediaBrowser.ApiClient.nuspec b/Nuget/MediaBrowser.ApiClient.nuspec index 3d6ec3a31c..a13bfd84c7 100644 --- a/Nuget/MediaBrowser.ApiClient.nuspec +++ b/Nuget/MediaBrowser.ApiClient.nuspec @@ -2,7 +2,7 @@ MediaBrowser.ApiClient - 3.0.0.6-beta + 3.0.0.7-beta MediaBrowser.ApiClient Media Browser Team scottisafool,Luke diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 6fc5414b66..d215e503bd 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.6 + 3.0.7 <authors>Luke</authors> <owners>Media Browser Team</owners> @@ -10,7 +10,7 @@ <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>Contains common components shared by Media Browser Theatre and Media Browser Server. Not intended for plugin developer consumption.</description> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.6" /> + <dependency id="MediaBrowser.Common" version="3.0.7" /> <dependency id="NLog" version="2.0.0.2000" /> <dependency id="ServiceStack" version="3.9.37" /> <dependency id="ServiceStack.Api.Swagger" version="3.9.35" /> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 1044fd6330..c529f29a3d 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.6</version> + <version>3.0.7</version> <title>MediaBrowser.Common Media Browser Team diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index b152a5d3eb..d07345f091 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.6 + 3.0.7 Media Browser.Server.Core Media Browser Team @@ -10,7 +10,7 @@ false Contains core components required to build plugins for Media Browser Server. - +