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="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" />
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace MediaBrowser.Api.Playback.Progressive
|
|||
}
|
||||
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 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
|
||||
{
|
||||
|
@ -15,6 +10,16 @@ namespace MediaBrowser.Api
|
|||
/// </summary>
|
||||
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>
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
@ -123,12 +124,18 @@ namespace MediaBrowser.Api
|
|||
/// </summary>
|
||||
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);
|
||||
}
|
||||
|
|
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.Kernel;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Common.Plugins;
|
||||
using MediaBrowser.Common.ScheduledTasks;
|
||||
using MediaBrowser.Common.Updates;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
@ -25,6 +26,12 @@ namespace MediaBrowser.Common.Implementations
|
|||
/// <value>The logger.</value>
|
||||
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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -121,12 +118,6 @@ namespace MediaBrowser.Common.Kernel
|
|||
/// <value>The application paths.</value>
|
||||
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>
|
||||
|
@ -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,64 +215,11 @@ 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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
@ -71,12 +71,6 @@ namespace MediaBrowser.Common.Kernel
|
|||
/// </summary>
|
||||
void PerformPendingRestart();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugins.
|
||||
/// </summary>
|
||||
/// <value>The plugins.</value>
|
||||
IEnumerable<IPlugin> Plugins { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the UDP server port number.
|
||||
/// </summary>
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
@ -23,6 +22,12 @@ namespace MediaBrowser.Common.Plugins
|
|||
/// <value>The kernel.</value>
|
||||
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>
|
||||
|
@ -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>
|
||||
/// Gets the type of configuration this plugin uses
|
||||
/// </summary>
|
||||
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
@ -92,26 +92,6 @@ namespace MediaBrowser.Common.Plugins
|
|||
/// <value>The data folder path.</value>
|
||||
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>
|
||||
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ namespace MediaBrowser.Common.ScheduledTasks
|
|||
{
|
||||
if (isApplicationStartup)
|
||||
{
|
||||
await Task.Delay(2000).ConfigureAwait(false);
|
||||
await Task.Delay(3000).ConfigureAwait(false);
|
||||
|
||||
OnTriggered();
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
||||
|
|
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 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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
|
|
|
@ -253,4 +253,7 @@ Global
|
|||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue
Block a user