mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
added IServerEntryPoint to replace plugin.initialize
This commit is contained in:
parent
71fe785c6d
commit
0ea90ef7c6
@ -97,6 +97,7 @@
|
|||||||
<Compile Include="PluginService.cs" />
|
<Compile Include="PluginService.cs" />
|
||||||
<Compile Include="ScheduledTasks\ScheduledTaskService.cs" />
|
<Compile Include="ScheduledTasks\ScheduledTaskService.cs" />
|
||||||
<Compile Include="ScheduledTasks\ScheduledTasksWebSocketListener.cs" />
|
<Compile Include="ScheduledTasks\ScheduledTasksWebSocketListener.cs" />
|
||||||
|
<Compile Include="ServerEntryPoint.cs" />
|
||||||
<Compile Include="SystemService.cs" />
|
<Compile Include="SystemService.cs" />
|
||||||
<Compile Include="UserLibrary\BaseItemsByNameService.cs" />
|
<Compile Include="UserLibrary\BaseItemsByNameService.cs" />
|
||||||
<Compile Include="UserLibrary\GenresService.cs" />
|
<Compile Include="UserLibrary\GenresService.cs" />
|
||||||
|
@ -518,7 +518,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
EnableRaisingEvents = true
|
EnableRaisingEvents = true
|
||||||
};
|
};
|
||||||
|
|
||||||
Plugin.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process);
|
ServerEntryPoint.Instance.OnTranscodeBeginning(outputPath, TranscodingJobType, process);
|
||||||
|
|
||||||
//Logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
|
//Logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments);
|
||||||
|
|
||||||
@ -537,7 +537,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
{
|
{
|
||||||
Logger.ErrorException("Error starting ffmpeg", ex);
|
Logger.ErrorException("Error starting ffmpeg", ex);
|
||||||
|
|
||||||
Plugin.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType);
|
ServerEntryPoint.Instance.OnTranscodeFailedToStart(outputPath, TranscodingJobType);
|
||||||
|
|
||||||
state.LogFileStream.Dispose();
|
state.LogFileStream.Dispose();
|
||||||
|
|
||||||
@ -588,7 +588,7 @@ namespace MediaBrowser.Api.Playback
|
|||||||
|
|
||||||
process.Dispose();
|
process.Dispose();
|
||||||
|
|
||||||
Plugin.Instance.OnTranscodingFinished(outputFilePath, TranscodingJobType);
|
ServerEntryPoint.Instance.OnTranscodingFinished(outputFilePath, TranscodingJobType);
|
||||||
|
|
||||||
if (!exitCode.HasValue || exitCode.Value != 0)
|
if (!exitCode.HasValue || exitCode.Value != 0)
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Plugin.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType.Hls);
|
ServerEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType.Hls);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current playlist text and convert to bytes
|
// Get the current playlist text and convert to bytes
|
||||||
@ -94,7 +94,7 @@ namespace MediaBrowser.Api.Playback.Hls
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Plugin.Instance.OnTranscodeEndRequest(playlist, TranscodingJobType.Hls);
|
ServerEntryPoint.Instance.OnTranscodeEndRequest(playlist, TranscodingJobType.Hls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
|
|
||||||
var outputPath = GetOutputFilePath(state);
|
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);
|
return ToStaticFileResult(outputPath);
|
||||||
}
|
}
|
||||||
@ -133,7 +133,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Plugin.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
|
ServerEntryPoint.Instance.OnTranscodeBeginRequest(outputPath, TranscodingJobType.Progressive);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ProgressiveStreamWriter
|
return new ProgressiveStreamWriter
|
||||||
|
@ -41,7 +41,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Plugin.Instance.OnTranscodeEndRequest(Path, TranscodingJobType.Progressive);
|
ServerEntryPoint.Instance.OnTranscodeEndRequest(Path, TranscodingJobType.Progressive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
using MediaBrowser.Common.Plugins;
|
using MediaBrowser.Common.Kernel;
|
||||||
|
using MediaBrowser.Common.Plugins;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
using System;
|
using MediaBrowser.Model.Serialization;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Api
|
namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
@ -15,6 +10,16 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class Plugin : BasePlugin<BasePluginConfiguration>
|
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>
|
/// <summary>
|
||||||
/// Gets the name of the plugin
|
/// Gets the name of the plugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -41,287 +46,5 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The instance.</value>
|
/// <value>The instance.</value>
|
||||||
public static Plugin Instance { get; private set; }
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Common.Implementations.HttpServer;
|
using MediaBrowser.Common.Implementations.HttpServer;
|
||||||
|
using MediaBrowser.Common.Kernel;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
@ -123,12 +124,18 @@ namespace MediaBrowser.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The _app host
|
||||||
|
/// </summary>
|
||||||
|
private readonly IApplicationHost _appHost;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="PluginService" /> class.
|
/// Initializes a new instance of the <see cref="PluginService" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="jsonSerializer">The json serializer.</param>
|
/// <param name="jsonSerializer">The json serializer.</param>
|
||||||
|
/// <param name="appHost">The app host.</param>
|
||||||
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
|
/// <exception cref="System.ArgumentNullException">jsonSerializer</exception>
|
||||||
public PluginService(IJsonSerializer jsonSerializer)
|
public PluginService(IJsonSerializer jsonSerializer, IApplicationHost appHost)
|
||||||
: base()
|
: base()
|
||||||
{
|
{
|
||||||
if (jsonSerializer == null)
|
if (jsonSerializer == null)
|
||||||
@ -136,6 +143,7 @@ namespace MediaBrowser.Api
|
|||||||
throw new ArgumentNullException("jsonSerializer");
|
throw new ArgumentNullException("jsonSerializer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_appHost = appHost;
|
||||||
_jsonSerializer = jsonSerializer;
|
_jsonSerializer = jsonSerializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +154,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPlugins request)
|
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);
|
return ToOptimizedResult(result);
|
||||||
}
|
}
|
||||||
@ -158,7 +166,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPluginAssembly request)
|
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);
|
return ToStaticFileResult(plugin.AssemblyFilePath);
|
||||||
}
|
}
|
||||||
@ -170,7 +178,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPluginConfiguration request)
|
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;
|
var dateModified = plugin.ConfigurationDateLastModified;
|
||||||
|
|
||||||
@ -186,7 +194,7 @@ namespace MediaBrowser.Api
|
|||||||
/// <returns>System.Object.</returns>
|
/// <returns>System.Object.</returns>
|
||||||
public object Get(GetPluginConfigurationFile request)
|
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);
|
return ToStaticFileResult(plugin.ConfigurationFilePath);
|
||||||
}
|
}
|
||||||
@ -235,7 +243,7 @@ namespace MediaBrowser.Api
|
|||||||
var pathInfo = PathInfo.Parse(Request.PathInfo);
|
var pathInfo = PathInfo.Parse(Request.PathInfo);
|
||||||
var id = new Guid(pathInfo.GetArgumentValue<string>(1));
|
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;
|
var configuration = _jsonSerializer.DeserializeFromStream(request.RequestStream, plugin.ConfigurationType) as BasePluginConfiguration;
|
||||||
|
|
||||||
@ -250,7 +258,7 @@ namespace MediaBrowser.Api
|
|||||||
{
|
{
|
||||||
var kernel = (Kernel)Kernel;
|
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);
|
kernel.InstallationManager.UninstallPlugin(plugin);
|
||||||
}
|
}
|
||||||
|
333
MediaBrowser.Api/ServerEntryPoint.cs
Normal file
333
MediaBrowser.Api/ServerEntryPoint.cs
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ using MediaBrowser.Common.Implementations.Updates;
|
|||||||
using MediaBrowser.Common.Implementations.WebSocket;
|
using MediaBrowser.Common.Implementations.WebSocket;
|
||||||
using MediaBrowser.Common.Kernel;
|
using MediaBrowser.Common.Kernel;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
|
using MediaBrowser.Common.Plugins;
|
||||||
using MediaBrowser.Common.ScheduledTasks;
|
using MediaBrowser.Common.ScheduledTasks;
|
||||||
using MediaBrowser.Common.Updates;
|
using MediaBrowser.Common.Updates;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
@ -25,6 +26,12 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
/// <value>The logger.</value>
|
/// <value>The logger.</value>
|
||||||
public ILogger Logger { get; protected set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the log manager.
|
/// Gets or sets the log manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -142,12 +149,13 @@ namespace MediaBrowser.Common.Implementations
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void FindParts()
|
protected virtual void FindParts()
|
||||||
{
|
{
|
||||||
Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false));
|
|
||||||
|
|
||||||
Resolve<IHttpServer>().Init(GetExports<IRestfulService>(false));
|
Resolve<IHttpServer>().Init(GetExports<IRestfulService>(false));
|
||||||
Resolve<IServerManager>().AddWebSocketListeners(GetExports<IWebSocketListener>(false));
|
Resolve<IServerManager>().AddWebSocketListeners(GetExports<IWebSocketListener>(false));
|
||||||
|
|
||||||
Resolve<IServerManager>().Start();
|
Resolve<IServerManager>().Start();
|
||||||
|
Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false));
|
||||||
|
|
||||||
|
Plugins = GetExports<IPlugin>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -348,6 +356,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>
|
/// <summary>
|
||||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
using MediaBrowser.Common.Events;
|
using MediaBrowser.Common.Events;
|
||||||
using MediaBrowser.Common.Plugins;
|
|
||||||
using MediaBrowser.Common.Security;
|
using MediaBrowser.Common.Security;
|
||||||
using MediaBrowser.Model.Configuration;
|
using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using MediaBrowser.Model.System;
|
using MediaBrowser.Model.System;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Kernel
|
namespace MediaBrowser.Common.Kernel
|
||||||
{
|
{
|
||||||
@ -121,12 +118,6 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// <value>The application paths.</value>
|
/// <value>The application paths.</value>
|
||||||
public TApplicationPathsType ApplicationPaths { get; private set; }
|
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>
|
/// <summary>
|
||||||
/// Gets or sets the TCP manager.
|
/// Gets or sets the TCP manager.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -211,9 +202,9 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// Initializes the Kernel
|
/// Initializes the Kernel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
public async Task Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
await ReloadInternal().ConfigureAwait(false);
|
ReloadInternal();
|
||||||
|
|
||||||
OnReloadCompleted();
|
OnReloadCompleted();
|
||||||
|
|
||||||
@ -224,64 +215,11 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// Performs initializations that can be reloaded at anytime
|
/// Performs initializations that can be reloaded at anytime
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <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>();
|
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>
|
/// <summary>
|
||||||
/// Notifies that the kernel that a change has been made that requires a restart
|
/// Notifies that the kernel that a change has been made that requires a restart
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -442,17 +380,5 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The resource pools.</value>
|
/// <value>The resource pools.</value>
|
||||||
public ResourcePool ResourcePools { get; set; }
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using MediaBrowser.Model.Updates;
|
using MediaBrowser.Common.Plugins;
|
||||||
|
using MediaBrowser.Model.Updates;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@ -97,5 +98,17 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// Shuts down.
|
/// Shuts down.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Shutdown();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// Inits this instance.
|
/// Inits this instance.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <returns>Task.</returns>
|
||||||
Task Init();
|
void Init();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether this instance has pending kernel reload.
|
/// Gets or sets a value indicating whether this instance has pending kernel reload.
|
||||||
@ -71,12 +71,6 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void PerformPendingRestart();
|
void PerformPendingRestart();
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the plugins.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The plugins.</value>
|
|
||||||
IEnumerable<IPlugin> Plugins { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the UDP server port number.
|
/// Gets the UDP server port number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -123,12 +117,5 @@ namespace MediaBrowser.Common.Kernel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The resource pools.</value>
|
/// <value>The resource pools.</value>
|
||||||
ResourcePool ResourcePools { get; set; }
|
ResourcePool ResourcePools { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes the plugin.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="plugin">The plugin.</param>
|
|
||||||
void RemovePlugin(IPlugin plugin);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using MediaBrowser.Common.Kernel;
|
using MediaBrowser.Common.Kernel;
|
||||||
using MediaBrowser.Model.Logging;
|
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using System;
|
using System;
|
||||||
@ -14,7 +13,7 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
/// Provides a common base class for all plugins
|
/// Provides a common base class for all plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TConfigurationType">The type of the T configuration type.</typeparam>
|
/// <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
|
where TConfigurationType : BasePluginConfiguration
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -23,6 +22,12 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
/// <value>The kernel.</value>
|
/// <value>The kernel.</value>
|
||||||
protected IKernel Kernel { get; private set; }
|
protected IKernel Kernel { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the XML serializer.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The XML serializer.</value>
|
||||||
|
protected IXmlSerializer XmlSerializer { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the plugin's current context
|
/// Gets or sets the plugin's current context
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -56,6 +61,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>
|
/// <summary>
|
||||||
/// Gets the type of configuration this plugin uses
|
/// Gets the type of configuration this plugin uses
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -252,87 +263,14 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the logger.
|
/// Initializes a new instance of the <see cref="BasePlugin{TConfigurationType}" /> class.
|
||||||
/// </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.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="kernel">The kernel.</param>
|
/// <param name="kernel">The kernel.</param>
|
||||||
/// <param name="xmlSerializer">The XML serializer.</param>
|
/// <param name="xmlSerializer">The XML serializer.</param>
|
||||||
/// <param name="logger">The logger.</param>
|
protected BasePlugin(IKernel kernel, IXmlSerializer xmlSerializer)
|
||||||
/// <exception cref="System.ArgumentNullException">kernel</exception>
|
|
||||||
public void Initialize(IKernel kernel, IXmlSerializer xmlSerializer, ILogger logger)
|
|
||||||
{
|
{
|
||||||
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;
|
Kernel = kernel;
|
||||||
|
XmlSerializer = xmlSerializer;
|
||||||
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)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -351,8 +289,6 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
throw new InvalidOperationException("Cannot call Plugin.SaveConfiguration from the UI.");
|
throw new InvalidOperationException("Cannot call Plugin.SaveConfiguration from the UI.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Info("Saving configuration");
|
|
||||||
|
|
||||||
lock (_configurationSaveLock)
|
lock (_configurationSaveLock)
|
||||||
{
|
{
|
||||||
XmlSerializer.SerializeToFile(Configuration, ConfigurationFilePath);
|
XmlSerializer.SerializeToFile(Configuration, ConfigurationFilePath);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
using MediaBrowser.Common.Kernel;
|
using MediaBrowser.Model.Plugins;
|
||||||
using MediaBrowser.Model.Logging;
|
|
||||||
using MediaBrowser.Model.Plugins;
|
|
||||||
using MediaBrowser.Model.Serialization;
|
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Plugins
|
namespace MediaBrowser.Common.Plugins
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface IPlugin
|
||||||
|
/// </summary>
|
||||||
public interface IPlugin
|
public interface IPlugin
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -92,26 +92,6 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
/// <value>The data folder path.</value>
|
/// <value>The data folder path.</value>
|
||||||
string DataFolderPath { get; }
|
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>
|
/// <summary>
|
||||||
/// Saves the current configuration to the file system
|
/// Saves the current configuration to the file system
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -136,5 +116,11 @@ namespace MediaBrowser.Common.Plugins
|
|||||||
/// Called when just before the plugin is uninstalled from the server.
|
/// Called when just before the plugin is uninstalled from the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void OnUninstalling();
|
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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,7 +16,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||||||
{
|
{
|
||||||
if (isApplicationStartup)
|
if (isApplicationStartup)
|
||||||
{
|
{
|
||||||
await Task.Delay(2000).ConfigureAwait(false);
|
await Task.Delay(3000).ConfigureAwait(false);
|
||||||
|
|
||||||
OnTriggered();
|
OnTriggered();
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ namespace MediaBrowser.Controller
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Composes the parts with ioc container.
|
/// Composes the parts with ioc container.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void FindParts()
|
protected void FindParts()
|
||||||
{
|
{
|
||||||
// For now there's no real way to inject this properly
|
// For now there's no real way to inject this properly
|
||||||
BaseItem.LibraryManager = ApplicationHost.Resolve<ILibraryManager>();
|
BaseItem.LibraryManager = ApplicationHost.Resolve<ILibraryManager>();
|
||||||
@ -194,8 +194,6 @@ namespace MediaBrowser.Controller
|
|||||||
ProviderManager = (ProviderManager)ApplicationHost.CreateInstance(typeof(ProviderManager));
|
ProviderManager = (ProviderManager)ApplicationHost.CreateInstance(typeof(ProviderManager));
|
||||||
SecurityManager = (PluginSecurityManager)ApplicationHost.CreateInstance(typeof(PluginSecurityManager));
|
SecurityManager = (PluginSecurityManager)ApplicationHost.CreateInstance(typeof(PluginSecurityManager));
|
||||||
|
|
||||||
base.FindParts();
|
|
||||||
|
|
||||||
UserDataRepositories = ApplicationHost.GetExports<IUserDataRepository>();
|
UserDataRepositories = ApplicationHost.GetExports<IUserDataRepository>();
|
||||||
UserRepositories = ApplicationHost.GetExports<IUserRepository>();
|
UserRepositories = ApplicationHost.GetExports<IUserRepository>();
|
||||||
DisplayPreferencesRepositories = ApplicationHost.GetExports<IDisplayPreferencesRepository>();
|
DisplayPreferencesRepositories = ApplicationHost.GetExports<IDisplayPreferencesRepository>();
|
||||||
@ -211,15 +209,24 @@ namespace MediaBrowser.Controller
|
|||||||
/// Performs initializations that can be reloaded at anytime
|
/// Performs initializations that can be reloaded at anytime
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <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();
|
ReloadResourcePools();
|
||||||
|
|
||||||
ReloadFileSystemManager();
|
ReloadFileSystemManager();
|
||||||
|
|
||||||
await ApplicationHost.Resolve<IUserManager>().RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false);
|
await ApplicationHost.Resolve<IUserManager>().RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var entryPoint in ApplicationHost.GetExports<IServerEntryPoint>())
|
||||||
|
{
|
||||||
|
entryPoint.Run();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -263,11 +270,8 @@ namespace MediaBrowser.Controller
|
|||||||
/// Called when [composable parts loaded].
|
/// Called when [composable parts loaded].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Task.</returns>
|
/// <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
|
// Get the current item repository
|
||||||
ItemRepository = GetRepository(ItemRepositories, Configuration.ItemRepository);
|
ItemRepository = GetRepository(ItemRepositories, Configuration.ItemRepository);
|
||||||
var itemRepoTask = ItemRepository.Initialize();
|
var itemRepoTask = ItemRepository.Initialize();
|
||||||
@ -284,7 +288,7 @@ namespace MediaBrowser.Controller
|
|||||||
DisplayPreferencesRepository = GetRepository(DisplayPreferencesRepositories, Configuration.DisplayPreferencesRepository);
|
DisplayPreferencesRepository = GetRepository(DisplayPreferencesRepositories, Configuration.DisplayPreferencesRepository);
|
||||||
var displayPreferencesRepoTask = DisplayPreferencesRepository.Initialize();
|
var displayPreferencesRepoTask = DisplayPreferencesRepository.Initialize();
|
||||||
|
|
||||||
await Task.WhenAll(itemRepoTask, userRepoTask, userDataRepoTask, displayPreferencesRepoTask).ConfigureAwait(false);
|
return Task.WhenAll(itemRepoTask, userRepoTask, userDataRepoTask, displayPreferencesRepoTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -131,6 +131,7 @@
|
|||||||
<Compile Include="Persistence\IUserRepository.cs" />
|
<Compile Include="Persistence\IUserRepository.cs" />
|
||||||
<Compile Include="Library\IIntroProvider.cs" />
|
<Compile Include="Library\IIntroProvider.cs" />
|
||||||
<Compile Include="Plugins\IPluginConfigurationPage.cs" />
|
<Compile Include="Plugins\IPluginConfigurationPage.cs" />
|
||||||
|
<Compile Include="Plugins\IServerEntryPoint.cs" />
|
||||||
<Compile Include="Plugins\PluginSecurityManager.cs" />
|
<Compile Include="Plugins\PluginSecurityManager.cs" />
|
||||||
<Compile Include="Providers\FanartBaseProvider.cs" />
|
<Compile Include="Providers\FanartBaseProvider.cs" />
|
||||||
<Compile Include="Providers\IImageEnhancer.cs" />
|
<Compile Include="Providers\IImageEnhancer.cs" />
|
||||||
|
15
MediaBrowser.Controller/Plugins/IServerEntryPoint.cs
Normal file
15
MediaBrowser.Controller/Plugins/IServerEntryPoint.cs
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -287,7 +287,7 @@ namespace MediaBrowser.Controller.Updates
|
|||||||
{
|
{
|
||||||
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
|
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
var plugins = Kernel.Plugins;
|
var plugins = ApplicationHost.Plugins;
|
||||||
|
|
||||||
if (withAutoUpdateEnabled)
|
if (withAutoUpdateEnabled)
|
||||||
{
|
{
|
||||||
@ -424,7 +424,7 @@ namespace MediaBrowser.Controller.Updates
|
|||||||
if (!(Path.GetExtension(package.targetFilename) ?? "").Equals(".zip", StringComparison.OrdinalIgnoreCase))
|
if (!(Path.GetExtension(package.targetFilename) ?? "").Equals(".zip", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
// Set last update time if we were installed before
|
// 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)
|
if (plugin != null)
|
||||||
{
|
{
|
||||||
@ -460,7 +460,7 @@ namespace MediaBrowser.Controller.Updates
|
|||||||
plugin.OnUninstalling();
|
plugin.OnUninstalling();
|
||||||
|
|
||||||
// Remove it the quick way for now
|
// Remove it the quick way for now
|
||||||
Kernel.RemovePlugin(plugin);
|
ApplicationHost.RemovePlugin(plugin);
|
||||||
|
|
||||||
File.Delete(plugin.AssemblyFilePath);
|
File.Delete(plugin.AssemblyFilePath);
|
||||||
|
|
||||||
|
@ -287,11 +287,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||||||
/// <exception cref="System.InvalidOperationException">Cannot create the root folder until plugins have loaded</exception>
|
/// <exception cref="System.InvalidOperationException">Cannot create the root folder until plugins have loaded</exception>
|
||||||
public AggregateFolder CreateRootFolder()
|
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 rootFolderPath = Kernel.ApplicationPaths.RootFolderPath;
|
||||||
var rootFolder = Kernel.ItemRepository.RetrieveItem(rootFolderPath.GetMBId(typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(rootFolderPath);
|
var rootFolder = Kernel.ItemRepository.RetrieveItem(rootFolderPath.GetMBId(typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(rootFolderPath);
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="BdInfo, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="BdInfo, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<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>
|
||||||
<Reference Include="MoreLinq">
|
<Reference Include="MoreLinq">
|
||||||
<HintPath>..\packages\morelinq.1.0.15631-beta\lib\net35\MoreLinq.dll</HintPath>
|
<HintPath>..\packages\morelinq.1.0.15631-beta\lib\net35\MoreLinq.dll</HintPath>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<packages>
|
<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="morelinq" version="1.0.15631-beta" targetFramework="net45" />
|
||||||
<package id="System.Data.SQLite" version="1.0.84.0" targetFramework="net45" />
|
<package id="System.Data.SQLite" version="1.0.84.0" targetFramework="net45" />
|
||||||
</packages>
|
</packages>
|
@ -177,7 +177,7 @@ namespace MediaBrowser.ServerApplication
|
|||||||
|
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
await Kernel.Init();
|
Kernel.Init();
|
||||||
|
|
||||||
var done = (DateTime.UtcNow - now);
|
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);
|
Logger.Info("Kernel.Init completed in {0}{1} minutes and {2} seconds.", done.Hours > 0 ? done.Hours + " Hours " : "", done.Minutes, done.Seconds);
|
||||||
|
@ -253,4 +253,7 @@ Global
|
|||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
GlobalSection(Performance) = preSolution
|
||||||
|
HasPerformanceSessions = true
|
||||||
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -2,16 +2,17 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Common.Internal</id>
|
<id>MediaBrowser.Common.Internal</id>
|
||||||
<version>3.0.22</version>
|
<version>3.0.23</version>
|
||||||
<title />
|
<title>MediaBrowser.Common.Internal</title>
|
||||||
<authors>Luke</authors>
|
<authors>Luke</authors>
|
||||||
<owners>Media Browser Team</owners>
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
<projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
|
<projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
|
||||||
<iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
|
<iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<description>Contains common components shared by Media Browser Theatre and Media Browser Server. Not intended for plugin developer consumption.</description>
|
<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>
|
<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="NLog" version="2.0.0.2000" />
|
||||||
<dependency id="ServiceStack" version="3.9.37" />
|
<dependency id="ServiceStack" version="3.9.37" />
|
||||||
<dependency id="ServiceStack.Api.Swagger" version="3.9.35" />
|
<dependency id="ServiceStack.Api.Swagger" version="3.9.35" />
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Common</id>
|
<id>MediaBrowser.Common</id>
|
||||||
<version>3.0.22</version>
|
<version>3.0.23</version>
|
||||||
<title>MediaBrowser.Common</title>
|
<title>MediaBrowser.Common</title>
|
||||||
<authors>Media Browser Team</authors>
|
<authors>Media Browser Team</authors>
|
||||||
<owners />
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
<projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
|
<projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
|
||||||
<iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
|
<iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
|
<copyright>Copyright © Media Browser 2013</copyright>
|
||||||
<description>Contains common model objects and interfaces used by all Media Browser solutions.</description>
|
<description>Contains common model objects and interfaces used by all Media Browser solutions.</description>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
|
@ -2,16 +2,17 @@
|
|||||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||||
<metadata>
|
<metadata>
|
||||||
<id>MediaBrowser.Server.Core</id>
|
<id>MediaBrowser.Server.Core</id>
|
||||||
<version>3.0.22</version>
|
<version>3.0.23</version>
|
||||||
<title>Media Browser.Server.Core</title>
|
<title>Media Browser.Server.Core</title>
|
||||||
<authors>Media Browser Team</authors>
|
<authors>Media Browser Team</authors>
|
||||||
<owners />
|
<owners>ebr,Luke,scottisafool</owners>
|
||||||
<projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
|
<projectUrl>https://github.com/MediaBrowser/MediaBrowser</projectUrl>
|
||||||
<iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
|
<iconUrl>http://www.mb3admin.com/images/mb3icons1-1.png</iconUrl>
|
||||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||||
<description>Contains core components required to build plugins for Media Browser Server.</description>
|
<description>Contains core components required to build plugins for Media Browser Server.</description>
|
||||||
|
<copyright>Copyright © Media Browser 2013</copyright>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency id="MediaBrowser.Common" version="3.0.22" />
|
<dependency id="MediaBrowser.Common" version="3.0.23" />
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</metadata>
|
</metadata>
|
||||||
<files>
|
<files>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user