From 1e4ee3f60e291c50cd7158125d3e960171ad706f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Jan 2016 15:25:46 -0500 Subject: [PATCH 01/90] 3.0.5840 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 706b839960..6f6d432099 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.5840")] From 086713064ca884655b41f15f6cb61766c5bf2ea0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Jan 2016 20:05:14 -0500 Subject: [PATCH 02/90] 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 aaf316884d4e705a9dc47002f492f28649e4821b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 03:23:02 -0500 Subject: [PATCH 03/90] 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 c71a319685b7a5027112ce3059e7fdff3fff3729 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 11:53:03 -0500 Subject: [PATCH 04/90] 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 06f8047ee6a68fb5429b3d938b2916f1a17a63b5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 12:29:14 -0500 Subject: [PATCH 05/90] support system wake on recording schedule --- .../MediaBrowser.Controller.csproj | 1 + .../Power/IPowerManagement.cs | 13 ++++++ .../LiveTv/EmbyTV/EmbyTV.cs | 5 ++- .../LiveTv/EmbyTV/TimerManager.cs | 30 +++++++++++++- .../Native/BaseMonoApp.cs | 14 +++++++ .../ApplicationHost.cs | 2 + .../INativeApp.cs | 7 ++++ .../MediaBrowser.ServerApplication.csproj | 1 + .../Native/WindowsApp.cs | 6 +++ .../Native/WindowsPowerManagement.cs | 40 +++++++++++++++++++ 10 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 MediaBrowser.Controller/Power/IPowerManagement.cs create mode 100644 MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 2227df3f03..471aa38d4b 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -265,6 +265,7 @@ + diff --git a/MediaBrowser.Controller/Power/IPowerManagement.cs b/MediaBrowser.Controller/Power/IPowerManagement.cs new file mode 100644 index 0000000000..faa2896952 --- /dev/null +++ b/MediaBrowser.Controller/Power/IPowerManagement.cs @@ -0,0 +1,13 @@ +using System; + +namespace MediaBrowser.Controller.Power +{ + public interface IPowerManagement + { + /// + /// Schedules the wake. + /// + /// The UTC time. + void ScheduleWake(DateTime utcTime); + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 356d0d83d5..3d1d9e0bab 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -28,6 +28,7 @@ using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Power; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { @@ -55,7 +56,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public static EmbyTV Current; - public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ISecurityManager security, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder) + public EmbyTV(IApplicationHost appHost, ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IServerConfigurationManager config, ILiveTvManager liveTvManager, IFileSystem fileSystem, ISecurityManager security, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager, IFileOrganizationService organizationService, IMediaEncoder mediaEncoder, IPowerManagement powerManagement) { Current = this; @@ -75,7 +76,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _recordingProvider = new ItemDataProvider(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "recordings"), (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)); _seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); - _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers")); + _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), powerManagement, _logger); _timerProvider.TimerFired += _timerProvider_TimerFired; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 80bb671fa7..ca20379b66 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -8,19 +8,23 @@ using System.Collections.Concurrent; using System.Linq; using System.Threading; using CommonIO; -using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Power; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { public class TimerManager : ItemDataProvider { private readonly ConcurrentDictionary _timers = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private readonly IPowerManagement _powerManagement; + private readonly ILogger _logger; public event EventHandler> TimerFired; - public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath) + public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, IPowerManagement powerManagement, ILogger logger1) : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) { + _powerManagement = powerManagement; + _logger = logger1; } public void RestartTimers() @@ -58,6 +62,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { var timespan = RecordingHelper.GetStartTime(item) - DateTime.UtcNow; timer.Change(timespan, TimeSpan.Zero); + ScheduleWake(item); } else { @@ -74,6 +79,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV base.Add(item); AddTimer(item); + ScheduleWake(item); } private void AddTimer(TimerInfo item) @@ -91,6 +97,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV StartTimer(item, timerLength); } + private void ScheduleWake(TimerInfo info) + { + var startDate = RecordingHelper.GetStartTime(info).AddMinutes(-5); + _logger.Info("Scheduling system wake timer at {0} (UTC)", startDate); + + try + { + _powerManagement.ScheduleWake(startDate); + _logger.Info("Scheduled system wake timer at {0} (UTC)", startDate); + } + catch (NotImplementedException) + { + + } + catch (Exception ex) + { + _logger.ErrorException("Error scheduling wake timer", ex); + } + } + public void StartTimer(TimerInfo item, TimeSpan length) { StopTimer(item); diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index 31d4592c8e..e57a651c00 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Text.RegularExpressions; +using MediaBrowser.Controller.Power; namespace MediaBrowser.Server.Mono.Native { @@ -203,5 +204,18 @@ namespace MediaBrowser.Server.Mono.Native public string sysname = string.Empty; public string machine = string.Empty; } + + public IPowerManagement GetPowerManagement() + { + return new NullPowerManagement(); + } + } + + public class NullPowerManagement : IPowerManagement + { + public void ScheduleWake(DateTime utcTime) + { + throw new NotImplementedException(); + } } } diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 21731a3a60..1db019d8d2 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -533,6 +533,8 @@ namespace MediaBrowser.Server.Startup.Common EncodingManager = new EncodingManager(FileSystemManager, Logger, MediaEncoder, ChapterManager); RegisterSingleInstance(EncodingManager); + RegisterSingleInstance(NativeApp.GetPowerManagement()); + var sharingRepo = new SharingRepository(LogManager, ApplicationPaths); await sharingRepo.Initialize().ConfigureAwait(false); RegisterSingleInstance(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this)); diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index 597caf34cc..75b38d0c4c 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -2,6 +2,7 @@ using MediaBrowser.Model.Logging; using System.Collections.Generic; using System.Reflection; +using MediaBrowser.Controller.Power; namespace MediaBrowser.Server.Startup.Common { @@ -90,5 +91,11 @@ namespace MediaBrowser.Server.Startup.Common /// Prevents the system stand by. /// void PreventSystemStandby(); + + /// + /// Gets the power management. + /// + /// IPowerManagement. + IPowerManagement GetPowerManagement(); } } diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index c629831923..80e56d6e11 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -120,6 +120,7 @@ + diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index ceab5379d5..9ef9c7d501 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -6,6 +6,7 @@ using MediaBrowser.ServerApplication.Networking; using System.Collections.Generic; using System.Reflection; using CommonIO; +using MediaBrowser.Controller.Power; namespace MediaBrowser.ServerApplication.Native { @@ -117,5 +118,10 @@ namespace MediaBrowser.ServerApplication.Native { Standby.PreventSystemStandby(); } + + public IPowerManagement GetPowerManagement() + { + return new WindowsPowerManagement(); + } } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs new file mode 100644 index 0000000000..6bd78553b6 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs @@ -0,0 +1,40 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Threading; +using MediaBrowser.Controller.Power; +using Microsoft.Win32.SafeHandles; + +namespace MediaBrowser.ServerApplication.Native +{ + public class WindowsPowerManagement : IPowerManagement + { + [DllImport("kernel32.dll")] + public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume); + + public void ScheduleWake(DateTime utcTime) + { + long duetime = utcTime.ToFileTime(); + + using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, "MyWaitabletimer")) + { + if (SetWaitableTimer(handle, ref duetime, 0, IntPtr.Zero, IntPtr.Zero, true)) + { + using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset)) + { + wh.SafeWaitHandle = handle; + wh.WaitOne(); + } + } + else + { + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + } + } + } +} From a10347a455fbc27284caa8a42c5e77cda9683eab Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 12:45:42 -0500 Subject: [PATCH 06/90] update wake timer --- .../LiveTv/LiveTvManager.cs | 1 + MediaBrowser.ServerApplication/MainStartup.cs | 2 +- .../Native/WindowsApp.cs | 6 +- .../Native/WindowsPowerManagement.cs | 77 ++++++++++++++++--- 4 files changed, 71 insertions(+), 15 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index e09e06bd4b..8bf1d27b8b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1954,6 +1954,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv await service.CreateTimerAsync(info, cancellationToken).ConfigureAwait(false); _lastRecordingRefreshTime = DateTime.MinValue; + _logger.Info("New recording scheduled"); } public async Task CreateSeriesTimer(SeriesTimerInfoDto timer, CancellationToken cancellationToken) diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 62cdbd05f4..cf174c2d3b 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -218,7 +218,7 @@ namespace MediaBrowser.ServerApplication var fileSystem = new WindowsFileSystem(new PatternsLogger(logManager.GetLogger("FileSystem"))); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - var nativeApp = new WindowsApp(fileSystem) + var nativeApp = new WindowsApp(fileSystem, _logger) { IsRunningAsService = runService }; diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 9ef9c7d501..fe2fe6de6c 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -13,10 +13,12 @@ namespace MediaBrowser.ServerApplication.Native public class WindowsApp : INativeApp { private readonly IFileSystem _fileSystem; + private readonly ILogger _logger; - public WindowsApp(IFileSystem fileSystem) + public WindowsApp(IFileSystem fileSystem, ILogger logger) { _fileSystem = fileSystem; + _logger = logger; } public List GetAssembliesWithParts() @@ -121,7 +123,7 @@ namespace MediaBrowser.ServerApplication.Native public IPowerManagement GetPowerManagement() { - return new WindowsPowerManagement(); + return new WindowsPowerManagement(_logger); } } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs index 6bd78553b6..3b05febafe 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Runtime.InteropServices; using System.Threading; using MediaBrowser.Controller.Power; +using MediaBrowser.Model.Logging; using Microsoft.Win32.SafeHandles; namespace MediaBrowser.ServerApplication.Native @@ -10,30 +11,82 @@ namespace MediaBrowser.ServerApplication.Native public class WindowsPowerManagement : IPowerManagement { [DllImport("kernel32.dll")] - public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName); + public static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, + bool bManualReset, + string lpTimerName); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume); + public static extern bool SetWaitableTimer(SafeWaitHandle hTimer, + [In] ref long pDueTime, + int lPeriod, + IntPtr pfnCompletionRoutine, + IntPtr lpArgToCompletionRoutine, + bool fResume); + + private BackgroundWorker _bgWorker; + private readonly ILogger _logger; + private readonly object _initLock = new object(); + + public WindowsPowerManagement(ILogger logger) + { + _logger = logger; + } public void ScheduleWake(DateTime utcTime) { - long duetime = utcTime.ToFileTime(); + Initialize(); + _bgWorker.RunWorkerAsync(utcTime.ToFileTime()); + } - using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, "MyWaitabletimer")) + private void Initialize() + { + lock (_initLock) { - if (SetWaitableTimer(handle, ref duetime, 0, IntPtr.Zero, IntPtr.Zero, true)) + if (_bgWorker == null) { - using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset)) + _bgWorker = new BackgroundWorker(); + + _bgWorker.DoWork += bgWorker_DoWork; + _bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted; + } + } + } + + void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + { + //if (Woken != null) + //{ + // Woken(this, new EventArgs()); + //} + } + + private void bgWorker_DoWork(object sender, DoWorkEventArgs e) + { + try + { + long waketime = (long)e.Argument; + + using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, GetType().Assembly.GetName().Name + "Timer")) + { + if (SetWaitableTimer(handle, ref waketime, 0, IntPtr.Zero, IntPtr.Zero, true)) { - wh.SafeWaitHandle = handle; - wh.WaitOne(); + using (EventWaitHandle wh = new EventWaitHandle(false, + EventResetMode.AutoReset)) + { + wh.SafeWaitHandle = handle; + wh.WaitOne(); + } + } + else + { + throw new Win32Exception(Marshal.GetLastWin32Error()); } } - else - { - throw new Win32Exception(Marshal.GetLastWin32Error()); - } + } + catch (Exception ex) + { + _logger.ErrorException("Error scheduling wake timer", ex); } } } From 410f1333e43d27c3af121f3e9e39d152c6eb8a05 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 12:48:07 -0500 Subject: [PATCH 07/90] 3.0.5841 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 6f6d432099..8791b5ec54 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5840")] +[assembly: AssemblyVersion("3.0.5841")] From 5cd032d86b2b5cf34c2dda8b7650df4725a71ae7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 13:50:43 -0500 Subject: [PATCH 08/90] 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 9719b8d532fdbf4e611d2f75ba036339e972bc30 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 13:56:28 -0500 Subject: [PATCH 09/90] 3.0.5842 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 8791b5ec54..9054ef0b61 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5841")] +[assembly: AssemblyVersion("3.0.5842")] From 7e0f97b2c371e6d96dc1ed0748f8054e27e82ea1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 14:45:52 -0500 Subject: [PATCH 10/90] 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 ccd237c4ded8dda7edfd6b7ab0fa86731cbad1ff Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 15:40:20 -0500 Subject: [PATCH 11/90] 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 5dc32c49a9cf06d96450df59ccbd6a141463e6a6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 21:29:00 -0500 Subject: [PATCH 12/90] 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 b050772b77682922226635675cd8b7a16efa4917 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 22:02:28 -0500 Subject: [PATCH 13/90] 3.0.5843 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 9054ef0b61..05ebe1ef89 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5842")] +[assembly: AssemblyVersion("3.0.5843")] From 1fe1908aeea9b1273c63edb19f187cef1f688d7a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 21:59:07 -0500 Subject: [PATCH 14/90] 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 8b545fea51eb68c952e928e675c375a984f8ebf0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 23:03:30 -0500 Subject: [PATCH 15/90] update naming project --- .../MediaBrowser.Server.Implementations.csproj | 4 ++-- MediaBrowser.Server.Implementations/packages.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index e5c94a01b4..b51c688b49 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -48,9 +48,9 @@ ..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll - + False - ..\packages\MediaBrowser.Naming.1.0.0.41\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll + ..\packages\MediaBrowser.Naming.1.0.0.42\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 5c04f27826..4b643fe219 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -2,7 +2,7 @@ - + From 86e7f58bb627d7d87f401dd811b1f32bd6e44c20 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 13:20:38 -0500 Subject: [PATCH 16/90] 3.0.5844 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 05ebe1ef89..68d67c0632 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5843")] +[assembly: AssemblyVersion("3.0.5844")] From 24b65b303fcfdd271b885dd4b7eab6c1a04c894e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 14:16:30 -0500 Subject: [PATCH 17/90] 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 db0bb0e070462af70c4aa2c2ae8f53311c1ea931 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 20:35:43 -0500 Subject: [PATCH 18/90] 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 636c7cc3ab9bb4444fb6bbb39904c76709d8c3e4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 20:57:35 -0500 Subject: [PATCH 19/90] 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 468a498768a87f5a2388a3fef9d0b6ab760e32f5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 20:58:22 -0500 Subject: [PATCH 20/90] 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 3f0927fb60560b0fb4aed7ef7215a688f2f548da Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 21:32:14 -0500 Subject: [PATCH 21/90] 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 1e62332d3d98ffad615b927c1a9960e118db75bd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 22:10:11 -0500 Subject: [PATCH 22/90] 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 111cf1d31522385fa62d8ee4b0cd310a567986d1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 22:10:21 -0500 Subject: [PATCH 23/90] trim logging --- .../HttpServer/HttpListenerHost.cs | 34 +++++++++++++-- .../HttpServer/LoggerUtils.cs | 19 +++++++++ .../SocketSharp/WebSocketSharpListener.cs | 42 +------------------ 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 6a23a84977..8d8d7f6f75 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -256,6 +256,25 @@ namespace MediaBrowser.Server.Implementations.HttpServer } } + private readonly Dictionary _skipLogExtensions = new Dictionary(StringComparer.OrdinalIgnoreCase) + { + {".js", 0}, + {".css", 0}, + {".woff", 0}, + {".woff2", 0}, + {".ttf", 0}, + {".html", 0} + }; + + private bool EnableLogging(string url) + { + var parts = url.Split(new[] { '?' }, 2); + + var extension = Path.GetExtension(parts[0]); + + return string.IsNullOrWhiteSpace(extension) || !_skipLogExtensions.ContainsKey(extension); + } + /// /// Overridable method that can be used to implement a custom hnandler /// @@ -271,6 +290,14 @@ namespace MediaBrowser.Server.Implementations.HttpServer var operationName = httpReq.OperationName; var localPath = url.LocalPath; + var urlString = url.ToString(); + var enableLog = EnableLogging(urlString); + + if (enableLog) + { + LoggerUtils.LogRequest(_logger, urlString, httpReq.HttpMethod, httpReq.UserAgent); + } + if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase)) { @@ -333,15 +360,16 @@ namespace MediaBrowser.Server.Implementations.HttpServer task.ContinueWith(x => httpRes.Close(), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent); //Matches Exceptions handled in HttpListenerBase.InitTask() - var urlString = url.ToString(); - task.ContinueWith(x => { var statusCode = httpRes.StatusCode; var duration = DateTime.Now - date; - LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration); + if (enableLog) + { + LoggerUtils.LogResponse(_logger, statusCode, urlString, remoteIp, duration); + } }, TaskContinuationOptions.None); return task; diff --git a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs index fae702023a..0b8caaa6e0 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/LoggerUtils.cs @@ -1,11 +1,30 @@ using MediaBrowser.Model.Logging; using System; using System.Globalization; +using System.IO; +using SocketHttpListener.Net; namespace MediaBrowser.Server.Implementations.HttpServer { public static class LoggerUtils { + /// + /// Logs the request. + /// + /// The logger. + /// The request. + public static void LogRequest(ILogger logger, HttpListenerRequest request) + { + var url = request.Url.ToString(); + + logger.Info("{0} {1}. UserAgent: {2}", (request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod), url, request.UserAgent ?? string.Empty); + } + + public static void LogRequest(ILogger logger, string url, string method, string userAgent) + { + logger.Info("{0} {1}. UserAgent: {2}", ("HTTP " + method), url, userAgent ?? string.Empty); + } + /// /// Logs the response. /// diff --git a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs index a91b1e3ed2..a029e09555 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/SocketSharp/WebSocketSharpListener.cs @@ -78,10 +78,10 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp { var request = context.Request; - LogRequest(_logger, request); - if (request.IsWebSocketRequest) { + LoggerUtils.LogRequest(_logger, request); + ProcessWebSocketRequest(context); return Task.FromResult(true); } @@ -156,44 +156,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer.SocketSharp return req; } - /// - /// Logs the request. - /// - /// The logger. - /// The request. - private static void LogRequest(ILogger logger, HttpListenerRequest request) - { - 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) { var httpReq = GetRequest(context); From 084404eaa13e69c464addc7ed3024c46082bf5d9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Jan 2016 22:11:37 -0500 Subject: [PATCH 24/90] 3.0.5845 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 68d67c0632..5953093f90 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5844")] +[assembly: AssemblyVersion("3.0.5845")] From 478c82126593ca69890a9c086386fb7b92b0dbea Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 12:12:11 -0500 Subject: [PATCH 25/90] 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 9168829afc3ca74b444092d5a809baba5bcd75c7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 12:15:35 -0500 Subject: [PATCH 26/90] 3.0.5846 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 5953093f90..f92aeb9442 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5845")] +[assembly: AssemblyVersion("3.0.5846")] From 5636b53ed110b5db20de04641cca878937271d1f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 13:21:35 -0500 Subject: [PATCH 27/90] 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 4e9cb26761b9195153b5c646b57072572ea66342 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 14:06:45 -0500 Subject: [PATCH 28/90] 3.0.5847 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index f92aeb9442..76c8b56b24 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5846")] +[assembly: AssemblyVersion("3.0.5847")] From 5710ef6892ef352195f772c40adc2189973f1af1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Jan 2016 23:21:31 -0500 Subject: [PATCH 29/90] improve reaction to image stub failures Conflicts: MediaBrowser.Server.Implementations/Library/LibraryManager.cs --- .../Manager/ItemImageProvider.cs | 35 ++++++++-------- .../Library/LibraryManager.cs | 40 ++++++++++++++----- 2 files changed, 48 insertions(+), 27 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); - - await _providerManagerFactory().SaveImage(item, image.Path, _dynamicImageResourcePool, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); - - var newImage = item.GetImageInfo(image.Type, imageIndex); - - if (newImage != null) + foreach (var url in image.Path.Split('|')) { - newImage.IsPlaceholder = image.IsPlaceholder; + try + { + _logger.Debug("ConvertImageToLocal item {0} - image url: {1}", item.Id, url); + + await _providerManagerFactory().SaveImage(item, url, _dynamicImageResourcePool, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); + + var newImage = item.GetImageInfo(image.Type, imageIndex); + + 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 cbeb9ca7622b0e9092299ddba77fb8d9ff71e213 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Jan 2016 17:00:44 -0500 Subject: [PATCH 30/90] 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 9b422977fe7d87a39e3dd6a4ce240a6199465c0a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Jan 2016 17:09:54 -0500 Subject: [PATCH 31/90] 3.0.5848 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 76c8b56b24..6b4b254703 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5847")] +[assembly: AssemblyVersion("3.0.5848")] From 80a6360f77595043e0c1db11018ebde6bc512139 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Jan 2016 17:11:46 -0500 Subject: [PATCH 32/90] 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 b74d091833935779f76083c4098338858fd54602 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Jan 2016 23:12:47 -0500 Subject: [PATCH 33/90] 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 db8d8ff2892935e4085b1fa31888a1a50f2463b5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 00:52:40 -0500 Subject: [PATCH 34/90] 3.0.5849 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 6b4b254703..91e41c34b0 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5848")] +[assembly: AssemblyVersion("3.0.5849")] From 1f9023a8d7bebe10029cab2c73d1ed21f4ad6f47 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 11:38:52 -0500 Subject: [PATCH 35/90] update wdtv live profile --- MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs | 10 +++++----- MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs index 5bfd377263..98e780a257 100644 --- a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs +++ b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Dlna.Profiles Container = "avi", Type = DlnaProfileType.Video, VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1", - AudioCodec = "ac3,dca,mp2,mp3,pcm" + AudioCodec = "ac3,dca,mp2,mp3,pcm,dca" }, new DirectPlayProfile @@ -66,7 +66,7 @@ namespace MediaBrowser.Dlna.Profiles Container = "mpeg", Type = DlnaProfileType.Video, VideoCodec = "mpeg1video,mpeg2video", - AudioCodec = "ac3,dca,mp2,mp3,pcm" + AudioCodec = "ac3,dca,mp2,mp3,pcm,dca" }, new DirectPlayProfile @@ -74,7 +74,7 @@ namespace MediaBrowser.Dlna.Profiles Container = "mkv", Type = DlnaProfileType.Video, VideoCodec = "mpeg1video,mpeg2video,mpeg4,h264,vc1", - AudioCodec = "ac3,dca,aac,mp2,mp3,pcm" + AudioCodec = "ac3,dca,aac,mp2,mp3,pcm,dca" }, new DirectPlayProfile @@ -82,7 +82,7 @@ namespace MediaBrowser.Dlna.Profiles Container = "ts", Type = DlnaProfileType.Video, VideoCodec = "mpeg1video,mpeg2video,h264,vc1", - AudioCodec = "ac3,dca,mp2,mp3,aac" + AudioCodec = "ac3,dca,mp2,mp3,aac,dca" }, new DirectPlayProfile @@ -90,7 +90,7 @@ namespace MediaBrowser.Dlna.Profiles Container = "mp4,mov", Type = DlnaProfileType.Video, VideoCodec = "h264,mpeg4", - AudioCodec = "ac3,aac,mp2,mp3" + AudioCodec = "ac3,aac,mp2,mp3,dca" }, new DirectPlayProfile diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml index 10b642bba4..e17fc087bd 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml @@ -37,11 +37,11 @@ true - - - - - + + + + + From 4d04acb3215e041bf0bb5d353fd84b37bd0bf8d5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 13:18:06 -0500 Subject: [PATCH 36/90] update naming project --- .../MediaBrowser.Server.Implementations.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index b51c688b49..7761125d01 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -48,9 +48,9 @@ ..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll - + False - ..\packages\MediaBrowser.Naming.1.0.0.42\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll + ..\packages\MediaBrowser.Naming.1.0.0.43\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll From 80ea0f06f3f61c0f28c10cf062bcc48e6ef95a93 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 13:18:21 -0500 Subject: [PATCH 37/90] rework device concurrency --- .../Devices/DeviceRepository.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs index 43b1e693cc..9e4a45253d 100644 --- a/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs +++ b/MediaBrowser.Server.Implementations/Devices/DeviceRepository.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Server.Implementations.Devices private readonly ILogger _logger; private readonly IFileSystem _fileSystem; - private ConcurrentBag _devices; + private List _devices; public DeviceRepository(IApplicationPaths appPaths, IJsonSerializer json, ILogger logger, IFileSystem fileSystem) { @@ -93,17 +93,14 @@ namespace MediaBrowser.Server.Implementations.Devices public IEnumerable GetDevices() { - if (_devices == null) + lock (_syncLock) { - lock (_syncLock) + if (_devices == null) { - if (_devices == null) - { - _devices = new ConcurrentBag(LoadDevices()); - } + _devices = LoadDevices().ToList(); } + return _devices.ToList(); } - return _devices.ToList(); } private IEnumerable LoadDevices() From 6693c47bf65e8801de2ffc8f3948fdbbe6ff19c9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 13:18:35 -0500 Subject: [PATCH 38/90] update naming project --- MediaBrowser.Server.Implementations/packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 4b643fe219..8d7e77df0b 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -2,7 +2,7 @@ - + From fcd12c831478f0ca9715b786c999b60681b7e5dd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 13:18:54 -0500 Subject: [PATCH 39/90] add recording logging --- .../LiveTv/EmbyTV/EmbyTV.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 3d1d9e0bab..dff57adf3f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -22,6 +22,7 @@ using MediaBrowser.Server.Implementations.FileOrganization; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Threading; @@ -604,6 +605,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { await RecordStream(timer, recordingEndDate, cancellationTokenSource.Token).ConfigureAwait(false); } + else + { + _logger.Info("Skipping RecordStream because it's already in progress."); + } } catch (OperationCanceledException) { @@ -722,7 +727,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.AddOrUpdate(recording); - _logger.Info("Beginning recording."); + _logger.Info("Beginning recording. Will record for {0} minutes.", duration.TotalMinutes.ToString(CultureInfo.InvariantCulture)); httpRequestOptions.BufferContent = false; var durationToken = new CancellationTokenSource(duration); From fae18c57bc2177172ec6a4ffc24d4e1201e39a17 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 13:26:04 -0500 Subject: [PATCH 40/90] merge from dev --- MediaBrowser.Api/StartupWizardService.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 399c81ae88..69639a5f9f 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -66,8 +66,6 @@ namespace MediaBrowser.Api { _config.Configuration.IsStartupWizardCompleted = true; _config.Configuration.EnableLocalizedGuids = true; - _config.Configuration.MergeMetadataAndImagesByName = true; - _config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableLibraryMetadataSubFolder = true; _config.Configuration.EnableCustomPathSubFolders = true; _config.Configuration.DisableXmlSavers = true; From c81388689e03c40987b00dfd629150eb85494554 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 13:19:05 -0500 Subject: [PATCH 41/90] deprecate options Conflicts: MediaBrowser.Api/StartupWizardService.cs --- .../Configuration/ServerConfiguration.cs | 3 --- .../ServerConfigurationManager.cs | 27 ++----------------- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 7208ccb1d9..3aea370c8c 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -180,9 +180,6 @@ namespace MediaBrowser.Model.Configuration /// The dashboard source path. public string DashboardSourcePath { get; set; } - public bool MergeMetadataAndImagesByName { get; set; } - public bool EnableStandaloneMetadata { get; set; } - /// /// Gets or sets the image saving convention. /// diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index a7d3854e71..6b668da47b 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -35,7 +35,6 @@ namespace MediaBrowser.Server.Implementations.Configuration public ServerConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer, IFileSystem fileSystem) : base(applicationPaths, logManager, xmlSerializer, fileSystem) { - UpdateItemsByNamePath(); UpdateMetadataPath(); } @@ -73,7 +72,6 @@ namespace MediaBrowser.Server.Implementations.Configuration /// protected override void OnConfigurationUpdated() { - UpdateItemsByNamePath(); UpdateMetadataPath(); base.OnConfigurationUpdated(); @@ -86,19 +84,6 @@ namespace MediaBrowser.Server.Implementations.Configuration UpdateTranscodingTempPath(); } - /// - /// Updates the items by name path. - /// - private void UpdateItemsByNamePath() - { - if (!Configuration.MergeMetadataAndImagesByName) - { - ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ? - null : - Configuration.ItemsByNamePath; - } - } - /// /// Updates the metadata path. /// @@ -121,20 +106,12 @@ namespace MediaBrowser.Server.Implementations.Configuration ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath; - if (Configuration.MergeMetadataAndImagesByName) - { - ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath; - } + ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath; } private string GetInternalMetadataPath() { - if (Configuration.EnableStandaloneMetadata) - { - return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata"); - } - - return null; + return Path.Combine(ApplicationPaths.ProgramDataPath, "metadata"); } /// From c0d26560db1778b4f9fd26a784a1b8804ce2e501 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 14:06:02 -0500 Subject: [PATCH 42/90] fix pt-br with tvdb --- MediaBrowser.Providers/TV/TvdbSeriesProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index 313ca9074d..4a7ae57fb0 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -238,7 +238,7 @@ namespace MediaBrowser.Providers.TV throw new ArgumentNullException("seriesId"); } - var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage); + var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, NormalizeLanguage(preferredMetadataLanguage)); using (var zipStream = await _httpClient.Get(new HttpRequestOptions { @@ -268,7 +268,7 @@ namespace MediaBrowser.Providers.TV await SanitizeXmlFile(file).ConfigureAwait(false); } - var downloadLangaugeXmlFile = Path.Combine(seriesDataPath, preferredMetadataLanguage + ".xml"); + var downloadLangaugeXmlFile = Path.Combine(seriesDataPath, NormalizeLanguage(preferredMetadataLanguage) + ".xml"); var saveAsLanguageXmlFile = Path.Combine(seriesDataPath, saveAsMetadataLanguage + ".xml"); if (!string.Equals(downloadLangaugeXmlFile, saveAsLanguageXmlFile, StringComparison.OrdinalIgnoreCase)) From 42a629078d95c1278177af75292fbaf88e6471f1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 01:06:02 -0500 Subject: [PATCH 43/90] 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 69639a5f9f..554d63ac11 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -68,7 +68,6 @@ namespace MediaBrowser.Api _config.Configuration.EnableLocalizedGuids = 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 3aea370c8c..77bce5cbd3 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -216,7 +216,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 1ea2ec9bdc8fe7cca63b79b69434217627167963 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Jan 2016 14:55:33 -0500 Subject: [PATCH 44/90] support itunes episode naming --- .../MediaBrowser.Server.Implementations.csproj | 4 ++-- MediaBrowser.Server.Implementations/packages.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 7761125d01..c54ea42a55 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -48,9 +48,9 @@ ..\packages\Interfaces.IO.1.0.0.5\lib\portable-net45+sl4+wp71+win8+wpa81\Interfaces.IO.dll - + False - ..\packages\MediaBrowser.Naming.1.0.0.43\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll + ..\packages\MediaBrowser.Naming.1.0.0.44\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 8d7e77df0b..b7f5533ced 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -2,7 +2,7 @@ - + From 9a83394e5d09c8685841f2fe951f5d1b8d5e43b1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 01:06:45 -0500 Subject: [PATCH 45/90] disable wake timer --- .../Native/WindowsPowerManagement.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs index 3b05febafe..abfbab50c0 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs @@ -35,8 +35,8 @@ namespace MediaBrowser.ServerApplication.Native public void ScheduleWake(DateTime utcTime) { - Initialize(); - _bgWorker.RunWorkerAsync(utcTime.ToFileTime()); + //Initialize(); + //_bgWorker.RunWorkerAsync(utcTime.ToFileTime()); } private void Initialize() From 51cd5e90b0a926ea728f9b98e5b9f380948b5cce Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 01:07:01 -0500 Subject: [PATCH 46/90] restart timers on wake --- .../LiveTv/EmbyTV/EmbyTV.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index dff57adf3f..c27f607124 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -30,6 +30,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Power; +using Microsoft.Win32; namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { @@ -84,6 +85,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public void Start() { _timerProvider.RestartTimers(); + + SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; + + } + + void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) + { + if (e.Mode == PowerModes.Resume) + { + _timerProvider.RestartTimers(); + } } public event EventHandler DataSourceChanged; From 106a2f3e1a0bfee9e056ef22b94599c7b2a47530 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 01:31:31 -0500 Subject: [PATCH 47/90] add back MergeMetadataAndImagesByName Conflicts: MediaBrowser.Model/Configuration/ServerConfiguration.cs --- MediaBrowser.Api/StartupWizardService.cs | 1 + .../Configuration/ServerConfiguration.cs | 2 ++ .../Configuration/ServerConfigurationManager.cs | 15 +++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 554d63ac11..b05a1bd209 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -71,6 +71,7 @@ namespace MediaBrowser.Api _config.Configuration.DisableStartupScan = true; _config.Configuration.EnableUserViews = true; _config.Configuration.EnableDateLastRefresh = true; + _config.Configuration.MergeMetadataAndImagesByName = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 77bce5cbd3..91e20c3e09 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -180,6 +180,8 @@ namespace MediaBrowser.Model.Configuration /// The dashboard source path. public string DashboardSourcePath { get; set; } + public bool MergeMetadataAndImagesByName { get; set; } + /// /// Gets or sets the image saving convention. /// diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index 6b668da47b..d7df37332a 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -35,6 +35,7 @@ namespace MediaBrowser.Server.Implementations.Configuration public ServerConfigurationManager(IApplicationPaths applicationPaths, ILogManager logManager, IXmlSerializer xmlSerializer, IFileSystem fileSystem) : base(applicationPaths, logManager, xmlSerializer, fileSystem) { + UpdateItemsByNamePath(); UpdateMetadataPath(); } @@ -72,6 +73,7 @@ namespace MediaBrowser.Server.Implementations.Configuration /// protected override void OnConfigurationUpdated() { + UpdateItemsByNamePath(); UpdateMetadataPath(); base.OnConfigurationUpdated(); @@ -84,6 +86,19 @@ namespace MediaBrowser.Server.Implementations.Configuration UpdateTranscodingTempPath(); } + /// + /// Updates the items by name path. + /// + private void UpdateItemsByNamePath() + { + if (!Configuration.MergeMetadataAndImagesByName) + { + ((ServerApplicationPaths)ApplicationPaths).ItemsByNamePath = string.IsNullOrEmpty(Configuration.ItemsByNamePath) ? + null : + Configuration.ItemsByNamePath; + } + } + /// /// Updates the metadata path. /// From 2b8cf9b89d9eeeff0affe9ca0c2501e3a0984ca4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 11:58:08 -0500 Subject: [PATCH 48/90] add logging --- MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index c27f607124..250b5655f1 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -92,6 +92,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) { + _logger.Info("Power mode changed to {0}", e.Mode); + if (e.Mode == PowerModes.Resume) { _timerProvider.RestartTimers(); From c167f792383e9f2cff320efc840c42efe7fbbdbb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 12:34:23 -0500 Subject: [PATCH 49/90] update photo resolver to exclude generated images --- .../Library/Resolvers/PhotoResolver.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs index 407aac53d6..8beb03b71a 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -51,8 +51,17 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers { var filename = Path.GetFileNameWithoutExtension(path) ?? string.Empty; - return !IgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase) - && imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase); + if (IgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase)) + { + return false; + } + + if (IgnoreFiles.Any(i => filename.IndexOf("-" + i, StringComparison.OrdinalIgnoreCase) != -1)) + { + return false; + } + + return imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase); } } From ddf7fdbcef9c987092a7591848801f28aa5baedd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 13:35:37 -0500 Subject: [PATCH 50/90] fixes #1421 - LogRequest() in WebSocketSharpListener broken for Reports --- .../HttpServer/HttpListenerHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 8d8d7f6f75..0381167032 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -290,7 +290,7 @@ namespace MediaBrowser.Server.Implementations.HttpServer var operationName = httpReq.OperationName; var localPath = url.LocalPath; - var urlString = url.ToString(); + var urlString = url.OriginalString; var enableLog = EnableLogging(urlString); if (enableLog) From 2bd0464322331b668be97a77a90ef486914d95ac Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 13:42:19 -0500 Subject: [PATCH 51/90] fixes #1410 - Entire server locks up, when files are locked during.. things.. --- .../Configuration/ServerConfiguration.cs | 4 ++-- .../IO/LibraryMonitor.cs | 12 +++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 91e20c3e09..152bdd993b 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -164,7 +164,7 @@ namespace MediaBrowser.Model.Configuration /// different directories and files. /// /// The file watcher delay. - public int RealtimeLibraryMonitorDelay { get; set; } + public int LibraryMonitorDelay { get; set; } /// /// Gets or sets a value indicating whether [enable dashboard response caching]. @@ -255,7 +255,7 @@ namespace MediaBrowser.Model.Configuration MinResumeDurationSeconds = 300; EnableLibraryMonitor = AutoOnOff.Auto; - RealtimeLibraryMonitorDelay = 40; + LibraryMonitorDelay = 60; EnableInternetProviders = true; FindInternetTrailers = true; diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 85ea8ec57b..184b72d8f8 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -471,11 +471,11 @@ namespace MediaBrowser.Server.Implementations.IO { if (_updateTimer == null) { - _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeLibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); + _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); } else { - _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeLibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); + _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); } } } @@ -513,12 +513,18 @@ namespace MediaBrowser.Server.Implementations.IO private bool IsFileLocked(string path) { + if (Environment.OSVersion.Platform != PlatformID.Win32NT) + { + // Causing lockups on linux + return false; + } + try { var data = _fileSystem.GetFileSystemInfo(path); if (!data.Exists - || data.Attributes.HasFlag(FileAttributes.Directory) + || data.IsDirectory // Opening a writable stream will fail with readonly files || data.Attributes.HasFlag(FileAttributes.ReadOnly)) From f0adb2e89173ae0a9b041dfaa45edca119bc7f4a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 14:28:12 -0500 Subject: [PATCH 52/90] restore channel view setting --- MediaBrowser.Model/Configuration/UserConfiguration.cs | 1 + .../Library/UserViewManager.cs | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index ab3a861a36..8199489096 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -48,6 +48,7 @@ namespace MediaBrowser.Model.Configuration public string[] PlainFolderViews { get; set; } public bool HidePlayedInLatest { get; set; } + public bool DisplayChannelsInline { get; set; } /// /// Initializes a new instance of the class. diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 30a720a62e..0df4742bd9 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -163,7 +163,14 @@ namespace MediaBrowser.Server.Implementations.Library var channels = channelResult.Items; - list.AddRange(channels); + if (user.Configuration.DisplayChannelsInline && channels.Length > 0) + { + list.Add(await _channelManager.GetInternalChannelFolder(cancellationToken).ConfigureAwait(false)); + } + else + { + list.AddRange(channels); + } if (_liveTvManager.GetEnabledUsers().Select(i => i.Id.ToString("N")).Contains(query.UserId)) { From 9dd55c15c0dd62568e0410127f5d91c1d13d3b5e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 14:28:33 -0500 Subject: [PATCH 53/90] fix changing added value --- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 10 +++++++--- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 6 ++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index c5184ec3d1..0fbf2fd111 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -215,7 +215,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val)) { DateTime added; - if (DateTime.TryParse(val, out added)) + if (DateTime.TryParseExact(val, BaseNfoSaver.DateAddedFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out added)) + { + item.EndDate = added.ToUniversalTime(); + } + else if (DateTime.TryParse(val, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out added)) { item.DateCreated = added.ToUniversalTime(); } @@ -976,11 +980,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers if (!string.IsNullOrWhiteSpace(val) && !string.IsNullOrWhiteSpace(userDataUserId)) { DateTime parsedValue; - if (DateTime.TryParseExact(val, "yyyy-MM-dd HH:mm:ss", _usCulture, DateTimeStyles.None, out parsedValue)) + if (DateTime.TryParseExact(val, "yyyy-MM-dd HH:mm:ss", _usCulture, DateTimeStyles.AssumeLocal, out parsedValue)) { var userData = GetOrAdd(itemResult, userDataUserId); - userData.LastPlayedDate = parsedValue; + userData.LastPlayedDate = parsedValue.ToUniversalTime(); } } break; diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 0da53f575c..c114f9dd99 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -416,6 +416,8 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteEndElement(); } + public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; + /// /// Adds the common nodes. /// @@ -472,7 +474,7 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteElementString("type", item.DisplayMediaType); } - writer.WriteElementString("dateadded", item.DateCreated.ToString("yyyy-MM-dd HH:mm:ss")); + writer.WriteElementString("dateadded", item.DateCreated.ToLocalTime().ToString(DateAddedFormat)); writer.WriteElementString("title", item.Name ?? string.Empty); writer.WriteElementString("originaltitle", item.Name ?? string.Empty); @@ -949,7 +951,7 @@ namespace MediaBrowser.XbmcMetadata.Savers if (userdata.LastPlayedDate.HasValue) { - writer.WriteElementString("lastplayed", userdata.LastPlayedDate.Value.ToString("yyyy-MM-dd HH:mm:ss").ToLower()); + writer.WriteElementString("lastplayed", userdata.LastPlayedDate.Value.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss").ToLower()); } writer.WriteStartElement("resume"); From 8c7296b560af1f926115ac23bad519b8d6fc5d7f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Jan 2016 14:39:10 -0500 Subject: [PATCH 54/90] update translations --- .../Localization/Core/ca.json | 22 +++++++++---------- .../Localization/Core/nl.json | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ca.json b/MediaBrowser.Server.Implementations/Localization/Core/ca.json index 40dfcd2c38..83d72030f0 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/ca.json @@ -1,6 +1,6 @@ { - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", + "AppDeviceValues": "App: {0}, Dispositiu: {1}", + "UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}", "FolderTypeMixed": "Mixed content", "FolderTypeMovies": "Pel\u00b7l\u00edcules", "FolderTypeMusic": "M\u00fasica", @@ -12,10 +12,10 @@ "FolderTypeBooks": "Llibres", "FolderTypeTvShows": "TV", "FolderTypeInherit": "Heretat", - "HeaderCastCrew": "Repartiment i equip", + "HeaderCastCrew": "Repartiment i Equip", "HeaderPeople": "People", "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", + "LabelChapterName": "Cap\u00edtol {0}", "NameSeasonNumber": "Temporada {0}", "LabelExit": "Sortir", "LabelVisitCommunity": "Visita la comunitat", @@ -77,7 +77,7 @@ "ViewTypeMovieMovies": "Pel\u00b7l\u00edcules", "ViewTypeMovieCollections": "Col\u00b7leccions", "ViewTypeMovieFavorites": "Preferides", - "ViewTypeMovieGenres": "Genres", + "ViewTypeMovieGenres": "G\u00e8neres", "ViewTypeMusicLatest": "Novetats", "ViewTypeMusicPlaylists": "Llistes de reproducci\u00f3", "ViewTypeMusicAlbums": "\u00c0lbums", @@ -89,7 +89,7 @@ "ViewTypeMusicFavoriteArtists": "Artistes Preferits", "ViewTypeMusicFavoriteSongs": "Can\u00e7ons Preferides", "ViewTypeFolders": "Directoris", - "ViewTypeLiveTvRecordingGroups": "Recordings", + "ViewTypeLiveTvRecordingGroups": "Enregistraments", "ViewTypeLiveTvChannels": "Canals", "ScheduledTaskFailedWithName": "{0} failed", "LabelRunningTimeValue": "Running time: {0}", @@ -103,7 +103,7 @@ "LabelIpAddressValue": "Ip address: {0}", "DeviceOnlineWithName": "{0} is connected", "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", + "ProviderValue": "Prove\u00efdor: {0}", "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", "UserCreatedWithName": "User {0} has been created", @@ -113,12 +113,12 @@ "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", "MessageApplicationUpdated": "Emby Server has been updated", "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", + "AuthenticationSucceededWithUserName": "{0} autenticat correctament", "DeviceOfflineWithName": "{0} has disconnected", "UserLockedOutWithName": "User {0} has been locked out", "UserOfflineFromDevice": "{0} has disconnected from {1}", - "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", + "UserStartedPlayingItemWithValues": "{0} ha comen\u00e7at a reproduir {1}", + "UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "HeaderUnidentified": "Unidentified", "HeaderImagePrimary": "Primary", @@ -164,7 +164,7 @@ "HeaderTracks": "Tracks", "HeaderMusicArtist": "M\u00fasic", "HeaderLocked": "Locked", - "HeaderStudios": "Studios", + "HeaderStudios": "Estudis", "HeaderActor": "Actors", "HeaderComposer": "Compositors", "HeaderDirector": "Directors", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nl.json b/MediaBrowser.Server.Implementations/Localization/Core/nl.json index b32ebefc35..fd0c586a2e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/nl.json @@ -63,7 +63,7 @@ "ViewTypeLatestGames": "Nieuwste games", "ViewTypeRecentlyPlayedGames": "Recent gespeelt", "ViewTypeGameFavorites": "Favorieten", - "ViewTypeGameSystems": "Gam systemen", + "ViewTypeGameSystems": "Game systemen", "ViewTypeGameGenres": "Genres", "ViewTypeTvResume": "Hervatten", "ViewTypeTvNextUp": "Volgende", @@ -147,7 +147,7 @@ "HeaderCommunityRating": "Gemeenschap cijfer", "HeaderTrailers": "Trailers", "HeaderSpecials": "Specials", - "HeaderGameSystems": "Spel systemen", + "HeaderGameSystems": "Game systemen", "HeaderPlayers": "Spelers:", "HeaderAlbumArtists": "Album artiesten", "HeaderAlbums": "Albums", From 8a50392ba73605fcd5a22c299352845bae0b7700 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 01:38:35 -0500 Subject: [PATCH 55/90] reduce server pinging --- .../ApplicationHost.cs | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 1db019d8d2..2d625f810e 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -210,7 +210,6 @@ namespace MediaBrowser.Server.Startup.Common private readonly string _releaseAssetFilename; internal INativeApp NativeApp { get; set; } - private Timer _ipAddressCacheTimer; /// /// Initializes a new instance of the class. @@ -234,8 +233,6 @@ namespace MediaBrowser.Server.Startup.Common NativeApp = nativeApp; SetBaseExceptionMessage(); - - _ipAddressCacheTimer = new Timer(OnCacheClearTimerFired, null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3)); } private Version _version; @@ -534,7 +531,7 @@ namespace MediaBrowser.Server.Startup.Common RegisterSingleInstance(EncodingManager); RegisterSingleInstance(NativeApp.GetPowerManagement()); - + var sharingRepo = new SharingRepository(LogManager, ApplicationPaths); await sharingRepo.Initialize().ConfigureAwait(false); RegisterSingleInstance(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this)); @@ -972,10 +969,10 @@ namespace MediaBrowser.Server.Startup.Common { get { - if (!ServerConfigurationManager.Configuration.EnableAutoUpdate) - { - return false; - } + if (!ServerConfigurationManager.Configuration.EnableAutoUpdate) + { + return false; + } #if DEBUG return false; #endif @@ -1159,7 +1156,12 @@ namespace MediaBrowser.Server.Startup.Common } private readonly ConcurrentDictionary _validAddressResults = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); + private DateTime _lastAddressCacheClear; private bool IsIpAddressValid(IPAddress address) + { + return IsIpAddressValidInternal(address).Result; + } + private async Task IsIpAddressValidInternal(IPAddress address) { if (IPAddress.IsLoopback(address)) { @@ -1169,6 +1171,12 @@ namespace MediaBrowser.Server.Startup.Common var apiUrl = GetLocalApiUrl(address.ToString()); apiUrl += "/system/ping"; + if ((DateTime.UtcNow - _lastAddressCacheClear).TotalMinutes >= 5) + { + _lastAddressCacheClear = DateTime.UtcNow; + _validAddressResults.Clear(); + } + bool cachedResult; if (_validAddressResults.TryGetValue(apiUrl, out cachedResult)) { @@ -1177,14 +1185,15 @@ namespace MediaBrowser.Server.Startup.Common try { - using (var response = HttpClient.SendAsync(new HttpRequestOptions + using (var response = await HttpClient.SendAsync(new HttpRequestOptions { Url = apiUrl, LogErrorResponseBody = false, LogErrors = false, - LogRequest = false + LogRequest = false, + TimeoutMs = 30000 - }, "POST").Result) + }, "POST").ConfigureAwait(false)) { using (var reader = new StreamReader(response.Content)) { @@ -1192,25 +1201,20 @@ namespace MediaBrowser.Server.Startup.Common var valid = string.Equals(Name, result, StringComparison.OrdinalIgnoreCase); _validAddressResults.AddOrUpdate(apiUrl, valid, (k, v) => valid); - Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid); + //Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, valid); return valid; } } } catch { - Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false); + //Logger.Debug("Ping test result to {0}. Success: {1}", apiUrl, false); _validAddressResults.AddOrUpdate(apiUrl, false, (k, v) => false); return false; } } - private void OnCacheClearTimerFired(object state) - { - _validAddressResults.Clear(); - } - public string FriendlyName { get From af599ed5d74c886d390ea7a79123f0443543d0c7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 01:39:02 -0500 Subject: [PATCH 56/90] add logging --- MediaBrowser.Api/UserLibrary/PlaystateService.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index 7002a37035..08c6b0ba47 100644 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs @@ -370,6 +370,8 @@ namespace MediaBrowser.Api.UserLibrary public void Post(ReportPlaybackStopped request) { + Logger.Debug("ReportPlaybackStopped PlaySessionId: {0}", request.PlaySessionId ?? string.Empty); + if (!string.IsNullOrWhiteSpace(request.PlaySessionId)) { ApiEntryPoint.Instance.KillTranscodingJobs(AuthorizationContext.GetAuthorizationInfo(Request).DeviceId, request.PlaySessionId, s => true); From 2d97423a404228f742976dc6abe4a43746bc23fb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 13:29:41 -0500 Subject: [PATCH 57/90] don't organize episode if series has no provider ids --- .../FileOrganization/EpisodeFileOrganizer.cs | 211 +++++++++--------- 1 file changed, 110 insertions(+), 101 deletions(-) diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index 26392f5a95..ae40ed6b5a 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -76,50 +76,50 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { var seasonNumber = episodeInfo.SeasonNumber; - result.ExtractedSeasonNumber = seasonNumber; + result.ExtractedSeasonNumber = seasonNumber; - // Passing in true will include a few extra regex's - var episodeNumber = episodeInfo.EpisodeNumber; + // Passing in true will include a few extra regex's + var episodeNumber = episodeInfo.EpisodeNumber; - result.ExtractedEpisodeNumber = episodeNumber; + result.ExtractedEpisodeNumber = episodeNumber; - var premiereDate = episodeInfo.IsByDate ? - new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) : - (DateTime?)null; + var premiereDate = episodeInfo.IsByDate ? + new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value) : + (DateTime?)null; - if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue)) - { - if (episodeInfo.IsByDate) - { - _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value); - } - else - { - _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber); - } + if (episodeInfo.IsByDate || (seasonNumber.HasValue && episodeNumber.HasValue)) + { + if (episodeInfo.IsByDate) + { + _logger.Debug("Extracted information from {0}. Series name {1}, Date {2}", path, seriesName, premiereDate.Value); + } + else + { + _logger.Debug("Extracted information from {0}. Series name {1}, Season {2}, Episode {3}", path, seriesName, seasonNumber, episodeNumber); + } - var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber; + var endingEpisodeNumber = episodeInfo.EndingEpsiodeNumber; - result.ExtractedEndingEpisodeNumber = endingEpisodeNumber; + result.ExtractedEndingEpisodeNumber = endingEpisodeNumber; - await OrganizeEpisode(path, - seriesName, - seasonNumber, - episodeNumber, - endingEpisodeNumber, - premiereDate, - options, - overwriteExisting, - result, - cancellationToken).ConfigureAwait(false); - } - else - { - var msg = string.Format("Unable to determine episode number from {0}", path); - result.Status = FileSortingStatus.Failure; - result.StatusMessage = msg; - _logger.Warn(msg); - } + await OrganizeEpisode(path, + seriesName, + seasonNumber, + episodeNumber, + endingEpisodeNumber, + premiereDate, + options, + overwriteExisting, + result, + cancellationToken).ConfigureAwait(false); + } + else + { + var msg = string.Format("Unable to determine episode number from {0}", path); + result.Status = FileSortingStatus.Failure; + result.StatusMessage = msg; + _logger.Warn(msg); + } } else { @@ -151,32 +151,32 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId)); - await OrganizeEpisode(result.OriginalPath, - series, - request.SeasonNumber, - request.EpisodeNumber, - request.EndingEpisodeNumber, - null, - options, - true, - result, - cancellationToken).ConfigureAwait(false); + await OrganizeEpisode(result.OriginalPath, + series, + request.SeasonNumber, + request.EpisodeNumber, + request.EndingEpisodeNumber, + null, + options, + true, + result, + cancellationToken).ConfigureAwait(false); await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false); return result; } - private Task OrganizeEpisode(string sourcePath, - string seriesName, - int? seasonNumber, - int? episodeNumber, - int? endingEpiosdeNumber, - DateTime? premiereDate, - TvFileOrganizationOptions options, - bool overwriteExisting, - FileOrganizationResult result, - CancellationToken cancellationToken) + private Task OrganizeEpisode(string sourcePath, + string seriesName, + int? seasonNumber, + int? episodeNumber, + int? endingEpiosdeNumber, + DateTime? premiereDate, + TvFileOrganizationOptions options, + bool overwriteExisting, + FileOrganizationResult result, + CancellationToken cancellationToken) { var series = GetMatchingSeries(seriesName, result); @@ -189,33 +189,42 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return Task.FromResult(true); } - return OrganizeEpisode(sourcePath, - series, - seasonNumber, - episodeNumber, - endingEpiosdeNumber, - premiereDate, - options, - overwriteExisting, - result, - cancellationToken); + if (!series.ProviderIds.Any()) + { + var msg = string.Format("Series has not yet been identified: {0}. If you just added the series, please run a library scan or use the identify feature to identify it.", seriesName); + result.Status = FileSortingStatus.Failure; + result.StatusMessage = msg; + _logger.Warn(msg); + return Task.FromResult(true); + } + + return OrganizeEpisode(sourcePath, + series, + seasonNumber, + episodeNumber, + endingEpiosdeNumber, + premiereDate, + options, + overwriteExisting, + result, + cancellationToken); } - private async Task OrganizeEpisode(string sourcePath, - Series series, - int? seasonNumber, - int? episodeNumber, - int? endingEpiosdeNumber, - DateTime? premiereDate, - TvFileOrganizationOptions options, - bool overwriteExisting, - FileOrganizationResult result, - CancellationToken cancellationToken) + private async Task OrganizeEpisode(string sourcePath, + Series series, + int? seasonNumber, + int? episodeNumber, + int? endingEpiosdeNumber, + DateTime? premiereDate, + TvFileOrganizationOptions options, + bool overwriteExisting, + FileOrganizationResult result, + CancellationToken cancellationToken) { _logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path); // Proceed to sort the file - var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options, cancellationToken).ConfigureAwait(false); + var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, premiereDate, options, cancellationToken).ConfigureAwait(false); if (string.IsNullOrEmpty(newPath)) { @@ -324,17 +333,17 @@ namespace MediaBrowser.Server.Implementations.FileOrganization } } - private List GetOtherDuplicatePaths(string targetPath, - Series series, - int? seasonNumber, - int? episodeNumber, - int? endingEpisodeNumber) + private List GetOtherDuplicatePaths(string targetPath, + Series series, + int? seasonNumber, + int? episodeNumber, + int? endingEpisodeNumber) { - // TODO: Support date-naming? - if (!seasonNumber.HasValue || episodeNumber.HasValue) - { - return new List (); - } + // TODO: Support date-naming? + if (!seasonNumber.HasValue || episodeNumber.HasValue) + { + return new List(); + } var episodePaths = series.GetRecursiveChildren() .OfType() @@ -464,14 +473,14 @@ namespace MediaBrowser.Server.Implementations.FileOrganization /// The ending episode number. /// The options. /// System.String. - private async Task GetNewPath(string sourcePath, - Series series, - int? seasonNumber, - int? episodeNumber, - int? endingEpisodeNumber, - DateTime? premiereDate, - TvFileOrganizationOptions options, - CancellationToken cancellationToken) + private async Task GetNewPath(string sourcePath, + Series series, + int? seasonNumber, + int? episodeNumber, + int? endingEpisodeNumber, + DateTime? premiereDate, + TvFileOrganizationOptions options, + CancellationToken cancellationToken) { var episodeInfo = new EpisodeInfo { @@ -481,7 +490,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization MetadataLanguage = series.GetPreferredMetadataLanguage(), ParentIndexNumber = seasonNumber, SeriesProviderIds = series.ProviderIds, - PremiereDate = premiereDate + PremiereDate = premiereDate }; var searchResults = await _providerManager.GetRemoteSearchResults(new RemoteSearchQuery @@ -491,7 +500,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization }, cancellationToken).ConfigureAwait(false); var episode = searchResults.FirstOrDefault(); - + string episodeName = string.Empty; if (episode == null) @@ -503,10 +512,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization else { episodeName = episode.Name; - } + } - seasonNumber = seasonNumber ?? episode.ParentIndexNumber; - episodeNumber = episodeNumber ?? episode.IndexNumber; + seasonNumber = seasonNumber ?? episode.ParentIndexNumber; + episodeNumber = episodeNumber ?? episode.IndexNumber; var newPath = GetSeasonFolderPath(series, seasonNumber.Value, options); From 258b07a4164d9f3f3a2385f3f2a8cdaf5d857f63 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 13:38:40 -0500 Subject: [PATCH 58/90] handle empty person name --- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 0fbf2fd111..40b974ee77 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -631,7 +631,10 @@ namespace MediaBrowser.XbmcMetadata.Parsers { var person = GetPersonFromXmlNode(subtree); - itemResult.AddPerson(person); + if (!string.IsNullOrWhiteSpace(person.Name)) + { + itemResult.AddPerson(person); + } } break; } From 9d6f1a8b6151c2bfcb43ca0b358bab087044de83 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 14:10:56 -0500 Subject: [PATCH 59/90] update recording logging --- .../LiveTv/EmbyTV/TimerManager.cs | 9 +++++++-- .../Native/WindowsPowerManagement.cs | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index ca20379b66..94381cdac1 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -5,6 +5,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; using System.Collections.Concurrent; +using System.Globalization; using System.Linq; using System.Threading; using CommonIO; @@ -100,7 +101,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private void ScheduleWake(TimerInfo info) { var startDate = RecordingHelper.GetStartTime(info).AddMinutes(-5); - _logger.Info("Scheduling system wake timer at {0} (UTC)", startDate); try { @@ -123,9 +123,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV var timer = new Timer(TimerCallback, item.Id, length, TimeSpan.Zero); - if (!_timers.TryAdd(item.Id, timer)) + if (_timers.TryAdd(item.Id, timer)) + { + _logger.Warn("Creating recording timer for {0}, {1}. Timer will fire in {2} minutes", item.Id, item.Name, length.TotalMinutes.ToString(CultureInfo.InvariantCulture)); + } + else { timer.Dispose(); + _logger.Warn("Timer already exists for item {0}", item.Id); } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs index abfbab50c0..866272639f 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsPowerManagement.cs @@ -37,6 +37,7 @@ namespace MediaBrowser.ServerApplication.Native { //Initialize(); //_bgWorker.RunWorkerAsync(utcTime.ToFileTime()); + throw new NotImplementedException(); } private void Initialize() From f08084920ca4528dac50fcefb7004ebec80b6bd5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 15:13:01 -0500 Subject: [PATCH 60/90] 3.0.5850 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 91e41c34b0..ba3eaa378d 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5849")] +[assembly: AssemblyVersion("3.0.5850")] From 5763ce5a425aa2216ec4cb7f1787a26cd6d5dd19 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 20:15:59 -0500 Subject: [PATCH 61/90] catch BDInfo errors --- .../MediaInfo/FFProbeVideoInfo.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index efa6ff0cf4..8094aa58da 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -213,7 +213,7 @@ namespace MediaBrowser.Providers.MediaInfo } var chapters = mediaInfo.Chapters ?? new List(); - if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay)) + if (blurayInfo != null) { FetchBdInfo(video, chapters, mediaStreams, blurayInfo); } @@ -360,7 +360,15 @@ namespace MediaBrowser.Providers.MediaInfo /// VideoStream. private BlurayDiscInfo GetBDInfo(string path) { - return _blurayExaminer.GetDiscInfo(path); + try + { + return _blurayExaminer.GetDiscInfo(path); + } + catch (Exception ex) + { + _logger.ErrorException("Error getting BDInfo", ex); + return null; + } } private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options) @@ -628,7 +636,7 @@ namespace MediaBrowser.Providers.MediaInfo FetchFromDvdLib(item, mount); } - if (item.VideoType == VideoType.BluRay || (item.IsoType.HasValue && item.IsoType.Value == IsoType.BluRay)) + if (blurayDiscInfo != null) { item.PlayableStreamFileNames = blurayDiscInfo.Files.ToList(); } From a72c26d891a589b4d7005a21a38c4c0cf0137534 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 21:27:19 -0500 Subject: [PATCH 62/90] 3.0.5851 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ba3eaa378d..50a0ae7e9c 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5850")] +[assembly: AssemblyVersion("3.0.5851")] From 74d85e8b193d89378d4c2a9ccf9fbf6f6668964e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 22:43:20 -0500 Subject: [PATCH 63/90] update recording logging --- .../LiveTv/EmbyTV/TimerManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 94381cdac1..5d462f1069 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV if (_timers.TryAdd(item.Id, timer)) { - _logger.Warn("Creating recording timer for {0}, {1}. Timer will fire in {2} minutes", item.Id, item.Name, length.TotalMinutes.ToString(CultureInfo.InvariantCulture)); + _logger.Info("Creating recording timer for {0}, {1}. Timer will fire in {2} minutes", item.Id, item.Name, length.TotalMinutes.ToString(CultureInfo.InvariantCulture)); } else { From 83d96f9bdad194172cfa2f943cf433ea0e68c355 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 22:45:29 -0500 Subject: [PATCH 64/90] update network cache Conflicts: MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs --- .../Networking/BaseNetworkManager.cs | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index bc3dc360f7..ff11c889a6 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -6,7 +6,6 @@ using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; -using System.Threading; using MoreLinq; namespace MediaBrowser.Common.Implementations.Networking @@ -14,22 +13,11 @@ namespace MediaBrowser.Common.Implementations.Networking public abstract class BaseNetworkManager { protected ILogger Logger { get; private set; } - private Timer _clearCacheTimer; + private DateTime _lastRefresh; protected BaseNetworkManager(ILogger logger) { Logger = logger; - - // Can't use network change events due to a crash in Linux - _clearCacheTimer = new Timer(ClearCacheTimerCallback, null, TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); - } - - private void ClearCacheTimerCallback(object state) - { - lock (_localIpAddressSyncLock) - { - _localIpAddresses = null; - } } private volatile List _localIpAddresses; @@ -41,15 +29,21 @@ namespace MediaBrowser.Common.Implementations.Networking /// IPAddress. public IEnumerable GetLocalIpAddresses() { - if (_localIpAddresses == null) + const int cacheMinutes = 3; + var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; + + if (_localIpAddresses == null || forceRefresh) { lock (_localIpAddressSyncLock) { - if (_localIpAddresses == null) + forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; + + if (_localIpAddresses == null || forceRefresh) { var addresses = GetLocalIpAddressesInternal().ToList(); _localIpAddresses = addresses; + _lastRefresh = DateTime.UtcNow; return addresses; } From 51899f1880ebdd7ae05fdfe501476cdf68f713f2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 21:59:00 -0500 Subject: [PATCH 65/90] fixes #1218 - Dlna server doesn't work after resuming to sleep. --- MediaBrowser.Dlna/Ssdp/SsdpHandler.cs | 134 ++++---------------------- 1 file changed, 17 insertions(+), 117 deletions(-) diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 32c369a8ff..f800a12c1f 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -33,12 +33,8 @@ namespace MediaBrowser.Dlna.Ssdp private readonly IPAddress _ssdpIp = IPAddress.Parse(SSDPAddr); private readonly IPEndPoint _ssdpEndp = new IPEndPoint(IPAddress.Parse(SSDPAddr), SSDPPort); - private Timer _queueTimer; private Timer _notificationTimer; - private readonly AutoResetEvent _datagramPosted = new AutoResetEvent(false); - private readonly ConcurrentQueue _messageQueue = new ConcurrentQueue(); - private bool _isDisposed; private readonly ConcurrentDictionary> _devices = new ConcurrentDictionary>(); @@ -121,9 +117,13 @@ namespace MediaBrowser.Dlna.Ssdp public void Start() { - RestartSocketListener(); + DisposeSocket(); + StopAliveNotifier(); + RestartSocketListener(); ReloadAliveNotifier(); + + SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; } @@ -131,7 +131,7 @@ namespace MediaBrowser.Dlna.Ssdp { if (e.Mode == PowerModes.Resume) { - NotifyAll(); + Start(); } } @@ -154,7 +154,7 @@ namespace MediaBrowser.Dlna.Ssdp SendDatagram("M-SEARCH * HTTP/1.1", values, _ssdpEndp, localIp, true, 2); } - public void SendDatagram(string header, + public async void SendDatagram(string header, Dictionary values, EndPoint endpoint, EndPoint localAddress, @@ -162,28 +162,18 @@ namespace MediaBrowser.Dlna.Ssdp int sendCount) { var msg = new SsdpMessageBuilder().BuildMessage(header, values); - var queued = false; var enableDebugLogging = _config.GetDlnaConfiguration().EnableDebugLogging; for (var i = 0; i < sendCount; i++) { + if (i > 0) + { + await Task.Delay(500).ConfigureAwait(false); + } + var dgram = new Datagram(endpoint, localAddress, _logger, msg, isBroadcast, enableDebugLogging); - - if (_messageQueue.Count == 0) - { - dgram.Send(); - } - else - { - _messageQueue.Enqueue(dgram); - queued = true; - } - } - - if (queued) - { - StartQueueTimer(); + dgram.Send(); } } @@ -254,47 +244,10 @@ namespace MediaBrowser.Dlna.Ssdp } } - private readonly object _queueTimerSyncLock = new object(); - private void StartQueueTimer() - { - lock (_queueTimerSyncLock) - { - if (_queueTimer == null) - { - _queueTimer = new Timer(QueueTimerCallback, null, 500, Timeout.Infinite); - } - else - { - _queueTimer.Change(500, Timeout.Infinite); - } - } - } - - private void QueueTimerCallback(object state) - { - Datagram msg; - while (_messageQueue.TryDequeue(out msg)) - { - msg.Send(); - } - - _datagramPosted.Set(); - - if (_messageQueue.Count > 0) - { - StartQueueTimer(); - } - else - { - DisposeQueueTimer(); - } - } - private void RestartSocketListener() { if (_isDisposed) { - StopSocketRetryTimer(); return; } @@ -304,8 +257,6 @@ namespace MediaBrowser.Dlna.Ssdp _logger.Info("MultiCast socket created"); - StopSocketRetryTimer(); - Receive(); } catch (Exception ex) @@ -315,31 +266,6 @@ namespace MediaBrowser.Dlna.Ssdp } } - private Timer _socketRetryTimer; - private readonly object _socketRetryLock = new object(); - private void StartSocketRetryTimer() - { - lock (_socketRetryLock) - { - if (_socketRetryTimer == null) - { - _socketRetryTimer = new Timer(s => RestartSocketListener(), null, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)); - } - } - } - - private void StopSocketRetryTimer() - { - lock (_socketRetryLock) - { - if (_socketRetryTimer != null) - { - _socketRetryTimer.Dispose(); - _socketRetryTimer = null; - } - } - } - private void Receive() { try @@ -448,16 +374,9 @@ namespace MediaBrowser.Dlna.Ssdp SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; _isDisposed = true; - while (_messageQueue.Count != 0) - { - _datagramPosted.WaitOne(); - } DisposeSocket(); - DisposeQueueTimer(); - DisposeNotificationTimer(); - - _datagramPosted.Dispose(); + StopAliveNotifier(); } private void DisposeSocket() @@ -470,18 +389,6 @@ namespace MediaBrowser.Dlna.Ssdp } } - private void DisposeQueueTimer() - { - lock (_queueTimerSyncLock) - { - if (_queueTimer != null) - { - _queueTimer.Dispose(); - _queueTimer = null; - } - } - } - private Socket CreateMulticastSocket() { var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); @@ -534,14 +441,7 @@ namespace MediaBrowser.Dlna.Ssdp public void RegisterNotification(Guid uuid, Uri descriptionUri, IPAddress address, IEnumerable services) { - List list; - lock (_devices) - { - if (!_devices.TryGetValue(uuid, out list)) - { - _devices.TryAdd(uuid, list = new List()); - } - } + var list = _devices.GetOrAdd(uuid, new List()); list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); @@ -572,7 +472,7 @@ namespace MediaBrowser.Dlna.Ssdp if (!config.BlastAliveMessages) { - DisposeNotificationTimer(); + StopAliveNotifier(); return; } @@ -599,7 +499,7 @@ namespace MediaBrowser.Dlna.Ssdp } } - private void DisposeNotificationTimer() + private void StopAliveNotifier() { lock (_notificationTimerSyncLock) { From cfa8f6c6eca1b58a34a684c17a51b14fb4306f8b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 22:40:21 -0500 Subject: [PATCH 66/90] reduce use of timers throughout the system Conflicts: MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs --- .../Networking/BaseNetworkManager.cs | 13 +++- .../MediaBrowser.Common.csproj | 1 + .../Threading/PeriodicTimer.cs | 67 +++++++++++++++++++ .../People/MovieDbPersonProvider.cs | 18 ++--- .../Channels/ChannelManager.cs | 61 +---------------- .../Connect/ConnectEntryPoint.cs | 5 +- .../EntryPoints/ExternalPortForwarding.cs | 5 +- .../EntryPoints/UsageEntryPoint.cs | 16 ++--- 8 files changed, 99 insertions(+), 87 deletions(-) create mode 100644 MediaBrowser.Common/Threading/PeriodicTimer.cs diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index ff11c889a6..527a5fb3e6 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -20,6 +20,14 @@ namespace MediaBrowser.Common.Implementations.Networking Logger = logger; } + private void ClearCacheTimerCallback(object state) + { + lock (_localIpAddressSyncLock) + { + _localIpAddresses = null; + } + } + private volatile List _localIpAddresses; private readonly object _localIpAddressSyncLock = new object(); @@ -29,14 +37,13 @@ namespace MediaBrowser.Common.Implementations.Networking /// IPAddress. public IEnumerable GetLocalIpAddresses() { - const int cacheMinutes = 3; - var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; + var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1; if (_localIpAddresses == null || forceRefresh) { lock (_localIpAddressSyncLock) { - forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; + forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1; if (_localIpAddresses == null || forceRefresh) { diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index ccdb319fee..17f211d848 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -90,6 +90,7 @@ + diff --git a/MediaBrowser.Common/Threading/PeriodicTimer.cs b/MediaBrowser.Common/Threading/PeriodicTimer.cs new file mode 100644 index 0000000000..cb562a80dc --- /dev/null +++ b/MediaBrowser.Common/Threading/PeriodicTimer.cs @@ -0,0 +1,67 @@ +using System; +using System.Threading; +using Microsoft.Win32; + +namespace MediaBrowser.Common.Threading +{ + public class PeriodicTimer : IDisposable + { + public Action Callback { get; set; } + private Timer _timer; + private readonly object _state; + private readonly object _timerLock = new object(); + private readonly TimeSpan _period; + + public PeriodicTimer(Action callback, object state, TimeSpan dueTime, TimeSpan period) + { + Callback = callback; + _period = period; + _state = state; + + StartTimer(dueTime); + } + + void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e) + { + if (e.Mode == PowerModes.Resume) + { + DisposeTimer(); + StartTimer(Timeout.InfiniteTimeSpan); + } + } + + private void TimerCallback(object state) + { + Callback(state); + } + + private void StartTimer(TimeSpan dueTime) + { + lock (_timerLock) + { + _timer = new Timer(TimerCallback, _state, dueTime, _period); + + SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; + } + } + + private void DisposeTimer() + { + SystemEvents.PowerModeChanged -= SystemEvents_PowerModeChanged; + + lock (_timerLock) + { + if (_timer != null) + { + _timer.Dispose(); + _timer = null; + } + } + } + + public void Dispose() + { + DisposeTimer(); + } + } +} diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index 5c59197094..14304c2eb5 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.People private int _requestCount; private readonly object _requestCountLock = new object(); - private Timer _requestCountReset; + private DateTime _lastRequestCountReset; public MovieDbPersonProvider(IFileSystem fileSystem, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger) { @@ -48,16 +48,6 @@ namespace MediaBrowser.Providers.People _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 @@ -101,6 +91,12 @@ namespace MediaBrowser.Providers.People { lock (_requestCountLock) { + if ((DateTime.UtcNow - _lastRequestCountReset).TotalHours >= 1) + { + _requestCount = 0; + _lastRequestCountReset = DateTime.UtcNow; + } + var requestCount = _requestCount; if (requestCount >= 5) diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index b115c3bfdc..284556c72b 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -29,7 +29,7 @@ using CommonIO; namespace MediaBrowser.Server.Implementations.Channels { - public class ChannelManager : IChannelManager, IDisposable + public class ChannelManager : IChannelManager { private IChannel[] _channels; @@ -47,11 +47,6 @@ namespace MediaBrowser.Server.Implementations.Channels private readonly ILocalizationManager _localization; private readonly ConcurrentDictionary _refreshedItems = new ConcurrentDictionary(); - private readonly ConcurrentDictionary _downloadCounts = new ConcurrentDictionary(); - - private Timer _refreshTimer; - private Timer _clearDownloadCountsTimer; - public ChannelManager(IUserManager userManager, IDtoService dtoService, ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IUserDataManager userDataManager, IJsonSerializer jsonSerializer, ILocalizationManager localization, IHttpClient httpClient, IProviderManager providerManager) { _userManager = userManager; @@ -65,9 +60,6 @@ namespace MediaBrowser.Server.Implementations.Channels _localization = localization; _httpClient = httpClient; _providerManager = providerManager; - - _refreshTimer = new Timer(s => _refreshedItems.Clear(), null, TimeSpan.FromHours(3), TimeSpan.FromHours(3)); - _clearDownloadCountsTimer = new Timer(s => _downloadCounts.Clear(), null, TimeSpan.FromHours(24), TimeSpan.FromHours(24)); } private TimeSpan CacheLength @@ -206,6 +198,8 @@ namespace MediaBrowser.Server.Implementations.Channels public async Task RefreshChannels(IProgress progress, CancellationToken cancellationToken) { + _refreshedItems.Clear(); + var allChannelsList = GetAllChannels().ToList(); var numComplete = 0; @@ -1471,12 +1465,6 @@ namespace MediaBrowser.Server.Implementations.Channels var limit = features.DailyDownloadLimit; - if (!ValidateDownloadLimit(host, limit)) - { - _logger.Error(string.Format("Download limit has been reached for {0}", channel.Name)); - throw new ChannelDownloadException(string.Format("Download limit has been reached for {0}", channel.Name)); - } - foreach (var header in source.RequiredHttpHeaders) { options.RequestHeaders[header.Key] = header.Value; @@ -1495,8 +1483,6 @@ namespace MediaBrowser.Server.Implementations.Channels }; } - IncrementDownloadCount(host, limit); - if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase) && response.ContentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase)) { var extension = response.ContentType.Split('/') @@ -1531,46 +1517,5 @@ namespace MediaBrowser.Server.Implementations.Channels } } - - private void IncrementDownloadCount(string key, int? limit) - { - if (!limit.HasValue) - { - return; - } - - int current; - _downloadCounts.TryGetValue(key, out current); - - current++; - _downloadCounts.AddOrUpdate(key, current, (k, v) => current); - } - - private bool ValidateDownloadLimit(string key, int? limit) - { - if (!limit.HasValue) - { - return true; - } - - int current; - _downloadCounts.TryGetValue(key, out current); - - return current < limit.Value; - } - - public void Dispose() - { - if (_clearDownloadCountsTimer != null) - { - _clearDownloadCountsTimer.Dispose(); - _clearDownloadCountsTimer = null; - } - if (_refreshTimer != null) - { - _refreshTimer.Dispose(); - _refreshTimer = null; - } - } } } diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs index 6dab136a58..0d6b8ac26c 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs @@ -13,12 +13,13 @@ using System.Threading; using System.Threading.Tasks; using CommonIO; using MediaBrowser.Common.IO; +using MediaBrowser.Common.Threading; namespace MediaBrowser.Server.Implementations.Connect { public class ConnectEntryPoint : IServerEntryPoint { - private Timer _timer; + private PeriodicTimer _timer; private readonly IHttpClient _httpClient; private readonly IApplicationPaths _appPaths; private readonly ILogger _logger; @@ -43,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.Connect { Task.Run(() => LoadCachedAddress()); - _timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3)); + _timer = new PeriodicTimer(null, new TimerCallback(TimerCallback), TimeSpan.FromSeconds(5), TimeSpan.FromHours(3)); } private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.emby.media/service/ip" }; diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index a2ffa9affb..2b2c338dd3 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -11,6 +11,7 @@ using System.IO; using System.Net; using System.Text; using System.Threading; +using MediaBrowser.Common.Threading; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -21,7 +22,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly IServerConfigurationManager _config; private readonly ISsdpHandler _ssdp; - private Timer _timer; + private PeriodicTimer _timer; private bool _isStarted; public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) @@ -95,7 +96,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints NatUtility.UnhandledException += NatUtility_UnhandledException; NatUtility.StartDiscovery(); - _timer = new Timer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); + _timer = new PeriodicTimer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); _ssdp.MessageReceived += _ssdp_MessageReceived; diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs index c3b9c0d4df..d8aef909bb 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageEntryPoint.cs @@ -9,6 +9,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -23,7 +24,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ISessionManager _sessionManager; private readonly IUserManager _userManager; - private Timer _timer; private readonly TimeSpan _frequency = TimeSpan.FromHours(24); private readonly ConcurrentDictionary _apps = new ConcurrentDictionary(); @@ -95,16 +95,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints return info; } - public void Run() + public async void Run() { - _timer = new Timer(OnTimerFired, null, TimeSpan.FromMilliseconds(5000), _frequency); + await Task.Delay(5000).ConfigureAwait(false); + OnTimerFired(); } /// /// Called when [timer fired]. /// - /// The state. - private async void OnTimerFired(object state) + private async void OnTimerFired() { try { @@ -121,12 +121,6 @@ namespace MediaBrowser.Server.Implementations.EntryPoints public void Dispose() { _sessionManager.SessionStarted -= _sessionManager_SessionStarted; - - if (_timer != null) - { - _timer.Dispose(); - _timer = null; - } } } } From 352595bc16563b70fa254331c22f821e32432570 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Jan 2016 22:42:03 -0500 Subject: [PATCH 67/90] add null check to PeriodicTimer --- MediaBrowser.Common/Threading/PeriodicTimer.cs | 5 +++++ .../Connect/ConnectEntryPoint.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Common/Threading/PeriodicTimer.cs b/MediaBrowser.Common/Threading/PeriodicTimer.cs index cb562a80dc..75ccada4ef 100644 --- a/MediaBrowser.Common/Threading/PeriodicTimer.cs +++ b/MediaBrowser.Common/Threading/PeriodicTimer.cs @@ -14,6 +14,11 @@ namespace MediaBrowser.Common.Threading public PeriodicTimer(Action callback, object state, TimeSpan dueTime, TimeSpan period) { + if (callback == null) + { + throw new ArgumentNullException("callback"); + } + Callback = callback; _period = period; _state = state; diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs index 0d6b8ac26c..12de5f6ef1 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.Server.Implementations.Connect { Task.Run(() => LoadCachedAddress()); - _timer = new PeriodicTimer(null, new TimerCallback(TimerCallback), TimeSpan.FromSeconds(5), TimeSpan.FromHours(3)); + _timer = new PeriodicTimer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3)); } private readonly string[] _ipLookups = { "http://bot.whatismyipaddress.com", "https://connect.emby.media/service/ip" }; From 22bfa9ca82943795215c8f2e5735d31d58391f82 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 00:18:05 -0500 Subject: [PATCH 68/90] merge from dev --- .../Networking/BaseNetworkManager.cs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs index 527a5fb3e6..ff11c889a6 100644 --- a/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/MediaBrowser.Common.Implementations/Networking/BaseNetworkManager.cs @@ -20,14 +20,6 @@ namespace MediaBrowser.Common.Implementations.Networking Logger = logger; } - private void ClearCacheTimerCallback(object state) - { - lock (_localIpAddressSyncLock) - { - _localIpAddresses = null; - } - } - private volatile List _localIpAddresses; private readonly object _localIpAddressSyncLock = new object(); @@ -37,13 +29,14 @@ namespace MediaBrowser.Common.Implementations.Networking /// IPAddress. public IEnumerable GetLocalIpAddresses() { - var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1; + const int cacheMinutes = 3; + var forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; if (_localIpAddresses == null || forceRefresh) { lock (_localIpAddressSyncLock) { - forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= 1; + forceRefresh = (DateTime.UtcNow - _lastRefresh).TotalMinutes >= cacheMinutes; if (_localIpAddresses == null || forceRefresh) { From 933a1664242674d45c5b449fef01ebf555685df5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 00:18:23 -0500 Subject: [PATCH 69/90] 3.0.5852 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 50a0ae7e9c..4620e926eb 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5851")] +[assembly: AssemblyVersion("3.0.5852")] From 0361b8b0e8023c400df3eaac04718cf9b8ff01d0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 13:29:09 -0500 Subject: [PATCH 70/90] don't organize with unknown episode name --- .../FileOrganization/EpisodeFileOrganizer.cs | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index ae40ed6b5a..e15ce27e06 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -189,15 +189,6 @@ namespace MediaBrowser.Server.Implementations.FileOrganization return Task.FromResult(true); } - if (!series.ProviderIds.Any()) - { - var msg = string.Format("Series has not yet been identified: {0}. If you just added the series, please run a library scan or use the identify feature to identify it.", seriesName); - result.Status = FileSortingStatus.Failure; - result.StatusMessage = msg; - _logger.Warn(msg); - return Task.FromResult(true); - } - return OrganizeEpisode(sourcePath, series, seasonNumber, @@ -471,7 +462,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization /// The season number. /// The episode number. /// The ending episode number. + /// The premiere date. /// The options. + /// The cancellation token. /// System.String. private async Task GetNewPath(string sourcePath, Series series, @@ -501,17 +494,20 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var episode = searchResults.FirstOrDefault(); - string episodeName = string.Empty; - if (episode == null) { var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); _logger.Warn(msg); - //throw new Exception(msg); + return null; } - else + + var episodeName = episode.Name; + + if (string.IsNullOrWhiteSpace(episodeName)) { - episodeName = episode.Name; + var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); + _logger.Warn(msg); + return null; } seasonNumber = seasonNumber ?? episode.ParentIndexNumber; From 00de5b1ca7c921bf84b9ba2a51bcf40e4bdafe15 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 14:20:09 -0500 Subject: [PATCH 71/90] update use of timers --- MediaBrowser.Dlna/PlayTo/PlayToManager.cs | 24 ++++++------------- .../News/NewsEntryPoint.cs | 6 ++--- .../EntryPoints/KeepServerAwake.cs | 6 ++--- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index 6c79007c4e..94f8104be4 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IMediaSourceManager _mediaSourceManager; private readonly List _nonRendererUrls = new List(); - private Timer _clearNonRenderersTimer; + private DateTime _lastRendererClear; public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) { @@ -57,19 +57,9 @@ namespace MediaBrowser.Dlna.PlayTo public void Start() { - _clearNonRenderersTimer = new Timer(OnClearUrlTimerCallback, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); - _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; } - private void OnClearUrlTimerCallback(object state) - { - lock (_nonRendererUrls) - { - _nonRendererUrls.Clear(); - } - } - async void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) { string usn; @@ -99,6 +89,12 @@ namespace MediaBrowser.Dlna.PlayTo lock (_nonRendererUrls) { + if ((DateTime.UtcNow - _lastRendererClear).TotalMinutes >= 10) + { + _nonRendererUrls.Clear(); + _lastRendererClear = DateTime.UtcNow; + } + if (_nonRendererUrls.Contains(location, StringComparer.OrdinalIgnoreCase)) { return; @@ -181,12 +177,6 @@ namespace MediaBrowser.Dlna.PlayTo public void Dispose() { _deviceDiscovery.DeviceDiscovered -= _deviceDiscovery_DeviceDiscovered; - - if (_clearNonRenderersTimer != null) - { - _clearNonRenderersTimer.Dispose(); - _clearNonRenderersTimer = null; - } } } } diff --git a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs index e8f910f81b..969541fbc8 100644 --- a/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs +++ b/MediaBrowser.Server.Implementations/News/NewsEntryPoint.cs @@ -1,6 +1,5 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Notifications; @@ -17,12 +16,13 @@ using System.Threading; using System.Threading.Tasks; using System.Xml; using CommonIO; +using MediaBrowser.Common.Threading; namespace MediaBrowser.Server.Implementations.News { public class NewsEntryPoint : IServerEntryPoint { - private Timer _timer; + private PeriodicTimer _timer; private readonly IHttpClient _httpClient; private readonly IApplicationPaths _appPaths; private readonly IFileSystem _fileSystem; @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.News public void Run() { - _timer = new Timer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency); + _timer = new PeriodicTimer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency); } /// diff --git a/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs b/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs index ba335868d3..20d4c6b2a4 100644 --- a/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs +++ b/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs @@ -4,7 +4,7 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Model.Logging; using System; using System.Linq; -using System.Threading; +using MediaBrowser.Common.Threading; namespace MediaBrowser.Server.Startup.Common.EntryPoints { @@ -12,7 +12,7 @@ namespace MediaBrowser.Server.Startup.Common.EntryPoints { private readonly ISessionManager _sessionManager; private readonly ILogger _logger; - private Timer _timer; + private PeriodicTimer _timer; private readonly IServerApplicationHost _appHost; public KeepServerAwake(ISessionManager sessionManager, ILogger logger, IServerApplicationHost appHost) @@ -24,7 +24,7 @@ namespace MediaBrowser.Server.Startup.Common.EntryPoints public void Run() { - _timer = new Timer(obj => + _timer = new PeriodicTimer(obj => { var now = DateTime.UtcNow; if (_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 15)) From 24b925cb56c171a6d88159344f25bc910af5cd29 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 14:37:20 -0500 Subject: [PATCH 72/90] remove timer from PlayToController --- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 49 +++++++------------- 1 file changed, 18 insertions(+), 31 deletions(-) diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index cb3629678f..7e021b8771 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -37,11 +37,28 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IDeviceDiscovery _deviceDiscovery; private readonly string _serverAddress; private readonly string _accessToken; + private readonly DateTime _creationTime; public bool IsSessionActive { get { + var lastDateKnownActivity = new[] { _creationTime, _device.DateLastActivity }.Max(); + + if (DateTime.UtcNow >= lastDateKnownActivity.AddSeconds(120)) + { + try + { + // Session is inactive, mark it for Disposal and don't start the elapsed timer. + _sessionManager.ReportSessionEnded(_session.Id); + } + catch (Exception ex) + { + _logger.ErrorException("Error in ReportSessionEnded", ex); + } + return false; + } + return _device != null; } } @@ -55,8 +72,6 @@ namespace MediaBrowser.Dlna.PlayTo get { return IsSessionActive; } } - private Timer _updateTimer; - public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, IDeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) { _session = session; @@ -72,6 +87,7 @@ namespace MediaBrowser.Dlna.PlayTo _mediaSourceManager = mediaSourceManager; _accessToken = accessToken; _logger = logger; + _creationTime = DateTime.UtcNow; } public void Init(Device device) @@ -84,8 +100,6 @@ namespace MediaBrowser.Dlna.PlayTo _device.Start(); _deviceDiscovery.DeviceLeft += _deviceDiscovery_DeviceLeft; - - _updateTimer = new Timer(updateTimer_Elapsed, null, 60000, 60000); } void _deviceDiscovery_DeviceLeft(object sender, SsdpMessageEventArgs e) @@ -117,22 +131,6 @@ namespace MediaBrowser.Dlna.PlayTo } } - private void updateTimer_Elapsed(object state) - { - if (DateTime.UtcNow >= _device.DateLastActivity.AddSeconds(120)) - { - try - { - // Session is inactive, mark it for Disposal and don't start the elapsed timer. - _sessionManager.ReportSessionEnded(_session.Id); - } - catch (Exception ex) - { - _logger.ErrorException("Error in ReportSessionEnded", ex); - } - } - } - async void _device_MediaChanged(object sender, MediaChangedEventArgs e) { try @@ -634,21 +632,10 @@ namespace MediaBrowser.Dlna.PlayTo _device.MediaChanged -= _device_MediaChanged; _deviceDiscovery.DeviceLeft -= _deviceDiscovery_DeviceLeft; - DisposeUpdateTimer(); - _device.Dispose(); } } - private void DisposeUpdateTimer() - { - if (_updateTimer != null) - { - _updateTimer.Dispose(); - _updateTimer = null; - } - } - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public Task SendGeneralCommand(GeneralCommand command, CancellationToken cancellationToken) From de30a0e10bdc05a1ac44ec84e4a2be154a647236 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 14:52:39 -0500 Subject: [PATCH 73/90] remove volume timer from device --- MediaBrowser.Dlna/PlayTo/Device.cs | 79 ++++++++++++++++-------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/MediaBrowser.Dlna/PlayTo/Device.cs b/MediaBrowser.Dlna/PlayTo/Device.cs index 222a52736c..1ec7a4ce09 100644 --- a/MediaBrowser.Dlna/PlayTo/Device.cs +++ b/MediaBrowser.Dlna/PlayTo/Device.cs @@ -22,14 +22,26 @@ namespace MediaBrowser.Dlna.PlayTo #region Fields & Properties private Timer _timer; - private Timer _volumeTimer; public DeviceInfo Properties { get; set; } private int _muteVol; public bool IsMuted { get; set; } - public int Volume { get; set; } + private int _volume; + + public int Volume + { + get + { + RefreshVolumeIfNeeded(); + return _volume; + } + set + { + _volume = value; + } + } public TimeSpan? Duration { get; set; } @@ -93,11 +105,6 @@ namespace MediaBrowser.Dlna.PlayTo return 1000; } - private int GetVolumeTimerIntervalMs() - { - return 5000; - } - private int GetInactiveTimerIntervalMs() { return 20000; @@ -107,11 +114,37 @@ namespace MediaBrowser.Dlna.PlayTo { _timer = new Timer(TimerCallback, null, GetPlaybackTimerIntervalMs(), GetInactiveTimerIntervalMs()); - _volumeTimer = new Timer(VolumeTimerCallback, null, Timeout.Infinite, Timeout.Infinite); - _timerActive = false; } + private DateTime _lastVolumeRefresh; + private void RefreshVolumeIfNeeded() + { + if (!_timerActive) + { + return; + } + + if (DateTime.UtcNow >= _lastVolumeRefresh.AddSeconds(5)) + { + _lastVolumeRefresh = DateTime.UtcNow; + RefreshVolume(); + } + } + + private async void RefreshVolume() + { + try + { + await GetVolume().ConfigureAwait(false); + await GetMute().ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error updating device volume info for {0}", ex, Properties.Name); + } + } + private readonly object _timerLock = new object(); private bool _timerActive; private void RestartTimer() @@ -124,7 +157,6 @@ namespace MediaBrowser.Dlna.PlayTo { _logger.Debug("RestartTimer"); _timer.Change(10, GetPlaybackTimerIntervalMs()); - _volumeTimer.Change(100, GetVolumeTimerIntervalMs()); } _timerActive = true; @@ -150,10 +182,6 @@ namespace MediaBrowser.Dlna.PlayTo { _timer.Change(interval, interval); } - if (_volumeTimer != null) - { - _volumeTimer.Change(Timeout.Infinite, Timeout.Infinite); - } } _timerActive = false; @@ -440,19 +468,6 @@ namespace MediaBrowser.Dlna.PlayTo } } - private async void VolumeTimerCallback(object sender) - { - try - { - await GetVolume().ConfigureAwait(false); - await GetMute().ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error updating device volume info for {0}", ex, Properties.Name); - } - } - private async Task GetVolume() { var command = RendererCommands.ServiceActions.FirstOrDefault(c => c.Name == "GetVolume"); @@ -1012,7 +1027,6 @@ namespace MediaBrowser.Dlna.PlayTo _disposed = true; DisposeTimer(); - DisposeVolumeTimer(); } } @@ -1025,15 +1039,6 @@ namespace MediaBrowser.Dlna.PlayTo } } - private void DisposeVolumeTimer() - { - if (_volumeTimer != null) - { - _volumeTimer.Dispose(); - _volumeTimer = null; - } - } - #endregion public override string ToString() From b82b6fc97554009c045f2f2f0ffa10cf806bc71b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 14:52:50 -0500 Subject: [PATCH 74/90] remove no_accurate seek --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9e2e399d78..bb7f6bb1e9 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -2192,7 +2192,7 @@ namespace MediaBrowser.Api.Playback { if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase)) { - inputModifier += " -noaccurate_seek"; + //inputModifier += " -noaccurate_seek"; } } From b1c9984498db115bae5e32e3e1c018fb7cb340a9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 21:42:53 -0500 Subject: [PATCH 75/90] update timer --- .../EntryPoints/LoadRegistrations.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs index 701cf21fb1..efda368211 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs @@ -4,6 +4,7 @@ using MediaBrowser.Model.Logging; using System; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Threading; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -22,7 +23,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// private readonly ILogger _logger; - private Timer _timer; + private PeriodicTimer _timer; /// /// Initializes a new instance of the class. @@ -41,7 +42,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints /// public void Run() { - _timer = new Timer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12)); + _timer = new PeriodicTimer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12)); } private async Task LoadAllRegistrations() From 0a43522d15641c677fb73485cce2f7451c292736 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 23:54:42 -0500 Subject: [PATCH 76/90] default to include hidden --- MediaBrowser.Api/EnvironmentService.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index 8fdfea6b41..4e88e946f4 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; @@ -46,6 +45,11 @@ namespace MediaBrowser.Api /// true if [include hidden]; otherwise, false. [ApiMember(Name = "IncludeHidden", Description = "An optional filter to include or exclude hidden files and folders. true/false", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool IncludeHidden { get; set; } + + public GetDirectoryContents() + { + IncludeHidden = true; + } } [Route("/Environment/NetworkShares", "GET", Summary = "Gets shares from a network device")] From fae9b184810ec81de92e6d14b8043b37c085de9e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Jan 2016 23:54:55 -0500 Subject: [PATCH 77/90] update episode organizer --- .../FileOrganization/EpisodeFileOrganizer.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index e15ce27e06..73cc5ab014 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -503,12 +503,12 @@ namespace MediaBrowser.Server.Implementations.FileOrganization var episodeName = episode.Name; - if (string.IsNullOrWhiteSpace(episodeName)) - { - var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); - _logger.Warn(msg); - return null; - } + //if (string.IsNullOrWhiteSpace(episodeName)) + //{ + // var msg = string.Format("No provider metadata found for {0} season {1} episode {2}", series.Name, seasonNumber, episodeNumber); + // _logger.Warn(msg); + // return null; + //} seasonNumber = seasonNumber ?? episode.ParentIndexNumber; episodeNumber = episodeNumber ?? episode.IndexNumber; @@ -584,7 +584,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization { seriesName = _fileSystem.GetValidFilename(seriesName).Trim(); - if (string.IsNullOrEmpty(episodeTitle)) + if (string.IsNullOrWhiteSpace(episodeTitle)) { episodeTitle = string.Empty; } From c957ca936f76f6a25af8398feca9f9d1d18e2685 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Jan 2016 13:31:31 -0500 Subject: [PATCH 78/90] update components Conflicts: MediaBrowser.WebDashboard/dashboard-ui/bower_components/emby-webcomponents/browserdeviceprofile.js --- MediaBrowser.Api/Playback/MediaInfoService.cs | 6 +++--- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 3b577ac01e..2bf61f90bd 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -141,10 +141,10 @@ namespace MediaBrowser.Api.Playback var profile = request.DeviceProfile; - var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); - if (caps != null) + if (profile == null) { - if (profile == null) + var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); + if (caps != null) { profile = caps.DeviceProfile; } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index cc153a0106..a3788ef6cf 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -311,9 +311,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From 6ba51ef49508f8ae00c8f31521819a08c8f28b2f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Jan 2016 13:55:26 -0500 Subject: [PATCH 79/90] 3.0.5853 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 4620e926eb..1caaf8542e 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5852")] +[assembly: AssemblyVersion("3.0.5853")] From dc43c1077d28fa1f4b04bc06d6956e83dabedfd6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Jan 2016 13:31:31 -0500 Subject: [PATCH 80/90] merge from dev --- .../LiveTv/EmbyTV/EmbyTV.cs | 70 ++++++++++++++----- 1 file changed, 53 insertions(+), 17 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 250b5655f1..ea64950abe 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -171,7 +171,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { epgData = GetEpgDataForChannel(timer.ChannelId); } - await UpdateTimersForSeriesTimer(epgData, timer).ConfigureAwait(false); + await UpdateTimersForSeriesTimer(epgData, timer, false).ConfigureAwait(false); } var timers = await GetTimersAsync(cancellationToken).ConfigureAwait(false); @@ -348,25 +348,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV } _seriesTimerProvider.Add(info); - await UpdateTimersForSeriesTimer(epgData, info).ConfigureAwait(false); + await UpdateTimersForSeriesTimer(epgData, info, false).ConfigureAwait(false); } public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) { - _seriesTimerProvider.Update(info); - List epgData; - if (info.RecordAnyChannel) - { - var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); - var channelIds = channels.Select(i => i.Id).ToList(); - epgData = GetEpgDataForChannels(channelIds); - } - else - { - epgData = GetEpgDataForChannel(info.ChannelId); - } + var instance = _seriesTimerProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); - await UpdateTimersForSeriesTimer(epgData, info).ConfigureAwait(false); + if (instance != null) + { + instance.ChannelId = info.ChannelId; + instance.Days = info.Days; + instance.EndDate = info.EndDate; + instance.IsPostPaddingRequired = info.IsPostPaddingRequired; + instance.IsPrePaddingRequired = info.IsPrePaddingRequired; + instance.PostPaddingSeconds = info.PostPaddingSeconds; + instance.PrePaddingSeconds = info.PrePaddingSeconds; + instance.Priority = info.Priority; + instance.RecordAnyChannel = info.RecordAnyChannel; + instance.RecordAnyTime = info.RecordAnyTime; + instance.RecordNewOnly = info.RecordNewOnly; + instance.StartDate = info.StartDate; + + _seriesTimerProvider.Update(instance); + + List epgData; + if (instance.RecordAnyChannel) + { + var channels = await GetChannelsAsync(true, CancellationToken.None).ConfigureAwait(false); + var channelIds = channels.Select(i => i.Id).ToList(); + epgData = GetEpgDataForChannels(channelIds); + } + else + { + epgData = GetEpgDataForChannel(instance.ChannelId); + } + + await UpdateTimersForSeriesTimer(epgData, instance, true).ConfigureAwait(false); + } } public Task UpdateTimerAsync(TimerInfo info, CancellationToken cancellationToken) @@ -856,7 +875,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV return _config.GetConfiguration("livetv"); } - private async Task UpdateTimersForSeriesTimer(List epgData, SeriesTimerInfo seriesTimer) + private async Task UpdateTimersForSeriesTimer(List epgData, SeriesTimerInfo seriesTimer, bool deleteInvalidTimers) { var newTimers = GetTimersForSeries(seriesTimer, epgData, _recordingProvider.GetAll()).ToList(); @@ -869,12 +888,29 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _timerProvider.AddOrUpdate(timer); } } + + if (deleteInvalidTimers) + { + var allTimers = GetTimersForSeries(seriesTimer, epgData, new List()) + .Select(i => i.Id) + .ToList(); + + var deletes = _timerProvider.GetAll() + .Where(i => string.Equals(i.SeriesTimerId, seriesTimer.Id, StringComparison.OrdinalIgnoreCase)) + .Where(i => !allTimers.Contains(i.Id, StringComparer.OrdinalIgnoreCase) && i.StartDate > DateTime.UtcNow) + .ToList(); + + foreach (var timer in deletes) + { + await CancelTimerAsync(timer.Id, CancellationToken.None).ConfigureAwait(false); + } + } } private IEnumerable GetTimersForSeries(SeriesTimerInfo seriesTimer, IEnumerable allPrograms, IReadOnlyList currentRecordings) { // Exclude programs that have already ended - allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow); + allPrograms = allPrograms.Where(i => i.EndDate > DateTime.UtcNow && i.StartDate > DateTime.UtcNow); allPrograms = GetProgramsForSeries(seriesTimer, allPrograms); From 77a4c6af94e3f8ce02926b445ffff791b8ccd7d7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Jan 2016 15:59:09 -0500 Subject: [PATCH 81/90] switch to shared paperdialoghelper --- 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 a3788ef6cf..1657922919 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -158,9 +158,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From a789f1d425fc74d6f83318b54ae4d8b377a706df Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Jan 2016 16:34:28 -0500 Subject: [PATCH 82/90] 3.0.5854 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 1caaf8542e..f230a0b64c 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5853")] +[assembly: AssemblyVersion("3.0.5854")] From 7ac682f06cf45b11967ce51974a3f26da5612b0d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 31 Jan 2016 01:03:40 -0500 Subject: [PATCH 83/90] use shared slideshow --- MediaBrowser.WebDashboard/Api/DashboardService.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 5ad40e4c75..12cd5c385b 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -354,8 +354,7 @@ namespace MediaBrowser.WebDashboard.Api DeleteFoldersByName(Path.Combine(bowerPath, "jstree"), "src"); DeleteFoldersByName(Path.Combine(bowerPath, "Sortable"), "meteor"); DeleteFoldersByName(Path.Combine(bowerPath, "Sortable"), "st"); - DeleteFoldersByName(Path.Combine(bowerPath, "swipebox"), "lib"); - DeleteFoldersByName(Path.Combine(bowerPath, "swipebox"), "scss"); + DeleteFoldersByName(Path.Combine(bowerPath, "Swiper"), "src"); if (string.Equals(mode, "cordova", StringComparison.OrdinalIgnoreCase)) { From 0297d8f7d3bbb774749d627508849fc00d9a4c71 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 31 Jan 2016 19:57:40 -0500 Subject: [PATCH 84/90] update locking --- .../ScheduledTasks/ScheduledTaskWorker.cs | 8 ++++---- MediaBrowser.Controller/Entities/User.cs | 4 ++-- .../Library/LibraryManager.cs | 4 ++-- .../LiveTv/EmbyTV/EmbyTV.cs | 6 +++++- .../LiveTv/EmbyTV/ItemDataProvider.cs | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 95f29915db..a4ccbb6f84 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -233,7 +233,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// /// The _triggers /// - private IEnumerable _triggers; + private volatile List _triggers; /// /// The _triggers sync lock /// @@ -532,7 +532,7 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks /// Loads the triggers. /// /// IEnumerable{BaseTaskTrigger}. - private IEnumerable LoadTriggers() + private List LoadTriggers() { try { @@ -543,12 +543,12 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks catch (FileNotFoundException) { // File doesn't exist. No biggie. Return defaults. - return ScheduledTask.GetDefaultTriggers(); + return ScheduledTask.GetDefaultTriggers().ToList(); } catch (DirectoryNotFoundException) { // File doesn't exist. No biggie. Return defaults. - return ScheduledTask.GetDefaultTriggers(); + return ScheduledTask.GetDefaultTriggers().ToList(); } } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index a9e314ede1..be8521a5c4 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -109,7 +109,7 @@ namespace MediaBrowser.Controller.Entities /// The last activity date. public DateTime? LastActivityDate { get; set; } - private UserConfiguration _config; + private volatile UserConfiguration _config; private readonly object _configSyncLock = new object(); [IgnoreDataMember] public UserConfiguration Configuration @@ -132,7 +132,7 @@ namespace MediaBrowser.Controller.Entities set { _config = value; } } - private UserPolicy _policy; + private volatile UserPolicy _policy; private readonly object _policySyncLock = new object(); [IgnoreDataMember] public UserPolicy Policy diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 0cb5174c9a..b0b2680cac 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -222,7 +222,7 @@ namespace MediaBrowser.Server.Implementations.Library /// /// The _root folder /// - private AggregateFolder _rootFolder; + private volatile AggregateFolder _rootFolder; /// /// The _root folder sync lock /// @@ -743,7 +743,7 @@ namespace MediaBrowser.Server.Implementations.Library return rootFolder; } - private UserRootFolder _userRootFolder; + private volatile UserRootFolder _userRootFolder; private readonly object _syncLock = new object(); public Folder GetUserRootFolder() { diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index ea64950abe..cd91684ce1 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -239,7 +239,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken) { - var timers = _timerProvider.GetAll().Where(i => string.Equals(i.SeriesTimerId, timerId, StringComparison.OrdinalIgnoreCase)); + var timers = _timerProvider + .GetAll() + .Where(i => string.Equals(i.SeriesTimerId, timerId, StringComparison.OrdinalIgnoreCase)) + .ToList(); + foreach (var timer in timers) { CancelTimerInternal(timer.Id); diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index f46daa6d50..b29a7562cf 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV where T : class { private readonly object _fileDataLock = new object(); - private List _items; + private volatile List _items; private readonly IJsonSerializer _jsonSerializer; protected readonly ILogger Logger; private readonly string _dataPath; From 552694bb383e956eaa2ce75c208a70c75cfb2a41 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 31 Jan 2016 20:02:23 -0500 Subject: [PATCH 85/90] 3.0.5855 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index f230a0b64c..74dd1c2b14 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5854")] +[assembly: AssemblyVersion("3.0.5855")] From 025958a22d84d4d98876d8ba349f82087d585b7b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 1 Feb 2016 12:02:58 -0500 Subject: [PATCH 86/90] update interlaced detection --- .../Encoder/MediaEncoder.cs | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index ba0790bf3b..2a3a416ad3 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -292,16 +292,25 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } - // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content - if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1) + var formats = (video.Container ?? string.Empty).Split(',').ToList(); + var enableInterlacedDection = formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && + formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && + formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && + formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && + formats.Contains("wtv", StringComparer.OrdinalIgnoreCase); + + // If it's mpeg based, assume true + if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1) { - var formats = (video.Container ?? string.Empty).Split(',').ToList(); - - if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) && - !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase)) + if (enableInterlacedDection) + { + return true; + } + } + else + { + // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content + if (!enableInterlacedDection) { return false; } From 865e2babfa70809a165ddc7070ffd80b5ee3d87e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 1 Feb 2016 12:22:02 -0500 Subject: [PATCH 87/90] album refresh fixes --- .../Entities/Audio/MusicAlbum.cs | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 98d1eb4ce2..654c9abd3f 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -1,17 +1,21 @@ -using MediaBrowser.Controller.Providers; +using System; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Users; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.Entities.Audio { /// /// Class MusicAlbum /// - public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo + public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IMetadataContainer { public MusicAlbum() { @@ -139,5 +143,58 @@ namespace MediaBrowser.Controller.Entities.Audio return id; } + + public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress progress, CancellationToken cancellationToken) + { + var items = GetRecursiveChildren().ToList(); + + var songs = items.OfType