diff options
36 files changed, 604 insertions, 689 deletions
diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index 104ae7660..0fef1cb57 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -170,7 +170,7 @@ namespace MediaBrowser.Api dto.TrailerUrl = item.TrailerUrl;
dto.Type = item.GetType().Name;
- dto.UserRating = item.UserRating;
+ dto.CommunityRating = item.CommunityRating;
dto.UserData = GetDtoUserItemData(item.GetUserData(user, false));
diff --git a/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs b/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs index 7ad0ed8aa..96ef60681 100644 --- a/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs @@ -90,14 +90,15 @@ namespace MediaBrowser.Api.HttpHandlers }
}
- public override Task<string> GetContentType()
+ protected override Task<ResponseInfo> GetResponseInfo()
{
- return Task.FromResult(MimeTypes.GetMimeType("." + GetConversionOutputFormat()));
- }
+ ResponseInfo info = new ResponseInfo
+ {
+ ContentType = MimeTypes.GetMimeType("." + GetConversionOutputFormat()),
+ CompressResponse = false
+ };
- public override bool ShouldCompressResponse(string contentType)
- {
- return false;
+ return Task.FromResult<ResponseInfo>(info);
}
public override Task ProcessRequest(HttpListenerContext ctx)
diff --git a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs index f73f783af..4aa367fb7 100644 --- a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs @@ -1,13 +1,12 @@ -using MediaBrowser.Common.Logging;
-using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Controller;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
using System;
using System.ComponentModel.Composition;
using System.IO;
-using System.Linq;
using System.Net;
using System.Threading.Tasks;
@@ -20,8 +19,9 @@ namespace MediaBrowser.Api.HttpHandlers {
return ApiService.IsApiUrlMatch("image", request);
}
-
+
private string _imagePath;
+
private async Task<string> GetImagePath()
{
_imagePath = _imagePath ?? await DiscoverImagePath();
@@ -29,119 +29,99 @@ namespace MediaBrowser.Api.HttpHandlers return _imagePath;
}
- private async Task<string> DiscoverImagePath()
- {
- string personName = QueryString["personname"];
-
- if (!string.IsNullOrEmpty(personName))
- {
- return (await Kernel.Instance.ItemController.GetPerson(personName).ConfigureAwait(false)).PrimaryImagePath;
- }
-
- string genreName = QueryString["genre"];
-
- if (!string.IsNullOrEmpty(genreName))
- {
- return (await Kernel.Instance.ItemController.GetGenre(genreName).ConfigureAwait(false)).PrimaryImagePath;
- }
-
- string year = QueryString["year"];
-
- if (!string.IsNullOrEmpty(year))
- {
- return (await Kernel.Instance.ItemController.GetYear(int.Parse(year)).ConfigureAwait(false)).PrimaryImagePath;
- }
-
- string studio = QueryString["studio"];
-
- if (!string.IsNullOrEmpty(studio))
- {
- return (await Kernel.Instance.ItemController.GetStudio(studio).ConfigureAwait(false)).PrimaryImagePath;
- }
-
- string userId = QueryString["userid"];
-
- if (!string.IsNullOrEmpty(userId))
- {
- return ApiService.GetUserById(userId, false).PrimaryImagePath;
- }
-
- BaseItem item = ApiService.GetItemById(QueryString["id"]);
-
- string imageIndex = QueryString["index"];
- int index = string.IsNullOrEmpty(imageIndex) ? 0 : int.Parse(imageIndex);
-
- return GetImagePathFromTypes(item, ImageType, index);
- }
-
- private Stream _sourceStream;
- private async Task<Stream> GetSourceStream()
- {
- await EnsureSourceStream().ConfigureAwait(false);
- return _sourceStream;
- }
+ private BaseEntity _sourceEntity;
- private bool _sourceStreamEnsured;
- private async Task EnsureSourceStream()
+ private async Task<BaseEntity> GetSourceEntity()
{
- if (!_sourceStreamEnsured)
+ if (_sourceEntity == null)
{
- try
+ if (!string.IsNullOrEmpty(QueryString["personname"]))
{
- _sourceStream = File.OpenRead(await GetImagePath().ConfigureAwait(false));
+ _sourceEntity =
+ await Kernel.Instance.ItemController.GetPerson(QueryString["personname"]).ConfigureAwait(false);
}
- catch (FileNotFoundException ex)
+
+ else if (!string.IsNullOrEmpty(QueryString["genre"]))
{
- StatusCode = 404;
- Logger.LogException(ex);
+ _sourceEntity =
+ await Kernel.Instance.ItemController.GetGenre(QueryString["genre"]).ConfigureAwait(false);
}
- catch (DirectoryNotFoundException ex)
+
+ else if (!string.IsNullOrEmpty(QueryString["year"]))
{
- StatusCode = 404;
- Logger.LogException(ex);
+ _sourceEntity =
+ await
+ Kernel.Instance.ItemController.GetYear(int.Parse(QueryString["year"])).ConfigureAwait(false);
}
- catch (UnauthorizedAccessException ex)
+
+ else if (!string.IsNullOrEmpty(QueryString["studio"]))
{
- StatusCode = 403;
- Logger.LogException(ex);
+ _sourceEntity =
+ await Kernel.Instance.ItemController.GetStudio(QueryString["studio"]).ConfigureAwait(false);
}
- finally
+
+ else if (!string.IsNullOrEmpty(QueryString["userid"]))
{
- _sourceStreamEnsured = true;
+ _sourceEntity = ApiService.GetUserById(QueryString["userid"], false);
+ }
+
+ else
+ {
+ _sourceEntity = ApiService.GetItemById(QueryString["id"]);
}
}
+
+ return _sourceEntity;
}
- public async override Task<string> GetContentType()
+ private async Task<string> DiscoverImagePath()
{
- await EnsureSourceStream().ConfigureAwait(false);
+ var entity = await GetSourceEntity().ConfigureAwait(false);
+
+ return ImageProcessor.GetImagePath(entity, ImageType, ImageIndex);
+ }
+
+ protected async override Task<ResponseInfo> GetResponseInfo()
+ {
+ string path = await GetImagePath().ConfigureAwait(false);
+
+ ResponseInfo info = new ResponseInfo
+ {
+ CacheDuration = TimeSpan.FromDays(365),
+ ContentType = MimeTypes.GetMimeType(path)
+ };
- if (await GetSourceStream().ConfigureAwait(false) == null)
+ DateTime? date = File.GetLastWriteTimeUtc(path);
+
+ // If the file does not exist it will return jan 1, 1601
+ // http://msdn.microsoft.com/en-us/library/system.io.file.getlastwritetimeutc.aspx
+ if (date.Value.Year == 1601)
{
- return null;
+ if (!File.Exists(path))
+ {
+ info.StatusCode = 404;
+ date = null;
+ }
}
- return MimeTypes.GetMimeType(await GetImagePath().ConfigureAwait(false));
+ info.DateLastModified = date;
+
+ return info;
}
- public override TimeSpan CacheDuration
+ private int ImageIndex
{
get
{
- return TimeSpan.FromDays(365);
- }
- }
+ string val = QueryString["index"];
- protected async override Task<DateTime?> GetLastDateModified()
- {
- await EnsureSourceStream().ConfigureAwait(false);
+ if (string.IsNullOrEmpty(val))
+ {
+ return 0;
+ }
- if (await GetSourceStream().ConfigureAwait(false) == null)
- {
- return null;
+ return int.Parse(val);
}
-
- return File.GetLastWriteTimeUtc(await GetImagePath().ConfigureAwait(false));
}
private int? Height
@@ -236,33 +216,9 @@ namespace MediaBrowser.Api.HttpHandlers protected override async Task WriteResponseToOutputStream(Stream stream)
{
- ImageProcessor.ProcessImage(await GetSourceStream().ConfigureAwait(false), stream, Width, Height, MaxWidth, MaxHeight, Quality);
- }
-
- private string GetImagePathFromTypes(BaseItem item, ImageType imageType, int imageIndex)
- {
- if (imageType == ImageType.Logo)
- {
- return item.LogoImagePath;
- }
- if (imageType == ImageType.Backdrop)
- {
- return item.BackdropImagePaths.ElementAt(imageIndex);
- }
- if (imageType == ImageType.Banner)
- {
- return item.BannerImagePath;
- }
- if (imageType == ImageType.Art)
- {
- return item.ArtImagePath;
- }
- if (imageType == ImageType.Thumbnail)
- {
- return item.ThumbnailImagePath;
- }
+ var entity = await GetSourceEntity().ConfigureAwait(false);
- return item.PrimaryImagePath;
+ ImageProcessor.ProcessImage(entity, ImageType, ImageIndex, stream, Width, Height, MaxWidth, MaxHeight, Quality);
}
}
}
diff --git a/MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs b/MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs index 88161c114..47f08c8c3 100644 --- a/MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs @@ -15,8 +15,8 @@ namespace MediaBrowser.Api.HttpHandlers {
return ApiService.IsApiUrlMatch("pluginassembly", request);
}
-
- public override Task<string> GetContentType()
+
+ protected override Task<ResponseInfo> GetResponseInfo()
{
throw new NotImplementedException();
}
diff --git a/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs b/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs index 95af9a344..dc363956f 100644 --- a/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Api.HttpHandlers {
return ApiService.IsApiUrlMatch("pluginconfiguration", request);
}
-
+
private BasePlugin _plugin;
private BasePlugin Plugin
{
@@ -39,18 +39,15 @@ namespace MediaBrowser.Api.HttpHandlers return Task.FromResult(Plugin.Configuration);
}
- public override TimeSpan CacheDuration
+ protected override async Task<ResponseInfo> GetResponseInfo()
{
- get
- {
- return TimeSpan.FromDays(7);
- }
- }
+ var info = await base.GetResponseInfo().ConfigureAwait(false);
- protected override Task<DateTime?> GetLastDateModified()
- {
- return Task.FromResult<DateTime?>(Plugin.ConfigurationDateLastModified);
- }
+ info.DateLastModified = Plugin.ConfigurationDateLastModified;
+ info.CacheDuration = TimeSpan.FromDays(7);
+
+ return info;
+ }
}
}
diff --git a/MediaBrowser.Api/HttpHandlers/ServerConfigurationHandler.cs b/MediaBrowser.Api/HttpHandlers/ServerConfigurationHandler.cs index 64ba44ec2..48c6761b1 100644 --- a/MediaBrowser.Api/HttpHandlers/ServerConfigurationHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ServerConfigurationHandler.cs @@ -16,23 +16,22 @@ namespace MediaBrowser.Api.HttpHandlers {
return ApiService.IsApiUrlMatch("serverconfiguration", request);
}
-
+
protected override Task<ServerConfiguration> GetObjectToSerialize()
{
return Task.FromResult(Kernel.Instance.Configuration);
}
- public override TimeSpan CacheDuration
+ protected override async Task<ResponseInfo> GetResponseInfo()
{
- get
- {
- return TimeSpan.FromDays(7);
- }
- }
+ var info = await base.GetResponseInfo().ConfigureAwait(false);
- protected override Task<DateTime?> GetLastDateModified()
- {
- return Task.FromResult<DateTime?>(File.GetLastWriteTimeUtc(Kernel.Instance.ApplicationPaths.SystemConfigurationFilePath));
+ info.DateLastModified =
+ File.GetLastWriteTimeUtc(Kernel.Instance.ApplicationPaths.SystemConfigurationFilePath);
+
+ info.CacheDuration = TimeSpan.FromDays(7);
+
+ return info;
}
}
}
diff --git a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs index 9d52136f0..e34a1b41f 100644 --- a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs @@ -1,5 +1,5 @@ -using MediaBrowser.Common.Drawing;
-using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.DTO;
using MediaBrowser.Model.Entities;
@@ -7,7 +7,6 @@ using System; using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Drawing;
-using System.IO;
using System.Linq;
using System.Net;
diff --git a/MediaBrowser.Api/HttpHandlers/WeatherHandler.cs b/MediaBrowser.Api/HttpHandlers/WeatherHandler.cs index 93d4c8877..378e89067 100644 --- a/MediaBrowser.Api/HttpHandlers/WeatherHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/WeatherHandler.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller; using MediaBrowser.Model.Weather;
using System;
using System.ComponentModel.Composition;
+using System.Linq;
using System.Net;
using System.Threading.Tasks;
@@ -15,7 +16,7 @@ namespace MediaBrowser.Api.HttpHandlers {
return ApiService.IsApiUrlMatch("weather", request);
}
-
+
protected override Task<WeatherInfo> GetObjectToSerialize()
{
// If a specific zip code was requested on the query string, use that. Otherwise use the value from configuration
@@ -27,18 +28,16 @@ namespace MediaBrowser.Api.HttpHandlers zipCode = Kernel.Instance.Configuration.WeatherZipCode;
}
- return Kernel.Instance.WeatherClient.GetWeatherInfoAsync(zipCode);
+ return Kernel.Instance.WeatherProviders.First().GetWeatherInfoAsync(zipCode);
}
- /// <summary>
- /// Tell the client to cache the weather info for 15 minutes
- /// </summary>
- public override TimeSpan CacheDuration
+ protected override async Task<ResponseInfo> GetResponseInfo()
{
- get
- {
- return TimeSpan.FromMinutes(15);
- }
+ var info = await base.GetResponseInfo().ConfigureAwait(false);
+
+ info.CacheDuration = TimeSpan.FromMinutes(15);
+
+ return info;
}
}
}
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 858717e6e..44b58852b 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -83,7 +83,6 @@ <Compile Include="HttpHandlers\WeatherHandler.cs" />
<Compile Include="HttpHandlers\YearHandler.cs" />
<Compile Include="HttpHandlers\YearsHandler.cs" />
- <Compile Include="ImageProcessor.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
diff --git a/MediaBrowser.Api/Plugin.cs b/MediaBrowser.Api/Plugin.cs index b2bcefd1f..8def96da8 100644 --- a/MediaBrowser.Api/Plugin.cs +++ b/MediaBrowser.Api/Plugin.cs @@ -1,5 +1,4 @@ using MediaBrowser.Common.Plugins;
-using MediaBrowser.Model.Plugins;
using System.ComponentModel.Composition;
namespace MediaBrowser.Api
diff --git a/MediaBrowser.Common/Events/GenericEventArgs.cs b/MediaBrowser.Common/Events/GenericEventArgs.cs new file mode 100644 index 000000000..98e072816 --- /dev/null +++ b/MediaBrowser.Common/Events/GenericEventArgs.cs @@ -0,0 +1,12 @@ +using System;
+
+namespace MediaBrowser.Common.Events
+{
+ /// <summary>
+ /// Provides a generic EventArgs subclass that can hold any kind of object
+ /// </summary>
+ public class GenericEventArgs<T> : EventArgs
+ {
+ public T Argument { get; set; }
+ }
+}
diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 1fdc597ea..5a0e1c5e5 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Common.Logging;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Common.Logging;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net.Handlers;
using MediaBrowser.Common.Plugins;
@@ -9,7 +10,6 @@ using System; using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
-using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -24,6 +24,34 @@ namespace MediaBrowser.Common.Kernel where TConfigurationType : BaseApplicationConfiguration, new()
where TApplicationPathsType : BaseApplicationPaths, new()
{
+ #region ReloadBeginning Event
+ /// <summary>
+ /// Fires whenever the kernel begins reloading
+ /// </summary>
+ public event EventHandler<GenericEventArgs<IProgress<TaskProgress>>> ReloadBeginning;
+ private void OnReloadBeginning(IProgress<TaskProgress> progress)
+ {
+ if (ReloadBeginning != null)
+ {
+ ReloadBeginning(this, new GenericEventArgs<IProgress<TaskProgress>> { Argument = progress });
+ }
+ }
+ #endregion
+
+ #region ReloadCompleted Event
+ /// <summary>
+ /// Fires whenever the kernel completes reloading
+ /// </summary>
+ public event EventHandler<GenericEventArgs<IProgress<TaskProgress>>> ReloadCompleted;
+ private void OnReloadCompleted(IProgress<TaskProgress> progress)
+ {
+ if (ReloadCompleted != null)
+ {
+ ReloadCompleted(this, new GenericEventArgs<IProgress<TaskProgress>> { Argument = progress });
+ }
+ }
+ #endregion
+
/// <summary>
/// Gets the current configuration
/// </summary>
@@ -44,6 +72,12 @@ namespace MediaBrowser.Common.Kernel private IEnumerable<BaseHandler> HttpHandlers { get; set; }
/// <summary>
+ /// Gets the list of currently registered Loggers
+ /// </summary>
+ [ImportMany(typeof(BaseLogger))]
+ public IEnumerable<BaseLogger> Loggers { get; set; }
+
+ /// <summary>
/// Both the Ui and server will have a built-in HttpServer.
/// People will inevitably want remote control apps so it's needed in the Ui too.
/// </summary>
@@ -54,6 +88,8 @@ namespace MediaBrowser.Common.Kernel /// </summary>
private IDisposable HttpListener { get; set; }
+ private CompositionContainer CompositionContainer { get; set; }
+
protected virtual string HttpServerUrlPrefix
{
get
@@ -72,13 +108,13 @@ namespace MediaBrowser.Common.Kernel /// </summary>
public async Task Init(IProgress<TaskProgress> progress)
{
+ Logger.Kernel = this;
+
// Performs initializations that only occur once
InitializeInternal(progress);
// Performs initializations that can be reloaded at anytime
await Reload(progress).ConfigureAwait(false);
-
- progress.Report(new TaskProgress { Description = "Loading Complete" });
}
/// <summary>
@@ -87,44 +123,39 @@ namespace MediaBrowser.Common.Kernel protected virtual void InitializeInternal(IProgress<TaskProgress> progress)
{
ApplicationPaths = new TApplicationPathsType();
-
- ReloadLogger();
- progress.Report(new TaskProgress { Description = "Loading configuration" });
+ ReportProgress(progress, "Loading Configuration");
ReloadConfiguration();
- progress.Report(new TaskProgress { Description = "Starting Http server" });
+ ReportProgress(progress, "Loading Http Server");
ReloadHttpServer();
}
/// <summary>
/// Performs initializations that can be reloaded at anytime
/// </summary>
- public virtual async Task Reload(IProgress<TaskProgress> progress)
+ public async Task Reload(IProgress<TaskProgress> progress)
{
- await Task.Run(() =>
- {
- progress.Report(new TaskProgress { Description = "Loading Plugins" });
- ReloadComposableParts();
+ OnReloadBeginning(progress);
- }).ConfigureAwait(false);
+ await ReloadInternal(progress).ConfigureAwait(false);
+
+ OnReloadCompleted(progress);
+
+ ReportProgress(progress, "Kernel.Reload Complete");
}
-
+
/// <summary>
- /// Disposes the current logger and creates a new one
+ /// Performs initializations that can be reloaded at anytime
/// </summary>
- private void ReloadLogger()
+ protected virtual async Task ReloadInternal(IProgress<TaskProgress> progress)
{
- DisposeLogger();
-
- DateTime now = DateTime.Now;
-
- string logFilePath = Path.Combine(ApplicationPaths.LogDirectoryPath, "log-" + now.ToString("dMyyyy") + "-" + now.Ticks + ".log");
-
- Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));
- Trace.AutoFlush = true;
+ await Task.Run(() =>
+ {
+ ReportProgress(progress, "Loading Plugins");
+ ReloadComposableParts();
- Logger.LoggerInstance = new TraceLogger();
+ }).ConfigureAwait(false);
}
/// <summary>
@@ -135,14 +166,13 @@ namespace MediaBrowser.Common.Kernel {
DisposeComposableParts();
- var container = GetCompositionContainer(includeCurrentAssembly: true);
+ CompositionContainer = GetCompositionContainer(includeCurrentAssembly: true);
- container.ComposeParts(this);
+ CompositionContainer.ComposeParts(this);
OnComposablePartsLoaded();
- container.Catalog.Dispose();
- container.Dispose();
+ CompositionContainer.Catalog.Dispose();
}
/// <summary>
@@ -157,8 +187,7 @@ namespace MediaBrowser.Common.Kernel var catalog = new AggregateCatalog(pluginAssemblies.Select(a => new AssemblyCatalog(a)));
// Include composable parts in the Common assembly
- // Uncomment this if it's ever needed
- //catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
+ catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
if (includeCurrentAssembly)
{
@@ -174,8 +203,13 @@ namespace MediaBrowser.Common.Kernel /// </summary>
protected virtual void OnComposablePartsLoaded()
{
+ foreach (var logger in Loggers)
+ {
+ logger.Initialize(this);
+ }
+
// Start-up each plugin
- foreach (BasePlugin plugin in Plugins)
+ foreach (var plugin in Plugins)
{
plugin.Initialize(this);
}
@@ -189,17 +223,16 @@ namespace MediaBrowser.Common.Kernel //Configuration information for anything other than server-specific configuration will have to come via the API... -ebr
// Deserialize config
- if (!File.Exists(ApplicationPaths.SystemConfigurationFilePath))
+ // Use try/catch to avoid the extra file system lookup using File.Exists
+ try
{
- Configuration = new TConfigurationType();
- XmlSerializer.SerializeToFile(Configuration, ApplicationPaths.SystemConfigurationFilePath);
+ Configuration = XmlSerializer.DeserializeFromFile<TConfigurationType>(ApplicationPaths.SystemConfigurationFilePath);
}
- else
+ catch (FileNotFoundException)
{
- Configuration = XmlSerializer.DeserializeFromFile<TConfigurationType>(ApplicationPaths.SystemConfigurationFilePath);
+ Configuration = new TConfigurationType();
+ XmlSerializer.SerializeToFile(Configuration, ApplicationPaths.SystemConfigurationFilePath);
}
-
- Logger.LoggerInstance.LogSeverity = Configuration.EnableDebugLevelLogging ? LogSeverity.Debug : LogSeverity.Info;
}
/// <summary>
@@ -233,12 +266,10 @@ namespace MediaBrowser.Common.Kernel public virtual void Dispose()
{
Logger.LogInfo("Beginning Kernel.Dispose");
-
- DisposeComposableParts();
DisposeHttpServer();
- DisposeLogger();
+ DisposeComposableParts();
}
/// <summary>
@@ -246,22 +277,9 @@ namespace MediaBrowser.Common.Kernel /// </summary>
protected virtual void DisposeComposableParts()
{
- DisposePlugins();
- }
-
- /// <summary>
- /// Disposes all plugins
- /// </summary>
- private void DisposePlugins()
- {
- if (Plugins != null)
+ if (CompositionContainer != null)
{
- Logger.LogInfo("Disposing Plugins");
-
- foreach (BasePlugin plugin in Plugins)
- {
- plugin.Dispose();
- }
+ CompositionContainer.Dispose();
}
}
@@ -273,7 +291,7 @@ namespace MediaBrowser.Common.Kernel if (HttpServer != null)
{
Logger.LogInfo("Disposing Http Server");
-
+
HttpServer.Dispose();
}
@@ -284,21 +302,6 @@ namespace MediaBrowser.Common.Kernel }
/// <summary>
- /// Disposes the current Logger instance
- /// </summary>
- private void DisposeLogger()
- {
- Trace.Listeners.Clear();
-
- if (Logger.LoggerInstance != null)
- {
- Logger.LogInfo("Disposing Logger");
-
- Logger.LoggerInstance.Dispose();
- }
- }
-
- /// <summary>
/// Gets the current application version
/// </summary>
public Version ApplicationVersion
@@ -309,6 +312,13 @@ namespace MediaBrowser.Common.Kernel }
}
+ protected void ReportProgress(IProgress<TaskProgress> progress, string message)
+ {
+ progress.Report(new TaskProgress { Description = message });
+
+ Logger.LogInfo(message);
+ }
+
BaseApplicationPaths IKernel.ApplicationPaths
{
get { return ApplicationPaths; }
@@ -322,6 +332,7 @@ namespace MediaBrowser.Common.Kernel Task Init(IProgress<TaskProgress> progress);
Task Reload(IProgress<TaskProgress> progress);
+ IEnumerable<BaseLogger> Loggers { get; }
void Dispose();
}
}
diff --git a/MediaBrowser.Common/Logging/BaseLogger.cs b/MediaBrowser.Common/Logging/BaseLogger.cs index 572ce36b2..a97bc201f 100644 --- a/MediaBrowser.Common/Logging/BaseLogger.cs +++ b/MediaBrowser.Common/Logging/BaseLogger.cs @@ -1,92 +1,16 @@ -using System;
-using System.Text;
-using System.Threading;
+using MediaBrowser.Common.Kernel;
+using System;
namespace MediaBrowser.Common.Logging
{
public abstract class BaseLogger : IDisposable
{
- public LogSeverity LogSeverity { get; set; }
-
- public void LogInfo(string message, params object[] paramList)
- {
- LogEntry(message, LogSeverity.Info, paramList);
- }
-
- public void LogDebugInfo(string message, params object[] paramList)
- {
- LogEntry(message, LogSeverity.Debug, paramList);
- }
-
- public void LogError(string message, params object[] paramList)
- {
- LogEntry(message, LogSeverity.Error, paramList);
- }
-
- public void LogException(string message, Exception exception, params object[] paramList)
- {
- var builder = new StringBuilder();
-
- if (exception != null)
- {
- builder.AppendFormat("Exception. Type={0} Msg={1} StackTrace={3}{2}",
- exception.GetType().FullName,
- exception.Message,
- exception.StackTrace,
- Environment.NewLine);
- }
-
- message = FormatMessage(message, paramList);
-
- LogError(string.Format("{0} ( {1} )", message, builder));
- }
-
- public void LogWarning(string message, params object[] paramList)
- {
- LogEntry(message, LogSeverity.Warning, paramList);
- }
-
- private string FormatMessage(string message, params object[] paramList)
- {
- if (paramList != null)
- {
- for (int i = 0; i < paramList.Length; i++)
- {
- message = message.Replace("{" + i + "}", paramList[i].ToString());
- }
- }
-
- return message;
- }
-
- private void LogEntry(string message, LogSeverity severity, params object[] paramList)
- {
- if (severity < LogSeverity) return;
-
- message = FormatMessage(message, paramList);
-
- Thread currentThread = Thread.CurrentThread;
-
- var row = new LogRow
- {
- Severity = severity,
- Message = message,
- ThreadId = currentThread.ManagedThreadId,
- ThreadName = currentThread.Name,
- Time = DateTime.Now
- };
-
- LogEntry(row);
- }
-
- protected virtual void Flush()
- {
- }
+ public abstract void Initialize(IKernel kernel);
+ public abstract void LogEntry(LogRow row);
public virtual void Dispose()
{
+ Logger.LogInfo("Disposing " + GetType().Name);
}
-
- protected abstract void LogEntry(LogRow row);
}
}
diff --git a/MediaBrowser.Common/Logging/LogSeverity.cs b/MediaBrowser.Common/Logging/LogSeverity.cs index 2abab1a44..97abfe7b5 100644 --- a/MediaBrowser.Common/Logging/LogSeverity.cs +++ b/MediaBrowser.Common/Logging/LogSeverity.cs @@ -1,4 +1,4 @@ -using System;
+using System;
namespace MediaBrowser.Common.Logging
{
@@ -11,4 +11,4 @@ namespace MediaBrowser.Common.Logging Warning = 4,
Error = 8
}
-}
+}
\ No newline at end of file diff --git a/MediaBrowser.Common/Logging/Logger.cs b/MediaBrowser.Common/Logging/Logger.cs index e66c1d844..9ac02fe3e 100644 --- a/MediaBrowser.Common/Logging/Logger.cs +++ b/MediaBrowser.Common/Logging/Logger.cs @@ -1,24 +1,28 @@ using System;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+using MediaBrowser.Common.Kernel;
namespace MediaBrowser.Common.Logging
{
public static class Logger
{
- public static BaseLogger LoggerInstance { get; set; }
+ internal static IKernel Kernel { get; set; }
public static void LogInfo(string message, params object[] paramList)
{
- LoggerInstance.LogInfo(message, paramList);
+ LogEntry(message, LogSeverity.Info, paramList);
}
public static void LogDebugInfo(string message, params object[] paramList)
{
- LoggerInstance.LogDebugInfo(message, paramList);
+ LogEntry(message, LogSeverity.Debug, paramList);
}
public static void LogError(string message, params object[] paramList)
{
- LoggerInstance.LogError(message, paramList);
+ LogEntry(message, LogSeverity.Error, paramList);
}
public static void LogException(Exception ex, params object[] paramList)
@@ -28,12 +32,62 @@ namespace MediaBrowser.Common.Logging public static void LogException(string message, Exception ex, params object[] paramList)
{
- LoggerInstance.LogException(message, ex, paramList);
+ var builder = new StringBuilder();
+
+ if (ex != null)
+ {
+ builder.AppendFormat("Exception. Type={0} Msg={1} StackTrace={3}{2}",
+ ex.GetType().FullName,
+ ex.Message,
+ ex.StackTrace,
+ Environment.NewLine);
+ }
+
+ message = FormatMessage(message, paramList);
+
+ LogError(string.Format("{0} ( {1} )", message, builder));
}
public static void LogWarning(string message, params object[] paramList)
{
- LoggerInstance.LogWarning(message, paramList);
+ LogEntry(message, LogSeverity.Warning, paramList);
+ }
+
+ private static void LogEntry(string message, LogSeverity severity, params object[] paramList)
+ {
+ message = FormatMessage(message, paramList);
+
+ Thread currentThread = Thread.CurrentThread;
+
+ var row = new LogRow
+ {
+ Severity = severity,
+ Message = message,
+ ThreadId = currentThread.ManagedThreadId,
+ ThreadName = currentThread.Name,
+ Time = DateTime.Now
+ };
+
+ if (Kernel.Loggers != null)
+ {
+ foreach (var logger in Kernel.Loggers)
+ {
+ logger.LogEntry(row);
+ }
+ }
+ }
+
+ private static string FormatMessage(string message, params object[] paramList)
+ {
+ if (paramList != null)
+ {
+ for (int i = 0; i < paramList.Length; i++)
+ {
+ message = message.Replace("{" + i + "}", paramList[i].ToString());
+ }
+ }
+
+ return message;
}
}
}
diff --git a/MediaBrowser.Common/Logging/StreamLogger.cs b/MediaBrowser.Common/Logging/StreamLogger.cs deleted file mode 100644 index 03b9bd6d2..000000000 --- a/MediaBrowser.Common/Logging/StreamLogger.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System;
-using System.IO;
-using System.Text;
-
-namespace MediaBrowser.Common.Logging
-{
- /// <summary>
- /// Provides a Logger that can write to any Stream
- /// </summary>
- public class StreamLogger : BaseLogger
- {
- private Stream Stream { get; set; }
-
- public StreamLogger(Stream stream)
- : base()
- {
- Stream = stream;
- }
-
- protected override void LogEntry(LogRow row)
- {
- byte[] bytes = new UTF8Encoding().GetBytes(row.ToString() + Environment.NewLine);
-
- lock (Stream)
- {
- Stream.Write(bytes, 0, bytes.Length);
- Stream.Flush();
- }
- }
-
- public override void Dispose()
- {
- base.Dispose();
- Stream.Dispose();
- }
- }
-}
diff --git a/MediaBrowser.Common/Logging/TraceFileLogger.cs b/MediaBrowser.Common/Logging/TraceFileLogger.cs new file mode 100644 index 000000000..7ab67a137 --- /dev/null +++ b/MediaBrowser.Common/Logging/TraceFileLogger.cs @@ -0,0 +1,38 @@ +using MediaBrowser.Common.Kernel;
+using System;
+using System.ComponentModel.Composition;
+using System.Diagnostics;
+using System.IO;
+
+namespace MediaBrowser.Common.Logging
+{
+ [Export(typeof(BaseLogger))]
+ public class TraceFileLogger : BaseLogger
+ {
+ private TraceListener Listener { get; set; }
+
+ public override void Initialize(IKernel kernel)
+ {
+ DateTime now = DateTime.Now;
+
+ string logFilePath = Path.Combine(kernel.ApplicationPaths.LogDirectoryPath, "log-" + now.ToString("dMyyyy") + "-" + now.Ticks + ".log");
+
+ Listener = new TextWriterTraceListener(logFilePath);
+ Trace.Listeners.Add(Listener);
+ Trace.AutoFlush = true;
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+
+ Trace.Listeners.Remove(Listener);
+ Listener.Dispose();
+ }
+
+ public override void LogEntry(LogRow row)
+ {
+ Trace.WriteLine(row.ToString());
+ }
+ }
+}
diff --git a/MediaBrowser.Common/Logging/TraceLogger.cs b/MediaBrowser.Common/Logging/TraceLogger.cs deleted file mode 100644 index d152f9780..000000000 --- a/MediaBrowser.Common/Logging/TraceLogger.cs +++ /dev/null @@ -1,12 +0,0 @@ -using System.Diagnostics;
-
-namespace MediaBrowser.Common.Logging
-{
- public class TraceLogger : BaseLogger
- {
- protected override void LogEntry(LogRow row)
- {
- Trace.WriteLine(row.ToString());
- }
- }
-}
diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 198d78b09..baa846e48 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -82,9 +82,11 @@ </ItemGroup>
<ItemGroup>
<Compile Include="Extensions\BaseExtensions.cs" />
+ <Compile Include="Events\GenericEventArgs.cs" />
<Compile Include="Kernel\BaseApplicationPaths.cs" />
- <Compile Include="Drawing\DrawingUtils.cs" />
- <Compile Include="Logging\TraceLogger.cs" />
+ <Compile Include="Logging\BaseLogger.cs" />
+ <Compile Include="Logging\LogSeverity.cs" />
+ <Compile Include="Logging\TraceFileLogger.cs" />
<Compile Include="Net\Handlers\StaticFileHandler.cs" />
<Compile Include="Net\MimeTypes.cs" />
<Compile Include="Plugins\BaseTheme.cs" />
@@ -96,11 +98,8 @@ <Compile Include="Serialization\JsonSerializer.cs" />
<Compile Include="Kernel\BaseKernel.cs" />
<Compile Include="Kernel\KernelContext.cs" />
- <Compile Include="Logging\BaseLogger.cs" />
<Compile Include="Logging\Logger.cs" />
<Compile Include="Logging\LogRow.cs" />
- <Compile Include="Logging\LogSeverity.cs" />
- <Compile Include="Logging\StreamLogger.cs" />
<Compile Include="Net\Handlers\BaseEmbeddedResourceHandler.cs" />
<Compile Include="Net\Handlers\BaseHandler.cs" />
<Compile Include="Net\Handlers\BaseSerializationHandler.cs" />
@@ -152,6 +151,7 @@ <ItemGroup>
<Resource Include="Resources\Images\spinner.gif" />
</ItemGroup>
+ <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs index 3ce85a688..579e341fe 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs @@ -13,11 +13,6 @@ namespace MediaBrowser.Common.Net.Handlers protected string ResourcePath { get; set; }
- public override Task<string> GetContentType()
- {
- return Task.FromResult(MimeTypes.GetMimeType(ResourcePath));
- }
-
protected override Task WriteResponseToOutputStream(Stream stream)
{
return GetEmbeddedResourceStream().CopyToAsync(stream);
diff --git a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs index 1a014395a..a5058e6ca 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs @@ -112,32 +112,6 @@ namespace MediaBrowser.Common.Net.Handlers }
}
- /// <summary>
- /// Gets the MIME type to include in the response headers
- /// </summary>
- public abstract Task<string> GetContentType();
-
- /// <summary>
- /// Gets the status code to include in the response headers
- /// </summary>
- protected int StatusCode { get; set; }
-
- /// <summary>
- /// Gets the cache duration to include in the response headers
- /// </summary>
- public virtual TimeSpan CacheDuration
- {
- get
- {
- return TimeSpan.FromTicks(0);
- }
- }
-
- public virtual bool ShouldCompressResponse(string contentType)
- {
- return true;
- }
-
private bool ClientSupportsCompression
{
get
@@ -186,15 +160,21 @@ namespace MediaBrowser.Common.Net.Handlers ctx.Response.Headers["Accept-Ranges"] = "bytes";
}
- // Set the initial status code
- // When serving a range request, we need to return status code 206 to indicate a partial response body
- StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200;
+ ResponseInfo responseInfo = await GetResponseInfo().ConfigureAwait(false);
- ctx.Response.ContentType = await GetContentType().ConfigureAwait(false);
+ if (responseInfo.IsResponseValid)
+ {
+ // Set the initial status code
+ // When serving a range request, we need to return status code 206 to indicate a partial response body
+ responseInfo.StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200;
+ }
- TimeSpan cacheDuration = CacheDuration;
+ ctx.Response.ContentType = responseInfo.ContentType;
- DateTime? lastDateModified = await GetLastDateModified().ConfigureAwait(false);
+ if (!string.IsNullOrEmpty(responseInfo.Etag))
+ {
+ ctx.Response.Headers["ETag"] = responseInfo.Etag;
+ }
if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since"))
{
@@ -203,26 +183,26 @@ namespace MediaBrowser.Common.Net.Handlers if (DateTime.TryParse(ctx.Request.Headers["If-Modified-Since"], out ifModifiedSince))
{
// If the cache hasn't expired yet just return a 304
- if (IsCacheValid(ifModifiedSince.ToUniversalTime(), cacheDuration, lastDateModified))
+ if (IsCacheValid(ifModifiedSince.ToUniversalTime(), responseInfo.CacheDuration, responseInfo.DateLastModified))
{
- StatusCode = 304;
+ // ETag must also match (if supplied)
+ if ((responseInfo.Etag ?? string.Empty).Equals(ctx.Request.Headers["If-None-Match"] ?? string.Empty))
+ {
+ responseInfo.StatusCode = 304;
+ }
}
}
}
- await PrepareResponse().ConfigureAwait(false);
+ Logger.LogInfo("Responding with status code {0} for url {1}", responseInfo.StatusCode, url);
- Logger.LogInfo("Responding with status code {0} for url {1}", StatusCode, url);
-
- if (IsResponseValid)
+ if (responseInfo.IsResponseValid)
{
- bool compressResponse = ShouldCompressResponse(ctx.Response.ContentType) && ClientSupportsCompression;
-
- await ProcessUncachedRequest(ctx, compressResponse, cacheDuration, lastDateModified).ConfigureAwait(false);
+ await ProcessUncachedRequest(ctx, responseInfo).ConfigureAwait(false);
}
else
{
- ctx.Response.StatusCode = StatusCode;
+ ctx.Response.StatusCode = responseInfo.StatusCode;
ctx.Response.SendChunked = false;
}
}
@@ -239,7 +219,7 @@ namespace MediaBrowser.Common.Net.Handlers }
}
- private async Task ProcessUncachedRequest(HttpListenerContext ctx, bool compressResponse, TimeSpan cacheDuration, DateTime? lastDateModified)
+ private async Task ProcessUncachedRequest(HttpListenerContext ctx, ResponseInfo responseInfo)
{
long? totalContentLength = TotalContentLength;
@@ -258,22 +238,29 @@ namespace MediaBrowser.Common.Net.Handlers ctx.Response.ContentLength64 = totalContentLength.Value;
}
+ var compressResponse = responseInfo.CompressResponse && ClientSupportsCompression;
+
// Add the compression header
if (compressResponse)
{
ctx.Response.AddHeader("Content-Encoding", CompressionMethod);
}
+ if (responseInfo.DateLastModified.HasValue)
+ {
+ ctx.Response.Headers[HttpResponseHeader.LastModified] = responseInfo.DateLastModified.Value.ToString("r");
+ }
+
// Add caching headers
- if (cacheDuration.Ticks > 0)
+ if (responseInfo.CacheDuration.Ticks > 0)
{
- CacheResponse(ctx.Response, cacheDuration, lastDateModified);
+ CacheResponse(ctx.Response, responseInfo.CacheDuration);
}
// Set the status code
- ctx.Response.StatusCode = StatusCode;
+ ctx.Response.StatusCode = responseInfo.StatusCode;
- if (IsResponseValid)
+ if (responseInfo.IsResponseValid)
{
// Finally, write the response data
Stream outputStream = ctx.Response.OutputStream;
@@ -300,23 +287,10 @@ namespace MediaBrowser.Common.Net.Handlers }
}
- private void CacheResponse(HttpListenerResponse response, TimeSpan duration, DateTime? dateModified)
+ private void CacheResponse(HttpListenerResponse response, TimeSpan duration)
{
- DateTime now = DateTime.UtcNow;
-
- DateTime lastModified = dateModified ?? now;
-
response.Headers[HttpResponseHeader.CacheControl] = "public, max-age=" + Convert.ToInt32(duration.TotalSeconds);
- response.Headers[HttpResponseHeader.Expires] = now.Add(duration).ToString("r");
- response.Headers[HttpResponseHeader.LastModified] = lastModified.ToString("r");
- }
-
- /// <summary>
- /// Gives subclasses a chance to do any prep work, and also to validate data and set an error status code, if needed
- /// </summary>
- protected virtual Task PrepareResponse()
- {
- return Task.FromResult<object>(null);
+ response.Headers[HttpResponseHeader.Expires] = DateTime.UtcNow.Add(duration).ToString("r");
}
protected abstract Task WriteResponseToOutputStream(Stream stream);
@@ -364,20 +338,7 @@ namespace MediaBrowser.Common.Net.Handlers return null;
}
- protected virtual Task<DateTime?> GetLastDateModified()
- {
- DateTime? value = null;
-
- return Task.FromResult(value);
- }
-
- private bool IsResponseValid
- {
- get
- {
- return StatusCode == 200 || StatusCode == 206;
- }
- }
+ protected abstract Task<ResponseInfo> GetResponseInfo();
private Hashtable _formValues;
@@ -439,4 +400,31 @@ namespace MediaBrowser.Common.Net.Handlers return formVars;
}
}
+
+ public class ResponseInfo
+ {
+ public string ContentType { get; set; }
+ public string Etag { get; set; }
+ public DateTime? DateLastModified { get; set; }
+ public TimeSpan CacheDuration { get; set; }
+ public bool CompressResponse { get; set; }
+ public int StatusCode { get; set; }
+
+ public ResponseInfo()
+ {
+ CacheDuration = TimeSpan.FromTicks(0);
+
+ CompressResponse = true;
+
+ StatusCode = 200;
+ }
+
+ public bool IsResponseValid
+ {
+ get
+ {
+ return StatusCode == 200 || StatusCode == 206;
+ }
+ }
+ }
}
\ No newline at end of file diff --git a/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs index d60a9ae1f..53b3ee817 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs @@ -1,12 +1,12 @@ -using System;
+using MediaBrowser.Common.Serialization;
+using System;
using System.IO;
using System.Threading.Tasks;
-using MediaBrowser.Common.Serialization;
namespace MediaBrowser.Common.Net.Handlers
{
public abstract class BaseSerializationHandler<T> : BaseHandler
- where T : class
+ where T : class
{
public SerializationFormat SerializationFormat
{
@@ -22,61 +22,61 @@ namespace MediaBrowser.Common.Net.Handlers return (SerializationFormat)Enum.Parse(typeof(SerializationFormat), format, true);
}
}
-
- public override Task<string> GetContentType()
+
+ protected string ContentType
{
- switch (SerializationFormat)
+ get
{
- case SerializationFormat.Jsv:
- return Task.FromResult("text/plain");
- case SerializationFormat.Protobuf:
- return Task.FromResult("application/x-protobuf");
- default:
- return Task.FromResult(MimeTypes.JsonMimeType);
+ switch (SerializationFormat)
+ {
+ case SerializationFormat.Jsv:
+ return "text/plain";
+ case SerializationFormat.Protobuf:
+ return "application/x-protobuf";
+ default:
+ return MimeTypes.JsonMimeType;
+ }
}
}
- private bool _objectToSerializeEnsured;
- private T _objectToSerialize;
-
- private async Task EnsureObjectToSerialize()
+ protected override async Task<ResponseInfo> GetResponseInfo()
{
- if (!_objectToSerializeEnsured)
+ ResponseInfo info = new ResponseInfo
{
- _objectToSerialize = await GetObjectToSerialize().ConfigureAwait(false);
+ ContentType = ContentType
+ };
- if (_objectToSerialize == null)
- {
- StatusCode = 404;
- }
+ _objectToSerialize = await GetObjectToSerialize().ConfigureAwait(false);
- _objectToSerializeEnsured = true;
+ if (_objectToSerialize == null)
+ {
+ info.StatusCode = 404;
}
+
+ return info;
}
- protected abstract Task<T> GetObjectToSerialize();
+ private T _objectToSerialize;
- protected override Task PrepareResponse()
- {
- return EnsureObjectToSerialize();
- }
+ protected abstract Task<T> GetObjectToSerialize();
- protected async override Task WriteResponseToOutputStream(Stream stream)
+ protected override Task WriteResponseToOutputStream(Stream stream)
{
- await EnsureObjectToSerialize().ConfigureAwait(false);
-
- switch (SerializationFormat)
+ return Task.Run(() =>
{
- case SerializationFormat.Jsv:
- JsvSerializer.SerializeToStream(_objectToSerialize, stream);
- break;
- case SerializationFormat.Protobuf:
- ProtobufSerializer.SerializeToStream(_objectToSerialize, stream);
- break;
- default:
- JsonSerializer.SerializeToStream(_objectToSerialize, stream);
- break;
- }
+ switch (SerializationFormat)
+ {
+ case SerializationFormat.Jsv:
+ JsvSerializer.SerializeToStream(_objectToSerialize, stream);
+ break;
+ case SerializationFormat.Protobuf:
+ ProtobufSerializer.SerializeToStream(_objectToSerialize, stream);
+ break;
+ default:
+ JsonSerializer.SerializeToStream(_objectToSerialize, stream);
+ break;
+ }
+ });
}
}
diff --git a/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs b/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs index 741d2d6c1..11438b164 100644 --- a/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs @@ -33,46 +33,7 @@ namespace MediaBrowser.Common.Net.Handlers }
}
- private bool _sourceStreamEnsured;
- private Stream _sourceStream;
- private Stream SourceStream
- {
- get
- {
- EnsureSourceStream();
- return _sourceStream;
- }
- }
-
- private void EnsureSourceStream()
- {
- if (!_sourceStreamEnsured)
- {
- try
- {
- _sourceStream = File.OpenRead(Path);
- }
- catch (FileNotFoundException ex)
- {
- StatusCode = 404;
- Logger.LogException(ex);
- }
- catch (DirectoryNotFoundException ex)
- {
- StatusCode = 404;
- Logger.LogException(ex);
- }
- catch (UnauthorizedAccessException ex)
- {
- StatusCode = 403;
- Logger.LogException(ex);
- }
- finally
- {
- _sourceStreamEnsured = true;
- }
- }
- }
+ private Stream SourceStream { get; set; }
protected override bool SupportsByteRangeRequests
{
@@ -82,7 +43,7 @@ namespace MediaBrowser.Common.Net.Handlers }
}
- public override bool ShouldCompressResponse(string contentType)
+ private bool ShouldCompressResponse(string contentType)
{
// Can't compress these
if (IsRangeRequest)
@@ -105,29 +66,41 @@ namespace MediaBrowser.Common.Net.Handlers return SourceStream.Length;
}
- protected override Task<DateTime?> GetLastDateModified()
+ protected override Task<ResponseInfo> GetResponseInfo()
{
- DateTime? value = null;
-
- EnsureSourceStream();
+ ResponseInfo info = new ResponseInfo
+ {
+ ContentType = MimeTypes.GetMimeType(Path),
+ };
- if (SourceStream != null)
+ try
+ {
+ SourceStream = File.OpenRead(Path);
+ }
+ catch (FileNotFoundException ex)
+ {
+ info.StatusCode = 404;
+ Logger.LogException(ex);
+ }
+ catch (DirectoryNotFoundException ex)
{
- value = File.GetLastWriteTimeUtc(Path);
+ info.StatusCode = 404;
+ Logger.LogException(ex);
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ info.StatusCode = 403;
+ Logger.LogException(ex);
}
- return Task.FromResult(value);
- }
+ info.CompressResponse = ShouldCompressResponse(info.ContentType);
- public override Task<string> GetContentType()
- {
- return Task.FromResult(MimeTypes.GetMimeType(Path));
- }
+ if (SourceStream != null)
+ {
+ info.DateLastModified = File.GetLastWriteTimeUtc(Path);
+ }
- protected override Task PrepareResponse()
- {
- EnsureSourceStream();
- return Task.FromResult<object>(null);
+ return Task.FromResult<ResponseInfo>(info);
}
protected override Task WriteResponseToOutputStream(Stream stream)
diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index 23825db04..a764c5eab 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Kernel;
+using MediaBrowser.Common.Logging;
using MediaBrowser.Common.Serialization;
using MediaBrowser.Model.Plugins;
using System;
@@ -200,6 +201,8 @@ namespace MediaBrowser.Common.Plugins /// </summary>
public void Dispose()
{
+ Logger.LogInfo("Disposing {0} Plugin", Name);
+
if (Context == KernelContext.Server)
{
DisposeOnServer();
diff --git a/MediaBrowser.Common/UI/BaseApplication.cs b/MediaBrowser.Common/UI/BaseApplication.cs index e22eed158..c3792c714 100644 --- a/MediaBrowser.Common/UI/BaseApplication.cs +++ b/MediaBrowser.Common/UI/BaseApplication.cs @@ -5,7 +5,6 @@ using Microsoft.Shell; using System;
using System.Collections.Generic;
using System.ComponentModel;
-using System.Threading.Tasks;
using System.Windows;
namespace MediaBrowser.Common.UI
@@ -44,8 +43,6 @@ namespace MediaBrowser.Common.UI var progress = new Progress<TaskProgress>();
- progress.ProgressChanged += progress_ProgressChanged;
-
var splash = new Splash(progress);
splash.Show();
@@ -56,8 +53,6 @@ namespace MediaBrowser.Common.UI await Kernel.Init(progress);
- progress.ProgressChanged -= progress_ProgressChanged;
-
Logger.LogInfo("Kernel.Init completed in {0} seconds.", (DateTime.UtcNow - now).TotalSeconds);
splash.Close();
@@ -69,12 +64,7 @@ namespace MediaBrowser.Common.UI }
catch (Exception ex)
{
- progress.ProgressChanged -= progress_ProgressChanged;
-
- if (Logger.LoggerInstance != null)
- {
- Logger.LogException(ex);
- }
+ Logger.LogException(ex);
MessageBox.Show("There was an error launching Media Browser: " + ex.Message);
splash.Close();
@@ -84,44 +74,8 @@ namespace MediaBrowser.Common.UI }
}
- public async Task ReloadKernel()
- {
- var progress = new Progress<TaskProgress>();
-
- progress.ProgressChanged += progress_ProgressChanged;
-
- try
- {
- DateTime now = DateTime.UtcNow;
-
- await Kernel.Reload(progress);
-
- progress.ProgressChanged -= progress_ProgressChanged;
-
- Logger.LogInfo("Kernel.Reload completed in {0} seconds.", (DateTime.UtcNow - now).TotalSeconds);
- }
- catch (Exception ex)
- {
- progress.ProgressChanged -= progress_ProgressChanged;
-
- Logger.LogException(ex);
-
- // Shutdown the app with an error code
- Shutdown(1);
- }
- }
-
- void progress_ProgressChanged(object sender, TaskProgress e)
- {
- if (Logger.LoggerInstance != null)
- {
- Logger.LogInfo(e.Description);
- }
- }
-
protected virtual void OnKernelLoaded()
{
-
}
protected override void OnExit(ExitEventArgs e)
diff --git a/MediaBrowser.Common/Drawing/DrawingUtils.cs b/MediaBrowser.Controller/Drawing/DrawingUtils.cs index 4c0b5c207..8e2f829b9 100644 --- a/MediaBrowser.Common/Drawing/DrawingUtils.cs +++ b/MediaBrowser.Controller/Drawing/DrawingUtils.cs @@ -1,7 +1,7 @@ using System;
using System.Drawing;
-namespace MediaBrowser.Common.Drawing
+namespace MediaBrowser.Controller.Drawing
{
public static class DrawingUtils
{
diff --git a/MediaBrowser.Api/ImageProcessor.cs b/MediaBrowser.Controller/Drawing/ImageProcessor.cs index f02b90c22..29e40d17d 100644 --- a/MediaBrowser.Api/ImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessor.cs @@ -1,26 +1,33 @@ -using MediaBrowser.Common.Drawing;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Model.Entities;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
+using System.Linq;
-namespace MediaBrowser.Api
+namespace MediaBrowser.Controller.Drawing
{
public static class ImageProcessor
{
/// <summary>
- /// Resizes an image from a source stream and saves the result to an output stream
+ /// Processes an image by resizing to target dimensions
/// </summary>
+ /// <param name="entity">The entity that owns the image</param>
+ /// <param name="imageType">The image type</param>
+ /// <param name="imageIndex">The image index (currently only used with backdrops)</param>
+ /// <param name="toStream">The stream to save the new image to</param>
/// <param name="width">Use if a fixed width is required. Aspect ratio will be preserved.</param>
/// <param name="height">Use if a fixed height is required. Aspect ratio will be preserved.</param>
/// <param name="maxWidth">Use if a max width is required. Aspect ratio will be preserved.</param>
/// <param name="maxHeight">Use if a max height is required. Aspect ratio will be preserved.</param>
/// <param name="quality">Quality level, from 0-100. Currently only applies to JPG. The default value should suffice.</param>
- public static void ProcessImage(Stream sourceImageStream, Stream toStream, int? width, int? height, int? maxWidth, int? maxHeight, int? quality)
+ public static void ProcessImage(BaseEntity entity, ImageType imageType, int imageIndex, Stream toStream, int? width, int? height, int? maxWidth, int? maxHeight, int? quality)
{
- Image originalImage = Image.FromStream(sourceImageStream);
+ Image originalImage = Image.FromFile(GetImagePath(entity, imageType, imageIndex));
+ // Determine the output size based on incoming parameters
Size newSize = DrawingUtils.Resize(originalImage.Size, width, height, maxWidth, maxHeight);
Bitmap thumbnail;
@@ -35,6 +42,9 @@ namespace MediaBrowser.Api thumbnail = new Bitmap(newSize.Width, newSize.Height, originalImage.PixelFormat);
}
+ thumbnail.MakeTransparent();
+
+ // Preserve the original resolution
thumbnail.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
Graphics thumbnailGraph = Graphics.FromImage(thumbnail);
@@ -47,32 +57,66 @@ namespace MediaBrowser.Api thumbnailGraph.DrawImage(originalImage, 0, 0, newSize.Width, newSize.Height);
- Write(originalImage, thumbnail, toStream, quality);
+ ImageFormat outputFormat = originalImage.RawFormat;
+
+ // Write to the output stream
+ SaveImage(outputFormat, thumbnail, toStream, quality);
thumbnailGraph.Dispose();
thumbnail.Dispose();
originalImage.Dispose();
}
- private static void Write(Image originalImage, Image newImage, Stream toStream, int? quality)
+ public static string GetImagePath(BaseEntity entity, ImageType imageType, int imageIndex)
+ {
+ var item = entity as BaseItem;
+
+ if (item != null)
+ {
+ if (imageType == ImageType.Logo)
+ {
+ return item.LogoImagePath;
+ }
+ if (imageType == ImageType.Backdrop)
+ {
+ return item.BackdropImagePaths.ElementAt(imageIndex);
+ }
+ if (imageType == ImageType.Banner)
+ {
+ return item.BannerImagePath;
+ }
+ if (imageType == ImageType.Art)
+ {
+ return item.ArtImagePath;
+ }
+ if (imageType == ImageType.Thumbnail)
+ {
+ return item.ThumbnailImagePath;
+ }
+ }
+
+ return entity.PrimaryImagePath;
+ }
+
+ public static void SaveImage(ImageFormat outputFormat, Image newImage, Stream toStream, int? quality)
{
// Use special save methods for jpeg and png that will result in a much higher quality image
// All other formats use the generic Image.Save
- if (ImageFormat.Jpeg.Equals(originalImage.RawFormat))
+ if (ImageFormat.Jpeg.Equals(outputFormat))
{
SaveJpeg(newImage, toStream, quality);
}
- else if (ImageFormat.Png.Equals(originalImage.RawFormat))
+ else if (ImageFormat.Png.Equals(outputFormat))
{
newImage.Save(toStream, ImageFormat.Png);
}
else
{
- newImage.Save(toStream, originalImage.RawFormat);
+ newImage.Save(toStream, outputFormat);
}
}
- private static void SaveJpeg(Image newImage, Stream target, int? quality)
+ public static void SaveJpeg(Image image, Stream target, int? quality)
{
if (!quality.HasValue)
{
@@ -82,11 +126,11 @@ namespace MediaBrowser.Api using (var encoderParameters = new EncoderParameters(1))
{
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality.Value);
- newImage.Save(target, GetImageCodeInfo("image/jpeg"), encoderParameters);
+ image.Save(target, GetImageCodecInfo("image/jpeg"), encoderParameters);
}
}
- private static ImageCodecInfo GetImageCodeInfo(string mimeType)
+ public static ImageCodecInfo GetImageCodecInfo(string mimeType)
{
ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 8bbc94272..f845c0f97 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Entities public string DisplayMediaType { get; set; }
- public float? UserRating { get; set; }
+ public float? CommunityRating { get; set; }
public long? RunTimeTicks { get; set; }
public string AspectRatio { get; set; }
diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 503935eed..16576a42b 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Kernel;
using MediaBrowser.Common.Logging;
+using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
@@ -43,7 +44,6 @@ namespace MediaBrowser.Controller public static Kernel Instance { get; private set; }
public ItemController ItemController { get; private set; }
- public WeatherClient WeatherClient { get; private set; }
public IEnumerable<User> Users { get; private set; }
public Folder RootFolder { get; private set; }
@@ -64,6 +64,12 @@ namespace MediaBrowser.Controller }
/// <summary>
+ /// Gets the list of currently registered weather prvoiders
+ /// </summary>
+ [ImportMany(typeof(BaseWeatherProvider))]
+ public IEnumerable<BaseWeatherProvider> WeatherProviders { get; private set; }
+
+ /// <summary>
/// Gets the list of currently registered metadata prvoiders
/// </summary>
[ImportMany(typeof(BaseMetadataProvider))]
@@ -101,28 +107,27 @@ namespace MediaBrowser.Controller /// </summary>
protected override void InitializeInternal(IProgress<TaskProgress> progress)
{
+ base.InitializeInternal(progress);
+
ItemController = new ItemController();
DirectoryWatchers = new DirectoryWatchers();
- base.InitializeInternal(progress);
+ ExtractFFMpeg();
}
/// <summary>
/// Performs initializations that can be reloaded at anytime
/// </summary>
- public override async Task Reload(IProgress<TaskProgress> progress)
+ protected override async Task ReloadInternal(IProgress<TaskProgress> progress)
{
- await base.Reload(progress).ConfigureAwait(false);
+ await base.ReloadInternal(progress).ConfigureAwait(false);
- ReloadWeatherClient();
-
- ExtractFFMpeg();
-
- progress.Report(new TaskProgress { Description = "Loading Users" });
+ ReportProgress(progress, "Loading Users");
ReloadUsers();
- progress.Report(new TaskProgress { Description = "Loading Media Library" });
+ ReportProgress(progress, "Loading Media Library");
+
await ReloadRoot(allowInternetProviders: false).ConfigureAwait(false);
}
@@ -136,8 +141,6 @@ namespace MediaBrowser.Controller DirectoryWatchers.Stop();
- DisposeWeatherClient();
-
}
protected override void OnComposablePartsLoaded()
@@ -380,26 +383,5 @@ namespace MediaBrowser.Controller }
}
}
-
- /// <summary>
- /// Disposes the current WeatherClient
- /// </summary>
- private void DisposeWeatherClient()
- {
- if (WeatherClient != null)
- {
- WeatherClient.Dispose();
- }
- }
-
- /// <summary>
- /// Disposes the current WeatherClient and creates a new one
- /// </summary>
- private void ReloadWeatherClient()
- {
- DisposeWeatherClient();
-
- WeatherClient = new WeatherClient();
- }
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index f5d89f87d..fc1e578e9 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -36,6 +36,7 @@ <Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
+ <Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Reactive.Core, Version=2.0.20823.0, Culture=neutral, PublicKeyToken=f300afd708cefcd3, processorArchitecture=MSIL">
@@ -58,6 +59,8 @@ <Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="Drawing\DrawingUtils.cs" />
+ <Compile Include="Drawing\ImageProcessor.cs" />
<Compile Include="Entities\Audio.cs" />
<Compile Include="Entities\BaseEntity.cs" />
<Compile Include="Entities\BaseItem.cs" />
@@ -111,7 +114,8 @@ <Compile Include="Resolvers\BaseItemResolver.cs" />
<Compile Include="Resolvers\FolderResolver.cs" />
<Compile Include="Resolvers\VideoResolver.cs" />
- <Compile Include="Weather\WeatherClient.cs" />
+ <Compile Include="Weather\BaseWeatherProvider.cs" />
+ <Compile Include="Weather\WeatherProvider.cs" />
<Compile Include="Providers\BaseItemXmlParser.cs" />
<Compile Include="Xml\XmlExtensions.cs" />
</ItemGroup>
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index 45343b051..38afb2b52 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -220,7 +220,7 @@ namespace MediaBrowser.Controller.Providers if (float.TryParse(rating, out val))
{
- item.UserRating = val;
+ item.CommunityRating = val;
}
}
break;
diff --git a/MediaBrowser.Controller/Weather/BaseWeatherProvider.cs b/MediaBrowser.Controller/Weather/BaseWeatherProvider.cs new file mode 100644 index 000000000..c3d436e66 --- /dev/null +++ b/MediaBrowser.Controller/Weather/BaseWeatherProvider.cs @@ -0,0 +1,34 @@ +using MediaBrowser.Common.Logging;
+using MediaBrowser.Model.Weather;
+using System;
+using System.Net;
+using System.Net.Cache;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Weather
+{
+ public abstract class BaseWeatherProvider : IDisposable
+ {
+ protected HttpClient HttpClient { get; private set; }
+
+ protected BaseWeatherProvider()
+ {
+ var handler = new WebRequestHandler { };
+
+ handler.AutomaticDecompression = DecompressionMethods.Deflate;
+ handler.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate);
+
+ HttpClient = new HttpClient(handler);
+ }
+
+ public virtual void Dispose()
+ {
+ Logger.LogInfo("Disposing " + GetType().Name);
+
+ HttpClient.Dispose();
+ }
+
+ public abstract Task<WeatherInfo> GetWeatherInfoAsync(string zipCode);
+ }
+}
diff --git a/MediaBrowser.Controller/Weather/WeatherClient.cs b/MediaBrowser.Controller/Weather/WeatherProvider.cs index 7226dccf0..0fc728879 100644 --- a/MediaBrowser.Controller/Weather/WeatherClient.cs +++ b/MediaBrowser.Controller/Weather/WeatherProvider.cs @@ -2,11 +2,9 @@ using MediaBrowser.Common.Serialization;
using MediaBrowser.Model.Weather;
using System;
+using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
-using System.Net;
-using System.Net.Cache;
-using System.Net.Http;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Weather
@@ -15,21 +13,10 @@ namespace MediaBrowser.Controller.Weather /// Based on http://www.worldweatheronline.com/free-weather-feed.aspx
/// The classes in this file are a reproduction of the json output, which will then be converted to our weather model classes
/// </summary>
- public class WeatherClient : IDisposable
+ [Export(typeof(BaseWeatherProvider))]
+ public class WeatherProvider : BaseWeatherProvider
{
- private HttpClient HttpClient { get; set; }
-
- public WeatherClient()
- {
- var handler = new WebRequestHandler { };
-
- handler.AutomaticDecompression = DecompressionMethods.Deflate;
- handler.CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate);
-
- HttpClient = new HttpClient(handler);
- }
-
- public async Task<WeatherInfo> GetWeatherInfoAsync(string zipCode)
+ public override async Task<WeatherInfo> GetWeatherInfoAsync(string zipCode)
{
if (string.IsNullOrWhiteSpace(zipCode))
{
@@ -73,11 +60,6 @@ namespace MediaBrowser.Controller.Weather return info;
}
-
- public void Dispose()
- {
- HttpClient.Dispose();
- }
}
class WeatherResult
diff --git a/MediaBrowser.Model/DTO/DTOBaseItem.cs b/MediaBrowser.Model/DTO/DTOBaseItem.cs index 66049d3fd..61607ab02 100644 --- a/MediaBrowser.Model/DTO/DTOBaseItem.cs +++ b/MediaBrowser.Model/DTO/DTOBaseItem.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Model.DTO public string DisplayMediaType { get; set; }
[ProtoMember(12)]
- public float? UserRating { get; set; }
+ public float? CommunityRating { get; set; }
[ProtoMember(13)]
public long? RunTimeTicks { get; set; }
diff --git a/MediaBrowser.ServerApplication/MainWindow.xaml.cs b/MediaBrowser.ServerApplication/MainWindow.xaml.cs index 3839dc52e..6180482d7 100644 --- a/MediaBrowser.ServerApplication/MainWindow.xaml.cs +++ b/MediaBrowser.ServerApplication/MainWindow.xaml.cs @@ -1,4 +1,7 @@ using Hardcodet.Wpf.TaskbarNotification;
+using MediaBrowser.Common.Events;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.Progress;
using System;
using System.ComponentModel;
using System.Threading;
@@ -11,15 +14,36 @@ namespace MediaBrowser.ServerApplication /// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
+ private Timer LoadingIconTimer { get; set; }
+
public MainWindow()
{
InitializeComponent();
- Loaded += MainWindow_Loaded;
+ Loaded += MainWindowLoaded;
}
- void MainWindow_Loaded(object sender, RoutedEventArgs e)
+ void MainWindowLoaded(object sender, RoutedEventArgs e)
{
DataContext = this;
+
+ Kernel.Instance.ReloadBeginning += KernelReloadBeginning;
+ Kernel.Instance.ReloadCompleted += KernelReloadCompleted;
+ }
+
+ void KernelReloadBeginning(object sender, GenericEventArgs<IProgress<TaskProgress>> e)
+ {
+ MbTaskbarIcon.ShowBalloonTip("Media Browser is reloading", "Please wait...", BalloonIcon.Info);
+
+ LoadingImageIndex = 0;
+
+ LoadingIconTimer = new Timer(LoadingIconTimerCallback, null, 0, 250);
+ }
+
+ void KernelReloadCompleted(object sender, GenericEventArgs<IProgress<TaskProgress>> e)
+ {
+ LoadingIconTimer.Dispose();
+
+ LoadingImageIndex = 0;
}
public event PropertyChangedEventHandler PropertyChanged;
@@ -62,17 +86,7 @@ namespace MediaBrowser.ServerApplication private async void cmdReloadServer_click(object sender, RoutedEventArgs e)
{
- MbTaskbarIcon.ShowBalloonTip("Media Browser is reloading", "Please wait...", BalloonIcon.Info);
-
- LoadingImageIndex = 0;
-
- Timer timer = new Timer(LoadingIconTimerCallback, null, 0, 250);
-
- await (Application.Current as App).ReloadKernel().ConfigureAwait(false);
-
- timer.Dispose();
-
- LoadingImageIndex = 0;
+ await Kernel.Instance.Reload(new Progress<TaskProgress>()).ConfigureAwait(false);
}
private void LoadingIconTimerCallback(object stateInfo)
diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 17b3a6290..b3f1b7835 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -52,4 +52,7 @@ Global GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(Performance) = preSolution
+ HasPerformanceSessions = true
+ EndGlobalSection
EndGlobal
|
