From ca13b01daa106ad816809d7624a7b46c58e780e2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 22 Apr 2015 09:54:58 -0400 Subject: [PATCH 01/11] increment version --- SharedVersion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ef66190171..1469ab6395 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -//[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5588.1")] +[assembly: AssemblyVersion("3.0.*")] +//[assembly: AssemblyVersion("3.0.5588.1")] From 6f016525208f665502d844d151c31e9ff38fd20a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 23 Apr 2015 12:50:54 -0400 Subject: [PATCH 02/11] control the number of simultaneous image operations --- Emby.Drawing/ImageProcessor.cs | 49 ++++++++++++++++++- .../Drawing/IImageProcessor.cs | 2 +- .../Configuration/EncodingOptions.cs | 2 +- .../EntryPoints/ExternalPortForwarding.cs | 24 ++++----- .../Library/UserManager.cs | 16 ++---- .../Photos/BaseDynamicImageProvider.cs | 34 ++++++------- .../UserViews/DynamicImageProvider.cs | 6 +-- 7 files changed, 85 insertions(+), 48 deletions(-) diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 55c6f6455e..6365bd2940 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -51,6 +51,7 @@ namespace Emby.Drawing private readonly IJsonSerializer _jsonSerializer; private readonly IServerApplicationPaths _appPaths; private readonly IImageEncoder _imageEncoder; + private readonly SemaphoreSlim _imageProcessingSemaphore; public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IImageEncoder imageEncoder) { @@ -88,6 +89,8 @@ namespace Emby.Drawing } _cachedImagedSizes = new ConcurrentDictionary(sizeDictionary); + var count = Environment.ProcessorCount; + _imageProcessingSemaphore = new SemaphoreSlim(count, count); } public string[] SupportedInputFormats @@ -201,6 +204,8 @@ namespace Emby.Drawing await semaphore.WaitAsync().ConfigureAwait(false); + var imageProcessingLockTaken = false; + try { CheckDisposed(); @@ -212,11 +217,20 @@ namespace Emby.Drawing Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + imageProcessingLockTaken = true; + _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options); } } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -254,10 +268,15 @@ namespace Emby.Drawing return GetResult(croppedImagePath); } + var imageProcessingLockTaken = false; + try { Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + imageProcessingLockTaken = true; + _imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath); } catch (Exception ex) @@ -269,6 +288,11 @@ namespace Emby.Drawing } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -592,13 +616,25 @@ namespace Emby.Drawing return enhancedImagePath; } + var imageProcessingLockTaken = false; + try { Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); + + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + imageProcessingLockTaken = true; + await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false); } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -717,9 +753,18 @@ namespace Emby.Drawing return Path.Combine(path, filename); } - public void CreateImageCollage(ImageCollageOptions options) + public async Task CreateImageCollage(ImageCollageOptions options) { - _imageEncoder.CreateImageCollage(options); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + try + { + _imageEncoder.CreateImageCollage(options); + } + finally + { + _imageProcessingSemaphore.Release(); + } } public IEnumerable GetSupportedEnhancers(IHasImages item, ImageType imageType) diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 685d2706da..aeb8173921 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -104,6 +104,6 @@ namespace MediaBrowser.Controller.Drawing /// Creates the image collage. /// /// The options. - void CreateImageCollage(ImageCollageOptions options); + Task CreateImageCollage(ImageCollageOptions options); } } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index c44a7c94d2..afd67eb153 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Model.Configuration DownMixAudioBoost = 2; EncodingQuality = EncodingQuality.Auto; EnableThrottling = true; - ThrottleThresholdSeconds = 90; + ThrottleThresholdSeconds = 120; } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 3fa0df7608..2106a58dee 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints NatUtility.UnhandledException += NatUtility_UnhandledException; NatUtility.StartDiscovery(); - _timer = new Timer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3)); + _timer = new Timer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); _lastConfigIdentifier = GetConfigIdentifier(); @@ -97,17 +97,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) { - //var ex = e.ExceptionObject as Exception; - - //if (ex == null) - //{ - // _logger.Error("Unidentified error reported by Mono.Nat"); - //} - //else - //{ - // // Seeing some blank exceptions coming through here - // _logger.ErrorException("Error reported by Mono.Nat: ", ex); - //} + var ex = e.ExceptionObject as Exception; + + if (ex == null) + { + //_logger.Error("Unidentified error reported by Mono.Nat"); + } + else + { + // Seeing some blank exceptions coming through here + _logger.ErrorException("Error reported by Mono.Nat: ", ex); + } } void NatUtility_DeviceFound(object sender, DeviceEventArgs e) diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 03471a8e9b..02e1795f36 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -345,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Library { var name = MakeValidUsername(Environment.UserName); - var user = InstantiateNewUser(name, false); + var user = InstantiateNewUser(name); user.DateLastSaved = DateTime.UtcNow; @@ -552,7 +552,7 @@ namespace MediaBrowser.Server.Implementations.Library try { - var user = InstantiateNewUser(name, true); + var user = InstantiateNewUser(name); var list = Users.ToList(); list.Add(user); @@ -697,21 +697,13 @@ namespace MediaBrowser.Server.Implementations.Library /// Instantiates the new user. /// /// The name. - /// if set to true [check identifier]. /// User. - private User InstantiateNewUser(string name, bool checkId) + private User InstantiateNewUser(string name) { - var id = ("MBUser" + name).GetMD5(); - - if (checkId && Users.Select(i => i.Id).Contains(id)) - { - id = Guid.NewGuid(); - } - return new User { Name = name, - Id = id, + Id = Guid.NewGuid(), DateCreated = DateTime.UtcNow, DateModified = DateTime.UtcNow, UsesIdForConfigurationPath = true diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 15c43213f7..be71a6408a 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Photos { var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png"); Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var imageCreated = CreateImage(item, itemsWithImages, outputPath, imageType, 0); + var imageCreated = await CreateImage(item, itemsWithImages, outputPath, imageType, 0).ConfigureAwait(false); if (!imageCreated) { @@ -103,9 +103,9 @@ namespace MediaBrowser.Server.Implementations.Photos return parts.GetMD5().ToString("N"); } - protected void CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) + protected Task CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 960, 540, drawText, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 960, 540, drawText, primaryItem.Name); } protected virtual IEnumerable GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable items) @@ -115,22 +115,22 @@ namespace MediaBrowser.Server.Implementations.Photos .Where(i => !string.IsNullOrWhiteSpace(i)); } - protected void CreatePosterCollage(IHasImages primaryItem, List items, string outputPath) + protected Task CreatePosterCollage(IHasImages primaryItem, List items, string outputPath) { - CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name); } - protected void CreateSquareCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) + protected Task CreateSquareCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 800, 800, drawText, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 800, 800, drawText, primaryItem.Name); } - protected void CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) + protected Task CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) { - CreateCollage(primaryItem, items, outputPath, width, height, drawText, text); + return CreateCollage(primaryItem, items, outputPath, width, height, drawText, text); } - private void CreateCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) + private Task CreateCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) { Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); @@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Photos InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray() }; - ImageProcessor.CreateImageCollage(options); + return ImageProcessor.CreateImageCollage(options); } public string Name @@ -151,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.Photos get { return "Dynamic Image Provider"; } } - protected virtual bool CreateImage(IHasImages item, + protected virtual async Task CreateImage(IHasImages item, List itemsWithImages, string outputPath, ImageType imageType, @@ -166,7 +166,7 @@ namespace MediaBrowser.Server.Implementations.Photos if (imageType == ImageType.Thumb) { - CreateThumbCollage(item, itemsWithImages, outputPath, drawText); + await CreateThumbCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); return true; } @@ -174,15 +174,15 @@ namespace MediaBrowser.Server.Implementations.Photos { if (item is UserView) { - CreateSquareCollage(item, itemsWithImages, outputPath, drawText); + await CreateSquareCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); } else if (item is PhotoAlbum || item is Playlist) { - CreateSquareCollage(item, itemsWithImages, outputPath, drawText); + await CreateSquareCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); } else { - CreatePosterCollage(item, itemsWithImages, outputPath); + await CreatePosterCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); } return true; @@ -234,7 +234,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected virtual List GetFinalItems(List items, int limit) { // Rotate the images once every x days - var random = DateTime.Now.DayOfYear % 5; + var random = DateTime.Now.DayOfYear % 7; return items .OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index 4a4d90d14f..24dc2cc1d2 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -216,7 +216,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); } - protected override bool CreateImage(IHasImages item, List itemsWithImages, string outputPath, ImageType imageType, int imageIndex) + protected override async Task CreateImage(IHasImages item, List itemsWithImages, string outputPath, ImageType imageType, int imageIndex) { var view = (UserView)item; if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) @@ -226,11 +226,11 @@ namespace MediaBrowser.Server.Implementations.UserViews return false; } - CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540, false, item.Name); + await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540, false, item.Name).ConfigureAwait(false); return true; } - return base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex); + return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); } protected override IEnumerable GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable items) From db66b73a4f500230dd0ed4f5b93d02c6c6916973 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 23 Apr 2015 22:15:29 -0400 Subject: [PATCH 03/11] updated ImageMagickSharp --- Emby.Drawing/Emby.Drawing.csproj | 2 +- .../ImageMagick/ImageMagickEncoder.cs | 1 + Emby.Drawing/packages.config | 2 +- MediaBrowser.Api/StartupWizardService.cs | 1 + .../Configuration/BaseConfigurationManager.cs | 19 ++++++++++-- .../BaseApplicationConfiguration.cs | 6 ++++ .../Configuration/ServerConfiguration.cs | 2 -- .../ServerConfigurationManager.cs | 21 ++++++++++--- .../Sync/CloudSyncProfile.cs | 18 +++++------ .../ApplicationHost.cs | 5 +--- .../MediaBrowser.Server.Startup.Common.csproj | 1 - .../Migrations/MigrateTranscodingPath.cs | 30 ------------------- .../MediaBrowser.ServerApplication.csproj | 5 ++-- .../packages.config | 2 +- 14 files changed, 56 insertions(+), 59 deletions(-) delete mode 100644 MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index f278e1e296..b286885a55 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -34,7 +34,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.15\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.16\lib\net45\ImageMagickSharp.dll diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 3d6cdd03dd..380c56059d 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -63,6 +63,7 @@ namespace Emby.Drawing.ImageMagick { _logger.Info("ImageMagick version: " + Wand.VersionString); TestWebp(); + Wand.SetMagickThreadCount(1); } private bool _webpAvailable = true; diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config index 35c98e592f..acbd2ee3ac 100644 --- a/Emby.Drawing/packages.config +++ b/Emby.Drawing/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index 4655f2c6f9..6ee8d36035 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -66,6 +66,7 @@ namespace MediaBrowser.Api _config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableLibraryMetadataSubFolder = true; _config.Configuration.EnableUserSpecificUserViews = true; + _config.Configuration.EnableCustomPathSubFolders = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs index c53947e443..1b9146644a 100644 --- a/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs +++ b/MediaBrowser.Common.Implementations/Configuration/BaseConfigurationManager.cs @@ -164,9 +164,22 @@ namespace MediaBrowser.Common.Implementations.Configuration /// private void UpdateCachePath() { - ((BaseApplicationPaths)CommonApplicationPaths).CachePath = string.IsNullOrEmpty(CommonConfiguration.CachePath) ? - null : - CommonConfiguration.CachePath; + string cachePath; + + if (string.IsNullOrWhiteSpace(CommonConfiguration.CachePath)) + { + cachePath = null; + } + else if (CommonConfiguration.EnableCustomPathSubFolders) + { + cachePath = Path.Combine(CommonConfiguration.CachePath, "cache"); + } + else + { + cachePath = CommonConfiguration.CachePath; + } + + ((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath; } /// diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index 19620890e7..ca9db0bf08 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -50,6 +50,12 @@ namespace MediaBrowser.Model.Configuration /// The cache path. public string CachePath { get; set; } + /// + /// Gets or sets a value indicating whether [enable custom path sub folders]. + /// + /// true if [enable custom path sub folders]; otherwise, false. + public bool EnableCustomPathSubFolders { get; set; } + /// /// Initializes a new instance of the class. /// diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index ac9bd6b08f..8a3a2a3e43 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -185,8 +185,6 @@ namespace MediaBrowser.Model.Configuration public MetadataOptions[] MetadataOptions { get; set; } - public string TranscodingTempPath { get; set; } - public bool EnableAutomaticRestart { get; set; } public bool EnableRealtimeMonitor { get; set; } diff --git a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs index bb9e9057a3..bf199503be 100644 --- a/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/MediaBrowser.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -101,9 +101,22 @@ namespace MediaBrowser.Server.Implementations.Configuration /// private void UpdateMetadataPath() { - ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = string.IsNullOrEmpty(Configuration.MetadataPath) ? - GetInternalMetadataPath() : - Configuration.MetadataPath; + string metadataPath; + + if (string.IsNullOrWhiteSpace(Configuration.MetadataPath)) + { + metadataPath = GetInternalMetadataPath(); + } + else if (Configuration.EnableCustomPathSubFolders) + { + metadataPath = Path.Combine(Configuration.MetadataPath, "metadata"); + } + else + { + metadataPath = Configuration.MetadataPath; + } + + ((ServerApplicationPaths)ApplicationPaths).InternalMetadataPath = metadataPath; if (Configuration.MergeMetadataAndImagesByName) { @@ -130,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Configuration ((ServerApplicationPaths)ApplicationPaths).TranscodingTempPath = string.IsNullOrEmpty(encodingConfig.TranscodingTempPath) ? null : - encodingConfig.TranscodingTempPath; + Path.Combine(encodingConfig.TranscodingTempPath, "transcoding-temp"); } protected override void OnNamedConfigurationUpdated(string key, object configuration) diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs index 992f1d16c0..0bc527ed56 100644 --- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs +++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; -using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dlna; +using System.Collections.Generic; namespace MediaBrowser.Server.Implementations.Sync { @@ -31,13 +31,13 @@ namespace MediaBrowser.Server.Implementations.Sync DirectPlayProfiles = new[] { - new DirectPlayProfile - { - Container = "mkv", - VideoCodec = "h264,mpeg4", - AudioCodec = mkvAudio, - Type = DlnaProfileType.Video - }, + //new DirectPlayProfile + //{ + // Container = "mkv", + // VideoCodec = "h264,mpeg4", + // AudioCodec = mkvAudio, + // Type = DlnaProfileType.Video + //}, new DirectPlayProfile { Container = "mp4,mov,m4v", diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 0579967394..1a20f7431c 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -357,10 +357,7 @@ namespace MediaBrowser.Server.Startup.Common private void PerformPostInitMigrations() { - var migrations = new List - { - new MigrateTranscodingPath(ServerConfigurationManager) - }; + var migrations = new List(); foreach (var task in migrations) { diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index fb49692b54..4653e6ac77 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -66,7 +66,6 @@ - diff --git a/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs b/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs deleted file mode 100644 index 88f60841de..0000000000 --- a/MediaBrowser.Server.Startup.Common/Migrations/MigrateTranscodingPath.cs +++ /dev/null @@ -1,30 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Server.Startup.Common.Migrations -{ - public class MigrateTranscodingPath : IVersionMigration - { - private readonly IServerConfigurationManager _config; - - public MigrateTranscodingPath(IServerConfigurationManager config) - { - _config = config; - } - - public void Run() - { - if (!string.IsNullOrWhiteSpace(_config.Configuration.TranscodingTempPath)) - { - var newConfig = _config.GetConfiguration("encoding"); - - newConfig.TranscodingTempPath = _config.Configuration.TranscodingTempPath; - _config.SaveConfiguration("encoding", newConfig); - - _config.Configuration.TranscodingTempPath = null; - _config.SaveConfiguration(); - } - } - } -} diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 5c4a15d70a..7e150248e3 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -60,9 +60,8 @@ true - - False - ..\packages\ImageMagickSharp.1.0.0.15\lib\net45\ImageMagickSharp.dll + + ..\packages\ImageMagickSharp.1.0.0.16\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 6c69a853d6..5007cf8af3 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file From 4d57e9b63e24abed41ba38ab82eb50c21a6938fe Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 24 Apr 2015 16:06:37 -0400 Subject: [PATCH 04/11] dlna fix for media monkey --- .../Playback/BaseStreamingService.cs | 4 +++ .../ContentDirectory/ControlHandler.cs | 11 ++++++++ MediaBrowser.Model/Dlna/StreamInfo.cs | 5 ++++ .../Manager/MetadataService.cs | 25 ++++++++----------- .../Localization/Server/server.json | 2 +- 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 923af3816a..dc085dab94 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1522,6 +1522,10 @@ namespace MediaBrowser.Api.Playback { request.LiveStreamId = val; } + else if (i == 24) + { + // Duplicating ItemId because of MediaMonkey + } } } diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 3d7ae8cc4d..246c234625 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -638,6 +638,17 @@ namespace MediaBrowser.Dlna.ContentDirectory Guid itemId; StubType? stubType = null; + // After using PlayTo, MediaMonkey sends a request to the server trying to get item info + const string paramsSrch = "Params="; + var paramsIndex = id.IndexOf(paramsSrch, StringComparison.OrdinalIgnoreCase); + if (paramsIndex != -1) + { + id = id.Substring(paramsIndex + paramsSrch.Length); + + var parts = id.Split(';'); + id = parts[24]; + } + if (id.StartsWith("folder_", StringComparison.OrdinalIgnoreCase)) { stubType = StubType.Folder; diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index b062bc240f..645c1c7d02 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -233,6 +233,11 @@ namespace MediaBrowser.Model.Dlna string liveStreamId = item.MediaSource == null ? null : item.MediaSource.LiveStreamId; list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); + if (isDlna) + { + list.Add(new NameValuePair("ItemId", item.ItemId)); + } + return list; } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 334e148506..71bc9c0651 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -360,7 +360,7 @@ namespace MediaBrowser.Providers.Manager // If replacing all metadata, run internet providers first if (options.ReplaceAllMetadata) { - var remoteResult = await ExecuteRemoteProviders(item, temp, logName, id, providers.OfType>(), cancellationToken) + var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType>(), cancellationToken) .ConfigureAwait(false); refreshResult.UpdateType = refreshResult.UpdateType | remoteResult.UpdateType; @@ -372,9 +372,8 @@ namespace MediaBrowser.Providers.Manager var hasLocalMetadata = false; var userDataList = new List(); - var localProviders = providers.OfType>().ToList(); - foreach (var provider in localProviders) + foreach (var provider in providers.OfType>().ToList()) { var providerName = provider.GetType().Name; Logger.Debug("Running {0} for {1}", providerName, logName); @@ -433,7 +432,7 @@ namespace MediaBrowser.Providers.Manager // Local metadata is king - if any is found don't run remote providers if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh)) { - var remoteResult = await ExecuteRemoteProviders(item, temp, logName, id, providers.OfType>(), cancellationToken) + var remoteResult = await ExecuteRemoteProviders(temp, logName, id, providers.OfType>(), cancellationToken) .ConfigureAwait(false); refreshResult.UpdateType = refreshResult.UpdateType | remoteResult.UpdateType; @@ -447,17 +446,15 @@ namespace MediaBrowser.Providers.Manager if (providers.Any(i => !(i is ICustomMetadataProvider))) { - // If no local providers and doing a full refresh, take data from item itself - if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh && - localProviders.Count == 0 && - refreshResult.UpdateType > ItemUpdateType.None) - { - // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields - MergeData(item, temp, new List(), false, true); - } - if (refreshResult.UpdateType > ItemUpdateType.None) { + // If no local metadata, take data from item itself + if (!hasLocalMetadata) + { + // TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields + MergeData(item, temp, new List(), false, true); + } + MergeData(temp, item, item.LockedFields, true, true); } } @@ -529,7 +526,7 @@ namespace MediaBrowser.Providers.Manager return new TItemType(); } - private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, string logName, TIdType id, IEnumerable> providers, CancellationToken cancellationToken) + private async Task ExecuteRemoteProviders(TItemType temp, string logName, TIdType id, IEnumerable> providers, CancellationToken cancellationToken) { var refreshResult = new RefreshResult(); diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index f464dad4ba..009fc11870 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -1432,7 +1432,7 @@ "MyPreferencesWelcomeMessage2": "Would you like to set your preferences now?", "ToAccessPreferencesHelp": "To access your preferences later, click your user icon in the top right header and select My Preferences.", "HeaderViewStyles": "View Styles", - "LabelSelectViewStyles": "Enable rich presentations for:", + "LabelSelectViewStyles": "Enable enhanced presentations for:", "LabelSelectViewStylesHelp": "If enabled, views will be built with metadata to offer categories such as Suggestions, Latest, Genres, and more. If disabled, they'll be displayed with simple folders.", "TabPhotos": "Photos", "TabVideos": "Videos" From 25cdbf014e16c7607605ee7287adcc953bba6211 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 24 Apr 2015 23:30:44 -0400 Subject: [PATCH 05/11] fix refFrames not being recorded --- MediaBrowser.Api/ItemRefreshService.cs | 13 ++++++++-- .../Encoder/MediaEncoder.cs | 6 +++-- .../Probing/ProbeResultNormalizer.cs | 8 +++--- MediaBrowser.Model/Dlna/StreamBuilder.cs | 26 ++++++++++++++++--- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index 419077f212..f56fd32828 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -1,7 +1,9 @@ -using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Providers; using ServiceStack; +using System.Threading; namespace MediaBrowser.Api { @@ -52,7 +54,14 @@ namespace MediaBrowser.Api var options = GetRefreshOptions(request); - _providerManager.QueueRefresh(item.Id, options); + if (item is Folder) + { + _providerManager.QueueRefresh(item.Id, options); + } + else + { + _providerManager.RefreshFullItem(item, options, CancellationToken.None); + } } private MetadataRefreshOptions GetRefreshOptions(BaseRefreshRequest request) diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index d076a5b6ba..a01f37f91d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -119,7 +119,7 @@ namespace MediaBrowser.MediaEncoding.Encoder var extractKeyFrameInterval = request.ExtractKeyFrameInterval && request.Protocol == MediaProtocol.File && request.VideoType == VideoType.VideoFile; return GetMediaInfoInternal(GetInputArgument(inputFiles, request.Protocol), request.InputPath, request.Protocol, extractChapters, extractKeyFrameInterval, - GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, cancellationToken); + GetProbeSizeArgument(inputFiles, request.Protocol), request.MediaType == DlnaProfileType.Audio, request.VideoType, cancellationToken); } /// @@ -155,6 +155,7 @@ namespace MediaBrowser.MediaEncoding.Encoder /// if set to true [extract key frame interval]. /// The probe size argument. /// if set to true [is audio]. + /// Type of the video. /// The cancellation token. /// Task{MediaInfoResult}. /// @@ -165,6 +166,7 @@ namespace MediaBrowser.MediaEncoding.Encoder bool extractKeyFrameInterval, string probeSizeArgument, bool isAudio, + VideoType videoType, CancellationToken cancellationToken) { var args = extractChapters @@ -236,7 +238,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, isAudio, primaryPath, protocol); + var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol); if (extractKeyFrameInterval && mediaInfo.RunTimeTicks.HasValue) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 267ff875a9..2ef1c0cbd4 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.MediaEncoding.Probing _fileSystem = fileSystem; } - public Model.MediaInfo.MediaInfo GetMediaInfo(InternalMediaInfoResult data, bool isAudio, string path, MediaProtocol protocol) + public Model.MediaInfo.MediaInfo GetMediaInfo(InternalMediaInfoResult data, VideoType videoType, bool isAudio, string path, MediaProtocol protocol) { var info = new Model.MediaInfo.MediaInfo { @@ -79,7 +79,7 @@ namespace MediaBrowser.MediaEncoding.Probing var videoStream = info.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video); - if (videoStream != null) + if (videoStream != null && videoType == VideoType.VideoFile) { UpdateFromMediaInfo(info, videoStream); } @@ -863,12 +863,14 @@ namespace MediaBrowser.MediaEncoding.Probing private void UpdateFromMediaInfo(MediaSourceInfo video, MediaStream videoStream) { - if (video.VideoType == VideoType.VideoFile && video.Protocol == MediaProtocol.File) + if (video.Protocol == MediaProtocol.File) { if (videoStream != null) { try { + _logger.Debug("Running MediaInfo against {0}", video.Path); + var result = new MediaInfoLib().GetVideoInfo(video.Path); videoStream.IsCabac = result.IsCabac ?? videoStream.IsCabac; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 30da8bb4c9..7cda57f4be 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -456,7 +456,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue); } - int audioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec); + int audioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream); playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate); int? maxBitrateSetting = options.GetMaxBitrate(); @@ -479,17 +479,35 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } - private int GetAudioBitrate(int? channels, string codec) + private int GetAudioBitrate(int? channels, string outputCodec, MediaStream audioStream) { + var defaultBitrate = 128000; + if (channels.HasValue) { if (channels.Value >= 5) { - return 320000; + defaultBitrate = 320000; + } + } + + int encoderAudioBitrateLimit = int.MaxValue; + + if (audioStream != null) + { + // Seeing webm encoding failures when source has 1 audio channel and 22k bitrate. + // Any attempts to transcode over 64k will fail + if (audioStream.Channels.HasValue && + audioStream.Channels.Value == 1) + { + if ((audioStream.BitRate ?? 0) < 64000) + { + encoderAudioBitrateLimit = 64000; + } } } - return 128000; + return Math.Min(defaultBitrate, encoderAudioBitrateLimit); } private PlayMethod? GetVideoDirectPlayProfile(DeviceProfile profile, From a7b32d4ec0bd3f4b383078a9ecf2e2f20757bdc9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 25 Apr 2015 23:25:07 -0400 Subject: [PATCH 06/11] update audio transcoding bitrate --- MediaBrowser.Api/Library/LibraryService.cs | 50 +------------ MediaBrowser.Api/UserLibrary/ItemsService.cs | 12 +-- .../Entities/Audio/IHasAlbumArtist.cs | 4 - MediaBrowser.Controller/Entities/BaseItem.cs | 35 +++------ MediaBrowser.Controller/Entities/Game.cs | 5 +- .../Entities/IHasSoundtracks.cs | 29 -------- .../Entities/Movies/Movie.cs | 4 +- MediaBrowser.Controller/Entities/TV/Series.cs | 4 +- MediaBrowser.Controller/Entities/Trailer.cs | 5 +- .../MediaBrowser.Controller.csproj | 1 - MediaBrowser.Dlna/PlayTo/PlayToController.cs | 9 +-- MediaBrowser.Dlna/PlayTo/PlayToManager.cs | 1 + MediaBrowser.Dlna/PlayTo/PlaylistItem.cs | 2 - MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs | 7 +- MediaBrowser.Dlna/Ssdp/SsdpHandler.cs | 7 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 8 +- MediaBrowser.Model/Querying/ItemFields.cs | 5 -- .../Music/MusicBrainzArtistProvider.cs | 2 +- .../Dto/DtoService.cs | 12 --- .../EntryPoints/ExternalPortForwarding.cs | 2 +- .../Library/MusicManager.cs | 6 +- .../Localization/JavaScript/kk.json | 22 +++--- .../Localization/JavaScript/nl.json | 2 +- .../Localization/JavaScript/pt_BR.json | 4 +- .../Localization/JavaScript/ru.json | 74 +++++++++---------- .../Localization/Server/nl.json | 12 +-- .../Localization/Server/pt_BR.json | 2 +- .../Localization/Server/ru.json | 58 +++++++-------- .../Api/PackageCreator.cs | 2 +- 29 files changed, 130 insertions(+), 256 deletions(-) delete mode 100644 MediaBrowser.Controller/Entities/IHasSoundtracks.cs diff --git a/MediaBrowser.Api/Library/LibraryService.cs b/MediaBrowser.Api/Library/LibraryService.cs index 4d9afa260e..f89a703406 100644 --- a/MediaBrowser.Api/Library/LibraryService.cs +++ b/MediaBrowser.Api/Library/LibraryService.cs @@ -591,7 +591,7 @@ namespace MediaBrowser.Api.Library ThemeSongsResult = themeSongs, ThemeVideosResult = themeVideos, - SoundtrackSongsResult = GetSoundtrackSongs(request, request.Id, request.UserId, request.InheritFromParent) + SoundtrackSongsResult = new ThemeMediaResult() }); } @@ -789,53 +789,5 @@ namespace MediaBrowser.Api.Library return ToOptimizedSerializedResultUsingCache(lookup); } - - public ThemeMediaResult GetSoundtrackSongs(GetThemeMedia request, string id, Guid? userId, bool inheritFromParent) - { - var user = userId.HasValue ? _userManager.GetUserById(userId.Value) : null; - - var item = string.IsNullOrEmpty(id) - ? (userId.HasValue - ? user.RootFolder - : _libraryManager.RootFolder) - : _libraryManager.GetItemById(id); - - var dtoOptions = GetDtoOptions(request); - - var dtos = GetSoundtrackSongIds(item, inheritFromParent) - .Select(_libraryManager.GetItemById) - .OfType() - .SelectMany(i => i.GetRecursiveChildren(a => a is Audio)) - .OrderBy(i => i.SortName) - .Select(i => _dtoService.GetBaseItemDto(i, dtoOptions, user, item)); - - var items = dtos.ToArray(); - - return new ThemeMediaResult - { - Items = items, - TotalRecordCount = items.Length, - OwnerId = _dtoService.GetDtoId(item) - }; - } - - private IEnumerable GetSoundtrackSongIds(BaseItem item, bool inherit) - { - var hasSoundtracks = item as IHasSoundtracks; - - if (hasSoundtracks != null) - { - return hasSoundtracks.SoundtrackIds; - } - - if (!inherit) - { - return new List(); - } - - hasSoundtracks = item.Parents.OfType().FirstOrDefault(); - - return hasSoundtracks != null ? hasSoundtracks.SoundtrackIds : new List(); - } } } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index a734581f58..51f88d5743 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string StudioIds { get; set; } - + /// /// Gets or sets the studios. /// @@ -68,7 +68,7 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string ArtistIds { get; set; } - + [ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string Albums { get; set; } @@ -622,7 +622,7 @@ namespace MediaBrowser.Api.UserLibrary private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, bool isPreFiltered, ILibraryManager libraryManager) { var video = i as Video; - + if (!isPreFiltered) { var mediaTypes = request.GetMediaTypes(); @@ -979,8 +979,8 @@ namespace MediaBrowser.Api.UserLibrary if (years.Length > 0 && !(i.ProductionYear.HasValue && years.Contains(i.ProductionYear.Value))) { return false; - } - + } + // Apply person filter var personIds = request.GetPersonIds(); if (personIds.Length > 0) @@ -1057,7 +1057,7 @@ namespace MediaBrowser.Api.UserLibrary // Artists if (!string.IsNullOrEmpty(request.ArtistIds)) { - var artistIds = request.ArtistIds.Split('|'); + var artistIds = request.ArtistIds.Split(new[] { '|', ',' }); var audio = i as IHasArtist; diff --git a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs index 254f90376d..a7c914664e 100644 --- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs @@ -17,10 +17,6 @@ namespace MediaBrowser.Controller.Entities.Audio public static class HasArtistExtensions { - public static bool HasArtist(this IHasArtist hasArtist, string artist) - { - return NameExtensions.EqualsAny(hasArtist.Artists, artist); - } public static bool HasAnyArtist(this IHasArtist hasArtist, string artist) { return NameExtensions.EqualsAny(hasArtist.AllArtists, artist); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 22efd3fba7..3313f45fd1 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -491,6 +491,17 @@ namespace MediaBrowser.Controller.Entities } } + /// + /// Finds a parent of a given type + /// + /// + /// ``0. + public T FindParent() + where T : Folder + { + return Parents.OfType().FirstOrDefault(); + } + [IgnoreDataMember] public virtual BaseItem DisplayParent { @@ -1457,30 +1468,6 @@ namespace MediaBrowser.Controller.Entities return Task.FromResult(true); } - /// - /// Finds a parent of a given type - /// - /// - /// ``0. - public T FindParent() - where T : Folder - { - var parent = Parent; - - while (parent != null) - { - var result = parent as T; - if (result != null) - { - return result; - } - - parent = parent.Parent; - } - - return null; - } - /// /// Gets an image /// diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index 899e5628f1..15d2d755a8 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -8,10 +8,8 @@ using System.Linq; namespace MediaBrowser.Controller.Entities { - public class Game : BaseItem, IHasSoundtracks, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasPreferredMetadataLanguage, IHasLookupInfo + public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasPreferredMetadataLanguage, IHasLookupInfo { - public List SoundtrackIds { get; set; } - public List ThemeSongIds { get; set; } public List ThemeVideoIds { get; set; } @@ -26,7 +24,6 @@ namespace MediaBrowser.Controller.Entities public Game() { MultiPartGameFiles = new List(); - SoundtrackIds = new List(); RemoteTrailers = new List(); LocalTrailerIds = new List(); RemoteTrailerIds = new List(); diff --git a/MediaBrowser.Controller/Entities/IHasSoundtracks.cs b/MediaBrowser.Controller/Entities/IHasSoundtracks.cs deleted file mode 100644 index 3ac2491fbc..0000000000 --- a/MediaBrowser.Controller/Entities/IHasSoundtracks.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities -{ - /// - /// Interface IHasSoundtracks - /// - public interface IHasSoundtracks - { - /// - /// Gets or sets the soundtrack ids. - /// - /// The soundtrack ids. - List SoundtrackIds { get; set; } - - /// - /// Gets the name. - /// - /// The name. - string Name { get; } - - /// - /// Gets the identifier. - /// - /// The identifier. - Guid Id { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 4110047821..429832088f 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -14,12 +14,11 @@ namespace MediaBrowser.Controller.Entities.Movies /// /// Class Movie /// - public class Movie : Video, IHasCriticRating, IHasSoundtracks, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping, IHasOriginalTitle + public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo, ISupportsBoxSetGrouping, IHasOriginalTitle { public List SpecialFeatureIds { get; set; } public string OriginalTitle { get; set; } - public List SoundtrackIds { get; set; } public List ThemeSongIds { get; set; } public List ThemeVideoIds { get; set; } @@ -28,7 +27,6 @@ namespace MediaBrowser.Controller.Entities.Movies public Movie() { SpecialFeatureIds = new List(); - SoundtrackIds = new List(); RemoteTrailers = new List(); LocalTrailerIds = new List(); RemoteTrailerIds = new List(); diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 91014ccdad..e7a5c69ba2 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -15,10 +15,9 @@ namespace MediaBrowser.Controller.Entities.TV /// /// Class Series /// - public class Series : Folder, IHasSoundtracks, IHasTrailers, IHasDisplayOrder, IHasLookupInfo, IHasSpecialFeatures, IMetadataContainer, IHasOriginalTitle + public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo, IHasSpecialFeatures, IMetadataContainer, IHasOriginalTitle { public List SpecialFeatureIds { get; set; } - public List SoundtrackIds { get; set; } public string OriginalTitle { get; set; } public int SeasonCount { get; set; } @@ -30,7 +29,6 @@ namespace MediaBrowser.Controller.Entities.TV AirDays = new List(); SpecialFeatureIds = new List(); - SoundtrackIds = new List(); RemoteTrailers = new List(); LocalTrailerIds = new List(); RemoteTrailerIds = new List(); diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 522e6edf69..f44128e2d6 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -14,17 +14,14 @@ namespace MediaBrowser.Controller.Entities /// Class Trailer /// [Obsolete] - public class Trailer : Video, IHasCriticRating, IHasSoundtracks, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo + public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo { - public List SoundtrackIds { get; set; } - public List ProductionLocations { get; set; } public Trailer() { RemoteTrailers = new List(); Taglines = new List(); - SoundtrackIds = new List(); Keywords = new List(); ProductionLocations = new List(); } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 199f5e0d1f..64490a74f1 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -150,7 +150,6 @@ - diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 66cdc51afe..7a1d547e32 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -310,12 +310,12 @@ namespace MediaBrowser.Dlna.PlayTo { if (isFirst && command.StartPositionTicks.HasValue) { - playlist.Add(CreatePlaylistItem(item, user, command.StartPositionTicks.Value)); + playlist.Add(CreatePlaylistItem(item, user, command.StartPositionTicks.Value, null, null, null)); isFirst = false; } else { - playlist.Add(CreatePlaylistItem(item, user, 0)); + playlist.Add(CreatePlaylistItem(item, user, 0, null, null, null)); } } @@ -456,11 +456,6 @@ namespace MediaBrowser.Dlna.PlayTo } } - private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks) - { - return CreatePlaylistItem(item, user, startPostionTicks, null, null, null); - } - private PlaylistItem CreatePlaylistItem(BaseItem item, User user, long startPostionTicks, string mediaSourceId, int? audioStreamIndex, int? subtitleStreamIndex) { var deviceInfo = _device.Properties; diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index 77c98f9b97..c13f61ee5e 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -85,6 +85,7 @@ namespace MediaBrowser.Dlna.PlayTo { var uri = new Uri(location); + // TODO: Cache list of non-renderers by url to avoid repeating calls var device = await Device.CreateuPnpDeviceAsync(uri, _httpClient, _config, _logger).ConfigureAwait(false); if (device.RendererCommands != null) diff --git a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs index 2af9f8da91..e1f14bfa2c 100644 --- a/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs +++ b/MediaBrowser.Dlna/PlayTo/PlaylistItem.cs @@ -4,8 +4,6 @@ namespace MediaBrowser.Dlna.PlayTo { public class PlaylistItem { - public int PlayState { get; set; } - public string StreamUrl { get; set; } public string Didl { get; set; } diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs index a90c6dc01e..cac1ffe7ec 100644 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs +++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs @@ -47,12 +47,13 @@ namespace MediaBrowser.Dlna.Ssdp if (!network.SupportsMulticast || OperationalStatus.Up != network.OperationalStatus || !network.GetIPProperties().MulticastAddresses.Any()) continue; - - var ipV4 = network.GetIPProperties().GetIPv4Properties(); + + var properties = network.GetIPProperties(); + var ipV4 = properties.GetIPv4Properties(); if (null == ipV4) continue; - var localIps = network.GetIPProperties().UnicastAddresses + var localIps = properties.UnicastAddresses .Where(i => i.Address.AddressFamily == AddressFamily.InterNetwork) .Select(i => i.Address) .ToList(); diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 73bc4984c8..68602a381f 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -116,13 +116,14 @@ namespace MediaBrowser.Dlna.Ssdp // Seconds to delay response values["MX"] = "3"; - SendDatagram("M-SEARCH * HTTP/1.1", values, localIp); + // UDP is unreliable, so send 3 requests at a time (per Upnp spec, sec 1.1.2) + SendDatagram("M-SEARCH * HTTP/1.1", values, localIp, 1); } public void SendDatagram(string header, Dictionary values, EndPoint localAddress, - int sendCount = 1) + int sendCount) { SendDatagram(header, values, _ssdpEndp, localAddress, false, sendCount); } @@ -132,7 +133,7 @@ namespace MediaBrowser.Dlna.Ssdp EndPoint endpoint, EndPoint localAddress, bool ignoreBindFailure, - int sendCount = 1) + int sendCount) { var msg = new SsdpMessageBuilder().BuildMessage(header, values); var queued = false; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 7cda57f4be..cecd61e79d 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -456,7 +456,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.MaxAudioChannels = Math.Min(options.MaxAudioChannels.Value, currentValue); } - int audioBitrate = GetAudioBitrate(playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream); + int audioBitrate = GetAudioBitrate(options.GetMaxBitrate(), playlistItem.TargetAudioChannels, playlistItem.TargetAudioCodec, audioStream); playlistItem.AudioBitrate = Math.Min(playlistItem.AudioBitrate ?? audioBitrate, audioBitrate); int? maxBitrateSetting = options.GetMaxBitrate(); @@ -479,13 +479,13 @@ namespace MediaBrowser.Model.Dlna return playlistItem; } - private int GetAudioBitrate(int? channels, string outputCodec, MediaStream audioStream) + private int GetAudioBitrate(int? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream) { var defaultBitrate = 128000; - if (channels.HasValue) + if (targetAudioChannels.HasValue) { - if (channels.Value >= 5) + if (targetAudioChannels.Value >= 5 && (maxTotalBitrate ?? 0) >= 1500000) { defaultBitrate = 320000; } diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 77b3dc0ee1..0362b7aedd 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -199,11 +199,6 @@ /// The series studio /// SeriesStudio, - - /// - /// The soundtrack ids - /// - SoundtrackIds, /// /// The sort name of the item diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs index 9741b772a5..c04f805495 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs @@ -122,7 +122,7 @@ namespace MediaBrowser.Providers.Music if (singleResult != null) { musicBrainzId = singleResult.GetProviderId(MetadataProviders.MusicBrainzArtist); - result.Item.Name = singleResult.Name; + //result.Item.Name = singleResult.Name; } } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index f44b7b5a84..402bd4d985 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -325,18 +325,6 @@ namespace MediaBrowser.Server.Implementations.Dto AttachBasicFields(dto, item, owner, options); - if (fields.Contains(ItemFields.SoundtrackIds)) - { - var hasSoundtracks = item as IHasSoundtracks; - - if (hasSoundtracks != null) - { - dto.SoundtrackIds = hasSoundtracks.SoundtrackIds - .Select(i => i.ToString("N")) - .ToArray(); - } - } - var playlist = item as Playlist; if (playlist != null) { diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 2106a58dee..fa05973d87 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -106,7 +106,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints else { // Seeing some blank exceptions coming through here - _logger.ErrorException("Error reported by Mono.Nat: ", ex); + //_logger.ErrorException("Error reported by Mono.Nat: ", ex); } } diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs index 3a854f2fe0..1a9e982688 100644 --- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MusicManager.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Library var genres = user.RootFolder .GetRecursiveChildren(user, i => i is Audio) .Cast