From 105ecae1de194fd35b4d542735a216063c710386 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Jan 2016 20:05:14 -0500 Subject: [PATCH 01/27] update image loader --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 2a2515197e..cc153a0106 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1045,9 +1045,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From 570d63d783e4975486f907b5d63d8af954044723 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 14:45:52 -0500 Subject: [PATCH 02/27] trim logging --- .../TV/MissingEpisodeProvider.cs | 2 +- .../HttpServer/HttpListenerHost.cs | 6 +- .../SocketSharp/WebSocketSharpListener.cs | 56 +++++++++++-------- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 19eda49051..9c0e0b8731 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.Providers.TV } catch (DirectoryNotFoundException) { - _logger.Warn("Series files missing for series id {0}", seriesGroup.Key); + //_logger.Warn("Series files missing for series id {0}", seriesGroup.Key); } catch (Exception ex) { diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 0283c1f7a5..6a23a84977 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -154,10 +154,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer return this; } - private void OnRequestReceived(string localEndPoint) - { - } - /// /// Starts the Web Service /// @@ -177,7 +173,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer private IHttpListener GetListener() { - return new WebSocketSharpListener(_logger, OnRequestReceived, CertificatePath); + return new WebSocketSharpListener(_logger, CertificatePath); } private void OnWebSocketConnecting(WebSocketConnectingEventArgs args) diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index 9f80c8ac98..a91b1e3ed2 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -7,6 +7,7 @@ using ServiceStack.Web; using SocketHttpListener.Net; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -18,14 +19,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp private HttpListener _listener; private readonly ILogger _logger; - private readonly Action _endpointListener; private readonly string _certificatePath; - public WebSocketSharpListener(ILogger logger, Action endpointListener, - string certificatePath) + public WebSocketSharpListener(ILogger logger, string certificatePath) { _logger = logger; - _endpointListener = endpointListener; _certificatePath = certificatePath; } @@ -80,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { var request = context.Request; - LogHttpRequest(request); + LogRequest(_logger, request); if (request.IsWebSocketRequest) { @@ -96,24 +94,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp return RequestHandler(httpReq, request.Url); } - /// - /// Logs the HTTP request. - /// - /// The request. - private void LogHttpRequest(HttpListenerRequest request) - { - var endpoint = request.LocalEndPoint; - - if (endpoint != null) - { - var address = endpoint.ToString(); - - _endpointListener(address); - } - - LogRequest(_logger, request); - } - private void ProcessWebSocketRequest(HttpListenerContext ctx) { try @@ -183,7 +163,35 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp /// The request. private static void LogRequest(ILogger logger, HttpListenerRequest request) { - logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), request.Url, request.UserAgent ?? string.Empty); + var url = request.Url.ToString(); + var extension = Path.GetExtension(url); + + if (string.Equals(extension, ".js", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".css", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".woff", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".woff2", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".ttf", StringComparison.OrdinalIgnoreCase)) + { + return; + } + if (string.Equals(extension, ".html", StringComparison.OrdinalIgnoreCase)) + { + return; + } + + logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), url, request.UserAgent ?? string.Empty); } private void HandleError(Exception ex, HttpListenerContext context) From 55d3f89d22c7bac5c5da2c83fc7c9a0504185747 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 15:40:20 -0500 Subject: [PATCH 03/27] disable http compression --- .../Security/PluginSecurityManager.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index d8f3502075..a6dbf77e98 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -258,7 +258,17 @@ namespace MediaBrowser.Common.Implementations.Security try { - using (var json = await _httpClient.Post(MBValidateUrl, data, CancellationToken.None).ConfigureAwait(false)) + var options = new HttpRequestOptions + { + Url = MBValidateUrl, + + // Seeing block length errors + EnableHttpCompression = false + }; + + options.SetPostData(data); + + using (var json = (await _httpClient.Post(options).ConfigureAwait(false)).Content) { reg = _jsonSerializer.DeserializeFromStream(json); success = true; From 6d45337e7bc17e7bf167b041a1b7bebba26711fd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 21:29:00 -0500 Subject: [PATCH 04/27] update cdart order --- .../Images/LocalImageProvider.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index 1cadef7f2c..afbc2640d2 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -129,8 +129,19 @@ namespace MediaBrowser.LocalMetadata.Images AddImage(files, images, "logo", imagePrefix, isInMixedFolder, ImageType.Logo); AddImage(files, images, "clearart", imagePrefix, isInMixedFolder, ImageType.Art); - AddImage(files, images, "disc", imagePrefix, isInMixedFolder, ImageType.Disc); - AddImage(files, images, "cdart", imagePrefix, isInMixedFolder, ImageType.Disc); + + // For music albums, prefer cdart before disc + if (item is MusicAlbum) + { + AddImage(files, images, "cdart", imagePrefix, isInMixedFolder, ImageType.Disc); + AddImage(files, images, "disc", imagePrefix, isInMixedFolder, ImageType.Disc); + } + else + { + AddImage(files, images, "disc", imagePrefix, isInMixedFolder, ImageType.Disc); + AddImage(files, images, "cdart", imagePrefix, isInMixedFolder, ImageType.Disc); + } + AddImage(files, images, "box", imagePrefix, isInMixedFolder, ImageType.Box); AddImage(files, images, "back", imagePrefix, isInMixedFolder, ImageType.BoxRear); AddImage(files, images, "boxrear", imagePrefix, isInMixedFolder, ImageType.BoxRear); From 08d9c1fc2d8c64001cc60dd72d15bd7da4162ef2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 23:09:19 -0500 Subject: [PATCH 05/27] 3.0.5817 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 706b839960..76cc4acd2b 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5816")] +[assembly: AssemblyVersion("3.0.5817")] From 6d31d60fe174953f98cbfbc55f36b21f8292243b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 12:47:46 -0500 Subject: [PATCH 06/27] update mac project --- MediaBrowser.Server.Mac/Emby.Server.Mac.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index f7a6a8cd61..e3887f6371 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -79,7 +79,7 @@ False - ..\packages\CommonIO.1.0.0.5\lib\net45\CommonIO.dll + ..\packages\CommonIO.1.0.0.7\lib\net45\CommonIO.dll ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll From eca02c7360e69fb2c2ef17427d6315587d625e3d Mon Sep 17 00:00:00 2001 From: Luke Date: Fri, 22 Jan 2016 13:31:57 -0500 Subject: [PATCH 07/27] update mac project --- .../Emby.Server.Mac.csproj | 24 ++++++++++++++----- MediaBrowser.Server.Mac/Main.cs | 2 +- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index e3887f6371..4e6bfaa43b 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -506,6 +506,9 @@ Resources\dashboard-ui\selectserver.html + + Resources\dashboard-ui\serversecurity.html + Resources\dashboard-ui\shared.html @@ -1139,6 +1142,15 @@ Resources\dashboard-ui\bower_components\emby-webcomponents\visibleinviewport.js + + Resources\dashboard-ui\bower_components\emby-webcomponents\images\basicimagefetcher.js + + + Resources\dashboard-ui\bower_components\emby-webcomponents\images\imagehelper.js + + + Resources\dashboard-ui\bower_components\emby-webcomponents\images\persistentimagefetcher.js + Resources\dashboard-ui\bower_components\fastclick\.bower.json @@ -1301,6 +1313,9 @@ Resources\dashboard-ui\bower_components\hls.js\src\errors.js + + Resources\dashboard-ui\bower_components\hls.js\src\event-handler.js + Resources\dashboard-ui\bower_components\hls.js\src\events.js @@ -4640,9 +4655,6 @@ Resources\dashboard-ui\components\humanedate.js - - Resources\dashboard-ui\components\imagestore.js - Resources\dashboard-ui\components\paperdialoghelper.js @@ -5531,6 +5543,9 @@ Resources\dashboard-ui\scripts\selectserver.js + + Resources\dashboard-ui\scripts\serversecurity.js + Resources\dashboard-ui\scripts\shared.js @@ -5882,9 +5897,6 @@ Resources\dashboard-ui\themes\holiday\theme.js - - Resources\dashboard-ui\thirdparty\jquery.unveil-custom.js - Resources\dashboard-ui\thirdparty\paper-button-style.css diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index 67effa95fd..b7e158c5d6 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -96,7 +96,7 @@ namespace MediaBrowser.Server.Mac var nativeApp = new NativeApp(); - AppHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "MBServer.Mono", nativeApp); + AppHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "Emby.Server.Mac.pkg", nativeApp); if (options.ContainsOption("-v")) { Console.WriteLine (AppHost.ApplicationVersion.ToString()); From 02ad5527926a3081b828300546b6945978f7da04 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 14:16:30 -0500 Subject: [PATCH 08/27] adjust default library monitor behavior --- MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 97f082295e..85ea8ec57b 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -160,7 +160,7 @@ namespace MediaBrowser.Server.Implementations.IO switch (ConfigurationManager.Configuration.EnableLibraryMonitor) { case AutoOnOff.Auto: - return _appHost.SupportsLibraryMonitor; + return Environment.OSVersion.Platform == PlatformID.Win32NT; case AutoOnOff.Enabled: return true; default: From ed49e931182b240f623e96422604e75a61d50e91 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 03:23:02 -0500 Subject: [PATCH 09/27] support photo orientation --- Emby.Drawing/GDI/GDIImageEncoder.cs | 2 +- Emby.Drawing/IImageEncoder.cs | 3 +- .../ImageMagick/ImageMagickEncoder.cs | 20 +++++++++++- Emby.Drawing/ImageProcessor.cs | 31 ++++++++++++++++++- Emby.Drawing/NullImageEncoder.cs | 2 +- .../Dto/DtoService.cs | 26 ++++++++++++++-- 6 files changed, 76 insertions(+), 8 deletions(-) diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs index 3df84cf112..51b4605c33 100644 --- a/Emby.Drawing/GDI/GDIImageEncoder.cs +++ b/Emby.Drawing/GDI/GDIImageEncoder.cs @@ -89,7 +89,7 @@ namespace Emby.Drawing.GDI } } - public void EncodeImage(string inputPath, string cacheFilePath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string cacheFilePath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0; diff --git a/Emby.Drawing/IImageEncoder.cs b/Emby.Drawing/IImageEncoder.cs index bfd382bb7c..f36498be76 100644 --- a/Emby.Drawing/IImageEncoder.cs +++ b/Emby.Drawing/IImageEncoder.cs @@ -27,12 +27,13 @@ namespace Emby.Drawing /// /// The input path. /// The output path. + /// The rotation angle. /// The width. /// The height. /// The quality. /// The options. /// The output format. - void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); + void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); /// /// Creates the image collage. diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 6858c6d520..fd9ed5f1e5 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -139,7 +139,7 @@ namespace Emby.Drawing.ImageMagick string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase); } - public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { // Even if the caller specified 100, don't use it because it takes forever quality = Math.Min(quality, 99); @@ -150,6 +150,11 @@ namespace Emby.Drawing.ImageMagick { ScaleImage(originalImage, width, height); + if (rotationAngle > 0) + { + RotateImage(originalImage, rotationAngle); + } + DrawIndicator(originalImage, width, height, options); originalImage.CurrentImage.CompressionQuality = quality; @@ -166,6 +171,11 @@ namespace Emby.Drawing.ImageMagick { ScaleImage(originalImage, width, height); + if (rotationAngle > 0) + { + RotateImage(originalImage, rotationAngle); + } + wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); DrawIndicator(wand, width, height, options); @@ -179,6 +189,14 @@ namespace Emby.Drawing.ImageMagick SaveDelay(); } + public static void RotateImage(MagickWand wand, float angle) + { + using (var pixelWand = new PixelWand("none", 1)) + { + wand.CurrentImage.RotateImage(pixelWand, angle); + } + } + private void ScaleImage(MagickWand wand, int width, int height) { var highQuality = false; diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index e1b92bbffc..9de6d20427 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -257,7 +257,7 @@ namespace Emby.Drawing imageProcessingLockTaken = true; - _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options, outputFormat); + _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, GetRotationAngle(options.Item), newWidth, newHeight, quality, options, outputFormat); } return new Tuple(cacheFilePath, GetMimeType(outputFormat, cacheFilePath)); @@ -281,6 +281,35 @@ namespace Emby.Drawing } } + private int GetRotationAngle(IHasImages item) + { + var photo = item as Photo; + if (photo != null && photo.Orientation.HasValue) + { + switch (photo.Orientation.Value) + { + case ImageOrientation.TopLeft: + return 0; + case ImageOrientation.TopRight: + return 0; + case ImageOrientation.BottomLeft: + return 270; + case ImageOrientation.BottomRight: + return 180; + case ImageOrientation.LeftBottom: + return -90; + case ImageOrientation.LeftTop: + return 0; + case ImageOrientation.RightBottom: + return 0; + case ImageOrientation.RightTop: + return 90; + } + } + + return 0; + } + private string GetMimeType(ImageFormat format, string path) { if (format == ImageFormat.Bmp) diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index 1638a675ac..032335a460 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -32,7 +32,7 @@ namespace Emby.Drawing throw new NotImplementedException(); } - public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { throw new NotImplementedException(); } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index b0071828e2..0cd551f6a7 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1783,11 +1783,31 @@ namespace MediaBrowser.Server.Implementations.Dto } } - if (size.Width > 0 && size.Height > 0) + var width = size.Width; + var height = size.Height; + + if (width == 0 || height == 0) { - return size.Width / size.Height; + return null; } - return null; + + var photo = item as Photo; + if (photo != null && photo.Orientation.HasValue) + { + switch (photo.Orientation.Value) + { + case ImageOrientation.LeftBottom: + case ImageOrientation.LeftTop: + case ImageOrientation.RightBottom: + case ImageOrientation.RightTop: + var temp = height; + height = width; + width = temp; + break; + } + } + + return width / height; } } } From de83adb38c10ccb98f68e2904e419dc77119978c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 11:53:03 -0500 Subject: [PATCH 10/27] use image magick for auto-orientation --- Emby.Drawing/Emby.Drawing.csproj | 2 +- Emby.Drawing/GDI/GDIImageEncoder.cs | 2 +- Emby.Drawing/IImageEncoder.cs | 4 +- .../ImageMagick/ImageMagickEncoder.cs | 15 ++++--- Emby.Drawing/ImageProcessor.cs | 41 +++++++++---------- Emby.Drawing/NullImageEncoder.cs | 2 +- Emby.Drawing/packages.config | 2 +- .../MediaBrowser.ServerApplication.csproj | 2 +- .../packages.config | 2 +- 9 files changed, 37 insertions(+), 35 deletions(-) diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 45ac97ecc4..06e042d74e 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -37,7 +37,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.18\lib\net45\ImageMagickSharp.dll ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs index 51b4605c33..bdd1c5a22f 100644 --- a/Emby.Drawing/GDI/GDIImageEncoder.cs +++ b/Emby.Drawing/GDI/GDIImageEncoder.cs @@ -89,7 +89,7 @@ namespace Emby.Drawing.GDI } } - public void EncodeImage(string inputPath, string cacheFilePath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string cacheFilePath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0; diff --git a/Emby.Drawing/IImageEncoder.cs b/Emby.Drawing/IImageEncoder.cs index f36498be76..73b5398993 100644 --- a/Emby.Drawing/IImageEncoder.cs +++ b/Emby.Drawing/IImageEncoder.cs @@ -27,13 +27,13 @@ namespace Emby.Drawing /// /// The input path. /// The output path. - /// The rotation angle. + /// if set to true [automatic orient]. /// The width. /// The height. /// The quality. /// The options. /// The output format. - void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); + void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); /// /// Creates the image collage. diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index fd9ed5f1e5..b8300ac979 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -139,7 +139,7 @@ namespace Emby.Drawing.ImageMagick string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase); } - public void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { // Even if the caller specified 100, don't use it because it takes forever quality = Math.Min(quality, 99); @@ -150,9 +150,9 @@ namespace Emby.Drawing.ImageMagick { ScaleImage(originalImage, width, height); - if (rotationAngle > 0) + if (autoOrient) { - RotateImage(originalImage, rotationAngle); + AutoOrientImage(originalImage); } DrawIndicator(originalImage, width, height, options); @@ -171,9 +171,9 @@ namespace Emby.Drawing.ImageMagick { ScaleImage(originalImage, width, height); - if (rotationAngle > 0) + if (autoOrient) { - RotateImage(originalImage, rotationAngle); + AutoOrientImage(originalImage); } wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); @@ -189,6 +189,11 @@ namespace Emby.Drawing.ImageMagick SaveDelay(); } + private void AutoOrientImage(MagickWand wand) + { + wand.CurrentImage.AutoOrientImage(); + } + public static void RotateImage(MagickWand wand, float angle) { using (var pixelWand = new PixelWand("none", 1)) diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 9de6d20427..e016127004 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -257,7 +257,7 @@ namespace Emby.Drawing imageProcessingLockTaken = true; - _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, GetRotationAngle(options.Item), newWidth, newHeight, quality, options, outputFormat); + _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat); } return new Tuple(cacheFilePath, GetMimeType(outputFormat, cacheFilePath)); @@ -281,35 +281,32 @@ namespace Emby.Drawing } } - private int GetRotationAngle(IHasImages item) + private bool AutoOrient(IHasImages item) { var photo = item as Photo; if (photo != null && photo.Orientation.HasValue) { - switch (photo.Orientation.Value) - { - case ImageOrientation.TopLeft: - return 0; - case ImageOrientation.TopRight: - return 0; - case ImageOrientation.BottomLeft: - return 270; - case ImageOrientation.BottomRight: - return 180; - case ImageOrientation.LeftBottom: - return -90; - case ImageOrientation.LeftTop: - return 0; - case ImageOrientation.RightBottom: - return 0; - case ImageOrientation.RightTop: - return 90; - } + return true; } - return 0; + return false; } + //private static int[][] OPERATIONS = new int[][] { + // TopLeft + //new int[] { 0, NONE}, + // TopRight + //new int[] { 0, HORIZONTAL}, + //new int[] {180, NONE}, + // LeftTop + //new int[] { 0, VERTICAL}, + //new int[] { 90, HORIZONTAL}, + // RightTop + //new int[] { 90, NONE}, + //new int[] {-90, HORIZONTAL}, + //new int[] {-90, NONE}, + //}; + private string GetMimeType(ImageFormat format, string path) { if (format == ImageFormat.Bmp) diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index 032335a460..4fa18ce553 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -32,7 +32,7 @@ namespace Emby.Drawing throw new NotImplementedException(); } - public void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { throw new NotImplementedException(); } diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config index 51731c4748..62a241f1fc 100644 --- a/Emby.Drawing/packages.config +++ b/Emby.Drawing/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 3e62f47351..c629831923 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -67,7 +67,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.17\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.18\lib\net45\ImageMagickSharp.dll ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index db2bb54761..be12bcd5c3 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,7 +1,7 @@  - + From aa6d6d8ec7f5e9a53d9519daa24cbc6cbdb0b33a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 13:50:43 -0500 Subject: [PATCH 11/27] get people info during media refresh --- .../Entities/PeopleHelper.cs | 17 +++++-- MediaBrowser.Controller/Entities/Person.cs | 12 ++++- .../Manager/MetadataService.cs | 43 +++++++++++++++++ .../Movies/GenericMovieDbInfo.cs | 47 +++++++++++++++++-- .../TV/TvdbSeriesProvider.cs | 15 ++++++ 5 files changed, 126 insertions(+), 8 deletions(-) diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs index 3468ca2d58..40a93d9e6f 100644 --- a/MediaBrowser.Controller/Entities/PeopleHelper.cs +++ b/MediaBrowser.Controller/Entities/PeopleHelper.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Controller.Entities if (existing != null) { existing.Type = PersonType.GuestStar; - existing.SortOrder = person.SortOrder ?? existing.SortOrder; + MergeExisting(existing, person); return; } } @@ -67,7 +67,7 @@ namespace MediaBrowser.Controller.Entities existing.Role = person.Role; } - existing.SortOrder = person.SortOrder ?? existing.SortOrder; + MergeExisting(existing, person); } } else @@ -83,11 +83,22 @@ namespace MediaBrowser.Controller.Entities } else { - existing.SortOrder = person.SortOrder ?? existing.SortOrder; + MergeExisting(existing, person); } } } + private static void MergeExisting(PersonInfo existing, PersonInfo person) + { + existing.SortOrder = person.SortOrder ?? existing.SortOrder; + existing.ImageUrl = person.ImageUrl ?? existing.ImageUrl; + + foreach (var id in person.ProviderIds) + { + existing.SetProviderId(id.Key, id.Value); + } + } + public static bool ContainsPerson(List people, string name) { if (string.IsNullOrWhiteSpace(name)) diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 6c277da565..a365b99c67 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities { @@ -106,8 +107,13 @@ namespace MediaBrowser.Controller.Entities /// /// This is the small Person stub that is attached to BaseItems /// - public class PersonInfo + public class PersonInfo : IHasProviderIds { + public PersonInfo() + { + ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + public Guid ItemId { get; set; } /// @@ -132,6 +138,10 @@ namespace MediaBrowser.Controller.Entities /// The sort order. public int? SortOrder { get; set; } + public string ImageUrl { get; set; } + + public Dictionary ProviderIds { get; set; } + /// /// Returns a that represents this instance. /// diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 083c8f1f3d..d9f5c30fd5 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -254,10 +254,53 @@ namespace MediaBrowser.Providers.Manager if (result.Item.SupportsPeople && result.People != null) { await LibraryManager.UpdatePeople(result.Item as BaseItem, result.People.ToList()); + await SavePeopleMetadata(result.People, cancellationToken).ConfigureAwait(false); } await result.Item.UpdateToRepository(reason, cancellationToken).ConfigureAwait(false); } + private async Task SavePeopleMetadata(List people, CancellationToken cancellationToken) + { + foreach (var person in people) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (person.ProviderIds.Any() || !string.IsNullOrWhiteSpace(person.ImageUrl)) + { + var updateType = ItemUpdateType.MetadataDownload; + + var saveEntity = false; + var personEntity = LibraryManager.GetPerson(person.Name); + foreach (var id in person.ProviderIds) + { + if (!string.Equals(personEntity.GetProviderId(id.Key), id.Value, StringComparison.OrdinalIgnoreCase)) + { + personEntity.SetProviderId(id.Key, id.Value); + saveEntity = true; + } + } + + if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary)) + { + personEntity.SetImage(new ItemImageInfo + { + Path = person.ImageUrl, + Type = ImageType.Primary, + IsPlaceholder = true + }, 0); + + saveEntity = true; + updateType = updateType | ItemUpdateType.ImageUpdate; + } + + if (saveEntity) + { + await personEntity.UpdateToRepository(updateType, cancellationToken).ConfigureAwait(false); + } + } + } + } + private readonly Task _cachedTask = Task.FromResult(true); protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index 3c2d9c82fc..abd4a62029 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -104,7 +104,9 @@ namespace MediaBrowser.Providers.Movies dataFilePath = dataFilePath ?? MovieDbProvider.Current.GetDataFilePath(tmdbId, language); movieInfo = movieInfo ?? _jsonSerializer.DeserializeFromFile(dataFilePath); - ProcessMainInfo(item, preferredCountryCode, movieInfo); + var settings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); + + ProcessMainInfo(item, settings, preferredCountryCode, movieInfo); item.HasMetadata = true; } @@ -115,9 +117,10 @@ namespace MediaBrowser.Providers.Movies /// Processes the main info. /// /// The result item. + /// The settings. /// The preferred country code. /// The movie data. - private void ProcessMainInfo(MetadataResult resultItem, string preferredCountryCode, MovieDbProvider.CompleteMovieData movieData) + private void ProcessMainInfo(MetadataResult resultItem, TmdbSettingsResult settings, string preferredCountryCode, MovieDbProvider.CompleteMovieData movieData) { var movie = resultItem.Item; @@ -247,6 +250,7 @@ namespace MediaBrowser.Providers.Movies } resultItem.ResetPeople(); + var tmdbImageUrl = settings.images.base_url + "original"; //Actors, Directors, Writers - all in People //actors come from cast @@ -254,7 +258,25 @@ namespace MediaBrowser.Providers.Movies { foreach (var actor in movieData.casts.cast.OrderBy(a => a.order)) { - resultItem.AddPerson(new PersonInfo { Name = actor.name.Trim(), Role = actor.character, Type = PersonType.Actor, SortOrder = actor.order }); + var personInfo = new PersonInfo + { + Name = actor.name.Trim(), + Role = actor.character, + Type = PersonType.Actor, + SortOrder = actor.order + }; + + if (!string.IsNullOrWhiteSpace(actor.profile_path)) + { + personInfo.ImageUrl = tmdbImageUrl + actor.profile_path; + } + + if (actor.id > 0) + { + personInfo.SetProviderId(MetadataProviders.Tmdb, actor.id.ToString(CultureInfo.InvariantCulture)); + } + + resultItem.AddPerson(personInfo); } } @@ -270,7 +292,24 @@ namespace MediaBrowser.Providers.Movies type = PersonType.Writer; } - resultItem.AddPerson(new PersonInfo { Name = person.name.Trim(), Role = person.job, Type = type }); + var personInfo = new PersonInfo + { + Name = person.name.Trim(), + Role = person.job, + Type = type + }; + + if (!string.IsNullOrWhiteSpace(person.profile_path)) + { + personInfo.ImageUrl = tmdbImageUrl + person.profile_path; + } + + if (person.id > 0) + { + personInfo.SetProviderId(MetadataProviders.Tmdb, person.id.ToString(CultureInfo.InvariantCulture)); + } + + resultItem.AddPerson(personInfo); } } diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 9452438cb1..00bc032ca7 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -826,6 +826,21 @@ namespace MediaBrowser.Providers.TV break; } + case "id": + { + break; + } + + case "Image": + { + var url = (reader.ReadElementContentAsString() ?? string.Empty).Trim(); + if (!string.IsNullOrWhiteSpace(url)) + { + personInfo.ImageUrl = TVUtils.BannerUrl + url; + } + break; + } + case "SortOrder": { var val = reader.ReadElementContentAsString(); From 975f8d8f3f41bc08c1b8e4720a5dd1876b278142 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 21:59:07 -0500 Subject: [PATCH 12/27] sync image file names --- .../Images/LocalImageProvider.cs | 40 +++++--- MediaBrowser.Providers/Manager/ImageSaver.cs | 91 ++++++++++--------- 2 files changed, 73 insertions(+), 58 deletions(-) diff --git a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs index afbc2640d2..c6f81d8742 100644 --- a/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs +++ b/MediaBrowser.LocalMetadata/Images/LocalImageProvider.cs @@ -122,6 +122,16 @@ namespace MediaBrowser.LocalMetadata.Images private void PopulateImages(IHasImages item, List images, List files, bool supportParentSeriesFiles, IDirectoryService directoryService) { + if (supportParentSeriesFiles) + { + var season = item as Season; + + if (season != null) + { + PopulateSeasonImagesFromSeriesFolder(season, images, directoryService); + } + } + var imagePrefix = item.FileNameWithoutExtension + "-"; var isInMixedFolder = item.IsInMixedFolder; @@ -151,33 +161,33 @@ namespace MediaBrowser.LocalMetadata.Images AddImage(files, images, "banner", imagePrefix, isInMixedFolder, ImageType.Banner); // Thumb - AddImage(files, images, "thumb", imagePrefix, isInMixedFolder, ImageType.Thumb); AddImage(files, images, "landscape", imagePrefix, isInMixedFolder, ImageType.Thumb); + AddImage(files, images, "thumb", imagePrefix, isInMixedFolder, ImageType.Thumb); PopulateBackdrops(item, images, files, imagePrefix, isInMixedFolder, directoryService); PopulateScreenshots(images, files, imagePrefix, isInMixedFolder); - - if (supportParentSeriesFiles) - { - var season = item as Season; - - if (season != null) - { - PopulateSeasonImagesFromSeriesFolder(season, images, directoryService); - } - } } private void PopulatePrimaryImages(IHasImages item, List images, List files, string imagePrefix, bool isInMixedFolder) { var names = new List { - "folder", - "poster", "cover", "default" }; + if (item is MusicAlbum || item is MusicArtist) + { + // these prefer folder + names.Insert(0, "poster"); + names.Insert(0, "folder"); + } + else + { + names.Insert(0, "folder"); + names.Insert(0, "poster"); + } + // Support plex/kodi convention if (item is Series) { @@ -212,8 +222,6 @@ namespace MediaBrowser.LocalMetadata.Images private void PopulateBackdrops(IHasImages item, List images, List files, string imagePrefix, bool isInMixedFolder, IDirectoryService directoryService) { - PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", isInMixedFolder, ImageType.Backdrop); - if (!string.IsNullOrEmpty(item.Path)) { var name = item.FileNameWithoutExtension; @@ -241,6 +249,8 @@ namespace MediaBrowser.LocalMetadata.Images { PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images, directoryService); } + + PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", isInMixedFolder, ImageType.Backdrop); } private void PopulateBackdropsFromExtraFanart(string path, List images, IDirectoryService directoryService) diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 4542c9c428..4bec352f6c 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -332,7 +332,50 @@ namespace MediaBrowser.Providers.Manager /// private string GetStandardSavePath(IHasImages item, ImageType type, int? imageIndex, string mimeType, bool saveLocally) { + var season = item as Season; + var extension = MimeTypes.ToExtension(mimeType); + + if (type == ImageType.Thumb && saveLocally) + { + if (season != null && season.IndexNumber.HasValue) + { + var seriesFolder = season.SeriesPath; + + var seasonMarker = season.IndexNumber.Value == 0 + ? "-specials" + : season.IndexNumber.Value.ToString("00", UsCulture); + + var imageFilename = "season" + seasonMarker + "-landscape" + extension; + + return Path.Combine(seriesFolder, imageFilename); + } + + if (item.IsInMixedFolder) + { + return GetSavePathForItemInMixedFolder(item, type, "landscape", extension); + } + + return Path.Combine(item.ContainingFolderPath, "landscape" + extension); + } + + if (type == ImageType.Banner && saveLocally) + { + if (season != null && season.IndexNumber.HasValue) + { + var seriesFolder = season.SeriesPath; + + var seasonMarker = season.IndexNumber.Value == 0 + ? "-specials" + : season.IndexNumber.Value.ToString("00", UsCulture); + + var imageFilename = "season" + seasonMarker + "-banner" + extension; + + return Path.Combine(seriesFolder, imageFilename); + } + } + string filename; + var folderName = item is MusicAlbum || item is MusicArtist ? "folder" : "poster"; switch (type) { @@ -342,11 +385,14 @@ namespace MediaBrowser.Providers.Manager case ImageType.BoxRear: filename = "back"; break; + case ImageType.Thumb: + filename = "landscape"; + break; case ImageType.Disc: filename = item is MusicAlbum ? "cdart" : "disc"; break; case ImageType.Primary: - filename = item is Episode ? _fileSystem.GetFileNameWithoutExtension(item.Path) : "folder"; + filename = item is Episode ? _fileSystem.GetFileNameWithoutExtension(item.Path) : folderName; break; case ImageType.Backdrop: filename = GetBackdropSaveFilename(item.GetImages(type), "backdrop", "backdrop", imageIndex); @@ -359,8 +405,6 @@ namespace MediaBrowser.Providers.Manager break; } - var extension = mimeType.Split('/').Last(); - if (string.Equals(extension, "jpeg", StringComparison.OrdinalIgnoreCase)) { extension = "jpg"; @@ -393,7 +437,7 @@ namespace MediaBrowser.Providers.Manager { if (string.IsNullOrEmpty(filename)) { - filename = "folder"; + filename = folderName; } path = Path.Combine(item.GetInternalMetadataPath(), filename + extension); } @@ -526,45 +570,6 @@ namespace MediaBrowser.Providers.Manager return new[] { Path.Combine(item.ContainingFolderPath, "poster" + extension) }; } - if (type == ImageType.Banner) - { - if (season != null && season.IndexNumber.HasValue) - { - var seriesFolder = season.SeriesPath; - - var seasonMarker = season.IndexNumber.Value == 0 - ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); - - var imageFilename = "season" + seasonMarker + "-banner" + extension; - - return new[] { Path.Combine(seriesFolder, imageFilename) }; - } - } - - if (type == ImageType.Thumb) - { - if (season != null && season.IndexNumber.HasValue) - { - var seriesFolder = season.SeriesPath; - - var seasonMarker = season.IndexNumber.Value == 0 - ? "-specials" - : season.IndexNumber.Value.ToString("00", UsCulture); - - var imageFilename = "season" + seasonMarker + "-landscape" + extension; - - return new[] { Path.Combine(seriesFolder, imageFilename) }; - } - - if (item.IsInMixedFolder) - { - return new[] { GetSavePathForItemInMixedFolder(item, type, "landscape", extension) }; - } - - return new[] { Path.Combine(item.ContainingFolderPath, "landscape" + extension) }; - } - // All other paths are the same return new[] { GetStandardSavePath(item, type, imageIndex, mimeType, true) }; } From 4f26c7496cc1e388b653fd2124b8d2c2d9d5e68c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 20:35:43 -0500 Subject: [PATCH 13/27] add dvbsub as not text --- MediaBrowser.Model/Entities/MediaStream.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 7f4cc2f84d..1e19a06019 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -195,6 +195,7 @@ namespace MediaBrowser.Model.Entities return StringHelper.IndexOfIgnoreCase(codec, "pgs") == -1 && StringHelper.IndexOfIgnoreCase(codec, "dvd") == -1 && + StringHelper.IndexOfIgnoreCase(codec, "dvbsub") == -1 && !StringHelper.EqualsIgnoreCase(codec, "sub"); } From 49d88278ff8f3d09188288db14a57aa57851090e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 20:57:35 -0500 Subject: [PATCH 14/27] add version to all tmdb requests --- MediaBrowser.Providers/Movies/MovieDbProvider.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index b7530ebb45..f7e4142fa5 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -20,6 +20,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Common; using MediaBrowser.Model.Net; namespace MediaBrowser.Providers.Movies @@ -40,10 +41,11 @@ namespace MediaBrowser.Providers.Movies private readonly ILogger _logger; private readonly ILocalizationManager _localization; private readonly ILibraryManager _libraryManager; + private readonly IApplicationHost _appHost; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - public MovieDbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager) + public MovieDbProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILogger logger, ILocalizationManager localization, ILibraryManager libraryManager, IApplicationHost appHost) { _jsonSerializer = jsonSerializer; _httpClient = httpClient; @@ -52,6 +54,7 @@ namespace MediaBrowser.Providers.Movies _logger = logger; _localization = localization; _libraryManager = libraryManager; + _appHost = appHost; Current = this; } @@ -160,7 +163,8 @@ namespace MediaBrowser.Providers.Movies { Url = string.Format(TmdbConfigUrl, ApiKey), CancellationToken = cancellationToken, - AcceptHeader = AcceptHeader + AcceptHeader = AcceptHeader, + UserAgent = "Emby/" + _appHost.ApplicationVersion }).ConfigureAwait(false)) { From 84684434103c008006ffb6804a2af8e3a0b1ed78 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 20:58:22 -0500 Subject: [PATCH 15/27] update movie db user agent --- MediaBrowser.Providers/Movies/MovieDbProvider.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index f7e4142fa5..593c6f180e 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -163,8 +163,7 @@ namespace MediaBrowser.Providers.Movies { Url = string.Format(TmdbConfigUrl, ApiKey), CancellationToken = cancellationToken, - AcceptHeader = AcceptHeader, - UserAgent = "Emby/" + _appHost.ApplicationVersion + AcceptHeader = AcceptHeader }).ConfigureAwait(false)) { @@ -391,6 +390,8 @@ namespace MediaBrowser.Providers.Movies options.ResourcePool = MovieDbResourcePool; _lastRequestTicks = DateTime.UtcNow.Ticks; + options.UserAgent = "Emby/" + _appHost.ApplicationVersion; + return await _httpClient.Get(options).ConfigureAwait(false); } From 0181383d1e5a05b1a6950faf5e872133c987f676 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 21:32:14 -0500 Subject: [PATCH 16/27] throttle people requests --- MediaBrowser.Api/ItemRefreshService.cs | 3 +- .../Providers/ImageRefreshOptions.cs | 2 + .../Providers/ItemLookupInfo.cs | 4 +- .../Manager/MetadataService.cs | 1 + .../People/MovieDbPersonProvider.cs | 38 ++++++++++++++++++- 5 files changed, 45 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index af1f1c90ad..1e912c92d6 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -76,7 +76,8 @@ namespace MediaBrowser.Api ImageRefreshMode = request.ImageRefreshMode, ReplaceAllImages = request.ReplaceAllImages, ReplaceAllMetadata = request.ReplaceAllMetadata, - ForceSave = true + ForceSave = true, + IsAutomated = false }; } } diff --git a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs index a66cc6f222..9b21a29724 100644 --- a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs @@ -11,6 +11,7 @@ namespace MediaBrowser.Controller.Providers public bool ReplaceAllImages { get; set; } public List ReplaceImages { get; set; } + public bool IsAutomated { get; set; } public ImageRefreshOptions(IDirectoryService directoryService) { @@ -18,6 +19,7 @@ namespace MediaBrowser.Controller.Providers DirectoryService = directoryService; ReplaceImages = new List(); + IsAutomated = true; } public bool IsReplacingImage(ImageType type) diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs index 7114cde3e2..dc7a04135a 100644 --- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs @@ -33,10 +33,12 @@ namespace MediaBrowser.Controller.Providers public int? Year { get; set; } public int? IndexNumber { get; set; } public int? ParentIndexNumber { get; set; } - public DateTime? PremiereDate { get; set; } + public DateTime? PremiereDate { get; set; } + public bool IsAutomated { get; set; } public ItemLookupInfo() { + IsAutomated = true; ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index d9f5c30fd5..e18da565df 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -138,6 +138,7 @@ namespace MediaBrowser.Providers.Manager var id = itemOfType.GetLookupInfo(); //await FindIdentities(id, cancellationToken).ConfigureAwait(false); + id.IsAutomated = refreshOptions.IsAutomated; var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index 4e652a4285..0dab24b11a 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; using MediaBrowser.Providers.Movies; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -18,6 +19,7 @@ using System.Net; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; namespace MediaBrowser.Providers.People @@ -32,14 +34,30 @@ namespace MediaBrowser.Providers.People private readonly IFileSystem _fileSystem; private readonly IServerConfigurationManager _configurationManager; private readonly IHttpClient _httpClient; + private readonly ILogger _logger; - public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient) + private int _requestCount; + private readonly object _requestCountLock = new object(); + private Timer _requestCountReset; + + public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger) { _fileSystem = fileSystem; _configurationManager = configurationManager; _jsonSerializer = jsonSerializer; _httpClient = httpClient; + _logger = logger; Current = this; + + _requestCountReset = new Timer(OnRequestThrottleTimerFired, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1)); + } + + private void OnRequestThrottleTimerFired(object state) + { + lock (_requestCountLock) + { + _requestCount = 0; + } } public string Name @@ -79,6 +97,24 @@ namespace MediaBrowser.Providers.People return new[] { result }; } + if (searchInfo.IsAutomated) + { + lock (_requestCountLock) + { + var requestCount = _requestCount; + + if (requestCount >= 5) + { + _logger.Debug("Throttling Tmdb people"); + + // This needs to be throttled + return new List(); + } + + _requestCount = requestCount + 1; + } + } + var url = string.Format(@"http://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey); using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions From 0eb664ccfffd8b4e4b13c1bc538b6451ffd81036 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 22:10:11 -0500 Subject: [PATCH 17/27] trim logging --- MediaBrowser.Providers/People/MovieDbPersonProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index 0dab24b11a..5c59197094 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -105,7 +105,7 @@ namespace MediaBrowser.Providers.People if (requestCount >= 5) { - _logger.Debug("Throttling Tmdb people"); + //_logger.Debug("Throttling Tmdb people"); // This needs to be throttled return new List(); From 7a2ab5d0285ae294d02f87e52497e7f89d96512b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 12:12:11 -0500 Subject: [PATCH 18/27] fix image extension --- MediaBrowser.Providers/Manager/ImageSaver.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 4bec352f6c..32ea474258 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -405,12 +405,12 @@ namespace MediaBrowser.Providers.Manager break; } - if (string.Equals(extension, "jpeg", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(extension, ".jpeg", StringComparison.OrdinalIgnoreCase)) { - extension = "jpg"; + extension = ".jpg"; } - extension = "." + extension.ToLower(); + extension = extension.ToLower(); string path = null; From 18cd0dd98cb00068ffef082ad8a0dc6c18040471 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 13:21:35 -0500 Subject: [PATCH 19/27] update http compression --- .../Connect/ConnectEntryPoint.cs | 5 ++- .../EntryPoints/UsageReporter.cs | 36 ++++++++++++++++--- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs index af81b4eeaf..6dab136a58 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs @@ -66,7 +66,10 @@ namespace MediaBrowser.Server.Implementations.Connect { Url = ipLookupUrl, UserAgent = "Emby/" + _appHost.ApplicationVersion, - LogErrors = logErrors + LogErrors = logErrors, + + // Seeing block length errors with our server + EnableHttpCompression = false }).ConfigureAwait(false)) { diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs index 5496bd9b27..be2817fd29 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _logger = logger; } - public Task ReportServerUsage(CancellationToken cancellationToken) + public async Task ReportServerUsage(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); @@ -51,10 +51,24 @@ namespace MediaBrowser.Server.Implementations.EntryPoints data["plugins"] = string.Join(",", _applicationHost.Plugins.Select(i => i.Id).ToArray()); - return _httpClient.Post(MbAdminUrl + "service/registration/ping", data, cancellationToken); + var options = new HttpRequestOptions + { + Url = MbAdminUrl + "service/registration/ping", + CancellationToken = cancellationToken, + + // Seeing block length errors + EnableHttpCompression = false + }; + + options.SetPostData(data); + + using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) + { + + } } - public Task ReportAppUsage(ClientInfo app, CancellationToken cancellationToken) + public async Task ReportAppUsage(ClientInfo app, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(app.DeviceId)) { @@ -79,7 +93,21 @@ namespace MediaBrowser.Server.Implementations.EntryPoints { "platform", app.DeviceName }, }; - return _httpClient.Post(MbAdminUrl + "service/registration/ping", data, cancellationToken); + var options = new HttpRequestOptions + { + Url = MbAdminUrl + "service/registration/ping", + CancellationToken = cancellationToken, + + // Seeing block length errors + EnableHttpCompression = false + }; + + options.SetPostData(data); + + using (var response = await _httpClient.SendAsync(options, "POST").ConfigureAwait(false)) + { + + } } } From e08ab66dd61860bc13d3a5149afe0d7fbbddd93e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 14:13:45 -0500 Subject: [PATCH 20/27] 3.0.5818 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 76cc4acd2b..26718c7002 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5817")] +[assembly: AssemblyVersion("3.0.5818")] From 53a1fbeb61b3641100ea93023ca3adb443d9a044 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Jan 2016 17:00:44 -0500 Subject: [PATCH 21/27] update ffmpeg for osx --- .../FFMpeg/FFMpegDownloadInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index 0314fcc7eb..b055c250b8 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg switch (environment.SystemArchitecture) { case Architecture.X86_X64: - info.Version = "20150917"; + info.Version = "20160124"; break; case Architecture.X86: info.Version = "20150110"; @@ -102,7 +102,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg case Architecture.X86_X64: return new[] { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.0.7z" + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.5.7z" }; case Architecture.X86: return new[] From 51c70ab84005932f594c49f4db4563f4fb2e951b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Jan 2016 23:12:47 -0500 Subject: [PATCH 22/27] fix pt-br from tvdb --- MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs | 4 +--- MediaBrowser.Providers/TV/TvdbSeriesProvider.cs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs index d039207422..3920330489 100644 --- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs @@ -169,10 +169,8 @@ namespace MediaBrowser.Providers.TV /// /// Gets the episode XML files. /// - /// The season number. - /// The episode number. - /// The ending episode number. /// The series data path. + /// The search information. /// List{FileInfo}. internal List GetEpisodeXmlNodes(string seriesDataPath, EpisodeInfo searchInfo) { diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 00bc032ca7..313ca9074d 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -58,6 +58,17 @@ namespace MediaBrowser.Providers.TV private const string SeriesGetZip = "http://www.thetvdb.com/api/{0}/series/{1}/all/{2}.zip"; private const string GetSeriesByImdbId = "http://www.thetvdb.com/api/GetSeriesByRemoteID.php?imdbid={0}&language={1}"; + private string NormalizeLanguage(string language) + { + if (string.IsNullOrWhiteSpace(language)) + { + return language; + } + + // pt-br is just pt to tvdb + return language.Split('-')[0].ToLower(); + } + public async Task> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) { if (IsValidSeries(searchInfo.ProviderIds)) @@ -270,7 +281,7 @@ namespace MediaBrowser.Providers.TV private async Task GetSeriesByRemoteId(string id, string idType, string language, CancellationToken cancellationToken) { - var url = string.Format(GetSeriesByImdbId, id, language); + var url = string.Format(GetSeriesByImdbId, id, NormalizeLanguage(language)); using (var result = await _httpClient.Get(new HttpRequestOptions { @@ -455,7 +466,7 @@ namespace MediaBrowser.Providers.TV private async Task> FindSeriesInternal(string name, string language, CancellationToken cancellationToken) { - var url = string.Format(SeriesSearchUrl, WebUtility.UrlEncode(name), language.ToLower()); + var url = string.Format(SeriesSearchUrl, WebUtility.UrlEncode(name), NormalizeLanguage(language)); var doc = new XmlDocument(); using (var results = await _httpClient.Get(new HttpRequestOptions From d317bedd851b04bc427a6c7c396a09c48ea7a069 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 23:21:31 -0500 Subject: [PATCH 23/27] improve reaction to image stub failures Conflicts: MediaBrowser.Server.Implementations/Library/LibraryManager.cs --- .../Manager/ItemImageProvider.cs | 35 +++++++++--------- .../Library/LibraryManager.cs | 36 ++++++++++++++----- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index f99aa967fb..370187801e 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -480,22 +480,21 @@ namespace MediaBrowser.Providers.Manager ImageType type, CancellationToken cancellationToken) { - foreach (var image in images.Where(i => i.Type == type)) + var eligibleImages = images + .Where(i => i.Type == type && !(i.Width.HasValue && i.Width.Value < minWidth)) + .ToList(); + + if (EnableImageStub(item, type) && eligibleImages.Count > 0) { - if (image.Width.HasValue && image.Width.Value < minWidth) - { - continue; - } + SaveImageStub(item, type, eligibleImages.Select(i => i.Url)); + result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; + return true; + } + foreach (var image in eligibleImages) + { var url = image.Url; - if (EnableImageStub(item, type)) - { - SaveImageStub(item, type, url); - result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; - return true; - } - try { var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false); @@ -557,18 +556,20 @@ namespace MediaBrowser.Providers.Manager } } - private void SaveImageStub(IHasImages item, ImageType imageType, string url) + private void SaveImageStub(IHasImages item, ImageType imageType, IEnumerable urls) { var newIndex = item.AllowsMultipleImages(imageType) ? item.GetImages(imageType).Count() : 0; - SaveImageStub(item, imageType, url, newIndex); + SaveImageStub(item, imageType, urls, newIndex); } - private void SaveImageStub(IHasImages item, ImageType imageType, string url, int newIndex) + private void SaveImageStub(IHasImages item, ImageType imageType, IEnumerable urls, int newIndex) { + var path = string.Join("|", urls.Take(1).ToArray()); + item.SetImage(new ItemImageInfo { - Path = url, + Path = path, Type = imageType }, newIndex); @@ -592,7 +593,7 @@ namespace MediaBrowser.Providers.Manager if (EnableImageStub(item, imageType)) { - SaveImageStub(item, imageType, url); + SaveImageStub(item, imageType, new[] { url }); result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate; continue; } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index f27f35c486..d0e72ac63f 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -2387,20 +2387,40 @@ namespace MediaBrowser.Server.Implementations.Library private readonly SemaphoreSlim _dynamicImageResourcePool = new SemaphoreSlim(1,1); public async Task ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex) { - _logger.Debug("ConvertImageToLocal item {0}", item.Id); + foreach (var url in image.Path.Split('|')) + { + try + { + _logger.Debug("ConvertImageToLocal item {0} - image url: {1}", item.Id, url); - await _providerManagerFactory().SaveImage(item, image.Path, _dynamicImageResourcePool, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); + await _providerManagerFactory().SaveImage(item, url, _dynamicImageResourcePool, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); - var newImage = item.GetImageInfo(image.Type, imageIndex); + var newImage = item.GetImageInfo(image.Type, imageIndex); - if (newImage != null) - { - newImage.IsPlaceholder = image.IsPlaceholder; + if (newImage != null) + { + newImage.IsPlaceholder = image.IsPlaceholder; + } + + await item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); + + return item.GetImageInfo(image.Type, imageIndex); + } + catch (HttpException ex) + { + if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.NotFound) + { + continue; + } + throw; + } } + // Remove this image to prevent it from retrying over and over + item.RemoveImage(image); await item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); - - return item.GetImageInfo(image.Type, imageIndex); + + throw new InvalidOperationException(); } } } From 50e983e3a1784f35eb72c340613f639ba7eae9d7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Jan 2016 17:11:46 -0500 Subject: [PATCH 24/27] fix merge error --- MediaBrowser.Server.Implementations/Library/LibraryManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index d0e72ac63f..0cb5174c9a 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -32,10 +32,12 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Net; using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Net; using MoreLinq; using SortOrder = MediaBrowser.Model.Entities.SortOrder; From c48a4cfb992d486cf55f8d687b6ff0559ae38783 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 01:06:02 -0500 Subject: [PATCH 25/27] remove xml savers --- MediaBrowser.Api/StartupWizardService.cs | 1 - .../MediaBrowser.LocalMetadata.csproj | 3 - .../Savers/EpisodeXmlSaver.cs | 166 ------------------ .../Savers/MovieXmlSaver.cs | 147 ---------------- .../Savers/SeriesXmlSaver.cs | 154 ---------------- .../Configuration/ServerConfiguration.cs | 1 - 6 files changed, 472 deletions(-) delete mode 100644 MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs delete mode 100644 MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs delete mode 100644 MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 399c81ae88..afe3da7106 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -70,7 +70,6 @@ namespace MediaBrowser.Api _config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableLibraryMetadataSubFolder = true; _config.Configuration.EnableCustomPathSubFolders = true; - _config.Configuration.DisableXmlSavers = true; _config.Configuration.DisableStartupScan = true; _config.Configuration.EnableUserViews = true; _config.Configuration.EnableDateLastRefresh = true; diff --git a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj index 9a641776aa..c673c01df8 100644 --- a/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj +++ b/MediaBrowser.LocalMetadata/MediaBrowser.LocalMetadata.csproj @@ -79,14 +79,11 @@ - - - diff --git a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs deleted file mode 100644 index dc8a16cd8b..0000000000 --- a/MediaBrowser.LocalMetadata/Savers/EpisodeXmlSaver.cs +++ /dev/null @@ -1,166 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using CommonIO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.LocalMetadata.Savers -{ - public class EpisodeXmlProvider : IMetadataFileSaver, IConfigurableProvider - { - private readonly IItemRepository _itemRepository; - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private IFileSystem _fileSystem; - - public EpisodeXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem) - { - _itemRepository = itemRepository; - _config = config; - _libraryManager = libraryManager; - _fileSystem = fileSystem; - } - - /// - /// Determines whether [is enabled for] [the specified item]. - /// - /// The item. - /// Type of the update. - /// true if [is enabled for] [the specified item]; otherwise, false. - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is Episode && updateType >= ItemUpdateType.MetadataDownload; - } - - public string Name - { - get - { - return XmlProviderUtils.Name; - } - } - - public bool IsEnabled - { - get { return !_config.Configuration.DisableXmlSavers; } - } - - /// - /// Saves the specified item. - /// - /// The item. - /// The cancellation token. - /// Task. - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var episode = (Episode)item; - - var builder = new StringBuilder(); - - builder.Append(""); - - if (!string.IsNullOrEmpty(item.Name)) - { - builder.Append("" + SecurityElement.Escape(episode.Name) + ""); - } - - if (episode.IndexNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.IndexNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.IndexNumberEnd.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + ""); - } - - if (episode.AirsAfterSeasonNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + ""); - } - if (episode.AirsBeforeEpisodeNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + ""); - } - if (episode.AirsBeforeSeasonNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.ParentIndexNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.ParentIndexNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.AbsoluteEpisodeNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.DvdEpisodeNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.DvdSeasonNumber.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + ""); - } - - if (episode.PremiereDate.HasValue) - { - builder.Append("" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + ""); - } - - XmlSaverHelpers.AddCommonNodes(episode, _libraryManager, builder); - XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository); - - builder.Append(""); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List - { - "FirstAired", - "SeasonNumber", - "EpisodeNumber", - "EpisodeName", - "EpisodeNumberEnd", - "airsafter_season", - "airsbefore_episode", - "airsbefore_season", - "DVD_episodenumber", - "DVD_season", - "absolute_number" - - }, _config, _fileSystem); - } - - /// - /// Gets the save path. - /// - /// The item. - /// System.String. - public string GetSavePath(IHasMetadata item) - { - var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml"); - - return Path.Combine(Path.GetDirectoryName(item.Path), "metadata", filename); - } - } -} diff --git a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs deleted file mode 100644 index 2e3e7aaa1e..0000000000 --- a/MediaBrowser.LocalMetadata/Savers/MovieXmlSaver.cs +++ /dev/null @@ -1,147 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using System.Collections.Generic; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using CommonIO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.LocalMetadata.Savers -{ - /// - /// Saves movie.xml for movies, trailers and music videos - /// - public class MovieXmlProvider : IMetadataFileSaver, IConfigurableProvider - { - private readonly IItemRepository _itemRepository; - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private IFileSystem _fileSystem; - - public MovieXmlProvider(IItemRepository itemRepository, IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem) - { - _itemRepository = itemRepository; - _config = config; - _libraryManager = libraryManager; - _fileSystem = fileSystem; - } - - public string Name - { - get - { - return XmlProviderUtils.Name; - } - } - - public bool IsEnabled - { - get { return !_config.Configuration.DisableXmlSavers; } - } - - /// - /// Determines whether [is enabled for] [the specified item]. - /// - /// The item. - /// Type of the update. - /// true if [is enabled for] [the specified item]; otherwise, false. - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - var video = item as Video; - - // Check parent for null to avoid running this against things like video backdrops - if (video != null && !(item is Episode) && !video.IsOwnedItem) - { - return updateType >= ItemUpdateType.MetadataDownload; - } - - return false; - } - - /// - /// Saves the specified item. - /// - /// The item. - /// The cancellation token. - /// Task. - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var video = (Video)item; - - var builder = new StringBuilder(); - - builder.Append(""); - - XmlSaverHelpers.AddCommonNodes(video, _libraryManager, builder); - - var musicVideo = item as MusicVideo; - - if (musicVideo != null) - { - if (musicVideo.Artists.Count > 0) - { - builder.Append("<Artist>" + SecurityElement.Escape(string.Join(";", musicVideo.Artists.ToArray())) + "</Artist>"); - } - if (!string.IsNullOrEmpty(musicVideo.Album)) - { - builder.Append("<Album>" + SecurityElement.Escape(musicVideo.Album) + "</Album>"); - } - } - - var movie = item as Movie; - - if (movie != null) - { - if (!string.IsNullOrEmpty(movie.TmdbCollectionName)) - { - builder.Append("<TmdbCollectionName>" + SecurityElement.Escape(movie.TmdbCollectionName) + "</TmdbCollectionName>"); - } - } - - XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository); - - builder.Append(""); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List - { - // Deprecated. No longer saving in this field. - "IMDBrating", - - // Deprecated. No longer saving in this field. - "Description", - - "Artist", - "Album", - "TmdbCollectionName" - }, _config, _fileSystem); - } - - public string GetSavePath(IHasMetadata item) - { - return GetMovieSavePath((Video)item); - } - - public static string GetMovieSavePath(Video item) - { - if (item.IsInMixedFolder) - { - return Path.ChangeExtension(item.Path, ".xml"); - } - - return Path.Combine(item.ContainingFolderPath, "movie.xml"); - } - } -} diff --git a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs deleted file mode 100644 index 9806c4216e..0000000000 --- a/MediaBrowser.LocalMetadata/Savers/SeriesXmlSaver.cs +++ /dev/null @@ -1,154 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using CommonIO; -using MediaBrowser.Common.IO; - -namespace MediaBrowser.LocalMetadata.Savers -{ - public class SeriesXmlProvider : IMetadataFileSaver, IConfigurableProvider - { - private readonly IServerConfigurationManager _config; - private readonly ILibraryManager _libraryManager; - private IFileSystem _fileSystem; - - public SeriesXmlProvider(IServerConfigurationManager config, ILibraryManager libraryManager, IFileSystem fileSystem) - { - _config = config; - _libraryManager = libraryManager; - _fileSystem = fileSystem; - } - - public string Name - { - get - { - return XmlProviderUtils.Name; - } - } - - /// - /// Determines whether [is enabled for] [the specified item]. - /// - /// The item. - /// Type of the update. - /// true if [is enabled for] [the specified item]; otherwise, false. - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is Series && updateType >= ItemUpdateType.MetadataDownload; - } - - public bool IsEnabled - { - get { return !_config.Configuration.DisableXmlSavers; } - } - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - /// - /// Saves the specified item. - /// - /// The item. - /// The cancellation token. - /// Task. - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var series = (Series)item; - - var builder = new StringBuilder(); - - builder.Append(""); - - var tvdb = item.GetProviderId(MetadataProviders.Tvdb); - - if (!string.IsNullOrEmpty(tvdb)) - { - builder.Append("" + SecurityElement.Escape(tvdb) + ""); - } - - if (series.Status.HasValue) - { - builder.Append("" + SecurityElement.Escape(series.Status.Value.ToString()) + ""); - } - - if (series.Studios.Count > 0) - { - builder.Append("" + SecurityElement.Escape(series.Studios[0]) + ""); - } - - if (!string.IsNullOrEmpty(series.AirTime)) - { - builder.Append("" + SecurityElement.Escape(series.AirTime) + ""); - } - - if (series.AirDays != null) - { - if (series.AirDays.Count == 7) - { - builder.Append("" + SecurityElement.Escape("Daily") + ""); - } - else if (series.AirDays.Count > 0) - { - builder.Append("" + SecurityElement.Escape(series.AirDays[0].ToString()) + ""); - } - } - - if (series.PremiereDate.HasValue) - { - builder.Append("" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + ""); - } - - if (series.AnimeSeriesIndex.HasValue) - { - builder.Append("" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(UsCulture)) + ""); - } - - XmlSaverHelpers.AddCommonNodes(series, _libraryManager, builder); - - builder.Append(""); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List - { - "id", - "Status", - "Network", - "Airs_Time", - "Airs_DayOfWeek", - "FirstAired", - - // Don't preserve old series node - "Series", - - "SeriesName", - - // Deprecated. No longer saving in this field. - "AnimeSeriesIndex" - }, _config, _fileSystem); - } - - /// - /// Gets the save path. - /// - /// The item. - /// System.String. - public string GetSavePath(IHasMetadata item) - { - return Path.Combine(item.Path, "series.xml"); - } - } -} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 7208ccb1d9..fb22637f95 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -219,7 +219,6 @@ namespace MediaBrowser.Model.Configuration public int SharingExpirationDays { get; set; } - public bool DisableXmlSavers { get; set; } public bool EnableWindowsShortcuts { get; set; } public bool EnableVideoFrameByFrameAnalysis { get; set; } From f14e9b8d3af98f6ffbe243b105f96f46e8cf3b06 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 1 Feb 2016 14:21:22 -0500 Subject: [PATCH 26/27] fix merge conflict --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 26718c7002..a5c9547e00 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5818")] +[assembly: AssemblyVersion("3.0.5857")] From 008522226f52256cc7d6304178adb8887b403b1e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 1 Feb 2016 14:25:16 -0500 Subject: [PATCH 27/27] 3.0.5820 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index a5c9547e00..000dd49ee0 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5857")] +[assembly: AssemblyVersion("3.0.5820")]