diff options
27 files changed, 487 insertions, 534 deletions
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index cf2a55695..97c399fbe 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -97,6 +97,7 @@ <Compile Include="PluginService.cs" /> <Compile Include="ScheduledTasks\ScheduledTaskService.cs" /> <Compile Include="ScheduledTasks\ScheduledTasksWebSocketListener.cs" /> + <Compile Include="ServerEntryPoint.cs" /> <Compile Include="SystemService.cs" /> <Compile Include="UserLibrary\BaseItemsByNameService.cs" /> <Compile Include="UserLibrary\GenresService.cs" /> diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index ce9fe0e0b..980856410 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -518,7 +518,7 @@ namespace MediaBrowser.Api.Playback EnableRaisingEvents = true }; - Plugin.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process); + ServerEntryPoint.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process); //Logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments); @@ -537,7 +537,7 @@ namespace MediaBrowser.Api.Playback { Logger.ErrorException("Error starting ffmpeg", ex); - Plugin.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType); + ServerEntryPoint.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType); state.LogFileStream.Dispose(); @@ -588,7 +588,7 @@ namespace MediaBrowser.Api.Playback process.Dispose(); - Plugin.Instance.OnTranscodingFinished(outputFilePath, TranscodingJobType); + ServerEntryPoint.Instance.OnTranscodingFinished(outputFilePath, TranscodingJobType); if (!exitCode.HasValue || exitCode.Value != 0) { diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 8c7edbe91..d616565ca 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Api.Playback.Hls } else { - Plugin.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType.Hls); + ServerEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType.Hls); } // Get the current playlist text and convert to bytes @@ -94,7 +94,7 @@ namespace MediaBrowser.Api.Playback.Hls } finally { - Plugin.Instance.OnTranscodeEndRequest(playlist, TranscodingJobType.Hls); + ServerEntryPoint.Instance.OnTranscodeEndRequest(playlist, TranscodingJobType.Hls); } } diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 08e66c387..bbfe65504 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -107,7 +107,7 @@ namespace MediaBrowser.Api.Playback.Progressive var outputPath = GetOutputFilePath(state); - if (File.Exists(outputPath) && !Plugin.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive)) + if (File.Exists(outputPath) && !ServerEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive)) { return ToStaticFileResult(outputPath); } @@ -133,7 +133,7 @@ namespace MediaBrowser.Api.Playback.Progressive } else { - Plugin.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive); + ServerEntryPoint.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive); } return new ProgressiveStreamWriter diff --git a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs index 9ac93694b..b6b73c78d 100644 --- a/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs +++ b/MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs @@ -41,7 +41,7 @@ namespace MediaBrowser.Api.Playback.Progressive } finally { - Plugin.Instance.OnTranscodeEndRequest(Path, TranscodingJobType.Progressive); + ServerEntryPoint.Instance.OnTranscodeEndRequest(Path, TranscodingJobType.Progressive); } } diff --git a/MediaBrowser.Api/Plugin.cs b/MediaBrowser.Api/Plugin.cs index 58c0ffcfa..b8c81bbe1 100644 --- a/MediaBrowser.Api/Plugin.cs +++ b/MediaBrowser.Api/Plugin.cs @@ -1,12 +1,7 @@ -using MediaBrowser.Common.Plugins; +using MediaBrowser.Common.Kernel; +using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Plugins; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Api { @@ -16,6 +11,16 @@ namespace MediaBrowser.Api public class Plugin : BasePlugin<BasePluginConfiguration> { /// <summary> + /// Initializes a new instance of the <see cref="Plugin" /> class. + /// </summary> + /// <param name="kernel">The kernel.</param> + /// <param name="xmlSerializer">The XML serializer.</param> + public Plugin(IKernel kernel, IXmlSerializer xmlSerializer) : base(kernel, xmlSerializer) + { + Instance = this; + } + + /// <summary> /// Gets the name of the plugin /// </summary> /// <value>The name.</value> @@ -41,287 +46,5 @@ namespace MediaBrowser.Api /// </summary> /// <value>The instance.</value> public static Plugin Instance { get; private set; } - - /// <summary> - /// Initializes a new instance of the <see cref="Plugin" /> class. - /// </summary> - public Plugin() - { - Instance = 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 DisposeOnServer(bool dispose) - { - if (dispose) - { - var jobCount = ActiveTranscodingJobs.Count; - - Parallel.ForEach(ActiveTranscodingJobs, OnTranscodeKillTimerStopped); - - // Try to allow for some time to kill the ffmpeg processes and delete the partial stream files - if (jobCount > 0) - { - Thread.Sleep(1000); - } - } - - base.DisposeOnServer(dispose); - } - - /// <summary> - /// The active transcoding jobs - /// </summary> - private readonly List<TranscodingJob> ActiveTranscodingJobs = new List<TranscodingJob>(); - - /// <summary> - /// Called when [transcode beginning]. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="type">The type.</param> - /// <param name="process">The process.</param> - public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process) - { - lock (ActiveTranscodingJobs) - { - ActiveTranscodingJobs.Add(new TranscodingJob - { - Type = type, - Path = path, - Process = process, - ActiveRequestCount = 1 - }); - } - } - - /// <summary> - /// Called when [transcode failed to start]. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="type">The type.</param> - public void OnTranscodeFailedToStart(string path, TranscodingJobType type) - { - lock (ActiveTranscodingJobs) - { - var job = ActiveTranscodingJobs.First(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); - - ActiveTranscodingJobs.Remove(job); - } - } - - /// <summary> - /// Determines whether [has active transcoding job] [the specified path]. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="type">The type.</param> - /// <returns><c>true</c> if [has active transcoding job] [the specified path]; otherwise, <c>false</c>.</returns> - public bool HasActiveTranscodingJob(string path, TranscodingJobType type) - { - lock (ActiveTranscodingJobs) - { - return ActiveTranscodingJobs.Any(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); - } - } - - /// <summary> - /// Called when [transcode begin request]. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="type">The type.</param> - public void OnTranscodeBeginRequest(string path, TranscodingJobType type) - { - lock (ActiveTranscodingJobs) - { - var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); - - if (job == null) - { - return; - } - - job.ActiveRequestCount++; - - if (job.KillTimer != null) - { - job.KillTimer.Dispose(); - job.KillTimer = null; - } - } - } - - /// <summary> - /// Called when [transcode end request]. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="type">The type.</param> - public void OnTranscodeEndRequest(string path, TranscodingJobType type) - { - lock (ActiveTranscodingJobs) - { - var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); - - if (job == null) - { - return; - } - - job.ActiveRequestCount--; - - if (job.ActiveRequestCount == 0) - { - var timerDuration = type == TranscodingJobType.Progressive ? 1000 : 30000; - - if (job.KillTimer == null) - { - job.KillTimer = new Timer(OnTranscodeKillTimerStopped, job, timerDuration, Timeout.Infinite); - } - else - { - job.KillTimer.Change(timerDuration, Timeout.Infinite); - } - } - } - } - - /// <summary> - /// Called when [transcoding finished]. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="type">The type.</param> - public void OnTranscodingFinished(string path, TranscodingJobType type) - { - lock (ActiveTranscodingJobs) - { - var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); - - if (job == null) - { - return; - } - - ActiveTranscodingJobs.Remove(job); - - if (job.KillTimer != null) - { - job.KillTimer.Dispose(); - job.KillTimer = null; - } - } - } - - /// <summary> - /// Called when [transcode kill timer stopped]. - /// </summary> - /// <param name="state">The state.</param> - private void OnTranscodeKillTimerStopped(object state) - { - var job = (TranscodingJob)state; - - lock (ActiveTranscodingJobs) - { - ActiveTranscodingJobs.Remove(job); - - if (job.KillTimer != null) - { - job.KillTimer.Dispose(); - job.KillTimer = null; - } - } - - var process = job.Process; - - var hasExited = true; - - try - { - hasExited = process.HasExited; - } - catch (Win32Exception ex) - { - Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path); - } - catch (InvalidOperationException ex) - { - Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path); - } - catch (NotSupportedException ex) - { - Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path); - } - - if (hasExited) - { - return; - } - - try - { - Logger.Info("Killing ffmpeg process for {0}", job.Path); - - process.Kill(); - } - catch (Win32Exception ex) - { - Logger.ErrorException("Error killing transcoding job for {0}", ex, job.Path); - } - catch (InvalidOperationException ex) - { - Logger.ErrorException("Error killing transcoding job for {0}", ex, job.Path); - } - catch (NotSupportedException ex) - { - Logger.ErrorException("Error killing transcoding job for {0}", ex, job.Path); - } - } - } - - /// <summary> - /// Class TranscodingJob - /// </summary> - public class TranscodingJob - { - /// <summary> - /// Gets or sets the path. - /// </summary> - /// <value>The path.</value> - public string Path { get; set; } - /// <summary> - /// Gets or sets the type. - /// </summary> - /// <value>The type.</value> - public TranscodingJobType Type { get; set; } - /// <summary> - /// Gets or sets the process. - /// </summary> - /// <value>The process.</value> - public Process Process { get; set; } - /// <summary> - /// Gets or sets the active request count. - /// </summary> - /// <value>The active request count.</value> - public int ActiveRequestCount { get; set; } - /// <summary> - /// Gets or sets the kill timer. - /// </summary> - /// <value>The kill timer.</value> - public Timer KillTimer { get; set; } - } - - /// <summary> - /// Enum TranscodingJobType - /// </summary> - public enum TranscodingJobType - { - /// <summary> - /// The progressive - /// </summary> - Progressive, - /// <summary> - /// The HLS - /// </summary> - Hls } } diff --git a/MediaBrowser.Api/PluginService.cs b/MediaBrowser.Api/PluginService.cs index 06db7a276..7e907c2dd 100644 --- a/MediaBrowser.Api/PluginService.cs +++ b/MediaBrowser.Api/PluginService.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Implementations.HttpServer; +using MediaBrowser.Common.Kernel; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Plugins; @@ -124,11 +125,17 @@ namespace MediaBrowser.Api private readonly IJsonSerializer _jsonSerializer; /// <summary> + /// The _app host + /// </summary> + private readonly IApplicationHost _appHost; + + /// <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> /// <exception cref="System.ArgumentNullException">jsonSerializer</exception> - public PluginService(IJsonSerializer jsonSerializer) + public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost) : base() { if (jsonSerializer == null) @@ -136,6 +143,7 @@ namespace MediaBrowser.Api throw new ArgumentNullException("jsonSerializer"); } + _appHost = appHost; _jsonSerializer = jsonSerializer; } @@ -146,7 +154,7 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetPlugins request) { - var result = Kernel.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToList(); + var result = _appHost.Plugins.OrderBy(p => p.Name).Select(p => p.GetPluginInfo()).ToList(); return ToOptimizedResult(result); } @@ -158,7 +166,7 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetPluginAssembly request) { - var plugin = Kernel.Plugins.First(p => p.Id == request.Id); + var plugin = _appHost.Plugins.First(p => p.Id == request.Id); return ToStaticFileResult(plugin.AssemblyFilePath); } @@ -170,7 +178,7 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetPluginConfiguration request) { - var plugin = Kernel.Plugins.First(p => p.Id == request.Id); + var plugin = _appHost.Plugins.First(p => p.Id == request.Id); var dateModified = plugin.ConfigurationDateLastModified; @@ -186,7 +194,7 @@ namespace MediaBrowser.Api /// <returns>System.Object.</returns> public object Get(GetPluginConfigurationFile request) { - var plugin = Kernel.Plugins.First(p => p.Id == request.Id); + var plugin = _appHost.Plugins.First(p => p.Id == request.Id); return ToStaticFileResult(plugin.ConfigurationFilePath); } @@ -235,7 +243,7 @@ namespace MediaBrowser.Api var pathInfo = PathInfo.Parse(Request.PathInfo); var id = new Guid(pathInfo.GetArgumentValue<string>(1)); - var plugin = Kernel.Plugins.First(p => p.Id == id); + var plugin = _appHost.Plugins.First(p => p.Id == id); var configuration = _jsonSerializer.DeserializeFromStream(request.RequestStream, plugin.ConfigurationType) as BasePluginConfiguration; @@ -250,7 +258,7 @@ namespace MediaBrowser.Api { var kernel = (Kernel)Kernel; - var plugin = kernel.Plugins.First(p => p.Id == request.Id); + var plugin = _appHost.Plugins.First(p => p.Id == request.Id); kernel.InstallationManager.UninstallPlugin(plugin); } diff --git a/MediaBrowser.Api/ServerEntryPoint.cs b/MediaBrowser.Api/ServerEntryPoint.cs new file mode 100644 index 000000000..663d1aeca --- /dev/null +++ b/MediaBrowser.Api/ServerEntryPoint.cs @@ -0,0 +1,333 @@ +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Api +{ + /// <summary> + /// Class ServerEntryPoint + /// </summary> + public class ServerEntryPoint : IServerEntryPoint + { + /// <summary> + /// The instance + /// </summary> + public static ServerEntryPoint Instance; + + /// <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="ServerEntryPoint" /> class. + /// </summary> + /// <param name="logger">The logger.</param> + public ServerEntryPoint(ILogger logger) + { + Logger = logger; + + Instance = this; + } + + /// <summary> + /// Runs this instance. + /// </summary> + public void Run() + { + } + + /// <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) + { + var jobCount = ActiveTranscodingJobs.Count; + + Parallel.ForEach(ActiveTranscodingJobs, OnTranscodeKillTimerStopped); + + // Try to allow for some time to kill the ffmpeg processes and delete the partial stream files + if (jobCount > 0) + { + Thread.Sleep(1000); + } + } + + /// <summary> + /// The active transcoding jobs + /// </summary> + private readonly List<TranscodingJob> ActiveTranscodingJobs = new List<TranscodingJob>(); + + /// <summary> + /// Called when [transcode beginning]. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="type">The type.</param> + /// <param name="process">The process.</param> + public void OnTranscodeBeginning(string path, TranscodingJobType type, Process process) + { + lock (ActiveTranscodingJobs) + { + ActiveTranscodingJobs.Add(new TranscodingJob + { + Type = type, + Path = path, + Process = process, + ActiveRequestCount = 1 + }); + } + } + + /// <summary> + /// <summary> + /// The progressive + /// </summary> + /// Called when [transcode failed to start]. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="type">The type.</param> + public void OnTranscodeFailedToStart(string path, TranscodingJobType type) + { + lock (ActiveTranscodingJobs) + { + var job = ActiveTranscodingJobs.First(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); + + ActiveTranscodingJobs.Remove(job); + } + } + + /// <summary> + /// Determines whether [has active transcoding job] [the specified path]. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="type">The type.</param> + /// <returns><c>true</c> if [has active transcoding job] [the specified path]; otherwise, <c>false</c>.</returns> + public bool HasActiveTranscodingJob(string path, TranscodingJobType type) + { + lock (ActiveTranscodingJobs) + { + return ActiveTranscodingJobs.Any(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); + } + } + + /// <summary> + /// Called when [transcode begin request]. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="type">The type.</param> + public void OnTranscodeBeginRequest(string path, TranscodingJobType type) + { + lock (ActiveTranscodingJobs) + { + var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); + + if (job == null) + { + return; + } + + job.ActiveRequestCount++; + + if (job.KillTimer != null) + { + job.KillTimer.Dispose(); + job.KillTimer = null; + } + } + } + + /// <summary> + /// Called when [transcode end request]. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="type">The type.</param> + public void OnTranscodeEndRequest(string path, TranscodingJobType type) + { + lock (ActiveTranscodingJobs) + { + var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); + + if (job == null) + { + return; + } + + job.ActiveRequestCount--; + + if (job.ActiveRequestCount == 0) + { + var timerDuration = type == TranscodingJobType.Progressive ? 1000 : 30000; + + if (job.KillTimer == null) + { + job.KillTimer = new Timer(OnTranscodeKillTimerStopped, job, timerDuration, Timeout.Infinite); + } + else + { + job.KillTimer.Change(timerDuration, Timeout.Infinite); + } + } + } + } + + /// <summary> + /// Called when [transcoding finished]. + /// </summary> + /// <param name="path">The path.</param> + /// <param name="type">The type.</param> + public void OnTranscodingFinished(string path, TranscodingJobType type) + { + lock (ActiveTranscodingJobs) + { + var job = ActiveTranscodingJobs.FirstOrDefault(j => j.Type == type && j.Path.Equals(path, StringComparison.OrdinalIgnoreCase)); + + if (job == null) + { + return; + } + + ActiveTranscodingJobs.Remove(job); + + if (job.KillTimer != null) + { + job.KillTimer.Dispose(); + job.KillTimer = null; + } + } + } + + /// <summary> + /// Called when [transcode kill timer stopped]. + /// </summary> + /// <param name="state">The state.</param> + private void OnTranscodeKillTimerStopped(object state) + { + var job = (TranscodingJob)state; + + lock (ActiveTranscodingJobs) + { + ActiveTranscodingJobs.Remove(job); + + if (job.KillTimer != null) + { + job.KillTimer.Dispose(); + job.KillTimer = null; + } + } + + var process = job.Process; + + var hasExited = true; + + try + { + hasExited = process.HasExited; + } + catch (Win32Exception ex) + { + Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path); + } + catch (InvalidOperationException ex) + { + Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path); + } + catch (NotSupportedException ex) + { + Logger.ErrorException("Error determining if ffmpeg process has exited for {0}", ex, job.Path); + } + + if (hasExited) + { + return; + } + + try + { + Logger.Info("Killing ffmpeg process for {0}", job.Path); + + process.Kill(); + } + catch (Win32Exception ex) + { + Logger.ErrorException("Error killing transcoding job for {0}", ex, job.Path); + } + catch (InvalidOperationException ex) + { + Logger.ErrorException("Error killing transcoding job for {0}", ex, job.Path); + } + catch (NotSupportedException ex) + { + Logger.ErrorException("Error killing transcoding job for {0}", ex, job.Path); + } + } + + } + + /// <summary> + /// Class TranscodingJob + /// </summary> + public class TranscodingJob + { + /// <summary> + /// Gets or sets the path. + /// </summary> + /// <value>The path.</value> + public string Path { get; set; } + /// <summary> + /// Gets or sets the type. + /// </summary> + /// <value>The type.</value> + public TranscodingJobType Type { get; set; } + /// <summary> + /// Gets or sets the process. + /// </summary> + /// <value>The process.</value> + public Process Process { get; set; } + /// <summary> + /// Gets or sets the active request count. + /// </summary> + /// <value>The active request count.</value> + public int ActiveRequestCount { get; set; } + /// <summary> + /// <summary> + /// Enum TranscodingJobType + /// </summary> + /// <summary> + /// Gets or sets the kill timer. + /// </summary> + /// <value>The kill timer.</value> + public Timer KillTimer { get; set; } + } + + /// <summary> + /// Enum TranscodingJobType + /// </summary> + public enum TranscodingJobType + { + /// <summary> + /// The progressive + /// </summary> + Progressive, + /// <summary> + /// The HLS + /// </summary> + Hls + } +} diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index f23d859e8..3d7421f67 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.Implementations.Updates; using MediaBrowser.Common.Implementations.WebSocket; using MediaBrowser.Common.Kernel; using MediaBrowser.Common.Net; +using MediaBrowser.Common.Plugins; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Common.Updates; using MediaBrowser.Model.Logging; @@ -26,6 +27,12 @@ namespace MediaBrowser.Common.Implementations public ILogger Logger { get; protected set; } /// <summary> + /// Gets or sets the plugins. + /// </summary> + /// <value>The plugins.</value> + public IEnumerable<IPlugin> Plugins { get; protected set; } + + /// <summary> /// Gets or sets the log manager. /// </summary> /// <value>The log manager.</value> @@ -142,12 +149,13 @@ namespace MediaBrowser.Common.Implementations /// </summary> protected virtual void FindParts() { - Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false)); - Resolve<IHttpServer>().Init(GetExports<IRestfulService>(false)); Resolve<IServerManager>().AddWebSocketListeners(GetExports<IWebSocketListener>(false)); Resolve<IServerManager>().Start(); + Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false)); + + Plugins = GetExports<IPlugin>(); } /// <summary> @@ -349,6 +357,17 @@ namespace MediaBrowser.Common.Implementations } /// <summary> + /// Removes the plugin. + /// </summary> + /// <param name="plugin">The plugin.</param> + public void RemovePlugin(IPlugin plugin) + { + var list = Plugins.ToList(); + list.Remove(plugin); + Plugins = list; + } + + /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 78277ed2f..d35ee42c9 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -1,16 +1,13 @@ using MediaBrowser.Common.Events; -using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Security; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.System; using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; -using System.Threading.Tasks; namespace MediaBrowser.Common.Kernel { @@ -122,12 +119,6 @@ namespace MediaBrowser.Common.Kernel public TApplicationPathsType ApplicationPaths { get; private set; } /// <summary> - /// Gets the list of currently loaded plugins - /// </summary> - /// <value>The plugins.</value> - public IEnumerable<IPlugin> Plugins { get; protected set; } - - /// <summary> /// Gets or sets the TCP manager. /// </summary> /// <value>The TCP manager.</value> @@ -211,9 +202,9 @@ namespace MediaBrowser.Common.Kernel /// Initializes the Kernel /// </summary> /// <returns>Task.</returns> - public async Task Init() + public void Init() { - await ReloadInternal().ConfigureAwait(false); + ReloadInternal(); OnReloadCompleted(); @@ -224,65 +215,12 @@ namespace MediaBrowser.Common.Kernel /// Performs initializations that can be reloaded at anytime /// </summary> /// <returns>Task.</returns> - protected virtual async Task ReloadInternal() + protected virtual void ReloadInternal() { - // Set these to null so that they can be lazy loaded again - Configuration = null; - - await OnConfigurationLoaded().ConfigureAwait(false); - - FindParts(); - - await OnComposablePartsLoaded().ConfigureAwait(false); - ServerManager = ApplicationHost.Resolve<IServerManager>(); } /// <summary> - /// Called when [configuration loaded]. - /// </summary> - /// <returns>Task.</returns> - protected virtual Task OnConfigurationLoaded() - { - return Task.FromResult<object>(null); - } - - /// <summary> - /// Composes the parts with ioc container. - /// </summary> - protected virtual void FindParts() - { - Plugins = ApplicationHost.GetExports<IPlugin>(); - } - - /// <summary> - /// Fires after MEF finishes finding composable parts within plugin assemblies - /// </summary> - /// <returns>Task.</returns> - protected virtual Task OnComposablePartsLoaded() - { - return Task.Run(() => - { - // Start-up each plugin - Parallel.ForEach(Plugins, plugin => - { - Logger.Info("Initializing {0} {1}", plugin.Name, plugin.Version); - - try - { - plugin.Initialize(this, _xmlSerializer, Logger); - - Logger.Info("{0} {1} initialized.", plugin.Name, plugin.Version); - } - catch (Exception ex) - { - Logger.ErrorException("Error initializing {0}", ex, plugin.Name); - } - }); - }); - } - - /// <summary> /// Notifies that the kernel that a change has been made that requires a restart /// </summary> public void NotifyPendingRestart() @@ -442,17 +380,5 @@ namespace MediaBrowser.Common.Kernel /// </summary> /// <value>The resource pools.</value> public ResourcePool ResourcePools { get; set; } - - /// <summary> - /// Removes the plugin. - /// </summary> - /// <param name="plugin">The plugin.</param> - public void RemovePlugin(IPlugin plugin) - { - var list = Plugins.ToList(); - list.Remove(plugin); - Plugins = list; - } - } } diff --git a/MediaBrowser.Common/Kernel/IApplicationHost.cs b/MediaBrowser.Common/Kernel/IApplicationHost.cs index bb007ddff..29934988a 100644 --- a/MediaBrowser.Common/Kernel/IApplicationHost.cs +++ b/MediaBrowser.Common/Kernel/IApplicationHost.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Updates; +using MediaBrowser.Common.Plugins; +using MediaBrowser.Model.Updates; using System; using System.Collections.Generic; using System.Threading; @@ -97,5 +98,17 @@ namespace MediaBrowser.Common.Kernel /// Shuts down. /// </summary> void Shutdown(); + + /// <summary> + /// Gets the plugins. + /// </summary> + /// <value>The plugins.</value> + IEnumerable<IPlugin> Plugins { get; } + + /// <summary> + /// Removes the plugin. + /// </summary> + /// <param name="plugin">The plugin.</param> + void RemovePlugin(IPlugin plugin); } } diff --git a/MediaBrowser.Common/Kernel/IKernel.cs b/MediaBrowser.Common/Kernel/IKernel.cs index d02f0af20..0d123476c 100644 --- a/MediaBrowser.Common/Kernel/IKernel.cs +++ b/MediaBrowser.Common/Kernel/IKernel.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Common.Kernel /// Inits this instance. /// </summary> /// <returns>Task.</returns> - Task Init(); + void Init(); /// <summary> /// Gets or sets a value indicating whether this instance has pending kernel reload. @@ -72,12 +72,6 @@ namespace MediaBrowser.Common.Kernel void PerformPendingRestart(); /// <summary> - /// Gets the plugins. - /// </summary> - /// <value>The plugins.</value> - IEnumerable<IPlugin> Plugins { get; } - - /// <summary> /// Gets the UDP server port number. /// </summary> /// <value>The UDP server port number.</value> @@ -123,12 +117,5 @@ namespace MediaBrowser.Common.Kernel /// </summary> /// <value>The resource pools.</value> ResourcePool ResourcePools { get; set; } - - /// <summary> - /// Removes the plugin. - /// </summary> - /// <param name="plugin">The plugin.</param> - void RemovePlugin(IPlugin plugin); - } } diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index 0d7c5c060..c968a65c8 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; using MediaBrowser.Model.Plugins; using MediaBrowser.Model.Serialization; using System; @@ -14,7 +13,7 @@ namespace MediaBrowser.Common.Plugins /// Provides a common base class for all plugins /// </summary> /// <typeparam name="TConfigurationType">The type of the T configuration type.</typeparam> - public abstract class BasePlugin<TConfigurationType> : IDisposable, IPlugin + public abstract class BasePlugin<TConfigurationType> : IPlugin where TConfigurationType : BasePluginConfiguration { /// <summary> @@ -24,6 +23,12 @@ namespace MediaBrowser.Common.Plugins protected IKernel Kernel { 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> @@ -57,6 +62,12 @@ namespace MediaBrowser.Common.Plugins } /// <summary> + /// Gets a value indicating whether this instance is first run. + /// </summary> + /// <value><c>true</c> if this instance is first run; otherwise, <c>false</c>.</value> + public bool IsFirstRun { get; private set; } + + /// <summary> /// Gets the type of configuration this plugin uses /// </summary> /// <value>The type of the configuration.</value> @@ -252,87 +263,14 @@ namespace MediaBrowser.Common.Plugins } /// <summary> - /// Gets the logger. - /// </summary> - /// <value>The logger.</value> - public ILogger Logger { get; private set; } - - /// <summary> - /// Gets the XML serializer. - /// </summary> - /// <value>The XML serializer.</value> - protected IXmlSerializer XmlSerializer { get; private set; } - - /// <summary> - /// Starts the plugin. + /// Initializes a new instance of the <see cref="BasePlugin{TConfigurationType}" /> class. /// </summary> /// <param name="kernel">The kernel.</param> /// <param name="xmlSerializer">The XML serializer.</param> - /// <param name="logger">The logger.</param> - /// <exception cref="System.ArgumentNullException">kernel</exception> - public void Initialize(IKernel kernel, IXmlSerializer xmlSerializer, ILogger logger) + protected BasePlugin(IKernel kernel, IXmlSerializer xmlSerializer) { - if (kernel == null) - { - throw new ArgumentNullException("kernel"); - } - - if (xmlSerializer == null) - { - throw new ArgumentNullException("xmlSerializer"); - } - - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - XmlSerializer = xmlSerializer; - Logger = logger; Kernel = kernel; - - if (kernel.KernelContext == KernelContext.Server) - { - InitializeOnServer(!File.Exists(ConfigurationFilePath)); - } - } - - /// <summary> - /// Starts the plugin on the server - /// </summary> - /// <param name="isFirstRun">if set to <c>true</c> [is first run].</param> - protected virtual void InitializeOnServer(bool isFirstRun) - { - } - - /// <summary> - /// Disposes the plugins. Undos all actions performed during Init. - /// </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 void Dispose(bool dispose) - { - if (Kernel.KernelContext == KernelContext.Server) - { - DisposeOnServer(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 virtual void DisposeOnServer(bool dispose) - { - + XmlSerializer = xmlSerializer; } /// <summary> @@ -351,8 +289,6 @@ namespace MediaBrowser.Common.Plugins throw new InvalidOperationException("Cannot call Plugin.SaveConfiguration from the UI."); } - Logger.Info("Saving configuration"); - lock (_configurationSaveLock) { XmlSerializer.SerializeToFile(Configuration, ConfigurationFilePath); diff --git a/MediaBrowser.Common/Plugins/IPlugin.cs b/MediaBrowser.Common/Plugins/IPlugin.cs index 7d5fddb9a..ace82d83f 100644 --- a/MediaBrowser.Common/Plugins/IPlugin.cs +++ b/MediaBrowser.Common/Plugins/IPlugin.cs @@ -1,11 +1,11 @@ -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Plugins; -using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Plugins; using System; namespace MediaBrowser.Common.Plugins { + /// <summary> + /// Interface IPlugin + /// </summary> public interface IPlugin { /// <summary> @@ -93,26 +93,6 @@ namespace MediaBrowser.Common.Plugins string DataFolderPath { get; } /// <summary> - /// Gets the logger. - /// </summary> - /// <value>The logger.</value> - ILogger Logger { get; } - - /// <summary> - /// Starts the plugin. - /// </summary> - /// <param name="kernel">The kernel.</param> - /// <param name="xmlSerializer">The XML serializer.</param> - /// <param name="logger">The logger.</param> - /// <exception cref="System.ArgumentNullException">kernel</exception> - void Initialize(IKernel kernel, IXmlSerializer xmlSerializer, ILogger logger); - - /// <summary> - /// Disposes the plugins. Undos all actions performed during Init. - /// </summary> - void Dispose(); - - /// <summary> /// Saves the current configuration to the file system /// </summary> /// <exception cref="System.InvalidOperationException">Cannot call Plugin.SaveConfiguration from the UI.</exception> @@ -136,5 +116,11 @@ namespace MediaBrowser.Common.Plugins /// Called when just before the plugin is uninstalled from the server. /// </summary> void OnUninstalling(); + + /// <summary> + /// Gets a value indicating whether this instance is first run. + /// </summary> + /// <value><c>true</c> if this instance is first run; otherwise, <c>false</c>.</value> + bool IsFirstRun { get; } } }
\ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs b/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs index e48551425..6dc5c6b38 100644 --- a/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs +++ b/MediaBrowser.Common/ScheduledTasks/StartupTrigger.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Common.ScheduledTasks { if (isApplicationStartup) { - await Task.Delay(2000).ConfigureAwait(false); + await Task.Delay(3000).ConfigureAwait(false); OnTriggered(); } diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 16175783f..99e0ef783 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -183,7 +183,7 @@ namespace MediaBrowser.Controller /// <summary> /// Composes the parts with ioc container. /// </summary> - protected override void FindParts() + protected void FindParts() { // For now there's no real way to inject this properly BaseItem.LibraryManager = ApplicationHost.Resolve<ILibraryManager>(); @@ -194,8 +194,6 @@ namespace MediaBrowser.Controller ProviderManager = (ProviderManager)ApplicationHost.CreateInstance(typeof(ProviderManager)); SecurityManager = (PluginSecurityManager)ApplicationHost.CreateInstance(typeof(PluginSecurityManager)); - base.FindParts(); - UserDataRepositories = ApplicationHost.GetExports<IUserDataRepository>(); UserRepositories = ApplicationHost.GetExports<IUserRepository>(); DisplayPreferencesRepositories = ApplicationHost.GetExports<IDisplayPreferencesRepository>(); @@ -211,15 +209,24 @@ namespace MediaBrowser.Controller /// Performs initializations that can be reloaded at anytime /// </summary> /// <returns>Task.</returns> - protected override async Task ReloadInternal() + protected override async void ReloadInternal() { - await base.ReloadInternal().ConfigureAwait(false); + base.ReloadInternal(); + + FindParts(); + + await LoadRepositories().ConfigureAwait(false); ReloadResourcePools(); ReloadFileSystemManager(); await ApplicationHost.Resolve<IUserManager>().RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false); + + foreach (var entryPoint in ApplicationHost.GetExports<IServerEntryPoint>()) + { + entryPoint.Run(); + } } /// <summary> @@ -263,11 +270,8 @@ namespace MediaBrowser.Controller /// Called when [composable parts loaded]. /// </summary> /// <returns>Task.</returns> - protected override async Task OnComposablePartsLoaded() + protected Task LoadRepositories() { - // The base class will start up all the plugins - await base.OnComposablePartsLoaded().ConfigureAwait(false); - // Get the current item repository ItemRepository = GetRepository(ItemRepositories, Configuration.ItemRepository); var itemRepoTask = ItemRepository.Initialize(); @@ -284,7 +288,7 @@ namespace MediaBrowser.Controller DisplayPreferencesRepository = GetRepository(DisplayPreferencesRepositories, Configuration.DisplayPreferencesRepository); var displayPreferencesRepoTask = DisplayPreferencesRepository.Initialize(); - await Task.WhenAll(itemRepoTask, userRepoTask, userDataRepoTask, displayPreferencesRepoTask).ConfigureAwait(false); + return Task.WhenAll(itemRepoTask, userRepoTask, userDataRepoTask, displayPreferencesRepoTask); } /// <summary> diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 71116881e..63468a8e8 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -131,6 +131,7 @@ <Compile Include="Persistence\IUserRepository.cs" /> <Compile Include="Library\IIntroProvider.cs" /> <Compile Include="Plugins\IPluginConfigurationPage.cs" /> + <Compile Include="Plugins\IServerEntryPoint.cs" /> <Compile Include="Plugins\PluginSecurityManager.cs" /> <Compile Include="Providers\FanartBaseProvider.cs" /> <Compile Include="Providers\IImageEnhancer.cs" /> diff --git a/MediaBrowser.Controller/Plugins/IServerEntryPoint.cs b/MediaBrowser.Controller/Plugins/IServerEntryPoint.cs new file mode 100644 index 000000000..de6de8f84 --- /dev/null +++ b/MediaBrowser.Controller/Plugins/IServerEntryPoint.cs @@ -0,0 +1,15 @@ +using System; + +namespace MediaBrowser.Controller.Plugins +{ + /// <summary> + /// Interface IServerEntryPoint + /// </summary> + public interface IServerEntryPoint : IDisposable + { + /// <summary> + /// Runs this instance. + /// </summary> + void Run(); + } +} diff --git a/MediaBrowser.Controller/Updates/InstallationManager.cs b/MediaBrowser.Controller/Updates/InstallationManager.cs index d616e8898..f67f690ae 100644 --- a/MediaBrowser.Controller/Updates/InstallationManager.cs +++ b/MediaBrowser.Controller/Updates/InstallationManager.cs @@ -287,7 +287,7 @@ namespace MediaBrowser.Controller.Updates { var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false); - var plugins = Kernel.Plugins; + var plugins = ApplicationHost.Plugins; if (withAutoUpdateEnabled) { @@ -424,7 +424,7 @@ namespace MediaBrowser.Controller.Updates if (!(Path.GetExtension(package.targetFilename) ?? "").Equals(".zip", StringComparison.OrdinalIgnoreCase)) { // Set last update time if we were installed before - var plugin = Kernel.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase)); + var plugin = ApplicationHost.Plugins.FirstOrDefault(p => p.Name.Equals(package.name, StringComparison.OrdinalIgnoreCase)); if (plugin != null) { @@ -460,7 +460,7 @@ namespace MediaBrowser.Controller.Updates plugin.OnUninstalling(); // Remove it the quick way for now - Kernel.RemovePlugin(plugin); + ApplicationHost.RemovePlugin(plugin); File.Delete(plugin.AssemblyFilePath); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 18108842f..ba54b5d2b 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -287,11 +287,6 @@ namespace MediaBrowser.Server.Implementations.Library /// <exception cref="System.InvalidOperationException">Cannot create the root folder until plugins have loaded</exception> public AggregateFolder CreateRootFolder() { - if (Kernel.Plugins == null) - { - throw new InvalidOperationException("Cannot create the root folder until plugins have loaded"); - } - var rootFolderPath = Kernel.ApplicationPaths.RootFolderPath; var rootFolder = Kernel.ItemRepository.RetrieveItem(rootFolderPath.GetMBId(typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(rootFolderPath); diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index f18df77c2..83136aed9 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -34,7 +34,7 @@ <ItemGroup> <Reference Include="BdInfo, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.0\lib\net45\BdInfo.dll</HintPath> + <HintPath>..\packages\MediaBrowser.BdInfo.1.0.0.2\lib\net45\BdInfo.dll</HintPath> </Reference> <Reference Include="MoreLinq"> <HintPath>..\packages\morelinq.1.0.15631-beta\lib\net35\MoreLinq.dll</HintPath> diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index c20edb5ab..fb84d9aa7 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="MediaBrowser.BdInfo" version="1.0.0.0" targetFramework="net45" /> + <package id="MediaBrowser.BdInfo" version="1.0.0.2" targetFramework="net45" /> <package id="morelinq" version="1.0.15631-beta" targetFramework="net45" /> <package id="System.Data.SQLite" version="1.0.84.0" targetFramework="net45" /> </packages>
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/App.xaml.cs b/MediaBrowser.ServerApplication/App.xaml.cs index dddd87782..95ece67e6 100644 --- a/MediaBrowser.ServerApplication/App.xaml.cs +++ b/MediaBrowser.ServerApplication/App.xaml.cs @@ -177,7 +177,7 @@ namespace MediaBrowser.ServerApplication var now = DateTime.UtcNow; - await Kernel.Init(); + Kernel.Init(); 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); diff --git a/MediaBrowser.sln b/MediaBrowser.sln index b473b2062..0fe54d005 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -253,4 +253,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(Performance) = preSolution + HasPerformanceSessions = true + EndGlobalSection EndGlobal diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index c005b145b..cc6679348 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,16 +2,17 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.22</version> - <title /> + <version>3.0.23</version> + <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> - <owners>Media Browser Team</owners> + <owners>ebr,Luke,scottisafool</owners> <projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl> <iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>Contains common components shared by Media Browser Theatre and Media Browser Server. Not intended for plugin developer consumption.</description> + <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.22" /> + <dependency id="MediaBrowser.Common" version="3.0.23" /> <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 bd5363302..cf832f548 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,13 +2,14 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.22</version> + <version>3.0.23</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> - <owners /> + <owners>ebr,Luke,scottisafool</owners> <projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl> <iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> + <copyright>Copyright © Media Browser 2013</copyright> <description>Contains common model objects and interfaces used by all Media Browser solutions.</description> </metadata> <files> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index be7a20a8a..7a195fe55 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,16 +2,17 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.22</version> + <version>3.0.23</version> <title>Media Browser.Server.Core</title> <authors>Media Browser Team</authors> - <owners /> + <owners>ebr,Luke,scottisafool</owners> <projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl> <iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>Contains core components required to build plugins for Media Browser Server.</description> + <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.22" /> + <dependency id="MediaBrowser.Common" version="3.0.23" /> </dependencies> </metadata> <files> |
