From 96f6985b4b5eee8fbb926989b1cf22076c9d6861 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 27 Mar 2016 23:38:31 -0400 Subject: [PATCH 001/852] restore version --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index f6c35210c..e0c8719c1 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5911")] +[assembly: AssemblyVersion("3.0.5921")] From ab2a29187074b518a06b3bb4d6467d73ca616110 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 00:26:25 -0400 Subject: [PATCH 002/852] update hls stop --- MediaBrowser.Api/ApiEntryPoint.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index 8233717ab..66ca8c25d 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -349,7 +349,7 @@ namespace MediaBrowser.Api if (job.Type != TranscodingJobType.Progressive) { - timerDuration = 1800000; + timerDuration = 60000; } job.PingTimeout = timerDuration; From fd16a9ffdaddbc43e3a7a28c47681a1fd485a7eb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 01:16:44 -0400 Subject: [PATCH 003/852] make download function modular --- .../MediaBrowser.WebDashboard.csproj | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 6c67e4483..59f192bcc 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -107,6 +107,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -1148,11 +1151,6 @@ PreserveNewest - - - PreserveNewest - - PreserveNewest From 139a9625a500946669eed1296882c0e1f38c752c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 01:17:08 -0400 Subject: [PATCH 004/852] removed dead code --- 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 59f192bcc..e1a6dc481 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1370,9 +1370,6 @@ - - PreserveNewest - PreserveNewest From a46a245d29d4f45e6ae83e8709700fdf977cb1ca Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 21:17:49 -0400 Subject: [PATCH 005/852] update profiles --- MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Default.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Kodi.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml | 1 - MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml | 1 - MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml | 1 - MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml | 1 - MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml | 1 - MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml | 1 - MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml | 1 - MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Vlc.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml | 3 +-- MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml | 3 +-- 25 files changed, 18 insertions(+), 43 deletions(-) diff --git a/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml index b80137dea..2b67b0eaf 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Default.xml b/MediaBrowser.Dlna/Profiles/Xml/Default.xml index bfb4a7bc2..779c800e5 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Default.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Default.xml @@ -1,10 +1,9 @@ Generic Device - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml index d0a5026fd..89f6c03c7 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml @@ -6,10 +6,9 @@ Denon - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml index 5cc027549..437e6bdb4 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml index dfd8730fb..62cc5d81e 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml @@ -8,10 +8,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml b/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml index 48c4dcd8e..73cb54c70 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Kodi.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml index 6717504bf..9649b5e68 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml index f101fb7b6..102e05d93 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml @@ -5,10 +5,9 @@ DMA2100us - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml index 5756bc219..588752d91 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml index adbbbb386..20a112b67 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml @@ -8,10 +8,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml index a38236476..b6b420ba2 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml @@ -1,10 +1,9 @@ Popcorn Hour - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml index af4f6e913..1f3692322 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml index b32c369f3..673affa70 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml @@ -7,7 +7,6 @@ Sony - Emby Microsoft Corporation http://emby.media/ Windows Media Player Sharing diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml index 7d05fdbdc..8780229c5 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml @@ -9,7 +9,6 @@ - Emby Microsoft Corporation http://emby.media/ Windows Media Player Sharing diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml index 73f5baf65..1ea6276f8 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml @@ -8,7 +8,6 @@ - Emby Microsoft Corporation http://www.microsoft.com/ Windows Media Player Sharing diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml index b156bfa5b..012b6ca73 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml @@ -8,7 +8,6 @@ - Emby Microsoft Corporation http://www.microsoft.com/ Windows Media Player Sharing diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml index c0f92fe15..52a3e196c 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml @@ -8,7 +8,6 @@ - Emby Microsoft Corporation http://www.microsoft.com/ Windows Media Player Sharing diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml index f21da6ecc..f060f6ef4 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml @@ -8,7 +8,6 @@ - Emby Microsoft Corporation http://www.microsoft.com/ Windows Media Player Sharing diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml index a407ba473..de418f8be 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml @@ -8,7 +8,6 @@ - Emby Microsoft Corporation http://www.microsoft.com/ Windows Media Player Sharing diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml index f0c7cb40a..f147d75b6 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml @@ -8,10 +8,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml index 58c76d914..bc83d488e 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml @@ -8,10 +8,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml index 7a7f37b66..69ee8a002 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml index 50f30d40f..2c812f98c 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml @@ -8,10 +8,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml index ab8ed713f..ad08adf0d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml @@ -8,10 +8,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ diff --git a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml index 0aeb4d912..12eba1e35 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml @@ -7,10 +7,9 @@ - Emby Emby http://emby.media/ - Emby + Emby Server Emby Emby http://emby.media/ From eeef5439891ecf3a25d271ea9ec15629c66c4b10 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 21:33:08 -0400 Subject: [PATCH 006/852] support music dynamic images --- MediaBrowser.Providers/Folders/DefaultImageProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs index ca543163d..ee83efd26 100644 --- a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs +++ b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.Folders } if (string.Equals(viewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase)) { - return urlPrefix + "music.jpg"; + //return urlPrefix + "music.jpg"; } if (string.Equals(viewType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) { @@ -105,7 +105,7 @@ namespace MediaBrowser.Providers.Folders } if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { - return urlPrefix + "homevideos.jpg"; + //return urlPrefix + "homevideos.jpg"; } if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { From 62cb2195eab0605b98c59d9dd08d6927c984969e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 21:33:18 -0400 Subject: [PATCH 007/852] update dlna server friendly name --- MediaBrowser.Dlna/Profiles/DefaultProfile.cs | 3 +-- MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs | 5 +++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs index a8e6b1ca6..386a4eb1e 100644 --- a/MediaBrowser.Dlna/Profiles/DefaultProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DefaultProfile.cs @@ -15,10 +15,9 @@ namespace MediaBrowser.Dlna.Profiles XDlnaDoc = "DMS-1.50"; - FriendlyName = "Emby"; Manufacturer = "Emby"; ModelDescription = "Emby"; - ModelName = "Emby"; + ModelName = "Emby Server"; ModelNumber = "Emby"; ModelUrl = "http://emby.media/"; ManufacturerUrl = "http://emby.media/"; diff --git a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs index 386370596..c4568a2ae 100644 --- a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs +++ b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs @@ -138,6 +138,11 @@ namespace MediaBrowser.Dlna.Server private string GetFriendlyName() { + if (string.IsNullOrWhiteSpace(_profile.FriendlyName)) + { + return _serverName; + } + var characters = _serverName.Where(c => (char.IsLetterOrDigit(c) || c == '-')).ToArray(); var serverName = new string(characters); From 5bf1dcd5199026cb52d15892f48dbf8727b17036 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 23:10:01 -0400 Subject: [PATCH 008/852] update channel view --- MediaBrowser.Model/Configuration/UserConfiguration.cs | 3 +-- MediaBrowser.Server.Implementations/Library/UserViewManager.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs index f294d1dec..5f42dd2de 100644 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Model.Configuration public string[] PlainFolderViews { get; set; } public bool HidePlayedInLatest { get; set; } - public bool DisplayChannelsInline { get; set; } + public bool EnableChannelView { get; set; } public bool RememberAudioSelections { get; set; } public bool RememberSubtitleSelections { get; set; } @@ -60,7 +60,6 @@ namespace MediaBrowser.Model.Configuration EnableNextEpisodeAutoPlay = true; RememberAudioSelections = true; RememberSubtitleSelections = true; - DisplayChannelsInline = true; HidePlayedInLatest = true; PlayDefaultAudioTrack = true; diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs index 9f6e39b46..1bba20ec5 100644 --- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs @@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.Library var channels = channelResult.Items; - if (!user.Configuration.DisplayChannelsInline && channels.Length > 0) + if (user.Configuration.EnableChannelView && channels.Length > 0) { list.Add(await _channelManager.GetInternalChannelFolder(cancellationToken).ConfigureAwait(false)); } From 4295f0c10fb5387084d8e236fb62ed55d558c257 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 23:12:20 -0400 Subject: [PATCH 009/852] update dlna server name --- MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs index c4568a2ae..37006915c 100644 --- a/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs +++ b/MediaBrowser.Dlna/Server/DescriptionXmlBuilder.cs @@ -140,7 +140,7 @@ namespace MediaBrowser.Dlna.Server { if (string.IsNullOrWhiteSpace(_profile.FriendlyName)) { - return _serverName; + return "Emby - " + _serverName; } var characters = _serverName.Where(c => (char.IsLetterOrDigit(c) || c == '-')).ToArray(); From b293211628409753b8d8f47c31bbf19414440f73 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 23:31:11 -0400 Subject: [PATCH 010/852] resolve missing trailers --- MediaBrowser.Controller/Entities/BaseItem.cs | 6 +++++- .../Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 903c5cfd5..bf25da2ac 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2084,7 +2084,7 @@ namespace MediaBrowser.Controller.Entities { get { - if (GetParent() is AggregateFolder || this is Channel || this is BasePluginFolder) + if (GetParent() is AggregateFolder || this is BasePluginFolder) { return true; } @@ -2094,6 +2094,10 @@ namespace MediaBrowser.Controller.Entities { return true; } + if (view != null && string.Equals(view.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase)) + { + return true; + } return false; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index af275faee..4a7235928 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 53; + private const int LatestSchemaVersion = 55; /// /// Initializes a new instance of the class. From f308a41cab09d8ee09bdc4188cbe6f7799730a2e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 12:37:29 -0400 Subject: [PATCH 011/852] update cinema mode trailer selection --- MediaBrowser.Controller/Entities/Trailer.cs | 6 +++--- .../Intros/DefaultIntroProvider.cs | 7 ++++++- .../Library/LibraryManager.cs | 1 + .../Persistence/SqliteItemRepository.cs | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index bd7d30858..c3e24090c 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -21,11 +21,11 @@ namespace MediaBrowser.Controller.Entities Taglines = new List(); Keywords = new List(); ProductionLocations = new List(); - TrailerTypes = new List(); + TrailerTypes = new List { TrailerType.LocalTrailer }; } public List TrailerTypes { get; set; } - + public float? Metascore { get; set; } public List RemoteTrailers { get; set; } @@ -86,7 +86,7 @@ namespace MediaBrowser.Controller.Entities var info = GetItemLookupInfo(); info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer); - + if (!IsInMixedFolder) { info.Name = System.IO.Path.GetFileName(ContainingFolderPath); diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 49012c65a..9ebae5d91 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -102,10 +102,15 @@ namespace MediaBrowser.Server.Implementations.Intros if (trailerTypes.Count > 0) { + var excludeTrailerTypes = Enum.GetNames(typeof(TrailerType)) + .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) + .Except(trailerTypes) + .ToArray(); + var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - TrailerTypes = trailerTypes.ToArray() + ExcludeTrailerTypes = excludeTrailerTypes }); candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 28671fb7c..ccba293a3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -2361,6 +2361,7 @@ namespace MediaBrowser.Server.Implementations.Library } video.ExtraType = ExtraType.Trailer; + video.TrailerTypes = new List { TrailerType.LocalTrailer }; return video; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4a7235928..de914b773 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 55; + private const int LatestSchemaVersion = 56; /// /// Initializes a new instance of the class. From 425948359a1f1bb3f575704f6928ead2c48451cf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 14:30:04 -0400 Subject: [PATCH 012/852] handle empty album artists --- MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 3139392b0..743351406 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -791,6 +791,11 @@ namespace MediaBrowser.MediaEncoding.Probing } + if (audio.AlbumArtists.Count == 0) + { + audio.AlbumArtists = audio.Artists.Take(1).ToList(); + } + // Track number audio.IndexNumber = GetDictionaryDiscValue(tags, "track"); From 6ebaf278886a8fac90e3dceee21b401c5d7ddb1c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 15:08:52 -0400 Subject: [PATCH 013/852] update translations --- .../Localization/Core/hu.json | 6 +++--- .../Localization/Core/sv.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hu.json b/MediaBrowser.Server.Implementations/Localization/Core/hu.json index b175ae6c1..d098a893c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/hu.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/hu.json @@ -33,10 +33,10 @@ "CategoryPlugin": "B\u0151v\u00edtm\u00e9ny", "NotificationOptionPluginError": "B\u0151v\u00edtm\u00e9ny hiba", "NotificationOptionApplicationUpdateAvailable": "Friss\u00edt\u00e9s el\u00e9rhet\u0151", - "NotificationOptionApplicationUpdateInstalled": "Friss\u00edt\u00e9s telep\u00edtve", - "NotificationOptionPluginUpdateInstalled": "B\u0151v\u00edtm\u00e9ny friss\u00edtve", + "NotificationOptionApplicationUpdateInstalled": "Program friss\u00edt\u00e9s telep\u00edtve", + "NotificationOptionPluginUpdateInstalled": "B\u0151v\u00edtm\u00e9ny friss\u00edt\u00e9s telep\u00edtve", "NotificationOptionPluginInstalled": "B\u0151v\u00edtm\u00e9ny telep\u00edtve", - "NotificationOptionPluginUninstalled": "B\u0151v\u00edtm\u00e9ny t\u00f6r\u00f6lve", + "NotificationOptionPluginUninstalled": "B\u0151v\u00edtm\u00e9ny elt\u00e1vol\u00edtva", "NotificationOptionVideoPlayback": "Vide\u00f3 elind\u00edtva", "NotificationOptionAudioPlayback": "Zene elind\u00edtva", "NotificationOptionGamePlayback": "J\u00e1t\u00e9k elind\u00edtva", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sv.json b/MediaBrowser.Server.Implementations/Localization/Core/sv.json index f52f656d4..eca16e2b4 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/sv.json @@ -24,9 +24,9 @@ "LabelApiDocumentation": "Api Dokumentation", "LabelDeveloperResources": "Resurser f\u00f6r utvecklare", "LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket", - "LabelConfigureServer": "Configure Emby", + "LabelConfigureServer": "Konfigurera Emby", "LabelRestartServer": "Starta om servern", - "CategorySync": "Sync", + "CategorySync": "Synka", "CategoryUser": "Anv\u00e4ndare", "CategorySystem": "System", "CategoryApplication": "App", From 12a1414d73c0671b0b502352b524aac66bf9c4c6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 15:43:37 -0400 Subject: [PATCH 014/852] remove unneeded wait for exit --- .../LiveTv/EmbyTV/EncodedRecorder.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 69cc8ebf7..442f151dd 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -175,9 +175,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV //process.Kill(); _process.StandardInput.WriteLine("q"); - - // Need to wait because killing is asynchronous - _process.WaitForExit(5000); } catch (Exception ex) { From e1568a8b6e16f815a0967b80e6bc457355ece836 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 30 Mar 2016 22:00:05 -0400 Subject: [PATCH 015/852] update components --- 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 e1a6dc481..ba0216e1a 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -275,9 +275,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From e61014aa881c0720a9b3a3f9bddab702ddd44671 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 02:33:37 -0400 Subject: [PATCH 016/852] fix different styles of favorites --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index ba0216e1a..1c89a6e34 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -107,6 +107,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -305,6 +308,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 0be3fdc062ab218ba5702f065b4bee565850c402 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 12:44:02 -0400 Subject: [PATCH 017/852] fix merge conflict --- SharedVersion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index e0c8719c1..2d2a44ae5 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -//[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5921")] +[assembly: AssemblyVersion("3.0.*")] +//[assembly: AssemblyVersion("3.0.5911")] From ba192144ecdcca0081a41834df680ed9125d0047 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 12:46:39 -0400 Subject: [PATCH 018/852] 3.0.5922 --- SharedVersion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 2d2a44ae5..29b0afc2c 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("3.0.*")] -//[assembly: AssemblyVersion("3.0.5911")] +//[assembly: AssemblyVersion("3.0.*")] +[assembly: AssemblyVersion("3.0.5922")] From d5b7ed325e5930b30fd8ecf54088d1bccdd2e8ba Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 14:46:03 -0400 Subject: [PATCH 019/852] switch from Mono.Nat to Open.Nat --- .../EntryPoints/ExternalPortForwarding.cs | 227 ++++-------------- ...MediaBrowser.Server.Implementations.csproj | 4 + .../packages.config | 1 + 3 files changed, 52 insertions(+), 180 deletions(-) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 95763c43f..c0c626438 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -3,7 +3,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; -using Mono.Nat; using System; using System.Collections.Generic; using System.Globalization; @@ -11,6 +10,9 @@ using System.IO; using System.Net; using System.Text; using MediaBrowser.Common.Threading; +using Open.Nat; +using System.Threading; +using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -20,9 +22,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly ISsdpHandler _ssdp; - - private PeriodicTimer _timer; - private bool _isStarted; + private CancellationTokenSource _currentCancellationTokenSource; + private TimeSpan _interval = TimeSpan.FromHours(1); public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) { @@ -32,157 +33,70 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _ssdp = ssdp; } - private string _lastConfigIdentifier; - private string GetConfigIdentifier() - { - var values = new List(); - var config = _config.Configuration; - - values.Add(config.EnableUPnP.ToString()); - values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); - values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); - values.Add(config.EnableHttps.ToString()); - values.Add(_appHost.EnableHttps.ToString()); - - return string.Join("|", values.ToArray()); - } - - void _config_ConfigurationUpdated(object sender, EventArgs e) - { - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - - if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) - { - if (_isStarted) - { - DisposeNat(); - } - - Run(); - } - } - public void Run() { //NatUtility.Logger = new LogWriter(_logger); if (_config.Configuration.EnableUPnP) { - Start(); - } - - _config.ConfigurationUpdated -= _config_ConfigurationUpdated; - _config.ConfigurationUpdated += _config_ConfigurationUpdated; - } - - private void Start() - { - _logger.Debug("Starting NAT discovery"); - NatUtility.EnabledProtocols = new List - { - NatProtocol.Pmp - }; - NatUtility.DeviceFound += NatUtility_DeviceFound; - - // Mono.Nat does never rise this event. The event is there however it is useless. - // You could remove it with no risk. - NatUtility.DeviceLost += NatUtility_DeviceLost; - - - // it is hard to say what one should do when an unhandled exception is raised - // because there isn't anything one can do about it. Probably save a log or ignored it. - NatUtility.UnhandledException += NatUtility_UnhandledException; - NatUtility.StartDiscovery(); - - _timer = new PeriodicTimer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); - - _ssdp.MessageReceived += _ssdp_MessageReceived; - - _lastConfigIdentifier = GetConfigIdentifier(); - - _isStarted = true; - } - - void _ssdp_MessageReceived(object sender, SsdpMessageEventArgs e) - { - var endpoint = e.EndPoint as IPEndPoint; - - if (endpoint != null && e.LocalEndPoint != null) - { - NatUtility.Handle(e.LocalEndPoint.Address, e.Message, endpoint, NatProtocol.Upnp); + Discover(); } } - void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) + private async void Discover() { - var ex = e.ExceptionObject as Exception; + var discoverer = new NatDiscoverer(); - 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 cancellationTokenSource = new CancellationTokenSource(10000); + _currentCancellationTokenSource = cancellationTokenSource; - void NatUtility_DeviceFound(object sender, DeviceEventArgs e) - { try { - var device = e.Device; - _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); + var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cancellationTokenSource).ConfigureAwait(false); + + await CreateRules(device).ConfigureAwait(false); + } + catch (OperationCanceledException) + { - CreateRules(device); } catch (Exception ex) { - // I think it could be a good idea to log the exception because - // you are using permanent portmapping here (never expire) and that means that next time - // CreatePortMap is invoked it can fails with a 718-ConflictInMappingEntry or not. That depends - // on the router's upnp implementation (specs says it should fail however some routers don't do it) - // It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable - // and those errors (upnp errors) could be useful for diagnosting. + _logger.ErrorException("Error discovering NAT devices", ex); + } + finally + { + _currentCancellationTokenSource = null; + } - // Commenting out because users are reporting problems out of our control - //_logger.ErrorException("Error creating port forwarding rules", ex); + if (_config.Configuration.EnableUPnP) + { + await Task.Delay(_interval).ConfigureAwait(false); + Discover(); } } - private List _createdRules = new List(); - private void CreateRules(INatDevice device) + private async Task CreateRules(NatDevice device) { // On some systems the device discovered event seems to fire repeatedly // This check will help ensure we're not trying to port map the same device over and over - var address = device.LocalAddress.ToString(); - - if (!_createdRules.Contains(address)) - { - _createdRules.Add(address); - - CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); - CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); - } + await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); + await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); } - private void CreatePortMap(INatDevice device, int privatePort, int publicPort) + private async Task CreatePortMap(NatDevice device, int privatePort, int publicPort) { _logger.Debug("Creating port map on port {0}", privatePort); - device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) - { - Description = _appHost.Name - }); - } - // As I said before, this method will be never invoked. You can remove it. - void NatUtility_DeviceLost(object sender, DeviceEventArgs e) - { - var device = e.Device; - _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString()); + try + { + await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, privatePort, publicPort, _appHost.Name)).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error creating port map", ex); + } } public void Dispose() @@ -192,63 +106,16 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private void DisposeNat() { - _logger.Debug("Stopping NAT discovery"); - - if (_timer != null) + if (_currentCancellationTokenSource != null) { - _timer.Dispose(); - _timer = null; - } - - _ssdp.MessageReceived -= _ssdp_MessageReceived; - - try - { - // This is not a significant improvement - NatUtility.StopDiscovery(); - NatUtility.DeviceFound -= NatUtility_DeviceFound; - NatUtility.DeviceLost -= NatUtility_DeviceLost; - NatUtility.UnhandledException -= NatUtility_UnhandledException; - } - // Statements in try-block will no fail because StopDiscovery is a one-line - // method that was no chances to fail. - // public static void StopDiscovery () - // { - // searching.Reset(); - // } - // IMO you could remove the catch-block - catch (Exception ex) - { - _logger.ErrorException("Error stopping NAT Discovery", ex); - } - finally - { - _isStarted = false; - } - } - - private class LogWriter : TextWriter - { - private readonly ILogger _logger; - - public LogWriter(ILogger logger) - { - _logger = logger; - } - - public override Encoding Encoding - { - get { return Encoding.UTF8; } - } - - public override void WriteLine(string format, params object[] arg) - { - _logger.Debug(format, arg); - } - - public override void WriteLine(string value) - { - _logger.Debug(value); + try + { + _currentCancellationTokenSource.Cancel(); + } + catch (Exception ex) + { + _logger.ErrorException("Error calling _currentCancellationTokenSource.Cancel", ex); + } } } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 97f090ab2..84c1cae54 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -62,6 +62,10 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll + + ..\packages\Open.NAT.2.0.15.0\lib\net45\Open.Nat.dll + True + ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 66aede029..814a67643 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,6 +7,7 @@ + \ No newline at end of file From e13fcb3cd42b67374621d7e02961e4bd335a235f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 15:22:07 -0400 Subject: [PATCH 020/852] update sat/ip --- .../EntryPoints/ExternalPortForwarding.cs | 18 +- .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 176 ++++++++---------- ...MediaBrowser.Server.Implementations.csproj | 1 + 3 files changed, 86 insertions(+), 109 deletions(-) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index c0c626438..a7e5396eb 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -31,20 +31,26 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _appHost = appHost; _config = config; _ssdp = ssdp; + + _config.ConfigurationUpdated += _config_ConfigurationUpdated; + } + + private void _config_ConfigurationUpdated(object sender, EventArgs e) + { } public void Run() { - //NatUtility.Logger = new LogWriter(_logger); - - if (_config.Configuration.EnableUPnP) - { - Discover(); - } + Discover(); } private async void Discover() { + if (!_config.Configuration.EnableUPnP) + { + return; + } + var discoverer = new NatDiscoverer(); var cancellationTokenSource = new CancellationTokenSource(10000); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index da1894bb7..413ce4549 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -15,6 +15,7 @@ using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Extensions; +using System.Xml.Linq; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { @@ -171,58 +172,87 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public async Task GetInfo(string url, CancellationToken cancellationToken) { - var result = new SatIpTunerHostInfo + Uri locationUri = new Uri(url); + string devicetype = ""; + string friendlyname = ""; + string uniquedevicename = ""; + string manufacturer = ""; + string manufacturerurl = ""; + string modelname = ""; + string modeldescription = ""; + string modelnumber = ""; + string modelurl = ""; + string serialnumber = ""; + string presentationurl = ""; + string capabilities = ""; + string m3u = ""; + var document = XDocument.Load(locationUri.AbsoluteUri); + var xnm = new XmlNamespaceManager(new NameTable()); + XNamespace n1 = "urn:ses-com:satip"; + XNamespace n0 = "urn:schemas-upnp-org:device-1-0"; + xnm.AddNamespace("root", n0.NamespaceName); + xnm.AddNamespace("satip:", n1.NamespaceName); + if (document.Root != null) { - Url = url, - IsEnabled = true, - Type = SatIpHost.DeviceType, - Tuners = 1, - TunersAvailable = 1 - }; - - using (var stream = await _httpClient.Get(url, cancellationToken).ConfigureAwait(false)) - { - using (var streamReader = new StreamReader(stream)) + var deviceElement = document.Root.Element(n0 + "device"); + if (deviceElement != null) { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader)) - { - reader.MoveToContent(); - - // Loop through each element - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.Name) - { - case "device": - using (var subtree = reader.ReadSubtree()) - { - FillFromDeviceNode(result, subtree); - } - break; - default: - reader.Skip(); - break; - } - } - } - } + var devicetypeElement = deviceElement.Element(n0 + "deviceType"); + if (devicetypeElement != null) + devicetype = devicetypeElement.Value; + var friendlynameElement = deviceElement.Element(n0 + "friendlyName"); + if (friendlynameElement != null) + friendlyname = friendlynameElement.Value; + var manufactureElement = deviceElement.Element(n0 + "manufacturer"); + if (manufactureElement != null) + manufacturer = manufactureElement.Value; + var manufactureurlElement = deviceElement.Element(n0 + "manufacturerURL"); + if (manufactureurlElement != null) + manufacturerurl = manufactureurlElement.Value; + var modeldescriptionElement = deviceElement.Element(n0 + "modelDescription"); + if (modeldescriptionElement != null) + modeldescription = modeldescriptionElement.Value; + var modelnameElement = deviceElement.Element(n0 + "modelName"); + if (modelnameElement != null) + modelname = modelnameElement.Value; + var modelnumberElement = deviceElement.Element(n0 + "modelNumber"); + if (modelnumberElement != null) + modelnumber = modelnumberElement.Value; + var modelurlElement = deviceElement.Element(n0 + "modelURL"); + if (modelurlElement != null) + modelurl = modelurlElement.Value; + var serialnumberElement = deviceElement.Element(n0 + "serialNumber"); + if (serialnumberElement != null) + serialnumber = serialnumberElement.Value; + var uniquedevicenameElement = deviceElement.Element(n0 + "UDN"); + if (uniquedevicenameElement != null) uniquedevicename = uniquedevicenameElement.Value; + var presentationUrlElement = deviceElement.Element(n0 + "presentationURL"); + if (presentationUrlElement != null) presentationurl = presentationUrlElement.Value; + var capabilitiesElement = deviceElement.Element(n1 + "X_SATIPCAP"); + if (capabilitiesElement != null) capabilities = capabilitiesElement.Value; + var m3uElement = deviceElement.Element(n1 + "X_SATIPM3U"); + if (m3uElement != null) m3u = m3uElement.Value; } } - if (string.IsNullOrWhiteSpace(result.DeviceId)) + + var result = new SatIpTunerHostInfo + { + Url = url, + Id = uniquedevicename, + IsEnabled = true, + Type = SatIpHost.DeviceType, + Tuners = 1, + TunersAvailable = 1, + M3UUrl = m3u + }; + + result.FriendlyName = friendlyname; + if (string.IsNullOrWhiteSpace(result.Id)) { throw new NotImplementedException(); } - // Device hasn't implemented an m3u list - if (string.IsNullOrWhiteSpace(result.M3UUrl)) - { - result.IsEnabled = false; - } - else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase)) { var fullM3uUrl = url.Substring(0, url.LastIndexOf('/')); @@ -233,66 +263,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return result; } - - private void FillFromDeviceNode(SatIpTunerHostInfo info, XmlReader reader) - { - reader.MoveToContent(); - - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - switch (reader.LocalName) - { - case "UDN": - { - info.DeviceId = reader.ReadElementContentAsString(); - break; - } - - case "friendlyName": - { - info.FriendlyName = reader.ReadElementContentAsString(); - break; - } - - case "satip:X_SATIPCAP": - case "X_SATIPCAP": - { - // DVBS2-2 - var value = reader.ReadElementContentAsString() ?? string.Empty; - var parts = value.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries); - if (parts.Length == 2) - { - int intValue; - if (int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - { - info.TunersAvailable = intValue; - } - - if (int.TryParse(parts[0].Substring(parts[0].Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out intValue)) - { - info.Tuners = intValue; - } - } - break; - } - - case "satip:X_SATIPM3U": - case "X_SATIPM3U": - { - // /channellist.lua?select=m3u - info.M3UUrl = reader.ReadElementContentAsString(); - break; - } - - default: - reader.Skip(); - break; - } - } - } - } } public class SatIpTunerHostInfo : TunerHostInfo diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 84c1cae54..14d275505 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -103,6 +103,7 @@ ..\ThirdParty\ServiceStack.Text\ServiceStack.Text.dll + ..\ThirdParty\UniversalDetector\UniversalDetector.dll From 54de1b744b996683fe9209c8ebbd2316290e9eb0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 15:32:26 -0400 Subject: [PATCH 021/852] stub out sat channel scan --- MediaBrowser.Api/LiveTv/LiveTvService.cs | 16 ++++++++++++++- .../LiveTv/ILiveTvManager.cs | 2 ++ .../LiveTv/LiveTvManager.cs | 7 +++++++ .../LiveTv/TunerHosts/SatIp/ChannelScan.cs | 20 +++++++++++++++++++ ...MediaBrowser.Server.Implementations.csproj | 1 + 5 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs index 5b7bc78a8..ebcf8fbea 100644 --- a/MediaBrowser.Api/LiveTv/LiveTvService.cs +++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs @@ -482,7 +482,14 @@ namespace MediaBrowser.Api.LiveTv [Authenticated(AllowBeforeStartupWizard = true)] public class GetSatIniMappings : IReturn> { - + + } + + [Route("/LiveTv/TunerHosts/Satip/ChannelScan", "GET", Summary = "Scans for available channels")] + [Authenticated(AllowBeforeStartupWizard = true)] + public class GetSatChannnelScanResult : TunerHostInfo + { + } public class LiveTvService : BaseApiService @@ -504,6 +511,13 @@ namespace MediaBrowser.Api.LiveTv _dtoService = dtoService; } + public async Task Get(GetSatChannnelScanResult request) + { + var result = await _liveTvManager.GetSatChannelScanResult(request, CancellationToken.None).ConfigureAwait(false); + + return ToOptimizedResult(result); + } + public async Task Get(GetLiveTvRegistrationInfo request) { var result = await _liveTvManager.GetRegistrationInfo(request.ChannelId, request.ProgramId, request.Feature).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 56b7a307a..a4bd32fff 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -383,5 +383,7 @@ namespace MediaBrowser.Controller.LiveTv /// /// List<NameValuePair>. List GetSatIniMappings(); + + Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 3849f44ab..87c2e8394 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2480,5 +2480,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } } + + public async Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken) + { + var result = await new TunerHosts.SatIp.ChannelScan().Scan(info, cancellationToken).ConfigureAwait(false); + + return result.Select(i => new ChannelInfo()).ToList(); + } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs new file mode 100644 index 000000000..2277f8f63 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.LiveTv; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp +{ + public class ChannelScan + { + public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) + { + return new List(); + } + } + + public class SatChannel + { + // TODO: Add properties + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 14d275505..b5ec4649e 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -247,6 +247,7 @@ + From d8cf48ae41409ccde5578960186e2d5cc46f9dcd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 15:41:52 -0400 Subject: [PATCH 022/852] update satip page --- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 71f87ac3a..660f30cc9 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -37,6 +37,10 @@ namespace MediaBrowser.Model.LiveTv public string FriendlyName { get; set; } public int Tuners { get; set; } public string DiseqC { get; set; } + public string SourceA { get; set; } + public string SourceB { get; set; } + public string SourceC { get; set; } + public string SourceD { get; set; } public int DataVersion { get; set; } From edd9ad6d63aaa320e97cd48b75ac544ed7c8b361 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 16:01:27 -0400 Subject: [PATCH 023/852] add rtsp classes --- .../TunerHosts/SatIp/Rtsp/RtspMethod.cs | 88 ++++++ .../TunerHosts/SatIp/Rtsp/RtspRequest.cs | 141 ++++++++++ .../TunerHosts/SatIp/Rtsp/RtspResponse.cs | 150 +++++++++++ .../TunerHosts/SatIp/Rtsp/RtspStatusCode.cs | 251 ++++++++++++++++++ .../LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs | 1 - ...MediaBrowser.Server.Implementations.csproj | 4 + 6 files changed, 634 insertions(+), 1 deletion(-) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs new file mode 100644 index 000000000..fae7c4bfc --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs @@ -0,0 +1,88 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System.Collections.Generic; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// Standard RTSP request methods. + /// + public sealed class RtspMethod + { + public override int GetHashCode() + { + return (_name != null ? _name.GetHashCode() : 0); + } + + private readonly string _name; + private static readonly IDictionary _values = new Dictionary(); + + public static readonly RtspMethod Describe = new RtspMethod("DESCRIBE"); + public static readonly RtspMethod Announce = new RtspMethod("ANNOUNCE"); + public static readonly RtspMethod GetParameter = new RtspMethod("GET_PARAMETER"); + public static readonly RtspMethod Options = new RtspMethod("OPTIONS"); + public static readonly RtspMethod Pause = new RtspMethod("PAUSE"); + public static readonly RtspMethod Play = new RtspMethod("PLAY"); + public static readonly RtspMethod Record = new RtspMethod("RECORD"); + public static readonly RtspMethod Redirect = new RtspMethod("REDIRECT"); + public static readonly RtspMethod Setup = new RtspMethod("SETUP"); + public static readonly RtspMethod SetParameter = new RtspMethod("SET_PARAMETER"); + public static readonly RtspMethod Teardown = new RtspMethod("TEARDOWN"); + + private RtspMethod(string name) + { + _name = name; + _values.Add(name, this); + } + + public override string ToString() + { + return _name; + } + + public override bool Equals(object obj) + { + var method = obj as RtspMethod; + if (method != null && this == method) + { + return true; + } + return false; + } + + public static ICollection Values + { + get { return _values.Values; } + } + + public static explicit operator RtspMethod(string name) + { + RtspMethod value; + if (!_values.TryGetValue(name, out value)) + { + return null; + } + return value; + } + + public static implicit operator string(RtspMethod method) + { + return method._name; + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs new file mode 100644 index 000000000..d8462b223 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs @@ -0,0 +1,141 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System.Collections.Generic; +using System.Text; + + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// A simple class that can be used to serialise RTSP requests. + /// + public class RtspRequest + { + private readonly RtspMethod _method; + private readonly string _uri; + private readonly int _majorVersion; + private readonly int _minorVersion; + private IDictionary _headers = new Dictionary(); + private string _body = string.Empty; + + /// + /// Initialise a new instance of the class. + /// + /// The request method. + /// The request URI + /// The major version number. + /// The minor version number. + public RtspRequest(RtspMethod method, string uri, int majorVersion, int minorVersion) + { + _method = method; + _uri = uri; + _majorVersion = majorVersion; + _minorVersion = minorVersion; + } + + /// + /// Get the request method. + /// + public RtspMethod Method + { + get + { + return _method; + } + } + + /// + /// Get the request URI. + /// + public string Uri + { + get + { + return _uri; + } + } + + /// + /// Get the request major version number. + /// + public int MajorVersion + { + get + { + return _majorVersion; + } + } + + /// + /// Get the request minor version number. + /// + public int MinorVersion + { + get + { + return _minorVersion; + } + } + + /// + /// Get or set the request headers. + /// + public IDictionary Headers + { + get + { + return _headers; + } + set + { + _headers = value; + } + } + + /// + /// Get or set the request body. + /// + public string Body + { + get + { + return _body; + } + set + { + _body = value; + } + } + + /// + /// Serialise this request. + /// + /// raw request bytes + public byte[] Serialise() + { + var request = new StringBuilder(); + request.AppendFormat("{0} {1} RTSP/{2}.{3}\r\n", _method, _uri, _majorVersion, _minorVersion); + foreach (var header in _headers) + { + request.AppendFormat("{0}: {1}\r\n", header.Key, header.Value); + } + request.AppendFormat("\r\n{0}", _body); + return Encoding.UTF8.GetBytes(request.ToString()); + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs new file mode 100644 index 000000000..0bf80012d --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs @@ -0,0 +1,150 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; + + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// A simple class that can be used to deserialise RTSP responses. + /// + public class RtspResponse + { + private static readonly Regex RegexStatusLine = new Regex(@"RTSP/(\d+)\.(\d+)\s+(\d+)\s+([^.]+?)\r\n(.*)", RegexOptions.Singleline); + + private int _majorVersion = 1; + private int _minorVersion; + private RtspStatusCode _statusCode; + private string _reasonPhrase; + private IDictionary _headers; + private string _body; + + /// + /// Initialise a new instance of the class. + /// + private RtspResponse() + { + } + + /// + /// Get the response major version number. + /// + public int MajorVersion + { + get + { + return _majorVersion; + } + } + + /// + /// Get the response minor version number. + /// + public int MinorVersion + { + get + { + return _minorVersion; + } + } + + /// + /// Get the response status code. + /// + public RtspStatusCode StatusCode + { + get + { + return _statusCode; + } + } + + /// + /// Get the response reason phrase. + /// + public string ReasonPhrase + { + get + { + return _reasonPhrase; + } + } + + /// + /// Get the response headers. + /// + public IDictionary Headers + { + get + { + return _headers; + } + } + + /// + /// Get the response body. + /// + public string Body + { + get + { + return _body; + } + set + { + _body = value; + } + } + + /// + /// Deserialise/parse an RTSP response. + /// + /// The raw response bytes. + /// The number of valid bytes in the response. + /// a response object + public static RtspResponse Deserialise(byte[] responseBytes, int responseByteCount) + { + var response = new RtspResponse(); + var responseString = Encoding.UTF8.GetString(responseBytes, 0, responseByteCount); + + var m = RegexStatusLine.Match(responseString); + if (m.Success) + { + response._majorVersion = int.Parse(m.Groups[1].Captures[0].Value); + response._minorVersion = int.Parse(m.Groups[2].Captures[0].Value); + response._statusCode = (RtspStatusCode)int.Parse(m.Groups[3].Captures[0].Value); + response._reasonPhrase = m.Groups[4].Captures[0].Value; + responseString = m.Groups[5].Captures[0].Value; + } + + var sections = responseString.Split(new[] { "\r\n\r\n" }, StringSplitOptions.None); + response._body = sections[1]; + var headers = sections[0].Split(new[] { "\r\n" }, StringSplitOptions.None); + response._headers = new Dictionary(); + foreach (var headerInfo in headers.Select(header => header.Split(':'))) + { + response._headers.Add(headerInfo[0], headerInfo[1].Trim()); + } + return response; + } + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs new file mode 100644 index 000000000..8786314ed --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs @@ -0,0 +1,251 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System.ComponentModel; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + /// + /// Standard RTSP status codes. + /// + public enum RtspStatusCode + { + /// + /// 100 continue + /// + Continue = 100, + + /// + /// 200 OK + /// + [Description("Okay")] + Ok = 200, + /// + /// 201 created + /// + Created = 201, + + /// + /// 250 low on storage space + /// + [Description("Low On Storage Space")] + LowOnStorageSpace = 250, + + /// + /// 300 multiple choices + /// + [Description("Multiple Choices")] + MultipleChoices = 300, + /// + /// 301 moved permanently + /// + [Description("Moved Permanently")] + MovedPermanently = 301, + /// + /// 302 moved temporarily + /// + [Description("Moved Temporarily")] + MovedTemporarily = 302, + /// + /// 303 see other + /// + [Description("See Other")] + SeeOther = 303, + /// + /// 304 not modified + /// + [Description("Not Modified")] + NotModified = 304, + /// + /// 305 use proxy + /// + [Description("Use Proxy")] + UseProxy = 305, + + /// + /// 400 bad request + /// + [Description("Bad Request")] + BadRequest = 400, + /// + /// 401 unauthorised + /// + Unauthorised = 401, + /// + /// 402 payment required + /// + [Description("Payment Required")] + PaymentRequired = 402, + /// + /// 403 forbidden + /// + Forbidden = 403, + /// + /// 404 not found + /// + [Description("Not Found")] + NotFound = 404, + /// + /// 405 method not allowed + /// + [Description("Method Not Allowed")] + MethodNotAllowed = 405, + /// + /// 406 not acceptable + /// + [Description("Not Acceptable")] + NotAcceptable = 406, + /// + /// 407 proxy authentication required + /// + [Description("Proxy Authentication Required")] + ProxyAuthenticationRequred = 407, + /// + /// 408 request time-out + /// + [Description("Request Time-Out")] + RequestTimeOut = 408, + + /// + /// 410 gone + /// + Gone = 410, + /// + /// 411 length required + /// + [Description("Length Required")] + LengthRequired = 411, + /// + /// 412 precondition failed + /// + [Description("Precondition Failed")] + PreconditionFailed = 412, + /// + /// 413 request entity too large + /// + [Description("Request Entity Too Large")] + RequestEntityTooLarge = 413, + /// + /// 414 request URI too large + /// + [Description("Request URI Too Large")] + RequestUriTooLarge = 414, + /// + /// 415 unsupported media type + /// + [Description("Unsupported Media Type")] + UnsupportedMediaType = 415, + + /// + /// 451 parameter not understood + /// + [Description("Parameter Not Understood")] + ParameterNotUnderstood = 451, + /// + /// 452 conference not found + /// + [Description("Conference Not Found")] + ConferenceNotFound = 452, + /// + /// 453 not enough bandwidth + /// + [Description("Not Enough Bandwidth")] + NotEnoughBandwidth = 453, + /// + /// 454 session not found + /// + [Description("Session Not Found")] + SessionNotFound = 454, + /// + /// 455 method not valid in this state + /// + [Description("Method Not Valid In This State")] + MethodNotValidInThisState = 455, + /// + /// 456 header field not valid for this resource + /// + [Description("Header Field Not Valid For This Resource")] + HeaderFieldNotValidForThisResource = 456, + /// + /// 457 invalid range + /// + [Description("Invalid Range")] + InvalidRange = 457, + /// + /// 458 parameter is read-only + /// + [Description("Parameter Is Read-Only")] + ParameterIsReadOnly = 458, + /// + /// 459 aggregate operation not allowed + /// + [Description("Aggregate Operation Not Allowed")] + AggregateOperationNotAllowed = 459, + /// + /// 460 only aggregate operation allowed + /// + [Description("Only Aggregate Operation Allowed")] + OnlyAggregateOperationAllowed = 460, + /// + /// 461 unsupported transport + /// + [Description("Unsupported Transport")] + UnsupportedTransport = 461, + /// + /// 462 destination unreachable + /// + [Description("Destination Unreachable")] + DestinationUnreachable = 462, + + /// + /// 500 internal server error + /// + [Description("Internal Server Error")] + InternalServerError = 500, + /// + /// 501 not implemented + /// + [Description("Not Implemented")] + NotImplemented = 501, + /// + /// 502 bad gateway + /// + [Description("Bad Gateway")] + BadGateway = 502, + /// + /// 503 service unavailable + /// + [Description("Service Unavailable")] + ServiceUnavailable = 503, + /// + /// 504 gateway time-out + /// + [Description("Gateway Time-Out")] + GatewayTimeOut = 504, + /// + /// 505 RTSP version not supported + /// + [Description("RTSP Version Not Supported")] + RtspVersionNotSupported = 505, + + /// + /// 551 option not supported + /// + [Description("Option Not Supported")] + OptionNotSupported = 551 + } +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs index 413ce4549..d0a55966f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpDiscovery.cs @@ -235,7 +235,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp } } - var result = new SatIpTunerHostInfo { Url = url, diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index b5ec4649e..02f7596e0 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -248,6 +248,10 @@ + + + + From fa841e86104cb05f59b4caec686b69dba9284084 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 16:04:07 -0400 Subject: [PATCH 024/852] add RtspSession --- .../TunerHosts/SatIp/Rtsp/RtspSession.cs | 681 ++++++++++++++++++ ...MediaBrowser.Server.Implementations.csproj | 1 + 2 files changed, 682 insertions(+) create mode 100644 MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs new file mode 100644 index 000000000..e76fb7175 --- /dev/null +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs @@ -0,0 +1,681 @@ +/* + Copyright (C) <2007-2016> + + SatIp.RtspSample is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + SatIp.RtspSample is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with SatIp.RtspSample. If not, see . +*/ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Net; +using System.Net.NetworkInformation; +using System.Net.Sockets; +using System.Text.RegularExpressions; +using MediaBrowser.Model.Logging; + +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +{ + public class RtspSession : IDisposable + { + #region Private Fields + private static readonly Regex RegexRtspSessionHeader = new Regex(@"\s*([^\s;]+)(;timeout=(\d+))?"); + private const int DefaultRtspSessionTimeout = 30; // unit = s + private static readonly Regex RegexDescribeResponseSignalInfo = new Regex(@";tuner=\d+,(\d+),(\d+),(\d+),", RegexOptions.Singleline | RegexOptions.IgnoreCase); + private string _address; + private string _rtspSessionId; + + public string RtspSessionId + { + get { return _rtspSessionId; } + set { _rtspSessionId = value; } + } + private int _rtspSessionTimeToLive = 0; + private string _rtspStreamId; + private int _clientRtpPort; + private int _clientRtcpPort; + private int _serverRtpPort; + private int _serverRtcpPort; + private int _rtpPort; + private int _rtcpPort; + private string _rtspStreamUrl; + private string _destination; + private string _source; + private string _transport; + private int _signalLevel; + private int _signalQuality; + private Socket _rtspSocket; + private int _rtspSequenceNum = 1; + private bool _disposed = false; + private ILogger _logger; + #endregion + + #region Constructor + + public RtspSession(string address, ILogger logger) + { + _address = address; + _logger = logger; + } + ~RtspSession() + { + Dispose(false); + } + #endregion + + #region Properties + + #region Rtsp + + public string RtspStreamId + { + get { return _rtspStreamId; } + set { if (_rtspStreamId != value) { _rtspStreamId = value; OnPropertyChanged("RtspStreamId"); } } + } + public string RtspStreamUrl + { + get { return _rtspStreamUrl; } + set { if (_rtspStreamUrl != value) { _rtspStreamUrl = value; OnPropertyChanged("RtspStreamUrl"); } } + } + + public int RtspSessionTimeToLive + { + get + { + if (_rtspSessionTimeToLive == 0) + _rtspSessionTimeToLive = DefaultRtspSessionTimeout; + return _rtspSessionTimeToLive * 1000 - 20; + } + set { if (_rtspSessionTimeToLive != value) { _rtspSessionTimeToLive = value; OnPropertyChanged("RtspSessionTimeToLive"); } } + } + + #endregion + + #region Rtp Rtcp + + /// + /// The LocalEndPoint Address + /// + public string Destination + { + get + { + if (string.IsNullOrEmpty(_destination)) + { + var result = ""; + var host = Dns.GetHostName(); + var hostentry = Dns.GetHostEntry(host); + foreach (var ip in hostentry.AddressList.Where(ip => ip.AddressFamily == AddressFamily.InterNetwork)) + { + result = ip.ToString(); + } + + _destination = result; + } + return _destination; + } + set + { + if (_destination != value) + { + _destination = value; + OnPropertyChanged("Destination"); + } + } + } + + /// + /// The RemoteEndPoint Address + /// + public string Source + { + get { return _source; } + set + { + if (_source != value) + { + _source = value; + OnPropertyChanged("Source"); + } + } + } + + /// + /// The Media Data Delivery RemoteEndPoint Port if we use Unicast + /// + public int ServerRtpPort + { + get + { + return _serverRtpPort; + } + set { if (_serverRtpPort != value) { _serverRtpPort = value; OnPropertyChanged("ServerRtpPort"); } } + } + + /// + /// The Media Metadata Delivery RemoteEndPoint Port if we use Unicast + /// + public int ServerRtcpPort + { + get { return _serverRtcpPort; } + set { if (_serverRtcpPort != value) { _serverRtcpPort = value; OnPropertyChanged("ServerRtcpPort"); } } + } + + /// + /// The Media Data Delivery LocalEndPoint Port if we use Unicast + /// + public int ClientRtpPort + { + get { return _clientRtpPort; } + set { if (_clientRtpPort != value) { _clientRtpPort = value; OnPropertyChanged("ClientRtpPort"); } } + } + + /// + /// The Media Metadata Delivery LocalEndPoint Port if we use Unicast + /// + public int ClientRtcpPort + { + get { return _clientRtcpPort; } + set { if (_clientRtcpPort != value) { _clientRtcpPort = value; OnPropertyChanged("ClientRtcpPort"); } } + } + + /// + /// The Media Data Delivery RemoteEndPoint Port if we use Multicast + /// + public int RtpPort + { + get { return _rtpPort; } + set { if (_rtpPort != value) { _rtpPort = value; OnPropertyChanged("RtpPort"); } } + } + + /// + /// The Media Meta Delivery RemoteEndPoint Port if we use Multicast + /// + public int RtcpPort + { + get { return _rtcpPort; } + set { if (_rtcpPort != value) { _rtcpPort = value; OnPropertyChanged("RtcpPort"); } } + } + + #endregion + + public string Transport + { + get + { + if (string.IsNullOrEmpty(_transport)) + { + _transport = "unicast"; + } + return _transport; + } + set + { + if (_transport != value) + { + _transport = value; + OnPropertyChanged("Transport"); + } + } + } + public int SignalLevel + { + get { return _signalLevel; } + set { if (_signalLevel != value) { _signalLevel = value; OnPropertyChanged("SignalLevel"); } } + } + public int SignalQuality + { + get { return _signalQuality; } + set { if (_signalQuality != value) { _signalQuality = value; OnPropertyChanged("SignalQuality"); } } + } + + #endregion + + #region Private Methods + + private void ProcessSessionHeader(string sessionHeader, string response) + { + if (!string.IsNullOrEmpty(sessionHeader)) + { + var m = RegexRtspSessionHeader.Match(sessionHeader); + if (!m.Success) + { + _logger.Error("Failed to tune, RTSP {0} response session header {1} format not recognised", response, sessionHeader); + } + _rtspSessionId = m.Groups[1].Captures[0].Value; + _rtspSessionTimeToLive = m.Groups[3].Captures.Count == 1 ? int.Parse(m.Groups[3].Captures[0].Value) : DefaultRtspSessionTimeout; + } + } + private void ProcessTransportHeader(string transportHeader) + { + if (!string.IsNullOrEmpty(transportHeader)) + { + var transports = transportHeader.Split(','); + foreach (var transport in transports) + { + if (transport.Trim().StartsWith("RTP/AVP")) + { + var sections = transport.Split(';'); + foreach (var section in sections) + { + var parts = section.Split('='); + if (parts[0].Equals("server_port")) + { + var ports = parts[1].Split('-'); + _serverRtpPort = int.Parse(ports[0]); + _serverRtcpPort = int.Parse(ports[1]); + } + else if (parts[0].Equals("destination")) + { + _destination = parts[1]; + } + else if (parts[0].Equals("port")) + { + var ports = parts[1].Split('-'); + _rtpPort = int.Parse(ports[0]); + _rtcpPort = int.Parse(ports[1]); + } + else if (parts[0].Equals("ttl")) + { + _rtspSessionTimeToLive = int.Parse(parts[1]); + } + else if (parts[0].Equals("source")) + { + _source = parts[1]; + } + else if (parts[0].Equals("client_port")) + { + var ports = parts[1].Split('-'); + var rtp = int.Parse(ports[0]); + var rtcp = int.Parse(ports[1]); + //if (!rtp.Equals(_rtpPort)) + //{ + // Logger.Error("SAT>IP base: server specified RTP client port {0} instead of {1}", rtp, _rtpPort); + //} + //if (!rtcp.Equals(_rtcpPort)) + //{ + // Logger.Error("SAT>IP base: server specified RTCP client port {0} instead of {1}", rtcp, _rtcpPort); + //} + _rtpPort = rtp; + _rtcpPort = rtcp; + } + } + } + } + } + } + private void Connect() + { + _rtspSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + var ip = IPAddress.Parse(_address); + var rtspEndpoint = new IPEndPoint(ip, 554); + _rtspSocket.Connect(rtspEndpoint); + } + private void Disconnect() + { + if (_rtspSocket != null && _rtspSocket.Connected) + { + _rtspSocket.Shutdown(SocketShutdown.Both); + _rtspSocket.Close(); + } + } + private void SendRequest(RtspRequest request) + { + if (_rtspSocket == null) + { + Connect(); + } + try + { + request.Headers.Add("CSeq", _rtspSequenceNum.ToString()); + _rtspSequenceNum++; + byte[] requestBytes = request.Serialise(); + if (_rtspSocket != null) + { + var requestBytesCount = _rtspSocket.Send(requestBytes, requestBytes.Length, SocketFlags.None); + if (requestBytesCount < 1) + { + + } + } + } + catch (Exception e) + { + _logger.Error(e.Message); + } + } + private void ReceiveResponse(out RtspResponse response) + { + response = null; + var responseBytesCount = 0; + byte[] responseBytes = new byte[1024]; + try + { + responseBytesCount = _rtspSocket.Receive(responseBytes, responseBytes.Length, SocketFlags.None); + response = RtspResponse.Deserialise(responseBytes, responseBytesCount); + string contentLengthString; + int contentLength = 0; + if (response.Headers.TryGetValue("Content-Length", out contentLengthString)) + { + contentLength = int.Parse(contentLengthString); + if ((string.IsNullOrEmpty(response.Body) && contentLength > 0) || response.Body.Length < contentLength) + { + if (response.Body == null) + { + response.Body = string.Empty; + } + while (responseBytesCount > 0 && response.Body.Length < contentLength) + { + responseBytesCount = _rtspSocket.Receive(responseBytes, responseBytes.Length, SocketFlags.None); + response.Body += System.Text.Encoding.UTF8.GetString(responseBytes, 0, responseBytesCount); + } + } + } + } + catch (SocketException) + { + } + } + + #endregion + + #region Public Methods + + public RtspStatusCode Setup(string query, string transporttype) + { + + RtspRequest request; + RtspResponse response; + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + if ((_rtspSocket == null)) + { + Connect(); + } + if (string.IsNullOrEmpty(_rtspSessionId)) + { + request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _address, 554, query), 1, 0); + switch (transporttype) + { + case "multicast": + request.Headers.Add("Transport", string.Format("RTP/AVP;multicast")); + break; + case "unicast": + var activeTcpConnections = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpConnections(); + var usedPorts = new HashSet(); + foreach (var connection in activeTcpConnections) + { + usedPorts.Add(connection.LocalEndPoint.Port); + } + for (var port = 40000; port <= 65534; port += 2) + { + if (!usedPorts.Contains(port) && !usedPorts.Contains(port + 1)) + { + + _clientRtpPort = port; + _clientRtcpPort = port + 1; + break; + } + } + request.Headers.Add("Transport", string.Format("RTP/AVP;unicast;client_port={0}-{1}", _clientRtpPort, _clientRtcpPort)); + break; + } + } + else + { + request = new RtspRequest(RtspMethod.Setup, string.Format("rtsp://{0}:{1}/?{2}", _address, 554, query), 1, 0); + switch (transporttype) + { + case "multicast": + request.Headers.Add("Transport", string.Format("RTP/AVP;multicast")); + break; + case "unicast": + request.Headers.Add("Transport", string.Format("RTP/AVP;unicast;client_port={0}-{1}", _clientRtpPort, _clientRtcpPort)); + break; + } + + } + SendRequest(request); + ReceiveResponse(out response); + + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + if (!response.Headers.TryGetValue("com.ses.streamID", out _rtspStreamId)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Stream ID header in RTSP SETUP response")); + } + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Session header in RTSP SETUP response")); + } + ProcessSessionHeader(sessionHeader, "Setup"); + string transportHeader; + if (!response.Headers.TryGetValue("Transport", out transportHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Transport header in RTSP SETUP response")); + } + ProcessTransportHeader(transportHeader); + return response.StatusCode; + } + + public RtspStatusCode Play(string query) + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspResponse response; + string data; + if (string.IsNullOrEmpty(query)) + { + data = string.Format("rtsp://{0}:{1}/stream={2}", _address, + 554, _rtspStreamId); + } + else + { + data = string.Format("rtsp://{0}:{1}/stream={2}?{3}", _address, + 554, _rtspStreamId, query); + } + var request = new RtspRequest(RtspMethod.Play, data, 1, 0); + request.Headers.Add("Session", _rtspSessionId); + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + //Logger.Info("RtspSession-Play : \r\n {0}", response); + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Session header in RTSP Play response")); + } + ProcessSessionHeader(sessionHeader, "Play"); + string rtpinfoHeader; + if (!response.Headers.TryGetValue("RTP-Info", out rtpinfoHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate Rtp-Info header in RTSP Play response")); + } + return response.StatusCode; + } + + public RtspStatusCode Options() + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspRequest request; + RtspResponse response; + + + if (string.IsNullOrEmpty(_rtspSessionId)) + { + request = new RtspRequest(RtspMethod.Options, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); + } + else + { + request = new RtspRequest(RtspMethod.Options, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); + request.Headers.Add("Session", _rtspSessionId); + } + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP SETUP status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + //Logger.Info("RtspSession-Options : \r\n {0}", response); + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate session header in RTSP Options response")); + } + ProcessSessionHeader(sessionHeader, "Options"); + string optionsHeader; + if (!response.Headers.TryGetValue("Public", out optionsHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to Options header in RTSP Options response")); + } + return response.StatusCode; + } + + public RtspStatusCode Describe(out int level, out int quality) + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspRequest request; + RtspResponse response; + level = 0; + quality = 0; + + if (string.IsNullOrEmpty(_rtspSessionId)) + { + request = new RtspRequest(RtspMethod.Describe, string.Format("rtsp://{0}:{1}/", _address, 554), 1, 0); + request.Headers.Add("Accept", "application/sdp"); + + } + else + { + request = new RtspRequest(RtspMethod.Describe, string.Format("rtsp://{0}:{1}/stream={2}", _address, 554, _rtspStreamId), 1, 0); + request.Headers.Add("Accept", "application/sdp"); + request.Headers.Add("Session", _rtspSessionId); + } + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP Describe status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + //Logger.Info("RtspSession-Describe : \r\n {0}", response); + string sessionHeader; + if (!response.Headers.TryGetValue("Session", out sessionHeader)) + { + _logger.Error(string.Format("Failed to tune, not able to locate session header in RTSP Describe response")); + } + ProcessSessionHeader(sessionHeader, "Describe"); + var m = RegexDescribeResponseSignalInfo.Match(response.Body); + if (m.Success) + { + + //isSignalLocked = m.Groups[2].Captures[0].Value.Equals("1"); + level = int.Parse(m.Groups[1].Captures[0].Value) * 100 / 255; // level: 0..255 => 0..100 + quality = int.Parse(m.Groups[3].Captures[0].Value) * 100 / 15; // quality: 0..15 => 0..100 + + } + /* + v=0 + o=- 1378633020884883 1 IN IP4 192.168.2.108 + s=SatIPServer:1 4 + t=0 0 + a=tool:idl4k + m=video 52780 RTP/AVP 33 + c=IN IP4 0.0.0.0 + b=AS:5000 + a=control:stream=4 + a=fmtp:33 ver=1.0;tuner=1,0,0,0,12344,h,dvbs2,,off,,22000,34;pids=0,100,101,102,103,106 + =sendonly + */ + + + return response.StatusCode; + } + + public RtspStatusCode TearDown() + { + if ((_rtspSocket == null)) + { + Connect(); + } + //_rtspClient = new RtspClient(_rtspDevice.ServerAddress); + RtspResponse response; + + var request = new RtspRequest(RtspMethod.Teardown, string.Format("rtsp://{0}:{1}/stream={2}", _address, 554, _rtspStreamId), 1, 0); + request.Headers.Add("Session", _rtspSessionId); + SendRequest(request); + ReceiveResponse(out response); + //if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) + //{ + // Logger.Error("Failed to tune, non-OK RTSP Teardown status code {0} {1}", response.StatusCode, response.ReasonPhrase); + //} + return response.StatusCode; + } + + #endregion + + #region Public Events + + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + + #region Protected Methods + + protected void OnPropertyChanged(string name) + { + //var handler = PropertyChanged; + //if (handler != null) + //{ + // handler(this, new PropertyChangedEventArgs(name)); + //} + } + + #endregion + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this);//Disconnect(); + } + + protected virtual void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + TearDown(); + Disconnect(); + } + } + _disposed = true; + } + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 02f7596e0..ae39d3eb9 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -251,6 +251,7 @@ + From 31e98681fa980bc17fbe8ff4ae717b21f1b25f8f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 17:14:03 -0400 Subject: [PATCH 025/852] update sort names --- MediaBrowser.Controller/Entities/BaseItem.cs | 18 ++++++++++++------ MediaBrowser.Controller/Entities/TV/Episode.cs | 2 +- .../Persistence/CleanDatabaseScheduledTask.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 2 +- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index bf25da2ac..74ff187c5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -494,7 +494,18 @@ namespace MediaBrowser.Controller.Entities { get { - return _sortName ?? (_sortName = CreateSortName()); + if (_sortName == null) + { + if (!string.IsNullOrWhiteSpace(ForcedSortName)) + { + _sortName = ModifySortChunks(ForcedSortName); + } + else + { + _sortName = CreateSortName(); + } + } + return _sortName; } set { @@ -529,11 +540,6 @@ namespace MediaBrowser.Controller.Entities /// System.String. protected virtual string CreateSortName() { - if (!string.IsNullOrWhiteSpace(ForcedSortName)) - { - return ModifySortChunks(ForcedSortName).ToLower(); - } - if (Name == null) return null; //some items may not have name filled in properly if (!EnableAlphaNumericSorting) diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 88dae3c7c..d016392e8 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -175,7 +175,7 @@ namespace MediaBrowser.Controller.Entities.TV /// System.String. protected override string CreateSortName() { - return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000-") : "") + return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "") + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; } diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 3c8a0ffeb..38cca3c35 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly ILocalizationManager _localization; private readonly ITaskManager _taskManager; - public const int MigrationVersion = 20; + public const int MigrationVersion = 22; public static bool EnableUnavailableMessage = false; public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IHttpServer httpServer, ILocalizationManager localization, ITaskManager taskManager) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index de914b773..308645d02 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 56; + private const int LatestSchemaVersion = 57; /// /// Initializes a new instance of the class. From 1381447bda7982aa0fd8aac30fa29fc42dc437e3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 19:26:13 -0400 Subject: [PATCH 026/852] update sat/ip --- .../LiveTv/LiveTvManager.cs | 13 +-- .../LiveTv/TunerHosts/SatIp/ChannelScan.cs | 95 ++++++++++++++++++- .../TunerHosts/SatIp/Rtsp/RtspMethod.cs | 2 +- .../TunerHosts/SatIp/Rtsp/RtspRequest.cs | 3 +- .../TunerHosts/SatIp/Rtsp/RtspResponse.cs | 3 +- .../TunerHosts/SatIp/Rtsp/RtspSession.cs | 11 ++- .../TunerHosts/SatIp/Rtsp/RtspStatusCode.cs | 2 +- .../LiveTv/TunerHosts/SatIp/SatIpHost.cs | 3 +- 8 files changed, 114 insertions(+), 18 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 87c2e8394..d40f2a141 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -2450,7 +2450,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public List GetSatIniMappings() { - var names = GetType().Assembly.GetManifestResourceNames().Where(i => i.IndexOf("SatIp.ini.satellite", StringComparison.OrdinalIgnoreCase) != -1).ToList(); + var names = GetType().Assembly.GetManifestResourceNames().Where(i => i.IndexOf("SatIp.ini", StringComparison.OrdinalIgnoreCase) != -1).ToList(); return names.Select(GetSatIniMappings).Where(i => i != null).DistinctBy(i => i.Value.Split('|')[0]).ToList(); } @@ -2472,20 +2472,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv return null; } + var srch = "SatIp.ini."; + var filename = Path.GetFileName(resource); + return new NameValuePair { Name = satType1 + " " + satType2, - Value = satType2 + "|" + Path.GetFileName(resource) + Value = satType2 + "|" + filename.Substring(filename.IndexOf(srch) + srch.Length) }; } } } - public async Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken) + public Task> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken) { - var result = await new TunerHosts.SatIp.ChannelScan().Scan(info, cancellationToken).ConfigureAwait(false); - - return result.Select(i => new ChannelInfo()).ToList(); + return new TunerHosts.SatIp.ChannelScan(_logger).Scan(info, cancellationToken); } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs index 2277f8f63..20737df50 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs @@ -1,15 +1,104 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; +using IniParser; +using IniParser.Model; +using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.LiveTv; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp; namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp { public class ChannelScan { - public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) + private readonly ILogger _logger; + + public ChannelScan(ILogger logger) { - return new List(); + _logger = logger; + } + + public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) + { + var timedToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(timedToken.Token, cancellationToken); + + using (var rtspSession = new RtspSession(info.Url, _logger)) + { + var ini = info.SourceA.Split('|')[1]; + var resource = GetType().Assembly.GetManifestResourceNames().FirstOrDefault(i => i.EndsWith(ini, StringComparison.OrdinalIgnoreCase)); + + _logger.Info("Opening ini file {0}", resource); + using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) + { + using (var reader = new StreamReader(stream)) + { + var parser = new StreamIniDataParser(); + var data = parser.ReadData(reader); + + var count = GetInt(data, "DVB", "0", 0); + + var index = 1; + var source = "1"; + + while (!linkedToken.IsCancellationRequested) + { + float percent = count == 0 ? 0 : (float)(index) / count; + percent = Math.Max(percent * 100, 100); + + //SetControlPropertyThreadSafe(pgbSearchResult, "Value", (int)percent); + var strArray = data["DVB"][index.ToString(CultureInfo.InvariantCulture)].Split(','); + + string tuning; + if (strArray[4] == "S2") + { + tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs2&mtype={5}&plts=on&ro=0.35&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2].ToLower(), strArray[3], strArray[5].ToLower()); + } + else + { + tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs&mtype={5}&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2], strArray[3], strArray[5].ToLower()); + } + + if (string.IsNullOrEmpty(rtspSession.RtspSessionId)) + { + rtspSession.Setup(tuning, "unicast"); + + rtspSession.Play(string.Empty); + } + else + { + rtspSession.Play(tuning); + } + + int signallevel; + int signalQuality; + rtspSession.Describe(out signallevel, out signalQuality); + + await Task.Delay(500).ConfigureAwait(false); + index++; + } + } + } + } + + return new List(); + } + + private int GetInt(IniData data, string s1, string s2, int defaultValue) + { + var value = data[s1][s2]; + int numericValue; + if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out numericValue)) + { + return numericValue; + } + + return defaultValue; } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs index fae7c4bfc..5f286f1db 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspMethod.cs @@ -17,7 +17,7 @@ using System.Collections.Generic; -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// Standard RTSP request methods. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs index d8462b223..600eda02d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspRequest.cs @@ -18,8 +18,7 @@ using System.Collections.Generic; using System.Text; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// A simple class that can be used to serialise RTSP requests. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs index 0bf80012d..97290623b 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspResponse.cs @@ -21,8 +21,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; - -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// A simple class that can be used to deserialise RTSP responses. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs index e76fb7175..71b3f8a18 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspSession.cs @@ -25,7 +25,7 @@ using System.Net.Sockets; using System.Text.RegularExpressions; using MediaBrowser.Model.Logging; -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { public class RtspSession : IDisposable { @@ -58,15 +58,22 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp private Socket _rtspSocket; private int _rtspSequenceNum = 1; private bool _disposed = false; - private ILogger _logger; + private readonly ILogger _logger; #endregion #region Constructor public RtspSession(string address, ILogger logger) { + if (string.IsNullOrWhiteSpace(address)) + { + throw new ArgumentNullException("address"); + } + _address = address; _logger = logger; + + _logger.Info("Creating RtspSession with url {0}", address); } ~RtspSession() { diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs index 8786314ed..6d6d50623 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/Rtsp/RtspStatusCode.cs @@ -17,7 +17,7 @@ using System.ComponentModel; -namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.SatIp +namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp.Rtsp { /// /// Standard RTSP status codes. diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs index 46a2a8524..ffd85fd18 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs @@ -40,7 +40,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return await new M3uParser(Logger, _fileSystem, _httpClient).Parse(tuner.M3UUrl, ChannelIdPrefix, tuner.Id, cancellationToken).ConfigureAwait(false); } - return new List(); + var channels = await new ChannelScan(Logger).Scan(tuner, cancellationToken).ConfigureAwait(false); + return channels; } public static string DeviceType From 0694dba1e0ac86e9f8b6f6a135baddbe76b41033 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 31 Mar 2016 20:31:55 -0400 Subject: [PATCH 027/852] update channel scan --- .../LiveTv/TunerHosts/SatIp/ChannelScan.cs | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs index 20737df50..fdeae25b0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/ChannelScan.cs @@ -25,28 +25,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp public async Task> Scan(TunerHostInfo info, CancellationToken cancellationToken) { - var timedToken = new CancellationTokenSource(TimeSpan.FromSeconds(30)); - var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(timedToken.Token, cancellationToken); + var ini = info.SourceA.Split('|')[1]; + var resource = GetType().Assembly.GetManifestResourceNames().FirstOrDefault(i => i.EndsWith(ini, StringComparison.OrdinalIgnoreCase)); - using (var rtspSession = new RtspSession(info.Url, _logger)) + _logger.Info("Opening ini file {0}", resource); + var list = new List(); + + using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) { - var ini = info.SourceA.Split('|')[1]; - var resource = GetType().Assembly.GetManifestResourceNames().FirstOrDefault(i => i.EndsWith(ini, StringComparison.OrdinalIgnoreCase)); - - _logger.Info("Opening ini file {0}", resource); - using (var stream = GetType().Assembly.GetManifestResourceStream(resource)) + using (var reader = new StreamReader(stream)) { - using (var reader = new StreamReader(stream)) + var parser = new StreamIniDataParser(); + var data = parser.ReadData(reader); + + var count = GetInt(data, "DVB", "0", 0); + + _logger.Info("DVB Count: {0}", count); + + var index = 1; + var source = "1"; + + while (index <= count) { - var parser = new StreamIniDataParser(); - var data = parser.ReadData(reader); + cancellationToken.ThrowIfCancellationRequested(); - var count = GetInt(data, "DVB", "0", 0); - - var index = 1; - var source = "1"; - - while (!linkedToken.IsCancellationRequested) + using (var rtspSession = new RtspSession(info.Url, _logger)) { float percent = count == 0 ? 0 : (float)(index) / count; percent = Math.Max(percent * 100, 100); @@ -64,16 +67,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp tuning = string.Format("src={0}&freq={1}&pol={2}&sr={3}&fec={4}&msys=dvbs&mtype={5}&pids=0,16,17,18,20", source, strArray[0], strArray[1].ToLower(), strArray[2], strArray[3], strArray[5].ToLower()); } - if (string.IsNullOrEmpty(rtspSession.RtspSessionId)) - { - rtspSession.Setup(tuning, "unicast"); + rtspSession.Setup(tuning, "unicast"); - rtspSession.Play(string.Empty); - } - else - { - rtspSession.Play(tuning); - } + rtspSession.Play(string.Empty); int signallevel; int signalQuality; @@ -86,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp } } - return new List(); + return list; } private int GetInt(IniData data, string s1, string s2, int defaultValue) From 504c9e34c0ed47ce28fcf59e596a20adf2d3c509 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 1 Apr 2016 01:02:29 -0400 Subject: [PATCH 028/852] resolve audio channel playback --- MediaBrowser.Controller/Entities/BaseItem.cs | 5 +++++ MediaBrowser.Controller/Entities/Video.cs | 17 ----------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 74ff187c5..453ffd23f 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -255,6 +255,11 @@ namespace MediaBrowser.Controller.Entities if (string.IsNullOrWhiteSpace(Path)) { + if (SourceType == SourceType.Channel) + { + return LocationType.Remote; + } + return LocationType.Virtual; } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 511606efc..2c7d3856b 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -79,23 +79,6 @@ namespace MediaBrowser.Controller.Entities locationType != LocationType.Virtual; } - [IgnoreDataMember] - public override LocationType LocationType - { - get - { - if (SourceType == SourceType.Channel) - { - if (string.IsNullOrEmpty(Path)) - { - return LocationType.Remote; - } - } - - return base.LocationType; - } - } - [IgnoreDataMember] public override bool SupportsAddingToPlaylist { From 132766ff15cd2511ca09be0f2b878ebf5ceb5632 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 00:16:18 -0400 Subject: [PATCH 029/852] update ffmpeg --- .../Security/MbAdmin.cs | 4 +- .../Security/PluginSecurityManager.cs | 2 +- MediaBrowser.Dlna/Ssdp/SsdpHandler.cs | 47 +++++++++++++------ .../EntryPoints/UsageReporter.cs | 2 +- .../ApplicationHost.cs | 2 +- .../FFMpeg/FFMpegDownloadInfo.cs | 16 ++----- .../FFMpeg/FFMpegDownloader.cs | 47 +++++++++++++------ .../MediaBrowser.ServerApplication.csproj | 2 + .../ffmpeg/ffmpegx64.7z.REMOVED.git-id | 1 + .../ffmpeg/ffmpegx86.7z.REMOVED.git-id | 1 + 10 files changed, 80 insertions(+), 44 deletions(-) create mode 100644 MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id create mode 100644 MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id diff --git a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs b/MediaBrowser.Common.Implementations/Security/MbAdmin.cs index ab4a83257..76ff92c2e 100644 --- a/MediaBrowser.Common.Implementations/Security/MbAdmin.cs +++ b/MediaBrowser.Common.Implementations/Security/MbAdmin.cs @@ -3,11 +3,11 @@ namespace MediaBrowser.Common.Implementations.Security { public class MbAdmin { - public const string HttpUrl = "http://www.mb3admin.com/admin/"; + public const string HttpUrl = "https://www.mb3admin.com/admin/"; /// /// Leaving as http for now until we get it squared away /// - public const string HttpsUrl = "http://www.mb3admin.com/admin/"; + public const string HttpsUrl = "https://www.mb3admin.com/admin/"; } } diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs index af58c3731..4e01041bc 100644 --- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs +++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Common.Implementations.Security public class PluginSecurityManager : ISecurityManager { private const string MBValidateUrl = MbAdmin.HttpsUrl + "service/registration/validate"; - private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "http://mb3admin.com/admin/service/appstore/register"; + private const string AppstoreRegUrl = /*MbAdmin.HttpsUrl*/ "https://mb3admin.com/admin/service/appstore/register"; /// /// The _is MB supporter diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs index 2d1ec1273..3cdeb1afd 100644 --- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs +++ b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs @@ -36,7 +36,7 @@ namespace MediaBrowser.Dlna.Ssdp private Timer _notificationTimer; private bool _isDisposed; - private readonly ConcurrentDictionary> _devices = new ConcurrentDictionary>(); + private readonly Dictionary> _devices = new Dictionary>(); private readonly IApplicationHost _appHost; @@ -172,9 +172,12 @@ namespace MediaBrowser.Dlna.Ssdp { get { - var devices = _devices.ToList(); + lock (_devices) + { + var devices = _devices.ToList(); - return devices.SelectMany(i => i.Value).ToList(); + return devices.SelectMany(i => i.Value).ToList(); + } } } @@ -482,26 +485,42 @@ namespace MediaBrowser.Dlna.Ssdp public void RegisterNotification(string uuid, Uri descriptionUri, IPAddress address, IEnumerable services) { - var list = _devices.GetOrAdd(uuid, new List()); + lock (_devices) + { + List list; + List dl; + if (_devices.TryGetValue(uuid, out dl)) + { + list = dl; + } + else + { + list = new List(); + _devices[uuid] = list; + } - list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); + list.AddRange(services.Select(i => new UpnpDevice(uuid, i, descriptionUri, address))); - NotifyAll(); - _logger.Debug("Registered mount {0} at {1}", uuid, descriptionUri); + NotifyAll(); + _logger.Debug("Registered mount {0} at {1}", uuid, descriptionUri); + } } public void UnregisterNotification(string uuid) { - List dl; - if (_devices.TryRemove(uuid, out dl)) + lock (_devices) { - - foreach (var d in dl.ToList()) + List dl; + if (_devices.TryGetValue(uuid, out dl)) { - NotifyDevice(d, "byebye", true); - } + _devices.Remove(uuid); + foreach (var d in dl.ToList()) + { + NotifyDevice(d, "byebye", true); + } - _logger.Debug("Unregistered mount {0}", uuid); + _logger.Debug("Unregistered mount {0}", uuid); + } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs index 7e22efb23..7b3a7a30d 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/UsageReporter.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly IHttpClient _httpClient; private readonly IUserManager _userManager; private readonly ILogger _logger; - private const string MbAdminUrl = "http://www.mb3admin.com/admin/"; + private const string MbAdminUrl = "https://www.mb3admin.com/admin/"; public UsageReporter(IApplicationHost applicationHost, IHttpClient httpClient, IUserManager userManager, ILogger logger) { diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index dd7e3cc01..b5988b18a 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -618,7 +618,7 @@ namespace MediaBrowser.Server.Startup.Common /// Task. private async Task RegisterMediaEncoder(IProgress progress) { - var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment) + var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment, NativeApp.GetType().Assembly) .GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false); var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs index 60cb50e30..4979ff82b 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs @@ -8,6 +8,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg public string FFProbeFilename { get; set; } public string ArchiveType { get; set; } public string[] DownloadUrls { get; set; } + public bool IsEmbedded { get; set; } public FFMpegDownloadInfo() { @@ -54,8 +55,9 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg info.FFMpegFilename = "ffmpeg.exe"; info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20160131"; + info.Version = "20160401"; info.ArchiveType = "7z"; + info.IsEmbedded = true; switch (environment.SystemArchitecture) { @@ -81,17 +83,9 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg switch (environment.SystemArchitecture) { case Architecture.X86_X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160131-win64.7z", - "http://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-20151109-git-480bad7-win64-static.7z" - }; + return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx64.7z" }; case Architecture.X86: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160131-win32.7z", - "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20151109-git-480bad7-win32-static.7z" - }; + return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx86.7z" }; } break; diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs index 000568c15..c538b81a4 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -23,13 +24,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg private readonly IZipClient _zipClient; private readonly IFileSystem _fileSystem; private readonly NativeEnvironment _environment; + private Assembly _ownerAssembly; private readonly string[] _fontUrls = { "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/ARIALUNI.7z" }; - public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment) + public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment, Assembly ownerAssembly) { _logger = logger; _appPaths = appPaths; @@ -37,6 +39,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg _zipClient = zipClient; _fileSystem = fileSystem; _environment = environment; + _ownerAssembly = ownerAssembly; } public async Task GetFFMpegInfo(NativeEnvironment environment, StartupOptions options, IProgress progress) @@ -78,11 +81,11 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg Version = version }; - _fileSystem.CreateDirectory(versionedDirectoryPath); + _fileSystem.CreateDirectory(versionedDirectoryPath); var excludeFromDeletions = new List { versionedDirectoryPath }; - if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath)) + if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath)) { // ffmpeg not present. See if there's an older version we can start with var existingVersion = GetExistingVersion(info, rootEncoderPath); @@ -106,7 +109,10 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } - await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + if (_environment.OperatingSystem == OperatingSystem.Windows) + { + await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + } DeleteOlderFolders(Path.GetDirectoryName(versionedDirectoryPath), excludeFromDeletions); @@ -189,6 +195,21 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg private async Task DownloadFFMpeg(FFMpegDownloadInfo downloadinfo, string directory, IProgress progress) { + if (downloadinfo.IsEmbedded) + { + var tempFile = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); + _fileSystem.CreateDirectory(Path.GetDirectoryName(tempFile)); + + using (var stream = _ownerAssembly.GetManifestResourceStream(downloadinfo.DownloadUrls[0])) + { + using (var fs = _fileSystem.GetFileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.Read, true)) + { + await stream.CopyToAsync(fs).ConfigureAwait(false); + } + } + ExtractFFMpeg(downloadinfo, tempFile, directory); + } + foreach (var url in downloadinfo.DownloadUrls) { progress.Report(0); @@ -216,10 +237,8 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { throw new ApplicationException("ffmpeg unvailable. Please install it and start the server with two command line arguments: -ffmpeg \"{PATH}\" and -ffprobe \"{PATH}\""); } - else - { - throw new ApplicationException("Unable to download required components. Please try again later."); - } + + throw new ApplicationException("Unable to download required components. Please try again later."); } private void ExtractFFMpeg(FFMpegDownloadInfo downloadinfo, string tempFile, string targetFolder) @@ -228,7 +247,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); - _fileSystem.CreateDirectory(tempFolder); + _fileSystem.CreateDirectory(tempFolder); try { @@ -247,7 +266,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg })) { var targetFile = Path.Combine(targetFolder, Path.GetFileName(file)); - _fileSystem.CopyFile(file, targetFile, true); + _fileSystem.CopyFile(file, targetFile, true); SetFilePermissions(targetFile); } } @@ -311,13 +330,13 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { var fontsDirectory = Path.Combine(targetPath, "fonts"); - _fileSystem.CreateDirectory(fontsDirectory); + _fileSystem.CreateDirectory(fontsDirectory); const string fontFilename = "ARIALUNI.TTF"; var fontFile = Path.Combine(fontsDirectory, fontFilename); - if (_fileSystem.FileExists(fontFile)) + if (_fileSystem.FileExists(fontFile)) { await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); } @@ -360,7 +379,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg { try { - _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true); + _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true); return; } catch (IOException ex) @@ -422,7 +441,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg const string fontConfigFilename = "fonts.conf"; var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename); - if (!_fileSystem.FileExists(fontConfigFile)) + if (!_fileSystem.FileExists(fontConfigFile)) { var contents = string.Format("{0}ArialArial Unicode MS", fontsDirectory); diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 6ba91c06f..d1bf58dda 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -144,6 +144,8 @@ + + diff --git a/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id new file mode 100644 index 000000000..b0542b75f --- /dev/null +++ b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx64.7z.REMOVED.git-id @@ -0,0 +1 @@ +9dc10b022537738edce7eb71aa8dd4adbfee2c7b \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id new file mode 100644 index 000000000..3939ec44d --- /dev/null +++ b/MediaBrowser.ServerApplication/ffmpeg/ffmpegx86.7z.REMOVED.git-id @@ -0,0 +1 @@ +00fa1afa35fbd0a7e97ad7956e42ae17f6882f64 \ No newline at end of file From d91c63c55324df395743d6104ba18a27ace01231 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 00:29:48 -0400 Subject: [PATCH 030/852] update ffmpeg info --- .../Native/BaseMonoApp.cs | 95 ++++++++++++ .../ApplicationHost.cs | 2 +- .../FFMpeg/FFMpegDownloadInfo.cs | 136 ------------------ .../FFMpeg/FFMpegInstallInfo.cs | 21 +++ .../{FFMpegDownloader.cs => FFMpegLoader.cs} | 18 +-- .../INativeApp.cs | 3 + .../MediaBrowser.Server.Startup.Common.csproj | 4 +- .../Native/WindowsApp.cs | 30 +++- 8 files changed, 161 insertions(+), 148 deletions(-) delete mode 100644 MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs create mode 100644 MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegInstallInfo.cs rename MediaBrowser.Server.Startup.Common/FFMpeg/{FFMpegDownloader.cs => FFMpegLoader.cs} (94%) diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index e54bc0b4a..6d19c3275 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -9,6 +9,8 @@ using System.Collections.Generic; using System.Reflection; using System.Text.RegularExpressions; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Startup.Common.FFMpeg; +using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem; namespace MediaBrowser.Server.Mono.Native { @@ -209,6 +211,99 @@ namespace MediaBrowser.Server.Mono.Native { return new NullPowerManagement(); } + + public FFMpegInstallInfo GetFfmpegInstallInfo() + { + return GetInfo(Environment); + } + + public static FFMpegInstallInfo GetInfo(NativeEnvironment environment) + { + var info = new FFMpegInstallInfo(); + + // Windows builds: http://ffmpeg.zeranoe.com/builds/ + // Linux builds: http://johnvansickle.com/ffmpeg/ + // OS X builds: http://ffmpegmac.net/ + // OS X x64: http://www.evermeet.cx/ffmpeg/ + + switch (environment.OperatingSystem) + { + case OperatingSystem.Bsd: + break; + case OperatingSystem.Linux: + + info.ArchiveType = "7z"; + info.Version = "20160215"; + break; + case OperatingSystem.Osx: + + info.ArchiveType = "7z"; + + switch (environment.SystemArchitecture) + { + case Architecture.X86_X64: + info.Version = "20160124"; + break; + case Architecture.X86: + info.Version = "20150110"; + break; + } + break; + } + + info.DownloadUrls = GetDownloadUrls(environment); + + return info; + } + + private static string[] GetDownloadUrls(NativeEnvironment environment) + { + switch (environment.OperatingSystem) + { + case OperatingSystem.Osx: + + switch (environment.SystemArchitecture) + { + case Architecture.X86_X64: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.5.7z" + }; + case Architecture.X86: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x86-2.5.3.7z" + }; + } + break; + + case OperatingSystem.Linux: + + switch (environment.SystemArchitecture) + { + case Architecture.X86_X64: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-64bit-static.7z" + }; + case Architecture.X86: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-32bit-static.7z" + }; + case Architecture.Arm: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-arm.7z" + }; + } + break; + } + + // No version available + return new string[] { }; + } + } public class NullPowerManagement : IPowerManagement diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index b5988b18a..93dbe2945 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -618,7 +618,7 @@ namespace MediaBrowser.Server.Startup.Common /// Task. private async Task RegisterMediaEncoder(IProgress progress) { - var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment, NativeApp.GetType().Assembly) + var info = await new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.Environment, NativeApp.GetType().Assembly, NativeApp.GetFfmpegInstallInfo()) .GetFFMpegInfo(NativeApp.Environment, _startupOptions, progress).ConfigureAwait(false); var mediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs deleted file mode 100644 index 4979ff82b..000000000 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloadInfo.cs +++ /dev/null @@ -1,136 +0,0 @@ - -namespace MediaBrowser.Server.Startup.Common.FFMpeg -{ - public class FFMpegDownloadInfo - { - public string Version { get; set; } - public string FFMpegFilename { get; set; } - public string FFProbeFilename { get; set; } - public string ArchiveType { get; set; } - public string[] DownloadUrls { get; set; } - public bool IsEmbedded { get; set; } - - public FFMpegDownloadInfo() - { - DownloadUrls = new string[] { }; - Version = "Path"; - FFMpegFilename = "ffmpeg"; - FFProbeFilename = "ffprobe"; - } - - public static FFMpegDownloadInfo GetInfo(NativeEnvironment environment) - { - var info = new FFMpegDownloadInfo(); - - // Windows builds: http://ffmpeg.zeranoe.com/builds/ - // Linux builds: http://johnvansickle.com/ffmpeg/ - // OS X builds: http://ffmpegmac.net/ - // OS X x64: http://www.evermeet.cx/ffmpeg/ - - switch (environment.OperatingSystem) - { - case OperatingSystem.Bsd: - break; - case OperatingSystem.Linux: - - info.ArchiveType = "7z"; - info.Version = "20160215"; - break; - case OperatingSystem.Osx: - - info.ArchiveType = "7z"; - - switch (environment.SystemArchitecture) - { - case Architecture.X86_X64: - info.Version = "20160124"; - break; - case Architecture.X86: - info.Version = "20150110"; - break; - } - break; - - case OperatingSystem.Windows: - - info.FFMpegFilename = "ffmpeg.exe"; - info.FFProbeFilename = "ffprobe.exe"; - info.Version = "20160401"; - info.ArchiveType = "7z"; - info.IsEmbedded = true; - - switch (environment.SystemArchitecture) - { - case Architecture.X86_X64: - break; - case Architecture.X86: - break; - } - break; - } - - info.DownloadUrls = GetDownloadUrls(environment); - - return info; - } - - private static string[] GetDownloadUrls(NativeEnvironment environment) - { - switch (environment.OperatingSystem) - { - case OperatingSystem.Windows: - - switch (environment.SystemArchitecture) - { - case Architecture.X86_X64: - return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx64.7z" }; - case Architecture.X86: - return new string[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx86.7z" }; - } - break; - - case OperatingSystem.Osx: - - switch (environment.SystemArchitecture) - { - case Architecture.X86_X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.5.7z" - }; - case Architecture.X86: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x86-2.5.3.7z" - }; - } - break; - - case OperatingSystem.Linux: - - switch (environment.SystemArchitecture) - { - case Architecture.X86_X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-64bit-static.7z" - }; - case Architecture.X86: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-git-20160215-32bit-static.7z" - }; - case Architecture.Arm: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/linux/ffmpeg-arm.7z" - }; - } - break; - } - - // No version available - return new string[] { }; - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegInstallInfo.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegInstallInfo.cs new file mode 100644 index 000000000..1ce1b55c2 --- /dev/null +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegInstallInfo.cs @@ -0,0 +1,21 @@ + +namespace MediaBrowser.Server.Startup.Common.FFMpeg +{ + public class FFMpegInstallInfo + { + public string Version { get; set; } + public string FFMpegFilename { get; set; } + public string FFProbeFilename { get; set; } + public string ArchiveType { get; set; } + public string[] DownloadUrls { get; set; } + public bool IsEmbedded { get; set; } + + public FFMpegInstallInfo() + { + DownloadUrls = new string[] { }; + Version = "Path"; + FFMpegFilename = "ffmpeg"; + FFProbeFilename = "ffprobe"; + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs similarity index 94% rename from MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs rename to MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs index c538b81a4..fd005de86 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs @@ -16,7 +16,7 @@ using CommonIO; namespace MediaBrowser.Server.Startup.Common.FFMpeg { - public class FFMpegDownloader + public class FFMpegLoader { private readonly IHttpClient _httpClient; private readonly IApplicationPaths _appPaths; @@ -24,14 +24,15 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg private readonly IZipClient _zipClient; private readonly IFileSystem _fileSystem; private readonly NativeEnvironment _environment; - private Assembly _ownerAssembly; + private readonly Assembly _ownerAssembly; + private readonly FFMpegInstallInfo _ffmpegInstallInfo; private readonly string[] _fontUrls = { "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/ARIALUNI.7z" }; - public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment, Assembly ownerAssembly) + public FFMpegLoader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, NativeEnvironment environment, Assembly ownerAssembly, FFMpegInstallInfo ffmpegInstallInfo) { _logger = logger; _appPaths = appPaths; @@ -40,6 +41,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg _fileSystem = fileSystem; _environment = environment; _ownerAssembly = ownerAssembly; + _ffmpegInstallInfo = ffmpegInstallInfo; } public async Task GetFFMpegInfo(NativeEnvironment environment, StartupOptions options, IProgress progress) @@ -57,7 +59,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg }; } - var downloadInfo = FFMpegDownloadInfo.GetInfo(environment); + var downloadInfo = _ffmpegInstallInfo; var version = downloadInfo.Version; @@ -181,7 +183,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg return null; } - private async void DownloadFFMpegInBackground(FFMpegDownloadInfo downloadinfo, string directory) + private async void DownloadFFMpegInBackground(FFMpegInstallInfo downloadinfo, string directory) { try { @@ -193,7 +195,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } - private async Task DownloadFFMpeg(FFMpegDownloadInfo downloadinfo, string directory, IProgress progress) + private async Task DownloadFFMpeg(FFMpegInstallInfo downloadinfo, string directory, IProgress progress) { if (downloadinfo.IsEmbedded) { @@ -241,7 +243,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg throw new ApplicationException("Unable to download required components. Please try again later."); } - private void ExtractFFMpeg(FFMpegDownloadInfo downloadinfo, string tempFile, string targetFolder) + private void ExtractFFMpeg(FFMpegInstallInfo downloadinfo, string tempFile, string targetFolder) { _logger.Info("Extracting ffmpeg from {0}", tempFile); @@ -287,7 +289,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } - private void ExtractArchive(FFMpegDownloadInfo downloadinfo, string archivePath, string targetPath) + private void ExtractArchive(FFMpegInstallInfo downloadinfo, string archivePath, string targetPath) { _logger.Info("Extracting {0} to {1}", archivePath, targetPath); diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index 9df670bda..121d4192e 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging; using System.Collections.Generic; using System.Reflection; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Startup.Common.FFMpeg; namespace MediaBrowser.Server.Startup.Common { @@ -97,5 +98,7 @@ namespace MediaBrowser.Server.Startup.Common /// /// IPowerManagement. IPowerManagement GetPowerManagement(); + + FFMpegInstallInfo GetFfmpegInstallInfo(); } } diff --git a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj index 80ce88fa3..19ce9ed9e 100644 --- a/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj +++ b/MediaBrowser.Server.Startup.Common/MediaBrowser.Server.Startup.Common.csproj @@ -65,8 +65,8 @@ - - + + diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 164037dc5..056258f96 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Reflection; using CommonIO; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Startup.Common.FFMpeg; namespace MediaBrowser.ServerApplication.Native { @@ -30,7 +31,7 @@ namespace MediaBrowser.ServerApplication.Native } list.Add(GetType().Assembly); - + return list; } @@ -124,5 +125,32 @@ namespace MediaBrowser.ServerApplication.Native { return new WindowsPowerManagement(_logger); } + + public FFMpegInstallInfo GetFfmpegInstallInfo() + { + var info = new FFMpegInstallInfo(); + + info.FFMpegFilename = "ffmpeg.exe"; + info.FFProbeFilename = "ffprobe.exe"; + info.Version = "20160401"; + info.ArchiveType = "7z"; + info.IsEmbedded = true; + info.DownloadUrls = GetDownloadUrls(); + + return info; + } + + private string[] GetDownloadUrls() + { + switch (Environment.SystemArchitecture) + { + case Architecture.X86_X64: + return new[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx64.7z" }; + case Architecture.X86: + return new[] { "MediaBrowser.ServerApplication.ffmpeg.ffmpegx86.7z" }; + } + + return new string[] { }; + } } } From 4577148217fd3daed60cec9560ac0a4b36959845 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 00:46:18 -0400 Subject: [PATCH 031/852] update ffmpeg downloader --- MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs index fd005de86..ee284fdc5 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegLoader.cs @@ -210,6 +210,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } ExtractFFMpeg(downloadinfo, tempFile, directory); + return; } foreach (var url in downloadinfo.DownloadUrls) From 6b4c191503b8dcf4e82287672ec257734cf0e1b6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 02:20:29 -0400 Subject: [PATCH 032/852] remove unused package --- .../MediaBrowser.ServerApplication.csproj | 6 ------ MediaBrowser.ServerApplication/packages.config | 1 - 2 files changed, 7 deletions(-) diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index d1bf58dda..a654bd2b5 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -69,16 +69,10 @@ False ..\packages\ImageMagickSharp.1.0.0.18\lib\net45\ImageMagickSharp.dll - - ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll - False ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll - - ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\pfmclrapi.dll - ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 5187a1db3..16acb0c81 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -2,7 +2,6 @@ - \ No newline at end of file From fbf4d40c5d83b44e258fd5548c1e39eacf7df241 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 28 Mar 2016 13:13:20 -0400 Subject: [PATCH 033/852] update WdtvLiveProfile --- MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs index 98e780a25..1c0c7d297 100644 --- a/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs +++ b/MediaBrowser.Dlna/Profiles/WdtvLiveProfile.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Dlna.Profiles new DirectPlayProfile { - Container = "ts", + Container = "ts,m2ts", Type = DlnaProfileType.Video, VideoCodec = "mpeg1video,mpeg2video,h264,vc1", AudioCodec = "ac3,dca,mp2,mp3,aac,dca" From a22981071eb05367215520205abb839a2fea8e98 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 28 Mar 2016 13:15:57 -0400 Subject: [PATCH 034/852] update WDTV Live.xml --- MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml index 514168f43..50f30d40f 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml @@ -40,7 +40,7 @@ - + From efb87de801c66d20524b7d3736ee297111a2fb7d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 21:33:08 -0400 Subject: [PATCH 035/852] support music dynamic images --- MediaBrowser.Providers/Folders/DefaultImageProvider.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs index ca543163d..ee83efd26 100644 --- a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs +++ b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.Folders } if (string.Equals(viewType, CollectionType.Music, StringComparison.OrdinalIgnoreCase)) { - return urlPrefix + "music.jpg"; + //return urlPrefix + "music.jpg"; } if (string.Equals(viewType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) { @@ -105,7 +105,7 @@ namespace MediaBrowser.Providers.Folders } if (string.Equals(viewType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { - return urlPrefix + "homevideos.jpg"; + //return urlPrefix + "homevideos.jpg"; } if (string.Equals(viewType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { From 8ec1795abc100f2b724271ed0dd3120914888a54 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 29 Mar 2016 23:31:11 -0400 Subject: [PATCH 036/852] resolve missing trailers --- MediaBrowser.Controller/Entities/BaseItem.cs | 6 +++++- .../Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 4117b7521..72980a58e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -2084,7 +2084,7 @@ namespace MediaBrowser.Controller.Entities { get { - if (GetParent() is AggregateFolder || this is Channel || this is BasePluginFolder) + if (GetParent() is AggregateFolder || this is BasePluginFolder) { return true; } @@ -2094,6 +2094,10 @@ namespace MediaBrowser.Controller.Entities { return true; } + if (view != null && string.Equals(view.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase)) + { + return true; + } return false; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index af275faee..4a7235928 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 53; + private const int LatestSchemaVersion = 55; /// /// Initializes a new instance of the class. From cbcadbf892b9546ec6b6d1ce821401dfa463a090 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 12:47:23 -0400 Subject: [PATCH 037/852] update sorting --- MediaBrowser.Controller/Entities/BaseItem.cs | 3 ++- .../Persistence/CleanDatabaseScheduledTask.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 453ffd23f..ba5da03d1 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -503,7 +503,8 @@ namespace MediaBrowser.Controller.Entities { if (!string.IsNullOrWhiteSpace(ForcedSortName)) { - _sortName = ModifySortChunks(ForcedSortName); + // Need the ToLower because that's what CreateSortName does + _sortName = ModifySortChunks(ForcedSortName).ToLower(); } else { diff --git a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs index 38cca3c35..031333f2c 100644 --- a/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs +++ b/MediaBrowser.Server.Implementations/Persistence/CleanDatabaseScheduledTask.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private readonly ILocalizationManager _localization; private readonly ITaskManager _taskManager; - public const int MigrationVersion = 22; + public const int MigrationVersion = 23; public static bool EnableUnavailableMessage = false; public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem, IHttpServer httpServer, ILocalizationManager localization, ITaskManager taskManager) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 308645d02..eda0a263a 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; - private const int LatestSchemaVersion = 57; + private const int LatestSchemaVersion = 58; /// /// Initializes a new instance of the class. From c215c80d1116fa938687ef14c0001e0b992f47c6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 12:52:39 -0400 Subject: [PATCH 038/852] 3.0.5923 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 29b0afc2c..f4e604d58 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5922")] +[assembly: AssemblyVersion("3.0.5923")] From 9b339d7caea199ddf3f3f53812830010799eace1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 17:08:35 -0400 Subject: [PATCH 039/852] resolve issue with querying by multiple item ids --- .../ImageMagick/StripCollageBuilder.cs | 12 ++++++------ MediaBrowser.Controller/Channels/Channel.cs | 2 +- .../Channels/ChannelFolderItem.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 19 ++++++++++++++----- MediaBrowser.Controller/Entities/TV/Season.cs | 2 +- MediaBrowser.Controller/Entities/TV/Series.cs | 2 +- .../Entities/UserRootFolder.cs | 3 ++- MediaBrowser.Controller/Entities/UserView.cs | 2 +- .../Configuration/ServerConfiguration.cs | 2 -- 9 files changed, 27 insertions(+), 19 deletions(-) diff --git a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs index 8c50fb5eb..c9e291a5e 100644 --- a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs +++ b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs @@ -295,9 +295,9 @@ namespace Emby.Drawing.ImageMagick wand.OpenImage("gradient:#111111-#111111"); using (var draw = new DrawingWand()) { - var iSlice = Convert.ToInt32(width * .1166666667 * 2); + var iSlice = Convert.ToInt32(width * 0.24125); int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .62); + int iHeight = Convert.ToInt32(height * .70); var horizontalImagePadding = Convert.ToInt32(width * 0.0125); foreach (var element in wandImages.ImageList) @@ -339,7 +339,7 @@ namespace Emby.Drawing.ImageMagick wandList.AddImage(mwr); int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2; - wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .085)); + wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .045)); } } } @@ -360,9 +360,9 @@ namespace Emby.Drawing.ImageMagick wand.OpenImage("gradient:#111111-#111111"); using (var draw = new DrawingWand()) { - var iSlice = Convert.ToInt32(width * .3); + var iSlice = Convert.ToInt32(width * .32); int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .63); + int iHeight = Convert.ToInt32(height * .68); var horizontalImagePadding = Convert.ToInt32(width * 0.02); foreach (var element in wandImages.ImageList) @@ -404,7 +404,7 @@ namespace Emby.Drawing.ImageMagick wandList.AddImage(mwr); int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2; - wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .07)); + wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .03)); } } } diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index 43f7b6637..718a0d878 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.Channels set { } } - public override async Task> GetItems(InternalItemsQuery query) + protected override async Task> GetItemsInternal(InternalItemsQuery query) { try { diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs index da5d60863..62e0d694e 100644 --- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs +++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Channels return ExternalId; } - public override async Task> GetItems(InternalItemsQuery query) + protected override async Task> GetItemsInternal(InternalItemsQuery query) { try { diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index af1cbdf2c..f4cdc8fa1 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -111,7 +111,7 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] protected virtual bool SupportsShortcutChildren { - get { return ConfigurationManager.Configuration.EnableWindowsShortcuts; } + get { return false; } } /// @@ -1122,7 +1122,18 @@ namespace MediaBrowser.Controller.Entities return false; } - public virtual async Task> GetItems(InternalItemsQuery query) + public Task> GetItems(InternalItemsQuery query) + { + if (query.ItemIds.Length > 0) + { + var specificItems = query.ItemIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList(); + return Task.FromResult(PostFilterAndSort(specificItems, query)); + } + + return GetItemsInternal(query); + } + + protected virtual async Task> GetItemsInternal(InternalItemsQuery query) { if (SourceType == SourceType.Channel) { @@ -1175,9 +1186,7 @@ namespace MediaBrowser.Controller.Entities : GetChildren(user, true).Where(filter); } - var result = PostFilterAndSort(items, query); - - return result; + return PostFilterAndSort(items, query); } protected QueryResult PostFilterAndSort(IEnumerable items, InternalItemsQuery query) diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 9efa609ef..5e067afd4 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -129,7 +129,7 @@ namespace MediaBrowser.Controller.Entities.TV get { return (IndexNumber ?? -1) == 0; } } - public override Task> GetItems(InternalItemsQuery query) + protected override Task> GetItemsInternal(InternalItemsQuery query) { var user = query.User; diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index aa07ab378..9eeb89a1f 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Controller.Entities.TV return GetSeasons(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } - public override Task> GetItems(InternalItemsQuery query) + protected override Task> GetItemsInternal(InternalItemsQuery query) { var user = query.User; diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index 104408860..8ce39c697 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Library; namespace MediaBrowser.Controller.Entities { @@ -17,7 +18,7 @@ namespace MediaBrowser.Controller.Entities /// public class UserRootFolder : Folder { - public override async Task> GetItems(InternalItemsQuery query) + protected override async Task> GetItemsInternal(InternalItemsQuery query) { if (query.Recursive) { diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 41c19f11d..40fec3e28 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -45,7 +45,7 @@ namespace MediaBrowser.Controller.Entities return list; } - public override Task> GetItems(InternalItemsQuery query) + protected override Task> GetItemsInternal(InternalItemsQuery query) { var parent = this as Folder; diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 041f51a89..ba3362332 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -196,8 +196,6 @@ namespace MediaBrowser.Model.Configuration public int SharingExpirationDays { get; set; } - public bool EnableWindowsShortcuts { get; set; } - public bool EnableDateLastRefresh { get; set; } public string[] Migrations { get; set; } From 51fe0310314a3b5c0a8c625b0c0e3f953a432392 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 19:39:08 -0400 Subject: [PATCH 040/852] update subtitles --- .../Subtitles/SubtitleEncoder.cs | 9 ++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 42 ++++++++++++------- MediaBrowser.Model/Dlna/StreamInfo.cs | 2 +- 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index d539879e6..baf78ad92 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -219,14 +219,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles string outputFormat; string outputCodec; - if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(subtitleStream.Codec, "ass", StringComparison.OrdinalIgnoreCase) || + string.Equals(subtitleStream.Codec, "ssa", StringComparison.OrdinalIgnoreCase) || + string.Equals(subtitleStream.Codec, "srt", StringComparison.OrdinalIgnoreCase)) { // Extract outputCodec = "copy"; - outputFormat = "ass"; + outputFormat = subtitleStream.Codec; } - else if (string.Equals(subtitleStream.Codec, "subrip", StringComparison.OrdinalIgnoreCase) || - string.Equals(subtitleStream.Codec, "srt", StringComparison.OrdinalIgnoreCase)) + else if (string.Equals(subtitleStream.Codec, "subrip", StringComparison.OrdinalIgnoreCase)) { // Extract outputCodec = "copy"; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index b04f1b0fb..a080011ec 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -383,7 +383,7 @@ namespace MediaBrowser.Model.Dlna if (subtitleStream != null) { - SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, options.Context, directPlay.Value); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, directPlay.Value); playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleFormat = subtitleProfile.Format; @@ -413,7 +413,7 @@ namespace MediaBrowser.Model.Dlna if (subtitleStream != null) { - SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, options.Context, PlayMethod.Transcode); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode); playlistItem.SubtitleDeliveryMethod = subtitleProfile.Method; playlistItem.SubtitleFormat = subtitleProfile.Format; @@ -739,7 +739,7 @@ namespace MediaBrowser.Model.Dlna { if (subtitleStream != null) { - SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, options.Context, playMethod); + SubtitleProfile subtitleProfile = GetSubtitleProfile(subtitleStream, options.Profile.SubtitleProfiles, playMethod); if (subtitleProfile.Method != SubtitleDeliveryMethod.External && subtitleProfile.Method != SubtitleDeliveryMethod.Embed) { @@ -751,7 +751,7 @@ namespace MediaBrowser.Model.Dlna return IsAudioEligibleForDirectPlay(item, maxBitrate); } - public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, EncodingContext context, PlayMethod playMethod) + public static SubtitleProfile GetSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod) { if (playMethod != PlayMethod.Transcode && !subtitleStream.IsExternal) { @@ -775,7 +775,16 @@ namespace MediaBrowser.Model.Dlna } } - // Look for an external profile that matches the stream type (text/graphical) + // Look for an external or hls profile that matches the stream type (text/graphical) and doesn't require conversion + return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false) ?? GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false) ?? new SubtitleProfile + { + Method = SubtitleDeliveryMethod.Encode, + Format = subtitleStream.Codec + }; + } + + private static SubtitleProfile GetExternalSubtitleProfile(MediaStream subtitleStream, SubtitleProfile[] subtitleProfiles, PlayMethod playMethod, bool allowConversion) + { foreach (SubtitleProfile profile in subtitleProfiles) { if (profile.Method != SubtitleDeliveryMethod.External && profile.Method != SubtitleDeliveryMethod.Hls) @@ -798,21 +807,24 @@ namespace MediaBrowser.Model.Dlna { bool requiresConversion = !StringHelper.EqualsIgnoreCase(subtitleStream.Codec, profile.Format); - if (subtitleStream.IsTextSubtitleStream || !requiresConversion) + if (requiresConversion && !allowConversion) { - if (subtitleStream.SupportsExternalStream) - { - return profile; - } + continue; + } + + if (!requiresConversion) + { + return profile; + } + + if (subtitleStream.IsTextSubtitleStream && subtitleStream.SupportsExternalStream) + { + return profile; } } } - return new SubtitleProfile - { - Method = SubtitleDeliveryMethod.Encode, - Format = subtitleStream.Codec - }; + return null; } private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate) diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index f78047d47..436ed2071 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -321,7 +321,7 @@ namespace MediaBrowser.Model.Dlna private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles) { - SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, Context, PlayMethod); + SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, PlayMethod); SubtitleStreamInfo info = new SubtitleStreamInfo { IsForced = stream.IsForced, From da82c0c3f731f70dc416425682cfbeaed9b98b75 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 19:53:21 -0400 Subject: [PATCH 041/852] 3.0.5924 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index f4e604d58..f9f6b86d5 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5923")] +[assembly: AssemblyVersion("3.0.5924")] From 6ba2a9ebd2cc42d83b8bbef959b8d5b71c0fee4d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 2 Apr 2016 21:19:27 -0400 Subject: [PATCH 042/852] update subtitle encoding --- .../Playback/BaseStreamingService.cs | 2 +- .../MediaEncoding/ISubtitleEncoder.cs | 2 +- .../Encoder/BaseEncoder.cs | 2 +- .../Subtitles/SubtitleEncoder.cs | 63 ++++++++++++------- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- 5 files changed, 45 insertions(+), 26 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 44bc95ed1..00ac7be87 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -614,7 +614,7 @@ namespace MediaBrowser.Api.Playback if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.MediaSource.Protocol, CancellationToken.None).Result; + var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language, state.MediaSource.Protocol, CancellationToken.None).Result; if (!string.IsNullOrEmpty(charenc)) { diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs index 826711e51..e538b84d8 100644 --- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs @@ -33,6 +33,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// The protocol. /// The cancellation token. /// System.String. - Task GetSubtitleFileCharacterSet(string path, MediaProtocol protocol, CancellationToken cancellationToken); + Task GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 8c0a7b0b5..263efbb62 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -969,7 +969,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!string.IsNullOrEmpty(state.SubtitleStream.Language)) { - var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.MediaSource.Protocol, CancellationToken.None).Result; + var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.SubtitleStream.Language, state.MediaSource.Protocol, CancellationToken.None).Result; if (!string.IsNullOrEmpty(charenc)) { diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index baf78ad92..8c33cc7c0 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -161,16 +161,16 @@ namespace MediaBrowser.MediaEncoding.Subtitles var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false); - var stream = await GetSubtitleStream(fileInfo.Item1, fileInfo.Item2, fileInfo.Item4, cancellationToken).ConfigureAwait(false); + var stream = await GetSubtitleStream(fileInfo.Item1, subtitleStream.Language, fileInfo.Item2, fileInfo.Item4, cancellationToken).ConfigureAwait(false); return new Tuple(stream, fileInfo.Item3); } - private async Task GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) + private async Task GetSubtitleStream(string path, string language, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken) { if (requiresCharset) { - var charset = await GetSubtitleFileCharacterSet(path, protocol, cancellationToken).ConfigureAwait(false); + var charset = await GetSubtitleFileCharacterSet(path, language, protocol, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(charset)) { @@ -197,14 +197,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles { throw new ArgumentNullException("charset"); } - + + _logger.Debug("Getting encoding object for character set: {0}", charset); + try { return Encoding.GetEncoding(charset); } catch (ArgumentException) { - return Encoding.GetEncoding(charset.Replace("-", string.Empty)); + charset = charset.Replace("-", string.Empty); + _logger.Debug("Getting encoding object for character set: {0}", charset); + + return Encoding.GetEncoding(charset); } } @@ -257,7 +262,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles // Convert var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, ".srt"); - await ConvertTextSubtitleToSrt(subtitleStream.Path, protocol, outputPath, cancellationToken).ConfigureAwait(false); + await ConvertTextSubtitleToSrt(subtitleStream.Path, subtitleStream.Language, protocol, outputPath, cancellationToken).ConfigureAwait(false); return new Tuple(outputPath, MediaProtocol.File, "srt", true); } @@ -356,7 +361,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// The output path. /// The cancellation token. /// Task. - private async Task ConvertTextSubtitleToSrt(string inputPath, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) + private async Task ConvertTextSubtitleToSrt(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { var semaphore = GetLock(outputPath); @@ -364,9 +369,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { - if (!_fileSystem.FileExists(outputPath)) + if (!_fileSystem.FileExists(outputPath)) { - await ConvertTextSubtitleToSrtInternal(inputPath, inputProtocol, outputPath, cancellationToken).ConfigureAwait(false); + await ConvertTextSubtitleToSrtInternal(inputPath, language, inputProtocol, outputPath, cancellationToken).ConfigureAwait(false); } } finally @@ -389,7 +394,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles /// outputPath /// /// - private async Task ConvertTextSubtitleToSrtInternal(string inputPath, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) + private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string language, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken) { if (string.IsNullOrEmpty(inputPath)) { @@ -401,9 +406,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException("outputPath"); } - _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); - var encodingParam = await GetSubtitleFileCharacterSet(inputPath, inputProtocol, cancellationToken).ConfigureAwait(false); + var encodingParam = await GetSubtitleFileCharacterSet(inputPath, language, inputProtocol, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(encodingParam)) { @@ -431,7 +436,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); @@ -484,7 +489,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles { failed = true; - if (_fileSystem.FileExists(outputPath)) + if (_fileSystem.FileExists(outputPath)) { try { @@ -497,7 +502,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } } - else if (!_fileSystem.FileExists(outputPath)) + else if (!_fileSystem.FileExists(outputPath)) { failed = true; } @@ -533,7 +538,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles try { - if (!_fileSystem.FileExists(outputPath)) + if (!_fileSystem.FileExists(outputPath)) { await ExtractTextSubtitleInternal(_mediaEncoder.GetInputArgument(inputFiles, protocol), subtitleStreamIndex, outputCodec, outputPath, cancellationToken).ConfigureAwait(false); @@ -558,7 +563,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles throw new ArgumentNullException("outputPath"); } - _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); var processArgs = string.Format("-i {0} -map 0:{1} -an -vn -c:s {2} \"{3}\"", inputPath, subtitleStreamIndex, outputCodec, outputPath); @@ -584,7 +589,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); var logFileStream = _fileSystem.GetFileStream(logFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, true); @@ -653,7 +658,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.ErrorException("Error deleting extracted subtitle {0}", ex, outputPath); } } - else if (!_fileSystem.FileExists(outputPath)) + else if (!_fileSystem.FileExists(outputPath)) { failed = true; } @@ -733,7 +738,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - public async Task GetSubtitleFileCharacterSet(string path, MediaProtocol protocol, CancellationToken cancellationToken) + public async Task GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken) { if (protocol == MediaProtocol.File) { @@ -743,7 +748,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - var charset = await DetectCharset(path, protocol, cancellationToken).ConfigureAwait(false); + var charset = await DetectCharset(path, language, protocol, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(charset)) { @@ -755,6 +760,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles return charset; } + if (!string.IsNullOrWhiteSpace(language)) + { + return GetSubtitleFileCharacterSetFromLanguage(language); + } + return null; } @@ -799,7 +809,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private async Task DetectCharset(string path, MediaProtocol protocol, CancellationToken cancellationToken) + private async Task DetectCharset(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken) { try { @@ -816,6 +826,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.Info("UniversalDetector detected charset {0} for {1}", charset, path); } + // This is often incorrectly indetected. If this happens, try to use other techniques instead + if (string.Equals("x-mac-cyrillic", charset, StringComparison.OrdinalIgnoreCase)) + { + if (!string.IsNullOrWhiteSpace(language)) + { + return null; + } + } + return charset; } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index a080011ec..e5477cfd0 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -776,7 +776,7 @@ namespace MediaBrowser.Model.Dlna } // Look for an external or hls profile that matches the stream type (text/graphical) and doesn't require conversion - return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false) ?? GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false) ?? new SubtitleProfile + return GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, false) ?? GetExternalSubtitleProfile(subtitleStream, subtitleProfiles, playMethod, true) ?? new SubtitleProfile { Method = SubtitleDeliveryMethod.Encode, Format = subtitleStream.Codec From c2d84fc26da028ade684fdd7b924744d9c5fedfb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 12:45:51 -0400 Subject: [PATCH 043/852] 3.0.5925 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index f9f6b86d5..a9922393f 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5924")] +[assembly: AssemblyVersion("3.0.5925")] From 91ee2e22a82773a86832a0ce96a309403ab3bb78 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 13:34:52 -0400 Subject: [PATCH 044/852] update components --- .../MediaBrowser.ServerApplication.csproj | 1 - .../Native/Autorun.cs | 35 ------------------- .../Native/WindowsApp.cs | 18 +++++++++- 3 files changed, 17 insertions(+), 37 deletions(-) delete mode 100644 MediaBrowser.ServerApplication/Native/Autorun.cs diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index a654bd2b5..f1a2915fe 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -110,7 +110,6 @@ MainForm.cs - diff --git a/MediaBrowser.ServerApplication/Native/Autorun.cs b/MediaBrowser.ServerApplication/Native/Autorun.cs deleted file mode 100644 index 4d3f66b91..000000000 --- a/MediaBrowser.ServerApplication/Native/Autorun.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.IO; -using CommonIO; - -namespace MediaBrowser.ServerApplication.Native -{ - /// - /// Class Autorun - /// - public static class Autorun - { - /// - /// Configures the specified autorun. - /// - /// if set to true [autorun]. - /// The file system. - public static void Configure(bool autorun, IFileSystem fileSystem) - { - var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk"); - - var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup); - - if (autorun) - { - //Copy our shortut into the startup folder for this user - File.Copy(shortcutPath, Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"), true); - } - else - { - //Remove our shortcut from the startup folder for this user - fileSystem.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk")); - } - } - } -} diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 056258f96..146a4372b 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Server.Startup.Common; using MediaBrowser.ServerApplication.Networking; using System.Collections.Generic; +using System.IO; using System.Reflection; using CommonIO; using MediaBrowser.Controller.Power; @@ -108,7 +109,22 @@ namespace MediaBrowser.ServerApplication.Native public void ConfigureAutoRun(bool autorun) { - Autorun.Configure(autorun, _fileSystem); + var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk"); + + var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup); + + if (autorun) + { + //Copy our shortut into the startup folder for this user + var targetPath = Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"); + _fileSystem.CreateDirectory(Path.GetDirectoryName(targetPath)); + File.Copy(shortcutPath, targetPath, true); + } + else + { + //Remove our shortcut from the startup folder for this user + _fileSystem.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk")); + } } public INetworkManager CreateNetworkManager(ILogger logger) From 4afc2c9156a266a980d06b6657a74f0f4ad47a65 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 14:23:17 -0400 Subject: [PATCH 045/852] set notification info url --- MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs | 3 ++- MediaBrowser.Model/Updates/PackageVersionInfo.cs | 2 ++ .../EntryPoints/Notifications/Notifications.cs | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs index 82ebf92b2..2ffaedc4b 100644 --- a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs +++ b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs @@ -111,7 +111,8 @@ namespace MediaBrowser.Common.Implementations.Updates targetFilename = targetFilename, versionStr = version.ToString(), requiredVersionStr = "1.0.0", - description = obj.body + description = obj.body, + infoUrl = obj.html_url } }; } diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs index b9bf6e7fe..22404b6f6 100644 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs @@ -87,5 +87,7 @@ namespace MediaBrowser.Model.Updates /// /// The target filename. public string targetFilename { get; set; } + + public string infoUrl { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 918110226..9e68ce4ef 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -116,7 +116,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications var notification = new NotificationRequest { - NotificationType = type + NotificationType = type, + Url = e.Argument.infoUrl }; notification.Variables["Version"] = e.Argument.versionStr; From 66c6bc2e605ab563670342e3c4361cfe9ce48e2a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 16:14:46 -0400 Subject: [PATCH 046/852] 3.0.5912 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index f6c35210c..a088e2601 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5911")] +[assembly: AssemblyVersion("3.0.5912")] From 024d1928df38d69ef642757f30b06536532cadee Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 3 Apr 2016 16:40:32 -0400 Subject: [PATCH 047/852] update mac project --- MediaBrowser.Server.Mac/Emby.Server.Mac.csproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index 01531c3a3..237325cfe 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -1316,6 +1316,9 @@ Resources\dashboard-ui\bower_components\emby-webcomponents\layoutmanager.js + + Resources\dashboard-ui\bower_components\emby-webcomponents\objectassign.js + Resources\dashboard-ui\bower_components\emby-webcomponents\qualityoptions.js @@ -2525,6 +2528,9 @@ Resources\dashboard-ui\bower_components\iron-input\test\letters-only.html + + Resources\dashboard-ui\bower_components\iron-location\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\iron-media-query\.bower.json From 04c8cb5aec70b2ec04fd65c662af7a46cb760b1a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 19:20:43 -0400 Subject: [PATCH 048/852] get dynamic info from hdhr --- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 83 ++++++++++++------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index db7f6f86c..9629f608c 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun return id; } - protected override async Task> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) + private async Task> GetLineup(TunerHostInfo info, CancellationToken cancellationToken) { var options = new HttpRequestOptions { @@ -68,31 +68,31 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun }; using (var stream = await _httpClient.Get(options)) { - var root = JsonSerializer.DeserializeFromStream>(stream); + var lineup = JsonSerializer.DeserializeFromStream>(stream) ?? new List(); - if (root != null) + if (info.ImportFavoritesOnly) { - var result = root.Select(i => new ChannelInfo - { - Name = i.GuideName, - Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), - Id = GetChannelId(info, i), - IsFavorite = i.Favorite, - TunerHostId = info.Id - - }); - - if (info.ImportFavoritesOnly) - { - result = result.Where(i => i.IsFavorite ?? true).ToList(); - } - - return result; + lineup = lineup.Where(i => i.Favorite).ToList(); } - return new List(); + + return lineup; } } + protected override async Task> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken) + { + var lineup = await GetLineup(info, cancellationToken).ConfigureAwait(false); + + return lineup.Select(i => new ChannelInfo + { + Name = i.GuideName, + Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), + Id = GetChannelId(info, i), + IsFavorite = i.Favorite, + TunerHostId = info.Id + }); + } + private async Task GetModelInfo(TunerHostInfo info, CancellationToken cancellationToken) { using (var stream = await _httpClient.Get(new HttpRequestOptions() @@ -226,17 +226,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun { public string GuideNumber { get; set; } public string GuideName { get; set; } + public string VideoCodec { get; set; } + public string AudioCodec { get; set; } public string URL { get; set; } public bool Favorite { get; set; } public bool DRM { get; set; } + public int HD { get; set; } } - private MediaSourceInfo GetMediaSource(TunerHostInfo info, string channelId, string profile) + private async Task GetMediaSource(TunerHostInfo info, string channelId, string profile) { int? width = null; int? height = null; bool isInterlaced = true; - var videoCodec = !string.IsNullOrWhiteSpace(GetEncodingOptions().HardwareAccelerationType) ? null : "mpeg2video"; + string videoCodec = null; + string audioCodec = "ac3"; int? videoBitrate = null; @@ -297,6 +301,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoBitrate = 1000000; } + if (string.IsNullOrWhiteSpace(videoCodec)) + { + var lineup = await GetLineup(info, CancellationToken.None).ConfigureAwait(false); + var channel = lineup.FirstOrDefault(i => string.Equals(i.GuideNumber, channelId, StringComparison.OrdinalIgnoreCase)); + if (channel != null) + { + videoCodec = channel.VideoCodec; + audioCodec = channel.AudioCodec; + + videoBitrate = channel.HD == 1 ? 15000000 : 2000000; + } + } + + // normalize + if (string.Equals(videoCodec, "mpeg2", StringComparison.OrdinalIgnoreCase)) + { + videoCodec = "mpeg2video"; + } + var url = GetApiUrl(info, true) + "/auto/v" + channelId; if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) @@ -327,7 +350,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Type = MediaStreamType.Audio, // Set the index to -1 because we don't know the exact index of the audio stream within the container Index = -1, - Codec = "ac3", + Codec = audioCodec, BitRate = 192000 } }, @@ -364,7 +387,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var hdhrId = GetHdHrIdFromChannelId(channelId); - list.Add(GetMediaSource(info, hdhrId, "native")); + list.Add(await GetMediaSource(info, hdhrId, "native").ConfigureAwait(false)); try { @@ -373,12 +396,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1) { - list.Insert(0, GetMediaSource(info, hdhrId, "heavy")); + list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); - list.Add(GetMediaSource(info, hdhrId, "internet480")); - list.Add(GetMediaSource(info, hdhrId, "internet360")); - list.Add(GetMediaSource(info, hdhrId, "internet240")); - list.Add(GetMediaSource(info, hdhrId, "mobile")); + list.Add(await GetMediaSource(info, hdhrId, "internet480").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "internet360").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "internet240").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "mobile").ConfigureAwait(false)); } } catch (Exception ex) @@ -409,7 +432,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var hdhrId = GetHdHrIdFromChannelId(channelId); - return GetMediaSource(info, hdhrId, streamId); + return await GetMediaSource(info, hdhrId, streamId).ConfigureAwait(false); } public async Task Validate(TunerHostInfo info) From 0bf4d35f533195da40dd31428e74ab23932c89bf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 19:20:56 -0400 Subject: [PATCH 049/852] remove temp file from open subtitles --- .../XML-RPC/XmlRpcGenerator.cs | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs index 5a190ab72..c39917e29 100644 --- a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs +++ b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs @@ -51,47 +51,45 @@ namespace XmlRpcHandler XmlWriterSettings sett = new XmlWriterSettings(); sett.Indent = true; - var requestXmlPath = Path.Combine(Path.GetTempPath(), "request.xml"); - sett.Encoding = Encoding.UTF8; - FileStream str = new FileStream(requestXmlPath, FileMode.Create, FileAccess.Write); - XmlWriter XMLwrt = XmlWriter.Create(str, sett); - // Let's write the methods - foreach (XmlRpcMethodCall method in methods) + using (var ms = new MemoryStream()) { - XMLwrt.WriteStartElement("methodCall");//methodCall - XMLwrt.WriteStartElement("methodName");//methodName - XMLwrt.WriteString(method.Name); - XMLwrt.WriteEndElement();//methodName - XMLwrt.WriteStartElement("params");//params - // Write values - foreach (IXmlRpcValue p in method.Parameters) + XmlWriter XMLwrt = XmlWriter.Create(ms, sett); + // Let's write the methods + foreach (XmlRpcMethodCall method in methods) { - XMLwrt.WriteStartElement("param");//param - if (p is XmlRpcValueBasic) + XMLwrt.WriteStartElement("methodCall");//methodCall + XMLwrt.WriteStartElement("methodName");//methodName + XMLwrt.WriteString(method.Name); + XMLwrt.WriteEndElement();//methodName + XMLwrt.WriteStartElement("params");//params + // Write values + foreach (IXmlRpcValue p in method.Parameters) { - WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p); + XMLwrt.WriteStartElement("param");//param + if (p is XmlRpcValueBasic) + { + WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p); + } + else if (p is XmlRpcValueStruct) + { + WriteStructValue(XMLwrt, (XmlRpcValueStruct)p); + } + else if (p is XmlRpcValueArray) + { + WriteArrayValue(XMLwrt, (XmlRpcValueArray)p); + } + XMLwrt.WriteEndElement();//param } - else if (p is XmlRpcValueStruct) - { - WriteStructValue(XMLwrt, (XmlRpcValueStruct)p); - } - else if (p is XmlRpcValueArray) - { - WriteArrayValue(XMLwrt, (XmlRpcValueArray)p); - } - XMLwrt.WriteEndElement();//param - } - XMLwrt.WriteEndElement();//params - XMLwrt.WriteEndElement();//methodCall + XMLwrt.WriteEndElement();//params + XMLwrt.WriteEndElement();//methodCall + } + XMLwrt.Flush(); + XMLwrt.Close(); + return ms.ToArray(); } - XMLwrt.Flush(); - XMLwrt.Close(); - str.Close(); - string requestContent = File.ReadAllText(requestXmlPath); - return Encoding.UTF8.GetBytes(requestContent); } /// /// Decode response then return the values From d9dcd21c47b95919745ec7b5058383357fd73d65 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 20:01:03 -0400 Subject: [PATCH 050/852] update hdhr streaming --- .../Playback/BaseStreamingService.cs | 23 ++++--------------- .../Playback/Progressive/VideoService.cs | 4 +--- MediaBrowser.Api/Playback/StreamRequest.cs | 3 --- MediaBrowser.Api/Playback/StreamState.cs | 13 ----------- MediaBrowser.Controller/LiveTv/ChannelInfo.cs | 4 ++++ .../MediaEncoding/EncodingJobOptions.cs | 3 --- MediaBrowser.Dlna/Didl/DidlBuilder.cs | 2 -- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 1 - .../Encoder/EncodingJob.cs | 13 ----------- .../Encoder/EncodingJobFactory.cs | 9 -------- MediaBrowser.Model/Dlna/ConditionProcessor.cs | 3 --- .../Dlna/ContentFeatureBuilder.cs | 2 -- MediaBrowser.Model/Dlna/DeviceProfile.cs | 3 +-- .../Dlna/ProfileConditionValue.cs | 1 - MediaBrowser.Model/Dlna/StreamBuilder.cs | 21 ++--------------- MediaBrowser.Model/Dlna/StreamInfo.cs | 18 +++------------ MediaBrowser.Model/Entities/MediaStream.cs | 6 ----- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 13 +++++++---- .../Persistence/SqliteItemRepository.cs | 7 ++---- 19 files changed, 26 insertions(+), 123 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 00ac7be87..108b59494 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1452,10 +1452,7 @@ namespace MediaBrowser.Api.Playback } else if (i == 19) { - if (videoRequest != null) - { - videoRequest.Cabac = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); - } + // cabac no longer used } else if (i == 20) { @@ -1805,10 +1802,10 @@ namespace MediaBrowser.Api.Playback { if (string.IsNullOrEmpty(videoStream.Profile)) { - return false; + //return false; } - if (!string.Equals(request.Profile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(videoStream.Profile) && !string.Equals(request.Profile, videoStream.Profile, StringComparison.OrdinalIgnoreCase)) { var currentScore = GetVideoProfileScore(videoStream.Profile); var requestedScore = GetVideoProfileScore(request.Profile); @@ -1884,24 +1881,16 @@ namespace MediaBrowser.Api.Playback { if (!videoStream.Level.HasValue) { - return false; + //return false; } - if (videoStream.Level.Value > requestLevel) + if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel) { return false; } } } - if (request.Cabac.HasValue && request.Cabac.Value) - { - if (videoStream.IsCabac.HasValue && !videoStream.IsCabac.Value) - { - return false; - } - } - return request.EnableAutoStreamCopy; } @@ -2028,7 +2017,6 @@ namespace MediaBrowser.Api.Playback state.TargetPacketLength, state.TargetTimestamp, state.IsTargetAnamorphic, - state.IsTargetCabac, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, @@ -2131,7 +2119,6 @@ namespace MediaBrowser.Api.Playback state.TargetPacketLength, state.TranscodeSeekInfo, state.IsTargetAnamorphic, - state.IsTargetCabac, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 7c68b1731..b0d87c975 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -137,12 +137,10 @@ namespace MediaBrowser.Api.Playback.Progressive args += " -mpegts_m2ts_mode 1"; } - var isOutputMkv = string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase); - if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) || isOutputMkv)) + (string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase))) { args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 1135a3a54..5167af98a 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -190,9 +190,6 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "CopyTimestamps", Description = "Whether or not to copy timestamps when transcoding with an offset. Defaults to false.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool CopyTimestamps { get; set; } - [ApiMember(Name = "Cabac", Description = "Enable if cabac encoding is required", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] - public bool? Cabac { get; set; } - public VideoStreamRequest() { EnableAutoStreamCopy = true; diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index f1f6bb71f..ed8a27faf 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -480,18 +480,5 @@ namespace MediaBrowser.Api.Playback return false; } } - - public bool? IsTargetCabac - { - get - { - if (Request.Static) - { - return VideoStream == null ? null : VideoStream.IsCabac; - } - - return true; - } - } } } diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs index 7d8df96ed..372b095fd 100644 --- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs +++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs @@ -59,5 +59,9 @@ namespace MediaBrowser.Controller.LiveTv /// /// null if [is favorite] contains no value, true if [is favorite]; otherwise, false. public bool? IsFavorite { get; set; } + + public bool? IsHD { get; set; } + public string AudioCodec { get; set; } + public string VideoCodec { get; set; } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs index ddaf7ff6d..c87ac4e73 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs @@ -58,8 +58,6 @@ namespace MediaBrowser.Controller.MediaEncoding } } - public bool? Cabac { get; set; } - public EncodingJobOptions() { @@ -87,7 +85,6 @@ namespace MediaBrowser.Controller.MediaEncoding MaxRefFrames = info.MaxRefFrames; MaxVideoBitDepth = info.MaxVideoBitDepth; SubtitleMethod = info.SubtitleDeliveryMethod; - Cabac = info.Cabac; Context = info.Context; if (info.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index e8e969a5f..728b397de 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -171,7 +171,6 @@ namespace MediaBrowser.Dlna.Didl streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic, - streamInfo.IsTargetCabac, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, @@ -317,7 +316,6 @@ namespace MediaBrowser.Dlna.Didl streamInfo.TargetPacketLength, streamInfo.TargetTimestamp, streamInfo.IsTargetAnamorphic, - streamInfo.IsTargetCabac, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 314756cdf..db5e0ee29 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -523,7 +523,6 @@ namespace MediaBrowser.Dlna.PlayTo streamInfo.TargetPacketLength, streamInfo.TranscodeSeekInfo, streamInfo.IsTargetAnamorphic, - streamInfo.IsTargetCabac, streamInfo.TargetRefFrames, streamInfo.TargetVideoStreamCount, streamInfo.TargetAudioStreamCount, diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index ae676dbc5..b23bd16f3 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -391,19 +391,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - public bool? IsTargetCabac - { - get - { - if (Options.Static) - { - return VideoStream == null ? null : VideoStream.IsCabac; - } - - return true; - } - } - public int? TargetVideoStreamCount { get diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index f782fd05f..070aae3a7 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -664,14 +664,6 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - if (request.Cabac.HasValue && request.Cabac.Value) - { - if (videoStream.IsCabac.HasValue && !videoStream.IsCabac.Value) - { - return false; - } - } - return request.EnableAutoStreamCopy; } @@ -773,7 +765,6 @@ namespace MediaBrowser.MediaEncoding.Encoder state.TargetPacketLength, state.TargetTimestamp, state.IsTargetAnamorphic, - state.IsTargetCabac, state.TargetRefFrames, state.TargetVideoStreamCount, state.TargetAudioStreamCount, diff --git a/MediaBrowser.Model/Dlna/ConditionProcessor.cs b/MediaBrowser.Model/Dlna/ConditionProcessor.cs index fef04647a..69f1369dc 100644 --- a/MediaBrowser.Model/Dlna/ConditionProcessor.cs +++ b/MediaBrowser.Model/Dlna/ConditionProcessor.cs @@ -17,7 +17,6 @@ namespace MediaBrowser.Model.Dlna int? packetLength, TransportStreamTimestamp? timestamp, bool? isAnamorphic, - bool? isCabac, int? refFrames, int? numVideoStreams, int? numAudioStreams, @@ -27,8 +26,6 @@ namespace MediaBrowser.Model.Dlna { case ProfileConditionValue.IsAnamorphic: return IsConditionSatisfied(condition, isAnamorphic); - case ProfileConditionValue.IsCabac: - return IsConditionSatisfied(condition, isCabac); case ProfileConditionValue.VideoFramerate: return IsConditionSatisfied(condition, videoFramerate); case ProfileConditionValue.VideoLevel: diff --git a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs index 58d669c22..c4b3383a2 100644 --- a/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs +++ b/MediaBrowser.Model/Dlna/ContentFeatureBuilder.cs @@ -115,7 +115,6 @@ namespace MediaBrowser.Model.Dlna int? packetLength, TranscodeSeekInfo transcodeSeekInfo, bool? isAnamorphic, - bool? isCabac, int? refFrames, int? numVideoStreams, int? numAudioStreams, @@ -157,7 +156,6 @@ namespace MediaBrowser.Model.Dlna packetLength, timestamp, isAnamorphic, - isCabac, refFrames, numVideoStreams, numAudioStreams, diff --git a/MediaBrowser.Model/Dlna/DeviceProfile.cs b/MediaBrowser.Model/Dlna/DeviceProfile.cs index 80c060c49..423928f62 100644 --- a/MediaBrowser.Model/Dlna/DeviceProfile.cs +++ b/MediaBrowser.Model/Dlna/DeviceProfile.cs @@ -283,7 +283,6 @@ namespace MediaBrowser.Model.Dlna int? packetLength, TransportStreamTimestamp timestamp, bool? isAnamorphic, - bool? isCabac, int? refFrames, int? numVideoStreams, int? numAudioStreams, @@ -321,7 +320,7 @@ namespace MediaBrowser.Model.Dlna var anyOff = false; foreach (ProfileCondition c in i.Conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(c, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) + if (!conditionProcessor.IsVideoConditionSatisfied(c, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { anyOff = true; break; diff --git a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs index 4ad326e51..c17a09c3f 100644 --- a/MediaBrowser.Model/Dlna/ProfileConditionValue.cs +++ b/MediaBrowser.Model/Dlna/ProfileConditionValue.cs @@ -17,7 +17,6 @@ VideoTimestamp = 12, IsAnamorphic = 13, RefFrames = 14, - IsCabac = 15, NumAudioStreams = 16, NumVideoStreams = 17, IsSecondaryAudio = 18, diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index e5477cfd0..f80c52e38 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -597,7 +597,6 @@ namespace MediaBrowser.Model.Dlna string videoProfile = videoStream == null ? null : videoStream.Profile; float? videoFramerate = videoStream == null ? null : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate; bool? isAnamorphic = videoStream == null ? null : videoStream.IsAnamorphic; - bool? isCabac = videoStream == null ? null : videoStream.IsCabac; string videoCodecTag = videoStream == null ? null : videoStream.CodecTag; int? audioBitrate = audioStream == null ? null : audioStream.BitRate; @@ -614,7 +613,7 @@ namespace MediaBrowser.Model.Dlna // Check container conditions foreach (ProfileCondition i in conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) + if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { LogConditionFailure(profile, "VideoContainerProfile", i, mediaSource); @@ -647,7 +646,7 @@ namespace MediaBrowser.Model.Dlna foreach (ProfileCondition i in conditions) { - if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, isCabac, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) + if (!conditionProcessor.IsVideoConditionSatisfied(i, width, height, bitDepth, videoBitrate, videoProfile, videoLevel, videoFramerate, packetLength, timestamp, isAnamorphic, refFrames, numVideoStreams, numAudioStreams, videoCodecTag)) { LogConditionFailure(profile, "VideoCodecProfile", i, mediaSource); @@ -910,22 +909,6 @@ namespace MediaBrowser.Model.Dlna } break; } - case ProfileConditionValue.IsCabac: - { - bool val; - if (BoolHelper.TryParseCultureInvariant(value, out val)) - { - if (condition.Condition == ProfileConditionType.Equals) - { - item.Cabac = val; - } - else if (condition.Condition == ProfileConditionType.NotEquals) - { - item.Cabac = !val; - } - } - break; - } case ProfileConditionValue.IsAnamorphic: case ProfileConditionValue.AudioProfile: case ProfileConditionValue.Has64BitOffsets: diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 436ed2071..a2867dcc9 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -30,7 +30,6 @@ namespace MediaBrowser.Model.Dlna public string VideoCodec { get; set; } public string VideoProfile { get; set; } - public bool? Cabac { get; set; } public bool CopyTimestamps { get; set; } public string AudioCodec { get; set; } @@ -219,7 +218,9 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("MaxRefFrames", item.MaxRefFrames.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxRefFrames.Value) : string.Empty)); list.Add(new NameValuePair("MaxVideoBitDepth", item.MaxVideoBitDepth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxVideoBitDepth.Value) : string.Empty)); list.Add(new NameValuePair("Profile", item.VideoProfile ?? string.Empty)); - list.Add(new NameValuePair("Cabac", item.Cabac.HasValue ? item.Cabac.Value.ToString() : string.Empty)); + + // no longer used + list.Add(new NameValuePair("Cabac", string.Empty)); list.Add(new NameValuePair("PlaySessionId", item.PlaySessionId ?? string.Empty)); list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); @@ -632,19 +633,6 @@ namespace MediaBrowser.Model.Dlna } } - public bool? IsTargetCabac - { - get - { - if (IsDirectStream) - { - return TargetVideoStream == null ? null : TargetVideoStream.IsCabac; - } - - return true; - } - } - public int? TargetWidth { get diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 79fa46baf..bdc043e9a 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -232,11 +232,5 @@ namespace MediaBrowser.Model.Entities /// /// true if this instance is anamorphic; otherwise, false. public bool? IsAnamorphic { get; set; } - - /// - /// Gets or sets a value indicating whether this instance is cabac. - /// - /// null if [is cabac] contains no value, true if [is cabac]; otherwise, false. - public bool? IsCabac { get; set; } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 9629f608c..ef8efbe98 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -89,7 +89,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Number = i.GuideNumber.ToString(CultureInfo.InvariantCulture), Id = GetChannelId(info, i), IsFavorite = i.Favorite, - TunerHostId = info.Id + TunerHostId = info.Id, + IsHD = i.HD == 1, + AudioCodec = i.AudioCodec, + VideoCodec = i.VideoCodec }); } @@ -303,14 +306,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun if (string.IsNullOrWhiteSpace(videoCodec)) { - var lineup = await GetLineup(info, CancellationToken.None).ConfigureAwait(false); - var channel = lineup.FirstOrDefault(i => string.Equals(i.GuideNumber, channelId, StringComparison.OrdinalIgnoreCase)); + var channels = await GetChannels(info, true, CancellationToken.None).ConfigureAwait(false); + var channel = channels.FirstOrDefault(i => string.Equals(i.Number, channelId, StringComparison.OrdinalIgnoreCase)); if (channel != null) { videoCodec = channel.VideoCodec; audioCodec = channel.AudioCodec; - videoBitrate = channel.HD == 1 ? 15000000 : 2000000; + videoBitrate = (channel.IsHD ?? true) ? 15000000 : 2000000; } } @@ -343,7 +346,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Width = width, Height = height, BitRate = videoBitrate - + }, new MediaStream { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index eda0a263a..71c338fdb 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2755,7 +2755,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - _saveStreamCommand.GetParameter(index++).Value = stream.IsCabac; + _saveStreamCommand.GetParameter(index++).Value = null; _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; @@ -2907,10 +2907,7 @@ namespace MediaBrowser.Server.Implementations.Persistence item.RefFrames = reader.GetInt32(24); } - if (!reader.IsDBNull(25)) - { - item.IsCabac = reader.GetBoolean(25); - } + // cabac no longer used if (!reader.IsDBNull(26)) { From 25125377e53ac1ff795dd43876ebc08afe04bfc5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 00:18:36 -0400 Subject: [PATCH 051/852] update hls --- .../Playback/BaseStreamingService.cs | 7 +++++-- .../Playback/Hls/DynamicHlsService.cs | 21 +++++++++++++++---- .../Api/PackageCreator.cs | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 108b59494..9e9bfd728 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1677,7 +1677,7 @@ namespace MediaBrowser.Api.Playback private void TryStreamCopy(StreamState state, VideoStreamRequest videoRequest) { - if (state.VideoStream != null && CanStreamCopyVideo(videoRequest, state.VideoStream)) + if (state.VideoStream != null && CanStreamCopyVideo(state)) { state.OutputVideoCodec = "copy"; } @@ -1770,8 +1770,11 @@ namespace MediaBrowser.Api.Playback state.MediaSource = mediaSource; } - protected virtual bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream) + protected virtual bool CanStreamCopyVideo(StreamState state) { + var request = state.VideoRequest; + var videoStream = state.VideoStream; + if (videoStream.IsInterlaced) { return false; diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 3e46ee426..c7fe50941 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -500,13 +500,20 @@ namespace MediaBrowser.Api.Playback.Hls return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary()); } + private bool IsLiveStream(StreamState state) + { + var isLiveStream = (state.RunTimeTicks ?? 0) == 0; + + return isLiveStream; + } + private string GetMasterPlaylistFileText(StreamState state, int totalBitrate) { var builder = new StringBuilder(); builder.AppendLine("#EXTM3U"); - var isLiveStream = (state.RunTimeTicks ?? 0) == 0; + var isLiveStream = IsLiveStream(state); var queryStringIndex = Request.RawUrl.IndexOf('?'); var queryString = queryStringIndex == -1 ? string.Empty : Request.RawUrl.Substring(queryStringIndex); @@ -929,10 +936,16 @@ namespace MediaBrowser.Api.Playback.Hls return isOutputVideo ? ".ts" : ".ts"; } - protected override bool CanStreamCopyVideo(VideoStreamRequest request, MediaStream videoStream) + protected override bool CanStreamCopyVideo(StreamState state) { - return false; - //return base.CanStreamCopyVideo(request, videoStream); + var isLiveStream = IsLiveStream(state); + + if (!isLiveStream) + { + return false; + } + + return base.CanStreamCopyVideo(state); } } } \ No newline at end of file diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index 79e2d6102..01c2a4104 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -477,7 +477,7 @@ namespace MediaBrowser.WebDashboard.Api var tags = files.Select(s => { - if (s.IndexOf("require", StringComparison.OrdinalIgnoreCase) == -1) + if (s.IndexOf("require", StringComparison.OrdinalIgnoreCase) == -1 && s.IndexOf("alameda", StringComparison.OrdinalIgnoreCase) == -1) { return string.Format("", s); } From 64795ef35b8291bee4de409af5bb267f66aa71d3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 01:07:10 -0400 Subject: [PATCH 052/852] update hls stream copy rules --- MediaBrowser.Api/MediaBrowser.Api.csproj | 2 - .../Playback/BaseStreamingService.cs | 19 +- .../Playback/Dash/ManifestBuilder.cs | 224 ------- .../Playback/Dash/MpegDashService.cs | 547 ------------------ .../Playback/Hls/BaseHlsService.cs | 61 +- .../Playback/Hls/DynamicHlsService.cs | 5 + .../Playback/Hls/HlsSegmentService.cs | 19 - .../Playback/Hls/VideoHlsService.cs | 10 - MediaBrowser.Api/Playback/StreamRequest.cs | 4 +- MediaBrowser.Model/Dlna/StreamBuilder.cs | 9 +- 10 files changed, 49 insertions(+), 851 deletions(-) delete mode 100644 MediaBrowser.Api/Playback/Dash/ManifestBuilder.cs delete mode 100644 MediaBrowser.Api/Playback/Dash/MpegDashService.cs diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index cdc0cd6ae..db8961a66 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -80,8 +80,6 @@ - - diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9e9bfd728..dfa279019 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1026,7 +1026,7 @@ namespace MediaBrowser.Api.Playback StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream); // Wait for the file to exist before proceeeding - while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) + while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) { await Task.Delay(100, cancellationTokenSource.Token).ConfigureAwait(false); } @@ -1651,9 +1651,9 @@ namespace MediaBrowser.Api.Playback if (state.OutputVideoBitrate.HasValue) { var resolution = ResolutionNormalizer.Normalize( - state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, - state.OutputVideoBitrate.Value, - state.VideoStream == null ? null : state.VideoStream.Codec, + state.VideoStream == null ? (int?)null : state.VideoStream.BitRate, + state.OutputVideoBitrate.Value, + state.VideoStream == null ? null : state.VideoStream.Codec, state.OutputVideoCodec, videoRequest.MaxWidth, videoRequest.MaxHeight); @@ -1682,7 +1682,7 @@ namespace MediaBrowser.Api.Playback state.OutputVideoCodec = "copy"; } - if (state.AudioStream != null && CanStreamCopyAudio(videoRequest, state.AudioStream, state.SupportedAudioCodecs)) + if (state.AudioStream != null && CanStreamCopyAudio(state, state.SupportedAudioCodecs)) { state.OutputAudioCodec = "copy"; } @@ -1784,7 +1784,7 @@ namespace MediaBrowser.Api.Playback { return false; } - + // Can't stream copy if we're burning in subtitles if (request.SubtitleStreamIndex.HasValue) { @@ -1913,8 +1913,11 @@ namespace MediaBrowser.Api.Playback return Array.FindIndex(list.ToArray(), t => string.Equals(t, profile, StringComparison.OrdinalIgnoreCase)); } - protected virtual bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List supportedAudioCodecs) + protected virtual bool CanStreamCopyAudio(StreamState state, List supportedAudioCodecs) { + var request = state.VideoRequest; + var audioStream = state.AudioStream; + // Source and target codecs must match if (string.IsNullOrEmpty(audioStream.Codec) || !supportedAudioCodecs.Contains(audioStream.Codec, StringComparer.OrdinalIgnoreCase)) { @@ -2213,7 +2216,7 @@ namespace MediaBrowser.Api.Playback inputModifier += " -noaccurate_seek"; } } - + return inputModifier; } diff --git a/MediaBrowser.Api/Playback/Dash/ManifestBuilder.cs b/MediaBrowser.Api/Playback/Dash/ManifestBuilder.cs deleted file mode 100644 index 35e252a19..000000000 --- a/MediaBrowser.Api/Playback/Dash/ManifestBuilder.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Globalization; -using System.Security; -using System.Text; - -namespace MediaBrowser.Api.Playback.Dash -{ - public class ManifestBuilder - { - protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public string GetManifestText(StreamState state, string playlistUrl) - { - var builder = new StringBuilder(); - - var time = TimeSpan.FromTicks(state.RunTimeTicks.Value); - - var duration = "PT" + time.Hours.ToString("00", UsCulture) + "H" + time.Minutes.ToString("00", UsCulture) + "M" + time.Seconds.ToString("00", UsCulture) + ".00S"; - - builder.Append(""); - - builder.AppendFormat( - "", - duration); - - builder.Append(""); - builder.Append(""); - - builder.Append(""); - builder.Append(GetVideoAdaptationSet(state, playlistUrl)); - builder.Append(GetAudioAdaptationSet(state, playlistUrl)); - builder.Append(""); - - builder.Append(""); - - return builder.ToString(); - } - - private string GetVideoAdaptationSet(StreamState state, string playlistUrl) - { - var builder = new StringBuilder(); - - builder.Append(""); - builder.Append(GetVideoRepresentationOpenElement(state)); - - AppendSegmentList(state, builder, "0", playlistUrl); - - builder.Append(""); - builder.Append(""); - - return builder.ToString(); - } - - private string GetAudioAdaptationSet(StreamState state, string playlistUrl) - { - var builder = new StringBuilder(); - - builder.Append(""); - builder.Append(GetAudioRepresentationOpenElement(state)); - - builder.Append(""); - - AppendSegmentList(state, builder, "1", playlistUrl); - - builder.Append(""); - builder.Append(""); - - return builder.ToString(); - } - - private string GetVideoRepresentationOpenElement(StreamState state) - { - var codecs = GetVideoCodecDescriptor(state); - - var mime = "video/mp4"; - - var xml = "= 4.1) - { - return "avc1.640028"; - } - - if (level >= 4) - { - return "avc1.640028"; - } - - return "avc1.64001f"; - } - - if (profile.IndexOf("main", StringComparison.OrdinalIgnoreCase) != -1) - { - if (level >= 4) - { - return "avc1.4d0028"; - } - - if (level >= 3.1) - { - return "avc1.4d001f"; - } - - return "avc1.4d001e"; - } - - if (level >= 3.1) - { - return "avc1.42001f"; - } - - return "avc1.42E01E"; - } - - private string GetAudioCodecDescriptor(StreamState state) - { - // https://developer.apple.com/library/ios/documentation/networkinginternet/conceptual/streamingmediaguide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html - - if (string.Equals(state.OutputAudioCodec, "mp3", StringComparison.OrdinalIgnoreCase)) - { - return "mp4a.40.34"; - } - - // AAC 5ch - if (state.OutputAudioChannels.HasValue && state.OutputAudioChannels.Value >= 5) - { - return "mp4a.40.5"; - } - - // AAC 2ch - return "mp4a.40.2"; - } - - private void AppendSegmentList(StreamState state, StringBuilder builder, string type, string playlistUrl) - { - var extension = ".m4s"; - - var seconds = TimeSpan.FromTicks(state.RunTimeTicks ?? 0).TotalSeconds; - - var queryStringIndex = playlistUrl.IndexOf('?'); - var queryString = queryStringIndex == -1 ? string.Empty : playlistUrl.Substring(queryStringIndex); - - var index = 0; - var duration = 1000000 * state.SegmentLength; - builder.AppendFormat("", duration.ToString(CultureInfo.InvariantCulture)); - - while (seconds > 0) - { - var filename = index == 0 - ? "init" - : (index - 1).ToString(UsCulture); - - var segmentUrl = string.Format("dash/{3}/{0}{1}{2}", - filename, - extension, - SecurityElement.Escape(queryString), - type); - - if (index == 0) - { - builder.AppendFormat("", segmentUrl); - } - else - { - builder.AppendFormat("", segmentUrl); - } - - seconds -= state.SegmentLength; - index++; - } - builder.Append(""); - } - } -} diff --git a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs b/MediaBrowser.Api/Playback/Dash/MpegDashService.cs deleted file mode 100644 index a35d13c5b..000000000 --- a/MediaBrowser.Api/Playback/Dash/MpegDashService.cs +++ /dev/null @@ -1,547 +0,0 @@ -using MediaBrowser.Api.Playback.Hls; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Devices; -using MediaBrowser.Controller.Dlna; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Serialization; -using ServiceStack; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using CommonIO; -using MimeTypes = MediaBrowser.Model.Net.MimeTypes; - -namespace MediaBrowser.Api.Playback.Dash -{ - /// - /// Options is needed for chromecast. Threw Head in there since it's related - /// - [Route("/Videos/{Id}/master.mpd", "GET", Summary = "Gets a video stream using Mpeg dash.")] - [Route("/Videos/{Id}/master.mpd", "HEAD", Summary = "Gets a video stream using Mpeg dash.")] - public class GetMasterManifest : VideoStreamRequest - { - public bool EnableAdaptiveBitrateStreaming { get; set; } - - public GetMasterManifest() - { - EnableAdaptiveBitrateStreaming = true; - } - } - - [Route("/Videos/{Id}/dash/{RepresentationId}/{SegmentId}.m4s", "GET")] - public class GetDashSegment : VideoStreamRequest - { - /// - /// Gets or sets the segment id. - /// - /// The segment id. - public string SegmentId { get; set; } - - /// - /// Gets or sets the representation identifier. - /// - /// The representation identifier. - public string RepresentationId { get; set; } - } - - public class MpegDashService : BaseHlsService - { - public MpegDashService(IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, IIsoManager isoManager, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IDlnaManager dlnaManager, ISubtitleEncoder subtitleEncoder, IDeviceManager deviceManager, IMediaSourceManager mediaSourceManager, IZipClient zipClient, IJsonSerializer jsonSerializer, INetworkManager networkManager) : base(serverConfig, userManager, libraryManager, isoManager, mediaEncoder, fileSystem, dlnaManager, subtitleEncoder, deviceManager, mediaSourceManager, zipClient, jsonSerializer) - { - NetworkManager = networkManager; - } - - protected INetworkManager NetworkManager { get; private set; } - - public object Get(GetMasterManifest request) - { - var result = GetAsync(request, "GET").Result; - - return result; - } - - public object Head(GetMasterManifest request) - { - var result = GetAsync(request, "HEAD").Result; - - return result; - } - - protected override bool EnableOutputInSubFolder - { - get - { - return true; - } - } - - private async Task GetAsync(GetMasterManifest request, string method) - { - if (string.IsNullOrEmpty(request.MediaSourceId)) - { - throw new ArgumentException("MediaSourceId is required"); - } - - var state = await GetState(request, CancellationToken.None).ConfigureAwait(false); - - var playlistText = string.Empty; - - if (string.Equals(method, "GET", StringComparison.OrdinalIgnoreCase)) - { - playlistText = new ManifestBuilder().GetManifestText(state, Request.RawUrl); - } - - return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.mpd"), new Dictionary()); - } - - public object Get(GetDashSegment request) - { - return GetDynamicSegment(request, request.SegmentId, request.RepresentationId).Result; - } - - private async Task GetDynamicSegment(VideoStreamRequest request, string segmentId, string representationId) - { - if ((request.StartTimeTicks ?? 0) > 0) - { - throw new ArgumentException("StartTimeTicks is not allowed."); - } - - var cancellationTokenSource = new CancellationTokenSource(); - var cancellationToken = cancellationTokenSource.Token; - - var requestedIndex = string.Equals(segmentId, "init", StringComparison.OrdinalIgnoreCase) ? - -1 : - int.Parse(segmentId, NumberStyles.Integer, UsCulture); - - var state = await GetState(request, cancellationToken).ConfigureAwait(false); - - var playlistPath = Path.ChangeExtension(state.OutputFilePath, ".mpd"); - - var segmentExtension = GetSegmentFileExtension(state); - - var segmentPath = FindSegment(playlistPath, representationId, segmentExtension, requestedIndex); - var segmentLength = state.SegmentLength; - - TranscodingJob job = null; - - if (!string.IsNullOrWhiteSpace(segmentPath)) - { - job = ApiEntryPoint.Instance.GetTranscodingJob(playlistPath, TranscodingJobType); - return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false); - } - - await ApiEntryPoint.Instance.TranscodingStartLock.WaitAsync(cancellationTokenSource.Token).ConfigureAwait(false); - try - { - segmentPath = FindSegment(playlistPath, representationId, segmentExtension, requestedIndex); - if (!string.IsNullOrWhiteSpace(segmentPath)) - { - job = ApiEntryPoint.Instance.GetTranscodingJob(playlistPath, TranscodingJobType); - return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job, cancellationToken).ConfigureAwait(false); - } - else - { - if (string.Equals(representationId, "0", StringComparison.OrdinalIgnoreCase)) - { - job = ApiEntryPoint.Instance.GetTranscodingJob(playlistPath, TranscodingJobType); - var currentTranscodingIndex = GetCurrentTranscodingIndex(playlistPath, segmentExtension); - var segmentGapRequiringTranscodingChange = 24 / state.SegmentLength; - Logger.Debug("Current transcoding index is {0}. requestedIndex={1}. segmentGapRequiringTranscodingChange={2}", currentTranscodingIndex ?? -2, requestedIndex, segmentGapRequiringTranscodingChange); - if (currentTranscodingIndex == null || requestedIndex < currentTranscodingIndex.Value || requestedIndex - currentTranscodingIndex.Value > segmentGapRequiringTranscodingChange) - { - // If the playlist doesn't already exist, startup ffmpeg - try - { - ApiEntryPoint.Instance.KillTranscodingJobs(request.DeviceId, request.PlaySessionId, p => false); - - if (currentTranscodingIndex.HasValue) - { - DeleteLastTranscodedFiles(playlistPath, 0); - } - - var positionTicks = GetPositionTicks(state, requestedIndex); - request.StartTimeTicks = positionTicks; - - var startNumber = GetStartNumber(state); - - var workingDirectory = Path.Combine(Path.GetDirectoryName(playlistPath), (startNumber == -1 ? 0 : startNumber).ToString(CultureInfo.InvariantCulture)); - state.WaitForPath = Path.Combine(workingDirectory, Path.GetFileName(playlistPath)); - FileSystem.CreateDirectory(workingDirectory); - job = await StartFfMpeg(state, playlistPath, cancellationTokenSource, workingDirectory).ConfigureAwait(false); - await WaitForMinimumDashSegmentCount(Path.Combine(workingDirectory, Path.GetFileName(playlistPath)), 1, cancellationTokenSource.Token).ConfigureAwait(false); - } - catch - { - state.Dispose(); - throw; - } - } - } - } - } - finally - { - ApiEntryPoint.Instance.TranscodingStartLock.Release(); - } - - while (string.IsNullOrWhiteSpace(segmentPath)) - { - segmentPath = FindSegment(playlistPath, representationId, segmentExtension, requestedIndex); - await Task.Delay(50, cancellationToken).ConfigureAwait(false); - } - - Logger.Info("returning {0}", segmentPath); - return await GetSegmentResult(playlistPath, segmentPath, requestedIndex, segmentLength, job ?? ApiEntryPoint.Instance.GetTranscodingJob(playlistPath, TranscodingJobType), cancellationToken).ConfigureAwait(false); - } - - private long GetPositionTicks(StreamState state, int requestedIndex) - { - if (requestedIndex <= 0) - { - return 0; - } - - var startSeconds = requestedIndex * state.SegmentLength; - return TimeSpan.FromSeconds(startSeconds).Ticks; - } - - protected Task WaitForMinimumDashSegmentCount(string playlist, int segmentCount, CancellationToken cancellationToken) - { - return WaitForSegment(playlist, "stream0-" + segmentCount.ToString("00000", CultureInfo.InvariantCulture) + ".m4s", cancellationToken); - } - - private async Task GetSegmentResult(string playlistPath, - string segmentPath, - int segmentIndex, - int segmentLength, - TranscodingJob transcodingJob, - CancellationToken cancellationToken) - { - // If all transcoding has completed, just return immediately - if (transcodingJob != null && transcodingJob.HasExited) - { - return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob); - } - - // Wait for the file to stop being written to, then stream it - var length = new FileInfo(segmentPath).Length; - var eofCount = 0; - - while (eofCount < 10) - { - var info = new FileInfo(segmentPath); - - if (!info.Exists) - { - break; - } - - var newLength = info.Length; - - if (newLength == length) - { - eofCount++; - } - else - { - eofCount = 0; - } - - length = newLength; - await Task.Delay(100, cancellationToken).ConfigureAwait(false); - } - - return GetSegmentResult(segmentPath, segmentIndex, segmentLength, transcodingJob); - } - - private object GetSegmentResult(string segmentPath, int index, int segmentLength, TranscodingJob transcodingJob) - { - var segmentEndingSeconds = (1 + index) * segmentLength; - var segmentEndingPositionTicks = TimeSpan.FromSeconds(segmentEndingSeconds).Ticks; - - return ResultFactory.GetStaticFileResult(Request, new StaticFileResultOptions - { - Path = segmentPath, - FileShare = FileShare.ReadWrite, - OnComplete = () => - { - if (transcodingJob != null) - { - transcodingJob.DownloadPositionTicks = Math.Max(transcodingJob.DownloadPositionTicks ?? segmentEndingPositionTicks, segmentEndingPositionTicks); - } - - } - }); - } - - public int? GetCurrentTranscodingIndex(string playlist, string segmentExtension) - { - var job = ApiEntryPoint.Instance.GetTranscodingJob(playlist, TranscodingJobType); - - if (job == null || job.HasExited) - { - return null; - } - - var file = GetLastTranscodingFiles(playlist, segmentExtension, FileSystem, 1).FirstOrDefault(); - - if (file == null) - { - return null; - } - - return GetIndex(file.FullName); - } - - public int GetIndex(string segmentPath) - { - var indexString = Path.GetFileNameWithoutExtension(segmentPath).Split('-').LastOrDefault(); - - if (string.Equals(indexString, "init", StringComparison.OrdinalIgnoreCase)) - { - return -1; - } - var startNumber = int.Parse(Path.GetFileNameWithoutExtension(Path.GetDirectoryName(segmentPath)), NumberStyles.Integer, UsCulture); - - return startNumber + int.Parse(indexString, NumberStyles.Integer, UsCulture) - 1; - } - - private void DeleteLastTranscodedFiles(string playlistPath, int retryCount) - { - if (retryCount >= 5) - { - return; - } - } - - private static List GetLastTranscodingFiles(string playlist, string segmentExtension, IFileSystem fileSystem, int count) - { - var folder = Path.GetDirectoryName(playlist); - - try - { - return fileSystem.GetFiles(folder) - .Where(i => string.Equals(i.Extension, segmentExtension, StringComparison.OrdinalIgnoreCase)) - .OrderByDescending(fileSystem.GetLastWriteTimeUtc) - .Take(count) - .ToList(); - } - catch (DirectoryNotFoundException) - { - return new List(); - } - } - - private string FindSegment(string playlist, string representationId, string segmentExtension, int requestedIndex) - { - var folder = Path.GetDirectoryName(playlist); - - if (requestedIndex == -1) - { - var path = Path.Combine(folder, "0", "stream" + representationId + "-" + "init" + segmentExtension); - return FileSystem.FileExists(path) ? path : null; - } - - try - { - foreach (var subfolder in FileSystem.GetDirectoryPaths(folder).ToList()) - { - var subfolderName = Path.GetFileNameWithoutExtension(subfolder); - int startNumber; - if (int.TryParse(subfolderName, NumberStyles.Any, UsCulture, out startNumber)) - { - var segmentIndex = requestedIndex - startNumber + 1; - var path = Path.Combine(folder, subfolderName, "stream" + representationId + "-" + segmentIndex.ToString("00000", CultureInfo.InvariantCulture) + segmentExtension); - if (FileSystem.FileExists(path)) - { - return path; - } - } - } - } - catch (DirectoryNotFoundException) - { - - } - - return null; - } - - protected override string GetAudioArguments(StreamState state) - { - var codec = GetAudioEncoder(state); - - if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) - { - return "-codec:a:0 copy"; - } - - var args = "-codec:a:0 " + codec; - - var channels = state.OutputAudioChannels; - - if (channels.HasValue) - { - args += " -ac " + channels.Value; - } - - var bitrate = state.OutputAudioBitrate; - - if (bitrate.HasValue) - { - args += " -ab " + bitrate.Value.ToString(UsCulture); - } - - args += " " + GetAudioFilterParam(state, true); - - return args; - } - - protected override string GetVideoArguments(StreamState state) - { - var codec = GetVideoEncoder(state); - - var args = "-codec:v:0 " + codec; - - if (state.EnableMpegtsM2TsMode) - { - args += " -mpegts_m2ts_mode 1"; - } - - // See if we can save come cpu cycles by avoiding encoding - if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) - { - return state.VideoStream != null && IsH264(state.VideoStream) ? - args + " -bsf:v h264_mp4toannexb" : - args; - } - - var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})", - state.SegmentLength.ToString(UsCulture)); - - var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream; - - args += " " + GetVideoQualityParam(state, GetH264Encoder(state)) + keyFrameArg; - - // Add resolution params, if specified - if (!hasGraphicalSubs) - { - args += GetOutputSizeParam(state, codec, false); - } - - // This is for internal graphical subs - if (hasGraphicalSubs) - { - args += GetGraphicalSubtitleParam(state, codec); - } - - return args; - } - - protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding) - { - // test url http://192.168.1.2:8096/videos/233e8905d559a8f230db9bffd2ac9d6d/master.mpd?mediasourceid=233e8905d559a8f230db9bffd2ac9d6d&videocodec=h264&audiocodec=aac&maxwidth=1280&videobitrate=500000&audiobitrate=128000&profile=baseline&level=3 - // Good info on i-frames http://blog.streamroot.io/encode-multi-bitrate-videos-mpeg-dash-mse-based-media-players/ - - var threads = GetNumberOfThreads(state, false); - - var inputModifier = GetInputModifier(state); - - var initSegmentName = "stream$RepresentationID$-init.m4s"; - var segmentName = "stream$RepresentationID$-$Number%05d$.m4s"; - - var args = string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -copyts {5} -f dash -init_seg_name \"{6}\" -media_seg_name \"{7}\" -use_template 0 -use_timeline 1 -min_seg_duration {8} -y \"{9}\"", - inputModifier, - GetInputArgument(state), - threads, - GetMapArgs(state), - GetVideoArguments(state), - GetAudioArguments(state), - initSegmentName, - segmentName, - (state.SegmentLength * 1000000).ToString(CultureInfo.InvariantCulture), - state.WaitForPath - ).Trim(); - - return args; - } - - protected override int GetStartNumber(StreamState state) - { - return GetStartNumber(state.VideoRequest); - } - - private int GetStartNumber(VideoStreamRequest request) - { - var segmentId = "0"; - - var segmentRequest = request as GetDashSegment; - if (segmentRequest != null) - { - segmentId = segmentRequest.SegmentId; - } - - if (string.Equals(segmentId, "init", StringComparison.OrdinalIgnoreCase)) - { - return -1; - } - - return int.Parse(segmentId, NumberStyles.Integer, UsCulture); - } - - /// - /// Gets the segment file extension. - /// - /// The state. - /// System.String. - protected override string GetSegmentFileExtension(StreamState state) - { - return ".m4s"; - } - - protected override TranscodingJobType TranscodingJobType - { - get - { - return TranscodingJobType.Dash; - } - } - - private async Task WaitForSegment(string playlist, string segment, CancellationToken cancellationToken) - { - var segmentFilename = Path.GetFileName(segment); - - Logger.Debug("Waiting for {0} in {1}", segmentFilename, playlist); - - while (true) - { - // Need to use FileShare.ReadWrite because we're reading the file at the same time it's being written - using (var fileStream = GetPlaylistFileStream(playlist)) - { - using (var reader = new StreamReader(fileStream)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - if (line.IndexOf(segmentFilename, StringComparison.OrdinalIgnoreCase) != -1) - { - Logger.Debug("Finished waiting for {0} in {1}", segmentFilename, playlist); - return; - } - } - await Task.Delay(100, cancellationToken).ConfigureAwait(false); - } - } - } - } - } -} diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index c11265742..cb344690c 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -83,11 +83,6 @@ namespace MediaBrowser.Api.Playback.Hls var state = await GetState(request, cancellationTokenSource.Token).ConfigureAwait(false); - if (isLive) - { - state.Request.StartTimeTicks = null; - } - TranscodingJob job = null; var playlist = state.OutputFilePath; @@ -137,13 +132,6 @@ namespace MediaBrowser.Api.Playback.Hls var appendBaselineStream = false; var baselineStreamBitrate = 64000; - var hlsVideoRequest = state.VideoRequest as GetHlsVideoStreamLegacy; - if (hlsVideoRequest != null) - { - appendBaselineStream = hlsVideoRequest.AppendBaselineStream; - baselineStreamBitrate = hlsVideoRequest.BaselineStreamAudioBitRate ?? baselineStreamBitrate; - } - var playlistText = GetMasterPlaylistFileText(playlist, videoBitrate + audioBitrate, appendBaselineStream, baselineStreamBitrate); job = job ?? ApiEntryPoint.Instance.OnTranscodeBeginRequest(playlist, TranscodingJobType); @@ -248,11 +236,7 @@ namespace MediaBrowser.Api.Playback.Hls protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding) { - var hlsVideoRequest = state.VideoRequest as GetHlsVideoStreamLegacy; - - var itsOffsetMs = hlsVideoRequest == null - ? 0 - : hlsVideoRequest.TimeStampOffsetMs; + var itsOffsetMs = 0; var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds.ToString(UsCulture)); @@ -286,26 +270,6 @@ namespace MediaBrowser.Api.Playback.Hls outputPath ).Trim(); - if (hlsVideoRequest != null) - { - if (hlsVideoRequest.AppendBaselineStream) - { - var lowBitratePath = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath) + "-low.m3u8"); - - var bitrate = hlsVideoRequest.BaselineStreamAudioBitRate ?? 64000; - - var lowBitrateParams = string.Format(" -threads {0} -vn -codec:a:0 libmp3lame -ac 2 -ab {1} -hls_time {2} -start_number {3} -hls_list_size {4} -y \"{5}\"", - threads, - bitrate / 2, - state.SegmentLength.ToString(UsCulture), - startNumberParam, - state.HlsListSize.ToString(UsCulture), - lowBitratePath); - - args += " " + lowBitrateParams; - } - } - return args; } @@ -314,9 +278,28 @@ namespace MediaBrowser.Api.Playback.Hls return 0; } - protected override bool CanStreamCopyAudio(VideoStreamRequest request, MediaStream audioStream, List supportedAudioCodecs) + protected bool IsLiveStream(StreamState state) { - return false; + var isLiveStream = (state.RunTimeTicks ?? 0) == 0; + + if (state.VideoRequest.ForceLiveStream) + { + return true; + } + + return isLiveStream; + } + + protected override bool CanStreamCopyAudio(StreamState state, List supportedAudioCodecs) + { + var isLiveStream = IsLiveStream(state); + + if (!isLiveStream) + { + return false; + } + + return base.CanStreamCopyAudio(state, supportedAudioCodecs); } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index c7fe50941..65e236525 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -504,6 +504,11 @@ namespace MediaBrowser.Api.Playback.Hls { var isLiveStream = (state.RunTimeTicks ?? 0) == 0; + if (state.VideoRequest.ForceLiveStream) + { + return true; + } + return isLiveStream; } diff --git a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs index b44d7f660..e9f33161e 100644 --- a/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs +++ b/MediaBrowser.Api/Playback/Hls/HlsSegmentService.cs @@ -31,25 +31,6 @@ namespace MediaBrowser.Api.Playback.Hls public string SegmentId { get; set; } } - /// - /// Class GetHlsVideoStream - /// - [Route("/Videos/{Id}/stream.m3u8", "GET")] - [Api(Description = "Gets a video stream using HTTP live streaming.")] - public class GetHlsVideoStreamLegacy : VideoStreamRequest - { - // TODO: Deprecate with new iOS app - - [ApiMember(Name = "BaselineStreamAudioBitRate", Description = "Optional. Specify the audio bitrate for the baseline stream.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] - public int? BaselineStreamAudioBitRate { get; set; } - - [ApiMember(Name = "AppendBaselineStream", Description = "Optional. Whether or not to include a baseline audio-only stream in the master playlist.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] - public bool AppendBaselineStream { get; set; } - - [ApiMember(Name = "TimeStampOffsetMs", Description = "Optional. Alter the timestamps in the playlist by a given amount, in ms. Default is 1000.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] - public int TimeStampOffsetMs { get; set; } - } - /// /// Class GetHlsVideoSegment /// diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index f154a05cc..610628ced 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -27,16 +27,6 @@ namespace MediaBrowser.Api.Playback.Hls { } - /// - /// Gets the specified request. - /// - /// The request. - /// System.Object. - public object Get(GetHlsVideoStreamLegacy request) - { - return ProcessRequest(request, false); - } - public object Get(GetLiveHlsStream request) { return ProcessRequest(request, true); diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 5167af98a..371dbbda2 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -189,7 +189,9 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "CopyTimestamps", Description = "Whether or not to copy timestamps when transcoding with an offset. Defaults to false.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool CopyTimestamps { get; set; } - + + public bool ForceLiveStream { get; set; } + public VideoStreamRequest() { EnableAutoStreamCopy = true; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index f80c52e38..93526c638 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -513,7 +513,14 @@ namespace MediaBrowser.Model.Dlna { if (targetAudioChannels.Value >= 5 && (maxTotalBitrate ?? 0) >= 2000000) { - defaultBitrate = 320000; + if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3")) + { + defaultBitrate = 384000; + } + else + { + defaultBitrate = 320000; + } } } From c40002dee01beab977e04b695899c44f80b65dcc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 01:51:27 -0400 Subject: [PATCH 053/852] add ForceLiveStream option --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 1 + MediaBrowser.Model/Dlna/StreamBuilder.cs | 1 + MediaBrowser.Model/Dlna/StreamInfo.cs | 4 +++- MediaBrowser.Model/Dlna/TranscodingProfile.cs | 3 +++ 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index dfa279019..2c3abe95e 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -2048,6 +2048,7 @@ namespace MediaBrowser.Api.Playback if (state.VideoRequest != null) { state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; + state.VideoRequest.ForceLiveStream = transcodingProfile.ForceLiveStream; } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 93526c638..d28e21bf2 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -443,6 +443,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; + playlistItem.ForceLiveStream = transcodingProfile.ForceLiveStream; playlistItem.SubProtocol = transcodingProfile.Protocol; playlistItem.AudioStreamIndex = audioStreamIndex; diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index a2867dcc9..644f732a7 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -31,6 +31,7 @@ namespace MediaBrowser.Model.Dlna public string VideoProfile { get; set; } public bool CopyTimestamps { get; set; } + public bool ForceLiveStream { get; set; } public string AudioCodec { get; set; } public int? AudioStreamIndex { get; set; } @@ -204,7 +205,7 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty)); list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty)); - if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls")) + if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls") && !item.ForceLiveStream) { list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } @@ -234,6 +235,7 @@ namespace MediaBrowser.Model.Dlna } list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString().ToLower())); + list.Add(new NameValuePair("ForceLiveStream", item.ForceLiveStream.ToString().ToLower())); list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); return list; diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs index e59ee6d63..bf6bf092f 100644 --- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs @@ -35,6 +35,9 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("context")] public EncodingContext Context { get; set; } + [XmlAttribute("forceLiveStream")] + public bool ForceLiveStream { get; set; } + public List GetAudioCodecs() { List list = new List(); From e9b439bd3fdf6732104d1b9d288877a68f394344 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 01:56:32 -0400 Subject: [PATCH 054/852] 3.0.5926 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index a9922393f..59a03c15b 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5925")] +[assembly: AssemblyVersion("3.0.5926")] From ddbf183df59b43e5b9f47c81e923b2669b4e26cf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 15:07:43 -0400 Subject: [PATCH 055/852] update edge playback --- .../EntryPoints/ExternalPortForwarding.cs | 230 +++++++++++++----- ...MediaBrowser.Server.Implementations.csproj | 4 - .../packages.config | 1 - 3 files changed, 165 insertions(+), 70 deletions(-) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index a7e5396eb..5777a0af7 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; +using Mono.Nat; using System; using System.Collections.Generic; using System.Globalization; @@ -10,9 +11,6 @@ using System.IO; using System.Net; using System.Text; using MediaBrowser.Common.Threading; -using Open.Nat; -using System.Threading; -using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.EntryPoints { @@ -22,8 +20,9 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private readonly ILogger _logger; private readonly IServerConfigurationManager _config; private readonly ISsdpHandler _ssdp; - private CancellationTokenSource _currentCancellationTokenSource; - private TimeSpan _interval = TimeSpan.FromHours(1); + + private PeriodicTimer _timer; + private bool _isStarted; public ExternalPortForwarding(ILogManager logmanager, IServerApplicationHost appHost, IServerConfigurationManager config, ISsdpHandler ssdp) { @@ -31,78 +30,157 @@ namespace MediaBrowser.Server.Implementations.EntryPoints _appHost = appHost; _config = config; _ssdp = ssdp; - - _config.ConfigurationUpdated += _config_ConfigurationUpdated; } - private void _config_ConfigurationUpdated(object sender, EventArgs e) + private string _lastConfigIdentifier; + private string GetConfigIdentifier() { + var values = new List(); + var config = _config.Configuration; + + values.Add(config.EnableUPnP.ToString()); + values.Add(config.PublicPort.ToString(CultureInfo.InvariantCulture)); + values.Add(_appHost.HttpPort.ToString(CultureInfo.InvariantCulture)); + values.Add(_appHost.HttpsPort.ToString(CultureInfo.InvariantCulture)); + values.Add(config.EnableHttps.ToString()); + values.Add(_appHost.EnableHttps.ToString()); + + return string.Join("|", values.ToArray()); + } + + void _config_ConfigurationUpdated(object sender, EventArgs e) + { + if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) + { + if (_isStarted) + { + DisposeNat(); + } + + Run(); + } } public void Run() { - Discover(); - } - - private async void Discover() - { - if (!_config.Configuration.EnableUPnP) - { - return; - } - - var discoverer = new NatDiscoverer(); - - var cancellationTokenSource = new CancellationTokenSource(10000); - _currentCancellationTokenSource = cancellationTokenSource; - - try - { - var device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cancellationTokenSource).ConfigureAwait(false); - - await CreateRules(device).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - - } - catch (Exception ex) - { - _logger.ErrorException("Error discovering NAT devices", ex); - } - finally - { - _currentCancellationTokenSource = null; - } + //NatUtility.Logger = new LogWriter(_logger); if (_config.Configuration.EnableUPnP) { - await Task.Delay(_interval).ConfigureAwait(false); - Discover(); + Start(); + } + + _config.ConfigurationUpdated -= _config_ConfigurationUpdated; + _config.ConfigurationUpdated += _config_ConfigurationUpdated; + } + + private void Start() + { + _logger.Debug("Starting NAT discovery"); + NatUtility.EnabledProtocols = new List + { + NatProtocol.Pmp + }; + NatUtility.DeviceFound += NatUtility_DeviceFound; + + // Mono.Nat does never rise this event. The event is there however it is useless. + // You could remove it with no risk. + NatUtility.DeviceLost += NatUtility_DeviceLost; + + + // it is hard to say what one should do when an unhandled exception is raised + // because there isn't anything one can do about it. Probably save a log or ignored it. + NatUtility.UnhandledException += NatUtility_UnhandledException; + NatUtility.StartDiscovery(); + + _timer = new PeriodicTimer(s => _createdRules = new List(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); + + _ssdp.MessageReceived += _ssdp_MessageReceived; + + _lastConfigIdentifier = GetConfigIdentifier(); + + _isStarted = true; + } + + void _ssdp_MessageReceived(object sender, SsdpMessageEventArgs e) + { + var endpoint = e.EndPoint as IPEndPoint; + + if (endpoint != null && e.LocalEndPoint != null) + { + NatUtility.Handle(e.LocalEndPoint.Address, e.Message, endpoint, NatProtocol.Upnp); } } - private async Task CreateRules(NatDevice device) + 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); + } + } + + void NatUtility_DeviceFound(object sender, DeviceEventArgs e) + { + try + { + var device = e.Device; + _logger.Debug("NAT device found: {0}", device.LocalAddress.ToString()); + + CreateRules(device); + } + catch (Exception ex) + { + // I think it could be a good idea to log the exception because + // you are using permanent portmapping here (never expire) and that means that next time + // CreatePortMap is invoked it can fails with a 718-ConflictInMappingEntry or not. That depends + // on the router's upnp implementation (specs says it should fail however some routers don't do it) + // It also can fail with others like 727-ExternalPortOnlySupportsWildcard, 728-NoPortMapsAvailable + // and those errors (upnp errors) could be useful for diagnosting. + + // Commenting out because users are reporting problems out of our control + //_logger.ErrorException("Error creating port forwarding rules", ex); + } + } + + private List _createdRules = new List(); + private void CreateRules(INatDevice device) { // On some systems the device discovered event seems to fire repeatedly // This check will help ensure we're not trying to port map the same device over and over - await CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort).ConfigureAwait(false); - await CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort).ConfigureAwait(false); + var address = device.LocalAddress.ToString(); + + if (!_createdRules.Contains(address)) + { + _createdRules.Add(address); + + CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort); + CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort); + } } - private async Task CreatePortMap(NatDevice device, int privatePort, int publicPort) + private void CreatePortMap(INatDevice device, int privatePort, int publicPort) { _logger.Debug("Creating port map on port {0}", privatePort); + device.CreatePortMap(new Mapping(Protocol.Tcp, privatePort, publicPort) + { + Description = _appHost.Name + }); + } - try - { - await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, privatePort, publicPort, _appHost.Name)).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error creating port map", ex); - } + // As I said before, this method will be never invoked. You can remove it. + void NatUtility_DeviceLost(object sender, DeviceEventArgs e) + { + var device = e.Device; + _logger.Debug("NAT device lost: {0}", device.LocalAddress.ToString()); } public void Dispose() @@ -112,17 +190,39 @@ namespace MediaBrowser.Server.Implementations.EntryPoints private void DisposeNat() { - if (_currentCancellationTokenSource != null) + _logger.Debug("Stopping NAT discovery"); + + if (_timer != null) { - try - { - _currentCancellationTokenSource.Cancel(); - } - catch (Exception ex) - { - _logger.ErrorException("Error calling _currentCancellationTokenSource.Cancel", ex); - } + _timer.Dispose(); + _timer = null; + } + + _ssdp.MessageReceived -= _ssdp_MessageReceived; + + try + { + // This is not a significant improvement + NatUtility.StopDiscovery(); + NatUtility.DeviceFound -= NatUtility_DeviceFound; + NatUtility.DeviceLost -= NatUtility_DeviceLost; + NatUtility.UnhandledException -= NatUtility_UnhandledException; + } + // Statements in try-block will no fail because StopDiscovery is a one-line + // method that was no chances to fail. + // public static void StopDiscovery () + // { + // searching.Reset(); + // } + // IMO you could remove the catch-block + catch (Exception ex) + { + _logger.ErrorException("Error stopping NAT Discovery", ex); + } + finally + { + _isStarted = false; } } } -} +} \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index ae39d3eb9..60d8f737f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -62,10 +62,6 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll - - ..\packages\Open.NAT.2.0.15.0\lib\net45\Open.Nat.dll - True - ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 814a67643..66aede029 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -7,7 +7,6 @@ - \ No newline at end of file From 1071a5a5f3814164c505255d2350c6ace744c8c3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 21:23:42 -0400 Subject: [PATCH 056/852] render ssa/ass subs in browser --- MediaBrowser.Model/Dto/MediaSourceInfo.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 2de4aa8ea..4e3e60063 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/MediaBrowser.Model/Dto/MediaSourceInfo.cs @@ -160,6 +160,16 @@ namespace MediaBrowser.Model.Dto public bool? IsSecondaryAudio(MediaStream stream) { + // Look for the first audio track marked as default + foreach (MediaStream currentStream in MediaStreams) + { + if (currentStream.Type == MediaStreamType.Audio && currentStream.IsDefault) + { + return currentStream.Index != stream.Index; + } + } + + // Look for the first audio track foreach (MediaStream currentStream in MediaStreams) { if (currentStream.Type == MediaStreamType.Audio) From dd6532b10b16aa013b6b94f1870430a4b4a63b4b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 4 Apr 2016 21:28:48 -0400 Subject: [PATCH 057/852] 3.0.5927 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 59a03c15b..d787501c5 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5926")] +[assembly: AssemblyVersion("3.0.5927")] From b844471860e468bc1641e2d854fd8a5ab8ce7f3f Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Sun, 3 Apr 2016 23:39:40 -0700 Subject: [PATCH 058/852] fix resolution for internet540 profile; remove obsolete internet720 profile --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index ef8efbe98..2503412d5 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -263,18 +263,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoCodec = "h264"; videoBitrate = 15000000; } - else if (string.Equals(profile, "internet720", StringComparison.OrdinalIgnoreCase)) - { - width = 1280; - height = 720; - isInterlaced = false; - videoCodec = "h264"; - videoBitrate = 8000000; - } else if (string.Equals(profile, "internet540", StringComparison.OrdinalIgnoreCase)) { - width = 1280; - height = 720; + width = 960; + height = 546; isInterlaced = false; videoCodec = "h264"; videoBitrate = 2500000; From aa817508e25ce164184c44d2c16fd5091961dc6d Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Sun, 3 Apr 2016 23:42:07 -0700 Subject: [PATCH 059/852] actually add internet540 profile --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 2503412d5..101238567 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -393,6 +393,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun { list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); + list.Add(await GetMediaSource(info, hdhrId, "internet540").ConfigureAwait(false)); list.Add(await GetMediaSource(info, hdhrId, "internet480").ConfigureAwait(false)); list.Add(await GetMediaSource(info, hdhrId, "internet360").ConfigureAwait(false)); list.Add(await GetMediaSource(info, hdhrId, "internet240").ConfigureAwait(false)); From c9092de032b4166f5907283f35d361ee7c49a3ee Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Sun, 3 Apr 2016 23:46:45 -0700 Subject: [PATCH 060/852] allow disabling of hardware transcoding on HDTC-2US --- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 4 +++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 660f30cc9..46f630fe0 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -31,6 +31,7 @@ namespace MediaBrowser.Model.LiveTv public string Type { get; set; } public string DeviceId { get; set; } public bool ImportFavoritesOnly { get; set; } + public bool AllowHWTranscoding { get; set; } public bool IsEnabled { get; set; } public string M3UUrl { get; set; } public string InfoUrl { get; set; } @@ -47,6 +48,7 @@ namespace MediaBrowser.Model.LiveTv public TunerHostInfo() { IsEnabled = true; + AllowHWTranscoding = true; } } @@ -70,4 +72,4 @@ namespace MediaBrowser.Model.LiveTv EnableAllTuners = true; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index ef8efbe98..64780a8e3 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -397,7 +397,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun string model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false); model = model ?? string.Empty; - if (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1) + if (info.AllowHWTranscoding && (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1)) { list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false)); From 6844b2a457bfdaeb85ec035657dd99d9003b3f55 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:34:09 -0400 Subject: [PATCH 061/852] update dlna images --- MediaBrowser.Dlna/Didl/DidlBuilder.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 728b397de..ba42a06e2 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -979,7 +979,10 @@ namespace MediaBrowser.Dlna.Didl if (item != null) { - return GetImageInfo(item, ImageType.Primary); + if (item.HasImage(ImageType.Primary)) + { + return GetImageInfo(item, ImageType.Primary); + } } return null; From f15e534d41a1f34bb7492671c4590f11303ed39a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:34:27 -0400 Subject: [PATCH 062/852] update initial user permissions --- MediaBrowser.Server.Implementations/Library/UserManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index c1807efe9..5ba83d6c7 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -352,6 +352,7 @@ namespace MediaBrowser.Server.Implementations.Library users.Add(user); user.Policy.IsAdministrator = true; + user.Policy.EnableContentDeletion = true; user.Policy.EnableRemoteControlOfOtherUsers = true; await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); } From 3ac2002759c324aef82c62fcf6cf54ab30ca8dcf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:34:45 -0400 Subject: [PATCH 063/852] normalize user specified external address --- .../Connect/ConnectManager.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index 9ed67f77e..e308acef0 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -62,6 +62,17 @@ namespace MediaBrowser.Server.Implementations.Connect { var address = _config.Configuration.WanDdns; + if (!string.IsNullOrWhiteSpace(address)) + { + try + { + address = new Uri(address).Host; + } + catch + { + } + } + if (string.IsNullOrWhiteSpace(address) && DiscoveredWanIpAddress != null) { if (DiscoveredWanIpAddress.AddressFamily == AddressFamily.InterNetworkV6) @@ -237,8 +248,8 @@ namespace MediaBrowser.Server.Implementations.Connect var postData = new Dictionary { - {"name", _appHost.FriendlyName}, - {"url", wanApiAddress}, + {"name", _appHost.FriendlyName}, + {"url", wanApiAddress}, {"systemId", _appHost.SystemId} }; From 2ca59daba71fdc213d7cde76ffc75d6702715fae Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:35:00 -0400 Subject: [PATCH 064/852] update channel media info --- MediaBrowser.Controller/Channels/ChannelMediaInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs index 1672b75fa..9424568b4 100644 --- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs @@ -65,7 +65,7 @@ namespace MediaBrowser.Controller.Channels Name = id, Id = id, ReadAtNativeFramerate = ReadAtNativeFramerate, - SupportsDirectStream = Protocol == MediaProtocol.File || Protocol == MediaProtocol.Http, + SupportsDirectStream = Protocol == MediaProtocol.File, SupportsDirectPlay = SupportsDirectPlay }; From d5396828fbf332d0f744069e3dda9684f3a6384b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:35:08 -0400 Subject: [PATCH 065/852] update components --- 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 24f44fea1..2b37d0462 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Providers.People var requestCount = _requestCount; - if (requestCount >= 20) + if (requestCount >= 30) { //_logger.Debug("Throttling Tmdb people"); From 1cea5bcbd8360fa7c5c9bfd273f27f472809a178 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 22:18:56 -0400 Subject: [PATCH 066/852] improve identify feature --- MediaBrowser.Api/ItemLookupService.cs | 17 +++++++++----- .../Providers/MetadataRefreshOptions.cs | 3 +++ .../Manager/MetadataService.cs | 13 +++++++++++ .../Omdb/OmdbItemProvider.cs | 6 ++--- .../HttpServer/HttpListenerHost.cs | 23 +++++++++++-------- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- 6 files changed, 43 insertions(+), 21 deletions(-) diff --git a/MediaBrowser.Api/ItemLookupService.cs b/MediaBrowser.Api/ItemLookupService.cs index 8be37e210..41bfd9da2 100644 --- a/MediaBrowser.Api/ItemLookupService.cs +++ b/MediaBrowser.Api/ItemLookupService.cs @@ -202,14 +202,19 @@ namespace MediaBrowser.Api // } //} Logger.Info("Setting provider id's to item {0}-{1}: {2}", item.Id, item.Name, _json.SerializeToString(request.ProviderIds)); - item.ProviderIds = request.ProviderIds; - var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem) + // Since the refresh process won't erase provider Ids, we need to set this explicitly now. + item.ProviderIds = request.ProviderIds; + //item.ProductionYear = request.ProductionYear; + //item.Name = request.Name; + + var task = _providerManager.RefreshFullItem(item, new MetadataRefreshOptions(_fileSystem) { MetadataRefreshMode = MetadataRefreshMode.FullRefresh, ImageRefreshMode = ImageRefreshMode.FullRefresh, ReplaceAllMetadata = true, - ReplaceAllImages = request.ReplaceAllImages + ReplaceAllImages = request.ReplaceAllImages, + SearchResult = request }, CancellationToken.None); Task.WaitAll(task); @@ -234,7 +239,7 @@ namespace MediaBrowser.Api contentPath = await reader.ReadToEndAsync().ConfigureAwait(false); } - if (_fileSystem.FileExists(contentPath)) + if (_fileSystem.FileExists(contentPath)) { return ToStaticFileResult(contentPath); } @@ -275,7 +280,7 @@ namespace MediaBrowser.Api var fullCachePath = GetFullCachePath(urlHash + "." + ext); - _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(fullCachePath)); using (var stream = result.Content) { using (var filestream = _fileSystem.GetFileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, true)) @@ -284,7 +289,7 @@ namespace MediaBrowser.Api } } - _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + _fileSystem.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); using (var writer = new StreamWriter(pointerCachePath)) { await writer.WriteAsync(fullCachePath).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index 29f4feb3d..9427b2afd 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -1,5 +1,6 @@ using System.Linq; using CommonIO; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Controller.Providers { @@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Providers public bool IsPostRecursiveRefresh { get; set; } public MetadataRefreshMode MetadataRefreshMode { get; set; } + public RemoteSearchResult SearchResult { get; set; } public bool ForceSave { get; set; } @@ -37,6 +39,7 @@ namespace MediaBrowser.Controller.Providers ImageRefreshMode = copy.ImageRefreshMode; ReplaceAllImages = copy.ReplaceAllImages; ReplaceImages = copy.ReplaceImages.ToList(); + SearchResult = copy.SearchResult; } } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index c1ae43124..8f7c93f32 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using CommonIO; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Model.Providers; namespace MediaBrowser.Providers.Manager { @@ -136,6 +137,11 @@ namespace MediaBrowser.Providers.Manager { var id = itemOfType.GetLookupInfo(); + if (refreshOptions.SearchResult != null) + { + ApplySearchResult(id, refreshOptions.SearchResult); + } + //await FindIdentities(id, cancellationToken).ConfigureAwait(false); id.IsAutomated = refreshOptions.IsAutomated; @@ -207,6 +213,13 @@ namespace MediaBrowser.Providers.Manager return updateType; } + private void ApplySearchResult(ItemLookupInfo lookupInfo, RemoteSearchResult result) + { + lookupInfo.ProviderIds = result.ProviderIds; + lookupInfo.Name = result.Name; + lookupInfo.Year = result.ProductionYear; + } + private async Task FindIdentities(TIdType id, CancellationToken cancellationToken) { try diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 75bec7b65..894750c81 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -60,9 +60,8 @@ namespace MediaBrowser.Providers.Omdb return GetSearchResultsInternal(searchInfo, type, true, cancellationToken); } - private async Task> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool enableMultipleResults, CancellationToken cancellationToken) + private async Task> GetSearchResultsInternal(ItemLookupInfo searchInfo, string type, bool isSearch, CancellationToken cancellationToken) { - bool isSearch = false; var episodeSearchInfo = searchInfo as EpisodeInfo; var list = new List(); @@ -95,10 +94,9 @@ namespace MediaBrowser.Providers.Omdb } // &s means search and returns a list of results as opposed to t - if (enableMultipleResults) + if (isSearch) { url += "&s=" + WebUtility.UrlEncode(name); - isSearch = true; } else { diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 3e4f4a70c..25463b660 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -344,6 +344,19 @@ namespace MediaBrowser.Server.Implementations.HttpServer LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent); } + if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl(DefaultRedirectPath); + return Task.FromResult(true); + } + if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); + return Task.FromResult(true); + } + if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) || localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1 || @@ -363,16 +376,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer } } - if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return Task.FromResult(true); - } - if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); - return Task.FromResult(true); - } if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) { httpRes.RedirectToUrl(DefaultRedirectPath); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index ef8efbe98..7fc54819d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -75,7 +75,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun lineup = lineup.Where(i => i.Favorite).ToList(); } - return lineup; + return lineup.Where(i => !i.DRM).ToList(); } } From 0e0398026232dac5b7fe71f0dfac1df854c10282 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 23:14:39 -0400 Subject: [PATCH 067/852] fix query case sensitivity --- .../Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 71c338fdb..b6699d164 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2283,7 +2283,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private static Dictionary GetTypeMapDictionary() { - var dict = new Dictionary(); + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var t in KnownTypes) { From c521fc2cf30fe1e5a9daf511462b4043cd60dbe8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 6 Apr 2016 12:19:38 -0400 Subject: [PATCH 068/852] 3.0.5928 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index d787501c5..384b50237 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5927")] +[assembly: AssemblyVersion("3.0.5928")] From 29f2a0145fc8747344e423af71cfd0e0aa113a0b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 6 Apr 2016 14:51:30 -0400 Subject: [PATCH 069/852] exclude trailers from suggestion categories --- MediaBrowser.Api/Movies/MoviesService.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index e06b2c7f8..065f88268 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -155,6 +155,8 @@ namespace MediaBrowser.Api.Movies listEligibleForSuggestion.AddRange(list); listEligibleForCategories = listEligibleForCategories + // Exclude trailers from the suggestion categories + .Where(i => i is Movie) .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase) .ToList(); From 8e0c9c53bc0a599aa90dc37ff040769653db5e7d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 7 Apr 2016 00:09:32 -0400 Subject: [PATCH 070/852] add open subtitle option to only download subtitles that are a perfect match --- .../Subtitles/SubtitleSearchRequest.cs | 1 + MediaBrowser.Model/Providers/SubtitleOptions.cs | 3 +++ MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs | 1 + MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs | 8 ++++++-- MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs | 1 + .../Subtitles/OpenSubtitleDownloader.cs | 4 ++-- 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs index e781c048b..a2371426a 100644 --- a/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs +++ b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs @@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Subtitles public int? ParentIndexNumber { get; set; } public int? ProductionYear { get; set; } public long? RuntimeTicks { get; set; } + public bool IsPerfectMatch { get; set; } public Dictionary ProviderIds { get; set; } public bool SearchAllProviders { get; set; } diff --git a/MediaBrowser.Model/Providers/SubtitleOptions.cs b/MediaBrowser.Model/Providers/SubtitleOptions.cs index 2b15c0e1f..5587e897f 100644 --- a/MediaBrowser.Model/Providers/SubtitleOptions.cs +++ b/MediaBrowser.Model/Providers/SubtitleOptions.cs @@ -12,11 +12,14 @@ namespace MediaBrowser.Model.Providers public string OpenSubtitlesPasswordHash { get; set; } public bool IsOpenSubtitleVipAccount { get; set; } + public bool RequirePerfectMatch { get; set; } + public SubtitleOptions() { DownloadLanguages = new string[] { }; SkipIfAudioTrackMatches = true; + RequirePerfectMatch = true; } } } \ No newline at end of file diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 24bf8b497..621510028 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -532,6 +532,7 @@ namespace MediaBrowser.Providers.MediaInfo currentStreams.Concat(externalSubtitleStreams).ToList(), subtitleOptions.SkipIfEmbeddedSubtitlesPresent, subtitleOptions.SkipIfAudioTrackMatches, + subtitleOptions.RequirePerfectMatch, subtitleOptions.DownloadLanguages, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs index d82289032..9ae8413d1 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs @@ -28,6 +28,7 @@ namespace MediaBrowser.Providers.MediaInfo List mediaStreams, bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, + bool requirePerfectMatch, IEnumerable languages, CancellationToken cancellationToken) { @@ -59,7 +60,7 @@ namespace MediaBrowser.Providers.MediaInfo { try { - var downloaded = await DownloadSubtitles(video, mediaStreams, skipIfEmbeddedSubtitlesPresent, skipIfAudioTrackMatches, lang, mediaType, cancellationToken) + var downloaded = await DownloadSubtitles(video, mediaStreams, skipIfEmbeddedSubtitlesPresent, skipIfAudioTrackMatches, requirePerfectMatch, lang, mediaType, cancellationToken) .ConfigureAwait(false); if (downloaded) @@ -80,6 +81,7 @@ namespace MediaBrowser.Providers.MediaInfo List mediaStreams, bool skipIfEmbeddedSubtitlesPresent, bool skipIfAudioTrackMatches, + bool requirePerfectMatch, string language, VideoContentType mediaType, CancellationToken cancellationToken) @@ -125,7 +127,9 @@ namespace MediaBrowser.Providers.MediaInfo ProviderIds = video.ProviderIds, // Stop as soon as we find something - SearchAllProviders = false + SearchAllProviders = false, + + IsPerfectMatch = requirePerfectMatch }; var episode = video as Episode; diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs index b8b17cefe..79da291b7 100644 --- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs +++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs @@ -116,6 +116,7 @@ namespace MediaBrowser.Providers.MediaInfo mediaStreams, options.SkipIfEmbeddedSubtitlesPresent, options.SkipIfAudioTrackMatches, + options.RequirePerfectMatch, options.DownloadLanguages, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs index 2276e391d..271f8170f 100644 --- a/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs +++ b/MediaBrowser.Providers/Subtitles/OpenSubtitleDownloader.cs @@ -308,8 +308,8 @@ namespace MediaBrowser.Providers.Subtitles // Avoid implicitly captured closure var hasCopy = hash; - return results.Where(x => x.SubBad == "0" && mediaFilter(x)) - .OrderBy(x => (x.MovieHash == hash ? 0 : 1)) + return results.Where(x => x.SubBad == "0" && mediaFilter(x) && (!request.IsPerfectMatch || string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase))) + .OrderBy(x => (string.Equals(x.MovieHash, hash, StringComparison.OrdinalIgnoreCase) ? 0 : 1)) .ThenBy(x => Math.Abs(long.Parse(x.MovieByteSize, _usCulture) - movieByteSize)) .ThenByDescending(x => int.Parse(x.SubDownloadsCnt, _usCulture)) .ThenByDescending(x => double.Parse(x.SubRating, _usCulture)) From 465824a5edf75578d64c0e2b1c68d019e793c92a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 7 Apr 2016 14:21:01 -0400 Subject: [PATCH 071/852] add test info --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 1c89a6e34..122176fac 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -146,6 +146,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From ffb33314903b2456ce1ac842728aeca206adc98a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 7 Apr 2016 14:25:45 -0400 Subject: [PATCH 072/852] 3.0.5929 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 384b50237..a1d5d0e60 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5928")] +[assembly: AssemblyVersion("3.0.5929")] From 3889bc0a115070892dcfb60fda7d8802d6edc242 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:00:35 -0400 Subject: [PATCH 073/852] fixes #1609 - Generated links are relative to site root --- MediaBrowser.Server.Implementations/Social/SharingManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Social/SharingManager.cs b/MediaBrowser.Server.Implementations/Social/SharingManager.cs index 326b2893c..2ffd33ca4 100644 --- a/MediaBrowser.Server.Implementations/Social/SharingManager.cs +++ b/MediaBrowser.Server.Implementations/Social/SharingManager.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.Social var externalUrl = _appHost.GetSystemInfo().WanAddress; info.ImageUrl = externalUrl + "/Social/Shares/Public/" + info.Id + "/Image"; - info.Url = externalUrl + "/web/shared.html?id=" + info.Id; + info.Url = externalUrl + "/emby/web/shared.html?id=" + info.Id; var item = _libraryManager.GetItemById(info.ItemId); From e31aec4bc5bdda2731fcef9d1d85ccd0f41847f3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:32:38 -0400 Subject: [PATCH 074/852] update metadata refresh --- .../Channels/IChannelItem.cs | 11 --- .../Channels/IChannelMediaItem.cs | 18 ----- MediaBrowser.Controller/Entities/BaseItem.cs | 3 + .../Entities/IHasImages.cs | 5 +- .../Entities/IHasMetadata.cs | 2 + .../MediaBrowser.Controller.csproj | 2 - .../Providers/IHasItemChangeMonitor.cs | 3 +- .../Folders/DefaultImageProvider.cs | 2 +- .../Manager/MetadataService.cs | 76 ++++++++++++++++--- .../MediaInfo/AudioImageProvider.cs | 9 +-- .../MediaInfo/FFProbeProvider.cs | 6 +- .../MediaInfo/VideoImageProvider.cs | 6 +- .../Photos/PhotoProvider.cs | 6 +- .../TV/TheTVDB/TvdbSeriesImageProvider.cs | 4 +- .../Channels/ChannelImageProvider.cs | 2 +- .../Channels/ChannelManager.cs | 3 +- .../LiveTv/ChannelImageProvider.cs | 2 +- .../LiveTv/ProgramImageProvider.cs | 2 +- .../LiveTv/RecordingImageProvider.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 23 +++++- 20 files changed, 115 insertions(+), 72 deletions(-) delete mode 100644 MediaBrowser.Controller/Channels/IChannelItem.cs delete mode 100644 MediaBrowser.Controller/Channels/IChannelMediaItem.cs diff --git a/MediaBrowser.Controller/Channels/IChannelItem.cs b/MediaBrowser.Controller/Channels/IChannelItem.cs deleted file mode 100644 index 9b5f0359b..000000000 --- a/MediaBrowser.Controller/Channels/IChannelItem.cs +++ /dev/null @@ -1,11 +0,0 @@ -using MediaBrowser.Controller.Entities; - -namespace MediaBrowser.Controller.Channels -{ - public interface IChannelItem : IHasImages, IHasTags - { - string ChannelId { get; set; } - - string ExternalId { get; set; } - } -} diff --git a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs b/MediaBrowser.Controller/Channels/IChannelMediaItem.cs deleted file mode 100644 index 60a29da90..000000000 --- a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs +++ /dev/null @@ -1,18 +0,0 @@ -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Channels -{ - public interface IChannelMediaItem : IChannelItem - { - long? RunTimeTicks { get; set; } - string MediaType { get; } - - ChannelMediaContentType ContentType { get; set; } - - ExtraType? ExtraType { get; set; } - - List ChannelMediaSources { get; set; } - } -} \ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index ba5da03d1..29f416b8c 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -412,6 +412,9 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public DateTime DateLastRefreshed { get; set; } + [IgnoreDataMember] + public DateTime? DateModifiedDuringLastRefresh { get; set; } + /// /// The logger /// diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs index a38b7394d..897250caa 100644 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ b/MediaBrowser.Controller/Entities/IHasImages.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Providers; +using System; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using System.Collections.Generic; using System.Threading; @@ -206,6 +207,8 @@ namespace MediaBrowser.Controller.Entities /// The image. /// The index. void SetImage(ItemImageInfo image, int index); + + DateTime? DateModifiedDuringLastRefresh { get; set; } } public static class HasImagesExtensions diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 0e4ae04ff..1f680b35f 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -25,6 +25,8 @@ namespace MediaBrowser.Controller.Entities /// The date last saved. DateTime DateLastSaved { get; set; } + SourceType SourceType { get; set; } + /// /// Gets or sets the date last refreshed. /// diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 6f429ed2f..235638b5f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -85,10 +85,8 @@ - - diff --git a/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs index 4c7069dd6..9441c3ecd 100644 --- a/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs +++ b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs @@ -8,9 +8,8 @@ namespace MediaBrowser.Controller.Providers /// Determines whether the specified item has changed. /// /// The item. - /// The status. /// The directory service. /// true if the specified item has changed; otherwise, false. - bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService); + bool HasChanged(IHasMetadata item, IDirectoryService directoryService); } } \ No newline at end of file diff --git a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs index ee83efd26..afd8c583d 100644 --- a/MediaBrowser.Providers/Folders/DefaultImageProvider.cs +++ b/MediaBrowser.Providers/Folders/DefaultImageProvider.cs @@ -157,7 +157,7 @@ namespace MediaBrowser.Providers.Folders }); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { return GetSupportedImages(item).Any(i => !item.HasImage(i)); } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 8f7c93f32..47783ebc6 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -11,8 +12,11 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Providers; namespace MediaBrowser.Providers.Manager @@ -68,6 +72,11 @@ namespace MediaBrowser.Providers.Manager result.ItemDateModified = item.DateModified; + if (EnableDateLastRefreshed(item)) + { + return Task.FromResult(true); + } + return ProviderRepo.SaveMetadataStatus(result, CancellationToken.None); } @@ -83,7 +92,22 @@ namespace MediaBrowser.Providers.Manager return new MetadataStatus { ItemId = item.Id }; } - return ProviderRepo.GetMetadataStatus(item.Id) ?? new MetadataStatus { ItemId = item.Id }; + if (EnableDateLastRefreshed(item) && item.DateModifiedDuringLastRefresh.HasValue) + { + return new MetadataStatus + { + ItemId = item.Id, + DateLastImagesRefresh = item.DateLastRefreshed, + DateLastMetadataRefresh = item.DateLastRefreshed, + ItemDateModified = item.DateModifiedDuringLastRefresh.Value + }; + } + + var result = ProviderRepo.GetMetadataStatus(item.Id) ?? new MetadataStatus { ItemId = item.Id }; + + item.DateModifiedDuringLastRefresh = result.ItemDateModified; + + return result; } public async Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) @@ -119,13 +143,20 @@ namespace MediaBrowser.Providers.Manager Item = itemOfType }; + bool hasRefreshedMetadata = false; + bool hasRefreshedImages = false; + // Next run metadata providers if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) { var providers = GetProviders(item, refreshResult, refreshOptions) .ToList(); - if (providers.Count > 0 || !refreshResult.DateLastMetadataRefresh.HasValue) + var dateLastRefresh = EnableDateLastRefreshed(item) + ? item.DateLastRefreshed + : refreshResult.DateLastMetadataRefresh ?? default(DateTime); + + if (providers.Count > 0 || dateLastRefresh == default(DateTime)) { if (item.BeforeMetadataRefresh()) { @@ -151,6 +182,7 @@ namespace MediaBrowser.Providers.Manager if (result.Failures == 0) { refreshResult.SetDateLastMetadataRefresh(DateTime.UtcNow); + hasRefreshedMetadata = true; } else { @@ -172,6 +204,7 @@ namespace MediaBrowser.Providers.Manager if (result.Failures == 0) { refreshResult.SetDateLastImagesRefresh(DateTime.UtcNow); + hasRefreshedImages = true; } else { @@ -194,9 +227,15 @@ namespace MediaBrowser.Providers.Manager updateType = updateType | ItemUpdateType.MetadataDownload; } - if (refreshOptions.MetadataRefreshMode >= MetadataRefreshMode.Default && refreshOptions.ImageRefreshMode >= ImageRefreshMode.Default) + if (hasRefreshedMetadata && hasRefreshedImages) { item.DateLastRefreshed = DateTime.UtcNow; + item.DateModifiedDuringLastRefresh = item.DateModified; + } + else + { + item.DateLastRefreshed = default(DateTime); + item.DateModifiedDuringLastRefresh = null; } // Save to database @@ -254,7 +293,12 @@ namespace MediaBrowser.Providers.Manager return true; } - if (item is BoxSet || (item is IItemByName && !(item is MusicArtist))) + if (item is BoxSet || item is IItemByName || item is Playlist) + { + return true; + } + + if (item.SourceType != SourceType.Library) { return true; } @@ -364,8 +408,12 @@ namespace MediaBrowser.Providers.Manager // Get providers to refresh var providers = ((ProviderManager)ProviderManager).GetMetadataProviders(item).ToList(); + var dateLastRefresh = EnableDateLastRefreshed(item) + ? item.DateLastRefreshed + : status.DateLastMetadataRefresh ?? default(DateTime); + // Run all if either of these flags are true - var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || !status.DateLastMetadataRefresh.HasValue; + var runAllProviders = options.ReplaceAllMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || dateLastRefresh == default(DateTime); if (!runAllProviders) { @@ -384,7 +432,7 @@ namespace MediaBrowser.Providers.Manager var hasFileChangeMonitor = i as IHasItemChangeMonitor; if (hasFileChangeMonitor != null) { - return HasChanged(item, hasFileChangeMonitor, status, options.DirectoryService); + return HasChanged(item, hasFileChangeMonitor, options.DirectoryService); } return false; @@ -429,8 +477,12 @@ namespace MediaBrowser.Providers.Manager // Get providers to refresh var providers = allImageProviders.Where(i => !(i is ILocalImageProvider)).ToList(); + var dateLastImageRefresh = EnableDateLastRefreshed(item) + ? item.DateLastRefreshed + : status.DateLastImagesRefresh ?? default(DateTime); + // Run all if either of these flags are true - var runAllProviders = options.ImageRefreshMode == ImageRefreshMode.FullRefresh || !status.DateLastImagesRefresh.HasValue; + var runAllProviders = options.ImageRefreshMode == ImageRefreshMode.FullRefresh || dateLastImageRefresh == default(DateTime); if (!runAllProviders) { @@ -440,13 +492,13 @@ namespace MediaBrowser.Providers.Manager var hasChangeMonitor = i as IHasChangeMonitor; if (hasChangeMonitor != null) { - return HasChanged(item, hasChangeMonitor, status.DateLastImagesRefresh.Value, options.DirectoryService); + return HasChanged(item, hasChangeMonitor, dateLastImageRefresh, options.DirectoryService); } var hasFileChangeMonitor = i as IHasItemChangeMonitor; if (hasFileChangeMonitor != null) { - return HasChanged(item, hasFileChangeMonitor, status, options.DirectoryService); + return HasChanged(item, hasFileChangeMonitor, options.DirectoryService); } return false; @@ -558,7 +610,7 @@ namespace MediaBrowser.Providers.Manager if (options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh) { // If the local provider fails don't continue with remote providers because the user's saved metadata could be lost - return refreshResult; + //return refreshResult; } } } @@ -738,11 +790,11 @@ namespace MediaBrowser.Providers.Manager } } - private bool HasChanged(IHasMetadata item, IHasItemChangeMonitor changeMonitor, MetadataStatus status, IDirectoryService directoryService) + private bool HasChanged(IHasMetadata item, IHasItemChangeMonitor changeMonitor, IDirectoryService directoryService) { try { - var hasChanged = changeMonitor.HasChanged(item, status, directoryService); + var hasChanged = changeMonitor.HasChanged(item, directoryService); //if (hasChanged) //{ diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index af610520f..aa495afbc 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -159,14 +159,11 @@ namespace MediaBrowser.Providers.MediaInfo return item.LocationType == LocationType.FileSystem && audio != null && !audio.IsArchive; } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - if (status.ItemDateModified.Value != item.DateModified) - { - return true; - } + return item.DateModifiedDuringLastRefresh.Value != item.DateModified; } return false; diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index a2d15d863..9db4ab96e 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -163,11 +163,11 @@ namespace MediaBrowser.Providers.MediaInfo return prober.Probe(item, cancellationToken); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - if (status.ItemDateModified.Value != item.DateModified) + if (item.DateModifiedDuringLastRefresh.Value != item.DateModified) { return true; } diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index f3235a102..a5751da0a 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -151,11 +151,11 @@ namespace MediaBrowser.Providers.MediaInfo } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - if (status.ItemDateModified.Value != item.DateModified) + if (item.DateModifiedDuringLastRefresh.Value != item.DateModified) { return true; } diff --git a/MediaBrowser.Providers/Photos/PhotoProvider.cs b/MediaBrowser.Providers/Photos/PhotoProvider.cs index ef3144958..882363b2f 100644 --- a/MediaBrowser.Providers/Photos/PhotoProvider.cs +++ b/MediaBrowser.Providers/Photos/PhotoProvider.cs @@ -152,11 +152,11 @@ namespace MediaBrowser.Providers.Photos get { return "Embedded Information"; } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - if (status.ItemDateModified.HasValue) + if (item.DateModifiedDuringLastRefresh.HasValue) { - return status.ItemDateModified.Value != item.DateModified; + return item.DateModifiedDuringLastRefresh.Value != item.DateModified; } return false; diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs index 011ed9ed0..d1cdc717e 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesImageProvider.cs @@ -332,7 +332,7 @@ namespace MediaBrowser.Providers.TV }); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { if (!TvdbSeriesProvider.Current.GetTvDbOptions().EnableAutomaticUpdates) { @@ -346,7 +346,7 @@ namespace MediaBrowser.Providers.TV var fileInfo = _fileSystem.GetFileInfo(imagesXmlPath); - return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > (status.DateLastMetadataRefresh ?? DateTime.MinValue); + return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs index f13c71c6d..c98f71ce2 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Channels return ((ChannelManager)_channelManager).GetChannelProvider(channel); } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { return GetSupportedImages(item).Any(i => !item.HasImage(i)); } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index a206c1925..c9956c68a 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -1406,7 +1406,8 @@ namespace MediaBrowser.Server.Implementations.Channels throw new ArgumentNullException("channel"); } - var result = GetAllChannels().FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); + var result = GetAllChannels() + .FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); if (result == null) { diff --git a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs index 24d38a63e..dccc7aa93 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ChannelImageProvider.cs @@ -77,7 +77,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv get { return 0; } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { return GetSupportedImages(item).Any(i => !item.HasImage(i)); } diff --git a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs index ab8ec720b..3f0538bd0 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/ProgramImageProvider.cs @@ -74,7 +74,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var liveTvItem = item as LiveTvProgram; diff --git a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs index fce3223ea..25678c29d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/RecordingImageProvider.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv get { return 0; } } - public bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var liveTvItem = item as ILiveTvRecording; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index b6699d164..a30ff66df 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -223,6 +223,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); PrepareStatements(); @@ -355,7 +356,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "Studios", "Tags", "SourceType", - "TrailerTypes" + "TrailerTypes", + "DateModifiedDuringLastRefresh" }; private readonly string[] _mediaStreamSaveColumns = @@ -459,7 +461,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "SourceType", "TrailerTypes", "CriticRating", - "CriticRatingSummary" + "CriticRatingSummary", + "DateModifiedDuringLastRefresh" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -752,7 +755,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.CriticRating; _saveItemCommand.GetParameter(index++).Value = item.CriticRatingSummary; - + + if (!item.DateModifiedDuringLastRefresh.HasValue || item.DateModifiedDuringLastRefresh.Value == default(DateTime)) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1125,6 +1137,11 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + if (!reader.IsDBNull(51)) + { + item.DateModifiedDuringLastRefresh = reader.GetDateTime(51).ToUniversalTime(); + } + return item; } From 199f1bb9fd0f5ad433836f07a31ae7d2e604066f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:39:09 -0400 Subject: [PATCH 075/852] install 4.6 framework --- MediaBrowser.ServerApplication/MainStartup.cs | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 87acd652e..5f528926b 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -256,6 +256,9 @@ namespace MediaBrowser.ServerApplication task = InstallVcredistIfNeeded(_appHost, _logger); Task.WaitAll(task); + task = InstallFrameworkV46IfNeeded(_logger); + Task.WaitAll(task); + SystemEvents.SessionEnding += SystemEvents_SessionEnding; SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; @@ -573,6 +576,93 @@ namespace MediaBrowser.ServerApplication } } + private static async Task InstallFrameworkV46IfNeeded(ILogger logger) + { + bool installFrameworkV46 = false; + + try + { + using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) + .OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) + { + if (ndpKey != null && ndpKey.GetValue("Release") != null) + { + if ((int)ndpKey.GetValue("Release") <= 393295) + { + //Found framework V4, but not yet V4.6 + installFrameworkV46 = true; + } + } + else + { + //Nothing found in the registry for V4 + installFrameworkV46 = true; + } + } + } + catch (Exception ex) + { + logger.ErrorException("Error getting .NET Framework version", ex); + } + + _logger.Info(".NET Framework 4.6 found: {0}", !installFrameworkV46); + + if (installFrameworkV46) + { + try + { + await InstallFrameworkV46().ConfigureAwait(false); + } + catch (Exception ex) + { + logger.ErrorException("Error installing .NET Framework version 4.6", ex); + } + } + } + + private static async Task InstallFrameworkV46() + { + var httpClient = _appHost.HttpClient; + + var tmp = await httpClient.GetTempFile(new HttpRequestOptions + { + Url = "https://github.com/MediaBrowser/Emby.Resources/raw/master/netframeworkV46/NDP46-KB3045560-Web.exe", + Progress = new Progress() + + }).ConfigureAwait(false); + + var exePath = Path.ChangeExtension(tmp, ".exe"); + File.Copy(tmp, exePath); + + var startInfo = new ProcessStartInfo + { + FileName = exePath, + + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "runas", + ErrorDialog = false, + Arguments = "/q /norestart" + }; + + + _logger.Info("Running {0}", startInfo.FileName); + + using (var process = Process.Start(startInfo)) + { + process.WaitForExit(); + //process.ExitCode + /* + 0 --> Installation completed successfully. + 1602 --> The user canceled installation. + 1603 --> A fatal error occurred during installation. + 1641 --> A restart is required to complete the installation. This message indicates success. + 3010 --> A restart is required to complete the installation. This message indicates success. + 5100 --> The user's computer does not meet system requirements. + */ + } + } + private static async Task InstallVcredistIfNeeded(ApplicationHost appHost, ILogger logger) { try From 9ba905c284785561cb9b12143146f1913bbca63a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:58:47 -0400 Subject: [PATCH 076/852] 3.0.5930 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index a1d5d0e60..6785f5f0d 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5929")] +[assembly: AssemblyVersion("3.0.5930")] From a95cbac07610ec2ac4e10676bd97615a443eddf3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 22:30:22 -0400 Subject: [PATCH 077/852] update detail screen --- MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs | 2 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 ++-- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 2c0257c5f..13a06afc2 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -251,7 +251,7 @@ namespace MediaBrowser.Server.Implementations.IO /// path private static bool ContainsParentFolder(IEnumerable lst, string path) { - if (string.IsNullOrEmpty(path)) + if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException("path"); } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 10a898785..0ae08c4ad 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.644 + 3.0.645 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption. Copyright © Emby 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 616f0ca2a..b9bce00d0 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.644 + 3.0.645 MediaBrowser.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index d17ff16b6..3af1b91e2 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.644 + 3.0.645 MediaBrowser.Model - Signed Edition Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 2098bbcfe..d48b421c5 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.644 + 3.0.645 Media Browser.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + From 2ec515027fe8fc14a4e91a4e991e19fa3cd3590b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 00:16:53 -0400 Subject: [PATCH 078/852] update DisplayParent --- .../Channels/ChannelAudioItem.cs | 101 -------------- .../Channels/ChannelFolderItem.cs | 89 ------------- .../Channels/ChannelVideoItem.cs | 126 ------------------ MediaBrowser.Controller/Entities/BaseItem.cs | 29 +++- .../Entities/IHasTrailers.cs | 12 +- .../Entities/Movies/Movie.cs | 11 -- .../Entities/TV/Episode.cs | 4 +- MediaBrowser.Controller/Entities/TV/Season.cs | 8 +- .../MediaBrowser.Controller.csproj | 3 - MediaBrowser.Dlna/Didl/DidlBuilder.cs | 28 ++-- .../Dto/DtoService.cs | 6 +- 11 files changed, 67 insertions(+), 350 deletions(-) delete mode 100644 MediaBrowser.Controller/Channels/ChannelAudioItem.cs delete mode 100644 MediaBrowser.Controller/Channels/ChannelFolderItem.cs delete mode 100644 MediaBrowser.Controller/Channels/ChannelVideoItem.cs diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs deleted file mode 100644 index 41e9dd203..000000000 --- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs +++ /dev/null @@ -1,101 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Threading; - -namespace MediaBrowser.Controller.Channels -{ - public class ChannelAudioItem : Audio - { - public ChannelMediaContentType ContentType { get; set; } - - public List ChannelMediaSources { get; set; } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.ChannelContent; - } - - protected override string CreateUserDataKey() - { - return ExternalId; - } - - [IgnoreDataMember] - public override bool SupportsLocalMetadata - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return false; - } - - public ChannelAudioItem() - { - ChannelMediaSources = new List(); - } - - [IgnoreDataMember] - public override LocationType LocationType - { - get - { - if (string.IsNullOrEmpty(Path)) - { - return LocationType.Remote; - } - - return base.LocationType; - } - } - - protected override string GetInternalMetadataPath(string basePath) - { - return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); - } - - public override IEnumerable GetMediaSources(bool enablePathSubstitution) - { - var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None) - .Result.ToList(); - - if (sources.Count > 0) - { - return sources; - } - - var list = base.GetMediaSources(enablePathSubstitution).ToList(); - - foreach (var mediaSource in list) - { - if (string.IsNullOrWhiteSpace(mediaSource.Path)) - { - mediaSource.Type = MediaSourceType.Placeholder; - } - } - - return list; - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsVisibleStandalone(User user) - { - return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user); - } - } -} diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs deleted file mode 100644 index 62e0d694e..000000000 --- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs +++ /dev/null @@ -1,89 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Users; -using System; -using System.Runtime.Serialization; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Configuration; - -namespace MediaBrowser.Controller.Channels -{ - public class ChannelFolderItem : Folder - { - public ChannelFolderType ChannelFolderType { get; set; } - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - // Don't block. - return false; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.ChannelContent; - } - - [IgnoreDataMember] - public override bool SupportsLocalMetadata - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return false; - } - - protected override string CreateUserDataKey() - { - return ExternalId; - } - - protected override async Task> GetItemsInternal(InternalItemsQuery query) - { - try - { - // Don't blow up here because it could cause parent screens with other content to fail - return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery - { - ChannelId = ChannelId, - FolderId = Id.ToString("N"), - Limit = query.Limit, - StartIndex = query.StartIndex, - UserId = query.User.Id.ToString("N"), - SortBy = query.SortBy, - SortOrder = query.SortOrder - - }, new Progress(), CancellationToken.None); - } - catch - { - // Already logged at lower levels - return new QueryResult - { - - }; - } - } - - protected override string GetInternalMetadataPath(string basePath) - { - return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsVisibleStandalone(User user) - { - return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user); - } - } -} diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs deleted file mode 100644 index 9fe04812e..000000000 --- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs +++ /dev/null @@ -1,126 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Runtime.Serialization; -using System.Threading; - -namespace MediaBrowser.Controller.Channels -{ - public class ChannelVideoItem : Video - { - public ChannelMediaContentType ContentType { get; set; } - - public List ChannelMediaSources { get; set; } - - protected override string CreateUserDataKey() - { - if (ContentType == ChannelMediaContentType.MovieExtra) - { - var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb); - - if (!string.IsNullOrWhiteSpace(key)) - { - key = key + "-" + ExtraType.ToString().ToLower(); - - // Make sure different trailers have their own data. - if (RunTimeTicks.HasValue) - { - key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); - } - - return key; - } - } - - return ExternalId; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.ChannelContent; - } - - [IgnoreDataMember] - public override bool SupportsLocalMetadata - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return false; - } - - public ChannelVideoItem() - { - ChannelMediaSources = new List(); - } - - [IgnoreDataMember] - public override LocationType LocationType - { - get - { - if (string.IsNullOrEmpty(Path)) - { - return LocationType.Remote; - } - - return base.LocationType; - } - } - - public override IEnumerable GetMediaSources(bool enablePathSubstitution) - { - var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None) - .Result.ToList(); - - if (sources.Count > 0) - { - return sources; - } - - var list = base.GetMediaSources(enablePathSubstitution).ToList(); - - foreach (var mediaSource in list) - { - if (string.IsNullOrWhiteSpace(mediaSource.Path)) - { - mediaSource.Type = MediaSourceType.Placeholder; - } - } - - return list; - } - - protected override string GetInternalMetadataPath(string basePath) - { - return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsVisibleStandalone(User user) - { - return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user); - } - - internal static bool IsChannelVisible(BaseItem item, User user) - { - var channel = ChannelManager.GetChannel(item.ChannelId); - - return channel.IsVisible(user); - } - } -} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 29f416b8c..26aae285d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -306,7 +306,7 @@ namespace MediaBrowser.Controller.Entities } } - private List> GetSortChunks(string s1) + private List> GetSortChunks(string s1) { var list = new List>(); @@ -668,9 +668,30 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public virtual BaseItem DisplayParent + public virtual Guid? DisplayParentId { - get { return GetParent(); } + get + { + if (ParentId == Guid.Empty) + { + return null; + } + return ParentId; + } + } + + [IgnoreDataMember] + public BaseItem DisplayParent + { + get + { + var id = DisplayParentId; + if (!id.HasValue) + { + return null; + } + return LibraryManager.GetItemById(id.Value); + } } /// @@ -1454,7 +1475,7 @@ namespace MediaBrowser.Controller.Entities public virtual string GetClientTypeName() { - if (IsFolder && SourceType == SourceType.Channel) + if (IsFolder && SourceType == SourceType.Channel && !(this is Channel)) { return "ChannelFolderItem"; } diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs index bc1c7d875..e5cbdff72 100644 --- a/MediaBrowser.Controller/Entities/IHasTrailers.cs +++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs @@ -1,6 +1,7 @@ using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Controller.Entities { @@ -18,11 +19,20 @@ namespace MediaBrowser.Controller.Entities /// The local trailer ids. List LocalTrailerIds { get; set; } List RemoteTrailerIds { get; set; } + } + public static class HasTrailerExtensions + { /// /// Gets the trailer ids. /// /// List<Guid>. - List GetTrailerIds(); + public static List GetTrailerIds(this IHasTrailers item) + { + var list = item.LocalTrailerIds.ToList(); + list.AddRange(item.RemoteTrailerIds); + return list; + } + } } diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index f5c2a9935..4d2ca9ffe 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -78,17 +78,6 @@ namespace MediaBrowser.Controller.Entities.Movies set { TmdbCollectionName = value; } } - /// - /// Gets the trailer ids. - /// - /// List<Guid>. - public List GetTrailerIds() - { - var list = LocalTrailerIds.ToList(); - list.AddRange(RemoteTrailerIds); - return list; - } - /// /// Gets the user data key. /// diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index d016392e8..ec65221bc 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -90,11 +90,11 @@ namespace MediaBrowser.Controller.Entities.TV } [IgnoreDataMember] - public override BaseItem DisplayParent + public override Guid? DisplayParentId { get { - return Season ?? GetParent(); + return SeasonId; } } diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index 5e067afd4..acd02e8ab 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -33,9 +33,13 @@ namespace MediaBrowser.Controller.Entities.TV } [IgnoreDataMember] - public override BaseItem DisplayParent + public override Guid? DisplayParentId { - get { return Series ?? GetParent(); } + get + { + var series = Series; + return series == null ? ParentId : series.Id; + } } // Genre, Rating and Stuido will all be the same diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 235638b5f..6ff4e39e2 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -75,15 +75,12 @@ - - - diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index ba42a06e2..89d00eb32 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -93,10 +93,10 @@ namespace MediaBrowser.Dlna.Didl } else { - var parent = item.DisplayParent; - if (parent != null) + var parent = item.DisplayParentId; + if (parent.HasValue) { - element.SetAttribute("parentID", GetClientId(parent, null)); + element.SetAttribute("parentID", GetClientId(parent.Value, null)); } } @@ -499,14 +499,21 @@ namespace MediaBrowser.Dlna.Didl { container.SetAttribute("id", clientId); - var parent = context ?? folder.DisplayParent; - if (parent == null) + if (context != null) { - container.SetAttribute("parentID", "0"); + container.SetAttribute("parentID", GetClientId(context, null)); } else { - container.SetAttribute("parentID", GetClientId(parent, null)); + var parent = folder.DisplayParentId; + if (!parent.HasValue) + { + container.SetAttribute("parentID", "0"); + } + else + { + container.SetAttribute("parentID", GetClientId(parent.Value, null)); + } } } @@ -1059,7 +1066,12 @@ namespace MediaBrowser.Dlna.Didl public static string GetClientId(BaseItem item, StubType? stubType) { - var id = item.Id.ToString("N"); + return GetClientId(item.Id, stubType); + } + + public static string GetClientId(Guid idValue, StubType? stubType) + { + var id = idValue.ToString("N"); if (stubType.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 234e15a66..50ae19580 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1149,10 +1149,10 @@ namespace MediaBrowser.Server.Implementations.Dto if (fields.Contains(ItemFields.ParentId)) { - var displayParent = item.DisplayParent; - if (displayParent != null) + var displayParentId = item.DisplayParentId; + if (displayParentId.HasValue) { - dto.ParentId = GetDtoId(displayParent); + dto.ParentId = displayParentId.Value.ToString("N"); } } From f9a9fd0a9f298f2b09cadd3e8eb4071c22a0aa08 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 15:04:14 -0400 Subject: [PATCH 079/852] update user pages --- MediaBrowser.WebDashboard/Api/PackageCreator.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.WebDashboard/Api/PackageCreator.cs b/MediaBrowser.WebDashboard/Api/PackageCreator.cs index 01c2a4104..b633d1590 100644 --- a/MediaBrowser.WebDashboard/Api/PackageCreator.cs +++ b/MediaBrowser.WebDashboard/Api/PackageCreator.cs @@ -415,6 +415,7 @@ namespace MediaBrowser.WebDashboard.Api sb.Append(""); sb.Append(""); sb.Append(""); + sb.Append(""); return sb.ToString(); } From 638dba51ec75f9180c44ec4e75b67f7cea774910 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 15:11:17 -0400 Subject: [PATCH 080/852] 3.0.5931 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 6785f5f0d..113d73899 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5930")] +[assembly: AssemblyVersion("3.0.5931")] From d328ae208a9363f97d45440211baa836688888d9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 14:23:17 -0400 Subject: [PATCH 081/852] set notification info url --- MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs | 3 ++- MediaBrowser.Model/Updates/PackageVersionInfo.cs | 2 ++ .../EntryPoints/Notifications/Notifications.cs | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs index 360428072..90a324193 100644 --- a/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs +++ b/MediaBrowser.Common.Implementations/Updates/GithubUpdater.cs @@ -113,7 +113,8 @@ namespace MediaBrowser.Common.Implementations.Updates targetFilename = targetFilename, versionStr = version.ToString(), requiredVersionStr = "1.0.0", - description = obj.body + description = obj.body, + infoUrl = obj.html_url } }; } diff --git a/MediaBrowser.Model/Updates/PackageVersionInfo.cs b/MediaBrowser.Model/Updates/PackageVersionInfo.cs index b9bf6e7fe..22404b6f6 100644 --- a/MediaBrowser.Model/Updates/PackageVersionInfo.cs +++ b/MediaBrowser.Model/Updates/PackageVersionInfo.cs @@ -87,5 +87,7 @@ namespace MediaBrowser.Model.Updates /// /// The target filename. public string targetFilename { get; set; } + + public string infoUrl { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index da1d25f2c..ca430eda9 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -118,7 +118,8 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications var notification = new NotificationRequest { - NotificationType = type + NotificationType = type, + Url = e.Argument.infoUrl }; notification.Variables["Version"] = e.Argument.versionStr; From 9b5f7f24955e8422dfeebf6f184518095d2e1caf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 3 Apr 2016 19:20:56 -0400 Subject: [PATCH 082/852] remove temp file from open subtitles --- .../XML-RPC/XmlRpcGenerator.cs | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs index 5a190ab72..c39917e29 100644 --- a/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs +++ b/OpenSubtitlesHandler/XML-RPC/XmlRpcGenerator.cs @@ -51,47 +51,45 @@ namespace XmlRpcHandler XmlWriterSettings sett = new XmlWriterSettings(); sett.Indent = true; - var requestXmlPath = Path.Combine(Path.GetTempPath(), "request.xml"); - sett.Encoding = Encoding.UTF8; - FileStream str = new FileStream(requestXmlPath, FileMode.Create, FileAccess.Write); - XmlWriter XMLwrt = XmlWriter.Create(str, sett); - // Let's write the methods - foreach (XmlRpcMethodCall method in methods) + using (var ms = new MemoryStream()) { - XMLwrt.WriteStartElement("methodCall");//methodCall - XMLwrt.WriteStartElement("methodName");//methodName - XMLwrt.WriteString(method.Name); - XMLwrt.WriteEndElement();//methodName - XMLwrt.WriteStartElement("params");//params - // Write values - foreach (IXmlRpcValue p in method.Parameters) + XmlWriter XMLwrt = XmlWriter.Create(ms, sett); + // Let's write the methods + foreach (XmlRpcMethodCall method in methods) { - XMLwrt.WriteStartElement("param");//param - if (p is XmlRpcValueBasic) + XMLwrt.WriteStartElement("methodCall");//methodCall + XMLwrt.WriteStartElement("methodName");//methodName + XMLwrt.WriteString(method.Name); + XMLwrt.WriteEndElement();//methodName + XMLwrt.WriteStartElement("params");//params + // Write values + foreach (IXmlRpcValue p in method.Parameters) { - WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p); + XMLwrt.WriteStartElement("param");//param + if (p is XmlRpcValueBasic) + { + WriteBasicValue(XMLwrt, (XmlRpcValueBasic)p); + } + else if (p is XmlRpcValueStruct) + { + WriteStructValue(XMLwrt, (XmlRpcValueStruct)p); + } + else if (p is XmlRpcValueArray) + { + WriteArrayValue(XMLwrt, (XmlRpcValueArray)p); + } + XMLwrt.WriteEndElement();//param } - else if (p is XmlRpcValueStruct) - { - WriteStructValue(XMLwrt, (XmlRpcValueStruct)p); - } - else if (p is XmlRpcValueArray) - { - WriteArrayValue(XMLwrt, (XmlRpcValueArray)p); - } - XMLwrt.WriteEndElement();//param - } - XMLwrt.WriteEndElement();//params - XMLwrt.WriteEndElement();//methodCall + XMLwrt.WriteEndElement();//params + XMLwrt.WriteEndElement();//methodCall + } + XMLwrt.Flush(); + XMLwrt.Close(); + return ms.ToArray(); } - XMLwrt.Flush(); - XMLwrt.Close(); - str.Close(); - string requestContent = File.ReadAllText(requestXmlPath); - return Encoding.UTF8.GetBytes(requestContent); } /// /// Decode response then return the values From 0b4cffc3db69ddb93af48ab978dca788a35905aa Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:34:27 -0400 Subject: [PATCH 083/852] update initial user permissions --- MediaBrowser.Server.Implementations/Library/UserManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 0d588b97b..bf09a8205 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -355,6 +355,7 @@ namespace MediaBrowser.Server.Implementations.Library users.Add(user); user.Policy.IsAdministrator = true; + user.Policy.EnableContentDeletion = true; user.Policy.EnableRemoteControlOfOtherUsers = true; await UpdateUserPolicy(user, user.Policy, false).ConfigureAwait(false); } From 84bc124a5546fb27d2fe13e0193b69df3df9c6a6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 6 Apr 2016 14:51:30 -0400 Subject: [PATCH 084/852] exclude trailers from suggestion categories --- MediaBrowser.Api/Movies/MoviesService.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index b3d485dc7..970e8df51 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -158,6 +158,8 @@ namespace MediaBrowser.Api.Movies listEligibleForSuggestion.AddRange(list); listEligibleForCategories = listEligibleForCategories + // Exclude trailers from the suggestion categories + .Where(i => i is Movie) .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase) .ToList(); From c079d4b7c26c5cb9e267ac846a186c5dfcde06fa Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:00:35 -0400 Subject: [PATCH 085/852] fixes #1609 - Generated links are relative to site root --- MediaBrowser.Server.Implementations/Social/SharingManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Social/SharingManager.cs b/MediaBrowser.Server.Implementations/Social/SharingManager.cs index 326b2893c..2ffd33ca4 100644 --- a/MediaBrowser.Server.Implementations/Social/SharingManager.cs +++ b/MediaBrowser.Server.Implementations/Social/SharingManager.cs @@ -84,7 +84,7 @@ namespace MediaBrowser.Server.Implementations.Social var externalUrl = _appHost.GetSystemInfo().WanAddress; info.ImageUrl = externalUrl + "/Social/Shares/Public/" + info.Id + "/Image"; - info.Url = externalUrl + "/web/shared.html?id=" + info.Id; + info.Url = externalUrl + "/emby/web/shared.html?id=" + info.Id; var item = _libraryManager.GetItemById(info.ItemId); From ecc47fa560f1060455aebc7c94946eb69798ee5e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 8 Apr 2016 14:39:09 -0400 Subject: [PATCH 086/852] install 4.6 framework --- MediaBrowser.ServerApplication/MainStartup.cs | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 87acd652e..5f528926b 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -256,6 +256,9 @@ namespace MediaBrowser.ServerApplication task = InstallVcredistIfNeeded(_appHost, _logger); Task.WaitAll(task); + task = InstallFrameworkV46IfNeeded(_logger); + Task.WaitAll(task); + SystemEvents.SessionEnding += SystemEvents_SessionEnding; SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; @@ -573,6 +576,93 @@ namespace MediaBrowser.ServerApplication } } + private static async Task InstallFrameworkV46IfNeeded(ILogger logger) + { + bool installFrameworkV46 = false; + + try + { + using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) + .OpenSubKey("SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Full\\")) + { + if (ndpKey != null && ndpKey.GetValue("Release") != null) + { + if ((int)ndpKey.GetValue("Release") <= 393295) + { + //Found framework V4, but not yet V4.6 + installFrameworkV46 = true; + } + } + else + { + //Nothing found in the registry for V4 + installFrameworkV46 = true; + } + } + } + catch (Exception ex) + { + logger.ErrorException("Error getting .NET Framework version", ex); + } + + _logger.Info(".NET Framework 4.6 found: {0}", !installFrameworkV46); + + if (installFrameworkV46) + { + try + { + await InstallFrameworkV46().ConfigureAwait(false); + } + catch (Exception ex) + { + logger.ErrorException("Error installing .NET Framework version 4.6", ex); + } + } + } + + private static async Task InstallFrameworkV46() + { + var httpClient = _appHost.HttpClient; + + var tmp = await httpClient.GetTempFile(new HttpRequestOptions + { + Url = "https://github.com/MediaBrowser/Emby.Resources/raw/master/netframeworkV46/NDP46-KB3045560-Web.exe", + Progress = new Progress() + + }).ConfigureAwait(false); + + var exePath = Path.ChangeExtension(tmp, ".exe"); + File.Copy(tmp, exePath); + + var startInfo = new ProcessStartInfo + { + FileName = exePath, + + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "runas", + ErrorDialog = false, + Arguments = "/q /norestart" + }; + + + _logger.Info("Running {0}", startInfo.FileName); + + using (var process = Process.Start(startInfo)) + { + process.WaitForExit(); + //process.ExitCode + /* + 0 --> Installation completed successfully. + 1602 --> The user canceled installation. + 1603 --> A fatal error occurred during installation. + 1641 --> A restart is required to complete the installation. This message indicates success. + 3010 --> A restart is required to complete the installation. This message indicates success. + 5100 --> The user's computer does not meet system requirements. + */ + } + } + private static async Task InstallVcredistIfNeeded(ApplicationHost appHost, ILogger logger) { try From 76884f8e743c15215ffbc94f0baeadc45f73c9cb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 23:14:39 -0400 Subject: [PATCH 087/852] fix query case sensitivity --- .../Persistence/SqliteItemRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4a7235928..3264abd22 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -2283,7 +2283,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private static Dictionary GetTypeMapDictionary() { - var dict = new Dictionary(); + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (var t in KnownTypes) { From 86e543d239fbd347f750ca381974207222f3cff9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 5 Apr 2016 15:35:00 -0400 Subject: [PATCH 088/852] update channel media info --- MediaBrowser.Controller/Channels/ChannelMediaInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs index 1672b75fa..9424568b4 100644 --- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs @@ -65,7 +65,7 @@ namespace MediaBrowser.Controller.Channels Name = id, Id = id, ReadAtNativeFramerate = ReadAtNativeFramerate, - SupportsDirectStream = Protocol == MediaProtocol.File || Protocol == MediaProtocol.Http, + SupportsDirectStream = Protocol == MediaProtocol.File, SupportsDirectPlay = SupportsDirectPlay }; From 88076948ef196ab9908ea4f23ed08b212dcd205d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 16:48:57 -0400 Subject: [PATCH 089/852] update redirects --- .../HttpServer/HttpListenerHost.cs | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 3e4f4a70c..25463b660 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -344,6 +344,19 @@ namespace MediaBrowser.Server.Implementations.HttpServer LoggerUtils.LogRequest(_logger, urlToLog, httpReq.HttpMethod, httpReq.UserAgent); } + if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl(DefaultRedirectPath); + return Task.FromResult(true); + } + if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase) || + string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase)) + { + httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); + return Task.FromResult(true); + } + if (string.Equals(localPath, "/mediabrowser/", StringComparison.OrdinalIgnoreCase) || string.Equals(localPath, "/mediabrowser", StringComparison.OrdinalIgnoreCase) || localPath.IndexOf("mediabrowser/web", StringComparison.OrdinalIgnoreCase) != -1 || @@ -363,16 +376,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer } } - if (string.Equals(localPath, "/emby/", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl(DefaultRedirectPath); - return Task.FromResult(true); - } - if (string.Equals(localPath, "/emby", StringComparison.OrdinalIgnoreCase)) - { - httpRes.RedirectToUrl("emby/" + DefaultRedirectPath); - return Task.FromResult(true); - } if (string.Equals(localPath, "/web", StringComparison.OrdinalIgnoreCase)) { httpRes.RedirectToUrl(DefaultRedirectPath); From 4ac4e4a0f5d224b7eeecad2002f96b088315597f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 17:16:17 -0400 Subject: [PATCH 090/852] update components --- .../EntryPoints/Notifications/Notifications.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 9e68ce4ef..c7a5e3b18 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -335,12 +335,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications private bool FilterItem(BaseItem item) { - if (!item.IsFolder && item.LocationType == LocationType.Virtual) + if (item.IsFolder) { return false; } - if (item is IItemByName && !(item is MusicArtist)) + if (item.LocationType == LocationType.Virtual) + { + return false; + } + + if (item is IItemByName) { return false; } From be4f301198fa0d1d455478eebfc960a6e61c33e9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 22:29:19 -0400 Subject: [PATCH 091/852] fix channel items in emc --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 72980a58e..a85ab621d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1439,7 +1439,7 @@ namespace MediaBrowser.Controller.Entities public virtual string GetClientTypeName() { - if (IsFolder && SourceType == SourceType.Channel) + if (IsFolder && SourceType == SourceType.Channel && !(this is Channel)) { return "ChannelFolderItem"; } From 670a388f61dac5cd72db0c2d4129623a4e1a804d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 9 Apr 2016 22:35:44 -0400 Subject: [PATCH 092/852] 3.0.5913 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index a088e2601..b9bd3b88e 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5912")] +[assembly: AssemblyVersion("3.0.5913")] From 4f8764ee5a28c2b5dba3524dc838c1304591bfb0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 10 Apr 2016 16:09:55 -0400 Subject: [PATCH 093/852] fix collection grouping for plain folders --- MediaBrowser.Controller/Entities/UserViewBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 2df2227bc..db669ca37 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -785,7 +785,7 @@ namespace MediaBrowser.Controller.Entities return false; } - if (query.IncludeItemTypes.Contains("Movie", StringComparer.OrdinalIgnoreCase)) + if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains("Movie", StringComparer.OrdinalIgnoreCase)) { param = true; } From 3d1c950de8eaa7292ab87f29c9cdb27bbdf18d0e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 10 Apr 2016 17:11:06 -0400 Subject: [PATCH 094/852] improve connect error messages --- .../Connect/ConnectManager.cs | 20 ++++++++++++++++--- .../MediaBrowser.WebDashboard.csproj | 3 --- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs index e308acef0..f3d545492 100644 --- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs +++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs @@ -24,6 +24,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Common.Extensions; namespace MediaBrowser.Server.Implementations.Connect { @@ -555,9 +556,22 @@ namespace MediaBrowser.Server.Implementations.Connect } catch (HttpException ex) { - if (!ex.StatusCode.HasValue || - ex.StatusCode.Value != HttpStatusCode.NotFound || - !Validator.EmailIsValid(connectUsername)) + if (!ex.StatusCode.HasValue) + { + throw; + } + + // If they entered a username, then whatever the error is just throw it, for example, user not found + if (!Validator.EmailIsValid(connectUsername)) + { + if (ex.StatusCode.Value == HttpStatusCode.NotFound) + { + throw new ResourceNotFoundException(); + } + throw; + } + + if (ex.StatusCode.Value != HttpStatusCode.NotFound) { throw; } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 122176fac..70b19f971 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1688,9 +1688,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From baca0d6244185facf899c15ce39e5e858c6f7df3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 11 Apr 2016 00:24:16 -0400 Subject: [PATCH 095/852] update scroll styles --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- MediaBrowser.ServerApplication/MainStartup.cs | 1 + .../MediaBrowser.ServerApplication.csproj | 1 + .../Native/LnkShortcutHandler.cs | 402 ++++++++++++++++++ 4 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 26aae285d..438c5cf23 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -686,7 +686,7 @@ namespace MediaBrowser.Controller.Entities get { var id = DisplayParentId; - if (!id.HasValue) + if (!id.HasValue || id.Value == Guid.Empty) { return null; } diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 5f528926b..ac1b7ca99 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -217,6 +217,7 @@ namespace MediaBrowser.ServerApplication { var fileSystem = new WindowsFileSystem(new PatternsLogger(logManager.GetLogger("FileSystem"))); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); + //fileSystem.AddShortcutHandler(new LnkShortcutHandler(fileSystem)); var nativeApp = new WindowsApp(fileSystem, _logger) { diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index f1a2915fe..26a9cd8b3 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -110,6 +110,7 @@ MainForm.cs + diff --git a/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs b/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs new file mode 100644 index 000000000..67d2e83f0 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/LnkShortcutHandler.cs @@ -0,0 +1,402 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security; +using System.Text; +using System.Threading.Tasks; +using CommonIO; + +namespace MediaBrowser.ServerApplication.Native +{ + public class LnkShortcutHandler : IShortcutHandler + { + public string Extension + { + get { return ".lnk"; } + } + + public string Resolve(string shortcutPath) + { + var link = new ShellLink(); + ((IPersistFile)link).Load(shortcutPath, NativeMethods.STGM_READ); + // ((IShellLinkW)link).Resolve(hwnd, 0) + var sb = new StringBuilder(NativeMethods.MAX_PATH); + WIN32_FIND_DATA data; + ((IShellLinkW)link).GetPath(sb, sb.Capacity, out data, 0); + return sb.ToString(); + } + + public void Create(string shortcutPath, string targetPath) + { + throw new NotImplementedException(); + } + } + + /// + /// Class NativeMethods + /// + [SuppressUnmanagedCodeSecurity] + public static class NativeMethods + { + /// + /// The MA x_ PATH + /// + public const int MAX_PATH = 260; + /// + /// The MA x_ ALTERNATE + /// + public const int MAX_ALTERNATE = 14; + /// + /// The INVALI d_ HANDL e_ VALUE + /// + public static IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); + /// + /// The STG m_ READ + /// + public const uint STGM_READ = 0; + } + + /// + /// Struct FILETIME + /// + [StructLayout(LayoutKind.Sequential)] + public struct FILETIME + { + /// + /// The dw low date time + /// + public uint dwLowDateTime; + /// + /// The dw high date time + /// + public uint dwHighDateTime; + } + + /// + /// Struct WIN32_FIND_DATA + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct WIN32_FIND_DATA + { + /// + /// The dw file attributes + /// + public FileAttributes dwFileAttributes; + /// + /// The ft creation time + /// + public FILETIME ftCreationTime; + /// + /// The ft last access time + /// + public FILETIME ftLastAccessTime; + /// + /// The ft last write time + /// + public FILETIME ftLastWriteTime; + /// + /// The n file size high + /// + public int nFileSizeHigh; + /// + /// The n file size low + /// + public int nFileSizeLow; + /// + /// The dw reserved0 + /// + public int dwReserved0; + /// + /// The dw reserved1 + /// + public int dwReserved1; + + /// + /// The c file name + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.MAX_PATH)] + public string cFileName; + + /// + /// This will always be null when FINDEX_INFO_LEVELS = basic + /// + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NativeMethods.MAX_ALTERNATE)] + public string cAlternate; + + /// + /// Gets or sets the path. + /// + /// The path. + public string Path { get; set; } + + /// + /// Returns a that represents this instance. + /// + /// A that represents this instance. + public override string ToString() + { + return Path ?? string.Empty; + } + } + + /// + /// Enum SLGP_FLAGS + /// + [Flags] + public enum SLGP_FLAGS + { + /// + /// Retrieves the standard short (8.3 format) file name + /// + SLGP_SHORTPATH = 0x1, + /// + /// Retrieves the Universal Naming Convention (UNC) path name of the file + /// + SLGP_UNCPRIORITY = 0x2, + /// + /// Retrieves the raw path name. A raw path is something that might not exist and may include environment variables that need to be expanded + /// + SLGP_RAWPATH = 0x4 + } + /// + /// Enum SLR_FLAGS + /// + [Flags] + public enum SLR_FLAGS + { + /// + /// Do not display a dialog box if the link cannot be resolved. When SLR_NO_UI is set, + /// the high-order word of fFlags can be set to a time-out value that specifies the + /// maximum amount of time to be spent resolving the link. The function returns if the + /// link cannot be resolved within the time-out duration. If the high-order word is set + /// to zero, the time-out duration will be set to the default value of 3,000 milliseconds + /// (3 seconds). To specify a value, set the high word of fFlags to the desired time-out + /// duration, in milliseconds. + /// + SLR_NO_UI = 0x1, + /// + /// Obsolete and no longer used + /// + SLR_ANY_MATCH = 0x2, + /// + /// If the link object has changed, update its path and list of identifiers. + /// If SLR_UPDATE is set, you do not need to call IPersistFile::IsDirty to determine + /// whether or not the link object has changed. + /// + SLR_UPDATE = 0x4, + /// + /// Do not update the link information + /// + SLR_NOUPDATE = 0x8, + /// + /// Do not execute the search heuristics + /// + SLR_NOSEARCH = 0x10, + /// + /// Do not use distributed link tracking + /// + SLR_NOTRACK = 0x20, + /// + /// Disable distributed link tracking. By default, distributed link tracking tracks + /// removable media across multiple devices based on the volume name. It also uses the + /// Universal Naming Convention (UNC) path to track remote file systems whose drive letter + /// has changed. Setting SLR_NOLINKINFO disables both types of tracking. + /// + SLR_NOLINKINFO = 0x40, + /// + /// Call the Microsoft Windows Installer + /// + SLR_INVOKE_MSI = 0x80 + } + + /// + /// The IShellLink interface allows Shell links to be created, modified, and resolved + /// + [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("000214F9-0000-0000-C000-000000000046")] + public interface IShellLinkW + { + /// + /// Retrieves the path and file name of a Shell link object + /// + /// The PSZ file. + /// The CCH max path. + /// The PFD. + /// The f flags. + void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out WIN32_FIND_DATA pfd, SLGP_FLAGS fFlags); + /// + /// Retrieves the list of item identifiers for a Shell link object + /// + /// The ppidl. + void GetIDList(out IntPtr ppidl); + /// + /// Sets the pointer to an item identifier list (PIDL) for a Shell link object. + /// + /// The pidl. + void SetIDList(IntPtr pidl); + /// + /// Retrieves the description string for a Shell link object + /// + /// Name of the PSZ. + /// Name of the CCH max. + void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName); + /// + /// Sets the description for a Shell link object. The description can be any application-defined string + /// + /// Name of the PSZ. + void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName); + /// + /// Retrieves the name of the working directory for a Shell link object + /// + /// The PSZ dir. + /// The CCH max path. + void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath); + /// + /// Sets the name of the working directory for a Shell link object + /// + /// The PSZ dir. + void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir); + /// + /// Retrieves the command-line arguments associated with a Shell link object + /// + /// The PSZ args. + /// The CCH max path. + void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath); + /// + /// Sets the command-line arguments for a Shell link object + /// + /// The PSZ args. + void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs); + /// + /// Retrieves the hot key for a Shell link object + /// + /// The pw hotkey. + void GetHotkey(out short pwHotkey); + /// + /// Sets a hot key for a Shell link object + /// + /// The w hotkey. + void SetHotkey(short wHotkey); + /// + /// Retrieves the show command for a Shell link object + /// + /// The pi show CMD. + void GetShowCmd(out int piShowCmd); + /// + /// Sets the show command for a Shell link object. The show command sets the initial show state of the window. + /// + /// The i show CMD. + void SetShowCmd(int iShowCmd); + /// + /// Retrieves the location (path and index) of the icon for a Shell link object + /// + /// The PSZ icon path. + /// The CCH icon path. + /// The pi icon. + void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, + int cchIconPath, out int piIcon); + /// + /// Sets the location (path and index) of the icon for a Shell link object + /// + /// The PSZ icon path. + /// The i icon. + void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon); + /// + /// Sets the relative path to the Shell link object + /// + /// The PSZ path rel. + /// The dw reserved. + void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved); + /// + /// Attempts to find the target of a Shell link, even if it has been moved or renamed + /// + /// The HWND. + /// The f flags. + void Resolve(IntPtr hwnd, SLR_FLAGS fFlags); + /// + /// Sets the path and file name of a Shell link object + /// + /// The PSZ file. + void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile); + + } + + /// + /// Interface IPersist + /// + [ComImport, Guid("0000010c-0000-0000-c000-000000000046"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersist + { + /// + /// Gets the class ID. + /// + /// The p class ID. + [PreserveSig] + void GetClassID(out Guid pClassID); + } + + /// + /// Interface IPersistFile + /// + [ComImport, Guid("0000010b-0000-0000-C000-000000000046"), + InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IPersistFile : IPersist + { + /// + /// Gets the class ID. + /// + /// The p class ID. + new void GetClassID(out Guid pClassID); + /// + /// Determines whether this instance is dirty. + /// + [PreserveSig] + int IsDirty(); + + /// + /// Loads the specified PSZ file name. + /// + /// Name of the PSZ file. + /// The dw mode. + [PreserveSig] + void Load([In, MarshalAs(UnmanagedType.LPWStr)] + string pszFileName, uint dwMode); + + /// + /// Saves the specified PSZ file name. + /// + /// Name of the PSZ file. + /// if set to true [remember]. + [PreserveSig] + void Save([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName, + [In, MarshalAs(UnmanagedType.Bool)] bool remember); + + /// + /// Saves the completed. + /// + /// Name of the PSZ file. + [PreserveSig] + void SaveCompleted([In, MarshalAs(UnmanagedType.LPWStr)] string pszFileName); + + /// + /// Gets the cur file. + /// + /// Name of the PPSZ file. + [PreserveSig] + void GetCurFile([In, MarshalAs(UnmanagedType.LPWStr)] string ppszFileName); + } + + // CLSID_ShellLink from ShlGuid.h + /// + /// Class ShellLink + /// + [ + ComImport, + Guid("00021401-0000-0000-C000-000000000046") + ] + public class ShellLink + { + } +} From b8217b6e504dd5172dd575a1ca3b0a538044c524 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 11 Apr 2016 10:16:17 -0400 Subject: [PATCH 096/852] 3.0.5932 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 113d73899..152434162 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5931")] +[assembly: AssemblyVersion("3.0.5932")] From 5c8bd5559d2b8706c423c81918ec42c7dc8a5550 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 11 Apr 2016 10:26:54 -0400 Subject: [PATCH 097/852] trim search requests --- MediaBrowser.Server.Implementations/Library/SearchEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 276fc329f..61a5d98a3 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("searchTerm"); } - searchTerm = searchTerm.RemoveDiacritics(); + searchTerm = searchTerm.Trim().RemoveDiacritics(); var terms = GetWords(searchTerm); From 3966eadfad665ab35a23e950c32dc255289c7b57 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 12 Apr 2016 00:03:07 -0400 Subject: [PATCH 098/852] update packages --- MediaBrowser.WebDashboard/packages.config | 1 - 1 file changed, 1 deletion(-) diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index eecb6bec2..a2d13fdf5 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,7 +1,6 @@  - \ No newline at end of file From 5bddb226f6ad3e42c3c32199684c4382d8e1661d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 12 Apr 2016 13:37:58 -0400 Subject: [PATCH 099/852] update hdhr stream --- MediaBrowser.Model/Dlna/StreamBuilder.cs | 4 ++++ .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index d28e21bf2..6bb2a9f82 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -509,6 +509,10 @@ namespace MediaBrowser.Model.Dlna private int GetAudioBitrate(int? maxTotalBitrate, int? targetAudioChannels, string targetAudioCodec, MediaStream audioStream) { var defaultBitrate = 128000; + if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3")) + { + defaultBitrate = 192000; + } if (targetAudioChannels.HasValue) { diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 3c1e4af36..638b4b9af 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -354,8 +354,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun BufferMs = 0, Container = "ts", Id = profile, - SupportsDirectPlay = true, - SupportsDirectStream = true, + SupportsDirectPlay = false, + SupportsDirectStream = false, SupportsTranscoding = true }; From 8c4468a33038eaa3acbda335286d23bea4d53c6e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 12 Apr 2016 14:01:23 -0400 Subject: [PATCH 100/852] update logging --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 2c3abe95e..beca1b1a5 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -995,7 +995,17 @@ namespace MediaBrowser.Api.Playback var commandLineLogMessage = process.StartInfo.FileName + " " + process.StartInfo.Arguments; Logger.Info(commandLineLogMessage); - var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, "transcode-" + Guid.NewGuid() + ".txt"); + var logFilePrefix = "transcode"; + if (state.VideoRequest != null && string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase) && string.Equals(state.OutputAudioCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + logFilePrefix = "directstream"; + } + else if (state.VideoRequest != null && string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + logFilePrefix = "remux"; + } + + var logFilePath = Path.Combine(ServerConfigurationManager.ApplicationPaths.LogDirectoryPath, logFilePrefix + "-" + Guid.NewGuid() + ".txt"); FileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. From 6f82815a5de2e47502ab3ed3f3f116a5c898db31 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 12 Apr 2016 14:14:59 -0400 Subject: [PATCH 101/852] target .net framework 4.6 --- MediaBrowser.ServerApplication/App.config | 60 +++++++++---------- .../MediaBrowser.ServerApplication.csproj | 5 +- .../Properties/Resources.Designer.cs | 2 +- .../packages.config | 2 +- 4 files changed, 35 insertions(+), 34 deletions(-) diff --git a/MediaBrowser.ServerApplication/App.config b/MediaBrowser.ServerApplication/App.config index 14ce35a96..a92d92300 100644 --- a/MediaBrowser.ServerApplication/App.config +++ b/MediaBrowser.ServerApplication/App.config @@ -1,80 +1,80 @@ - + -
+
-
+
- + - - - + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - \ No newline at end of file + diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 26a9cd8b3..291e63dac 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -1,5 +1,5 @@  - + Debug @@ -9,9 +9,10 @@ Properties MediaBrowser.ServerApplication MediaBrowser.ServerApplication - v4.5 + v4.6 512 ..\ + AnyCPU diff --git a/MediaBrowser.ServerApplication/Properties/Resources.Designer.cs b/MediaBrowser.ServerApplication/Properties/Resources.Designer.cs index 6323af6fd..e166f35d0 100644 --- a/MediaBrowser.ServerApplication/Properties/Resources.Designer.cs +++ b/MediaBrowser.ServerApplication/Properties/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.34011 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 16acb0c81..1c86a02ae 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -3,5 +3,5 @@ - + \ No newline at end of file From 6fdce00ea01f2c7ae930b000c494c1f3d9db7254 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 12 Apr 2016 14:15:55 -0400 Subject: [PATCH 102/852] 3.0.5933 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 152434162..ea90eda21 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5932")] +[assembly: AssemblyVersion("3.0.5933")] From 67fbaa2433264c2f6d7dc8e5a602050565bbe096 Mon Sep 17 00:00:00 2001 From: vicpa Date: Tue, 12 Apr 2016 16:09:05 -0400 Subject: [PATCH 103/852] qsv endcode --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index beca1b1a5..901554973 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -288,11 +288,9 @@ namespace MediaBrowser.Api.Playback { if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { - // It's currently failing on live tv - if (state.RunTimeTicks.HasValue) - { + return "h264_qsv"; - } + } return "libx264"; @@ -440,6 +438,8 @@ namespace MediaBrowser.Api.Playback param += " -level " + state.VideoRequest.Level; break; } + + return param; } else { From c72561176be3e6c07f8174deb3287613add2bb05 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 13 Apr 2016 02:05:30 -0400 Subject: [PATCH 104/852] 3.0.5934 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ea90eda21..073260ad7 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5933")] +[assembly: AssemblyVersion("3.0.5934")] From 41ee4600fd2b5af9732b363790d6b0f44dc272e5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 13 Apr 2016 12:17:52 -0400 Subject: [PATCH 105/852] fix tabs --- MediaBrowser.Api/TvShowsService.cs | 22 +++++++++++++++++-- .../Notifications/Notifications.cs | 13 +++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 5b5b0a902..3c32232ac 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -123,7 +123,7 @@ namespace MediaBrowser.Api } [Route("/Shows/{Id}/Episodes", "GET", Summary = "Gets episodes for a tv season")] - public class GetEpisodes : IReturn, IHasItemFields + public class GetEpisodes : IReturn, IHasItemFields, IHasDtoOptions { /// /// Gets or sets the user id. @@ -173,10 +173,19 @@ namespace MediaBrowser.Api /// The limit. [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] public int? Limit { get; set; } + + [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] + public bool? EnableImages { get; set; } + + [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? ImageTypeLimit { get; set; } + + [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string EnableImageTypes { get; set; } } [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")] - public class GetSeasons : IReturn, IHasItemFields + public class GetSeasons : IReturn, IHasItemFields, IHasDtoOptions { /// /// Gets or sets the user id. @@ -206,6 +215,15 @@ namespace MediaBrowser.Api [ApiMember(Name = "AdjacentTo", Description = "Optional. Return items that are siblings of a supplied item.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string AdjacentTo { get; set; } + + [ApiMember(Name = "EnableImages", Description = "Optional, include image information in output", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] + public bool? EnableImages { get; set; } + + [ApiMember(Name = "ImageTypeLimit", Description = "Optional, the max number of images to return, per image type", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")] + public int? ImageTypeLimit { get; set; } + + [ApiMember(Name = "EnableImageTypes", Description = "Optional. The image types to include in the output.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] + public string EnableImageTypes { get; set; } } /// diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index c7a5e3b18..71019e0ad 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -22,6 +22,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Entities.TV; namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications { @@ -393,6 +394,18 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications public static string GetItemName(BaseItem item) { var name = item.Name; + var episode = item as Episode; + if (episode != null) + { + if (episode.IndexNumber.HasValue) + { + name = string.Format("Ep{0} - {1}", episode.IndexNumber.Value.ToString(CultureInfo.InvariantCulture), name); + } + if (episode.ParentIndexNumber.HasValue) + { + name = string.Format("S{0}, {1}", episode.ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture), name); + } + } var hasSeries = item as IHasSeries; From b0379ec7f8fb4804f76d64264a4b35b65debedc6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 13 Apr 2016 16:49:16 -0400 Subject: [PATCH 106/852] improve embedded image extraction --- .../MediaEncoding/IMediaEncoder.cs | 2 + .../Encoder/MediaEncoder.cs | 8 ++- .../Probing/ProbeResultNormalizer.cs | 8 ++- MediaBrowser.Model/Dlna/StreamBuilder.cs | 22 +++++-- .../Manager/ProviderUtils.cs | 12 ++-- .../MediaInfo/AudioImageProvider.cs | 3 +- .../MediaInfo/VideoImageProvider.cs | 57 ++++++++++++++++--- .../Parsers/BaseNfoParser.cs | 6 +- 8 files changed, 92 insertions(+), 26 deletions(-) diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 76ef054de..d2feb4116 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -51,6 +51,8 @@ namespace MediaBrowser.Controller.MediaEncoding /// Task{Stream}. Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); + Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken); + /// /// Extracts the video images on interval. /// diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 97567db0e..01fb31d0c 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -484,12 +484,16 @@ namespace MediaBrowser.MediaEncoding.Encoder return ExtractImage(new[] { path }, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken); } - public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, - TimeSpan? offset, CancellationToken cancellationToken) + public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken); } + public Task ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken) + { + return ExtractImage(inputFiles, imageStreamIndex, protocol, false, null, null, cancellationToken); + } + private async Task ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 743351406..6ec9e6435 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -138,10 +138,14 @@ namespace MediaBrowser.MediaEncoding.Probing var parts = iTunEXTC.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); // Example // mpaa|G|100|For crude humor - if (parts.Length == 4) + if (parts.Length > 1) { info.OfficialRating = parts[1]; - info.OfficialRatingDescription = parts[3]; + + if (parts.Length > 3) + { + info.OfficialRatingDescription = parts[3]; + } } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 6bb2a9f82..09d762aae 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -520,7 +520,7 @@ namespace MediaBrowser.Model.Dlna { if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3")) { - defaultBitrate = 384000; + defaultBitrate = 448000; } else { @@ -840,13 +840,25 @@ namespace MediaBrowser.Model.Dlna private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate) { - if (!maxBitrate.HasValue || (item.Bitrate.HasValue && item.Bitrate.Value <= maxBitrate.Value)) + if (!maxBitrate.HasValue) { - return true; + _logger.Info("Cannot direct play due to unknown supported bitrate"); + return false; } - _logger.Info("Bitrate exceeds DirectPlay limit"); - return false; + if (!item.Bitrate.HasValue) + { + _logger.Info("Cannot direct play due to unknown content bitrate"); + return false; + } + + if (item.Bitrate.Value > maxBitrate.Value) + { + _logger.Info("Bitrate exceeds DirectPlay limit"); + return false; + } + + return true; } private void ValidateInput(VideoOptions options) diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 20b2ac6cd..278d8ed71 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -10,9 +10,9 @@ namespace MediaBrowser.Providers.Manager public static class ProviderUtils { public static void MergeBaseItemData(MetadataResult sourceResult, - MetadataResult targetResult, - List lockedFields, - bool replaceData, + MetadataResult targetResult, + List lockedFields, + bool replaceData, bool mergeMetadataSettings) where T : BaseItem { @@ -89,7 +89,7 @@ namespace MediaBrowser.Providers.Manager { target.CustomRating = source.CustomRating; } - + if (!lockedFields.Contains(MetadataFields.Overview)) { if (replaceData || string.IsNullOrEmpty(target.Overview)) @@ -107,7 +107,7 @@ namespace MediaBrowser.Providers.Manager { if (replaceData || targetResult.People == null || targetResult.People.Count == 0) { - targetResult.People = sourceResult.People ?? new List(); + targetResult.People = sourceResult.People; } } @@ -238,7 +238,7 @@ namespace MediaBrowser.Providers.Manager targetHasDisplayOrder.DisplayOrder = sourceHasDisplayOrder.DisplayOrder; } } - + private static void MergeShortOverview(BaseItem source, BaseItem target, List lockedFields, bool replaceData) { var sourceHasShortOverview = source as IHasShortOverview; diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs index aa495afbc..4b795a474 100644 --- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs @@ -78,7 +78,8 @@ namespace MediaBrowser.Providers.MediaInfo _fileSystem.CreateDirectory(Path.GetDirectoryName(path)); var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ?? - imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1); + imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ?? + imageStreams.FirstOrDefault(); var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index; diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index a5751da0a..ff6eef167 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -10,6 +10,8 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; @@ -93,20 +95,59 @@ namespace MediaBrowser.Providers.MediaInfo try { - // If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in. - // Always use 10 seconds for dvd because our duration could be out of whack - var imageOffset = item.VideoType != VideoType.Dvd && item.RunTimeTicks.HasValue && - item.RunTimeTicks.Value > 0 - ? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1)) - : TimeSpan.FromSeconds(10); - var protocol = item.LocationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File; var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, protocol, isoMount, item.PlayableStreamFileNames); - var stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); + var mediaStreams = + item.GetMediaSources(false) + .Take(1) + .SelectMany(i => i.MediaStreams) + .ToList(); + + var imageStreams = + mediaStreams + .Where(i => i.Type == MediaStreamType.EmbeddedImage) + .ToList(); + + var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ?? + imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ?? + imageStreams.FirstOrDefault(); + + Stream stream; + + if (imageStream != null) + { + // Instead of using the raw stream index, we need to use nth video/embedded image stream + var videoIndex = -1; + foreach (var mediaStream in mediaStreams) + { + if (mediaStream.Type == MediaStreamType.Video || + mediaStream.Type == MediaStreamType.EmbeddedImage) + { + videoIndex++; + } + if (mediaStream == imageStream) + { + break; + } + } + + stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, videoIndex, cancellationToken).ConfigureAwait(false); + } + else + { + // If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in. + // Always use 10 seconds for dvd because our duration could be out of whack + var imageOffset = item.VideoType != VideoType.Dvd && item.RunTimeTicks.HasValue && + item.RunTimeTicks.Value > 0 + ? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1)) + : TimeSpan.FromSeconds(10); + + stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false); + } return new DynamicImageResponse { diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index cb74d4dd7..75b5498c5 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -85,8 +85,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// The cancellation token. private void Fetch(MetadataResult item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken) { - item.ResetPeople(); - if (!SupportsUrlAfterClosingXmlTag) { using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile)) @@ -94,6 +92,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers // Use XmlReader for best performance using (var reader = XmlReader.Create(streamReader, settings)) { + item.ResetPeople(); + reader.MoveToContent(); // Loop through each element @@ -113,6 +113,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile)) { + item.ResetPeople(); + // Need to handle a url after the xml data // http://kodi.wiki/view/NFO_files/movies From a47271321f0483139905a2896814e79f9ac2236f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 13 Apr 2016 17:20:02 -0400 Subject: [PATCH 107/852] 3.0.5935 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 073260ad7..090bf7174 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5934")] +[assembly: AssemblyVersion("3.0.5935")] From 57e3bb72f93baca695ba2b6670faec8ee0e1796b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 14 Apr 2016 15:12:00 -0400 Subject: [PATCH 108/852] update stream selection --- .../Playback/Hls/VideoHlsService.cs | 7 +++---- MediaBrowser.Api/Playback/MediaInfoService.cs | 21 +++++++++++++++++-- MediaBrowser.Model/Dlna/StreamBuilder.cs | 10 ++++----- MediaBrowser.Model/Dlna/StreamInfoSorter.cs | 19 ++++++++++++++++- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 4 +++- 5 files changed, 48 insertions(+), 13 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 610628ced..5f427146e 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -86,11 +86,10 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { - return state.VideoStream != null && IsH264(state.VideoStream) ? - args + " -bsf:v h264_mp4toannexb" : - args; + // if h264_mp4toannexb is ever added, do not use it for live tv + return args; } - + var keyFrameArg = string.Format(" -force_key_frames \"expr:gte(t,n_forced*{0})\"", state.SegmentLength.ToString(UsCulture)); diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 2bf61f90b..ffe7c50c8 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -227,7 +227,7 @@ namespace MediaBrowser.Api.Playback SetDeviceSpecificData(item, mediaSource, profile, auth, maxBitrate, startTimeTicks, mediaSourceId, audioStreamIndex, subtitleStreamIndex, result.PlaySessionId); } - SortMediaSources(result); + SortMediaSources(result, maxBitrate); } private void SetDeviceSpecificData(BaseItem item, @@ -375,7 +375,7 @@ namespace MediaBrowser.Api.Playback } } - private void SortMediaSources(PlaybackInfoResponse result) + private void SortMediaSources(PlaybackInfoResponse result, int? maxBitrate) { var originalList = result.MediaSources.ToList(); @@ -409,6 +409,23 @@ namespace MediaBrowser.Api.Playback return 1; } + }).ThenBy(i => + { + if (maxBitrate.HasValue) + { + if (i.Bitrate.HasValue) + { + if (i.Bitrate.Value <= maxBitrate.Value) + { + return 0; + } + + return 2; + } + } + + return 1; + }).ThenBy(originalList.IndexOf) .ToList(); } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 09d762aae..1e6b7c729 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -55,7 +55,7 @@ namespace MediaBrowser.Model.Dlna stream.DeviceProfileId = options.Profile.Id; } - return GetOptimalStream(streams); + return GetOptimalStream(streams, options.GetMaxBitrate()); } public StreamInfo BuildVideoItem(VideoOptions options) @@ -88,12 +88,12 @@ namespace MediaBrowser.Model.Dlna stream.DeviceProfileId = options.Profile.Id; } - return GetOptimalStream(streams); + return GetOptimalStream(streams, options.GetMaxBitrate()); } - private StreamInfo GetOptimalStream(List streams) + private StreamInfo GetOptimalStream(List streams, int? maxBitrate) { - streams = StreamInfoSorter.SortMediaSources(streams); + streams = StreamInfoSorter.SortMediaSources(streams, maxBitrate); foreach (StreamInfo stream in streams) { @@ -424,7 +424,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.EstimateContentLength = transcodingProfile.EstimateContentLength; playlistItem.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo; - // TODO: We should probably preserve the full list and sent it tp the server that way + // TODO: We should probably preserve the full list and sent it to the server that way string[] supportedAudioCodecs = transcodingProfile.AudioCodec.Split(','); string inputAudioCodec = audioStream == null ? null : audioStream.Codec; foreach (string supportedAudioCodec in supportedAudioCodecs) diff --git a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs index 0cccd8080..293054e5b 100644 --- a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs +++ b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs @@ -7,7 +7,7 @@ namespace MediaBrowser.Model.Dlna { public class StreamInfoSorter { - public static List SortMediaSources(List streams) + public static List SortMediaSources(List streams, int? maxBitrate) { return streams.OrderBy(i => { @@ -41,6 +41,23 @@ namespace MediaBrowser.Model.Dlna return 1; } + }).ThenBy(i => + { + if (maxBitrate.HasValue) + { + if (i.MediaSource.Bitrate.HasValue) + { + if (i.MediaSource.Bitrate.Value <= maxBitrate.Value) + { + return 0; + } + + return 2; + } + } + + return 1; + }).ToList(); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 638b4b9af..3499fad41 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -246,6 +246,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun string audioCodec = "ac3"; int? videoBitrate = null; + int? audioBitrate = null; if (string.Equals(profile, "mobile", StringComparison.OrdinalIgnoreCase)) { @@ -306,6 +307,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun audioCodec = channel.AudioCodec; videoBitrate = (channel.IsHD ?? true) ? 15000000 : 2000000; + audioBitrate = (channel.IsHD ?? true) ? 448000 : 192000; } } @@ -346,7 +348,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun // Set the index to -1 because we don't know the exact index of the audio stream within the container Index = -1, Codec = audioCodec, - BitRate = 192000 + BitRate = audioBitrate } }, RequiresOpening = false, From 7f2b2e1b9aa5011413c6f9dc1098d547ea415fde Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 14 Apr 2016 22:39:39 -0400 Subject: [PATCH 109/852] fix block by inherited tags --- MediaBrowser.Controller/Entities/BaseItem.cs | 18 +++ .../Entities/InternalItemsQuery.cs | 4 +- .../Persistence/SqliteItemRepository.cs | 129 +++++++++++++++++- 3 files changed, 144 insertions(+), 7 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 438c5cf23..6a3f3ba19 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1348,6 +1348,24 @@ namespace MediaBrowser.Controller.Entities return LocalizationManager.GetRatingLevel(rating); } + public List GetInheritedTags() + { + var list = new List(); + list.AddRange(Tags); + + foreach (var parent in GetParents()) + { + list.AddRange(parent.Tags); + } + + foreach (var parent in LibraryManager.GetCollectionFolders(this)) + { + list.AddRange(parent.Tags); + } + + return list.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); + } + private bool IsVisibleViaTags(User user) { var hasTags = this as IHasTags; diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index b568aec18..fbf246b3a 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -33,6 +33,7 @@ namespace MediaBrowser.Controller.Entities public string[] IncludeItemTypes { get; set; } public string[] ExcludeItemTypes { get; set; } public string[] ExcludeTags { get; set; } + public string[] ExcludeInheritedTags { get; set; } public string[] Genres { get; set; } public bool? IsMissing { get; set; } @@ -157,6 +158,7 @@ namespace MediaBrowser.Controller.Entities AncestorIds = new string[] { }; TopParentIds = new string[] { }; ExcludeTags = new string[] { }; + ExcludeInheritedTags = new string[] { }; LocationTypes = new LocationType[] { }; ExcludeLocationTypes = new LocationType[] { }; PresetViews = new string[] { }; @@ -181,7 +183,7 @@ namespace MediaBrowser.Controller.Entities BlockUnratedItems = policy.BlockUnratedItems; } - ExcludeTags = policy.BlockedTags; + ExcludeInheritedTags = policy.BlockedTags; User = user; } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index a30ff66df..4a784e253 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -78,8 +78,9 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _saveAncestorCommand; private IDbCommand _updateInheritedRatingCommand; + private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 58; + private const int LatestSchemaVersion = 61; /// /// Initializes a new instance of the class. @@ -135,7 +136,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", "create index if not exists idx_AncestorIds2 on AncestorIds(AncestorIdText)", - + "create table if not exists People (ItemId GUID, Name TEXT NOT NULL, Role TEXT, PersonType TEXT, SortOrder int, ListOrder int)", "create index if not exists idxPeopleItemId on People(ItemId)", "create index if not exists idxPeopleName on People(Name)", @@ -224,6 +225,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "CriticRating", "Float"); _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); + _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); PrepareStatements(); @@ -402,7 +404,7 @@ namespace MediaBrowser.Server.Implementations.Persistence "guid", "type", "data", - "Path", + "Path", "StartDate", "EndDate", "ChannelId", @@ -462,7 +464,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "TrailerTypes", "CriticRating", "CriticRatingSummary", - "DateModifiedDuringLastRefresh" + "DateModifiedDuringLastRefresh", + "InheritedTags" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -540,8 +543,13 @@ namespace MediaBrowser.Server.Implementations.Persistence _updateInheritedRatingCommand = _connection.CreateCommand(); _updateInheritedRatingCommand.CommandText = "Update TypedBaseItems set InheritedParentalRatingValue=@InheritedParentalRatingValue where Guid=@Guid"; - _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue"); _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@Guid"); + _updateInheritedRatingCommand.Parameters.Add(_updateInheritedRatingCommand, "@InheritedParentalRatingValue"); + + _updateInheritedTagsCommand = _connection.CreateCommand(); + _updateInheritedTagsCommand.CommandText = "Update TypedBaseItems set InheritedTags=@InheritedTags where Guid=@Guid"; + _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@Guid"); + _updateInheritedTagsCommand.Parameters.Add(_updateInheritedTagsCommand, "@InheritedTags"); } /// @@ -715,7 +723,15 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.ServiceName; - _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); + if (item.Tags.Count > 0) + { + _saveItemCommand.GetParameter(index++).Value = string.Join("|", item.Tags.ToArray()); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + _saveItemCommand.GetParameter(index++).Value = item.IsFolder; _saveItemCommand.GetParameter(index++).Value = item.GetBlockUnratedType().ToString(); @@ -765,6 +781,16 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.DateModifiedDuringLastRefresh.Value; } + var inheritedTags = item.GetInheritedTags(); + if (inheritedTags.Count > 0) + { + _saveItemCommand.GetParameter(index++).Value = string.Join("|", inheritedTags.ToArray()); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -2165,6 +2191,14 @@ namespace MediaBrowser.Server.Implementations.Persistence excludeTagIndex++; } + excludeTagIndex = 0; + foreach (var excludeTag in query.ExcludeInheritedTags) + { + whereClauses.Add("InheritedTags not like @excludeInheritedTag" + excludeTagIndex); + cmd.Parameters.Add(cmd, "@excludeInheritedTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; + excludeTagIndex++; + } + if (addPaging) { if (query.StartIndex.HasValue && query.StartIndex.Value > 0) @@ -2224,6 +2258,88 @@ namespace MediaBrowser.Server.Implementations.Persistence }; public async Task UpdateInheritedValues(CancellationToken cancellationToken) + { + await UpdateInheritedParentalRating(cancellationToken).ConfigureAwait(false); + await UpdateInheritedTags(cancellationToken).ConfigureAwait(false); + } + + private async Task UpdateInheritedTags(CancellationToken cancellationToken) + { + var newValues = new List>(); + + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "select Guid,InheritedTags,(select group_concat(Tags, '|') from TypedBaseItems where (guid=outer.guid) OR (guid in (Select AncestorId from AncestorIds where ItemId=Outer.guid))) as NewInheritedTags from typedbaseitems as Outer where NewInheritedTags <> InheritedTags"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + var id = reader.GetGuid(0); + string value = reader.IsDBNull(2) ? null : reader.GetString(2); + + newValues.Add(new Tuple(id, value)); + } + } + } + + Logger.Debug("UpdateInheritedTags - {0} rows", newValues.Count); + if (newValues.Count == 0) + { + return; + } + + await WriteLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + IDbTransaction transaction = null; + + try + { + transaction = _connection.BeginTransaction(); + + foreach (var item in newValues) + { + _updateInheritedTagsCommand.GetParameter(0).Value = item.Item1; + _updateInheritedTagsCommand.GetParameter(1).Value = item.Item2; + + _updateInheritedTagsCommand.Transaction = transaction; + _updateInheritedTagsCommand.ExecuteNonQuery(); + } + + transaction.Commit(); + } + catch (OperationCanceledException) + { + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + catch (Exception e) + { + Logger.ErrorException("Error running query:", e); + + if (transaction != null) + { + transaction.Rollback(); + } + + throw; + } + finally + { + if (transaction != null) + { + transaction.Dispose(); + } + + WriteLock.Release(); + } + } + + private async Task UpdateInheritedParentalRating(CancellationToken cancellationToken) { var newValues = new List>(); @@ -2243,6 +2359,7 @@ namespace MediaBrowser.Server.Implementations.Persistence } } + Logger.Debug("UpdateInheritedParentalRatings - {0} rows", newValues.Count); if (newValues.Count == 0) { return; From 5de094674b052f947c56b79d71d4bbfdce49405f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 14 Apr 2016 22:43:46 -0400 Subject: [PATCH 110/852] 3.0.5936 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 090bf7174..d04c665c8 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5935")] +[assembly: AssemblyVersion("3.0.5936")] From 81d9ea05f6858e42895e8d693da71b2381194996 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 15 Apr 2016 22:18:40 -0400 Subject: [PATCH 111/852] fix image refresh --- .../CollectionFolderMetadataService.cs | 29 +++++++++++++++++++ .../Folders/UserViewMetadataService.cs | 13 --------- .../Manager/MetadataService.cs | 11 +++++-- .../MediaBrowser.Providers.csproj | 1 + 4 files changed, 39 insertions(+), 15 deletions(-) create mode 100644 MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs diff --git a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs new file mode 100644 index 000000000..e1de443de --- /dev/null +++ b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CommonIO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Providers.Manager; + +namespace MediaBrowser.Providers.Folders +{ + public class CollectionFolderMetadataService : MetadataService + { + public CollectionFolderMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager) + { + } + + protected override void MergeData(MetadataResult source, MetadataResult target, List lockedFields, bool replaceData, bool mergeMetadataSettings) + { + ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + } + } +} diff --git a/MediaBrowser.Providers/Folders/UserViewMetadataService.cs b/MediaBrowser.Providers/Folders/UserViewMetadataService.cs index 545b178e2..7c298a3ed 100644 --- a/MediaBrowser.Providers/Folders/UserViewMetadataService.cs +++ b/MediaBrowser.Providers/Folders/UserViewMetadataService.cs @@ -21,17 +21,4 @@ namespace MediaBrowser.Providers.Folders ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); } } - - public class CollectionFolderMetadataService : MetadataService - { - public CollectionFolderMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager) - { - } - - protected override void MergeData(MetadataResult source, MetadataResult target, List lockedFields, bool replaceData, bool mergeMetadataSettings) - { - ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); - } - } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 47783ebc6..3d584e858 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -143,8 +143,8 @@ namespace MediaBrowser.Providers.Manager Item = itemOfType }; - bool hasRefreshedMetadata = false; - bool hasRefreshedImages = false; + bool hasRefreshedMetadata = true; + bool hasRefreshedImages = true; // Next run metadata providers if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) @@ -186,6 +186,7 @@ namespace MediaBrowser.Providers.Manager } else { + hasRefreshedMetadata = false; refreshResult.SetDateLastMetadataRefresh(null); } } @@ -208,6 +209,7 @@ namespace MediaBrowser.Providers.Manager } else { + hasRefreshedImages = false; refreshResult.SetDateLastImagesRefresh(null); } } @@ -303,6 +305,11 @@ namespace MediaBrowser.Providers.Manager return true; } + if (item is ICollectionFolder) + { + return true; + } + return false; } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 8927e00aa..f07478f98 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -88,6 +88,7 @@ + From bfc8facc60f919f8455d4c6c7f48a4eca17f2812 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 01:05:34 -0400 Subject: [PATCH 112/852] fixes #1261 - Sync quality cannot be changed --- .../Sync/SyncJobProcessor.cs | 45 ++++++++----------- .../Sync/SyncManager.cs | 8 ++-- .../Sync/SyncRepository.cs | 2 +- 3 files changed, 23 insertions(+), 32 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 01334c121..33874b4d4 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -149,16 +149,6 @@ namespace MediaBrowser.Server.Implementations.Sync { var job = _syncRepo.GetJob(id); - return UpdateJobStatus(job); - } - - private Task UpdateJobStatus(SyncJob job) - { - if (job == null) - { - throw new ArgumentNullException("job"); - } - var result = _syncManager.GetJobItems(new SyncJobItemQuery { JobId = job.Id, @@ -476,14 +466,12 @@ namespace MediaBrowser.Server.Implementations.Sync if (jobItem != null) { - var job = _syncRepo.GetJob(jobItem.JobId); if (jobItem.Status != SyncJobItemStatus.Cancelled) { - await ProcessJobItem(job, jobItem, enableConversion, innerProgress, cancellationToken).ConfigureAwait(false); + await ProcessJobItem(jobItem, enableConversion, innerProgress, cancellationToken).ConfigureAwait(false); } - job = _syncRepo.GetJob(jobItem.JobId); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } numComplete++; @@ -493,7 +481,7 @@ namespace MediaBrowser.Server.Implementations.Sync } } - private async Task ProcessJobItem(SyncJob job, SyncJobItem jobItem, bool enableConversion, IProgress progress, CancellationToken cancellationToken) + private async Task ProcessJobItem(SyncJobItem jobItem, bool enableConversion, IProgress progress, CancellationToken cancellationToken) { var item = _libraryManager.GetItemById(jobItem.ItemId); if (item == null) @@ -507,6 +495,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 0; var syncOptions = _config.GetSyncOptions(); + var job = _syncManager.GetJob(jobItem.JobId); var user = _userManager.GetUserById(job.UserId); if (user == null) { @@ -521,7 +510,7 @@ namespace MediaBrowser.Server.Implementations.Sync { AddMetadata = false, ItemId = jobItem.ItemId, - TargetId = job.TargetId, + TargetId = jobItem.TargetId, Statuses = new[] { SyncJobItemStatus.Converting, SyncJobItemStatus.Queued, SyncJobItemStatus.ReadyToTransfer, SyncJobItemStatus.Synced, SyncJobItemStatus.Transferring } }); @@ -531,7 +520,7 @@ namespace MediaBrowser.Server.Implementations.Sync if (duplicateJobItems.Count > 0) { - var syncProvider = _syncManager.GetSyncProvider(jobItem, job) as IHasDuplicateCheck; + var syncProvider = _syncManager.GetSyncProvider(jobItem) as IHasDuplicateCheck; if (!duplicateJobItems.Any(i => AllowDuplicateJobItem(syncProvider, i, jobItem))) { @@ -545,12 +534,12 @@ namespace MediaBrowser.Server.Implementations.Sync var video = item as Video; if (video != null) { - await Sync(jobItem, job, video, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, video, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); } else if (item is Audio) { - await Sync(jobItem, job, (Audio)item, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); + await Sync(jobItem, (Audio)item, user, enableConversion, syncOptions, progress, cancellationToken).ConfigureAwait(false); } else if (item is Photo) @@ -574,8 +563,9 @@ namespace MediaBrowser.Server.Implementations.Sync return true; } - private async Task Sync(SyncJobItem jobItem, SyncJob job, Video item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) + private async Task Sync(SyncJobItem jobItem, Video item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) { + var job = _syncManager.GetJob(jobItem.JobId); var jobOptions = _syncManager.GetVideoOptions(jobItem, job); var conversionOptions = new VideoOptions { @@ -616,7 +606,7 @@ namespace MediaBrowser.Server.Implementations.Sync { // Save the job item now since conversion could take a while await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); try { @@ -630,7 +620,7 @@ namespace MediaBrowser.Server.Implementations.Sync { jobItem.Progress = pct / 2; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } }); @@ -642,7 +632,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); - _syncManager.OnConversionComplete(jobItem, job); + _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) { @@ -775,8 +765,9 @@ namespace MediaBrowser.Server.Implementations.Sync private const int DatabaseProgressUpdateIntervalSeconds = 2; - private async Task Sync(SyncJobItem jobItem, SyncJob job, Audio item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) + private async Task Sync(SyncJobItem jobItem, Audio item, User user, bool enableConversion, SyncOptions syncOptions, IProgress progress, CancellationToken cancellationToken) { + var job = _syncManager.GetJob(jobItem.JobId); var jobOptions = _syncManager.GetAudioOptions(jobItem, job); var conversionOptions = new AudioOptions { @@ -803,7 +794,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Status = SyncJobItemStatus.Converting; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); try { @@ -817,7 +808,7 @@ namespace MediaBrowser.Server.Implementations.Sync { jobItem.Progress = pct / 2; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); - await UpdateJobStatus(job).ConfigureAwait(false); + await UpdateJobStatus(jobItem.JobId).ConfigureAwait(false); } }); @@ -828,7 +819,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); - _syncManager.OnConversionComplete(jobItem, job); + _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) { diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 2effad2f7..044c8b93a 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -1117,7 +1117,7 @@ namespace MediaBrowser.Server.Implementations.Sync public SyncJobOptions GetAudioOptions(SyncJobItem jobItem, SyncJob job) { var options = GetSyncJobOptions(jobItem.TargetId, null, null); - + if (job.Bitrate.HasValue) { options.DeviceProfile.MaxStaticBitrate = job.Bitrate.Value; @@ -1126,7 +1126,7 @@ namespace MediaBrowser.Server.Implementations.Sync return options; } - public ISyncProvider GetSyncProvider(SyncJobItem jobItem, SyncJob job) + public ISyncProvider GetSyncProvider(SyncJobItem jobItem) { foreach (var provider in _providers) { @@ -1323,9 +1323,9 @@ namespace MediaBrowser.Server.Implementations.Sync return list; } - protected internal void OnConversionComplete(SyncJobItem item, SyncJob job) + protected internal void OnConversionComplete(SyncJobItem item) { - var syncProvider = GetSyncProvider(item, job); + var syncProvider = GetSyncProvider(item); if (syncProvider is AppSyncProvider) { return; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 39153526a..464e8aa58 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -104,7 +104,7 @@ namespace MediaBrowser.Server.Implementations.Sync // _updateJobCommand _updateJobCommand = _connection.CreateCommand(); - _updateJobCommand.CommandText = "update SyncJobs set TargetId=@TargetId,Name=@Name,Profile=@Profile,Quality=@Quality,Bitrate=@Bitrate,Status=@Status,Progress=@Progress,UserId=@UserId,ItemIds=@ItemIds,Category=@Category,ParentId=@ParentId,UnwatchedOnly=@UnwatchedOnly,ItemLimit=@ItemLimit,SyncNewContent=@SyncNewContent,DateCreated=@DateCreated,DateLastModified=@DateLastModified,ItemCount=@ItemCount where Id=@ID"; + _updateJobCommand.CommandText = "update SyncJobs set TargetId=@TargetId,Name=@Name,Profile=@Profile,Quality=@Quality,Bitrate=@Bitrate,Status=@Status,Progress=@Progress,UserId=@UserId,ItemIds=@ItemIds,Category=@Category,ParentId=@ParentId,UnwatchedOnly=@UnwatchedOnly,ItemLimit=@ItemLimit,SyncNewContent=@SyncNewContent,DateCreated=@DateCreated,DateLastModified=@DateLastModified,ItemCount=@ItemCount where Id=@Id"; _updateJobCommand.Parameters.Add(_updateJobCommand, "@Id"); _updateJobCommand.Parameters.Add(_updateJobCommand, "@TargetId"); From cff3df38ee353f49b4be3bb998bd65a119ac58bc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 01:08:14 -0400 Subject: [PATCH 113/852] fixes #1581 - Metadata Manager: Disable display of "MissingTrailer" icon --- 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 70b19f971..f7b550a13 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -796,9 +796,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From d1b3342e75f61b27f0cb9a8457b6e5ba9b86821c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 01:09:58 -0400 Subject: [PATCH 114/852] update inherited tags --- MediaBrowser.Controller/Entities/BaseItem.cs | 5 ----- .../Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6a3f3ba19..04371c13b 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1358,11 +1358,6 @@ namespace MediaBrowser.Controller.Entities list.AddRange(parent.Tags); } - foreach (var parent in LibraryManager.GetCollectionFolders(this)) - { - list.AddRange(parent.Tags); - } - return list.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4a784e253..212be2849 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 61; + private const int LatestSchemaVersion = 62; /// /// Initializes a new instance of the class. From da0f4017ac105509152be406fd532e63a647641f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 01:13:00 -0400 Subject: [PATCH 115/852] 3.0.5937 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index d04c665c8..17c735fe8 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5936")] +[assembly: AssemblyVersion("3.0.5937")] From cf4a14357ef8c602dd6dbfc0d8e9737ae0badaaa Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 13:19:20 -0400 Subject: [PATCH 116/852] restore hdhr direct play for now --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 3499fad41..4c140602d 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -356,7 +356,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun BufferMs = 0, Container = "ts", Id = profile, - SupportsDirectPlay = false, + SupportsDirectPlay = true, SupportsDirectStream = false, SupportsTranscoding = true }; From 4c64c42876d06fa8ea71d2a64494d74d737936bd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 13:24:00 -0400 Subject: [PATCH 117/852] update translations --- .../Localization/Core/ca.json | 10 +- .../Localization/Core/es.json | 142 +++++++++--------- .../Localization/Core/hu.json | 4 +- .../Localization/Core/nl.json | 2 +- .../Localization/Core/ru.json | 16 +- .../Localization/Core/sv.json | 78 +++++----- .../Localization/Core/zh-TW.json | 18 +-- 7 files changed, 135 insertions(+), 135 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ca.json b/MediaBrowser.Server.Implementations/Localization/Core/ca.json index 7cec213d3..7ca8e1553 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/ca.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/ca.json @@ -1,5 +1,5 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "DbUpgradeMessage": "Si et plau espera mentre la teva base de dades del Servidor Emby \u00e9s actualitzada. {0}% completat.", "AppDeviceValues": "App: {0}, Dispositiu: {1}", "UserDownloadingItemWithValues": "{0} est\u00e0 descarregant {1}", "FolderTypeMixed": "Contingut barrejat", @@ -19,11 +19,11 @@ "LabelChapterName": "Cap\u00edtol {0}", "NameSeasonNumber": "Temporada {0}", "LabelExit": "Sortir", - "LabelVisitCommunity": "Visita la comunitat", + "LabelVisitCommunity": "Visita la Comunitat", "LabelGithub": "Github", "LabelApiDocumentation": "Documentaci\u00f3 de l'API", - "LabelDeveloperResources": "Recursos per a programadors", - "LabelBrowseLibrary": "Examina la biblioteca", + "LabelDeveloperResources": "Recursos per a Desenvolupadors", + "LabelBrowseLibrary": "Examina la Biblioteca", "LabelConfigureServer": "Configura Emby", "LabelRestartServer": "Reiniciar Servidor", "CategorySync": "Sync", @@ -131,7 +131,7 @@ "HeaderType": "Type", "HeaderSeverity": "Severity", "HeaderUser": "Usuari", - "HeaderName": "Name", + "HeaderName": "Nom", "HeaderDate": "Data", "HeaderPremiereDate": "Premiere Date", "HeaderDateAdded": "Data afegida", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/es.json b/MediaBrowser.Server.Implementations/Localization/Core/es.json index 2a715a5b3..d1a56240d 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/es.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/es.json @@ -1,7 +1,7 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", + "DbUpgradeMessage": "Por favor espere mientras la base de datos de su servidor Emby se actualiza. {0}% completado.", + "AppDeviceValues": "Aplicaci\u00f3n: {0}, Dispositivo: {1}", + "UserDownloadingItemWithValues": "{0} est\u00e1 descargando {1}", "FolderTypeMixed": "Contenido mezclado", "FolderTypeMovies": "Peliculas", "FolderTypeMusic": "Musica", @@ -14,10 +14,10 @@ "FolderTypeTvShows": "TV", "FolderTypeInherit": "Heredado", "HeaderCastCrew": "Reparto y equipo t\u00e9cnico", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", + "HeaderPeople": "Gente", + "ValueSpecialEpisodeName": "Especial - {0}", "LabelChapterName": "Cap\u00edtulo {0}", - "NameSeasonNumber": "Season {0}", + "NameSeasonNumber": "Temporada {0}", "LabelExit": "Salir", "LabelVisitCommunity": "Visitar la comunidad", "LabelGithub": "Github", @@ -50,77 +50,77 @@ "NotificationOptionCameraImageUploaded": "Imagen de camara se a carcado", "NotificationOptionUserLockedOut": "Usuario bloqueado", "NotificationOptionServerRestartRequired": "Se requiere el reinicio del servidor", - "ViewTypePlaylists": "Playlists", + "ViewTypePlaylists": "Listas de reproducci\u00f3n", "ViewTypeMovies": "Pel\u00edculas", "ViewTypeTvShows": "TV", "ViewTypeGames": "Juegos", "ViewTypeMusic": "M\u00fasica", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", + "ViewTypeMusicGenres": "G\u00e9neros", + "ViewTypeMusicArtists": "Artistas", "ViewTypeBoxSets": "Colecciones", "ViewTypeChannels": "Canales", "ViewTypeLiveTV": "Tv en vivo", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", + "ViewTypeLiveTvNowPlaying": "Transmiti\u00e9ndose ahora", + "ViewTypeLatestGames": "\u00daltimos juegos", + "ViewTypeRecentlyPlayedGames": "Reproducido recientemente", + "ViewTypeGameFavorites": "Favoritos", + "ViewTypeGameSystems": "Sistemas de juego", + "ViewTypeGameGenres": "G\u00e9neros", + "ViewTypeTvResume": "Reanudar", + "ViewTypeTvNextUp": "Pr\u00f3ximamente", + "ViewTypeTvLatest": "\u00daltimas", "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", + "ViewTypeTvGenres": "G\u00e9neros", + "ViewTypeTvFavoriteSeries": "Series favoritas", + "ViewTypeTvFavoriteEpisodes": "Episodios favoritos", + "ViewTypeMovieResume": "Reanudar", + "ViewTypeMovieLatest": "\u00daltimas", + "ViewTypeMovieMovies": "Pel\u00edculas", + "ViewTypeMovieCollections": "Colecciones", + "ViewTypeMovieFavorites": "Favoritos", + "ViewTypeMovieGenres": "G\u00e9neros", + "ViewTypeMusicLatest": "\u00daltimas", + "ViewTypeMusicPlaylists": "Lista", + "ViewTypeMusicAlbums": "\u00c1lbumes", + "ViewTypeMusicAlbumArtists": "\u00c1lbumes de artistas", "HeaderOtherDisplaySettings": "Configuraci\u00f3n de pantalla", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", + "ViewTypeMusicSongs": "Canciones", + "ViewTypeMusicFavorites": "Favoritos", + "ViewTypeMusicFavoriteAlbums": "\u00c1lbumes favoritos", + "ViewTypeMusicFavoriteArtists": "Artistas favoritos", + "ViewTypeMusicFavoriteSongs": "Canciones favoritas", + "ViewTypeFolders": "Carpetas", + "ViewTypeLiveTvRecordingGroups": "Grabaciones", + "ViewTypeLiveTvChannels": "Canales", + "ScheduledTaskFailedWithName": "{0} fall\u00f3", + "LabelRunningTimeValue": "Tiempo de ejecuci\u00f3n: {0}", + "ScheduledTaskStartedWithName": "{0} iniciado", "VersionNumber": "Versi\u00f3n {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "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}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "PluginInstalledWithName": "{0} ha sido instalado", + "PluginUpdatedWithName": "{0} ha sido actualizado", + "PluginUninstalledWithName": "{0} ha sido desinstalado", + "ItemAddedWithName": "{0} ha sido a\u00f1adido a la biblioteca", + "ItemRemovedWithName": "{0} se ha eliminado de la biblioteca", + "LabelIpAddressValue": "Direcci\u00f3n IP: {0}", + "DeviceOnlineWithName": "{0} est\u00e1 conectado", + "UserOnlineFromDevice": "{0} est\u00e1 conectado desde {1}", + "ProviderValue": "Proveedor: {0}", + "SubtitlesDownloadedForItem": "Subt\u00edtulos descargados para {0}", + "UserConfigurationUpdatedWithName": "Se ha actualizado la configuraci\u00f3n de usuario para {0}", + "UserCreatedWithName": "Se ha creado el usuario {0}", + "UserPasswordChangedWithName": "Contrase\u00f1a cambiada al usuario {0}", + "UserDeletedWithName": "El usuario {0} ha sido eliminado", + "MessageServerConfigurationUpdated": "Se ha actualizado la configuraci\u00f3n del servidor", + "MessageNamedServerConfigurationUpdatedWithValue": "Se ha actualizado la secci\u00f3n {0} de la configuraci\u00f3n del servidor", + "MessageApplicationUpdated": "Se ha actualizado el servidor Emby", + "FailedLoginAttemptWithUserName": "Intento de inicio de sesi\u00f3n fallido desde {0}", + "AuthenticationSucceededWithUserName": "{0} se ha autenticado satisfactoriamente", + "DeviceOfflineWithName": "{0} se ha desconectado", + "UserLockedOutWithName": "El usuario {0} ha sido bloqueado", + "UserOfflineFromDevice": "{0} se ha desconectado de {1}", + "UserStartedPlayingItemWithValues": "{0} ha empezado a reproducir {1}", + "UserStoppedPlayingItemWithValues": "{0} ha parado de reproducir {1}", + "SubtitleDownloadFailureForItem": "Fallo en la descarga de subt\u00edtulos para {0}", "HeaderUnidentified": "Unidentified", "HeaderImagePrimary": "Primary", "HeaderImageBackdrop": "Backdrop", @@ -159,20 +159,20 @@ "HeaderEmbeddedImage": "Embedded image", "HeaderResolution": "Resolution", "HeaderSubtitles": "Subt\u00edtulos", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", + "HeaderGenres": "G\u00e9neros", + "HeaderCountries": "Paises", "HeaderStatus": "Estado", "HeaderTracks": "Tracks", "HeaderMusicArtist": "Music artist", "HeaderLocked": "Locked", - "HeaderStudios": "Studios", + "HeaderStudios": "Estudios", "HeaderActor": "Actors", "HeaderComposer": "Composers", "HeaderDirector": "Directors", "HeaderGuestStar": "Guest star", "HeaderProducer": "Producers", "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", + "HeaderParentalRatings": "Clasificaci\u00f3n parental", "HeaderCommunityRatings": "Community ratings", "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/hu.json b/MediaBrowser.Server.Implementations/Localization/Core/hu.json index d098a893c..2b9d28d8c 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/hu.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/hu.json @@ -169,8 +169,8 @@ "HeaderActor": "Sz\u00edn\u00e9szek", "HeaderComposer": "Zeneszerz\u0151k", "HeaderDirector": "Rendez\u0151k", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", + "HeaderGuestStar": "Vend\u00e9g szt\u00e1r", + "HeaderProducer": "Producerek", "HeaderWriter": "\u00cdr\u00f3k", "HeaderParentalRatings": "Korhat\u00e1r besorol\u00e1s", "HeaderCommunityRatings": "K\u00f6z\u00f6ss\u00e9gi \u00e9rt\u00e9kel\u00e9sek", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/nl.json b/MediaBrowser.Server.Implementations/Localization/Core/nl.json index a83182ee8..2818fbf6a 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/nl.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/nl.json @@ -1,5 +1,5 @@ { - "DbUpgradeMessage": "Even geduld svp terwijl de Emby Server database ge-upgrade wordt. {0}% gereed.", + "DbUpgradeMessage": "Een ogenblik geduld terwijl uw Emby Server-database wordt bijgewerkt. {0}% voltooid.", "AppDeviceValues": "App: {0}, Apparaat: {1}", "UserDownloadingItemWithValues": "{0} download {1}", "FolderTypeMixed": "Gemengde inhoud", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/ru.json b/MediaBrowser.Server.Implementations/Localization/Core/ru.json index fa68aadb9..62fe3b496 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/ru.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/ru.json @@ -2,17 +2,17 @@ "DbUpgradeMessage": "\u041f\u043e\u0434\u043e\u0436\u0434\u0438\u0442\u0435, \u043f\u043e\u043a\u0430 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0432\u0430\u0448\u0435\u043c Emby Server \u043c\u043e\u0434\u0435\u0440\u043d\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f. {0} % \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e.", "AppDeviceValues": "\u041f\u0440\u0438\u043b.: {0}, \u0423\u0441\u0442\u0440.: {1}", "UserDownloadingItemWithValues": "{0} \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 {1}", - "FolderTypeMixed": "\u0420\u0430\u0437\u043d\u043e\u0442\u0438\u043f\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435", + "FolderTypeMixed": "\u0421\u043c\u0435\u0448\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435", "FolderTypeMovies": "\u041a\u0438\u043d\u043e", "FolderTypeMusic": "\u041c\u0443\u0437\u044b\u043a\u0430", - "FolderTypeAdultVideos": "\u0412\u0438\u0434\u0435\u043e \u0434\u043b\u044f \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0445", - "FolderTypePhotos": "\u0424\u043e\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438", - "FolderTypeMusicVideos": "\u041c\u0443\u0437\u044b\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0435\u043e", - "FolderTypeHomeVideos": "\u0414\u043e\u043c\u0430\u0448\u043d\u0438\u0435 \u0432\u0438\u0434\u0435\u043e", + "FolderTypeAdultVideos": "\u0414\u043b\u044f \u0432\u0437\u0440\u043e\u0441\u043b\u044b\u0445", + "FolderTypePhotos": "\u0424\u043e\u0442\u043e", + "FolderTypeMusicVideos": "\u041c\u0443\u0437. \u0432\u0438\u0434\u0435\u043e", + "FolderTypeHomeVideos": "\u0414\u043e\u043c. \u0432\u0438\u0434\u0435\u043e", "FolderTypeGames": "\u0418\u0433\u0440\u044b", - "FolderTypeBooks": "\u041a\u043d\u0438\u0433\u0438", + "FolderTypeBooks": "\u041b\u0438\u0442\u0435\u0440\u0430\u0442\u0443\u0440\u0430", "FolderTypeTvShows": "\u0422\u0412", - "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0435", + "FolderTypeInherit": "\u041d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u043c\u044b\u0439", "HeaderCastCrew": "\u0421\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u044c \u0438 \u0441\u043d\u0438\u043c\u0430\u043b\u0438", "HeaderPeople": "\u041b\u044e\u0434\u0438", "ValueSpecialEpisodeName": "\u0421\u043f\u0435\u0446\u044d\u043f\u0438\u0437\u043e\u0434 - {0}", @@ -163,7 +163,7 @@ "HeaderCountries": "\u0421\u0442\u0440\u0430\u043d\u044b", "HeaderStatus": "\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435", "HeaderTracks": "\u0414\u043e\u0440-\u043a\u0438", - "HeaderMusicArtist": "\u0418\u0441\u043f. \u043c\u0443\u0437\u044b\u043a\u0438", + "HeaderMusicArtist": "\u041c\u0443\u0437. \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c", "HeaderLocked": "\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043e", "HeaderStudios": "\u0421\u0442\u0443\u0434\u0438\u0438", "HeaderActor": "\u0410\u043a\u0442\u0451\u0440\u044b", diff --git a/MediaBrowser.Server.Implementations/Localization/Core/sv.json b/MediaBrowser.Server.Implementations/Localization/Core/sv.json index eca16e2b4..4a6565aff 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/sv.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/sv.json @@ -1,7 +1,7 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "DbUpgradeMessage": "V\u00e4nligen v\u00e4nta medan databasen p\u00e5 din Emby Server uppgraderas. {0}% klar", "AppDeviceValues": "App: {0}, enhet: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", + "UserDownloadingItemWithValues": "{0} laddar ned {1}", "FolderTypeMixed": "Blandat inneh\u00e5ll", "FolderTypeMovies": "Filmer", "FolderTypeMusic": "Musik", @@ -15,18 +15,18 @@ "FolderTypeInherit": "\u00c4rv", "HeaderCastCrew": "Rollista & bes\u00e4ttning", "HeaderPeople": "Personer", - "ValueSpecialEpisodeName": "Special - {0}", + "ValueSpecialEpisodeName": "Specialavsnitt - {0}", "LabelChapterName": "Kapitel {0}", - "NameSeasonNumber": "Season {0}", + "NameSeasonNumber": "S\u00e4song {0}", "LabelExit": "Avsluta", "LabelVisitCommunity": "Bes\u00f6k v\u00e5rt diskussionsforum", "LabelGithub": "Github", - "LabelApiDocumentation": "Api Dokumentation", + "LabelApiDocumentation": "Api-dokumentation", "LabelDeveloperResources": "Resurser f\u00f6r utvecklare", "LabelBrowseLibrary": "Bl\u00e4ddra i biblioteket", "LabelConfigureServer": "Konfigurera Emby", "LabelRestartServer": "Starta om servern", - "CategorySync": "Synka", + "CategorySync": "Synkronisera", "CategoryUser": "Anv\u00e4ndare", "CategorySystem": "System", "CategoryApplication": "App", @@ -47,10 +47,10 @@ "NotificationOptionInstallationFailed": "Fel vid installation", "NotificationOptionNewLibraryContent": "Nytt inneh\u00e5ll har tillkommit", "NotificationOptionNewLibraryContentMultiple": "Nytillkommet inneh\u00e5ll finns (flera objekt)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", + "NotificationOptionCameraImageUploaded": "Kaberabild uppladdad", + "NotificationOptionUserLockedOut": "Anv\u00e4ndare har l\u00e5sts ute", "NotificationOptionServerRestartRequired": "Servern m\u00e5ste startas om", - "ViewTypePlaylists": "Playlists", + "ViewTypePlaylists": "Spellistor", "ViewTypeMovies": "Filmer", "ViewTypeTvShows": "TV", "ViewTypeGames": "Spel", @@ -80,10 +80,10 @@ "ViewTypeMovieFavorites": "Favoriter", "ViewTypeMovieGenres": "Genrer", "ViewTypeMusicLatest": "Nytillkommet", - "ViewTypeMusicPlaylists": "Playlists", + "ViewTypeMusicPlaylists": "Spellistor", "ViewTypeMusicAlbums": "Album", "ViewTypeMusicAlbumArtists": "Albumartister", - "HeaderOtherDisplaySettings": "Visningsinst\u00e4llningar", + "HeaderOtherDisplaySettings": "Visningsalternativ", "ViewTypeMusicSongs": "L\u00e5tar", "ViewTypeMusicFavorites": "Favoriter", "ViewTypeMusicFavoriteAlbums": "Favoritalbum", @@ -112,45 +112,45 @@ "UserDeletedWithName": "Anv\u00e4ndaren {0} har tagits bort", "MessageServerConfigurationUpdated": "Server konfigurationen har uppdaterats", "MessageNamedServerConfigurationUpdatedWithValue": "Serverinst\u00e4llningarnas del {0} ar uppdaterats", - "MessageApplicationUpdated": "Emby Server has been updated", + "MessageApplicationUpdated": "Emby Server har uppdaterats", "FailedLoginAttemptWithUserName": "Misslyckat inloggningsf\u00f6rs\u00f6k fr\u00e5n {0}", "AuthenticationSucceededWithUserName": "{0} har autentiserats", "DeviceOfflineWithName": "{0} har avbrutit anslutningen", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} har kopplats bort fr\u00e5n {1}", + "UserLockedOutWithName": "Anv\u00e4ndare {0} har l\u00e5sts ute", + "UserOfflineFromDevice": "{0} har avbrutit anslutningen fr\u00e5n {1}", "UserStartedPlayingItemWithValues": "{0} har p\u00e5b\u00f6rjat uppspelning av {1}", "UserStoppedPlayingItemWithValues": "{0} har avslutat uppspelning av {1}", "SubtitleDownloadFailureForItem": "Nerladdning av undertexter f\u00f6r {0} misslyckades", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", + "HeaderUnidentified": "Oidentifierad", + "HeaderImagePrimary": "Huvudbild", + "HeaderImageBackdrop": "Bakgrundsbild", + "HeaderImageLogo": "Logotyp", + "HeaderUserPrimaryImage": "Anv\u00e4ndarbild", + "HeaderOverview": "\u00d6versikt", + "HeaderShortOverview": "Kort \u00f6versikt", + "HeaderType": "Typ", "HeaderSeverity": "Severity", "HeaderUser": "Anv\u00e4ndare", "HeaderName": "Namn", "HeaderDate": "Datum", - "HeaderPremiereDate": "Premiere Date", + "HeaderPremiereDate": "Premi\u00e4rdatum", "HeaderDateAdded": "Date Added", "HeaderReleaseDate": "Premi\u00e4rdatum:", "HeaderRuntime": "Speltid", - "HeaderPlayCount": "Play Count", + "HeaderPlayCount": "Antal spelningar", "HeaderSeason": "S\u00e4song", "HeaderSeasonNumber": "S\u00e4songsnummer:", - "HeaderSeries": "Series:", + "HeaderSeries": "Serie:", "HeaderNetwork": "TV-bolag", - "HeaderYear": "Year:", - "HeaderYears": "Years:", + "HeaderYear": "\u00c5r:", + "HeaderYears": "\u00c5r:", "HeaderParentalRating": "Parental Rating", "HeaderCommunityRating": "Anv\u00e4ndaromd\u00f6me", "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specialer", + "HeaderSpecials": "Specialavsnitt", "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", + "HeaderPlayers": "Spelare:", + "HeaderAlbumArtists": "Albumartister", "HeaderAlbums": "Album", "HeaderDisc": "Skiva", "HeaderTrack": "Sp\u00e5r", @@ -163,16 +163,16 @@ "HeaderCountries": "L\u00e4nder", "HeaderStatus": "Status", "HeaderTracks": "Sp\u00e5r", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", + "HeaderMusicArtist": "Musikartist", + "HeaderLocked": "L\u00e5st", "HeaderStudios": "Studior", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", + "HeaderActor": "Sk\u00e5despelare", + "HeaderComposer": "Komposit\u00f6rer", + "HeaderDirector": "Regiss\u00f6r", + "HeaderGuestStar": "G\u00e4startist", + "HeaderProducer": "Producenter", + "HeaderWriter": "F\u00f6rfattare", "HeaderParentalRatings": "Parental Ratings", "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." + "StartupEmbyServerIsLoading": "Emby Server startar. V\u00e4nligen f\u00f6rs\u00f6k igen om en kort stund." } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json b/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json index 7f289fc1f..b711aab1f 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/zh-TW.json @@ -1,5 +1,5 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "DbUpgradeMessage": "\u8acb\u7a0d\u5019\uff0cEmby\u4f3a\u670d\u5668\u8cc7\u6599\u5eab\u6b63\u5728\u66f4\u65b0...\uff08\u5df2\u5b8c\u6210{0}%\uff09", "AppDeviceValues": "App: {0}, Device: {1}", "UserDownloadingItemWithValues": "{0} is downloading {1}", "FolderTypeMixed": "Mixed content", @@ -19,13 +19,13 @@ "LabelChapterName": "Chapter {0}", "NameSeasonNumber": "Season {0}", "LabelExit": "\u96e2\u958b", - "LabelVisitCommunity": "\u8a2a\u554f\u793e\u5340", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "\u700f\u89bd\u5a92\u9ad4\u5eab", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u4f3a\u5668\u670d", + "LabelVisitCommunity": "\u8a2a\u554f\u793e\u7fa4", + "LabelGithub": "GitHub", + "LabelApiDocumentation": "API\u8aaa\u660e\u6587\u4ef6", + "LabelDeveloperResources": "\u958b\u767c\u4eba\u54e1\u5c08\u5340", + "LabelBrowseLibrary": "\u700f\u89bd\u5a92\u9ad4\u6ac3", + "LabelConfigureServer": "Emby\u8a2d\u5b9a", + "LabelRestartServer": "\u91cd\u65b0\u555f\u52d5\u4f3a\u670d\u5668", "CategorySync": "Sync", "CategoryUser": "User", "CategorySystem": "System", @@ -59,7 +59,7 @@ "ViewTypeMusicArtists": "Artists", "ViewTypeBoxSets": "Collections", "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", + "ViewTypeLiveTV": "\u96fb\u8996", "ViewTypeLiveTvNowPlaying": "Now Airing", "ViewTypeLatestGames": "Latest Games", "ViewTypeRecentlyPlayedGames": "Recently Played", From b63dd2e9ae4f71d6e7ac09c72675294940705b98 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 15:03:19 -0400 Subject: [PATCH 118/852] update upcoming --- MediaBrowser.Api/TvShowsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 3c32232ac..cd95d9f10 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -291,7 +291,7 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var minPremiereDate = DateTime.Now.Date.ToUniversalTime(); + var minPremiereDate = DateTime.Now.Date.ToUniversalTime().AddDays(-1); var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId }; From 2ec76f8a16aa90b1f98bfc3e768084e7edcb130a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 15:07:40 -0400 Subject: [PATCH 119/852] 3.0.5938 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 17c735fe8..a40d0d15b 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5937")] +[assembly: AssemblyVersion("3.0.5938")] From 007f4e193af99036b250a8323f92b753a9b74797 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 15:25:16 -0400 Subject: [PATCH 120/852] fix merge conflict --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index b9bd3b88e..a40d0d15b 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5913")] +[assembly: AssemblyVersion("3.0.5938")] From b0839ffd2c10cb7a8ec0837f897db61ddd3a7c01 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 15:27:50 -0400 Subject: [PATCH 121/852] restore version --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index a40d0d15b..b9bd3b88e 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5938")] +[assembly: AssemblyVersion("3.0.5913")] From 0688be857eb3645260d4ca8aa0a0792f93497e58 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 16 Apr 2016 15:49:26 -0400 Subject: [PATCH 122/852] update people validator --- .../Library/Validators/PeopleValidator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs index 5c43f2e13..500a5ad3d 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators validIds.Add(item.Id); var hasMetdata = !string.IsNullOrWhiteSpace(item.Overview); - var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 30; + var performFullRefresh = !hasMetdata && (DateTime.UtcNow - item.DateLastRefreshed).TotalDays >= 14; var defaultMetadataRefreshMode = performFullRefresh ? MetadataRefreshMode.FullRefresh From 23e3243a733c3ed18190758d9403d6da213378f6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 00:07:06 -0400 Subject: [PATCH 123/852] update inherited tags --- .../Persistence/SqliteItemRepository.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 212be2849..746321e70 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 62; + private const int LatestSchemaVersion = 63; /// /// Initializes a new instance of the class. @@ -760,7 +760,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); var trailer = item as Trailer; - if (trailer != null) + if (trailer != null && trailer.TrailerTypes.Count > 0) { _saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); } @@ -1962,7 +1962,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var index = 0; foreach (var type in query.ExcludeTrailerTypes) { - clauses.Add("TrailerTypes not like @TrailerTypes" + index); + clauses.Add("(TrailerTypes is null OR TrailerTypes not like @TrailerTypes" + index + ")"); cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; index++; } @@ -2186,7 +2186,7 @@ namespace MediaBrowser.Server.Implementations.Persistence var excludeTagIndex = 0; foreach (var excludeTag in query.ExcludeTags) { - whereClauses.Add("Tags not like @excludeTag" + excludeTagIndex); + whereClauses.Add("(Tags is null OR Tags not like @excludeTag" + excludeTagIndex + ")"); cmd.Parameters.Add(cmd, "@excludeTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; excludeTagIndex++; } @@ -2194,7 +2194,7 @@ namespace MediaBrowser.Server.Implementations.Persistence excludeTagIndex = 0; foreach (var excludeTag in query.ExcludeInheritedTags) { - whereClauses.Add("InheritedTags not like @excludeInheritedTag" + excludeTagIndex); + whereClauses.Add("(InheritedTags is null OR InheritedTags not like @excludeInheritedTag" + excludeTagIndex +")"); cmd.Parameters.Add(cmd, "@excludeInheritedTag" + excludeTagIndex, DbType.String).Value = "%" + excludeTag + "%"; excludeTagIndex++; } From ab4d226684541edb3975a327c691be42d163e47c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 11:38:10 -0400 Subject: [PATCH 124/852] 3.0.5939 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index a40d0d15b..cd7b4944e 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5938")] +[assembly: AssemblyVersion("3.0.5939")] From 565b3350a125cf49cd288542bf28188ef906dd10 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 16:57:57 -0400 Subject: [PATCH 125/852] update version --- .../LiveTv/EmbyTV/DirectRecorder.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index d33b2c51d..3c7ee55b7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { onStarted(); - _logger.Info("Copying recording stream to file stream"); + _logger.Info("Copying recording stream to file {0}", targetFile); var durationToken = new CancellationTokenSource(duration); var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; @@ -48,6 +48,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, linkedToken).ConfigureAwait(false); } } + + _logger.Info("Recording completed to file {0}", targetFile); } } } From 8b163221f700e717dfacbbde0ba110f098319857 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 16:59:20 -0400 Subject: [PATCH 126/852] fix merge conflict --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index b9bd3b88e..cd7b4944e 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5913")] +[assembly: AssemblyVersion("3.0.5939")] From fd042e230d5b460698ecaf0a83434957d02132b4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 17:00:18 -0400 Subject: [PATCH 127/852] fix version --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index cd7b4944e..b9bd3b88e 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5939")] +[assembly: AssemblyVersion("3.0.5913")] From 48ffa74da8ff332fff26a959e05e701cee9c0c3d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 17:07:38 -0400 Subject: [PATCH 128/852] 3.0.5930 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index b9bd3b88e..6785f5f0d 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5913")] +[assembly: AssemblyVersion("3.0.5930")] From 2b4dece54afbe8dff04b18ef454abd60af0ab826 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 23:50:44 -0400 Subject: [PATCH 129/852] record nal length size --- .../Playback/Hls/DynamicHlsService.cs | 3 +- .../Playback/Hls/VideoHlsService.cs | 5 +++ .../Playback/Progressive/VideoService.cs | 4 +-- .../Encoder/VideoEncoder.cs | 4 +-- .../Probing/ProbeResultNormalizer.cs | 3 +- MediaBrowser.Model/Entities/MediaStream.cs | 4 ++- .../Persistence/MediaStreamColumns.cs | 32 +++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 11 +++++-- 8 files changed, 57 insertions(+), 9 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 65e236525..fa8f0c009 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -828,8 +828,9 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 5f427146e..5709ca15a 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -87,6 +87,11 @@ namespace MediaBrowser.Api.Playback.Hls if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { // if h264_mp4toannexb is ever added, do not use it for live tv + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); + args += " -bsf:v h264_mp4toannexb"; + } return args; } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index b0d87c975..6054a245b 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -139,9 +139,9 @@ namespace MediaBrowser.Api.Playback.Progressive if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase))) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 41bfb3b96..3a0526f43 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -73,9 +73,9 @@ namespace MediaBrowser.MediaEncoding.Encoder if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) || isOutputMkv)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 6ec9e6435..38528d845 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -407,7 +407,8 @@ namespace MediaBrowser.MediaEncoding.Probing Profile = streamInfo.profile, Level = streamInfo.level, Index = streamInfo.index, - PixelFormat = streamInfo.pix_fmt + PixelFormat = streamInfo.pix_fmt, + NalLengthSize = streamInfo.nal_length_size }; // Filter out junk diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index bdc043e9a..fa7a51291 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -33,7 +33,9 @@ namespace MediaBrowser.Model.Entities /// /// The comment. public string Comment { get; set; } - + + public string NalLengthSize { get; set; } + /// /// Gets or sets a value indicating whether this instance is interlaced. /// diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index 211c77107..518659930 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -26,6 +26,38 @@ namespace MediaBrowser.Server.Implementations.Persistence AddRefFramesCommand(); AddCodecTagColumn(); AddCommentColumn(); + AddNalColumn(); + } + + private void AddNalColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "NalLengthSize", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column NalLengthSize TEXT"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); } private void AddCommentColumn() diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 746321e70..590279db4 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -391,7 +391,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "RefFrames", "IsCabac", "CodecTag", - "Comment" + "Comment", + "NalLengthSize" }; /// @@ -2893,6 +2894,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; + _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); @@ -3053,6 +3055,11 @@ namespace MediaBrowser.Server.Implementations.Persistence item.Comment = reader.GetString(27); } + if (!reader.IsDBNull(28)) + { + item.NalLengthSize = reader.GetString(28); + } + return item; } From 169554ccc4087e36f63aab8e929a25b306570ac1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 00:25:12 -0400 Subject: [PATCH 130/852] finish removing cabac --- .../Persistence/MediaStreamColumns.cs | 32 ------------------- .../Persistence/SqliteItemRepository.cs | 18 ++++------- 2 files changed, 7 insertions(+), 43 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index 518659930..debcd054f 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -21,7 +21,6 @@ namespace MediaBrowser.Server.Implementations.Persistence AddPixelFormatColumnCommand(); AddBitDepthCommand(); AddIsAnamorphicColumn(); - AddIsCabacColumn(); AddKeyFramesColumn(); AddRefFramesCommand(); AddCodecTagColumn(); @@ -215,37 +214,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(new[] { builder.ToString() }, _logger); } - private void AddIsCabacColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "IsCabac", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column IsCabac BIT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - private void AddKeyFramesColumn() { using (var cmd = _connection.CreateCommand()) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 590279db4..fb655c9cb 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -389,7 +389,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "BitDepth", "IsAnamorphic", "RefFrames", - "IsCabac", "CodecTag", "Comment", "NalLengthSize" @@ -2890,7 +2889,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - _saveStreamCommand.GetParameter(index++).Value = null; _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; @@ -3043,21 +3041,19 @@ namespace MediaBrowser.Server.Implementations.Persistence item.RefFrames = reader.GetInt32(24); } - // cabac no longer used + if (!reader.IsDBNull(25)) + { + item.CodecTag = reader.GetString(25); + } if (!reader.IsDBNull(26)) { - item.CodecTag = reader.GetString(26); + item.Comment = reader.GetString(26); } if (!reader.IsDBNull(27)) { - item.Comment = reader.GetString(27); - } - - if (!reader.IsDBNull(28)) - { - item.NalLengthSize = reader.GetString(28); + item.NalLengthSize = reader.GetString(27); } return item; From 916b148274e2156cf22892f82118b986da66236a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 00:25:43 -0400 Subject: [PATCH 131/852] don't use omdb for missing episodes --- MediaBrowser.Controller/Entities/TV/Episode.cs | 2 ++ MediaBrowser.Controller/Providers/EpisodeInfo.cs | 3 +++ MediaBrowser.Providers/Manager/MetadataService.cs | 5 +++++ MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs | 8 +++++++- .../TV/TheMovieDb/MovieDbEpisodeProvider.cs | 6 ++++++ 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index ec65221bc..e1a91086b 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -287,7 +287,9 @@ namespace MediaBrowser.Controller.Entities.TV id.AnimeSeriesIndex = series.AnimeSeriesIndex; } + id.IsMissingEpisode = IsMissingEpisode; id.IndexNumberEnd = IndexNumberEnd; + id.IsVirtualUnaired = IsVirtualUnaired; return id; } diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs index 28abd636a..b879040f8 100644 --- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs +++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs @@ -10,6 +10,9 @@ namespace MediaBrowser.Controller.Providers public int? IndexNumberEnd { get; set; } public int? AnimeSeriesIndex { get; set; } + public bool IsMissingEpisode { get; set; } + public bool IsVirtualUnaired { get; set; } + public EpisodeInfo() { SeriesProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 3d584e858..eeec4ea56 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -310,6 +310,11 @@ namespace MediaBrowser.Providers.Manager return true; } + if (!(item is Audio) && !(item is Video)) + { + return true; + } + return false; } diff --git a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs index 785efc3b6..5da1fcf27 100644 --- a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.TV { private readonly IJsonSerializer _jsonSerializer; private readonly IHttpClient _httpClient; - private OmdbItemProvider _itemProvider; + private readonly OmdbItemProvider _itemProvider; public OmdbEpisodeProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger, ILibraryManager libraryManager) { @@ -41,6 +41,12 @@ namespace MediaBrowser.Providers.TV Item = new Episode() }; + // Allowing this will dramatically increase scan times + if (info.IsMissingEpisode || info.IsVirtualUnaired) + { + return result; + } + var imdbId = info.GetProviderId(MetadataProviders.Imdb); if (string.IsNullOrWhiteSpace(imdbId)) { diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs index 42254f360..9bab3d380 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs @@ -64,6 +64,12 @@ namespace MediaBrowser.Providers.TV { var result = new MetadataResult(); + // Allowing this will dramatically increase scan times + if (info.IsMissingEpisode || info.IsVirtualUnaired) + { + return result; + } + string seriesTmdbId; info.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out seriesTmdbId); From 1a69dee2e64c6a341cec09008670c7b7ebe3341b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 01:26:34 -0400 Subject: [PATCH 132/852] update version --- SharedVersion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 6785f5f0d..6b1c9e6bb 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -//[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5930")] +[assembly: AssemblyVersion("3.0.*")] +//[assembly: AssemblyVersion("3.0.5930")] From 052889130377eeb1ebcb1ea5aff3f0e192dd11c4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 01:58:08 -0400 Subject: [PATCH 133/852] update slideshow --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index f7b550a13..ad714c6ca 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -101,6 +101,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -110,9 +113,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From 0ebb82dc57fefcdf765855e3fda0dd0f90c43f33 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 13:43:00 -0400 Subject: [PATCH 134/852] update NAL usage --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 2 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 2 +- MediaBrowser.Api/Playback/Progressive/VideoService.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 2 +- .../LiveTv/LiveTvManager.cs | 9 ++++++++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 9 ++++++++- 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index fa8f0c009..bc155ff45 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -828,7 +828,7 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 5709ca15a..87b1c4248 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Api.Playback.Hls if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { // if h264_mp4toannexb is ever added, do not use it for live tv - if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 6054a245b..3319fbaec 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 3a0526f43..b8efedf09 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index d40f2a141..ab2b59d48 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -511,8 +511,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (!(service is EmbyTV.EmbyTV)) { // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says - mediaSource.SupportsDirectStream = true; + mediaSource.SupportsDirectStream = false; mediaSource.SupportsTranscoding = true; + foreach (var stream in mediaSource.MediaStreams) + { + if (stream.Type == MediaStreamType.Video && string.IsNullOrWhiteSpace(stream.NalLengthSize)) + { + stream.NalLengthSize = "0"; + } + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 4c140602d..469767c65 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -317,6 +317,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoCodec = "mpeg2video"; } + string nal = null; + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + nal = "0"; + } + var url = GetApiUrl(info, true) + "/auto/v" + channelId; if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) @@ -339,7 +345,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Codec = videoCodec, Width = width, Height = height, - BitRate = videoBitrate + BitRate = videoBitrate, + NalLengthSize = nal }, new MediaStream From 034ce317385fadba4d742fd6f96895d8e7179775 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 14:01:50 -0400 Subject: [PATCH 135/852] deprecate importCss --- MediaBrowser.Api/BrandingService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/MediaBrowser.Api/BrandingService.cs b/MediaBrowser.Api/BrandingService.cs index c900e4d06..e991565ad 100644 --- a/MediaBrowser.Api/BrandingService.cs +++ b/MediaBrowser.Api/BrandingService.cs @@ -10,6 +10,7 @@ namespace MediaBrowser.Api } [Route("/Branding/Css", "GET", Summary = "Gets custom css")] + [Route("/Branding/Css.css", "GET", Summary = "Gets custom css")] public class GetBrandingCss { } From 636f4b7c5c6e677d92727b43ade3b51c5e768af9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 14:57:19 -0400 Subject: [PATCH 136/852] 3.0.5940 --- SharedVersion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 6b1c9e6bb..5102a813a 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("3.0.*")] -//[assembly: AssemblyVersion("3.0.5930")] +//[assembly: AssemblyVersion("3.0.*")] +[assembly: AssemblyVersion("3.0.5940")] From 5bdfe2b44e3620821d3fe38eb5be30c6d0585020 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 16:14:27 -0400 Subject: [PATCH 137/852] update package --- MediaBrowser.WebDashboard/Api/DashboardService.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.WebDashboard/Api/DashboardService.cs b/MediaBrowser.WebDashboard/Api/DashboardService.cs index 3a69c9666..376978790 100644 --- a/MediaBrowser.WebDashboard/Api/DashboardService.cs +++ b/MediaBrowser.WebDashboard/Api/DashboardService.cs @@ -346,7 +346,9 @@ namespace MediaBrowser.WebDashboard.Api } _fileSystem.DeleteDirectory(Path.Combine(bowerPath, "jquery", "src"), true); - + _fileSystem.DeleteDirectory(Path.Combine(bowerPath, "fingerprintjs2", "flash"), true); + _fileSystem.DeleteDirectory(Path.Combine(bowerPath, "fingerprintjs2", "specs"), true); + DeleteCryptoFiles(Path.Combine(bowerPath, "cryptojslib", "components")); DeleteFoldersByName(Path.Combine(bowerPath, "jquery"), "src"); From 779b880f5ca8a5b767d1f74fe905d8aaafb4fc99 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 21:51:07 -0400 Subject: [PATCH 138/852] 3.0.5941 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 5102a813a..3deb1750c 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5940")] +[assembly: AssemblyVersion("3.0.5941")] From 57b5fa73eedbd588600755dc2937d530d3df1ccb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 23:14:45 -0400 Subject: [PATCH 139/852] pull content rating from tmdb for series --- .../TV/TheMovieDb/MovieDbSeriesProvider.cs | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs index 05b1ebc80..98580396d 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.TV { public class MovieDbSeriesProvider : IRemoteMetadataProvider, IHasOrder { - private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos"; + private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos,content_ratings"; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); internal static MovieDbSeriesProvider Current { get; private set; } @@ -168,7 +168,7 @@ namespace MediaBrowser.Providers.TV { cancellationToken.ThrowIfCancellationRequested(); - result.Item = await FetchMovieData(tmdbId, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); + result.Item = await FetchMovieData(tmdbId, info.MetadataLanguage, info.MetadataCountryCode, cancellationToken).ConfigureAwait(false); result.HasMetadata = result.Item != null; } @@ -176,7 +176,7 @@ namespace MediaBrowser.Providers.TV return result; } - private async Task FetchMovieData(string tmdbId, string language, CancellationToken cancellationToken) + private async Task FetchMovieData(string tmdbId, string language, string preferredCountryCode, CancellationToken cancellationToken) { string dataFilePath = null; RootObject seriesInfo = null; @@ -201,12 +201,12 @@ namespace MediaBrowser.Providers.TV var item = new Series(); - ProcessMainInfo(item, seriesInfo); + ProcessMainInfo(item, seriesInfo, preferredCountryCode); return item; } - private void ProcessMainInfo(Series series, RootObject seriesInfo) + private void ProcessMainInfo(Series series, RootObject seriesInfo, string preferredCountryCode) { series.Name = seriesInfo.name; series.SetProviderId(MetadataProviders.Tmdb, seriesInfo.id.ToString(_usCulture)); @@ -265,6 +265,26 @@ namespace MediaBrowser.Providers.TV series.SetProviderId(MetadataProviders.Tvdb, ids.tvdb_id.ToString(_usCulture)); } } + + var contentRatings = (seriesInfo.content_ratings ?? new ContentRatings()).results ?? new List(); + + var ourRelease = contentRatings.FirstOrDefault(c => string.Equals(c.iso_3166_1, preferredCountryCode, StringComparison.OrdinalIgnoreCase)); + var usRelease = contentRatings.FirstOrDefault(c => string.Equals(c.iso_3166_1, "US", StringComparison.OrdinalIgnoreCase)); + var minimumRelease = contentRatings.FirstOrDefault(); + + if (ourRelease != null) + { + series.OfficialRating = ourRelease.rating; + } + else if (usRelease != null) + { + series.OfficialRating = usRelease.rating; + } + else if (minimumRelease != null) + { + series.OfficialRating = minimumRelease.rating; + } + } internal static string GetSeriesDataPath(IApplicationPaths appPaths, string tmdbId) @@ -481,6 +501,7 @@ namespace MediaBrowser.Providers.TV public class Season { public string air_date { get; set; } + public int episode_count { get; set; } public int id { get; set; } public string poster_path { get; set; } public int season_number { get; set; } @@ -528,7 +549,6 @@ namespace MediaBrowser.Providers.TV public double aspect_ratio { get; set; } public string file_path { get; set; } public int height { get; set; } - public string id { get; set; } public string iso_639_1 { get; set; } public double vote_average { get; set; } public int vote_count { get; set; } @@ -560,6 +580,17 @@ namespace MediaBrowser.Providers.TV public List results { get; set; } } + public class ContentRating + { + public string iso_3166_1 { get; set; } + public string rating { get; set; } + } + + public class ContentRatings + { + public List results { get; set; } + } + public class RootObject { public string backdrop_path { get; set; } @@ -590,6 +621,7 @@ namespace MediaBrowser.Providers.TV public Keywords keywords { get; set; } public ExternalIds external_ids { get; set; } public Videos videos { get; set; } + public ContentRatings content_ratings { get; set; } } public int Order From 14548735f33ab32c2eab42338aef4cb09e7d5fac Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 19 Apr 2016 22:28:24 -0400 Subject: [PATCH 140/852] fix identify by imdb id --- MediaBrowser.Providers/Manager/ProviderManager.cs | 1 - MediaBrowser.Providers/Omdb/OmdbItemProvider.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 06db8a237..3199ed12b 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -762,7 +762,6 @@ namespace MediaBrowser.Providers.Manager var resultList = new List(); var foundProviderIds = new Dictionary, RemoteSearchResult>(); - var foundTitleYearStrings = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var provider in providers) { diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 894750c81..1b8ecd521 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -74,7 +74,6 @@ namespace MediaBrowser.Providers.Omdb episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId); } - var name = searchInfo.Name; var year = searchInfo.Year; @@ -107,6 +106,7 @@ namespace MediaBrowser.Providers.Omdb else { url += "&i=" + imdbId; + isSearch = false; } if (type == "episode") From 8d230261a38bcfd411254be423815e6252e45fa6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 23:50:44 -0400 Subject: [PATCH 141/852] record nal length size --- .../Playback/Hls/DynamicHlsService.cs | 3 +- .../Playback/Hls/VideoHlsService.cs | 5 +++ .../Playback/Progressive/VideoService.cs | 4 +-- .../Encoder/VideoEncoder.cs | 4 +-- .../Probing/ProbeResultNormalizer.cs | 3 +- MediaBrowser.Model/Entities/MediaStream.cs | 4 ++- .../Persistence/MediaStreamColumns.cs | 32 +++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 11 +++++-- 8 files changed, 57 insertions(+), 9 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 65e236525..fa8f0c009 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -828,8 +828,9 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 5f427146e..5709ca15a 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -87,6 +87,11 @@ namespace MediaBrowser.Api.Playback.Hls if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { // if h264_mp4toannexb is ever added, do not use it for live tv + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); + args += " -bsf:v h264_mp4toannexb"; + } return args; } diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index b0d87c975..6054a245b 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -139,9 +139,9 @@ namespace MediaBrowser.Api.Playback.Progressive if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase))) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 41bfb3b96..3a0526f43 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -73,9 +73,9 @@ namespace MediaBrowser.MediaEncoding.Encoder if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && - (string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) || isOutputMkv)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) { + Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 6ec9e6435..38528d845 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -407,7 +407,8 @@ namespace MediaBrowser.MediaEncoding.Probing Profile = streamInfo.profile, Level = streamInfo.level, Index = streamInfo.index, - PixelFormat = streamInfo.pix_fmt + PixelFormat = streamInfo.pix_fmt, + NalLengthSize = streamInfo.nal_length_size }; // Filter out junk diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index bdc043e9a..fa7a51291 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -33,7 +33,9 @@ namespace MediaBrowser.Model.Entities /// /// The comment. public string Comment { get; set; } - + + public string NalLengthSize { get; set; } + /// /// Gets or sets a value indicating whether this instance is interlaced. /// diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index 211c77107..518659930 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -26,6 +26,38 @@ namespace MediaBrowser.Server.Implementations.Persistence AddRefFramesCommand(); AddCodecTagColumn(); AddCommentColumn(); + AddNalColumn(); + } + + private void AddNalColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "NalLengthSize", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column NalLengthSize TEXT"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); } private void AddCommentColumn() diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 746321e70..590279db4 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -391,7 +391,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "RefFrames", "IsCabac", "CodecTag", - "Comment" + "Comment", + "NalLengthSize" }; /// @@ -2893,6 +2894,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; + _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); @@ -3053,6 +3055,11 @@ namespace MediaBrowser.Server.Implementations.Persistence item.Comment = reader.GetString(27); } + if (!reader.IsDBNull(28)) + { + item.NalLengthSize = reader.GetString(28); + } + return item; } From d12bc8596a7d5df6033b84a3ce2c47a9d4376605 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 00:25:12 -0400 Subject: [PATCH 142/852] finish removing cabac --- .../Persistence/MediaStreamColumns.cs | 32 ------------------- .../Persistence/SqliteItemRepository.cs | 18 ++++------- 2 files changed, 7 insertions(+), 43 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index 518659930..debcd054f 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -21,7 +21,6 @@ namespace MediaBrowser.Server.Implementations.Persistence AddPixelFormatColumnCommand(); AddBitDepthCommand(); AddIsAnamorphicColumn(); - AddIsCabacColumn(); AddKeyFramesColumn(); AddRefFramesCommand(); AddCodecTagColumn(); @@ -215,37 +214,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.RunQueries(new[] { builder.ToString() }, _logger); } - private void AddIsCabacColumn() - { - using (var cmd = _connection.CreateCommand()) - { - cmd.CommandText = "PRAGMA table_info(mediastreams)"; - - using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) - { - while (reader.Read()) - { - if (!reader.IsDBNull(1)) - { - var name = reader.GetString(1); - - if (string.Equals(name, "IsCabac", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - } - - var builder = new StringBuilder(); - - builder.AppendLine("alter table mediastreams"); - builder.AppendLine("add column IsCabac BIT NULL"); - - _connection.RunQueries(new[] { builder.ToString() }, _logger); - } - private void AddKeyFramesColumn() { using (var cmd = _connection.CreateCommand()) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 590279db4..fb655c9cb 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, IsCabac BIT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -389,7 +389,6 @@ namespace MediaBrowser.Server.Implementations.Persistence "BitDepth", "IsAnamorphic", "RefFrames", - "IsCabac", "CodecTag", "Comment", "NalLengthSize" @@ -2890,7 +2889,6 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.BitDepth; _saveStreamCommand.GetParameter(index++).Value = stream.IsAnamorphic; _saveStreamCommand.GetParameter(index++).Value = stream.RefFrames; - _saveStreamCommand.GetParameter(index++).Value = null; _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; @@ -3043,21 +3041,19 @@ namespace MediaBrowser.Server.Implementations.Persistence item.RefFrames = reader.GetInt32(24); } - // cabac no longer used + if (!reader.IsDBNull(25)) + { + item.CodecTag = reader.GetString(25); + } if (!reader.IsDBNull(26)) { - item.CodecTag = reader.GetString(26); + item.Comment = reader.GetString(26); } if (!reader.IsDBNull(27)) { - item.Comment = reader.GetString(27); - } - - if (!reader.IsDBNull(28)) - { - item.NalLengthSize = reader.GetString(28); + item.NalLengthSize = reader.GetString(27); } return item; From d9afd21ef5945a83b86dc01a878be6044a5f5c96 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 00:25:43 -0400 Subject: [PATCH 143/852] don't use omdb for missing episodes --- MediaBrowser.Controller/Entities/TV/Episode.cs | 2 ++ MediaBrowser.Controller/Providers/EpisodeInfo.cs | 3 +++ MediaBrowser.Providers/Manager/MetadataService.cs | 5 +++++ MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs | 8 +++++++- .../TV/TheMovieDb/MovieDbEpisodeProvider.cs | 6 ++++++ 5 files changed, 23 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index ec65221bc..e1a91086b 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -287,7 +287,9 @@ namespace MediaBrowser.Controller.Entities.TV id.AnimeSeriesIndex = series.AnimeSeriesIndex; } + id.IsMissingEpisode = IsMissingEpisode; id.IndexNumberEnd = IndexNumberEnd; + id.IsVirtualUnaired = IsVirtualUnaired; return id; } diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs index 28abd636a..b879040f8 100644 --- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs +++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs @@ -10,6 +10,9 @@ namespace MediaBrowser.Controller.Providers public int? IndexNumberEnd { get; set; } public int? AnimeSeriesIndex { get; set; } + public bool IsMissingEpisode { get; set; } + public bool IsVirtualUnaired { get; set; } + public EpisodeInfo() { SeriesProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 3d584e858..eeec4ea56 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -310,6 +310,11 @@ namespace MediaBrowser.Providers.Manager return true; } + if (!(item is Audio) && !(item is Video)) + { + return true; + } + return false; } diff --git a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs index 785efc3b6..5da1fcf27 100644 --- a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.TV { private readonly IJsonSerializer _jsonSerializer; private readonly IHttpClient _httpClient; - private OmdbItemProvider _itemProvider; + private readonly OmdbItemProvider _itemProvider; public OmdbEpisodeProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogger logger, ILibraryManager libraryManager) { @@ -41,6 +41,12 @@ namespace MediaBrowser.Providers.TV Item = new Episode() }; + // Allowing this will dramatically increase scan times + if (info.IsMissingEpisode || info.IsVirtualUnaired) + { + return result; + } + var imdbId = info.GetProviderId(MetadataProviders.Imdb); if (string.IsNullOrWhiteSpace(imdbId)) { diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs index 42254f360..9bab3d380 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs @@ -64,6 +64,12 @@ namespace MediaBrowser.Providers.TV { var result = new MetadataResult(); + // Allowing this will dramatically increase scan times + if (info.IsMissingEpisode || info.IsVirtualUnaired) + { + return result; + } + string seriesTmdbId; info.SeriesProviderIds.TryGetValue(MetadataProviders.Tmdb.ToString(), out seriesTmdbId); From 98cfbd99ad1fe5f3865ad624791ce69f31e68c3b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 13:43:00 -0400 Subject: [PATCH 144/852] update NAL usage --- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 2 +- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 2 +- MediaBrowser.Api/Playback/Progressive/VideoService.cs | 2 +- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 2 +- .../LiveTv/LiveTvManager.cs | 9 ++++++++- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 9 ++++++++- 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index fa8f0c009..bc155ff45 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -828,7 +828,7 @@ namespace MediaBrowser.Api.Playback.Hls // See if we can save come cpu cycles by avoiding encoding if (string.Equals(codec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 5709ca15a..87b1c4248 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -87,7 +87,7 @@ namespace MediaBrowser.Api.Playback.Hls if (codec.Equals("copy", StringComparison.OrdinalIgnoreCase)) { // if h264_mp4toannexb is ever added, do not use it for live tv - if (state.VideoStream != null && IsH264(state.VideoStream) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 6054a245b..3319fbaec 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -139,7 +139,7 @@ namespace MediaBrowser.Api.Playback.Progressive if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index 3a0526f43..b8efedf09 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (string.Equals(videoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(state.VideoStream.NalLengthSize)) + if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index d40f2a141..ab2b59d48 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -511,8 +511,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (!(service is EmbyTV.EmbyTV)) { // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says - mediaSource.SupportsDirectStream = true; + mediaSource.SupportsDirectStream = false; mediaSource.SupportsTranscoding = true; + foreach (var stream in mediaSource.MediaStreams) + { + if (stream.Type == MediaStreamType.Video && string.IsNullOrWhiteSpace(stream.NalLengthSize)) + { + stream.NalLengthSize = "0"; + } + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 4c140602d..469767c65 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -317,6 +317,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun videoCodec = "mpeg2video"; } + string nal = null; + if (string.Equals(videoCodec, "h264", StringComparison.OrdinalIgnoreCase)) + { + nal = "0"; + } + var url = GetApiUrl(info, true) + "/auto/v" + channelId; if (!string.IsNullOrWhiteSpace(profile) && !string.Equals(profile, "native", StringComparison.OrdinalIgnoreCase)) @@ -339,7 +345,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun Codec = videoCodec, Width = width, Height = height, - BitRate = videoBitrate + BitRate = videoBitrate, + NalLengthSize = nal }, new MediaStream From 316d8d3125b2152d9b8fe7224b37de2d21fb577e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 19 Apr 2016 22:28:24 -0400 Subject: [PATCH 145/852] fix identify by imdb id --- MediaBrowser.Providers/Manager/ProviderManager.cs | 1 - MediaBrowser.Providers/Omdb/OmdbItemProvider.cs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 06db8a237..3199ed12b 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -762,7 +762,6 @@ namespace MediaBrowser.Providers.Manager var resultList = new List(); var foundProviderIds = new Dictionary, RemoteSearchResult>(); - var foundTitleYearStrings = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var provider in providers) { diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 894750c81..1b8ecd521 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -74,7 +74,6 @@ namespace MediaBrowser.Providers.Omdb episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId); } - var name = searchInfo.Name; var year = searchInfo.Year; @@ -107,6 +106,7 @@ namespace MediaBrowser.Providers.Omdb else { url += "&i=" + imdbId; + isSearch = false; } if (type == "episode") From 9fa33fc2204807206a71348f50aaf0739fa9a919 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 19 Apr 2016 23:00:18 -0400 Subject: [PATCH 146/852] switch lock from image to icon --- 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 ad714c6ca..f84fe058a 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -781,9 +781,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From ace1ad778e319319eb0f3dfbd02979987c2d946b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 00:30:06 -0400 Subject: [PATCH 147/852] update xml parsing logging --- .../Providers/BaseItemXmlParser.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index f9060d184..1014fc2ee 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -61,16 +61,7 @@ namespace MediaBrowser.Controller.Providers }; //Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken); - - try - { - Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); - } - catch - { - Logger.Error("Error parsing xml file {0}", metadataFile); - throw; - } + Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); } /// From 992ca4c78a2bf44e1365d648989f6d028cdb9e8a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 01:21:40 -0400 Subject: [PATCH 148/852] add OriginalTitle to metadata editor --- MediaBrowser.Api/ItemUpdateService.cs | 6 ++++++ MediaBrowser.Controller/Entities/BaseItem.cs | 2 ++ MediaBrowser.Controller/Entities/Movies/Movie.cs | 2 -- MediaBrowser.Controller/Entities/TV/Series.cs | 2 -- MediaBrowser.Controller/Entities/Trailer.cs | 2 +- MediaBrowser.Model/Dto/BaseItemDto.cs | 2 ++ MediaBrowser.Model/Querying/ItemFields.cs | 2 ++ MediaBrowser.Providers/Manager/ProviderUtils.cs | 9 +++++++++ MediaBrowser.Server.Implementations/Dto/DtoService.cs | 5 +++++ 9 files changed, 27 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index f37874774..5bb4ed5f0 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -247,6 +247,12 @@ namespace MediaBrowser.Api hasBudget.Revenue = request.Revenue; } + var hasOriginalTitle = item as IHasOriginalTitle; + if (hasOriginalTitle != null) + { + hasOriginalTitle.OriginalTitle = hasOriginalTitle.OriginalTitle; + } + var hasCriticRating = item as IHasCriticRating; if (hasCriticRating != null) { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 04371c13b..959334d78 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -125,6 +125,8 @@ namespace MediaBrowser.Controller.Entities } } + public string OriginalTitle { get; set; } + /// /// Gets or sets the id. /// diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 4d2ca9ffe..6004992cc 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -18,8 +18,6 @@ namespace MediaBrowser.Controller.Entities.Movies { public List SpecialFeatureIds { get; set; } - public string OriginalTitle { get; set; } - public List ThemeSongIds { get; set; } public List ThemeVideoIds { get; set; } public List ProductionLocations { get; set; } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 9eeb89a1f..7eabff072 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -19,8 +19,6 @@ namespace MediaBrowser.Controller.Entities.TV { public List SpecialFeatureIds { get; set; } - public string OriginalTitle { get; set; } - public int? AnimeSeriesIndex { get; set; } public Series() diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index c3e24090c..fe8bf3ed3 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Controller.Entities /// /// Class Trailer /// - public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo + public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo { public List ProductionLocations { get; set; } diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 7928d0bf9..49ec9f8ef 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -26,6 +26,8 @@ namespace MediaBrowser.Model.Dto /// The name. public string Name { get; set; } + public string OriginalTitle { get; set; } + /// /// Gets or sets the server identifier. /// diff --git a/MediaBrowser.Model/Querying/ItemFields.cs b/MediaBrowser.Model/Querying/ItemFields.cs index 1540f178a..cea638a39 100644 --- a/MediaBrowser.Model/Querying/ItemFields.cs +++ b/MediaBrowser.Model/Querying/ItemFields.cs @@ -130,6 +130,8 @@ /// Metascore, + OriginalTitle, + /// /// The item overview /// diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs index 278d8ed71..59a2da460 100644 --- a/MediaBrowser.Providers/Manager/ProviderUtils.cs +++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs @@ -40,6 +40,15 @@ namespace MediaBrowser.Providers.Manager } } + if (replaceData || string.IsNullOrEmpty(target.OriginalTitle)) + { + // Safeguard against incoming data having an emtpy name + if (!string.IsNullOrWhiteSpace(source.OriginalTitle)) + { + target.OriginalTitle = source.OriginalTitle; + } + } + if (replaceData || !target.CommunityRating.HasValue) { target.CommunityRating = source.CommunityRating; diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 50ae19580..2ee55edb9 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1126,6 +1126,11 @@ namespace MediaBrowser.Server.Implementations.Dto dto.Overview = item.Overview; } + if (fields.Contains(ItemFields.OriginalTitle)) + { + dto.OriginalTitle = item.OriginalTitle; + } + if (fields.Contains(ItemFields.ShortOverview)) { var hasShortOverview = item as IHasShortOverview; From fe9ee3d891c36a2678c8013ff04e9b91aa6cf390 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 01:32:25 -0400 Subject: [PATCH 149/852] remove duplicate originaltitle --- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index ba8a3bdf5..e37b83f4b 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -479,7 +479,6 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteElementString("dateadded", item.DateCreated.ToLocalTime().ToString(DateAddedFormat)); writer.WriteElementString("title", item.Name ?? string.Empty); - writer.WriteElementString("originaltitle", item.Name ?? string.Empty); var hasOriginalTitle = item as IHasOriginalTitle; if (hasOriginalTitle != null) From 389046fb3fc36ada6f9ad0cf4c2d2205ae76666c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 00:30:06 -0400 Subject: [PATCH 150/852] update xml parsing logging --- .../Providers/BaseItemXmlParser.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index f9060d184..1014fc2ee 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -61,16 +61,7 @@ namespace MediaBrowser.Controller.Providers }; //Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken); - - try - { - Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); - } - catch - { - Logger.Error("Error parsing xml file {0}", metadataFile); - throw; - } + Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); } /// From 55a4510fd386b7cfa4c46de0c26ae614f4fecd57 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 12:05:25 -0400 Subject: [PATCH 151/852] 3.0.5942 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 3deb1750c..ae69c74c7 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5941")] +[assembly: AssemblyVersion("3.0.5942")] From 8b6fc3f6a2b78386c251db9ae7b71a80d5e338d8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 12:18:33 -0400 Subject: [PATCH 152/852] 3.0.5931 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 6785f5f0d..113d73899 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5930")] +[assembly: AssemblyVersion("3.0.5931")] From a38086126fc08bc64e9c73a259334807614ec874 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 14:51:47 -0400 Subject: [PATCH 153/852] update hls playback --- .../Playback/BaseStreamingService.cs | 1 - .../Playback/Hls/BaseHlsService.cs | 5 ---- .../Playback/Hls/DynamicHlsService.cs | 26 +++++++++---------- .../Playback/Hls/VideoHlsService.cs | 1 - .../Playback/Progressive/VideoService.cs | 1 - MediaBrowser.Api/Playback/StreamRequest.cs | 2 -- MediaBrowser.Api/Playback/StreamState.cs | 14 +++++++++- .../Encoder/VideoEncoder.cs | 1 - MediaBrowser.Model/Dlna/StreamBuilder.cs | 1 - MediaBrowser.Model/Dlna/StreamInfo.cs | 4 +-- MediaBrowser.Model/Dlna/TranscodingProfile.cs | 3 --- 11 files changed, 26 insertions(+), 33 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 901554973..4b05a5ee6 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -2058,7 +2058,6 @@ namespace MediaBrowser.Api.Playback if (state.VideoRequest != null) { state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; - state.VideoRequest.ForceLiveStream = transcodingProfile.ForceLiveStream; } } } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index cb344690c..49d3c37ea 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -282,11 +282,6 @@ namespace MediaBrowser.Api.Playback.Hls { var isLiveStream = (state.RunTimeTicks ?? 0) == 0; - if (state.VideoRequest.ForceLiveStream) - { - return true; - } - return isLiveStream; } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index bc155ff45..7ed8a9490 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -504,11 +504,6 @@ namespace MediaBrowser.Api.Playback.Hls { var isLiveStream = (state.RunTimeTicks ?? 0) == 0; - if (state.VideoRequest.ForceLiveStream) - { - return true; - } - return isLiveStream; } @@ -830,7 +825,6 @@ namespace MediaBrowser.Api.Playback.Hls { if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } @@ -862,12 +856,17 @@ namespace MediaBrowser.Api.Playback.Hls args += " -flags -global_header -sc_threshold 0"; } + if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1) + { + args += " -copyts"; + } + return args; } private bool EnableCopyTs(StreamState state) { - return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; + return true; } protected override string GetCommandLineArguments(string outputPath, StreamState state, bool isEncoding) @@ -891,7 +890,7 @@ namespace MediaBrowser.Api.Playback.Hls //var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); - //return string.Format("{0} {11} {1}{10} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", + //return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", // inputModifier, // GetInputArgument(state), // threads, @@ -902,11 +901,10 @@ namespace MediaBrowser.Api.Playback.Hls // startNumberParam, // outputPath, // outputTsArg, - // slowSeekParam, // toTimeParam // ).Trim(); - return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"", + return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"", inputModifier, GetInputArgument(state), threads, @@ -946,10 +944,10 @@ namespace MediaBrowser.Api.Playback.Hls { var isLiveStream = IsLiveStream(state); - if (!isLiveStream) - { - return false; - } + //if (!isLiveStream && Request.QueryString["AllowCustomSegmenting"] != "true") + //{ + // return false; + //} return base.CanStreamCopyVideo(state); } diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 87b1c4248..8a14948d2 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -89,7 +89,6 @@ namespace MediaBrowser.Api.Playback.Hls // if h264_mp4toannexb is ever added, do not use it for live tv if (state.VideoStream != null && IsH264(state.VideoStream) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } return args; diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index 3319fbaec..be3995aeb 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -141,7 +141,6 @@ namespace MediaBrowser.Api.Playback.Progressive { if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 371dbbda2..14fdb1197 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -190,8 +190,6 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "CopyTimestamps", Description = "Whether or not to copy timestamps when transcoding with an offset. Defaults to false.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool CopyTimestamps { get; set; } - public bool ForceLiveStream { get; set; } - public VideoStreamRequest() { EnableAutoStreamCopy = true; diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs index ed8a27faf..061afed6d 100644 --- a/MediaBrowser.Api/Playback/StreamState.cs +++ b/MediaBrowser.Api/Playback/StreamState.cs @@ -69,7 +69,19 @@ namespace MediaBrowser.Api.Playback public List PlayableStreamFileNames { get; set; } - public int SegmentLength = 3; + public int SegmentLength + { + get + { + if (string.Equals(OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) + { + return 10; + } + + return 3; + } + } + public int HlsListSize { get diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index b8efedf09..3ab55168d 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -75,7 +75,6 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (state.VideoStream != null && IsH264(state.VideoStream) && string.Equals(state.Options.OutputContainer, "ts", StringComparison.OrdinalIgnoreCase) && !string.Equals(state.VideoStream.NalLengthSize, "0", StringComparison.OrdinalIgnoreCase)) { - Logger.Debug("Enabling h264_mp4toannexb due to nal_length_size of {0}", state.VideoStream.NalLengthSize); args += " -bsf:v h264_mp4toannexb"; } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 1e6b7c729..f44f89f22 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -443,7 +443,6 @@ namespace MediaBrowser.Model.Dlna playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; - playlistItem.ForceLiveStream = transcodingProfile.ForceLiveStream; playlistItem.SubProtocol = transcodingProfile.Protocol; playlistItem.AudioStreamIndex = audioStreamIndex; diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 644f732a7..a2867dcc9 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -31,7 +31,6 @@ namespace MediaBrowser.Model.Dlna public string VideoProfile { get; set; } public bool CopyTimestamps { get; set; } - public bool ForceLiveStream { get; set; } public string AudioCodec { get; set; } public int? AudioStreamIndex { get; set; } @@ -205,7 +204,7 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty)); list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty)); - if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls") && !item.ForceLiveStream) + if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls")) { list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } @@ -235,7 +234,6 @@ namespace MediaBrowser.Model.Dlna } list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString().ToLower())); - list.Add(new NameValuePair("ForceLiveStream", item.ForceLiveStream.ToString().ToLower())); list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); return list; diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs index bf6bf092f..e59ee6d63 100644 --- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs @@ -35,9 +35,6 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("context")] public EncodingContext Context { get; set; } - [XmlAttribute("forceLiveStream")] - public bool ForceLiveStream { get; set; } - public List GetAudioCodecs() { List list = new List(); From c59b4329f4e152be0d186f4db720333fb7b2c4b7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Apr 2016 00:04:57 -0400 Subject: [PATCH 154/852] restore ForceLiveStream param --- .../Playback/BaseStreamingService.cs | 1 + .../Playback/Hls/BaseHlsService.cs | 13 ++---- .../Playback/Hls/DynamicHlsService.cs | 45 +++++++++---------- MediaBrowser.Api/Playback/StreamRequest.cs | 2 + MediaBrowser.Model/Dlna/StreamBuilder.cs | 1 + MediaBrowser.Model/Dlna/StreamInfo.cs | 4 +- MediaBrowser.Model/Dlna/TranscodingProfile.cs | 5 ++- 7 files changed, 36 insertions(+), 35 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 4b05a5ee6..901554973 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -2058,6 +2058,7 @@ namespace MediaBrowser.Api.Playback if (state.VideoRequest != null) { state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; + state.VideoRequest.ForceLiveStream = transcodingProfile.ForceLiveStream; } } } diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 49d3c37ea..49f50735f 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -282,19 +282,12 @@ namespace MediaBrowser.Api.Playback.Hls { var isLiveStream = (state.RunTimeTicks ?? 0) == 0; - return isLiveStream; - } - - protected override bool CanStreamCopyAudio(StreamState state, List supportedAudioCodecs) - { - var isLiveStream = IsLiveStream(state); - - if (!isLiveStream) + if (state.VideoRequest.ForceLiveStream) { - return false; + return true; } - return base.CanStreamCopyAudio(state, supportedAudioCodecs); + return isLiveStream; } } } \ No newline at end of file diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 7ed8a9490..f857a43e4 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -500,13 +500,6 @@ namespace MediaBrowser.Api.Playback.Hls return ResultFactory.GetResult(playlistText, MimeTypes.GetMimeType("playlist.m3u8"), new Dictionary()); } - private bool IsLiveStream(StreamState state) - { - var isLiveStream = (state.RunTimeTicks ?? 0) == 0; - - return isLiveStream; - } - private string GetMasterPlaylistFileText(StreamState state, int totalBitrate) { var builder = new StringBuilder(); @@ -828,7 +821,7 @@ namespace MediaBrowser.Api.Playback.Hls args += " -bsf:v h264_mp4toannexb"; } - args += " -flags -global_header -sc_threshold 0"; + args += " -flags -global_header"; } else { @@ -853,7 +846,7 @@ namespace MediaBrowser.Api.Playback.Hls args += GetGraphicalSubtitleParam(state, codec); } - args += " -flags -global_header -sc_threshold 0"; + args += " -flags -global_header"; } if (EnableCopyTs(state) && args.IndexOf("-copyts", StringComparison.OrdinalIgnoreCase) == -1) @@ -866,6 +859,7 @@ namespace MediaBrowser.Api.Playback.Hls private bool EnableCopyTs(StreamState state) { + //return state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.VideoRequest.SubtitleMethod == SubtitleDeliveryMethod.Encode; return true; } @@ -888,21 +882,26 @@ namespace MediaBrowser.Api.Playback.Hls var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty; - //var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); + var enableGenericSegmenter = false; - //return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", - // inputModifier, - // GetInputArgument(state), - // threads, - // mapArgs, - // GetVideoArguments(state), - // GetAudioArguments(state), - // state.SegmentLength.ToString(UsCulture), - // startNumberParam, - // outputPath, - // outputTsArg, - // toTimeParam - // ).Trim(); + if (enableGenericSegmenter) + { + var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); + + return string.Format("{0} {10} {1} -map_metadata -1 -threads {2} {3} {4} {5} -f segment -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -segment_time {6} -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", + inputModifier, + GetInputArgument(state), + threads, + mapArgs, + GetVideoArguments(state), + GetAudioArguments(state), + state.SegmentLength.ToString(UsCulture), + startNumberParam, + outputPath, + outputTsArg, + toTimeParam + ).Trim(); + } return string.Format("{0}{11} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7} -start_number {8} -hls_list_size {9} -y \"{10}\"", inputModifier, diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 14fdb1197..371dbbda2 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -190,6 +190,8 @@ namespace MediaBrowser.Api.Playback [ApiMember(Name = "CopyTimestamps", Description = "Whether or not to copy timestamps when transcoding with an offset. Defaults to false.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool CopyTimestamps { get; set; } + public bool ForceLiveStream { get; set; } + public VideoStreamRequest() { EnableAutoStreamCopy = true; diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index f44f89f22..1e6b7c729 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -443,6 +443,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; + playlistItem.ForceLiveStream = transcodingProfile.ForceLiveStream; playlistItem.SubProtocol = transcodingProfile.Protocol; playlistItem.AudioStreamIndex = audioStreamIndex; diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index a2867dcc9..644f732a7 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -31,6 +31,7 @@ namespace MediaBrowser.Model.Dlna public string VideoProfile { get; set; } public bool CopyTimestamps { get; set; } + public bool ForceLiveStream { get; set; } public string AudioCodec { get; set; } public int? AudioStreamIndex { get; set; } @@ -204,7 +205,7 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty)); list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty)); - if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls")) + if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls") && !item.ForceLiveStream) { list.Add(new NameValuePair("StartTimeTicks", string.Empty)); } @@ -234,6 +235,7 @@ namespace MediaBrowser.Model.Dlna } list.Add(new NameValuePair("CopyTimestamps", item.CopyTimestamps.ToString().ToLower())); + list.Add(new NameValuePair("ForceLiveStream", item.ForceLiveStream.ToString().ToLower())); list.Add(new NameValuePair("SubtitleMethod", item.SubtitleStreamIndex.HasValue && item.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External ? item.SubtitleDeliveryMethod.ToString() : string.Empty)); return list; diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs index e59ee6d63..36c357926 100644 --- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("protocol")] public string Protocol { get; set; } - + [XmlAttribute("estimateContentLength")] public bool EstimateContentLength { get; set; } @@ -35,6 +35,9 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("context")] public EncodingContext Context { get; set; } + [XmlAttribute("forceLiveStream")] + public bool ForceLiveStream { get; set; } + public List GetAudioCodecs() { List list = new List(); From f3c3c74d84d81ada293ff10c2eabcd1be418f54f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Apr 2016 14:00:46 -0400 Subject: [PATCH 155/852] add probe property --- .../LiveTv/TunerHosts/BaseTunerHost.cs | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 02a8d6938..9bb5b4fd7 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -224,7 +224,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false); - //await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false); + if (EnableMediaProbing) + { + await AddMediaInfo(stream, false, resourcePool, cancellationToken).ConfigureAwait(false); + } + return new Tuple(stream, resourcePool); } catch (Exception ex) @@ -239,6 +243,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts throw new LiveTvConflictException(); } + protected virtual bool EnableMediaProbing + { + get { return false; } + } + protected async Task IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken) { try @@ -268,6 +277,25 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts return _semaphoreLocks.GetOrAdd(url, key => new SemaphoreSlim(1, 1)); } + private async Task AddMediaInfo(MediaSourceInfo mediaSource, bool isAudio, SemaphoreSlim resourcePool, CancellationToken cancellationToken) + { + await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await AddMediaInfoInternal(mediaSource, isAudio, cancellationToken).ConfigureAwait(false); + + // Leave the resource locked. it will be released upstream + } + catch (Exception) + { + // Release the resource if there's some kind of failure. + resourcePool.Release(); + + throw; + } + } + private async Task AddMediaInfoInternal(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken) { var originalRuntime = mediaSource.RunTimeTicks; From c94706d6eec63f705eb69ec87a4887f314986dc0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Apr 2016 12:12:20 -0400 Subject: [PATCH 156/852] update shutdown --- .../HttpServer/HttpListenerHost.cs | 17 +++++++++++++++++ .../ServerManager/ServerManager.cs | 19 +++++++++++++++++++ MediaBrowser.ServerApplication/MainStartup.cs | 5 +++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs index 25463b660..c5cb810e5 100644 --- a/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/MediaBrowser.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -179,6 +179,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer private void OnWebSocketConnecting(WebSocketConnectingEventArgs args) { + if (_disposed) + { + return; + } + if (WebSocketConnecting != null) { WebSocketConnecting(this, args); @@ -187,6 +192,11 @@ namespace MediaBrowser.Server.Implementations.HttpServer private void OnWebSocketConnected(WebSocketConnectEventArgs args) { + if (_disposed) + { + return; + } + if (WebSocketConnected != null) { WebSocketConnected(this, args); @@ -331,6 +341,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer var httpRes = httpReq.Response; + if (_disposed) + { + httpRes.StatusCode = 503; + httpRes.Close(); + return Task.FromResult(true); + } + var operationName = httpReq.OperationName; var localPath = url.LocalPath; diff --git a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs index 8719f5448..33d106916 100644 --- a/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs +++ b/MediaBrowser.Server.Implementations/ServerManager/ServerManager.cs @@ -71,6 +71,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// The web socket listeners. private readonly List _webSocketListeners = new List(); + private bool _disposed; + /// /// Initializes a new instance of the class. /// @@ -143,6 +145,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// The instance containing the event data. void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e) { + if (_disposed) + { + return; + } + var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger) { OnReceive = ProcessWebSocketMessageReceived, @@ -164,6 +171,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// The result. private async void ProcessWebSocketMessageReceived(WebSocketMessageInfo result) { + if (_disposed) + { + return; + } + //_logger.Debug("Websocket message received: {0}", result.MessageType); var tasks = _webSocketListeners.Select(i => Task.Run(async () => @@ -244,6 +256,11 @@ namespace MediaBrowser.Server.Implementations.ServerManager throw new ArgumentNullException("dataFunction"); } + if (_disposed) + { + throw new ObjectDisposedException(GetType().Name); + } + cancellationToken.ThrowIfCancellationRequested(); var connectionsList = connections.Where(s => s.State == WebSocketState.Open).ToList(); @@ -301,6 +318,8 @@ namespace MediaBrowser.Server.Implementations.ServerManager /// public void Dispose() { + _disposed = true; + Dispose(true); GC.SuppressFinalize(this); } diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index ac1b7ca99..f83c7d545 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -555,9 +555,10 @@ namespace MediaBrowser.ServerApplication private static void ShutdownWindowsApplication() { - _logger.Info("Calling Application.Exit"); - Application.Exit(); + //_logger.Info("Calling Application.Exit"); + //Application.Exit(); + _logger.Info("Calling Environment.Exit"); Environment.Exit(0); _logger.Info("Calling ApplicationTaskCompletionSource.SetResult"); From 584e793a6d8782956fee5ae1658fdd99d72860ed Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Apr 2016 12:27:17 -0400 Subject: [PATCH 157/852] auto-organize fixes --- .../FileOrganization/EpisodeFileOrganizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index e45df3f4a..270f01b2b 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -304,7 +304,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization if (otherDuplicatePaths.Count > 0) { - var msg = string.Format("File '{0}' already exists as '{1}', stopping organization", sourcePath, otherDuplicatePaths); + var msg = string.Format("File '{0}' already exists as these:'{1}'. Stopping organization", sourcePath, string.Join("', '", otherDuplicatePaths)); _logger.Info(msg); result.Status = FileSortingStatus.SkippedExisting; result.StatusMessage = msg; From f33b246501f493fcc8ef49e4ae3f9a1b47d804da Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Apr 2016 12:35:46 -0400 Subject: [PATCH 158/852] 3.0.5943 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ae69c74c7..ab45a122c 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5942")] +[assembly: AssemblyVersion("3.0.5943")] From ad6bde6355ab4a8cf9d4d6a51c62844bdc029fcb Mon Sep 17 00:00:00 2001 From: softworkz Date: Sat, 23 Apr 2016 06:30:05 +0200 Subject: [PATCH 159/852] Restrict metadata refresh of missing/virtual episodes This commit can significantly improe library scan times! (in my case from 15minutes to 50s) This fixes the following situation: When a user has a series in his library with lots of episodes (like thousands), the metadata for ALL series episodes was refreshed during each library scan. This resulted in very long scan times, even when using the provider's cached data. This fix skips metadata refresh for episodes that are NOT present in the local library and are having an airdate older than 30days (no more changes likely to occur) during library scans. But these skipped items would still be refreshed during a full metadata refresh. I believe this is an acceptable balance between performance and accuracy. --- MediaBrowser.Controller/Entities/TV/Series.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 7eabff072..ad4ee436e 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -255,7 +255,7 @@ namespace MediaBrowser.Controller.Entities.TV // Refresh current item await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - // Refresh TV + // Refresh seasons foreach (var item in seasons) { cancellationToken.ThrowIfCancellationRequested(); @@ -268,12 +268,30 @@ namespace MediaBrowser.Controller.Entities.TV progress.Report(percent * 100); } - // Refresh all non-songs + // Refresh episodes and other children foreach (var item in otherItems) { cancellationToken.ThrowIfCancellationRequested(); - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + var skipItem = false; + + var episode = item as Episode; + + if (episode != null + && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh + && !refreshOptions.ReplaceAllMetadata + && episode.IsMissingEpisode + && episode.LocationType == Model.Entities.LocationType.Virtual + && episode.PremiereDate.HasValue + && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30) + { + skipItem = true; + } + + if (!skipItem) + { + await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + } numComplete++; double percent = numComplete; From 0879089eb50b527a9b1318074476a273d06465e4 Mon Sep 17 00:00:00 2001 From: nfnty Date: Thu, 21 Apr 2016 07:13:33 +0200 Subject: [PATCH 160/852] Use HTTPS for API requests --- .../BoxSets/MovieDbBoxSetProvider.cs | 2 +- .../Movies/FanArtMovieUpdatesPostScanTask.cs | 2 +- .../Movies/FanartMovieImageProvider.cs | 2 +- .../Movies/GenericMovieDbInfo.cs | 2 +- .../Movies/MovieDbProvider.cs | 6 +++--- MediaBrowser.Providers/Movies/MovieDbSearch.cs | 2 +- .../Movies/MovieExternalIds.cs | 10 +++++----- .../Movies/MovieUpdatesPrescanTask.cs | 2 +- .../Music/FanArtArtistProvider.cs | 2 +- .../Music/FanArtUpdatesPostScanTask.cs | 2 +- .../Music/MusicBrainzAlbumProvider.cs | 18 +++++++++--------- .../Music/MusicBrainzArtistProvider.cs | 8 ++++---- .../Music/MusicExternalIds.cs | 12 ++++++------ .../Omdb/OmdbImageProvider.cs | 2 +- .../Omdb/OmdbItemProvider.cs | 2 +- MediaBrowser.Providers/Omdb/OmdbProvider.cs | 2 +- .../People/MovieDbPersonProvider.cs | 4 ++-- .../TV/FanArt/FanArtTvUpdatesPostScanTask.cs | 2 +- .../TV/FanArt/FanartSeriesProvider.cs | 2 +- .../TV/TheMovieDb/MovieDbProviderBase.cs | 2 +- .../TV/TheMovieDb/MovieDbSeasonProvider.cs | 2 +- .../TV/TheMovieDb/MovieDbSeriesProvider.cs | 4 ++-- .../TV/TheTVDB/TvdbPrescanTask.cs | 4 ++-- .../TV/TheTVDB/TvdbSeriesProvider.cs | 8 ++++---- MediaBrowser.Providers/TV/TvExternalIds.cs | 2 +- OpenSubtitlesHandler/Utilities.cs | 4 ++-- 26 files changed, 55 insertions(+), 55 deletions(-) diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index 53a573bd1..a280a897a 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.BoxSets { public class MovieDbBoxSetProvider : IRemoteMetadataProvider { - private const string GetCollectionInfo3 = @"http://api.themoviedb.org/3/collection/{0}?api_key={1}&append_to_response=images"; + private const string GetCollectionInfo3 = @"https://api.themoviedb.org/3/collection/{0}?api_key={1}&append_to_response=images"; internal static MovieDbBoxSetProvider Current; diff --git a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs index d207e6e7c..5262f8e3b 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieUpdatesPostScanTask.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Movies { class FanartMovieUpdatesPostScanTask : ILibraryPostScanTask { - private const string UpdatesUrl = "http://webservice.fanart.tv/v3/movies/latest?api_key={0}&date={1}"; + private const string UpdatesUrl = "https://webservice.fanart.tv/v3/movies/latest?api_key={0}&date={1}"; /// /// The _HTTP client diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs index a1dbc1967..343586ea5 100644 --- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs +++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Movies private readonly IFileSystem _fileSystem; private readonly IJsonSerializer _json; - private const string FanArtBaseUrl = "http://webservice.fanart.tv/v3/movies/{1}?api_key={0}"; + private const string FanArtBaseUrl = "https://webservice.fanart.tv/v3/movies/{1}?api_key={0}"; // &client_key=52c813aa7b8c8b3bb87f4797532a2f8c internal static FanartMovieImageProvider Current; diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index 6c6f6f0eb..77d6f617d 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -329,7 +329,7 @@ namespace MediaBrowser.Providers.Movies { hasTrailers.RemoteTrailers = movieData.trailers.youtube.Select(i => new MediaUrl { - Url = string.Format("http://www.youtube.com/watch?v={0}", i.source), + Url = string.Format("https://www.youtube.com/watch?v={0}", i.source), Name = i.name, VideoSize = string.Equals("hd", i.size, StringComparison.OrdinalIgnoreCase) ? VideoSize.HighDefinition : VideoSize.StandardDefinition diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 51051e41d..9da717b7e 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -172,8 +172,8 @@ namespace MediaBrowser.Providers.Movies } } - private const string TmdbConfigUrl = "http://api.themoviedb.org/3/configuration?api_key={0}"; - private const string GetMovieInfo3 = @"http://api.themoviedb.org/3/movie/{0}?api_key={1}&append_to_response=casts,releases,images,keywords,trailers"; + private const string TmdbConfigUrl = "https://api.themoviedb.org/3/configuration?api_key={0}"; + private const string GetMovieInfo3 = @"https://api.themoviedb.org/3/movie/{0}?api_key={1}&append_to_response=casts,releases,images,keywords,trailers"; internal static string ApiKey = "f6bd687ffa63cd282b6ff2c6877f2669"; internal static string AcceptHeader = "application/json,image/*"; @@ -281,7 +281,7 @@ namespace MediaBrowser.Providers.Movies public static string NormalizeLanguage(string language) { // They require this to be uppercase - // http://emby.media/community/index.php?/topic/32454-fr-follow-tmdbs-new-language-api-update/?p=311148 + // https://emby.media/community/index.php?/topic/32454-fr-follow-tmdbs-new-language-api-update/?p=311148 var parts = language.Split('-'); if (parts.Length == 2) diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs index e8eeab9c5..8f3c4668f 100644 --- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs +++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Movies public class MovieDbSearch { private static readonly CultureInfo EnUs = new CultureInfo("en-US"); - private const string Search3 = @"http://api.themoviedb.org/3/search/{3}?api_key={1}&query={0}&language={2}"; + private const string Search3 = @"https://api.themoviedb.org/3/search/{3}?api_key={1}&query={0}&language={2}"; internal static string ApiKey = "f6bd687ffa63cd282b6ff2c6877f2669"; internal static string AcceptHeader = "application/json,image/*"; diff --git a/MediaBrowser.Providers/Movies/MovieExternalIds.cs b/MediaBrowser.Providers/Movies/MovieExternalIds.cs index 02c330267..3bceb976e 100644 --- a/MediaBrowser.Providers/Movies/MovieExternalIds.cs +++ b/MediaBrowser.Providers/Movies/MovieExternalIds.cs @@ -21,7 +21,7 @@ namespace MediaBrowser.Providers.Movies public string UrlFormatString { - get { return "http://www.themoviedb.org/movie/{0}"; } + get { return "https://www.themoviedb.org/movie/{0}"; } } public bool Supports(IHasProviderIds item) @@ -51,7 +51,7 @@ namespace MediaBrowser.Providers.Movies public string UrlFormatString { - get { return "http://www.themoviedb.org/tv/{0}"; } + get { return "https://www.themoviedb.org/tv/{0}"; } } public bool Supports(IHasProviderIds item) @@ -74,7 +74,7 @@ namespace MediaBrowser.Providers.Movies public string UrlFormatString { - get { return "http://www.themoviedb.org/collection/{0}"; } + get { return "https://www.themoviedb.org/collection/{0}"; } } public bool Supports(IHasProviderIds item) @@ -97,7 +97,7 @@ namespace MediaBrowser.Providers.Movies public string UrlFormatString { - get { return "http://www.themoviedb.org/person/{0}"; } + get { return "https://www.themoviedb.org/person/{0}"; } } public bool Supports(IHasProviderIds item) @@ -120,7 +120,7 @@ namespace MediaBrowser.Providers.Movies public string UrlFormatString { - get { return "http://www.themoviedb.org/collection/{0}"; } + get { return "https://www.themoviedb.org/collection/{0}"; } } public bool Supports(IHasProviderIds item) diff --git a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs index 7fa7e0d15..f7f0fd6cc 100644 --- a/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs +++ b/MediaBrowser.Providers/Movies/MovieUpdatesPrescanTask.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.Movies /// /// The updates URL /// - private const string UpdatesUrl = "http://api.themoviedb.org/3/movie/changes?start_date={0}&api_key={1}&page={2}"; + private const string UpdatesUrl = "https://api.themoviedb.org/3/movie/changes?start_date={0}&api_key={1}&page={2}"; /// /// The _HTTP client diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index b715803ea..9e58b4608 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Music { internal readonly SemaphoreSlim FanArtResourcePool = new SemaphoreSlim(3, 3); internal const string ApiKey = "5c6b04c68e904cfed1e6cbc9a9e683d4"; - private const string FanArtBaseUrl = "http://webservice.fanart.tv/v3.1/music/{1}?api_key={0}"; + private const string FanArtBaseUrl = "https://webservice.fanart.tv/v3.1/music/{1}?api_key={0}"; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IServerConfigurationManager _config; diff --git a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs index 30507b891..3b829af9e 100644 --- a/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs +++ b/MediaBrowser.Providers/Music/FanArtUpdatesPostScanTask.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.Music { class FanartUpdatesPostScanTask : ILibraryPostScanTask { - private const string UpdatesUrl = "http://api.fanart.tv/webservice/newmusic/{0}/{1}/"; + private const string UpdatesUrl = "https://api.fanart.tv/webservice/newmusic/{0}/{1}/"; /// /// The _HTTP client diff --git a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs index e73a98b6f..e41982ef6 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzAlbumProvider.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Music if (!string.IsNullOrEmpty(releaseId)) { - url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=reid:{0}", releaseId); + url = string.Format("https://www.musicbrainz.org/ws/2/release/?query=reid:{0}", releaseId); } else { @@ -50,7 +50,7 @@ namespace MediaBrowser.Providers.Music if (!string.IsNullOrWhiteSpace(artistMusicBrainzId)) { - url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND arid:{1}", + url = string.Format("https://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND arid:{1}", WebUtility.UrlEncode(searchInfo.Name), artistMusicBrainzId); } @@ -58,7 +58,7 @@ namespace MediaBrowser.Providers.Music { isNameSearch = true; - url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"", + url = string.Format("https://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"", WebUtility.UrlEncode(searchInfo.Name), WebUtility.UrlEncode(searchInfo.GetAlbumArtist())); } @@ -77,7 +77,7 @@ namespace MediaBrowser.Providers.Music private IEnumerable GetResultsFromResponse(XmlDocument doc) { var ns = new XmlNamespaceManager(doc.NameTable); - ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); + ns.AddNamespace("mb", "https://musicbrainz.org/ns/mmd-2.0#"); var list = new List(); @@ -197,7 +197,7 @@ namespace MediaBrowser.Providers.Music private async Task GetReleaseResult(string albumName, string artistId, CancellationToken cancellationToken) { - var url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND arid:{1}", + var url = string.Format("https://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND arid:{1}", WebUtility.UrlEncode(albumName), artistId); @@ -208,7 +208,7 @@ namespace MediaBrowser.Providers.Music private async Task GetReleaseResultByArtistName(string albumName, string artistName, CancellationToken cancellationToken) { - var url = string.Format("http://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"", + var url = string.Format("https://www.musicbrainz.org/ws/2/release/?query=\"{0}\" AND artist:\"{1}\"", WebUtility.UrlEncode(albumName), WebUtility.UrlEncode(artistName)); @@ -220,7 +220,7 @@ namespace MediaBrowser.Providers.Music private ReleaseResult GetReleaseResult(XmlDocument doc) { var ns = new XmlNamespaceManager(doc.NameTable); - ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); + ns.AddNamespace("mb", "https://musicbrainz.org/ns/mmd-2.0#"); var result = new ReleaseResult { @@ -258,12 +258,12 @@ namespace MediaBrowser.Providers.Music /// Task{System.String}. private async Task GetReleaseGroupId(string releaseEntryId, CancellationToken cancellationToken) { - var url = string.Format("http://www.musicbrainz.org/ws/2/release-group/?query=reid:{0}", releaseEntryId); + var url = string.Format("https://www.musicbrainz.org/ws/2/release-group/?query=reid:{0}", releaseEntryId); var doc = await GetMusicBrainzResponse(url, false, cancellationToken).ConfigureAwait(false); var ns = new XmlNamespaceManager(doc.NameTable); - ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); + ns.AddNamespace("mb", "https://musicbrainz.org/ns/mmd-2.0#"); var node = doc.SelectSingleNode("//mb:release-group-list/mb:release-group/@id", ns); return node != null ? node.Value : null; diff --git a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs index c04f80549..ad900123e 100644 --- a/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs +++ b/MediaBrowser.Providers/Music/MusicBrainzArtistProvider.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Music if (!string.IsNullOrWhiteSpace(musicBrainzId)) { - var url = string.Format("http://www.musicbrainz.org/ws/2/artist/?query=arid:{0}", musicBrainzId); + var url = string.Format("https://www.musicbrainz.org/ws/2/artist/?query=arid:{0}", musicBrainzId); var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, false, cancellationToken) .ConfigureAwait(false); @@ -35,7 +35,7 @@ namespace MediaBrowser.Providers.Music // They seem to throw bad request failures on any term with a slash var nameToSearch = searchInfo.Name.Replace('/', ' '); - var url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch)); + var url = String.Format("https://www.musicbrainz.org/ws/2/artist/?query=artist:\"{0}\"", UrlEncode(nameToSearch)); var doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false); @@ -49,7 +49,7 @@ namespace MediaBrowser.Providers.Music if (HasDiacritics(searchInfo.Name)) { // Try again using the search with accent characters url - url = String.Format("http://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); + url = String.Format("https://www.musicbrainz.org/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch)); doc = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, true, cancellationToken).ConfigureAwait(false); @@ -63,7 +63,7 @@ namespace MediaBrowser.Providers.Music private IEnumerable GetResultsFromResponse(XmlDocument doc) { var ns = new XmlNamespaceManager(doc.NameTable); - ns.AddNamespace("mb", "http://musicbrainz.org/ns/mmd-2.0#"); + ns.AddNamespace("mb", "https://musicbrainz.org/ns/mmd-2.0#"); var list = new List(); diff --git a/MediaBrowser.Providers/Music/MusicExternalIds.cs b/MediaBrowser.Providers/Music/MusicExternalIds.cs index bcafdc6f6..814488df1 100644 --- a/MediaBrowser.Providers/Music/MusicExternalIds.cs +++ b/MediaBrowser.Providers/Music/MusicExternalIds.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Music public string UrlFormatString { - get { return "http://musicbrainz.org/release-group/{0}"; } + get { return "https://musicbrainz.org/release-group/{0}"; } } public bool Supports(IHasProviderIds item) @@ -41,7 +41,7 @@ namespace MediaBrowser.Providers.Music public string UrlFormatString { - get { return "http://musicbrainz.org/artist/{0}"; } + get { return "https://musicbrainz.org/artist/{0}"; } } public bool Supports(IHasProviderIds item) @@ -64,7 +64,7 @@ namespace MediaBrowser.Providers.Music public string UrlFormatString { - get { return "http://musicbrainz.org/release/{0}"; } + get { return "https://musicbrainz.org/release/{0}"; } } public bool Supports(IHasProviderIds item) @@ -87,7 +87,7 @@ namespace MediaBrowser.Providers.Music public string UrlFormatString { - get { return "http://musicbrainz.org/artist/{0}"; } + get { return "https://musicbrainz.org/artist/{0}"; } } public bool Supports(IHasProviderIds item) @@ -110,7 +110,7 @@ namespace MediaBrowser.Providers.Music public string UrlFormatString { - get { return "http://musicbrainz.org/artist/{0}"; } + get { return "https://musicbrainz.org/artist/{0}"; } } public bool Supports(IHasProviderIds item) @@ -133,7 +133,7 @@ namespace MediaBrowser.Providers.Music public string UrlFormatString { - get { return "http://musicbrainz.org/track/{0}"; } + get { return "https://musicbrainz.org/track/{0}"; } } public bool Supports(IHasProviderIds item) diff --git a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs index ae563b287..a1e038374 100644 --- a/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbImageProvider.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Providers.Omdb list.Add(new RemoteImageInfo { ProviderName = Name, - Url = string.Format("http://img.omdbapi.com/?i={0}&apikey=82e83907", imdbId) + Url = string.Format("https://img.omdbapi.com/?i={0}&apikey=82e83907", imdbId) }); } diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 1b8ecd521..cec74c68a 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -68,7 +68,7 @@ namespace MediaBrowser.Providers.Omdb var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); - var url = "http://www.omdbapi.com/?plot=full&r=json"; + var url = "https://www.omdbapi.com/?plot=full&r=json"; if (type == "episode" && episodeSearchInfo != null) { episodeSearchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Imdb.ToString(), out imdbId); diff --git a/MediaBrowser.Providers/Omdb/OmdbProvider.cs b/MediaBrowser.Providers/Omdb/OmdbProvider.cs index b68f93cf6..44e250350 100644 --- a/MediaBrowser.Providers/Omdb/OmdbProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbProvider.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Omdb var imdbParam = imdbId.StartsWith("tt", StringComparison.OrdinalIgnoreCase) ? imdbId : "tt" + imdbId; - var url = string.Format("http://www.omdbapi.com/?i={0}&tomatoes=true", imdbParam); + var url = string.Format("https://www.omdbapi.com/?i={0}&tomatoes=true", imdbParam); using (var stream = await _httpClient.Get(new HttpRequestOptions { diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index 2b37d0462..bec70294f 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -109,7 +109,7 @@ namespace MediaBrowser.Providers.People } } - var url = string.Format(@"http://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey); + var url = string.Format(@"https://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 { @@ -234,7 +234,7 @@ namespace MediaBrowser.Providers.People return; } - var url = string.Format(@"http://api.themoviedb.org/3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", MovieDbProvider.ApiKey, id); + var url = string.Format(@"https://api.themoviedb.org/3/person/{1}?api_key={0}&append_to_response=credits,images,external_ids", MovieDbProvider.ApiKey, id); using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions { diff --git a/MediaBrowser.Providers/TV/FanArt/FanArtTvUpdatesPostScanTask.cs b/MediaBrowser.Providers/TV/FanArt/FanArtTvUpdatesPostScanTask.cs index 049ffd7d8..37e76531b 100644 --- a/MediaBrowser.Providers/TV/FanArt/FanArtTvUpdatesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanArtTvUpdatesPostScanTask.cs @@ -19,7 +19,7 @@ namespace MediaBrowser.Providers.TV { class FanArtTvUpdatesPostScanTask : ILibraryPostScanTask { - private const string UpdatesUrl = "http://webservice.fanart.tv/v3/tv/latest?api_key={0}&date={1}"; + private const string UpdatesUrl = "https://webservice.fanart.tv/v3/tv/latest?api_key={0}&date={1}"; /// /// The _HTTP client diff --git a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs index 517951cb8..1168bfeee 100644 --- a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs @@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.TV private readonly IFileSystem _fileSystem; private readonly IJsonSerializer _json; - private const string FanArtBaseUrl = "http://webservice.fanart.tv/v3/tv/{1}?api_key={0}"; + private const string FanArtBaseUrl = "https://webservice.fanart.tv/v3/tv/{1}?api_key={0}"; // &client_key=52c813aa7b8c8b3bb87f4797532a2f8c internal static FanartSeriesProvider Current { get; private set; } diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs index d22827c25..36800202f 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbProviderBase.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.Providers.TV { public abstract class MovieDbProviderBase { - private const string EpisodeUrlPattern = @"http://api.themoviedb.org/3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos"; + private const string EpisodeUrlPattern = @"https://api.themoviedb.org/3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos"; private readonly IHttpClient _httpClient; private readonly IServerConfigurationManager _configurationManager; private readonly IJsonSerializer _jsonSerializer; diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs index fe0bda828..2e51393e3 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeasonProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Providers.TV { public class MovieDbSeasonProvider : IRemoteMetadataProvider { - private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}/season/{1}?api_key={2}&append_to_response=images,keywords,external_ids,credits,videos"; + private const string GetTvInfo3 = @"https://api.themoviedb.org/3/tv/{0}/season/{1}?api_key={2}&append_to_response=images,keywords,external_ids,credits,videos"; private readonly IHttpClient _httpClient; private readonly IServerConfigurationManager _configurationManager; private readonly IJsonSerializer _jsonSerializer; diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs index 98580396d..7d30042dc 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.TV { public class MovieDbSeriesProvider : IRemoteMetadataProvider, IHasOrder { - private const string GetTvInfo3 = @"http://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos,content_ratings"; + private const string GetTvInfo3 = @"https://api.themoviedb.org/3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos,content_ratings"; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); internal static MovieDbSeriesProvider Current { get; private set; } @@ -438,7 +438,7 @@ namespace MediaBrowser.Providers.TV private async Task FindByExternalId(string id, string externalSource, CancellationToken cancellationToken) { - var url = string.Format("http://api.themoviedb.org/3/tv/find/{0}?api_key={1}&external_source={2}", + var url = string.Format("https://api.themoviedb.org/3/tv/find/{0}?api_key={1}&external_source={2}", id, MovieDbProvider.ApiKey, externalSource); diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs index 1c83d73fb..672ebc95d 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbPrescanTask.cs @@ -26,12 +26,12 @@ namespace MediaBrowser.Providers.TV /// /// The server time URL /// - private const string ServerTimeUrl = "http://thetvdb.com/api/Updates.php?type=none"; + private const string ServerTimeUrl = "https://thetvdb.com/api/Updates.php?type=none"; /// /// The updates URL /// - private const string UpdatesUrl = "http://thetvdb.com/api/Updates.php?type=all&time={0}"; + private const string UpdatesUrl = "https://thetvdb.com/api/Updates.php?type=all&time={0}"; /// /// The _HTTP client diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs index f66e9254e..ee1505b46 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeriesProvider.cs @@ -53,9 +53,9 @@ namespace MediaBrowser.Providers.TV Current = this; } - private const string SeriesSearchUrl = "http://www.thetvdb.com/api/GetSeries.php?seriesname={0}&language={1}"; - 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 const string SeriesSearchUrl = "https://www.thetvdb.com/api/GetSeries.php?seriesname={0}&language={1}"; + private const string SeriesGetZip = "https://www.thetvdb.com/api/{0}/series/{1}/all/{2}.zip"; + private const string GetSeriesByImdbId = "https://www.thetvdb.com/api/GetSeriesByRemoteID.php?imdbid={0}&language={1}"; private string NormalizeLanguage(string language) { @@ -1465,4 +1465,4 @@ namespace MediaBrowser.Providers.TV }; } } -} \ No newline at end of file +} diff --git a/MediaBrowser.Providers/TV/TvExternalIds.cs b/MediaBrowser.Providers/TV/TvExternalIds.cs index 82baae250..f5a26ba0a 100644 --- a/MediaBrowser.Providers/TV/TvExternalIds.cs +++ b/MediaBrowser.Providers/TV/TvExternalIds.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.TV public string UrlFormatString { - get { return "http://thetvdb.com/index.php?tab=series&id={0}"; } + get { return "https://thetvdb.com/index.php?tab=series&id={0}"; } } public bool Supports(IHasProviderIds item) diff --git a/OpenSubtitlesHandler/Utilities.cs b/OpenSubtitlesHandler/Utilities.cs index 2ae116521..d26c76b7c 100644 --- a/OpenSubtitlesHandler/Utilities.cs +++ b/OpenSubtitlesHandler/Utilities.cs @@ -32,7 +32,7 @@ namespace OpenSubtitlesHandler /// public sealed class Utilities { - private const string XML_RPC_SERVER = "http://api.opensubtitles.org/xml-rpc"; + private const string XML_RPC_SERVER = "https://api.opensubtitles.org/xml-rpc"; /// /// Compute movie hash @@ -195,7 +195,7 @@ namespace OpenSubtitlesHandler RequestContentBytes = request, RequestContentType = "text/xml", UserAgent = userAgent, - Host = "api.opensubtitles.org:80", + Host = "api.opensubtitles.org:443", Url = XML_RPC_SERVER, // Response parsing will fail with this enabled From 85a9363c7806be6206c6e6f4a533d7ed578c3787 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Apr 2016 01:52:33 -0400 Subject: [PATCH 161/852] update packages --- .../MediaBrowser.Common.Implementations.csproj | 10 ++++++---- MediaBrowser.Common.Implementations/packages.config | 6 +++--- .../MediaBrowser.Server.Implementations.csproj | 10 +++++++--- MediaBrowser.Server.Implementations/packages.config | 3 ++- Nuget/MediaBrowser.Common.Internal.nuspec | 4 ++-- 5 files changed, 20 insertions(+), 13 deletions(-) diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index 2017b40f4..8da1beb68 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -54,8 +54,9 @@ ..\packages\morelinq.1.4.0\lib\net35\MoreLinq.dll - - ..\packages\NLog.4.2.3\lib\net45\NLog.dll + + ..\packages\NLog.4.3.1\lib\net45\NLog.dll + True ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll @@ -64,8 +65,9 @@ False ..\ThirdParty\SharpCompress\SharpCompress.dll - - ..\packages\SimpleInjector.3.1.2\lib\net45\SimpleInjector.dll + + ..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll + True diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index 64b337221..6d7d86182 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -2,7 +2,7 @@ - + - - + + \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 60d8f737f..43f5d741b 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -68,9 +68,13 @@ ..\ThirdParty\ServiceStack\ServiceStack.Api.Swagger.dll - - False - ..\packages\SocketHttpListener.1.0.0.29\lib\net45\SocketHttpListener.dll + + ..\packages\SimpleInjector.3.1.3\lib\net45\SimpleInjector.dll + True + + + ..\packages\SocketHttpListener.1.0.0.30\lib\net45\SocketHttpListener.dll + True diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 66aede029..dce839b57 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -8,5 +8,6 @@ - + + \ No newline at end of file diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 0ae08c4ad..a561dbf4b 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -13,8 +13,8 @@ Copyright © Emby 2013 - - + + From 1bb287ccff73901b48fc089bca68f510ede9e5be Mon Sep 17 00:00:00 2001 From: nfnty Date: Thu, 21 Apr 2016 08:02:23 +0200 Subject: [PATCH 162/852] Dlna: Stop SSDP if disabled, Fixes #1578 --- MediaBrowser.Dlna/Main/DlnaEntryPoint.cs | 49 ++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index 37584f006..5e8be1c4c 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -39,6 +39,7 @@ namespace MediaBrowser.Dlna.Main private readonly IDeviceDiscovery _deviceDiscovery; private readonly List _registeredServerIds = new List(); + private bool _ssdpHandlerStarted; private bool _dlnaServerStarted; public DlnaEntryPoint(IServerConfigurationManager config, @@ -75,12 +76,22 @@ namespace MediaBrowser.Dlna.Main public void Run() { - StartSsdpHandler(); ReloadComponents(); + _config.ConfigurationUpdated += _config_ConfigurationUpdated; _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; } + private bool _lastEnableUPnP; + void _config_ConfigurationUpdated(object sender, EventArgs e) + { + if (_lastEnableUPnP != _config.Configuration.EnableUPnP) + { + ReloadComponents(); + } + _lastEnableUPnP = _config.Configuration.EnableUPnP; + } + void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) { if (string.Equals(e.Key, "dlna", StringComparison.OrdinalIgnoreCase)) @@ -91,10 +102,24 @@ namespace MediaBrowser.Dlna.Main private void ReloadComponents() { - var isServerStarted = _dlnaServerStarted; - var options = _config.GetDlnaConfiguration(); + if (!options.EnableServer && !options.EnablePlayTo && !_config.Configuration.EnableUPnP) + { + if (_ssdpHandlerStarted) + { + StopSsdpHandler(); + } + return; + } + + if (!_ssdpHandlerStarted) + { + StartSsdpHandler(); + } + + var isServerStarted = _dlnaServerStarted; + if (options.EnableServer && !isServerStarted) { StartDlnaServer(); @@ -123,6 +148,8 @@ namespace MediaBrowser.Dlna.Main _ssdpHandler.Start(); ((DeviceDiscovery)_deviceDiscovery).Start(_ssdpHandler); + + _ssdpHandlerStarted = true; } catch (Exception ex) { @@ -130,6 +157,22 @@ namespace MediaBrowser.Dlna.Main } } + private void StopSsdpHandler() + { + try + { + ((DeviceDiscovery)_deviceDiscovery).Dispose(); + + _ssdpHandler.Dispose(); + + _ssdpHandlerStarted = false; + } + catch (Exception ex) + { + _logger.ErrorException("Error stopping ssdp handlers", ex); + } + } + public void StartDlnaServer() { try From 9807448fce0bba3b1aaf9fcb249efc5efe7b3146 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Apr 2016 14:38:36 -0400 Subject: [PATCH 163/852] update sleep prevention --- .../People/MovieDbPersonProvider.cs | 2 +- .../Native/BaseMonoApp.cs | 5 +++ .../EntryPoints/KeepServerAwake.cs | 31 +++++++------- .../INativeApp.cs | 2 + MediaBrowser.ServerApplication/MainStartup.cs | 5 +++ .../Native/Standby.cs | 40 ++++++++++++------- .../Native/WindowsApp.cs | 8 +++- .../ServerNotifyIcon.cs | 7 +++- 8 files changed, 67 insertions(+), 33 deletions(-) diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index 2b37d0462..40ce6ad47 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Providers.People var requestCount = _requestCount; - if (requestCount >= 30) + if (requestCount >= 40) { //_logger.Debug("Throttling Tmdb people"); diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index 6d19c3275..72c191121 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -69,6 +69,11 @@ namespace MediaBrowser.Server.Mono.Native } + public void AllowSystemStandby() + { + + } + public List GetAssembliesWithParts() { var list = new List(); diff --git a/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs b/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs index 20d4c6b2a..dbfd6f4e8 100644 --- a/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs +++ b/MediaBrowser.Server.Startup.Common/EntryPoints/KeepServerAwake.cs @@ -27,28 +27,27 @@ namespace MediaBrowser.Server.Startup.Common.EntryPoints _timer = new PeriodicTimer(obj => { var now = DateTime.UtcNow; - if (_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 15)) + var nativeApp = ((ApplicationHost)_appHost).NativeApp; + + try { - KeepAlive(); + if (_sessionManager.Sessions.Any(i => (now - i.LastActivityDate).TotalMinutes < 15)) + { + nativeApp.PreventSystemStandby(); + } + else + { + nativeApp.AllowSystemStandby(); + } + } + catch (Exception ex) + { + _logger.ErrorException("Error resetting system standby timer", ex); } }, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); } - private void KeepAlive() - { - var nativeApp = ((ApplicationHost)_appHost).NativeApp; - - try - { - nativeApp.PreventSystemStandby(); - } - catch (Exception ex) - { - _logger.ErrorException("Error resetting system standby timer", ex); - } - } - public void Dispose() { if (_timer != null) diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index 121d4192e..00f987d3c 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -93,6 +93,8 @@ namespace MediaBrowser.Server.Startup.Common /// void PreventSystemStandby(); + void AllowSystemStandby(); + /// /// Gets the power management. /// diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index f83c7d545..4dc8a47f5 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -321,6 +321,11 @@ namespace MediaBrowser.ServerApplication } } + public static void Invoke(Action action) + { + _serverNotifyIcon.Invoke(action); + } + /// /// Starts the service. /// diff --git a/MediaBrowser.ServerApplication/Native/Standby.cs b/MediaBrowser.ServerApplication/Native/Standby.cs index 274c72b25..919709538 100644 --- a/MediaBrowser.ServerApplication/Native/Standby.cs +++ b/MediaBrowser.ServerApplication/Native/Standby.cs @@ -1,4 +1,5 @@ -using System.Runtime.InteropServices; +using System; +using System.Runtime.InteropServices; namespace MediaBrowser.ServerApplication.Native { @@ -7,11 +8,33 @@ namespace MediaBrowser.ServerApplication.Native /// public static class Standby { - public static void PreventSystemStandby() + public static void PreventSleepAndMonitorOff() { - SystemHelper.ResetStandbyTimer(); + NativeMethods.SetThreadExecutionState(NativeMethods.ES_CONTINUOUS | NativeMethods.ES_SYSTEM_REQUIRED | NativeMethods.ES_DISPLAY_REQUIRED); } + public static void PreventSleep() + { + NativeMethods.SetThreadExecutionState(NativeMethods.ES_CONTINUOUS | NativeMethods.ES_SYSTEM_REQUIRED); + } + + // Clear EXECUTION_STATE flags to allow the system to sleep and turn off monitor normally + public static void AllowSleep() + { + NativeMethods.SetThreadExecutionState(NativeMethods.ES_CONTINUOUS); + } + + internal static class NativeMethods + { + // Import SetThreadExecutionState Win32 API and necessary flags + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern uint SetThreadExecutionState(uint esFlags); + public const uint ES_CONTINUOUS = 0x80000000; + public const uint ES_SYSTEM_REQUIRED = 0x00000001; + public const uint ES_DISPLAY_REQUIRED = 0x00000002; + } + + [Flags] internal enum EXECUTION_STATE : uint { ES_NONE = 0, @@ -21,16 +44,5 @@ namespace MediaBrowser.ServerApplication.Native ES_AWAYMODE_REQUIRED = 0x00000040, ES_CONTINUOUS = 0x80000000 } - - public class SystemHelper - { - [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] - static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags); - - public static void ResetStandbyTimer() - { - EXECUTION_STATE es = SetThreadExecutionState(EXECUTION_STATE.ES_SYSTEM_REQUIRED); - } - } } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 146a4372b..ff5fe4d84 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -5,6 +5,7 @@ using MediaBrowser.ServerApplication.Networking; using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Windows.Forms; using CommonIO; using MediaBrowser.Controller.Power; using MediaBrowser.Server.Startup.Common.FFMpeg; @@ -134,7 +135,12 @@ namespace MediaBrowser.ServerApplication.Native public void PreventSystemStandby() { - Standby.PreventSystemStandby(); + MainStartup.Invoke(Standby.PreventSleep); + } + + public void AllowSystemStandby() + { + MainStartup.Invoke(Standby.AllowSleep); } public IPowerManagement GetPowerManagement() diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs index 673c6cddd..2146274af 100644 --- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs +++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs @@ -36,10 +36,15 @@ namespace MediaBrowser.ServerApplication set { Action act = () => notifyIcon1.Visible = false; - contextMenuStrip1.Invoke(act); + Invoke(act); } } + public void Invoke(Action action) + { + contextMenuStrip1.Invoke(action); + } + public ServerNotifyIcon(ILogManager logManager, IServerApplicationHost appHost, IServerConfigurationManager configurationManager, From 75fcde417ab18b8de01fdd42f819b1fe93d8a064 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Apr 2016 16:30:45 -0400 Subject: [PATCH 164/852] update library menu --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index f84fe058a..7aad3b91a 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -128,6 +128,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -146,6 +149,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From ebf0eeb3bd68cd5532e965167936537223521658 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Apr 2016 23:03:49 -0400 Subject: [PATCH 165/852] update browser launcher --- .../IServerApplicationHost.cs | 4 +- .../Native/BaseMonoApp.cs | 5 ++ .../ApplicationHost.cs | 5 ++ .../Browser/BrowserLauncher.cs | 59 +++++-------------- .../EntryPoints/StartupWizard.cs | 2 +- .../INativeApp.cs | 2 + MediaBrowser.ServerApplication/MainStartup.cs | 2 +- .../Native/WindowsApp.cs | 41 ++++++++++++- .../ServerNotifyIcon.cs | 8 +-- 9 files changed, 76 insertions(+), 52 deletions(-) diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index e4eecec18..65eed1a23 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller public interface IServerApplicationHost : IApplicationHost { event EventHandler HasUpdateAvailableChanged; - + /// /// Gets the system info. /// @@ -86,5 +86,7 @@ namespace MediaBrowser.Controller /// The ip address. /// System.String. string GetLocalApiUrl(IPAddress ipAddress); + + void LaunchUrl(string url); } } diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index 72c191121..fbfef9a34 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -222,6 +222,11 @@ namespace MediaBrowser.Server.Mono.Native return GetInfo(Environment); } + public void LaunchUrl(string url) + { + throw new NotImplementedException(); + } + public static FFMpegInstallInfo GetInfo(NativeEnvironment environment) { var info = new FFMpegInstallInfo(); diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 93dbe2945..2e2b42ba2 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -1404,5 +1404,10 @@ namespace MediaBrowser.Server.Startup.Common return externalDns; } } + + public void LaunchUrl(string url) + { + NativeApp.LaunchUrl(url); + } } } diff --git a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs index a4504f25a..db48d1110 100644 --- a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs +++ b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs @@ -15,87 +15,58 @@ namespace MediaBrowser.Server.Startup.Common.Browser /// /// The page. /// The app host. - /// The logger. - public static void OpenDashboardPage(string page, IServerApplicationHost appHost, ILogger logger) + public static void OpenDashboardPage(string page, IServerApplicationHost appHost) { var url = appHost.GetLocalApiUrl("localhost") + "/web/" + page; - OpenUrl(url, logger); + OpenUrl(appHost, url); } /// /// Opens the community. /// - /// The logger. - public static void OpenCommunity(ILogger logger) + public static void OpenCommunity(IServerApplicationHost appHost) { - OpenUrl("http://emby.media/community", logger); + OpenUrl(appHost, "http://emby.media/community"); } /// /// Opens the web client. /// /// The app host. - /// The logger. - public static void OpenWebClient(IServerApplicationHost appHost, ILogger logger) + public static void OpenWebClient(IServerApplicationHost appHost) { - OpenDashboardPage("index.html", appHost, logger); + OpenDashboardPage("index.html", appHost); } /// /// Opens the dashboard. /// /// The app host. - /// The logger. - public static void OpenDashboard(IServerApplicationHost appHost, ILogger logger) + public static void OpenDashboard(IServerApplicationHost appHost) { - OpenDashboardPage("dashboard.html", appHost, logger); + OpenDashboardPage("dashboard.html", appHost); } /// /// Opens the URL. /// /// The URL. - /// The logger. - private static void OpenUrl(string url, ILogger logger) + private static void OpenUrl(IServerApplicationHost appHost, string url) { - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = url - }, - - EnableRaisingEvents = true, - }; - - process.Exited += ProcessExited; - try { - process.Start(); + appHost.LaunchUrl(url); + } + catch (NotImplementedException) + { + } catch (Exception ex) { - logger.ErrorException("Error launching url: {0}", ex, url); - - Console.WriteLine("Error launching url: {0}", ex.Message); + Console.WriteLine("Error launching url: " + url); Console.WriteLine(ex.Message); - -//#if !__MonoCS__ -// System.Windows.Forms.MessageBox.Show("There was an error launching your web browser. Please check your default browser settings."); -//#endif } } - - /// - /// Processes the exited. - /// - /// The sender. - /// The instance containing the event data. - private static void ProcessExited(object sender, EventArgs e) - { - ((Process)sender).Dispose(); - } } } diff --git a/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs b/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs index 854fa44c1..f9d173c59 100644 --- a/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs +++ b/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Server.Startup.Common.EntryPoints /// private void LaunchStartupWizard() { - BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost, _logger); + BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost); } /// diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index 00f987d3c..c0758b47f 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -102,5 +102,7 @@ namespace MediaBrowser.Server.Startup.Common IPowerManagement GetPowerManagement(); FFMpegInstallInfo GetFfmpegInstallInfo(); + + void LaunchUrl(string url); } } diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 4dc8a47f5..454c415a1 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -317,7 +317,7 @@ namespace MediaBrowser.ServerApplication { if (e.Reason == SessionSwitchReason.SessionLogon) { - BrowserLauncher.OpenDashboard(_appHost, _logger); + BrowserLauncher.OpenDashboard(_appHost); } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index ff5fe4d84..10cd59436 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -1,14 +1,17 @@ -using MediaBrowser.Common.Net; +using System; +using MediaBrowser.Common.Net; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Startup.Common; using MediaBrowser.ServerApplication.Networking; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; using System.Windows.Forms; using CommonIO; using MediaBrowser.Controller.Power; using MediaBrowser.Server.Startup.Common.FFMpeg; +using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem; namespace MediaBrowser.ServerApplication.Native { @@ -162,6 +165,42 @@ namespace MediaBrowser.ServerApplication.Native return info; } + public void LaunchUrl(string url) + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = url + }, + + EnableRaisingEvents = true, + }; + + process.Exited += ProcessExited; + + try + { + process.Start(); + } + catch (Exception ex) + { + _logger.ErrorException("Error launching url: {0}", ex, url); + + throw; + } + } + + /// + /// Processes the exited. + /// + /// The sender. + /// The instance containing the event data. + private static void ProcessExited(object sender, EventArgs e) + { + ((Process)sender).Dispose(); + } + private string[] GetDownloadUrls() { switch (Environment.SystemArchitecture) diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs index 2146274af..27816db5a 100644 --- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs +++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs @@ -168,7 +168,7 @@ namespace MediaBrowser.ServerApplication void notifyIcon1_DoubleClick(object sender, EventArgs e) { - BrowserLauncher.OpenDashboard(_appHost, _logger); + BrowserLauncher.OpenDashboard(_appHost); } private void LocalizeText() @@ -199,17 +199,17 @@ namespace MediaBrowser.ServerApplication void cmdBrowse_Click(object sender, EventArgs e) { - BrowserLauncher.OpenWebClient(_appHost, _logger); + BrowserLauncher.OpenWebClient(_appHost); } void cmdCommunity_Click(object sender, EventArgs e) { - BrowserLauncher.OpenCommunity(_logger); + BrowserLauncher.OpenCommunity(_appHost); } void cmdConfigure_Click(object sender, EventArgs e) { - BrowserLauncher.OpenDashboard(_appHost, _logger); + BrowserLauncher.OpenDashboard(_appHost); } void cmdRestart_Click(object sender, EventArgs e) From 83c33dd7418dbec86454ceadeb1cb79b91c4f62f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Apr 2016 00:23:13 -0400 Subject: [PATCH 166/852] remove noaccurateseek param --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 901554973..9278de3be 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -2222,9 +2222,10 @@ namespace MediaBrowser.Api.Playback if (state.VideoRequest != null) { + // Important: If this is ever re-enabled, make sure not to use it with wtv because it breaks seeking if (string.Equals(state.OutputContainer, "mkv", StringComparison.OrdinalIgnoreCase) && state.VideoRequest.CopyTimestamps) { - inputModifier += " -noaccurate_seek"; + //inputModifier += " -noaccurate_seek"; } } From e7b0b455f0cdba80f6568b79c60267acda224d47 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Apr 2016 19:27:47 -0400 Subject: [PATCH 167/852] update lazy loading --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 7aad3b91a..7565c8dfb 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -128,7 +128,10 @@ PreserveNewest - + + PreserveNewest + + PreserveNewest From 6b1c6ace222d7b94a3a378b1a88126537349431d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Apr 2016 20:36:10 -0400 Subject: [PATCH 168/852] more identify fixes --- .../Manager/ProviderManager.cs | 49 +++++++++---------- .../Omdb/OmdbItemProvider.cs | 11 ++--- .../ApplicationHost.cs | 2 +- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 3199ed12b..c95d58a42 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -20,6 +20,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Manager { @@ -60,6 +61,7 @@ namespace MediaBrowser.Providers.Manager private IEnumerable _savers; private IImageSaver[] _imageSavers; private readonly IServerApplicationPaths _appPaths; + private readonly IJsonSerializer _json; private IExternalId[] _externalIds; @@ -73,7 +75,7 @@ namespace MediaBrowser.Providers.Manager /// The directory watchers. /// The log manager. /// The file system. - public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory) + public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory, IJsonSerializer json) { _logger = logManager.GetLogger("ProviderManager"); _httpClient = httpClient; @@ -82,6 +84,7 @@ namespace MediaBrowser.Providers.Manager _fileSystem = fileSystem; _appPaths = appPaths; _libraryManagerFactory = libraryManagerFactory; + _json = json; } /// @@ -730,8 +733,6 @@ namespace MediaBrowser.Providers.Manager where TItemType : BaseItem, new() where TLookupType : ItemLookupInfo { - const int maxResults = 10; - // Give it a dummy path just so that it looks like a file system item var dummy = new TItemType { @@ -761,7 +762,6 @@ namespace MediaBrowser.Providers.Manager } var resultList = new List(); - var foundProviderIds = new Dictionary, RemoteSearchResult>(); foreach (var provider in providers) { @@ -771,32 +771,27 @@ namespace MediaBrowser.Providers.Manager foreach (var result in results) { - var bFound = false; + var existingMatch = resultList.FirstOrDefault(i => i.ProviderIds.Any(p => string.Equals(result.GetProviderId(p.Key), p.Value, StringComparison.OrdinalIgnoreCase))); - // This check prevents duplicate search results by comparing provider ids - foreach (var providerId in result.ProviderIds) - { - var idTuple = new Tuple(providerId.Key.ToLower(), providerId.Value.ToLower()); - - if (!foundProviderIds.ContainsKey(idTuple)) - { - foundProviderIds.Add(idTuple, result); - } - else - { - bFound = true; - var existingResult = foundProviderIds[idTuple]; - if (string.IsNullOrEmpty(existingResult.ImageUrl) && !string.IsNullOrEmpty(result.ImageUrl)) - { - existingResult.ImageUrl = result.ImageUrl; - } - } - } - - if (!bFound && resultList.Count < maxResults) + if (existingMatch == null) { resultList.Add(result); } + else + { + foreach (var providerId in result.ProviderIds) + { + if (!existingMatch.ProviderIds.ContainsKey(providerId.Key)) + { + existingMatch.ProviderIds.Add(providerId.Key, providerId.Value); + } + } + + if (string.IsNullOrWhiteSpace(existingMatch.ImageUrl)) + { + existingMatch.ImageUrl = result.ImageUrl; + } + } } } catch (Exception ex) @@ -805,6 +800,8 @@ namespace MediaBrowser.Providers.Manager } } + //_logger.Debug("Returning search results {0}", _json.SerializeToString(resultList)); + return resultList; } diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index cec74c68a..a0d60c166 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -64,8 +64,6 @@ namespace MediaBrowser.Providers.Omdb { var episodeSearchInfo = searchInfo as EpisodeInfo; - var list = new List(); - var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); var url = "https://www.omdbapi.com/?plot=full&r=json"; @@ -148,14 +146,13 @@ namespace MediaBrowser.Providers.Omdb } } - foreach (var result in resultList) + return resultList.Select(result => { var item = new RemoteSearchResult { IndexNumber = searchInfo.IndexNumber, Name = result.Title, ParentIndexNumber = searchInfo.ParentIndexNumber, - ProviderIds = searchInfo.ProviderIds, SearchProviderName = Name }; @@ -185,11 +182,9 @@ namespace MediaBrowser.Providers.Omdb item.ImageUrl = result.Poster; } - list.Add(item); - } + return item; + }); } - - return list; } public Task> GetMetadata(TrailerInfo info, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 2e2b42ba2..01575e71f 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -440,7 +440,7 @@ namespace MediaBrowser.Server.Startup.Common LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, this); RegisterSingleInstance(LibraryMonitor); - ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths, () => LibraryManager); + ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); RegisterSingleInstance(ProviderManager); SeriesOrderManager = new SeriesOrderManager(); From d459b97a217380443d305630b575b078145c4d9b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 22 Apr 2016 12:27:17 -0400 Subject: [PATCH 169/852] auto-organize fixes --- .../FileOrganization/EpisodeFileOrganizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs index e45df3f4a..270f01b2b 100644 --- a/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs +++ b/MediaBrowser.Server.Implementations/FileOrganization/EpisodeFileOrganizer.cs @@ -304,7 +304,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization if (otherDuplicatePaths.Count > 0) { - var msg = string.Format("File '{0}' already exists as '{1}', stopping organization", sourcePath, otherDuplicatePaths); + var msg = string.Format("File '{0}' already exists as these:'{1}'. Stopping organization", sourcePath, string.Join("', '", otherDuplicatePaths)); _logger.Info(msg); result.Status = FileSortingStatus.SkippedExisting; result.StatusMessage = msg; From fb3863de7e0c8868c9175d6a23b96c5382d83abf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 24 Apr 2016 20:36:10 -0400 Subject: [PATCH 170/852] more identify fixes --- .../Manager/ProviderManager.cs | 49 +++++++++---------- .../Omdb/OmdbItemProvider.cs | 11 ++--- .../ApplicationHost.cs | 2 +- 3 files changed, 27 insertions(+), 35 deletions(-) diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 3199ed12b..c95d58a42 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -20,6 +20,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Manager { @@ -60,6 +61,7 @@ namespace MediaBrowser.Providers.Manager private IEnumerable _savers; private IImageSaver[] _imageSavers; private readonly IServerApplicationPaths _appPaths; + private readonly IJsonSerializer _json; private IExternalId[] _externalIds; @@ -73,7 +75,7 @@ namespace MediaBrowser.Providers.Manager /// The directory watchers. /// The log manager. /// The file system. - public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory) + public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory, IJsonSerializer json) { _logger = logManager.GetLogger("ProviderManager"); _httpClient = httpClient; @@ -82,6 +84,7 @@ namespace MediaBrowser.Providers.Manager _fileSystem = fileSystem; _appPaths = appPaths; _libraryManagerFactory = libraryManagerFactory; + _json = json; } /// @@ -730,8 +733,6 @@ namespace MediaBrowser.Providers.Manager where TItemType : BaseItem, new() where TLookupType : ItemLookupInfo { - const int maxResults = 10; - // Give it a dummy path just so that it looks like a file system item var dummy = new TItemType { @@ -761,7 +762,6 @@ namespace MediaBrowser.Providers.Manager } var resultList = new List(); - var foundProviderIds = new Dictionary, RemoteSearchResult>(); foreach (var provider in providers) { @@ -771,32 +771,27 @@ namespace MediaBrowser.Providers.Manager foreach (var result in results) { - var bFound = false; + var existingMatch = resultList.FirstOrDefault(i => i.ProviderIds.Any(p => string.Equals(result.GetProviderId(p.Key), p.Value, StringComparison.OrdinalIgnoreCase))); - // This check prevents duplicate search results by comparing provider ids - foreach (var providerId in result.ProviderIds) - { - var idTuple = new Tuple(providerId.Key.ToLower(), providerId.Value.ToLower()); - - if (!foundProviderIds.ContainsKey(idTuple)) - { - foundProviderIds.Add(idTuple, result); - } - else - { - bFound = true; - var existingResult = foundProviderIds[idTuple]; - if (string.IsNullOrEmpty(existingResult.ImageUrl) && !string.IsNullOrEmpty(result.ImageUrl)) - { - existingResult.ImageUrl = result.ImageUrl; - } - } - } - - if (!bFound && resultList.Count < maxResults) + if (existingMatch == null) { resultList.Add(result); } + else + { + foreach (var providerId in result.ProviderIds) + { + if (!existingMatch.ProviderIds.ContainsKey(providerId.Key)) + { + existingMatch.ProviderIds.Add(providerId.Key, providerId.Value); + } + } + + if (string.IsNullOrWhiteSpace(existingMatch.ImageUrl)) + { + existingMatch.ImageUrl = result.ImageUrl; + } + } } } catch (Exception ex) @@ -805,6 +800,8 @@ namespace MediaBrowser.Providers.Manager } } + //_logger.Debug("Returning search results {0}", _json.SerializeToString(resultList)); + return resultList; } diff --git a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs index 1b8ecd521..8acaf30d5 100644 --- a/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs +++ b/MediaBrowser.Providers/Omdb/OmdbItemProvider.cs @@ -64,8 +64,6 @@ namespace MediaBrowser.Providers.Omdb { var episodeSearchInfo = searchInfo as EpisodeInfo; - var list = new List(); - var imdbId = searchInfo.GetProviderId(MetadataProviders.Imdb); var url = "http://www.omdbapi.com/?plot=full&r=json"; @@ -148,14 +146,13 @@ namespace MediaBrowser.Providers.Omdb } } - foreach (var result in resultList) + return resultList.Select(result => { var item = new RemoteSearchResult { IndexNumber = searchInfo.IndexNumber, Name = result.Title, ParentIndexNumber = searchInfo.ParentIndexNumber, - ProviderIds = searchInfo.ProviderIds, SearchProviderName = Name }; @@ -185,11 +182,9 @@ namespace MediaBrowser.Providers.Omdb item.ImageUrl = result.Poster; } - list.Add(item); - } + return item; + }); } - - return list; } public Task> GetMetadata(TrailerInfo info, CancellationToken cancellationToken) diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 93dbe2945..b371ac751 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -440,7 +440,7 @@ namespace MediaBrowser.Server.Startup.Common LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, this); RegisterSingleInstance(LibraryMonitor); - ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths, () => LibraryManager); + ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); RegisterSingleInstance(ProviderManager); SeriesOrderManager = new SeriesOrderManager(); From 4d16f9704779c96f4dba46229e22554913f8107e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Apr 2016 23:03:49 -0400 Subject: [PATCH 171/852] update browser launcher --- .../IServerApplicationHost.cs | 4 +- .../Native/BaseMonoApp.cs | 5 ++ .../ApplicationHost.cs | 5 ++ .../Browser/BrowserLauncher.cs | 59 +++++-------------- .../EntryPoints/StartupWizard.cs | 2 +- .../INativeApp.cs | 2 + MediaBrowser.ServerApplication/MainStartup.cs | 2 +- .../Native/WindowsApp.cs | 41 ++++++++++++- .../ServerNotifyIcon.cs | 8 +-- 9 files changed, 76 insertions(+), 52 deletions(-) diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs index e4eecec18..65eed1a23 100644 --- a/MediaBrowser.Controller/IServerApplicationHost.cs +++ b/MediaBrowser.Controller/IServerApplicationHost.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller public interface IServerApplicationHost : IApplicationHost { event EventHandler HasUpdateAvailableChanged; - + /// /// Gets the system info. /// @@ -86,5 +86,7 @@ namespace MediaBrowser.Controller /// The ip address. /// System.String. string GetLocalApiUrl(IPAddress ipAddress); + + void LaunchUrl(string url); } } diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index 6d19c3275..0eab94a3b 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -217,6 +217,11 @@ namespace MediaBrowser.Server.Mono.Native return GetInfo(Environment); } + public void LaunchUrl(string url) + { + throw new NotImplementedException(); + } + public static FFMpegInstallInfo GetInfo(NativeEnvironment environment) { var info = new FFMpegInstallInfo(); diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index b371ac751..01575e71f 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -1404,5 +1404,10 @@ namespace MediaBrowser.Server.Startup.Common return externalDns; } } + + public void LaunchUrl(string url) + { + NativeApp.LaunchUrl(url); + } } } diff --git a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs index a4504f25a..db48d1110 100644 --- a/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs +++ b/MediaBrowser.Server.Startup.Common/Browser/BrowserLauncher.cs @@ -15,87 +15,58 @@ namespace MediaBrowser.Server.Startup.Common.Browser /// /// The page. /// The app host. - /// The logger. - public static void OpenDashboardPage(string page, IServerApplicationHost appHost, ILogger logger) + public static void OpenDashboardPage(string page, IServerApplicationHost appHost) { var url = appHost.GetLocalApiUrl("localhost") + "/web/" + page; - OpenUrl(url, logger); + OpenUrl(appHost, url); } /// /// Opens the community. /// - /// The logger. - public static void OpenCommunity(ILogger logger) + public static void OpenCommunity(IServerApplicationHost appHost) { - OpenUrl("http://emby.media/community", logger); + OpenUrl(appHost, "http://emby.media/community"); } /// /// Opens the web client. /// /// The app host. - /// The logger. - public static void OpenWebClient(IServerApplicationHost appHost, ILogger logger) + public static void OpenWebClient(IServerApplicationHost appHost) { - OpenDashboardPage("index.html", appHost, logger); + OpenDashboardPage("index.html", appHost); } /// /// Opens the dashboard. /// /// The app host. - /// The logger. - public static void OpenDashboard(IServerApplicationHost appHost, ILogger logger) + public static void OpenDashboard(IServerApplicationHost appHost) { - OpenDashboardPage("dashboard.html", appHost, logger); + OpenDashboardPage("dashboard.html", appHost); } /// /// Opens the URL. /// /// The URL. - /// The logger. - private static void OpenUrl(string url, ILogger logger) + private static void OpenUrl(IServerApplicationHost appHost, string url) { - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = url - }, - - EnableRaisingEvents = true, - }; - - process.Exited += ProcessExited; - try { - process.Start(); + appHost.LaunchUrl(url); + } + catch (NotImplementedException) + { + } catch (Exception ex) { - logger.ErrorException("Error launching url: {0}", ex, url); - - Console.WriteLine("Error launching url: {0}", ex.Message); + Console.WriteLine("Error launching url: " + url); Console.WriteLine(ex.Message); - -//#if !__MonoCS__ -// System.Windows.Forms.MessageBox.Show("There was an error launching your web browser. Please check your default browser settings."); -//#endif } } - - /// - /// Processes the exited. - /// - /// The sender. - /// The instance containing the event data. - private static void ProcessExited(object sender, EventArgs e) - { - ((Process)sender).Dispose(); - } } } diff --git a/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs b/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs index 854fa44c1..f9d173c59 100644 --- a/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs +++ b/MediaBrowser.Server.Startup.Common/EntryPoints/StartupWizard.cs @@ -46,7 +46,7 @@ namespace MediaBrowser.Server.Startup.Common.EntryPoints /// private void LaunchStartupWizard() { - BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost, _logger); + BrowserLauncher.OpenDashboardPage("wizardstart.html", _appHost); } /// diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index 121d4192e..c603a908e 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -100,5 +100,7 @@ namespace MediaBrowser.Server.Startup.Common IPowerManagement GetPowerManagement(); FFMpegInstallInfo GetFfmpegInstallInfo(); + + void LaunchUrl(string url); } } diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index ac1b7ca99..cbf7d298c 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -317,7 +317,7 @@ namespace MediaBrowser.ServerApplication { if (e.Reason == SessionSwitchReason.SessionLogon) { - BrowserLauncher.OpenDashboard(_appHost, _logger); + BrowserLauncher.OpenDashboard(_appHost); } } diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 146a4372b..34f4315de 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -1,13 +1,16 @@ -using MediaBrowser.Common.Net; +using System; +using MediaBrowser.Common.Net; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Startup.Common; using MediaBrowser.ServerApplication.Networking; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; using CommonIO; using MediaBrowser.Controller.Power; using MediaBrowser.Server.Startup.Common.FFMpeg; +using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem; namespace MediaBrowser.ServerApplication.Native { @@ -156,6 +159,42 @@ namespace MediaBrowser.ServerApplication.Native return info; } + public void LaunchUrl(string url) + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = url + }, + + EnableRaisingEvents = true, + }; + + process.Exited += ProcessExited; + + try + { + process.Start(); + } + catch (Exception ex) + { + _logger.ErrorException("Error launching url: {0}", ex, url); + + throw; + } + } + + /// + /// Processes the exited. + /// + /// The sender. + /// The instance containing the event data. + private static void ProcessExited(object sender, EventArgs e) + { + ((Process)sender).Dispose(); + } + private string[] GetDownloadUrls() { switch (Environment.SystemArchitecture) diff --git a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs index 673c6cddd..fbb93b660 100644 --- a/MediaBrowser.ServerApplication/ServerNotifyIcon.cs +++ b/MediaBrowser.ServerApplication/ServerNotifyIcon.cs @@ -163,7 +163,7 @@ namespace MediaBrowser.ServerApplication void notifyIcon1_DoubleClick(object sender, EventArgs e) { - BrowserLauncher.OpenDashboard(_appHost, _logger); + BrowserLauncher.OpenDashboard(_appHost); } private void LocalizeText() @@ -194,17 +194,17 @@ namespace MediaBrowser.ServerApplication void cmdBrowse_Click(object sender, EventArgs e) { - BrowserLauncher.OpenWebClient(_appHost, _logger); + BrowserLauncher.OpenWebClient(_appHost); } void cmdCommunity_Click(object sender, EventArgs e) { - BrowserLauncher.OpenCommunity(_logger); + BrowserLauncher.OpenCommunity(_appHost); } void cmdConfigure_Click(object sender, EventArgs e) { - BrowserLauncher.OpenDashboard(_appHost, _logger); + BrowserLauncher.OpenDashboard(_appHost); } void cmdRestart_Click(object sender, EventArgs e) From 5401641e2b4c0eb35a308a952e5370dd968b9621 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 13:35:49 -0400 Subject: [PATCH 172/852] remove special characters from sort names --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 959334d78..f5fb72de5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -605,7 +605,7 @@ namespace MediaBrowser.Controller.Entities builder.Append(chunkBuilder); } //Logger.Debug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); - return builder.ToString(); + return builder.ToString().RemoveDiacritics(); } [IgnoreDataMember] diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fb655c9cb..fb91a2dd2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 63; + private const int LatestSchemaVersion = 64; /// /// Initializes a new instance of the class. From 21b90bf6e1d6d18f619269f39b6f670f01bbd5a3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 13:35:49 -0400 Subject: [PATCH 173/852] remove special characters from sort names --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Persistence/SqliteItemRepository.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 04371c13b..475e2ace8 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -603,7 +603,7 @@ namespace MediaBrowser.Controller.Entities builder.Append(chunkBuilder); } //Logger.Debug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); - return builder.ToString(); + return builder.ToString().RemoveDiacritics(); } [IgnoreDataMember] diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fb655c9cb..fb91a2dd2 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 63; + private const int LatestSchemaVersion = 64; /// /// Initializes a new instance of the class. From 54e04dd027f75066981524f7db02664b3afed2ab Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 22:16:46 -0400 Subject: [PATCH 174/852] support duration on recording url --- MediaBrowser.Controller/LiveTv/ITunerHost.cs | 2 ++ .../LiveTv/EmbyTV/DirectRecorder.cs | 9 +++++--- .../LiveTv/EmbyTV/EmbyTV.cs | 23 ++++++++++++++----- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 8 +++++++ .../LiveTv/TunerHosts/M3UTunerHost.cs | 5 ++++ .../LiveTv/TunerHosts/SatIp/SatIpHost.cs | 5 ++++ 6 files changed, 43 insertions(+), 9 deletions(-) diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index 498602ddf..1e7aa3de5 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -46,6 +46,8 @@ namespace MediaBrowser.Controller.LiveTv /// The cancellation token. /// Task<List<MediaSourceInfo>>. Task> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken); + + string ApplyDuration(string streamPath, TimeSpan duration); } public interface IConfigurableTunerHost { diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 3c7ee55b7..98249f5ac 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -42,10 +42,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _logger.Info("Copying recording stream to file {0}", targetFile); - var durationToken = new CancellationTokenSource(duration); - var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + if (!mediaSource.RunTimeTicks.HasValue) + { + var durationToken = new CancellationTokenSource(duration); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } - await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, linkedToken).ConfigureAwait(false); + await response.Content.CopyToAsync(output, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 60ff23b04..d85e8ba3f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -591,7 +591,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV throw new ApplicationException("Tuner not found."); } - private async Task> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) + private async Task> GetChannelStreamInternal(string channelId, string streamId, CancellationToken cancellationToken) { _logger.Info("Streaming Channel " + channelId); @@ -599,7 +599,9 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { try { - return await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false); + var result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false); + + return new Tuple(result.Item1, hostInstance, result.Item2); } catch (Exception e) { @@ -797,8 +799,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV // HDHR doesn't seem to release the tuner right away after first probing with ffmpeg //await Task.Delay(3000, cancellationToken).ConfigureAwait(false); - var duration = recordingEndDate - DateTime.UtcNow; - var recorder = await GetRecorder().ConfigureAwait(false); if (recorder is EncodedRecorder) @@ -816,6 +816,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV recording.DateLastUpdated = DateTime.UtcNow; _recordingProvider.AddOrUpdate(recording); + var duration = recordingEndDate - DateTime.UtcNow; + _logger.Info("Beginning recording. Will record for {0} minutes.", duration.TotalMinutes.ToString(CultureInfo.InvariantCulture)); _logger.Info("Writing file to path: " + recordPath); @@ -823,10 +825,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV Action onStarted = () => { - result.Item2.Release(); + result.Item3.Release(); isResourceOpen = false; }; + var pathWithDuration = result.Item2.ApplyDuration(mediaStreamInfo.Path, duration); + + // If it supports supplying duration via url + if (!string.Equals(pathWithDuration, mediaStreamInfo.Path, StringComparison.OrdinalIgnoreCase)) + { + mediaStreamInfo.Path = pathWithDuration; + mediaStreamInfo.RunTimeTicks = duration.Ticks; + } + await recorder.Record(mediaStreamInfo, recordPath, duration, onStarted, cancellationToken).ConfigureAwait(false); recording.Status = RecordingStatus.Completed; @@ -836,7 +847,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { if (isResourceOpen) { - result.Item2.Release(); + result.Item3.Release(); } _libraryMonitor.ReportFileSystemChangeComplete(recordPath, false); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 469767c65..a3e5589e8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -59,6 +59,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun return id; } + public string ApplyDuration(string streamPath, TimeSpan duration) + { + streamPath += streamPath.IndexOf('?') == -1 ? "?" : "&"; + streamPath += "duration=" + Convert.ToInt32(duration.TotalSeconds).ToString(CultureInfo.InvariantCulture); + + return streamPath; + } + private async Task> GetLineup(TunerHostInfo info, CancellationToken cancellationToken) { var options = new HttpRequestOptions diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 523f14dfc..c874e51b6 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -146,5 +146,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts { return Task.FromResult(true); } + + public string ApplyDuration(string streamPath, TimeSpan duration) + { + return streamPath; + } } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs index ffd85fd18..1e571c84f 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/SatIp/SatIpHost.cs @@ -164,5 +164,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp return list; } + + public string ApplyDuration(string streamPath, TimeSpan duration) + { + return streamPath; + } } } From 69622a74a8c60f60d9859de8d247bcbe488e68d3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 23:39:21 -0400 Subject: [PATCH 175/852] faster cleanup of missing episodes --- .../Library/ILibraryManager.cs | 30 +++-- .../TV/MissingEpisodeProvider.cs | 18 ++- .../TV/SeriesPostScanTask.cs | 127 ++++++++++++++++-- .../Library/LibraryManager.cs | 3 + 4 files changed, 151 insertions(+), 27 deletions(-) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index c8b3d5131..0f6b10b43 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Controller.Library /// The file information. /// The parent. /// BaseItem. - BaseItem ResolvePath(FileSystemMetadata fileInfo, + BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null); /// @@ -36,9 +36,9 @@ namespace MediaBrowser.Controller.Library /// The parent. /// Type of the collection. /// List{``0}. - IEnumerable ResolvePaths(IEnumerable files, + IEnumerable ResolvePaths(IEnumerable files, IDirectoryService directoryService, - Folder parent, string + Folder parent, string collectionType = null); /// @@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Library /// The path. /// BaseItem. BaseItem FindByPath(string path); - + /// /// Gets the artist. /// @@ -156,7 +156,7 @@ namespace MediaBrowser.Controller.Library /// The identifier. /// BaseItem. BaseItem GetMemoryItemById(Guid id); - + /// /// Gets the intros. /// @@ -243,6 +243,8 @@ namespace MediaBrowser.Controller.Library /// BaseItem. BaseItem RetrieveItem(Guid id); + bool IsScanRunning { get; } + /// /// Occurs when [item added]. /// @@ -290,7 +292,7 @@ namespace MediaBrowser.Controller.Library /// The path. /// System.String. string GetConfiguredContentType(string path); - + /// /// Normalizes the root path list. /// @@ -332,8 +334,8 @@ namespace MediaBrowser.Controller.Library Task GetNamedView(User user, string name, string parentId, - string viewType, - string sortName, + string viewType, + string sortName, CancellationToken cancellationToken); /// @@ -346,8 +348,8 @@ namespace MediaBrowser.Controller.Library /// The cancellation token. /// Task<UserView>. Task GetNamedView(User user, - string name, - string viewType, + string name, + string viewType, string sortName, CancellationToken cancellationToken); @@ -393,7 +395,7 @@ namespace MediaBrowser.Controller.Library string viewType, string sortName, CancellationToken cancellationToken); - + /// /// Determines whether [is video file] [the specified path]. /// @@ -477,14 +479,14 @@ namespace MediaBrowser.Controller.Library /// The query. /// List<PersonInfo>. List GetPeople(InternalPeopleQuery query); - + /// /// Gets the people items. /// /// The query. /// List<Person>. List GetPeopleItems(InternalPeopleQuery query); - + /// /// Gets all people names. /// @@ -559,7 +561,7 @@ namespace MediaBrowser.Controller.Library /// The query. /// QueryResult<BaseItem>. QueryResult GetItemsResult(InternalItemsQuery query); - + /// /// Ignores the file. /// diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index ad55c186a..8ae9aa5bb 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -27,6 +27,8 @@ namespace MediaBrowser.Providers.TV private readonly IFileSystem _fileSystem; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private static readonly SemaphoreSlim _resourceLock = new SemaphoreSlim(1, 1); + public static bool IsRunning = false; public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, IFileSystem fileSystem) { @@ -37,13 +39,16 @@ namespace MediaBrowser.Providers.TV _fileSystem = fileSystem; } - public async Task Run(IEnumerable> series, CancellationToken cancellationToken) + public async Task Run(List> series, bool addNewItems, CancellationToken cancellationToken) { + await _resourceLock.WaitAsync(cancellationToken).ConfigureAwait(false); + IsRunning = true; + foreach (var seriesGroup in series) { try { - await Run(seriesGroup, cancellationToken).ConfigureAwait(false); + await Run(seriesGroup, addNewItems, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -58,9 +63,12 @@ namespace MediaBrowser.Providers.TV _logger.ErrorException("Error in missing episode provider for series id {0}", ex, seriesGroup.Key); } } + + IsRunning = false; + _resourceLock.Release(); } - private async Task Run(IGrouping group, CancellationToken cancellationToken) + private async Task Run(IGrouping group, bool addNewItems, CancellationToken cancellationToken) { var tvdbId = group.Key; @@ -110,7 +118,7 @@ namespace MediaBrowser.Providers.TV var hasNewEpisodes = false; - if (_config.Configuration.EnableInternetProviders) + if (_config.Configuration.EnableInternetProviders && addNewItems) { var seriesConfig = _config.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, typeof(Series).Name, StringComparison.OrdinalIgnoreCase)); @@ -427,7 +435,7 @@ namespace MediaBrowser.Providers.TV await season.AddChild(episode, cancellationToken).ConfigureAwait(false); - await episode.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) + await episode.RefreshMetadata(new MetadataRefreshOptions(_fileSystem) { }, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs index 5428e6c92..0fd6fa56f 100644 --- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs +++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs @@ -11,6 +11,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MediaBrowser.Common.ScheduledTasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Model.Tasks; namespace MediaBrowser.Providers.TV { @@ -46,14 +50,17 @@ namespace MediaBrowser.Providers.TV private async Task RunInternal(IProgress progress, CancellationToken cancellationToken) { - var seriesList = _libraryManager.RootFolder - .GetRecursiveChildren(i => i is Series) - .Cast() - .ToList(); + var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() + { + IncludeItemTypes = new[] { typeof(Series).Name }, + Recursive = true + + }).Cast().ToList(); var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); - await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem).Run(seriesGroups, cancellationToken).ConfigureAwait(false); + await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem) + .Run(seriesGroups, true, cancellationToken).ConfigureAwait(false); var numComplete = 0; @@ -82,7 +89,7 @@ namespace MediaBrowser.Providers.TV } } - private IEnumerable> FindSeriesGroups(List seriesList) + internal static IEnumerable> FindSeriesGroups(List seriesList) { var links = seriesList.ToDictionary(s => s, s => seriesList.Where(c => c != s && ShareProviderId(s, c)).ToList()); @@ -102,7 +109,7 @@ namespace MediaBrowser.Providers.TV } } - private void FindAllLinked(Series series, HashSet visited, IDictionary> linksMap, List results) + private static void FindAllLinked(Series series, HashSet visited, IDictionary> linksMap, List results) { results.Add(series); visited.Add(series); @@ -118,7 +125,7 @@ namespace MediaBrowser.Providers.TV } } - private bool ShareProviderId(Series a, Series b) + private static bool ShareProviderId(Series a, Series b) { return a.ProviderIds.Any(id => { @@ -137,4 +144,108 @@ namespace MediaBrowser.Providers.TV } } + public class CleanMissingEpisodesEntryPoint : IServerEntryPoint + { + private readonly ILibraryManager _libraryManager; + private readonly IServerConfigurationManager _config; + private readonly ILogger _logger; + private readonly ILocalizationManager _localization; + private readonly IFileSystem _fileSystem; + private readonly object _libraryChangedSyncLock = new object(); + private const int LibraryUpdateDuration = 180000; + private readonly ITaskManager _taskManager; + + public CleanMissingEpisodesEntryPoint(ILibraryManager libraryManager, IServerConfigurationManager config, ILogger logger, ILocalizationManager localization, IFileSystem fileSystem, ITaskManager taskManager) + { + _libraryManager = libraryManager; + _config = config; + _logger = logger; + _localization = localization; + _fileSystem = fileSystem; + _taskManager = taskManager; + } + + private Timer LibraryUpdateTimer { get; set; } + + public void Run() + { + _libraryManager.ItemAdded += _libraryManager_ItemAdded; + } + + private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) + { + if (!FilterItem(e.Item)) + { + return; + } + + lock (_libraryChangedSyncLock) + { + if (LibraryUpdateTimer == null) + { + LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite); + } + else + { + LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); + } + } + } + + private async void LibraryUpdateTimerCallback(object state) + { + if (MissingEpisodeProvider.IsRunning) + { + return; + } + + if (_libraryManager.IsScanRunning) + { + return ; + } + + var seriesList = _libraryManager.GetItemList(new InternalItemsQuery() + { + IncludeItemTypes = new[] { typeof(Series).Name }, + Recursive = true + + }).Cast().ToList(); + + var seriesGroups = SeriesPostScanTask.FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList(); + + await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization, _fileSystem) + .Run(seriesGroups, false, CancellationToken.None).ConfigureAwait(false); + } + + private bool FilterItem(BaseItem item) + { + return item is Episode && item.LocationType != LocationType.Virtual; + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + if (LibraryUpdateTimer != null) + { + LibraryUpdateTimer.Dispose(); + LibraryUpdateTimer = null; + } + + _libraryManager.ItemAdded -= _libraryManager_ItemAdded; + } + } + } } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index ccba293a3..17c4f59ba 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -143,6 +143,7 @@ namespace MediaBrowser.Server.Implementations.Library private readonly Func _libraryMonitorFactory; private readonly Func _providerManagerFactory; private readonly Func _userviewManager; + public bool IsScanRunning { get; private set; } /// /// The _library items cache @@ -1102,6 +1103,7 @@ namespace MediaBrowser.Server.Implementations.Library /// Task. public async Task ValidateMediaLibraryInternal(IProgress progress, CancellationToken cancellationToken) { + IsScanRunning = true; _libraryMonitorFactory().Stop(); try @@ -1111,6 +1113,7 @@ namespace MediaBrowser.Server.Implementations.Library finally { _libraryMonitorFactory().Start(); + IsScanRunning = false; } } From 2c07de2b55591df4de7e807c0663b09783f8d0d1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 23:54:24 -0400 Subject: [PATCH 176/852] 3.0.5944 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ab45a122c..654ff7197 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5943")] +[assembly: AssemblyVersion("3.0.5944")] From 0ace5b38c353781b056e17191b00df714594ec8f Mon Sep 17 00:00:00 2001 From: nfnty Date: Tue, 26 Apr 2016 10:26:41 +0200 Subject: [PATCH 177/852] Use HTTPS for API requests: Fix missed URLs --- MediaBrowser.Controller/Library/TVUtils.cs | 2 +- MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs | 2 +- MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index f8039b2cf..29421ebaf 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Library /// /// The banner URL /// - public static readonly string BannerUrl = "http://www.thetvdb.com/banners/"; + public static readonly string BannerUrl = "https://www.thetvdb.com/banners/"; /// /// Gets the air days. diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 75b5498c5..d020a73fe 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -662,7 +662,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers { if (!string.IsNullOrWhiteSpace(val)) { - val = val.Replace("plugin://plugin.video.youtube/?action=play_video&videoid=", "http://www.youtube.com/watch?v=", StringComparison.OrdinalIgnoreCase); + val = val.Replace("plugin://plugin.video.youtube/?action=play_video&videoid=", "https://www.youtube.com/watch?v=", StringComparison.OrdinalIgnoreCase); hasTrailer.AddTrailerUrl(val, false); } diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index e37b83f4b..6d15d168d 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -889,7 +889,7 @@ namespace MediaBrowser.XbmcMetadata.Savers { // This is what xbmc expects - return url.Replace("http://www.youtube.com/watch?v=", + return url.Replace("https://www.youtube.com/watch?v=", "plugin://plugin.video.youtube/?action=play_video&videoid=", StringComparison.OrdinalIgnoreCase); } From c40bf00587d08d606f7af96f303272416b6e3ef8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Apr 2016 14:28:04 -0400 Subject: [PATCH 178/852] unify guide between web and theater --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 7565c8dfb..5534b95a9 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -230,12 +230,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest From c2a1ab66df7eddef118c17568134c9c88349a50e Mon Sep 17 00:00:00 2001 From: anderbytes Date: Tue, 26 Apr 2016 23:51:05 -0300 Subject: [PATCH 179/852] Collection meta-fetch fallback condition update With this change I propose that english metadata from collection (fallback situation) occurs when a collection NAME is missing, instead of OVERVIEW (description). This means a translated collection that has the vital information such as name will be sufficient to be used... not forcing Emby to download english data (with the non-translated title and overview) just because the translated version has an empty overview. I took a while to understand why some of my collections weren't downloading their translated versions from provider. I traced the problem to this... the ones who had overview were pulled in, the ones who hadn't Emby used the fallback (easily seen in the logs). --- MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index a280a897a..74e668754 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -190,7 +190,7 @@ namespace MediaBrowser.Providers.BoxSets cancellationToken.ThrowIfCancellationRequested(); - if (mainResult != null && string.IsNullOrEmpty(mainResult.overview)) + if (mainResult != null && string.IsNullOrEmpty(mainResult.name)) { if (!string.IsNullOrEmpty(language) && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { From 371cbc0c1d712b702d5a792a0f2ddb05dbe7af2d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 26 Apr 2016 22:59:43 -0400 Subject: [PATCH 180/852] support headroom with guide --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../EntryPoints/Notifications/Notifications.cs | 12 ++++++++++++ .../MediaBrowser.WebDashboard.csproj | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f5fb72de5..f9f03a9c5 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1546,7 +1546,7 @@ namespace MediaBrowser.Controller.Entities if (itemByPath == null) { - Logger.Warn("Unable to find linked item at path {0}", info.Path); + //Logger.Warn("Unable to find linked item at path {0}", info.Path); } return itemByPath; diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs index 71019e0ad..e84b66c5a 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs @@ -215,6 +215,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications return; } + var video = e.Item as Video; + if (video != null && video.IsThemeMedia) + { + return; + } + var type = GetPlaybackNotificationType(item.MediaType); SendPlaybackNotification(type, e); @@ -230,6 +236,12 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications return; } + var video = e.Item as Video; + if (video != null && video.IsThemeMedia) + { + return; + } + var type = GetPlaybackStoppedNotificationType(item.MediaType); SendPlaybackNotification(type, e); diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 5534b95a9..bfa4995cf 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1712,6 +1712,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 8dc68a609efc7f9a07e74a855724b04b7cab80e8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 00:04:27 -0400 Subject: [PATCH 181/852] 3.0.5932 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 113d73899..152434162 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5931")] +[assembly: AssemblyVersion("3.0.5932")] From 8499183d77a5351e4dd0a9b200b8f82a6d303fe7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:43:09 -0400 Subject: [PATCH 182/852] update SearchEngine --- .../Library/SearchEngine.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 61a5d98a3..e271fbcb2 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -87,13 +87,16 @@ namespace MediaBrowser.Server.Implementations.Library { var searchTerm = query.SearchTerm; + if (searchTerm != null) + { + searchTerm = searchTerm.Trim().RemoveDiacritics(); + } + if (string.IsNullOrWhiteSpace(searchTerm)) { throw new ArgumentNullException("searchTerm"); } - searchTerm = searchTerm.Trim().RemoveDiacritics(); - var terms = GetWords(searchTerm); var hints = new List>(); From 50e29476f7d2d345e827b131871d290056730815 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:50:32 -0400 Subject: [PATCH 183/852] fix rating filters --- MediaBrowser.Api/Reports/ReportsService.cs | 6 +++--- MediaBrowser.Api/UserLibrary/ItemsService.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Api/Reports/ReportsService.cs b/MediaBrowser.Api/Reports/ReportsService.cs index c3af09cd5..cb1615826 100644 --- a/MediaBrowser.Api/Reports/ReportsService.cs +++ b/MediaBrowser.Api/Reports/ReportsService.cs @@ -326,15 +326,15 @@ namespace MediaBrowser.Api.Reports } // Min official rating - if (!string.IsNullOrEmpty(request.MinOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MinOfficialRating)) { query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); } // Max official rating - if (!string.IsNullOrEmpty(request.MaxOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MaxOfficialRating)) { - query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); + query.MaxParentalRating = _localization.GetRatingLevel(request.MaxOfficialRating); } // Artists diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index cfdc40bb2..7d2029cab 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -308,15 +308,15 @@ namespace MediaBrowser.Api.UserLibrary } // Min official rating - if (!string.IsNullOrEmpty(request.MinOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MinOfficialRating)) { query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); } // Max official rating - if (!string.IsNullOrEmpty(request.MaxOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MaxOfficialRating)) { - query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); + query.MaxParentalRating = _localization.GetRatingLevel(request.MaxOfficialRating); } // Artists From 64f51a3643a32bf21586b5b5e075802787868560 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:52:43 -0400 Subject: [PATCH 184/852] update IsFolder sorting --- .../Persistence/SqliteItemRepository.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fb91a2dd2..fcc39deb5 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1574,6 +1574,10 @@ namespace MediaBrowser.Server.Implementations.Persistence { return "RuntimeTicks"; } + if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) + { + return "IsFolder"; + } if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) { return "RANDOM()"; From 1e16ac9f2ac0cdc8833f2e53540a942876a3e979 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:52:56 -0400 Subject: [PATCH 185/852] add missing localization text --- .../Localization/Core/en-US.json | 353 +++++++++--------- 1 file changed, 177 insertions(+), 176 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json index 0d5b5c4aa..5e2f98c09 100644 --- a/MediaBrowser.Server.Implementations/Localization/Core/en-US.json +++ b/MediaBrowser.Server.Implementations/Localization/Core/en-US.json @@ -1,178 +1,179 @@ { - "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", - "AppDeviceValues": "App: {0}, Device: {1}", - "UserDownloadingItemWithValues": "{0} is downloading {1}", - "FolderTypeMixed": "Mixed content", - "FolderTypeMovies": "Movies", - "FolderTypeMusic": "Music", - "FolderTypeAdultVideos": "Adult videos", - "FolderTypePhotos": "Photos", - "FolderTypeMusicVideos": "Music videos", - "FolderTypeHomeVideos": "Home videos", - "FolderTypeGames": "Games", - "FolderTypeBooks": "Books", - "FolderTypeTvShows": "TV", - "FolderTypeInherit": "Inherit", - "HeaderCastCrew": "Cast & Crew", - "HeaderPeople": "People", - "ValueSpecialEpisodeName": "Special - {0}", - "LabelChapterName": "Chapter {0}", - "NameSeasonNumber": "Season {0}", - "LabelExit": "Exit", - "LabelVisitCommunity": "Visit Community", - "LabelGithub": "Github", - "LabelApiDocumentation": "Api Documentation", - "LabelDeveloperResources": "Developer Resources", - "LabelBrowseLibrary": "Browse Library", - "LabelConfigureServer": "Configure Emby", - "LabelRestartServer": "Restart Server", - "CategorySync": "Sync", - "CategoryUser": "User", - "CategorySystem": "System", - "CategoryApplication": "Application", - "CategoryPlugin": "Plugin", - "NotificationOptionPluginError": "Plugin failure", - "NotificationOptionApplicationUpdateAvailable": "Application update available", - "NotificationOptionApplicationUpdateInstalled": "Application update installed", - "NotificationOptionPluginUpdateInstalled": "Plugin update installed", - "NotificationOptionPluginInstalled": "Plugin installed", - "NotificationOptionPluginUninstalled": "Plugin uninstalled", - "NotificationOptionVideoPlayback": "Video playback started", - "NotificationOptionAudioPlayback": "Audio playback started", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionVideoPlaybackStopped": "Video playback stopped", - "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", - "NotificationOptionTaskFailed": "Scheduled task failure", - "NotificationOptionInstallationFailed": "Installation failure", - "NotificationOptionNewLibraryContent": "New content added", - "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", - "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionUserLockedOut": "User locked out", - "NotificationOptionServerRestartRequired": "Server restart required", - "ViewTypePlaylists": "Playlists", - "ViewTypeMovies": "Movies", - "ViewTypeTvShows": "TV", - "ViewTypeGames": "Games", - "ViewTypeMusic": "Music", - "ViewTypeMusicGenres": "Genres", - "ViewTypeMusicArtists": "Artists", - "ViewTypeBoxSets": "Collections", - "ViewTypeChannels": "Channels", - "ViewTypeLiveTV": "Live TV", - "ViewTypeLiveTvNowPlaying": "Now Airing", - "ViewTypeLatestGames": "Latest Games", - "ViewTypeRecentlyPlayedGames": "Recently Played", - "ViewTypeGameFavorites": "Favorites", - "ViewTypeGameSystems": "Game Systems", - "ViewTypeGameGenres": "Genres", - "ViewTypeTvResume": "Resume", - "ViewTypeTvNextUp": "Next Up", - "ViewTypeTvLatest": "Latest", - "ViewTypeTvShowSeries": "Series", - "ViewTypeTvGenres": "Genres", - "ViewTypeTvFavoriteSeries": "Favorite Series", - "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", - "ViewTypeMovieResume": "Resume", - "ViewTypeMovieLatest": "Latest", - "ViewTypeMovieMovies": "Movies", - "ViewTypeMovieCollections": "Collections", - "ViewTypeMovieFavorites": "Favorites", - "ViewTypeMovieGenres": "Genres", - "ViewTypeMusicLatest": "Latest", - "ViewTypeMusicPlaylists": "Playlists", - "ViewTypeMusicAlbums": "Albums", - "ViewTypeMusicAlbumArtists": "Album Artists", - "HeaderOtherDisplaySettings": "Display Settings", - "ViewTypeMusicSongs": "Songs", - "ViewTypeMusicFavorites": "Favorites", - "ViewTypeMusicFavoriteAlbums": "Favorite Albums", - "ViewTypeMusicFavoriteArtists": "Favorite Artists", - "ViewTypeMusicFavoriteSongs": "Favorite Songs", - "ViewTypeFolders": "Folders", - "ViewTypeLiveTvRecordingGroups": "Recordings", - "ViewTypeLiveTvChannels": "Channels", - "ScheduledTaskFailedWithName": "{0} failed", - "LabelRunningTimeValue": "Running time: {0}", - "ScheduledTaskStartedWithName": "{0} started", - "VersionNumber": "Version {0}", - "PluginInstalledWithName": "{0} was installed", - "PluginUpdatedWithName": "{0} was updated", - "PluginUninstalledWithName": "{0} was uninstalled", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", - "DeviceOnlineWithName": "{0} is connected", - "UserOnlineFromDevice": "{0} is online from {1}", - "ProviderValue": "Provider: {0}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", - "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", - "UserCreatedWithName": "User {0} has been created", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserDeletedWithName": "User {0} has been deleted", - "MessageServerConfigurationUpdated": "Server configuration has been updated", - "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", - "MessageApplicationUpdated": "Emby Server has been updated", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", - "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "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}", - "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "HeaderUnidentified": "Unidentified", - "HeaderImagePrimary": "Primary", - "HeaderImageBackdrop": "Backdrop", - "HeaderImageLogo": "Logo", - "HeaderUserPrimaryImage": "User Image", - "HeaderOverview": "Overview", - "HeaderShortOverview": "Short Overview", - "HeaderType": "Type", - "HeaderSeverity": "Severity", - "HeaderUser": "User", - "HeaderName": "Name", - "HeaderDate": "Date", - "HeaderPremiereDate": "Premiere Date", - "HeaderDateAdded": "Date Added", - "HeaderReleaseDate": "Release date", - "HeaderRuntime": "Runtime", - "HeaderPlayCount": "Play Count", - "HeaderSeason": "Season", - "HeaderSeasonNumber": "Season number", - "HeaderSeries": "Series:", - "HeaderNetwork": "Network", - "HeaderYear": "Year:", - "HeaderYears": "Years:", - "HeaderParentalRating": "Parental Rating", - "HeaderCommunityRating": "Community rating", - "HeaderTrailers": "Trailers", - "HeaderSpecials": "Specials", - "HeaderGameSystems": "Game Systems", - "HeaderPlayers": "Players:", - "HeaderAlbumArtists": "Album Artists", - "HeaderAlbums": "Albums", - "HeaderDisc": "Disc", - "HeaderTrack": "Track", - "HeaderAudio": "Audio", - "HeaderVideo": "Video", - "HeaderEmbeddedImage": "Embedded image", - "HeaderResolution": "Resolution", - "HeaderSubtitles": "Subtitles", - "HeaderGenres": "Genres", - "HeaderCountries": "Countries", - "HeaderStatus": "Status", - "HeaderTracks": "Tracks", - "HeaderMusicArtist": "Music artist", - "HeaderLocked": "Locked", - "HeaderStudios": "Studios", - "HeaderActor": "Actors", - "HeaderComposer": "Composers", - "HeaderDirector": "Directors", - "HeaderGuestStar": "Guest star", - "HeaderProducer": "Producers", - "HeaderWriter": "Writers", - "HeaderParentalRatings": "Parental Ratings", - "HeaderCommunityRatings": "Community ratings", - "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." + "DbUpgradeMessage": "Please wait while your Emby Server database is upgraded. {0}% complete.", + "AppDeviceValues": "App: {0}, Device: {1}", + "UserDownloadingItemWithValues": "{0} is downloading {1}", + "FolderTypeMixed": "Mixed content", + "FolderTypeMovies": "Movies", + "FolderTypeMusic": "Music", + "FolderTypeAdultVideos": "Adult videos", + "FolderTypePhotos": "Photos", + "FolderTypeMusicVideos": "Music videos", + "FolderTypeHomeVideos": "Home videos", + "FolderTypeGames": "Games", + "FolderTypeBooks": "Books", + "FolderTypeTvShows": "TV", + "FolderTypeInherit": "Inherit", + "HeaderCastCrew": "Cast & Crew", + "HeaderPeople": "People", + "ValueSpecialEpisodeName": "Special - {0}", + "LabelChapterName": "Chapter {0}", + "NameSeasonUnknown": "Season Unknown", + "NameSeasonNumber": "Season {0}", + "LabelExit": "Exit", + "LabelVisitCommunity": "Visit Community", + "LabelGithub": "Github", + "LabelApiDocumentation": "Api Documentation", + "LabelDeveloperResources": "Developer Resources", + "LabelBrowseLibrary": "Browse Library", + "LabelConfigureServer": "Configure Emby", + "LabelRestartServer": "Restart Server", + "CategorySync": "Sync", + "CategoryUser": "User", + "CategorySystem": "System", + "CategoryApplication": "Application", + "CategoryPlugin": "Plugin", + "NotificationOptionPluginError": "Plugin failure", + "NotificationOptionApplicationUpdateAvailable": "Application update available", + "NotificationOptionApplicationUpdateInstalled": "Application update installed", + "NotificationOptionPluginUpdateInstalled": "Plugin update installed", + "NotificationOptionPluginInstalled": "Plugin installed", + "NotificationOptionPluginUninstalled": "Plugin uninstalled", + "NotificationOptionVideoPlayback": "Video playback started", + "NotificationOptionAudioPlayback": "Audio playback started", + "NotificationOptionGamePlayback": "Game playback started", + "NotificationOptionVideoPlaybackStopped": "Video playback stopped", + "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", + "NotificationOptionGamePlaybackStopped": "Game playback stopped", + "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionInstallationFailed": "Installation failure", + "NotificationOptionNewLibraryContent": "New content added", + "NotificationOptionNewLibraryContentMultiple": "New content added (multiple)", + "NotificationOptionCameraImageUploaded": "Camera image uploaded", + "NotificationOptionUserLockedOut": "User locked out", + "NotificationOptionServerRestartRequired": "Server restart required", + "ViewTypePlaylists": "Playlists", + "ViewTypeMovies": "Movies", + "ViewTypeTvShows": "TV", + "ViewTypeGames": "Games", + "ViewTypeMusic": "Music", + "ViewTypeMusicGenres": "Genres", + "ViewTypeMusicArtists": "Artists", + "ViewTypeBoxSets": "Collections", + "ViewTypeChannels": "Channels", + "ViewTypeLiveTV": "Live TV", + "ViewTypeLiveTvNowPlaying": "Now Airing", + "ViewTypeLatestGames": "Latest Games", + "ViewTypeRecentlyPlayedGames": "Recently Played", + "ViewTypeGameFavorites": "Favorites", + "ViewTypeGameSystems": "Game Systems", + "ViewTypeGameGenres": "Genres", + "ViewTypeTvResume": "Resume", + "ViewTypeTvNextUp": "Next Up", + "ViewTypeTvLatest": "Latest", + "ViewTypeTvShowSeries": "Series", + "ViewTypeTvGenres": "Genres", + "ViewTypeTvFavoriteSeries": "Favorite Series", + "ViewTypeTvFavoriteEpisodes": "Favorite Episodes", + "ViewTypeMovieResume": "Resume", + "ViewTypeMovieLatest": "Latest", + "ViewTypeMovieMovies": "Movies", + "ViewTypeMovieCollections": "Collections", + "ViewTypeMovieFavorites": "Favorites", + "ViewTypeMovieGenres": "Genres", + "ViewTypeMusicLatest": "Latest", + "ViewTypeMusicPlaylists": "Playlists", + "ViewTypeMusicAlbums": "Albums", + "ViewTypeMusicAlbumArtists": "Album Artists", + "HeaderOtherDisplaySettings": "Display Settings", + "ViewTypeMusicSongs": "Songs", + "ViewTypeMusicFavorites": "Favorites", + "ViewTypeMusicFavoriteAlbums": "Favorite Albums", + "ViewTypeMusicFavoriteArtists": "Favorite Artists", + "ViewTypeMusicFavoriteSongs": "Favorite Songs", + "ViewTypeFolders": "Folders", + "ViewTypeLiveTvRecordingGroups": "Recordings", + "ViewTypeLiveTvChannels": "Channels", + "ScheduledTaskFailedWithName": "{0} failed", + "LabelRunningTimeValue": "Running time: {0}", + "ScheduledTaskStartedWithName": "{0} started", + "VersionNumber": "Version {0}", + "PluginInstalledWithName": "{0} was installed", + "PluginUpdatedWithName": "{0} was updated", + "PluginUninstalledWithName": "{0} was uninstalled", + "ItemAddedWithName": "{0} was added to the library", + "ItemRemovedWithName": "{0} was removed from the library", + "LabelIpAddressValue": "Ip address: {0}", + "DeviceOnlineWithName": "{0} is connected", + "UserOnlineFromDevice": "{0} is online from {1}", + "ProviderValue": "Provider: {0}", + "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", + "UserConfigurationUpdatedWithName": "User configuration has been updated for {0}", + "UserCreatedWithName": "User {0} has been created", + "UserPasswordChangedWithName": "Password has been changed for user {0}", + "UserDeletedWithName": "User {0} has been deleted", + "MessageServerConfigurationUpdated": "Server configuration has been updated", + "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated", + "MessageApplicationUpdated": "Emby Server has been updated", + "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", + "AuthenticationSucceededWithUserName": "{0} successfully authenticated", + "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}", + "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", + "HeaderUnidentified": "Unidentified", + "HeaderImagePrimary": "Primary", + "HeaderImageBackdrop": "Backdrop", + "HeaderImageLogo": "Logo", + "HeaderUserPrimaryImage": "User Image", + "HeaderOverview": "Overview", + "HeaderShortOverview": "Short Overview", + "HeaderType": "Type", + "HeaderSeverity": "Severity", + "HeaderUser": "User", + "HeaderName": "Name", + "HeaderDate": "Date", + "HeaderPremiereDate": "Premiere Date", + "HeaderDateAdded": "Date Added", + "HeaderReleaseDate": "Release date", + "HeaderRuntime": "Runtime", + "HeaderPlayCount": "Play Count", + "HeaderSeason": "Season", + "HeaderSeasonNumber": "Season number", + "HeaderSeries": "Series:", + "HeaderNetwork": "Network", + "HeaderYear": "Year:", + "HeaderYears": "Years:", + "HeaderParentalRating": "Parental Rating", + "HeaderCommunityRating": "Community rating", + "HeaderTrailers": "Trailers", + "HeaderSpecials": "Specials", + "HeaderGameSystems": "Game Systems", + "HeaderPlayers": "Players:", + "HeaderAlbumArtists": "Album Artists", + "HeaderAlbums": "Albums", + "HeaderDisc": "Disc", + "HeaderTrack": "Track", + "HeaderAudio": "Audio", + "HeaderVideo": "Video", + "HeaderEmbeddedImage": "Embedded image", + "HeaderResolution": "Resolution", + "HeaderSubtitles": "Subtitles", + "HeaderGenres": "Genres", + "HeaderCountries": "Countries", + "HeaderStatus": "Status", + "HeaderTracks": "Tracks", + "HeaderMusicArtist": "Music artist", + "HeaderLocked": "Locked", + "HeaderStudios": "Studios", + "HeaderActor": "Actors", + "HeaderComposer": "Composers", + "HeaderDirector": "Directors", + "HeaderGuestStar": "Guest star", + "HeaderProducer": "Producers", + "HeaderWriter": "Writers", + "HeaderParentalRatings": "Parental Ratings", + "HeaderCommunityRatings": "Community ratings", + "StartupEmbyServerIsLoading": "Emby Server is loading. Please try again shortly." } \ No newline at end of file From 6c62c20a9e3081950bf46fc96966e470ffc73b54 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:53:23 -0400 Subject: [PATCH 186/852] update CollectionFolder --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 +- .../Entities/CollectionFolder.cs | 27 ++++++++++++++++--- .../Library/ILibraryManager.cs | 2 +- .../IO/LibraryMonitor.cs | 2 +- .../Library/LibraryManager.cs | 5 ++-- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f9f03a9c5..908d65977 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1542,7 +1542,7 @@ namespace MediaBrowser.Controller.Entities { if (!string.IsNullOrEmpty(info.Path)) { - var itemByPath = LibraryManager.FindByPath(info.Path); + var itemByPath = LibraryManager.FindByPath(info.Path, null); if (itemByPath == null) { diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 429700327..5e0cf6e88 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -8,6 +8,7 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using CommonIO; +using MoreLinq; namespace MediaBrowser.Controller.Entities { @@ -97,7 +98,6 @@ namespace MediaBrowser.Controller.Entities } } - return base.IsValidFromResolver(newItem); } @@ -200,9 +200,30 @@ namespace MediaBrowser.Controller.Entities public IEnumerable GetPhysicalParents() { - return LibraryManager.RootFolder.Children + var rootChildren = LibraryManager.RootFolder.Children .OfType() - .Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase)); + .ToList(); + + return PhysicalLocations.Where(i => !string.Equals(i, Path, StringComparison.OrdinalIgnoreCase)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id); + } + + private IEnumerable GetPhysicalParents(string path, List rootChildren) + { + var result = rootChildren + .Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase)) + .ToList(); + + if (result.Count == 0) + { + var folder = LibraryManager.FindByPath(path, true) as Folder; + + if (folder != null) + { + result.Add(folder); + } + } + + return result; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 0f6b10b43..5388b8668 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Controller.Library /// /// The path. /// BaseItem. - BaseItem FindByPath(string path); + BaseItem FindByPath(string path, bool? isFolder); /// /// Gets the artist. diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs index 13a06afc2..09ca134d1 100644 --- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs +++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs @@ -663,7 +663,7 @@ namespace MediaBrowser.Server.Implementations.IO while (item == null && !string.IsNullOrEmpty(path)) { - item = LibraryManager.FindByPath(path); + item = LibraryManager.FindByPath(path, null); path = Path.GetDirectoryName(path); } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 17c4f59ba..e1bcfa861 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -801,11 +801,12 @@ namespace MediaBrowser.Server.Implementations.Library return _userRootFolder; } - public BaseItem FindByPath(string path) + public BaseItem FindByPath(string path, bool? isFolder) { var query = new InternalItemsQuery { - Path = path + Path = path, + IsFolder = isFolder }; // Only use the database result if there's exactly one item, otherwise we run the risk of returning old data that hasn't been cleaned yet. From 34b72a98cffe9247711f681a31344a56d6c4b912 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 14:10:59 -0400 Subject: [PATCH 187/852] improve socket disposal --- MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs | 37 ++++++++++++----------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs index a2eac41ec..5e0baa1f6 100644 --- a/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs +++ b/MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs @@ -109,30 +109,31 @@ namespace MediaBrowser.Dlna.Ssdp var endPoint = new IPEndPoint(localIp, 1900); - var socket = GetMulticastSocket(localIp, endPoint); - - var receiveBuffer = new byte[64000]; - - CreateNotifier(localIp); - - while (!_tokenSource.IsCancellationRequested) + using (var socket = GetMulticastSocket(localIp, endPoint)) { - var receivedBytes = await socket.ReceiveAsync(receiveBuffer, 0, 64000); + var receiveBuffer = new byte[64000]; - if (receivedBytes > 0) + CreateNotifier(localIp); + + while (!_tokenSource.IsCancellationRequested) { - var args = SsdpHelper.ParseSsdpResponse(receiveBuffer); - args.EndPoint = endPoint; - args.LocalEndPoint = new IPEndPoint(localIp, 0); + var receivedBytes = await socket.ReceiveAsync(receiveBuffer, 0, 64000); - if (_ssdpHandler.IgnoreMessage(args, true)) + if (receivedBytes > 0) { - return; + var args = SsdpHelper.ParseSsdpResponse(receiveBuffer); + args.EndPoint = endPoint; + args.LocalEndPoint = new IPEndPoint(localIp, 0); + + if (_ssdpHandler.IgnoreMessage(args, true)) + { + return; + } + + _ssdpHandler.LogMessageReceived(args, true); + + TryCreateDevice(args); } - - _ssdpHandler.LogMessageReceived(args, true); - - TryCreateDevice(args); } } From 92bdbe22b4db258996725d7452e628d8a456f8e2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 14:44:08 -0400 Subject: [PATCH 188/852] disable remember track selections for live channels --- MediaBrowser.Controller/Entities/BaseItem.cs | 9 +++++++++ MediaBrowser.Controller/Entities/IHasUserData.cs | 2 ++ MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 9 +++++++++ .../Library/MediaSourceManager.cs | 14 ++++++++------ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 908d65977..9171c2a71 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1555,6 +1555,15 @@ namespace MediaBrowser.Controller.Entities return null; } + [IgnoreDataMember] + public virtual bool EnableRememberingTrackSelections + { + get + { + return true; + } + } + /// /// Adds a studio to the item /// diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs index 34a820853..faddc3778 100644 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ b/MediaBrowser.Controller/Entities/IHasUserData.cs @@ -20,5 +20,7 @@ namespace MediaBrowser.Controller.Entities /// The user data. /// The user. void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user); + + bool EnableRememberingTrackSelections { get; } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 35b9a1959..2bb6cc182 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -45,6 +45,15 @@ namespace MediaBrowser.Controller.LiveTv set { } } + [IgnoreDataMember] + public override bool EnableRememberingTrackSelections + { + get + { + return false; + } + } + /// /// Gets or sets the number. /// diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 95f5cb0e1..092b797ce 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -269,13 +269,15 @@ namespace MediaBrowser.Server.Implementations.Library { var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); - SetDefaultAudioStreamIndex(source, userData, user); - SetDefaultSubtitleStreamIndex(source, userData, user); + var allowRememberingSelection = item == null || item.EnableRememberingTrackSelections; + + SetDefaultAudioStreamIndex(source, userData, user, allowRememberingSelection); + SetDefaultSubtitleStreamIndex(source, userData, user, allowRememberingSelection); } - private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user) + private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) { - if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None) + if (userData.SubtitleStreamIndex.HasValue && user.Configuration.RememberSubtitleSelections && user.Configuration.SubtitleMode != SubtitlePlaybackMode.None && allowRememberingSelection) { var index = userData.SubtitleStreamIndex.Value; // Make sure the saved index is still valid @@ -304,9 +306,9 @@ namespace MediaBrowser.Server.Implementations.Library user.Configuration.SubtitleMode, audioLangage); } - private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user) + private void SetDefaultAudioStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) { - if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections) + if (userData.AudioStreamIndex.HasValue && user.Configuration.RememberAudioSelections && allowRememberingSelection) { var index = userData.AudioStreamIndex.Value; // Make sure the saved index is still valid From dfa2557874a3023eedb0b67601a8dee80e80683d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 15:23:05 -0400 Subject: [PATCH 189/852] record IsAvc --- .../Playback/BaseStreamingService.cs | 15 +++++++-- .../Encoder/EncodingJobFactory.cs | 8 +++++ .../Probing/ProbeResultNormalizer.cs | 11 +++++++ MediaBrowser.Model/Entities/MediaStream.cs | 2 ++ .../Persistence/MediaStreamColumns.cs | 32 +++++++++++++++++++ .../Persistence/SqliteItemRepository.cs | 11 +++++-- 6 files changed, 74 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 9278de3be..45f1a64c9 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -288,9 +288,9 @@ namespace MediaBrowser.Api.Playback { if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { - - return "h264_qsv"; - + + return "h264_qsv"; + } return "libx264"; @@ -1804,6 +1804,15 @@ namespace MediaBrowser.Api.Playback } } + if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) + { + if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value) + { + Logger.Debug("Cannot stream copy video. Stream is marked as not AVC"); + return false; + } + } + // Source and target codecs must match if (!string.Equals(request.VideoCodec, videoStream.Codec, StringComparison.OrdinalIgnoreCase)) { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index 070aae3a7..ff5a3010e 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -575,6 +575,14 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } + if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) + { + if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value) + { + return false; + } + } + // If client is requesting a specific video profile, it must match the source if (!string.IsNullOrEmpty(request.Profile)) { diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 38528d845..c7c001cee 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -411,6 +411,17 @@ namespace MediaBrowser.MediaEncoding.Probing NalLengthSize = streamInfo.nal_length_size }; + if (string.Equals(streamInfo.is_avc, "true", StringComparison.OrdinalIgnoreCase) || + string.Equals(streamInfo.is_avc, "1", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAVC = true; + } + else if (string.Equals(streamInfo.is_avc, "false", StringComparison.OrdinalIgnoreCase) || + string.Equals(streamInfo.is_avc, "0", StringComparison.OrdinalIgnoreCase)) + { + stream.IsAVC = false; + } + // Filter out junk if (!string.IsNullOrWhiteSpace(streamInfo.codec_tag_string) && streamInfo.codec_tag_string.IndexOf("[0]", StringComparison.OrdinalIgnoreCase) == -1) { diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index fa7a51291..25252956b 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -42,6 +42,8 @@ namespace MediaBrowser.Model.Entities /// true if this instance is interlaced; otherwise, false. public bool IsInterlaced { get; set; } + public bool? IsAVC { get; set; } + /// /// Gets or sets the channel layout. /// diff --git a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs index debcd054f..76682c63b 100644 --- a/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs +++ b/MediaBrowser.Server.Implementations/Persistence/MediaStreamColumns.cs @@ -26,6 +26,38 @@ namespace MediaBrowser.Server.Implementations.Persistence AddCodecTagColumn(); AddCommentColumn(); AddNalColumn(); + AddIsAvcColumn(); + } + + private void AddIsAvcColumn() + { + using (var cmd = _connection.CreateCommand()) + { + cmd.CommandText = "PRAGMA table_info(mediastreams)"; + + using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) + { + while (reader.Read()) + { + if (!reader.IsDBNull(1)) + { + var name = reader.GetString(1); + + if (string.Equals(name, "IsAvc", StringComparison.OrdinalIgnoreCase)) + { + return; + } + } + } + } + } + + var builder = new StringBuilder(); + + builder.AppendLine("alter table mediastreams"); + builder.AppendLine("add column IsAvc BIT NULL"); + + _connection.RunQueries(new[] { builder.ToString() }, _logger); } private void AddNalColumn() diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fcc39deb5..783bd5ff4 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); var createMediaStreamsTableCommand - = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))"; + = "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, PRIMARY KEY (ItemId, StreamIndex))"; string[] queries = { @@ -391,7 +391,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "RefFrames", "CodecTag", "Comment", - "NalLengthSize" + "NalLengthSize", + "IsAvc" }; /// @@ -2897,6 +2898,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveStreamCommand.GetParameter(index++).Value = stream.CodecTag; _saveStreamCommand.GetParameter(index++).Value = stream.Comment; _saveStreamCommand.GetParameter(index++).Value = stream.NalLengthSize; + _saveStreamCommand.GetParameter(index++).Value = stream.IsAVC; _saveStreamCommand.Transaction = transaction; _saveStreamCommand.ExecuteNonQuery(); @@ -3060,6 +3062,11 @@ namespace MediaBrowser.Server.Implementations.Persistence item.NalLengthSize = reader.GetString(27); } + if (!reader.IsDBNull(28)) + { + item.IsAVC = reader.GetBoolean(28); + } + return item; } From 6d735b3216e54b5879a80a1d598011e44b51d742 Mon Sep 17 00:00:00 2001 From: anderbytes Date: Tue, 26 Apr 2016 23:51:05 -0300 Subject: [PATCH 190/852] Collection meta-fetch fallback condition update With this change I propose that english metadata from collection (fallback situation) occurs when a collection NAME is missing, instead of OVERVIEW (description). This means a translated collection that has the vital information such as name will be sufficient to be used... not forcing Emby to download english data (with the non-translated title and overview) just because the translated version has an empty overview. I took a while to understand why some of my collections weren't downloading their translated versions from provider. I traced the problem to this... the ones who had overview were pulled in, the ones who hadn't Emby used the fallback (easily seen in the logs). --- MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index 53a573bd1..2cac9b063 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -190,7 +190,7 @@ namespace MediaBrowser.Providers.BoxSets cancellationToken.ThrowIfCancellationRequested(); - if (mainResult != null && string.IsNullOrEmpty(mainResult.overview)) + if (mainResult != null && string.IsNullOrEmpty(mainResult.name)) { if (!string.IsNullOrEmpty(language) && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase)) { From 4d55176aaa12d827fd26bcc327e484c0764d8435 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:43:09 -0400 Subject: [PATCH 191/852] update SearchEngine --- .../Library/SearchEngine.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs index 61a5d98a3..e271fbcb2 100644 --- a/MediaBrowser.Server.Implementations/Library/SearchEngine.cs +++ b/MediaBrowser.Server.Implementations/Library/SearchEngine.cs @@ -87,13 +87,16 @@ namespace MediaBrowser.Server.Implementations.Library { var searchTerm = query.SearchTerm; + if (searchTerm != null) + { + searchTerm = searchTerm.Trim().RemoveDiacritics(); + } + if (string.IsNullOrWhiteSpace(searchTerm)) { throw new ArgumentNullException("searchTerm"); } - searchTerm = searchTerm.Trim().RemoveDiacritics(); - var terms = GetWords(searchTerm); var hints = new List>(); From 9e8dabbb036c310d98351ede8063a18d5cb4529f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:50:32 -0400 Subject: [PATCH 192/852] fix rating filters --- MediaBrowser.Api/Reports/ReportsService.cs | 6 +++--- MediaBrowser.Api/UserLibrary/ItemsService.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Api/Reports/ReportsService.cs b/MediaBrowser.Api/Reports/ReportsService.cs index c3af09cd5..cb1615826 100644 --- a/MediaBrowser.Api/Reports/ReportsService.cs +++ b/MediaBrowser.Api/Reports/ReportsService.cs @@ -326,15 +326,15 @@ namespace MediaBrowser.Api.Reports } // Min official rating - if (!string.IsNullOrEmpty(request.MinOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MinOfficialRating)) { query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); } // Max official rating - if (!string.IsNullOrEmpty(request.MaxOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MaxOfficialRating)) { - query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); + query.MaxParentalRating = _localization.GetRatingLevel(request.MaxOfficialRating); } // Artists diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index cfdc40bb2..7d2029cab 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -308,15 +308,15 @@ namespace MediaBrowser.Api.UserLibrary } // Min official rating - if (!string.IsNullOrEmpty(request.MinOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MinOfficialRating)) { query.MinParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); } // Max official rating - if (!string.IsNullOrEmpty(request.MaxOfficialRating)) + if (!string.IsNullOrWhiteSpace(request.MaxOfficialRating)) { - query.MaxParentalRating = _localization.GetRatingLevel(request.MinOfficialRating); + query.MaxParentalRating = _localization.GetRatingLevel(request.MaxOfficialRating); } // Artists From 5a894946dd2baeba3e361614e5ac7d82fe962441 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:52:43 -0400 Subject: [PATCH 193/852] update IsFolder sorting --- .../Persistence/SqliteItemRepository.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fb91a2dd2..fcc39deb5 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1574,6 +1574,10 @@ namespace MediaBrowser.Server.Implementations.Persistence { return "RuntimeTicks"; } + if (string.Equals(name, ItemSortBy.IsFolder, StringComparison.OrdinalIgnoreCase)) + { + return "IsFolder"; + } if (string.Equals(name, ItemSortBy.Random, StringComparison.OrdinalIgnoreCase)) { return "RANDOM()"; From d0aece61e7e74833a3f53050d2fc0fdd5a91e200 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 15:41:12 -0400 Subject: [PATCH 194/852] fixes for episodes directly in series folder --- MediaBrowser.Providers/TV/DummySeasonProvider.cs | 4 ++-- MediaBrowser.Providers/TV/MissingEpisodeProvider.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs index 5cf9966e8..2c6e27294 100644 --- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Providers.TV if (hasNewSeasons) { - var directoryService = new DirectoryService(_fileSystem); + //var directoryService = new DirectoryService(_fileSystem); //await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false); @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.TV // Season does not have a number // Remove if there are no episodes directly in series without a season number - return episodes.All(s => s.ParentIndexNumber.HasValue || !s.IsInSeasonFolder); + return episodes.All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder); }) .ToList(); diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index 8ae9aa5bb..e79ad2dfb 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -380,7 +380,7 @@ namespace MediaBrowser.Providers.TV // Season does not have a number // Remove if there are no episodes directly in series without a season number - return i.Season.Series.GetRecursiveChildren().OfType().All(s => s.ParentIndexNumber.HasValue || !s.IsInSeasonFolder); + return i.Season.Series.GetRecursiveChildren().OfType().All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder); }) .ToList(); From 0c065c12da7dc7483619ad103b30715516936688 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 15:41:12 -0400 Subject: [PATCH 195/852] fixes for episodes directly in series folder --- MediaBrowser.Providers/TV/DummySeasonProvider.cs | 4 ++-- MediaBrowser.Providers/TV/MissingEpisodeProvider.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs index 5cf9966e8..2c6e27294 100644 --- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs +++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs @@ -40,7 +40,7 @@ namespace MediaBrowser.Providers.TV if (hasNewSeasons) { - var directoryService = new DirectoryService(_fileSystem); + //var directoryService = new DirectoryService(_fileSystem); //await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false); @@ -163,7 +163,7 @@ namespace MediaBrowser.Providers.TV // Season does not have a number // Remove if there are no episodes directly in series without a season number - return episodes.All(s => s.ParentIndexNumber.HasValue || !s.IsInSeasonFolder); + return episodes.All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder); }) .ToList(); diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs index ad55c186a..efdf8ce5d 100644 --- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs @@ -372,7 +372,7 @@ namespace MediaBrowser.Providers.TV // Season does not have a number // Remove if there are no episodes directly in series without a season number - return i.Season.Series.GetRecursiveChildren().OfType().All(s => s.ParentIndexNumber.HasValue || !s.IsInSeasonFolder); + return i.Season.Series.GetRecursiveChildren().OfType().All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder); }) .ToList(); From f7128c7f8f04a39272ec10c699f3a05dac1a8e67 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:24:53 -0400 Subject: [PATCH 196/852] resync media after changes --- MediaBrowser.Model/Sync/SyncJobItem.cs | 2 ++ .../Sync/SyncJobProcessor.cs | 6 ++++++ .../Sync/SyncManager.cs | 16 +++++++++++++++- .../Sync/SyncRepository.cs | 9 ++++++++- 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Model/Sync/SyncJobItem.cs b/MediaBrowser.Model/Sync/SyncJobItem.cs index 77464be58..1c72ccd52 100644 --- a/MediaBrowser.Model/Sync/SyncJobItem.cs +++ b/MediaBrowser.Model/Sync/SyncJobItem.cs @@ -102,6 +102,8 @@ namespace MediaBrowser.Model.Sync /// The index of the job item. public int JobItemIndex { get; set; } + public long ItemDateModifiedTicks { get; set; } + public SyncJobItem() { AdditionalFiles = new List(); diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 33874b4d4..0bec528bb 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -632,6 +632,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) @@ -668,6 +669,7 @@ namespace MediaBrowser.Server.Implementations.Sync throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; jobItem.MediaSource = mediaSource; } @@ -819,6 +821,7 @@ namespace MediaBrowser.Server.Implementations.Sync }, innerProgress, cancellationToken); + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; _syncManager.OnConversionComplete(jobItem); } catch (OperationCanceledException) @@ -855,6 +858,7 @@ namespace MediaBrowser.Server.Implementations.Sync throw new InvalidOperationException(string.Format("Cannot direct stream {0} protocol", mediaSource.Protocol)); } + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; jobItem.MediaSource = mediaSource; } @@ -871,6 +875,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 50; jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } @@ -880,6 +885,7 @@ namespace MediaBrowser.Server.Implementations.Sync jobItem.Progress = 50; jobItem.Status = SyncJobItemStatus.ReadyToTransfer; + jobItem.ItemDateModifiedTicks = item.DateModified.Ticks; await _syncManager.UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 044c8b93a..fe1a7fb28 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -775,6 +775,13 @@ namespace MediaBrowser.Server.Implementations.Sync removeFromDevice = true; } } + else if (libraryItem != null && libraryItem.DateModified.Ticks != jobItem.ItemDateModifiedTicks && jobItem.ItemDateModifiedTicks > 0) + { + _logger.Info("Setting status to Queued for {0} because the media has been modified since the original sync.", jobItem.ItemId); + jobItem.Status = SyncJobItemStatus.Queued; + jobItem.Progress = 0; + requiresSaving = true; + } } else { @@ -881,6 +888,13 @@ namespace MediaBrowser.Server.Implementations.Sync removeFromDevice = true; } } + else if (libraryItem != null && libraryItem.DateModified.Ticks != jobItem.ItemDateModifiedTicks && jobItem.ItemDateModifiedTicks > 0) + { + _logger.Info("Setting status to Queued for {0} because the media has been modified since the original sync.", jobItem.ItemId); + jobItem.Status = SyncJobItemStatus.Queued; + jobItem.Progress = 0; + requiresSaving = true; + } } else { @@ -1117,7 +1131,7 @@ namespace MediaBrowser.Server.Implementations.Sync public SyncJobOptions GetAudioOptions(SyncJobItem jobItem, SyncJob job) { var options = GetSyncJobOptions(jobItem.TargetId, null, null); - + if (job.Bitrate.HasValue) { options.DeviceProfile.MaxStaticBitrate = job.Bitrate.Value; diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 464e8aa58..249c4212e 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.Sync "create table if not exists SyncJobs (Id GUID PRIMARY KEY, TargetId TEXT NOT NULL, Name TEXT NOT NULL, Profile TEXT, Quality TEXT, Bitrate INT, Status TEXT NOT NULL, Progress FLOAT, UserId TEXT NOT NULL, ItemIds TEXT NOT NULL, Category TEXT, ParentId TEXT, UnwatchedOnly BIT, ItemLimit INT, SyncNewContent BIT, DateCreated DateTime, DateLastModified DateTime, ItemCount int)", "create index if not exists idx_SyncJobs on SyncJobs(Id)", - "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT)", + "create table if not exists SyncJobItems (Id GUID PRIMARY KEY, ItemId TEXT, ItemName TEXT, MediaSourceId TEXT, JobId TEXT, TemporaryPath TEXT, OutputPath TEXT, Status TEXT, TargetId TEXT, DateCreated DateTime, Progress FLOAT, AdditionalFiles TEXT, MediaSource TEXT, IsMarkedForRemoval BIT, JobItemIndex INT, ItemDateModifiedTicks BIGINT)", "create index if not exists idx_SyncJobItems on SyncJobs(Id)", //pragmas @@ -63,6 +63,7 @@ namespace MediaBrowser.Server.Implementations.Sync _connection.AddColumn(Logger, "SyncJobs", "Profile", "TEXT"); _connection.AddColumn(Logger, "SyncJobs", "Bitrate", "INT"); + _connection.AddColumn(Logger, "SyncJobItems", "ItemDateModifiedTicks", "BIGINT"); PrepareStatements(); } @@ -678,6 +679,7 @@ namespace MediaBrowser.Server.Implementations.Sync cmd.GetParameter(index++).Value = jobItem.MediaSource == null ? null : _json.SerializeToString(jobItem.MediaSource); cmd.GetParameter(index++).Value = jobItem.IsMarkedForRemoval; cmd.GetParameter(index++).Value = jobItem.JobItemIndex; + cmd.GetParameter(index++).Value = jobItem.ItemDateModifiedTicks; cmd.Transaction = transaction; @@ -782,6 +784,11 @@ namespace MediaBrowser.Server.Implementations.Sync info.IsMarkedForRemoval = reader.GetBoolean(13); info.JobItemIndex = reader.GetInt32(14); + if (!reader.IsDBNull(15)) + { + info.ItemDateModifiedTicks = reader.GetInt64(15); + } + return info; } From d54f791159ecdf82e80c54ac663614eedf57f959 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:29:27 -0400 Subject: [PATCH 197/852] update resync --- .../Sync/SyncJobProcessor.cs | 5 +++++ .../Sync/SyncRepository.cs | 8 +++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 0bec528bb..10b872753 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -149,6 +149,11 @@ namespace MediaBrowser.Server.Implementations.Sync { var job = _syncRepo.GetJob(id); + if (job == null) + { + return Task.FromResult(true); + } + var result = _syncManager.GetJobItems(new SyncJobItemQuery { JobId = job.Id, diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 249c4212e..965c081eb 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.Sync // _insertJobItemCommand _insertJobItemCommand = _connection.CreateCommand(); - _insertJobItemCommand.CommandText = "insert into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex)"; + _insertJobItemCommand.CommandText = "insert into SyncJobItems (Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks) values (@Id, @ItemId, @ItemName, @MediaSourceId, @JobId, @TemporaryPath, @OutputPath, @Status, @TargetId, @DateCreated, @Progress, @AdditionalFiles, @MediaSource, @IsMarkedForRemoval, @JobItemIndex, @ItemDateModifiedTicks)"; _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@Id"); _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@ItemId"); @@ -145,10 +145,11 @@ namespace MediaBrowser.Server.Implementations.Sync _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@MediaSource"); _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@IsMarkedForRemoval"); _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@JobItemIndex"); + _insertJobItemCommand.Parameters.Add(_insertJobItemCommand, "@ItemDateModifiedTicks"); // _updateJobItemCommand _updateJobItemCommand = _connection.CreateCommand(); - _updateJobItemCommand.CommandText = "update SyncJobItems set ItemId=@ItemId,ItemName=@ItemName,MediaSourceId=@MediaSourceId,JobId=@JobId,TemporaryPath=@TemporaryPath,OutputPath=@OutputPath,Status=@Status,TargetId=@TargetId,DateCreated=@DateCreated,Progress=@Progress,AdditionalFiles=@AdditionalFiles,MediaSource=@MediaSource,IsMarkedForRemoval=@IsMarkedForRemoval,JobItemIndex=@JobItemIndex where Id=@Id"; + _updateJobItemCommand.CommandText = "update SyncJobItems set ItemId=@ItemId,ItemName=@ItemName,MediaSourceId=@MediaSourceId,JobId=@JobId,TemporaryPath=@TemporaryPath,OutputPath=@OutputPath,Status=@Status,TargetId=@TargetId,DateCreated=@DateCreated,Progress=@Progress,AdditionalFiles=@AdditionalFiles,MediaSource=@MediaSource,IsMarkedForRemoval=@IsMarkedForRemoval,JobItemIndex=@JobItemIndex,ItemDateModifiedTicks=@ItemDateModifiedTicks where Id=@Id"; _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@Id"); _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@ItemId"); @@ -165,10 +166,11 @@ namespace MediaBrowser.Server.Implementations.Sync _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@MediaSource"); _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@IsMarkedForRemoval"); _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@JobItemIndex"); + _updateJobItemCommand.Parameters.Add(_updateJobItemCommand, "@ItemDateModifiedTicks"); } private const string BaseJobSelectText = "select Id, TargetId, Name, Profile, Quality, Bitrate, Status, Progress, UserId, ItemIds, Category, ParentId, UnwatchedOnly, ItemLimit, SyncNewContent, DateCreated, DateLastModified, ItemCount from SyncJobs"; - private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex from SyncJobItems"; + private const string BaseJobItemSelectText = "select Id, ItemId, ItemName, MediaSourceId, JobId, TemporaryPath, OutputPath, Status, TargetId, DateCreated, Progress, AdditionalFiles, MediaSource, IsMarkedForRemoval, JobItemIndex, ItemDateModifiedTicks from SyncJobItems"; public SyncJob GetJob(string id) { From d0b8ff1cc751117caedc66ae6be42c986e519d46 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:30:50 -0400 Subject: [PATCH 198/852] 3.0.5945 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 654ff7197..37df3f3ed 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5944")] +[assembly: AssemblyVersion("3.0.5945")] From 9ec3b6c0ebc27c25f4837f4d79fc2415bf25409c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:52:09 -0400 Subject: [PATCH 199/852] update change monitors --- MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs | 6 +++--- MediaBrowser.Providers/Music/FanArtAlbumProvider.cs | 6 +++--- MediaBrowser.Providers/Music/FanArtArtistProvider.cs | 6 +++--- MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs | 6 +++--- .../TV/TheTVDB/TvdbSeasonImageProvider.cs | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs index 343586ea5..b174de455 100644 --- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs +++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs @@ -23,7 +23,7 @@ using MediaBrowser.Providers.TV; namespace MediaBrowser.Providers.Movies { - public class FanartMovieImageProvider : IRemoteImageProvider, IHasChangeMonitor, IHasOrder + public class FanartMovieImageProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IServerConfigurationManager _config; @@ -239,7 +239,7 @@ namespace MediaBrowser.Providers.Movies }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var options = FanartSeriesProvider.Current.GetFanartOptions(); if (!options.EnableAutomaticUpdates) @@ -260,7 +260,7 @@ namespace MediaBrowser.Providers.Movies var fileInfo = _fileSystem.GetFileInfo(path); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs index 444046208..5b3bd87db 100644 --- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs @@ -19,7 +19,7 @@ using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Music { - public class FanartAlbumProvider : IRemoteImageProvider, IHasChangeMonitor, IHasOrder + public class FanartAlbumProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IServerConfigurationManager _config; @@ -213,7 +213,7 @@ namespace MediaBrowser.Providers.Music }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var options = FanartSeriesProvider.Current.GetFanartOptions(); if (!options.EnableAutomaticUpdates) @@ -235,7 +235,7 @@ namespace MediaBrowser.Providers.Music var fileInfo = _fileSystem.GetFileInfo(artistJsonPath); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } } diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index 9e58b4608..37b51da5a 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -22,7 +22,7 @@ using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Music { - public class FanartArtistProvider : IRemoteImageProvider, IHasChangeMonitor, IHasOrder + public class FanartArtistProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder { internal readonly SemaphoreSlim FanArtResourcePool = new SemaphoreSlim(3, 3); internal const string ApiKey = "5c6b04c68e904cfed1e6cbc9a9e683d4"; @@ -207,7 +207,7 @@ namespace MediaBrowser.Providers.Music }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var options = FanartSeriesProvider.Current.GetFanartOptions(); if (!options.EnableAutomaticUpdates) @@ -224,7 +224,7 @@ namespace MediaBrowser.Providers.Music var fileInfo = _fileSystem.GetFileInfo(artistJsonPath); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs index e683907c4..673663d7f 100644 --- a/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanArtSeasonProvider.cs @@ -21,7 +21,7 @@ using CommonIO; namespace MediaBrowser.Providers.TV { - public class FanArtSeasonProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor + public class FanArtSeasonProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IServerConfigurationManager _config; @@ -225,7 +225,7 @@ namespace MediaBrowser.Providers.TV }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var options = FanartSeriesProvider.Current.GetFanartOptions(); if (!options.EnableAutomaticUpdates) @@ -250,7 +250,7 @@ namespace MediaBrowser.Providers.TV var fileInfo = _fileSystem.GetFileInfo(imagesFilePath); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs index 5e7ce9f7e..54d729eb7 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbSeasonImageProvider.cs @@ -20,7 +20,7 @@ using CommonIO; namespace MediaBrowser.Providers.TV { - public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor + public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor { private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); @@ -363,7 +363,7 @@ namespace MediaBrowser.Providers.TV }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { if (item.LocationType != LocationType.Virtual) { @@ -384,7 +384,7 @@ namespace MediaBrowser.Providers.TV var fileInfo = _fileSystem.GetFileInfo(imagesXmlPath); - return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return fileInfo.Exists && _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; From 5fc423394202a7b5e80b6274a90601e7ea14ffa8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 17:09:52 -0400 Subject: [PATCH 200/852] update change monitors --- .../Manager/MetadataService.cs | 17 ++++++----------- .../Movies/MovieDbImageProvider.cs | 6 +++--- .../Movies/MovieDbProvider.cs | 4 ++-- .../Movies/MovieDbTrailerProvider.cs | 4 ++-- .../Music/MovieDbMusicVideoProvider.cs | 4 ++-- .../TV/FanArt/FanartSeriesProvider.cs | 6 +++--- .../TV/TheMovieDb/MovieDbSeriesImageProvider.cs | 6 +++--- .../TV/TheMovieDb/MovieDbSeriesProvider.cs | 4 ++-- 8 files changed, 23 insertions(+), 28 deletions(-) diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index eeec4ea56..cb5e6c88f 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -295,7 +295,12 @@ namespace MediaBrowser.Providers.Manager return true; } - if (item is BoxSet || item is IItemByName || item is Playlist) + if (!(item is Audio) && !(item is Video)) + { + return true; + } + + if (item is IItemByName) { return true; } @@ -305,16 +310,6 @@ namespace MediaBrowser.Providers.Manager return true; } - if (item is ICollectionFolder) - { - return true; - } - - if (!(item is Audio) && !(item is Video)) - { - return true; - } - return false; } diff --git a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs index e091cddc6..51db77bf6 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs @@ -17,7 +17,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Movies { - class MovieDbImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor + class MovieDbImageProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor { private readonly IJsonSerializer _jsonSerializer; private readonly IHttpClient _httpClient; @@ -222,9 +222,9 @@ namespace MediaBrowser.Providers.Movies }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - return MovieDbProvider.Current.HasChanged(item, date); + return MovieDbProvider.Current.HasChanged(item); } } } diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 9da717b7e..872deba34 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -414,7 +414,7 @@ namespace MediaBrowser.Providers.Movies return _configurationManager.GetConfiguration("themoviedb"); } - public bool HasChanged(IHasMetadata item, DateTime date) + public bool HasChanged(IHasMetadata item) { if (!GetTheMovieDbOptions().EnableAutomaticUpdates) { @@ -430,7 +430,7 @@ namespace MediaBrowser.Providers.Movies var fileInfo = _fileSystem.GetFileInfo(dataFilePath); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs index 336968a84..5fb3ea369 100644 --- a/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs @@ -33,9 +33,9 @@ namespace MediaBrowser.Providers.Movies get { return MovieDbProvider.Current.Name; } } - public bool HasChanged(IHasMetadata item, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - return MovieDbProvider.Current.HasChanged(item, date); + return MovieDbProvider.Current.HasChanged(item); } public int Order diff --git a/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs b/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs index 55dcc99f5..d031b3d6b 100644 --- a/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs +++ b/MediaBrowser.Providers/Music/MovieDbMusicVideoProvider.cs @@ -27,9 +27,9 @@ namespace MediaBrowser.Providers.Music get { return MovieDbProvider.Current.Name; } } - public bool HasChanged(IHasMetadata item, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - return MovieDbProvider.Current.HasChanged(item, date); + return MovieDbProvider.Current.HasChanged(item); } public Task GetImageResponse(string url, CancellationToken cancellationToken) diff --git a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs index 1168bfeee..3c831dbbc 100644 --- a/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/FanArt/FanartSeriesProvider.cs @@ -23,7 +23,7 @@ using CommonIO; namespace MediaBrowser.Providers.TV { - public class FanartSeriesProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor + public class FanartSeriesProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor { private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IServerConfigurationManager _config; @@ -341,7 +341,7 @@ namespace MediaBrowser.Providers.TV } } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var options = GetFanartOptions(); if (!options.EnableAutomaticUpdates) @@ -358,7 +358,7 @@ namespace MediaBrowser.Providers.TV var fileInfo = _fileSystem.GetFileInfo(imagesFilePath); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs index f7c19988c..2c6b09ade 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs @@ -16,7 +16,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.TV { - public class MovieDbSeriesImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor + public class MovieDbSeriesImageProvider : IRemoteImageProvider, IHasOrder, IHasItemChangeMonitor { private readonly IJsonSerializer _jsonSerializer; private readonly IHttpClient _httpClient; @@ -196,9 +196,9 @@ namespace MediaBrowser.Providers.TV }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { - return MovieDbSeriesProvider.Current.HasChanged(item, date); + return MovieDbSeriesProvider.Current.HasChanged(item); } } } diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs index 7d30042dc..407ff762a 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs @@ -414,7 +414,7 @@ namespace MediaBrowser.Providers.TV return Path.Combine(path, filename); } - public bool HasChanged(IHasMetadata item, DateTime date) + public bool HasChanged(IHasMetadata item) { if (!MovieDbProvider.Current.GetTheMovieDbOptions().EnableAutomaticUpdates) { @@ -430,7 +430,7 @@ namespace MediaBrowser.Providers.TV var fileInfo = _fileSystem.GetFileInfo(dataFilePath); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > item.DateLastRefreshed; } return false; From 747518decc3e59a9c6b01f31e5360ce194919d8d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 17:26:28 -0400 Subject: [PATCH 201/852] added option to preserve original audio when recording --- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 1 + .../LiveTv/EmbyTV/EmbyTV.cs | 6 ++++-- .../LiveTv/EmbyTV/EncodedRecorder.cs | 7 +++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 46f630fe0..fc2b155ec 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -9,6 +9,7 @@ namespace MediaBrowser.Model.LiveTv public string RecordingPath { get; set; } public bool EnableAutoOrganize { get; set; } public bool EnableRecordingEncoding { get; set; } + public bool EnableOriginalAudioWithEncodedRecordings { get; set; } public List TunerHosts { get; set; } public List ListingProviders { get; set; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index d85e8ba3f..351bc05af 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -927,13 +927,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private async Task GetRecorder() { - if (GetConfiguration().EnableRecordingEncoding) + var config = GetConfiguration(); + + if (config.EnableRecordingEncoding) { var regInfo = await _security.GetRegistrationStatus("embytvrecordingconversion").ConfigureAwait(false); if (regInfo.IsValid) { - return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer); + return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, config); } } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 442f151dd..63d0846fc 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -12,6 +12,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -23,6 +24,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly IFileSystem _fileSystem; private readonly IMediaEncoder _mediaEncoder; private readonly IApplicationPaths _appPaths; + private readonly LiveTvOptions _liveTvOptions; private bool _hasExited; private Stream _logFileStream; private string _targetPath; @@ -30,13 +32,14 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV private readonly IJsonSerializer _json; private readonly TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); - public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IApplicationPaths appPaths, IJsonSerializer json) + public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IApplicationPaths appPaths, IJsonSerializer json, LiveTvOptions liveTvOptions) { _logger = logger; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; _appPaths = appPaths; _json = json; + _liveTvOptions = liveTvOptions; } public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) @@ -129,7 +132,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { var copyAudio = new[] { "aac", "mp3" }; var mediaStreams = mediaSource.MediaStreams ?? new List(); - if (mediaStreams.Any(i => i.Type == MediaStreamType.Audio && copyAudio.Contains(i.Codec, StringComparer.OrdinalIgnoreCase))) + if (_liveTvOptions.EnableOriginalAudioWithEncodedRecordings || mediaStreams.Any(i => i.Type == MediaStreamType.Audio && copyAudio.Contains(i.Codec, StringComparer.OrdinalIgnoreCase))) { return "-codec:a:0 copy"; } From 87091b6196941fdbbb11408ef1480a6f4175af49 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 21:59:09 -0400 Subject: [PATCH 202/852] update providers --- MediaBrowser.Controller/Entities/Video.cs | 5 +++++ MediaBrowser.LocalMetadata/BaseXmlProvider.cs | 6 +++--- MediaBrowser.Providers/Manager/MetadataService.cs | 12 ++++++------ .../TV/TheTVDB/TvdbEpisodeImageProvider.cs | 6 +++--- .../TV/TheTVDB/TvdbEpisodeProvider.cs | 6 +++--- .../Photos/BaseDynamicImageProvider.cs | 4 ++-- .../Providers/BaseNfoProvider.cs | 6 +++--- 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 2c7d3856b..d81e6f0ff 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -317,6 +317,11 @@ namespace MediaBrowser.Controller.Entities { return false; } + + if (newAsVideo.VideoType != VideoType) + { + return false; + } } return base.IsValidFromResolver(newItem); diff --git a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs index 4fc1d210d..4b64295ea 100644 --- a/MediaBrowser.LocalMetadata/BaseXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/BaseXmlProvider.cs @@ -8,7 +8,7 @@ using CommonIO; namespace MediaBrowser.LocalMetadata { - public abstract class BaseXmlProvider : ILocalMetadataProvider, IHasChangeMonitor, IHasOrder + public abstract class BaseXmlProvider : ILocalMetadataProvider, IHasItemChangeMonitor, IHasOrder where T : IHasMetadata, new() { protected IFileSystem FileSystem; @@ -56,7 +56,7 @@ namespace MediaBrowser.LocalMetadata protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService); - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var file = GetXmlFile(new ItemInfo(item), directoryService); @@ -65,7 +65,7 @@ namespace MediaBrowser.LocalMetadata return false; } - return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > date; + return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved; } public string Name diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index cb5e6c88f..ae48c996a 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -430,18 +430,18 @@ namespace MediaBrowser.Providers.Manager var providersWithChanges = providers .Where(i => { - var hasChangeMonitor = i as IHasChangeMonitor; - if (hasChangeMonitor != null) - { - return HasChanged(item, hasChangeMonitor, currentItem.DateLastSaved, options.DirectoryService); - } - var hasFileChangeMonitor = i as IHasItemChangeMonitor; if (hasFileChangeMonitor != null) { return HasChanged(item, hasFileChangeMonitor, options.DirectoryService); } + var hasChangeMonitor = i as IHasChangeMonitor; + if (hasChangeMonitor != null) + { + return HasChanged(item, hasChangeMonitor, currentItem.DateLastSaved, options.DirectoryService); + } + return false; }) .ToList(); diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs index 49d41e06c..ca3320cc6 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeImageProvider.cs @@ -17,7 +17,7 @@ using CommonIO; namespace MediaBrowser.Providers.TV { - public class TvdbEpisodeImageProvider : IRemoteImageProvider, IHasChangeMonitor + public class TvdbEpisodeImageProvider : IRemoteImageProvider, IHasItemChangeMonitor { private readonly IServerConfigurationManager _config; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); @@ -174,7 +174,7 @@ namespace MediaBrowser.Providers.TV }); } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var episode = (Episode)item; @@ -196,7 +196,7 @@ namespace MediaBrowser.Providers.TV // Process images var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage()); - return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > date; + return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > item.DateLastRefreshed; } } diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs index 291214fcd..5c88c87d8 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Providers.TV /// /// Class RemoteEpisodeProvider /// - class TvdbEpisodeProvider : IRemoteMetadataProvider, IItemIdentityProvider, IHasChangeMonitor + class TvdbEpisodeProvider : IRemoteMetadataProvider, IItemIdentityProvider, IHasItemChangeMonitor { private static readonly string FullIdKey = MetadataProviders.Tvdb + "-Full"; @@ -144,7 +144,7 @@ namespace MediaBrowser.Providers.TV return result; } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { // Only enable for virtual items if (item.LocationType != LocationType.Virtual) @@ -160,7 +160,7 @@ namespace MediaBrowser.Providers.TV // Process images var seriesXmlPath = TvdbSeriesProvider.Current.GetSeriesXmlPath(series.ProviderIds, series.GetPreferredMetadataLanguage()); - return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > date; + return _fileSystem.GetLastWriteTimeUtc(seriesXmlPath) > item.DateLastRefreshed; } return false; diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 4a69646f8..acb1227e4 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -17,7 +17,7 @@ using MediaBrowser.Model.Configuration; namespace MediaBrowser.Server.Implementations.Photos { - public abstract class BaseDynamicImageProvider : IHasChangeMonitor, IForcedProvider, ICustomMetadataProvider, IHasOrder + public abstract class BaseDynamicImageProvider : IHasItemChangeMonitor, IForcedProvider, ICustomMetadataProvider, IHasOrder where T : IHasMetadata { protected IFileSystem FileSystem { get; private set; } @@ -247,7 +247,7 @@ namespace MediaBrowser.Server.Implementations.Photos get { return 7; } } - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryServicee) { if (!Supports(item)) { diff --git a/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs index 5ce8d30ad..c1dd92987 100644 --- a/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs +++ b/MediaBrowser.XbmcMetadata/Providers/BaseNfoProvider.cs @@ -9,7 +9,7 @@ using CommonIO; namespace MediaBrowser.XbmcMetadata.Providers { - public abstract class BaseNfoProvider : ILocalMetadataProvider, IHasChangeMonitor + public abstract class BaseNfoProvider : ILocalMetadataProvider, IHasItemChangeMonitor where T : IHasMetadata, new() { protected IFileSystem FileSystem; @@ -57,7 +57,7 @@ namespace MediaBrowser.XbmcMetadata.Providers protected abstract FileSystemMetadata GetXmlFile(ItemInfo info, IDirectoryService directoryService); - public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) + public bool HasChanged(IHasMetadata item, IDirectoryService directoryService) { var file = GetXmlFile(new ItemInfo(item), directoryService); @@ -66,7 +66,7 @@ namespace MediaBrowser.XbmcMetadata.Providers return false; } - return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > date; + return file.Exists && FileSystem.GetLastWriteTimeUtc(file) > item.DateLastSaved; } public string Name From c7e99f424eb394f4a3b1e8d4239642c4a3b69cfd Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 21:59:38 -0400 Subject: [PATCH 203/852] update standby --- MediaBrowser.ServerApplication/MainStartup.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 454c415a1..dc61dcda8 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -273,11 +273,13 @@ namespace MediaBrowser.ServerApplication } private static ServerNotifyIcon _serverNotifyIcon; + private static TaskScheduler _mainTaskScheduler; private static void ShowTrayIcon() { //Application.EnableVisualStyles(); //Application.SetCompatibleTextRenderingDefault(false); _serverNotifyIcon = new ServerNotifyIcon(_appHost.LogManager, _appHost, _appHost.ServerConfigurationManager, _appHost.LocalizationManager); + _mainTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Application.Run(); } @@ -323,7 +325,14 @@ namespace MediaBrowser.ServerApplication public static void Invoke(Action action) { - _serverNotifyIcon.Invoke(action); + if (_isRunningAsService) + { + action(); + } + else + { + Task.Factory.StartNew(action, CancellationToken.None, TaskCreationOptions.None, _mainTaskScheduler ?? TaskScheduler.Current); + } } /// From 55705c34ec4c4fc13b6d4d0b55c624d341e13eb5 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 22:46:41 -0400 Subject: [PATCH 204/852] use common sharing manager --- 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 bfa4995cf..b2627562a 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -368,9 +368,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From a80070f478bbc3b1500859ad4ab795cfaa80b8ca Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Apr 2016 13:21:10 -0400 Subject: [PATCH 205/852] check codecs in audio direct play profiles --- MediaBrowser.Model/Dlna/StreamBuilder.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 1e6b7c729..98d246980 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1038,6 +1038,18 @@ namespace MediaBrowser.Model.Dlna } } + // Check audio codec + List audioCodecs = profile.GetAudioCodecs(); + if (audioCodecs.Count > 0) + { + // Check audio codecs + string audioCodec = audioStream == null ? null : audioStream.Codec; + if (string.IsNullOrEmpty(audioCodec) || !ListHelper.ContainsIgnoreCase(audioCodecs, audioCodec)) + { + return false; + } + } + return true; } @@ -1073,6 +1085,7 @@ namespace MediaBrowser.Model.Dlna } } + // Check audio codec List audioCodecs = profile.GetAudioCodecs(); if (audioCodecs.Count > 0) { From 671f686827f56a5efcab3ec96116f0c48ae138f3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Apr 2016 15:15:32 -0400 Subject: [PATCH 206/852] 3.0.5946 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 37df3f3ed..2d6b5c29a 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5945")] +[assembly: AssemblyVersion("3.0.5946")] From fc534f50d9802092247d0deef0c7b43e70c79a4a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Apr 2016 15:17:23 -0400 Subject: [PATCH 207/852] 3.0.5933 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 152434162..ea90eda21 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5932")] +[assembly: AssemblyVersion("3.0.5933")] From a12ec7167ead1ce5387919a0cefc92fc5bf46f47 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Apr 2016 23:10:48 -0400 Subject: [PATCH 208/852] update shared components --- .../MediaBrowser.WebDashboard.csproj | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index b2627562a..6bc9f9b1b 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -368,9 +368,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest @@ -473,17 +470,6 @@ PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - - PreserveNewest - PreserveNewest @@ -1730,17 +1716,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest From 6d7349284ffa5b5eea801ef651be14d22b9dde83 Mon Sep 17 00:00:00 2001 From: nfnty Date: Fri, 29 Apr 2016 10:06:41 +0200 Subject: [PATCH 209/852] Use HTTPS for API requests: TheMovieDb: base_url -> secure_base_url --- MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs | 2 +- MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs | 2 +- MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs | 2 +- MediaBrowser.Providers/Movies/MovieDbImageProvider.cs | 2 +- MediaBrowser.Providers/Movies/MovieDbProvider.cs | 2 +- MediaBrowser.Providers/Movies/MovieDbSearch.cs | 2 +- MediaBrowser.Providers/Movies/TmdbSettings.cs | 2 +- MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs | 2 +- MediaBrowser.Providers/People/MovieDbPersonProvider.cs | 2 +- .../TV/TheMovieDb/MovieDbEpisodeImageProvider.cs | 2 +- .../TV/TheMovieDb/MovieDbSeriesImageProvider.cs | 2 +- MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs | 4 ++-- 12 files changed, 13 insertions(+), 13 deletions(-) diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs index ff3d5a5b2..b3e73740d 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs @@ -61,7 +61,7 @@ namespace MediaBrowser.Providers.BoxSets { var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; return GetImages(mainResult, language, tmdbImageUrl); } diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs index 74e668754..ab05c959e 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetProvider.cs @@ -64,7 +64,7 @@ namespace MediaBrowser.Providers.BoxSets var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; var result = new RemoteSearchResult { diff --git a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs index 77d6f617d..d13716cba 100644 --- a/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs +++ b/MediaBrowser.Providers/Movies/GenericMovieDbInfo.cs @@ -249,7 +249,7 @@ namespace MediaBrowser.Providers.Movies } resultItem.ResetPeople(); - var tmdbImageUrl = settings.images.base_url + "original"; + var tmdbImageUrl = settings.images.secure_base_url + "original"; //Actors, Directors, Writers - all in People //actors come from cast diff --git a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs index 51db77bf6..5958c3a0a 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs @@ -72,7 +72,7 @@ namespace MediaBrowser.Providers.Movies var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; var supportedImages = GetSupportedImages(item).ToList(); diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index 872deba34..c588a9a69 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -78,7 +78,7 @@ namespace MediaBrowser.Providers.Movies var tmdbSettings = await GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; var remoteResult = new RemoteSearchResult { diff --git a/MediaBrowser.Providers/Movies/MovieDbSearch.cs b/MediaBrowser.Providers/Movies/MovieDbSearch.cs index 8f3c4668f..ceb41178e 100644 --- a/MediaBrowser.Providers/Movies/MovieDbSearch.cs +++ b/MediaBrowser.Providers/Movies/MovieDbSearch.cs @@ -56,7 +56,7 @@ namespace MediaBrowser.Providers.Movies var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; if (!string.IsNullOrWhiteSpace(name)) { diff --git a/MediaBrowser.Providers/Movies/TmdbSettings.cs b/MediaBrowser.Providers/Movies/TmdbSettings.cs index 59e8f7cef..12bb77afc 100644 --- a/MediaBrowser.Providers/Movies/TmdbSettings.cs +++ b/MediaBrowser.Providers/Movies/TmdbSettings.cs @@ -5,7 +5,7 @@ namespace MediaBrowser.Providers.Movies internal class TmdbImageSettings { public List backdrop_sizes { get; set; } - public string base_url { get; set; } + public string secure_base_url { get; set; } public List poster_sizes { get; set; } public List profile_sizes { get; set; } } diff --git a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs index 2ac9fdfa0..93eee69ae 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonImageProvider.cs @@ -67,7 +67,7 @@ namespace MediaBrowser.Providers.People var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; return GetImages(images, item.GetPreferredMetadataLanguage(), tmdbImageUrl); } diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs index ca7c08608..bb17b83ec 100644 --- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs +++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs @@ -59,7 +59,7 @@ namespace MediaBrowser.Providers.People var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; if (!string.IsNullOrEmpty(tmdbId)) { diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs index 9d1684948..719779674 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeImageProvider.cs @@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.TV var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; list.AddRange(GetPosters(response.images).Select(i => new RemoteImageInfo { diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs index 2c6b09ade..65ac12adf 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesImageProvider.cs @@ -64,7 +64,7 @@ namespace MediaBrowser.Providers.TV var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; list.AddRange(GetPosters(results).Select(i => new RemoteImageInfo { diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs index 407ff762a..7d0f49955 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbSeriesProvider.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Providers.TV var obj = _jsonSerializer.DeserializeFromFile(dataFilePath); var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; var remoteResult = new RemoteSearchResult { @@ -460,7 +460,7 @@ namespace MediaBrowser.Providers.TV if (tv != null) { var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false); - var tmdbImageUrl = tmdbSettings.images.base_url + "original"; + var tmdbImageUrl = tmdbSettings.images.secure_base_url + "original"; var remoteResult = new RemoteSearchResult { From 8711b8be14272ac63ebfa96136868d41e2d357c7 Mon Sep 17 00:00:00 2001 From: nfnty Date: Fri, 29 Apr 2016 10:46:29 +0200 Subject: [PATCH 210/852] Use HTTPS for API requests: FanArt: http:// -> https:// --- MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs index b174de455..775e6dfb9 100644 --- a/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs +++ b/MediaBrowser.Providers/Movies/FanartMovieImageProvider.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using CommonIO; @@ -185,6 +186,7 @@ namespace MediaBrowser.Providers.Movies PopulateImages(list, obj.moviebackground, ImageType.Backdrop, 1920, 1080); } + private Regex _regex_http = new Regex("^http://"); private void PopulateImages(List list, List images, ImageType type, int width, int height) { if (images == null) @@ -208,7 +210,7 @@ namespace MediaBrowser.Providers.Movies Width = width, Height = height, ProviderName = Name, - Url = url, + Url = _regex_http.Replace(url, "https://", 1), Language = i.lang }; From c37652058c651405335008c296d3d0baeeb80cf2 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Apr 2016 12:54:06 -0400 Subject: [PATCH 211/852] preserve image with audio sync encoding --- .../Encoder/AudioEncoder.cs | 25 ++++++++++++++++--- .../Encoder/EncodingJob.cs | 1 + .../Encoder/EncodingJobFactory.cs | 8 ++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs index 968d703be..2d5225344 100644 --- a/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/AudioEncoder.cs @@ -41,19 +41,36 @@ namespace MediaBrowser.MediaEncoding.Encoder } } - const string vn = " -vn"; - var threads = GetNumberOfThreads(state, false); var inputModifier = GetInputModifier(state); - return string.Format("{0} {1} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1 -y \"{5}\"", + var albumCoverInput = string.Empty; + var mapArgs = string.Empty; + var metadata = string.Empty; + var vn = string.Empty; + + if (!string.IsNullOrWhiteSpace(state.AlbumCoverPath)) + { + albumCoverInput = " -i \"" + state.AlbumCoverPath + "\""; + mapArgs = " -map 0:a -map 1:v -c:v copy"; + metadata = " -metadata:s:v title=\"Album cover\" -metadata:s:v comment=\"Cover(Front)\""; + } + else + { + vn = " -vn"; + } + + return string.Format("{0} {1}{6}{7} -threads {2}{3} {4} -id3v2_version 3 -write_id3v1 1{8} -y \"{5}\"", inputModifier, GetInputArgument(state), threads, vn, string.Join(" ", audioTranscodeParams.ToArray()), - state.OutputFilePath).Trim(); + state.OutputFilePath, + albumCoverInput, + mapArgs, + metadata).Trim(); } protected override string GetOutputFileExtension(EncodingJob state) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs index b23bd16f3..490a51128 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJob.cs @@ -64,6 +64,7 @@ namespace MediaBrowser.MediaEncoding.Encoder public long? InputFileSize { get; set; } public string OutputAudioSync = "1"; public string OutputVideoSync = "vfr"; + public string AlbumCoverPath { get; set; } public string GetMimeType(string outputPath) { diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index ff5a3010e..1544a78b6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -60,6 +60,14 @@ namespace MediaBrowser.MediaEncoding.Encoder state.IsInputVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase); + var primaryImage = item.GetImageInfo(ImageType.Primary, 0) ?? + item.Parents.Select(i => i.GetImageInfo(ImageType.Primary, 0)).FirstOrDefault(i => i != null); + + if (primaryImage != null) + { + state.AlbumCoverPath = primaryImage.Path; + } + var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(request.ItemId, null, false, new[] { MediaType.Audio, MediaType.Video }, cancellationToken).ConfigureAwait(false); var mediaSource = string.IsNullOrEmpty(request.MediaSourceId) From 8537cbe6c2e1b6a5508d3f13bf0ec0224e88b452 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Apr 2016 12:54:26 -0400 Subject: [PATCH 212/852] add audio sync to converted recordings --- .../LiveTv/EmbyTV/EncodedRecorder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index 63d0846fc..fa4f82136 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { audioChannels = audioStream.Channels ?? audioChannels; } - return "-codec:a:0 aac -strict experimental -ab 320000"; + return "-codec:a:0 aac -strict experimental -ab 320000 -af \"async=1000\""; } private bool EncodeVideo(MediaSourceInfo mediaSource) From a4f1c264b098fd691f12d377d11665917a6c057c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Apr 2016 12:54:51 -0400 Subject: [PATCH 213/852] update encoding log --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 45f1a64c9..dce29f6de 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1033,7 +1033,7 @@ namespace MediaBrowser.Api.Playback process.BeginOutputReadLine(); // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream); + Task.Run(() => StartStreamingLog(transcodingJob, state, process.StandardError.BaseStream, state.LogFileStream)); // Wait for the file to exist before proceeeding while (!FileSystem.FileExists(state.WaitForPath ?? outputPath) && !transcodingJob.HasExited) @@ -1076,7 +1076,7 @@ namespace MediaBrowser.Api.Playback return true; } - private async void StartStreamingLog(TranscodingJob transcodingJob, StreamState state, Stream source, Stream target) + private async Task StartStreamingLog(TranscodingJob transcodingJob, StreamState state, Stream source, Stream target) { try { From 1a02365f781f01e1efe9b12241a7368ae1cd5ba8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Apr 2016 23:59:46 -0400 Subject: [PATCH 214/852] cinema mode fixes --- .../Entities/InternalItemsQuery.cs | 2 -- .../Intros/DefaultIntroProvider.cs | 7 +------ .../Library/LocalTrailerPostScanTask.cs | 11 +++++++---- .../Persistence/SqliteItemRepository.cs | 14 -------------- 4 files changed, 8 insertions(+), 26 deletions(-) diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index fbf246b3a..f3b4f4053 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -123,7 +123,6 @@ namespace MediaBrowser.Controller.Entities public SourceType[] SourceTypes { get; set; } public SourceType[] ExcludeSourceTypes { get; set; } public TrailerType[] TrailerTypes { get; set; } - public TrailerType[] ExcludeTrailerTypes { get; set; } public DayOfWeek[] AirDays { get; set; } public SeriesStatus[] SeriesStatuses { get; set; } @@ -165,7 +164,6 @@ namespace MediaBrowser.Controller.Entities SourceTypes = new SourceType[] { }; ExcludeSourceTypes = new SourceType[] { }; TrailerTypes = new TrailerType[] { }; - ExcludeTrailerTypes = new TrailerType[] { }; AirDays = new DayOfWeek[] { }; SeriesStatuses = new SeriesStatus[] { }; } diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 9ebae5d91..49012c65a 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -102,15 +102,10 @@ namespace MediaBrowser.Server.Implementations.Intros if (trailerTypes.Count > 0) { - var excludeTrailerTypes = Enum.GetNames(typeof(TrailerType)) - .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) - .Except(trailerTypes) - .ToArray(); - var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - ExcludeTrailerTypes = excludeTrailerTypes + TrailerTypes = trailerTypes.ToArray() }); candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer diff --git a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs index 96d570ef9..5fc9c3168 100644 --- a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs @@ -27,13 +27,16 @@ namespace MediaBrowser.Server.Implementations.Library .Cast() .ToList(); + var trailerTypes = Enum.GetNames(typeof(TrailerType)) + .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) + .Except(new[] { TrailerType.LocalTrailer }) + .ToArray(); + var trailers = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - ExcludeTrailerTypes = new[] - { - TrailerType.LocalTrailer - } + TrailerTypes = trailerTypes + }).ToArray(); var numComplete = 0; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 783bd5ff4..4f724fe40 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1961,20 +1961,6 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add(clause); } - if (query.ExcludeTrailerTypes.Length > 0) - { - var clauses = new List(); - var index = 0; - foreach (var type in query.ExcludeTrailerTypes) - { - clauses.Add("(TrailerTypes is null OR TrailerTypes not like @TrailerTypes" + index + ")"); - cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; - index++; - } - var clause = "(" + string.Join(" AND ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - if (query.IsAiring.HasValue) { if (query.IsAiring.Value) From 5d28c65783f850db58ea990a04ec09da38c24442 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 00:00:28 -0400 Subject: [PATCH 215/852] update recordings --- .../LiveTv/EmbyTV/DirectRecorder.cs | 10 +++++++++- .../LiveTv/EmbyTV/EncodedRecorder.cs | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 98249f5ac..54443d9ca 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -42,8 +42,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV _logger.Info("Copying recording stream to file {0}", targetFile); - if (!mediaSource.RunTimeTicks.HasValue) + if (mediaSource.RunTimeTicks.HasValue) { + // The media source already has a fixed duration + // But add another stop 1 minute later just in case the recording gets stuck for any reason + var durationToken = new CancellationTokenSource(duration.Add(TimeSpan.FromMinutes(1))); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } + else + { + // The media source if infinite so we need to handle stopping ourselves var durationToken = new CancellationTokenSource(duration); cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; } diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index fa4f82136..d589b2bc3 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -44,6 +44,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV public async Task Record(MediaSourceInfo mediaSource, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { + if (mediaSource.RunTimeTicks.HasValue) + { + // The media source already has a fixed duration + // But add another stop 1 minute later just in case the recording gets stuck for any reason + var durationToken = new CancellationTokenSource(duration.Add(TimeSpan.FromMinutes(1))); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } + else + { + // The media source if infinite so we need to handle stopping ourselves + var durationToken = new CancellationTokenSource(duration); + cancellationToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, durationToken.Token).Token; + } + _targetPath = targetFile; _fileSystem.CreateDirectory(Path.GetDirectoryName(targetFile)); From 19c7c26dada0fe85c3295b53af4a824cb9bd58bc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 00:00:45 -0400 Subject: [PATCH 216/852] omit qsv decoder when stream copying --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 12 +++++++++--- MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs | 12 +++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index dce29f6de..800f246c4 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -821,9 +821,14 @@ namespace MediaBrowser.Api.Playback /// System.String. protected string GetVideoDecoder(StreamState state) { - if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) + return null; + } + + if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) + { + if (string.Equals(ApiEntryPoint.Instance.GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { switch (state.MediaSource.VideoStream.Codec.ToLower()) { @@ -831,7 +836,8 @@ namespace MediaBrowser.Api.Playback case "h264": if (MediaEncoder.SupportsDecoder("h264_qsv")) { - return "-c:v h264_qsv "; + // Seeing stalls and failures with decoding. Not worth it compared to encoding. + //return "-c:v h264_qsv "; } break; case "mpeg2video": diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index 263efbb62..0ea48fab6 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -366,9 +366,14 @@ namespace MediaBrowser.MediaEncoding.Encoder /// System.String. protected string GetVideoDecoder(EncodingJob state) { - if (string.Equals(GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase)) { - if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) + return null; + } + + if (state.VideoStream != null && !string.IsNullOrWhiteSpace(state.VideoStream.Codec)) + { + if (string.Equals(GetEncodingOptions().HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { switch (state.MediaSource.VideoStream.Codec.ToLower()) { @@ -376,7 +381,8 @@ namespace MediaBrowser.MediaEncoding.Encoder case "h264": if (MediaEncoder.SupportsDecoder("h264_qsv")) { - return "-c:v h264_qsv "; + // Seeing stalls and failures with decoding. Not worth it compared to encoding. + //return "-c:v h264_qsv "; } break; case "mpeg2video": From 0708c23ed7400f82a7d15f8719b8bfbe5e7b8025 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 29 Apr 2016 23:59:46 -0400 Subject: [PATCH 217/852] cinema mode fixes --- .../Entities/InternalItemsQuery.cs | 2 -- .../Intros/DefaultIntroProvider.cs | 7 +------ .../Library/LocalTrailerPostScanTask.cs | 11 +++++++---- .../Persistence/SqliteItemRepository.cs | 14 -------------- 4 files changed, 8 insertions(+), 26 deletions(-) diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index fbf246b3a..f3b4f4053 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -123,7 +123,6 @@ namespace MediaBrowser.Controller.Entities public SourceType[] SourceTypes { get; set; } public SourceType[] ExcludeSourceTypes { get; set; } public TrailerType[] TrailerTypes { get; set; } - public TrailerType[] ExcludeTrailerTypes { get; set; } public DayOfWeek[] AirDays { get; set; } public SeriesStatus[] SeriesStatuses { get; set; } @@ -165,7 +164,6 @@ namespace MediaBrowser.Controller.Entities SourceTypes = new SourceType[] { }; ExcludeSourceTypes = new SourceType[] { }; TrailerTypes = new TrailerType[] { }; - ExcludeTrailerTypes = new TrailerType[] { }; AirDays = new DayOfWeek[] { }; SeriesStatuses = new SeriesStatus[] { }; } diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 9ebae5d91..49012c65a 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -102,15 +102,10 @@ namespace MediaBrowser.Server.Implementations.Intros if (trailerTypes.Count > 0) { - var excludeTrailerTypes = Enum.GetNames(typeof(TrailerType)) - .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) - .Except(trailerTypes) - .ToArray(); - var trailerResult = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - ExcludeTrailerTypes = excludeTrailerTypes + TrailerTypes = trailerTypes.ToArray() }); candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer diff --git a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs index 96d570ef9..5fc9c3168 100644 --- a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs @@ -27,13 +27,16 @@ namespace MediaBrowser.Server.Implementations.Library .Cast() .ToList(); + var trailerTypes = Enum.GetNames(typeof(TrailerType)) + .Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)) + .Except(new[] { TrailerType.LocalTrailer }) + .ToArray(); + var trailers = _libraryManager.GetItemList(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - ExcludeTrailerTypes = new[] - { - TrailerType.LocalTrailer - } + TrailerTypes = trailerTypes + }).ToArray(); var numComplete = 0; diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index fcc39deb5..25582852f 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1960,20 +1960,6 @@ namespace MediaBrowser.Server.Implementations.Persistence whereClauses.Add(clause); } - if (query.ExcludeTrailerTypes.Length > 0) - { - var clauses = new List(); - var index = 0; - foreach (var type in query.ExcludeTrailerTypes) - { - clauses.Add("(TrailerTypes is null OR TrailerTypes not like @TrailerTypes" + index + ")"); - cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; - index++; - } - var clause = "(" + string.Join(" AND ", clauses.ToArray()) + ")"; - whereClauses.Add(clause); - } - if (query.IsAiring.HasValue) { if (query.IsAiring.Value) From 06b3016f56e565d0ba85102104b8b7433774234b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 00:21:35 -0400 Subject: [PATCH 218/852] add LaunchUrl --- MediaBrowser.Server.Mac/Native/BaseMonoApp.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs index 33df83b2f..c8c81e917 100644 --- a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs @@ -106,6 +106,11 @@ namespace MediaBrowser.Server.Mac { } + public void LaunchUrl(string url) + { + throw new NotImplementedException(); + } + public INetworkManager CreateNetworkManager(ILogger logger) { return new NetworkManager(logger); From 535b327e35ac347bd5d05a61c1df76c9ac7ffcd9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 00:24:45 -0400 Subject: [PATCH 219/852] add ffmpeg info --- MediaBrowser.Server.Mac/Native/BaseMonoApp.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs index c8c81e917..9c2d20d99 100644 --- a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs @@ -111,6 +111,52 @@ namespace MediaBrowser.Server.Mac throw new NotImplementedException(); } + public FFMpegInstallInfo GetFfmpegInstallInfo() + { + return GetInfo(Environment); + } + + public static FFMpegDownloadInfo GetInfo(NativeEnvironment environment) + { + var info = new FFMpegDownloadInfo(); + + info.ArchiveType = "7z"; + + switch (environment.SystemArchitecture) + { + case Architecture.X86_X64: + info.Version = "20160124"; + break; + case Architecture.X86: + info.Version = "20150110"; + break; + } + + info.DownloadUrls = GetDownloadUrls(environment); + + return info; + } + + private static string[] GetDownloadUrls(NativeEnvironment environment) + { + switch (environment.SystemArchitecture) + { + case Architecture.X86_X64: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.5.7z" + }; + case Architecture.X86: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x86-2.5.3.7z" + }; + } + + // No version available + return new string[] { }; + } + public INetworkManager CreateNetworkManager(ILogger logger) { return new NetworkManager(logger); From 657e924132be65d1d1700d857d9e12bbe3196dcb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 00:27:55 -0400 Subject: [PATCH 220/852] update ffmpeg info --- MediaBrowser.Server.Mac/Native/BaseMonoApp.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs index 9c2d20d99..abc373600 100644 --- a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Reflection; using System.Text.RegularExpressions; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Startup.Common.FFMpeg; namespace MediaBrowser.Server.Mac { @@ -116,9 +117,9 @@ namespace MediaBrowser.Server.Mac return GetInfo(Environment); } - public static FFMpegDownloadInfo GetInfo(NativeEnvironment environment) + public static FFMpegInstallInfo GetInfo(NativeEnvironment environment) { - var info = new FFMpegDownloadInfo(); + var info = new FFMpegInstallInfo(); info.ArchiveType = "7z"; From bfb1d8119162d34cffce49cde16141234cffe177 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 30 Apr 2016 00:31:23 -0400 Subject: [PATCH 221/852] update mac project --- MediaBrowser.Server.Mac/MenuBarIcon.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Server.Mac/MenuBarIcon.cs b/MediaBrowser.Server.Mac/MenuBarIcon.cs index 51ba7f432..865f45057 100644 --- a/MediaBrowser.Server.Mac/MenuBarIcon.cs +++ b/MediaBrowser.Server.Mac/MenuBarIcon.cs @@ -88,17 +88,17 @@ namespace MediaBrowser.Server.Mac private void Community(NSObject sender) { - BrowserLauncher.OpenCommunity(Logger); + BrowserLauncher.OpenCommunity(MainClass.AppHost); } private void Configure(NSObject sender) { - BrowserLauncher.OpenDashboard(MainClass.AppHost, Logger); + BrowserLauncher.OpenDashboard(MainClass.AppHost); } private void Browse(NSObject sender) { - BrowserLauncher.OpenWebClient(MainClass.AppHost, Logger); + BrowserLauncher.OpenWebClient(MainClass.AppHost); } public void Terminate() From bbf6ee9c1dca4f3cf877cea5d0cef2638a46cee9 Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 30 Apr 2016 00:35:02 -0400 Subject: [PATCH 222/852] update mac project --- .../Emby.Server.Mac.csproj | 199 ++++++++++++++---- 1 file changed, 162 insertions(+), 37 deletions(-) diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index 237325cfe..b61281f1b 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -32,6 +32,7 @@ true Developer ID Installer false + false true @@ -47,6 +48,7 @@ true Developer ID Installer false + false full @@ -63,6 +65,7 @@ false false false + false @@ -89,7 +92,6 @@ - @@ -260,9 +262,6 @@ Resources\dashboard-ui\addplugin.html - - Resources\dashboard-ui\advanced.html - Resources\dashboard-ui\appservices.html @@ -281,9 +280,6 @@ Resources\dashboard-ui\channels.html - - Resources\dashboard-ui\channelsettings.html - Resources\dashboard-ui\cinemamodeconfiguration.html @@ -317,9 +313,6 @@ Resources\dashboard-ui\dlnaprofiles.html - - Resources\dashboard-ui\dlnaserversettings.html - Resources\dashboard-ui\dlnasettings.html @@ -425,9 +418,6 @@ Resources\dashboard-ui\metadata.html - - Resources\dashboard-ui\metadataadvanced.html - Resources\dashboard-ui\metadataimages.html @@ -524,9 +514,6 @@ Resources\dashboard-ui\streamingsettings.html - - Resources\dashboard-ui\support.html - Resources\dashboard-ui\supporterkey.html @@ -929,6 +916,21 @@ Resources\dashboard-ui\bower_components\Swiper\src\less\swiper.less + + Resources\dashboard-ui\bower_components\alameda\.bower.json + + + Resources\dashboard-ui\bower_components\alameda\LICENSE + + + Resources\dashboard-ui\bower_components\alameda\alameda.js + + + Resources\dashboard-ui\bower_components\alameda\bower.json + + + Resources\dashboard-ui\bower_components\alameda\shrinktest.sh + Resources\dashboard-ui\bower_components\cryptojslib\.bower.json @@ -1334,6 +1336,12 @@ Resources\dashboard-ui\bower_components\emby-webcomponents\scrollhelper.js + + Resources\dashboard-ui\bower_components\emby-webcomponents\scrollstyles.css + + + Resources\dashboard-ui\bower_components\emby-webcomponents\servernotifications.js + Resources\dashboard-ui\bower_components\emby-webcomponents\usersettings.js @@ -1571,6 +1579,9 @@ Resources\dashboard-ui\bower_components\emby-webcomponents\images\persistentimagefetcher.js + + Resources\dashboard-ui\bower_components\emby-webcomponents\input\api.js + Resources\dashboard-ui\bower_components\emby-webcomponents\loading\loading-lite.js @@ -1970,6 +1981,9 @@ Resources\dashboard-ui\bower_components\iron-a11y-keys-behavior\iron-a11y-keys-behavior.html + + Resources\dashboard-ui\bower_components\iron-a11y-keys-behavior\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\iron-a11y-keys-behavior\demo\index.html @@ -2162,9 +2176,18 @@ Resources\dashboard-ui\bower_components\iron-demo-helpers\index.html + + Resources\dashboard-ui\bower_components\iron-demo-helpers\url-bar.html + + + Resources\dashboard-ui\bower_components\iron-demo-helpers\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\iron-demo-helpers\demo\index.html + + Resources\dashboard-ui\bower_components\iron-demo-helpers\demo\url-bar.html + Resources\dashboard-ui\bower_components\iron-demo-helpers\test\basic.html @@ -2513,6 +2536,9 @@ Resources\dashboard-ui\bower_components\iron-input\iron-input.html + + Resources\dashboard-ui\bower_components\iron-input\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\iron-input\demo\index.html @@ -2528,9 +2554,60 @@ Resources\dashboard-ui\bower_components\iron-input\test\letters-only.html + + Resources\dashboard-ui\bower_components\iron-location\.bower.json + + + Resources\dashboard-ui\bower_components\iron-location\.gitignore + + + Resources\dashboard-ui\bower_components\iron-location\.travis.yml + + + Resources\dashboard-ui\bower_components\iron-location\CONTRIBUTING.md + + + Resources\dashboard-ui\bower_components\iron-location\README.md + + + Resources\dashboard-ui\bower_components\iron-location\bower.json + + + Resources\dashboard-ui\bower_components\iron-location\index.html + + + Resources\dashboard-ui\bower_components\iron-location\iron-location.html + + + Resources\dashboard-ui\bower_components\iron-location\iron-query-params.html + Resources\dashboard-ui\bower_components\iron-location\.github\ISSUE_TEMPLATE.md + + Resources\dashboard-ui\bower_components\iron-location\demo\index.html + + + Resources\dashboard-ui\bower_components\iron-location\demo\iron-query-params.html + + + Resources\dashboard-ui\bower_components\iron-location\test\index.html + + + Resources\dashboard-ui\bower_components\iron-location\test\initialization-cases.html + + + Resources\dashboard-ui\bower_components\iron-location\test\initialization-iframe.html + + + Resources\dashboard-ui\bower_components\iron-location\test\initialization-tests.html + + + Resources\dashboard-ui\bower_components\iron-location\test\iron-location.html + + + Resources\dashboard-ui\bower_components\iron-location\test\iron-query-params.html + Resources\dashboard-ui\bower_components\iron-media-query\.bower.json @@ -2702,12 +2779,18 @@ Resources\dashboard-ui\bower_components\iron-overlay-behavior\test\index.html + + Resources\dashboard-ui\bower_components\iron-overlay-behavior\test\iron-overlay-backdrop.html + Resources\dashboard-ui\bower_components\iron-overlay-behavior\test\iron-overlay-behavior.html Resources\dashboard-ui\bower_components\iron-overlay-behavior\test\test-buttons.html + + Resources\dashboard-ui\bower_components\iron-overlay-behavior\test\test-menu-button.html + Resources\dashboard-ui\bower_components\iron-overlay-behavior\test\test-overlay.html @@ -2858,6 +2941,9 @@ Resources\dashboard-ui\bower_components\iron-selector\iron-selector.html + + Resources\dashboard-ui\bower_components\iron-selector\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\iron-selector\demo\index.html @@ -3353,6 +3439,36 @@ Resources\dashboard-ui\bower_components\jstree\src\themes\default-dark\throbber.gif + + Resources\dashboard-ui\bower_components\libjass\.bower.json + + + Resources\dashboard-ui\bower_components\libjass\CHANGELOG.md + + + Resources\dashboard-ui\bower_components\libjass\LICENSE + + + Resources\dashboard-ui\bower_components\libjass\README.md + + + Resources\dashboard-ui\bower_components\libjass\libjass.css + + + Resources\dashboard-ui\bower_components\libjass\libjass.js + + + Resources\dashboard-ui\bower_components\libjass\libjass.js.map + + + Resources\dashboard-ui\bower_components\libjass\libjass.min.js + + + Resources\dashboard-ui\bower_components\libjass\libjass.min.js.map + + + Resources\dashboard-ui\bower_components\libjass\package.json + Resources\dashboard-ui\bower_components\marked\.bower.json @@ -4163,6 +4279,9 @@ Resources\dashboard-ui\bower_components\neon-animation\web-animations.html + + Resources\dashboard-ui\bower_components\neon-animation\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\neon-animation\animations\cascaded-animation.html @@ -4307,6 +4426,9 @@ Resources\dashboard-ui\bower_components\neon-animation\test\index.html + + Resources\dashboard-ui\bower_components\neon-animation\test\neon-animated-pages-lazy.html + Resources\dashboard-ui\bower_components\neon-animation\test\neon-animated-pages.html @@ -4751,6 +4873,9 @@ Resources\dashboard-ui\bower_components\paper-input\paper-textarea.html + + Resources\dashboard-ui\bower_components\paper-input\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\paper-input\demo\index.html @@ -4820,6 +4945,9 @@ Resources\dashboard-ui\bower_components\paper-item\paper-item.html + + Resources\dashboard-ui\bower_components\paper-item\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\paper-item\demo\index.html @@ -4925,6 +5053,9 @@ Resources\dashboard-ui\bower_components\paper-menu-button\paper-menu-button.html + + Resources\dashboard-ui\bower_components\paper-menu-button\.github\ISSUE_TEMPLATE.md + Resources\dashboard-ui\bower_components\paper-menu-button\demo\index.html @@ -8879,6 +9010,12 @@ Resources\dashboard-ui\components\chromecasthelpers.js + + Resources\dashboard-ui\components\favoriteitems.js + + + Resources\dashboard-ui\components\filedownloader.js + Resources\dashboard-ui\components\humanedate.js @@ -8888,6 +9025,9 @@ Resources\dashboard-ui\components\remotecontrolautoplay.js + + Resources\dashboard-ui\components\servertestermessage.js + Resources\dashboard-ui\components\sharingwidget.js @@ -9068,6 +9208,9 @@ Resources\dashboard-ui\css\images\logindefault.png + + Resources\dashboard-ui\css\images\logo.png + Resources\dashboard-ui\css\images\logo536.png @@ -9161,9 +9304,6 @@ Resources\dashboard-ui\css\images\editor\missingprimaryimage.png - - Resources\dashboard-ui\css\images\editor\missingtrailer.png - Resources\dashboard-ui\css\images\items\detail\audio.png @@ -9338,9 +9478,6 @@ Resources\dashboard-ui\legacy\fnchecked.js - - Resources\dashboard-ui\legacy\objectassign.js - Resources\dashboard-ui\legacy\selectmenu.js @@ -9350,9 +9487,6 @@ Resources\dashboard-ui\scripts\addpluginpage.js - - Resources\dashboard-ui\scripts\advancedconfigurationpage.js - Resources\dashboard-ui\scripts\alphapicker.js @@ -9377,9 +9511,6 @@ Resources\dashboard-ui\scripts\channels.js - - Resources\dashboard-ui\scripts\channelsettings.js - Resources\dashboard-ui\scripts\channelslatest.js @@ -9416,9 +9547,6 @@ Resources\dashboard-ui\scripts\dlnaprofiles.js - - Resources\dashboard-ui\scripts\dlnaserversettings.js - Resources\dashboard-ui\scripts\dlnasettings.js @@ -9464,6 +9592,9 @@ Resources\dashboard-ui\scripts\gamesystemspage.js + + Resources\dashboard-ui\scripts\homefavorites.js + Resources\dashboard-ui\scripts\homenextup.js @@ -9578,9 +9709,6 @@ Resources\dashboard-ui\scripts\mediaplayer.js - - Resources\dashboard-ui\scripts\metadataadvanced.js - Resources\dashboard-ui\scripts\metadataconfigurationpage.js @@ -9917,9 +10045,6 @@ Resources\dashboard-ui\strings\ru.json - - Resources\dashboard-ui\strings\server.json - Resources\dashboard-ui\strings\sl-SI.json From e5a0d8dd8442e17a3ef398933a040bab77f8472f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 01:35:53 -0400 Subject: [PATCH 223/852] update mac project --- MediaBrowser.Server.Mac/Native/BaseMonoApp.cs | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs index abc373600..9c7421e42 100644 --- a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Text.RegularExpressions; using MediaBrowser.Controller.Power; using MediaBrowser.Server.Startup.Common.FFMpeg; +using System.Diagnostics; namespace MediaBrowser.Server.Mac { @@ -109,7 +110,38 @@ namespace MediaBrowser.Server.Mac public void LaunchUrl(string url) { - throw new NotImplementedException(); + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = url + }, + + EnableRaisingEvents = true, + }; + + process.Exited += ProcessExited; + + try + { + process.Start(); + } + catch (Exception ex) + { + _logger.ErrorException("Error launching url: {0}", ex, url); + + throw; + } + } + + /// + /// Processes the exited. + /// + /// The sender. + /// The instance containing the event data. + private static void ProcessExited(object sender, EventArgs e) + { + ((Process)sender).Dispose(); } public FFMpegInstallInfo GetFfmpegInstallInfo() From 873f1824c12fc06b07d4e7ec1bdc793c1b3d6b4b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 13:06:40 -0400 Subject: [PATCH 224/852] 3.0.5947 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 2d6b5c29a..2369b6a48 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5946")] +[assembly: AssemblyVersion("3.0.5947")] From 04ba2d57aca90ade64fafac0f3cd474645c79154 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 14:22:54 -0400 Subject: [PATCH 225/852] fixes #1562 - Sync status included in BaseItemDto does not reflect actual sync status. --- MediaBrowser.Server.Implementations/Dto/DtoService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 2ee55edb9..7adde5c27 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -282,7 +282,7 @@ namespace MediaBrowser.Server.Implementations.Dto else if (dto.HasSyncJob.Value) { - dto.SyncStatus = SyncJobItemStatus.Queued; + dto.SyncStatus = syncProgress.Where(i => string.Equals(i.ItemId, dto.Id, StringComparison.OrdinalIgnoreCase)).Select(i => i.Status).Max(); } } } @@ -307,7 +307,7 @@ namespace MediaBrowser.Server.Implementations.Dto else if (dto.HasSyncJob.Value) { - dto.SyncStatus = SyncJobItemStatus.Queued; + dto.SyncStatus = syncProgress.Where(i => string.Equals(i.ItemId, dto.Id, StringComparison.OrdinalIgnoreCase)).Select(i => i.Status).Max(); } } } From a15a762ba114683ffcc4c6aab5974d24f8f32c02 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 15:16:43 -0400 Subject: [PATCH 226/852] fixes #1484 - (Feature request) Make emby choose output stream based on ffmpeg config --- MediaBrowser.Api/Playback/MediaInfoService.cs | 7 +++-- .../MediaEncoding/IMediaEncoder.cs | 3 ++- .../ContentDirectory/ContentDirectory.cs | 8 ++++-- .../ContentDirectory/ControlHandler.cs | 7 +++-- MediaBrowser.Dlna/Didl/DidlBuilder.cs | 9 ++++--- MediaBrowser.Dlna/Main/DlnaEntryPoint.cs | 8 ++++-- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 11 +++++--- MediaBrowser.Dlna/PlayTo/PlayToManager.cs | 8 ++++-- .../Encoder/MediaEncoder.cs | 26 +++++++++++++++++-- MediaBrowser.Model/Dlna/ILocalPlayer.cs | 13 ++++++++++ MediaBrowser.Model/Dlna/StreamBuilder.cs | 23 +++++++++++++--- .../Sync/SyncJobProcessor.cs | 4 +-- .../ApplicationHost.cs | 2 +- .../FFMpeg/FFmpegValidator.cs | 4 ++- 14 files changed, 105 insertions(+), 28 deletions(-) diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index ffe7c50c8..2d9cc40c0 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Api.Playback { @@ -66,14 +67,16 @@ namespace MediaBrowser.Api.Playback private readonly ILibraryManager _libraryManager; private readonly IServerConfigurationManager _config; private readonly INetworkManager _networkManager; + private readonly IMediaEncoder _mediaEncoder; - public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager) + public MediaInfoService(IMediaSourceManager mediaSourceManager, IDeviceManager deviceManager, ILibraryManager libraryManager, IServerConfigurationManager config, INetworkManager networkManager, IMediaEncoder mediaEncoder) { _mediaSourceManager = mediaSourceManager; _deviceManager = deviceManager; _libraryManager = libraryManager; _config = config; _networkManager = networkManager; + _mediaEncoder = mediaEncoder; } public object Get(GetBitrateTestBytes request) @@ -241,7 +244,7 @@ namespace MediaBrowser.Api.Playback int? subtitleStreamIndex, string playSessionId) { - var streamBuilder = new StreamBuilder(Logger); + var streamBuilder = new StreamBuilder(_mediaEncoder, Logger); var options = new VideoOptions { diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index d2feb4116..7c3959f6e 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -4,13 +4,14 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Dlna; namespace MediaBrowser.Controller.MediaEncoding { /// /// Interface IMediaEncoder /// - public interface IMediaEncoder + public interface IMediaEncoder : ITranscoderSupport { /// /// Gets the encoder path. diff --git a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs index 21289970e..093b37df3 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ContentDirectory.cs @@ -12,6 +12,7 @@ using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.ContentDirectory { @@ -27,6 +28,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private readonly IChannelManager _channelManager; private readonly IMediaSourceManager _mediaSourceManager; private readonly IUserViewManager _userViewManager; + private readonly Func _mediaEncoder; public ContentDirectory(IDlnaManager dlna, IUserDataManager userDataManager, @@ -35,7 +37,7 @@ namespace MediaBrowser.Dlna.ContentDirectory IServerConfigurationManager config, IUserManager userManager, ILogger logger, - IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager) + IHttpClient httpClient, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, Func mediaEncoder) : base(logger, httpClient) { _dlna = dlna; @@ -48,6 +50,7 @@ namespace MediaBrowser.Dlna.ContentDirectory _channelManager = channelManager; _mediaSourceManager = mediaSourceManager; _userViewManager = userViewManager; + _mediaEncoder = mediaEncoder; } private int SystemUpdateId @@ -89,7 +92,8 @@ namespace MediaBrowser.Dlna.ContentDirectory _localization, _channelManager, _mediaSourceManager, - _userViewManager) + _userViewManager, + _mediaEncoder()) .ProcessControlRequest(request); } diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 01c7c33b6..34fb2a6df 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -23,6 +23,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.ContentDirectory { @@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private readonly IServerConfigurationManager _config; private readonly User _user; private readonly IUserViewManager _userViewManager; + private readonly IMediaEncoder _mediaEncoder; private const string NS_DC = "http://purl.org/dc/elements/1.1/"; private const string NS_DIDL = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"; @@ -47,7 +49,7 @@ namespace MediaBrowser.Dlna.ContentDirectory private readonly DeviceProfile _profile; - public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager) + public ControlHandler(ILogger logger, ILibraryManager libraryManager, DeviceProfile profile, string serverAddress, string accessToken, IImageProcessor imageProcessor, IUserDataManager userDataManager, User user, int systemUpdateId, IServerConfigurationManager config, ILocalizationManager localization, IChannelManager channelManager, IMediaSourceManager mediaSourceManager, IUserViewManager userViewManager, IMediaEncoder mediaEncoder) : base(config, logger) { _libraryManager = libraryManager; @@ -56,10 +58,11 @@ namespace MediaBrowser.Dlna.ContentDirectory _systemUpdateId = systemUpdateId; _channelManager = channelManager; _userViewManager = userViewManager; + _mediaEncoder = mediaEncoder; _profile = profile; _config = config; - _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager); + _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger, libraryManager, _mediaEncoder); } protected override IEnumerable> GetResult(string methodName, Headers methodParams) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 89d00eb32..af833a85c 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -19,6 +19,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Xml; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Configuration; namespace MediaBrowser.Dlna.Didl @@ -42,8 +43,9 @@ namespace MediaBrowser.Dlna.Didl private readonly IMediaSourceManager _mediaSourceManager; private readonly ILogger _logger; private readonly ILibraryManager _libraryManager; + private readonly IMediaEncoder _mediaEncoder; - public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, ILogger logger, ILibraryManager libraryManager) + public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, ILogger logger, ILibraryManager libraryManager, IMediaEncoder mediaEncoder) { _profile = profile; _imageProcessor = imageProcessor; @@ -53,6 +55,7 @@ namespace MediaBrowser.Dlna.Didl _mediaSourceManager = mediaSourceManager; _logger = logger; _libraryManager = libraryManager; + _mediaEncoder = mediaEncoder; _accessToken = accessToken; _user = user; } @@ -142,7 +145,7 @@ namespace MediaBrowser.Dlna.Didl { var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList(); - streamInfo = new StreamBuilder(GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions + streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildVideoItem(new VideoOptions { ItemId = GetClientId(video), MediaSources = sources, @@ -385,7 +388,7 @@ namespace MediaBrowser.Dlna.Didl { var sources = _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList(); - streamInfo = new StreamBuilder(GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions + streamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger(options)).BuildAudioItem(new AudioOptions { ItemId = GetClientId(audio), MediaSources = sources, diff --git a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs index 37584f006..733bda9ae 100644 --- a/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs +++ b/MediaBrowser.Dlna/Main/DlnaEntryPoint.cs @@ -14,6 +14,7 @@ using MediaBrowser.Dlna.Ssdp; using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.Main { @@ -34,6 +35,7 @@ namespace MediaBrowser.Dlna.Main private readonly IUserDataManager _userDataManager; private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; + private readonly IMediaEncoder _mediaEncoder; private readonly SsdpHandler _ssdpHandler; private readonly IDeviceDiscovery _deviceDiscovery; @@ -54,7 +56,7 @@ namespace MediaBrowser.Dlna.Main IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, - ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery) + ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery, IMediaEncoder mediaEncoder) { _config = config; _appHost = appHost; @@ -69,6 +71,7 @@ namespace MediaBrowser.Dlna.Main _localization = localization; _mediaSourceManager = mediaSourceManager; _deviceDiscovery = deviceDiscovery; + _mediaEncoder = mediaEncoder; _ssdpHandler = (SsdpHandler)ssdpHandler; _logger = logManager.GetLogger("Dlna"); } @@ -196,7 +199,8 @@ namespace MediaBrowser.Dlna.Main _config, _userDataManager, _localization, - _mediaSourceManager); + _mediaSourceManager, + _mediaEncoder); _manager.Start(); } diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index db5e0ee29..80bb756ef 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -18,6 +18,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.PlayTo { @@ -35,6 +36,7 @@ namespace MediaBrowser.Dlna.PlayTo private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; private readonly IConfigurationManager _config; + private readonly IMediaEncoder _mediaEncoder; private readonly IDeviceDiscovery _deviceDiscovery; private readonly string _serverAddress; @@ -74,7 +76,7 @@ namespace MediaBrowser.Dlna.PlayTo get { return IsSessionActive; } } - 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, IConfigurationManager config) + 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, IConfigurationManager config, IMediaEncoder mediaEncoder) { _session = session; _sessionManager = sessionManager; @@ -88,6 +90,7 @@ namespace MediaBrowser.Dlna.PlayTo _localization = localization; _mediaSourceManager = mediaSourceManager; _config = config; + _mediaEncoder = mediaEncoder; _accessToken = accessToken; _logger = logger; _creationTime = DateTime.UtcNow; @@ -478,7 +481,7 @@ namespace MediaBrowser.Dlna.PlayTo playlistItem.StreamUrl = playlistItem.StreamInfo.ToDlnaUrl(_serverAddress, _accessToken); - var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _libraryManager) + var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger, _libraryManager, _mediaEncoder) .GetItemDidl(_config.GetDlnaConfiguration(), item, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo); playlistItem.Didl = itemXml; @@ -550,7 +553,7 @@ namespace MediaBrowser.Dlna.PlayTo { return new PlaylistItem { - StreamInfo = new StreamBuilder(GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions + StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildVideoItem(new VideoOptions { ItemId = item.Id.ToString("N"), MediaSources = mediaSources, @@ -570,7 +573,7 @@ namespace MediaBrowser.Dlna.PlayTo { return new PlaylistItem { - StreamInfo = new StreamBuilder(GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions + StreamInfo = new StreamBuilder(_mediaEncoder, GetStreamBuilderLogger()).BuildAudioItem(new AudioOptions { ItemId = item.Id.ToString("N"), MediaSources = mediaSources, diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index 18daef331..bbb9bf6de 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -12,6 +12,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net; +using MediaBrowser.Controller.MediaEncoding; namespace MediaBrowser.Dlna.PlayTo { @@ -32,11 +33,12 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IDeviceDiscovery _deviceDiscovery; private readonly IMediaSourceManager _mediaSourceManager; + private readonly IMediaEncoder _mediaEncoder; private readonly List _nonRendererUrls = new List(); 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) + 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, IMediaEncoder mediaEncoder) { _logger = logger; _sessionManager = sessionManager; @@ -51,6 +53,7 @@ namespace MediaBrowser.Dlna.PlayTo _userDataManager = userDataManager; _localization = localization; _mediaSourceManager = mediaSourceManager; + _mediaEncoder = mediaEncoder; } public void Start() @@ -132,7 +135,8 @@ namespace MediaBrowser.Dlna.PlayTo _userDataManager, _localization, _mediaSourceManager, - _config); + _config, + _mediaEncoder); controller.Init(device); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 01fb31d0c..399fdead9 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -96,15 +96,23 @@ namespace MediaBrowser.MediaEncoding.Encoder FFMpegPath = ffMpegPath; } + private List _encoders = new List(); public void SetAvailableEncoders(List list) { - + _encoders = list.ToList(); + //_logger.Info("Supported encoders: {0}", string.Join(",", list.ToArray())); } private List _decoders = new List(); public void SetAvailableDecoders(List list) { _decoders = list.ToList(); + //_logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); + } + + public bool SupportsEncoder(string decoder) + { + return _encoders.Contains(decoder, StringComparer.OrdinalIgnoreCase); } public bool SupportsDecoder(string decoder) @@ -112,6 +120,20 @@ namespace MediaBrowser.MediaEncoding.Encoder return _decoders.Contains(decoder, StringComparer.OrdinalIgnoreCase); } + public bool CanEncodeToAudioCodec(string codec) + { + if (string.Equals(codec, "opus", StringComparison.OrdinalIgnoreCase)) + { + codec = "libopus"; + } + else if (string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase)) + { + codec = "libmp3lame"; + } + + return SupportsEncoder(codec); + } + /// /// Gets the encoder path. /// @@ -296,7 +318,7 @@ namespace MediaBrowser.MediaEncoding.Encoder 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) { diff --git a/MediaBrowser.Model/Dlna/ILocalPlayer.cs b/MediaBrowser.Model/Dlna/ILocalPlayer.cs index 55e11ec4b..9de360023 100644 --- a/MediaBrowser.Model/Dlna/ILocalPlayer.cs +++ b/MediaBrowser.Model/Dlna/ILocalPlayer.cs @@ -23,4 +23,17 @@ namespace MediaBrowser.Model.Dlna /// true if this instance [can access URL] the specified URL; otherwise, false. bool CanAccessUrl(string url, bool requiresCustomRequestHeaders); } + + public interface ITranscoderSupport + { + bool CanEncodeToAudioCodec(string codec); + } + + public class FullTranscoderSupport : ITranscoderSupport + { + public bool CanEncodeToAudioCodec(string codec) + { + return true; + } + } } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 98d246980..07a4b8995 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -13,15 +13,27 @@ namespace MediaBrowser.Model.Dlna { private readonly ILocalPlayer _localPlayer; private readonly ILogger _logger; + private readonly ITranscoderSupport _transcoderSupport; - public StreamBuilder(ILocalPlayer localPlayer, ILogger logger) + public StreamBuilder(ILocalPlayer localPlayer, ITranscoderSupport transcoderSupport, ILogger logger) { + _transcoderSupport = transcoderSupport; _localPlayer = localPlayer; _logger = logger; } + public StreamBuilder(ITranscoderSupport transcoderSupport, ILogger logger) + : this(new NullLocalPlayer(), transcoderSupport, logger) + { + } + + public StreamBuilder(ILocalPlayer localPlayer, ILogger logger) + : this(localPlayer, new FullTranscoderSupport(), logger) + { + } + public StreamBuilder(ILogger logger) - : this(new NullLocalPlayer(), logger) + : this(new NullLocalPlayer(), new FullTranscoderSupport(), logger) { } @@ -185,8 +197,11 @@ namespace MediaBrowser.Model.Dlna { if (i.Type == playlistItem.MediaType && i.Context == options.Context) { - transcodingProfile = i; - break; + if (_transcoderSupport.CanEncodeToAudioCodec(i.AudioCodec ?? i.Container)) + { + transcodingProfile = i; + break; + } } } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs index 10b872753..d95a4fefb 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs @@ -582,7 +582,7 @@ namespace MediaBrowser.Server.Implementations.Sync conversionOptions.ItemId = item.Id.ToString("N"); conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - var streamInfo = new StreamBuilder(_logger).BuildVideoItem(conversionOptions); + var streamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildVideoItem(conversionOptions); var mediaSource = streamInfo.MediaSource; // No sense creating external subs if we're already burning one into the video @@ -786,7 +786,7 @@ namespace MediaBrowser.Server.Implementations.Sync conversionOptions.ItemId = item.Id.ToString("N"); conversionOptions.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, false, user).ToList(); - var streamInfo = new StreamBuilder(_logger).BuildAudioItem(conversionOptions); + var streamInfo = new StreamBuilder(_mediaEncoder, _logger).BuildAudioItem(conversionOptions); var mediaSource = streamInfo.MediaSource; jobItem.MediaSourceId = streamInfo.MediaSourceId; diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 01575e71f..fd6dee0f6 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -515,7 +515,7 @@ namespace MediaBrowser.Server.Startup.Common UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager); RegisterSingleInstance(UserViewManager); - var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager, MediaSourceManager, UserViewManager); + var contentDirectory = new ContentDirectory(dlnaManager, UserDataManager, ImageProcessor, LibraryManager, ServerConfigurationManager, UserManager, LogManager.GetLogger("UpnpContentDirectory"), HttpClient, LocalizationManager, ChannelManager, MediaSourceManager, UserViewManager, () => MediaEncoder); RegisterSingleInstance(contentDirectory); var mediaRegistrar = new MediaReceiverRegistrar(LogManager.GetLogger("MediaReceiverRegistrar"), HttpClient, ServerConfigurationManager); diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs index 5ba5fb44a..0ae021407 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFmpegValidator.cs @@ -42,6 +42,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg catch { } + //_logger.Debug("ffmpeg decoder query result: {0}", output ?? string.Empty); var found = new List(); var required = new[] @@ -78,6 +79,7 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg catch { } + //_logger.Debug("ffmpeg encoder query result: {0}", output ?? string.Empty); var found = new List(); var required = new[] @@ -89,8 +91,8 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg //"libvpx", //"libvpx-vp9", "aac", - "ac3", "libmp3lame", + "libopus", //"libvorbis", "srt" }; From d75cc21d37cfa3b1ce2ad9dc4c26de41286f35f8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 15:47:47 -0400 Subject: [PATCH 227/852] fixes #1571 - Search containing umlauts fails --- .../Persistence/SqliteItemRepository.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 4f724fe40..a44d66c73 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -18,6 +18,7 @@ using System.Linq; using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.LiveTv; @@ -80,7 +81,7 @@ namespace MediaBrowser.Server.Implementations.Persistence private IDbCommand _updateInheritedRatingCommand; private IDbCommand _updateInheritedTagsCommand; - private const int LatestSchemaVersion = 64; + private const int LatestSchemaVersion = 65; /// /// Initializes a new instance of the class. @@ -226,6 +227,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "CriticRatingSummary", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "DateModifiedDuringLastRefresh", "DATETIME"); _connection.AddColumn(Logger, "TypedBaseItems", "InheritedTags", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "CleanName", "Text"); PrepareStatements(); @@ -466,7 +468,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "CriticRating", "CriticRatingSummary", "DateModifiedDuringLastRefresh", - "InheritedTags" + "InheritedTags", + "CleanName" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -792,6 +795,15 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = null; } + if (string.IsNullOrWhiteSpace(item.Name)) + { + _saveItemCommand.GetParameter(index++).Value = null; + } + else + { + _saveItemCommand.GetParameter(index++).Value = item.Name.RemoveDiacritics(); + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1986,7 +1998,7 @@ namespace MediaBrowser.Server.Implementations.Persistence if (!string.IsNullOrWhiteSpace(query.NameContains)) { - whereClauses.Add("Name like @NameContains"); + whereClauses.Add("CleanName like @NameContains"); cmd.Parameters.Add(cmd, "@NameContains", DbType.String).Value = "%" + query.NameContains + "%"; } From 8ee0e50a63f59ab8d816c0d9f20be3b08ee4dc3e Mon Sep 17 00:00:00 2001 From: Luke Date: Sat, 30 Apr 2016 16:54:11 -0400 Subject: [PATCH 228/852] update launch url --- MediaBrowser.Server.Mac/Native/BaseMonoApp.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs index 9c7421e42..67ad96859 100644 --- a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs @@ -122,16 +122,7 @@ namespace MediaBrowser.Server.Mac process.Exited += ProcessExited; - try - { - process.Start(); - } - catch (Exception ex) - { - _logger.ErrorException("Error launching url: {0}", ex, url); - - throw; - } + process.Start(); } /// From 1f9d32afc52e9bd133ddf22d12bdc468adaf9ebe Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 18:05:13 -0400 Subject: [PATCH 229/852] limit use of GetUserDataKey --- MediaBrowser.Api/Movies/MoviesService.cs | 4 +-- .../UserLibrary/BaseItemsByNameService.cs | 8 +++--- .../UserLibrary/UserLibraryService.cs | 8 ++---- MediaBrowser.Controller/Entities/BaseItem.cs | 14 ++++------- MediaBrowser.Controller/Entities/Folder.cs | 2 +- .../Entities/UserViewBuilder.cs | 10 ++++---- .../Library/IUserDataManager.cs | 5 ++++ .../ContentDirectory/ControlHandler.cs | 2 +- .../Channels/ChannelManager.cs | 12 ++++----- .../Dto/DtoService.cs | 4 +-- .../Library/MediaSourceManager.cs | 2 +- .../Library/UserDataManager.cs | 15 +++++++++++ .../LiveTv/LiveTvManager.cs | 12 ++++----- .../Session/SessionManager.cs | 25 +++++++------------ .../Sorting/DatePlayedComparer.cs | 2 +- .../Sorting/PlayCountComparer.cs | 2 +- .../Sync/SyncManager.cs | 2 +- .../TV/TVSeriesManager.cs | 4 +-- .../Savers/BaseNfoSaver.cs | 2 +- 19 files changed, 70 insertions(+), 65 deletions(-) diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index 065f88268..bfbb3a6d7 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -247,7 +247,7 @@ namespace MediaBrowser.Api.Movies var recentlyPlayedMovies = allMoviesForCategories .Select(i => { - var userdata = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = _userDataRepository.GetUserData(user, i); return new Tuple(i, userdata.Played, userdata.LastPlayedDate ?? DateTime.MinValue); }) .Where(i => i.Item2) @@ -260,7 +260,7 @@ namespace MediaBrowser.Api.Movies .Select(i => { var score = 0; - var userData = _userDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userData = _userDataRepository.GetUserData(user, i); if (userData.IsFavorite) { diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 6ae2b0832..b3164ce3f 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -274,7 +274,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value; }); @@ -284,7 +284,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value; }); @@ -294,7 +294,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); var likes = userdata.Likes ?? false; var favorite = userdata.IsFavorite; @@ -307,7 +307,7 @@ namespace MediaBrowser.Api.UserLibrary { items = items.Where(i => { - var userdata = UserDataRepository.GetUserData(user.Id, i.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(user, i); return userdata != null && userdata.IsFavorite; }); diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs index c2c481cb6..8cc5cab35 100644 --- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs +++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs @@ -519,10 +519,8 @@ namespace MediaBrowser.Api.UserLibrary var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId); - var key = item.GetUserDataKey(); - // Get the user data for this item - var data = _userDataRepository.GetUserData(user.Id, key); + var data = _userDataRepository.GetUserData(user, item); // Set favorite status data.IsFavorite = isFavorite; @@ -567,10 +565,8 @@ namespace MediaBrowser.Api.UserLibrary var item = string.IsNullOrEmpty(itemId) ? user.RootFolder : _libraryManager.GetItemById(itemId); - var key = item.GetUserDataKey(); - // Get the user data for this item - var data = _userDataRepository.GetUserData(user.Id, key); + var data = _userDataRepository.GetUserData(user, item); data.Likes = likes; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 9171c2a71..4828426fd 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1617,9 +1617,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException(); } - var key = GetUserDataKey(); - - var data = UserDataManager.GetUserData(user.Id, key); + var data = UserDataManager.GetUserData(user, this); if (datePlayed.HasValue) { @@ -1654,9 +1652,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException(); } - var key = GetUserDataKey(); - - var data = UserDataManager.GetUserData(user.Id, key); + var data = UserDataManager.GetUserData(user, this); //I think it is okay to do this here. // if this is only called when a user is manually forcing something to un-played @@ -1987,14 +1983,14 @@ namespace MediaBrowser.Controller.Entities public virtual bool IsPlayed(User user) { - var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey()); + var userdata = UserDataManager.GetUserData(user, this); return userdata != null && userdata.Played; } public bool IsFavoriteOrLiked(User user) { - var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey()); + var userdata = UserDataManager.GetUserData(user, this); return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false)); } @@ -2006,7 +2002,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("user"); } - var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey()); + var userdata = UserDataManager.GetUserData(user, this); return userdata == null || !userdata.Played; } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index f4cdc8fa1..41f0c02bd 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1635,7 +1635,7 @@ namespace MediaBrowser.Controller.Entities var isUnplayed = true; - var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey()); + var itemUserData = UserDataManager.GetUserData(user, child); // Incrememt totalPercentPlayed if (itemUserData != null) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index db669ca37..5a0e0b614 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -348,7 +348,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => !i.IsFolder) .OfType(); - var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite); + var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite); return GetResult(artists, parent, query); } @@ -1218,7 +1218,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsLiked.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value) { @@ -1228,7 +1228,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsFavoriteOrLiked.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false); if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value) @@ -1239,7 +1239,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsFavorite.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); if (userData.IsFavorite != query.IsFavorite.Value) { @@ -1249,7 +1249,7 @@ namespace MediaBrowser.Controller.Entities if (query.IsResumable.HasValue) { - userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + userData = userData ?? userDataManager.GetUserData(user, item); var isResumable = userData.PlaybackPositionTicks > 0; if (isResumable != query.IsResumable.Value) diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index 56ac14e9d..4ff0f6439 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -45,6 +45,11 @@ namespace MediaBrowser.Controller.Library /// Task{UserItemData}. UserItemData GetUserData(Guid userId, string key); + UserItemData GetUserData(IHasUserData user, IHasUserData item); + + UserItemData GetUserData(string userId, IHasUserData item); + UserItemData GetUserData(Guid userId, IHasUserData item); + /// /// Gets the user data dto. /// diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index 34fb2a6df..bc9fa1d7e 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -111,7 +111,7 @@ namespace MediaBrowser.Dlna.ContentDirectory var newbookmark = int.Parse(sparams["PosSecond"], _usCulture); - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); userdata.PlaybackPositionTicks = TimeSpan.FromSeconds(newbookmark).Ticks; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index c9956c68a..6a9842cb2 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Server.Implementations.Channels if (query.IsFavorite.HasValue) { var val = query.IsFavorite.Value; - channels = channels.Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val) + channels = channels.Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val) .ToList(); } @@ -1437,7 +1437,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.IsFavoriteOrLikes: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); if (userdata == null) { @@ -1453,7 +1453,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.Likes: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.Likes.HasValue && userdata.Likes.Value; }); @@ -1461,7 +1461,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.Dislikes: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.Likes.HasValue && !userdata.Likes.Value; }); @@ -1469,7 +1469,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.IsFavorite: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.IsFavorite; }); @@ -1477,7 +1477,7 @@ namespace MediaBrowser.Server.Implementations.Channels case ItemFilter.IsResumable: return items.Where(item => { - var userdata = _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = _userDataManager.GetUserData(user, item); return userdata != null && userdata.PlaybackPositionTicks > 0; }); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 7adde5c27..b19f5727c 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -487,7 +487,7 @@ namespace MediaBrowser.Server.Implementations.Dto { if (item.IsFolder) { - var userData = _userDataRepository.GetUserData(user.Id, item.GetUserDataKey()); + var userData = _userDataRepository.GetUserData(user, item); // Skip the user data manager because we've already looped through the recursive tree and don't want to do it twice // TODO: Improve in future @@ -1686,7 +1686,7 @@ namespace MediaBrowser.Server.Implementations.Dto dateLastMediaAdded = new[] { dateLastMediaAdded.Value, child.DateCreated }.Max(); } - var userdata = _userDataRepository.GetUserData(user.Id, child.GetUserDataKey()); + var userdata = _userDataRepository.GetUserData(user, child); recursiveItemCount++; diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 092b797ce..a47fcdf4f 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -267,7 +267,7 @@ namespace MediaBrowser.Server.Implementations.Library private void SetUserProperties(IHasUserData item, MediaSourceInfo source, User user) { - var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user.Id, item.GetUserDataKey()); + var userData = item == null ? new UserItemData() : _userDataManager.GetUserData(user, item); var allowRememberingSelection = item == null || item.EnableRememberingTrackSelections; diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index ae737d244..c16beed8c 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -172,6 +172,21 @@ namespace MediaBrowser.Server.Implementations.Library return userId + key; } + public UserItemData GetUserData(IHasUserData user, IHasUserData item) + { + return GetUserData(user.Id, item.GetUserDataKey()); + } + + public UserItemData GetUserData(string userId, IHasUserData item) + { + return GetUserData(userId, item.GetUserDataKey()); + } + + public UserItemData GetUserData(Guid userId, IHasUserData item) + { + return GetUserData(userId, item.GetUserDataKey()); + } + public UserItemDataDto GetUserDataDto(IHasUserData item, User user) { var userData = GetUserData(user.Id, item.GetUserDataKey()); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index ab2b59d48..eec8328f8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -164,7 +164,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var val = query.IsFavorite.Value; channels = channels - .Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite == val); + .Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val); } if (query.IsLiked.HasValue) @@ -174,7 +174,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv channels = channels .Where(i => { - var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes; + var likes = _userDataManager.GetUserData(user, i).Likes; return likes.HasValue && likes.Value == val; }); @@ -187,7 +187,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv channels = channels .Where(i => { - var likes = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).Likes; + var likes = _userDataManager.GetUserData(user, i).Likes; return likes.HasValue && likes.Value != val; }); @@ -200,7 +200,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv { if (enableFavoriteSorting) { - var userData = _userDataManager.GetUserData(user.Id, i.GetUserDataKey()); + var userData = _userDataManager.GetUserData(user, i); if (userData.IsFavorite) { @@ -1005,7 +1005,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv var channel = GetInternalChannel(program.ChannelId); - var channelUserdata = _userDataManager.GetUserData(userId, channel.GetUserDataKey()); + var channelUserdata = _userDataManager.GetUserData(userId, channel); if (channelUserdata.Likes ?? false) { @@ -1036,7 +1036,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv if (genres.TryGetValue(i, out genre)) { - var genreUserdata = _userDataManager.GetUserData(userId, genre.GetUserDataKey()); + var genreUserdata = _userDataManager.GetUserData(userId, genre); if (genreUserdata.Likes ?? false) { diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 88f11c368..014e8babf 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -601,11 +601,9 @@ namespace MediaBrowser.Server.Implementations.Session if (libraryItem != null) { - var key = libraryItem.GetUserDataKey(); - foreach (var user in users) { - await OnPlaybackStart(user.Id, key, libraryItem).ConfigureAwait(false); + await OnPlaybackStart(user.Id, libraryItem).ConfigureAwait(false); } } @@ -632,12 +630,11 @@ namespace MediaBrowser.Server.Implementations.Session /// Called when [playback start]. /// /// The user identifier. - /// The user data key. /// The item. /// Task. - private async Task OnPlaybackStart(Guid userId, string userDataKey, IHasUserData item) + private async Task OnPlaybackStart(Guid userId, IHasUserData item) { - var data = _userDataRepository.GetUserData(userId, userDataKey); + var data = _userDataRepository.GetUserData(userId, item); data.PlayCount++; data.LastPlayedDate = DateTime.UtcNow; @@ -676,11 +673,9 @@ namespace MediaBrowser.Server.Implementations.Session if (libraryItem != null) { - var key = libraryItem.GetUserDataKey(); - foreach (var user in users) { - await OnPlaybackProgress(user, key, libraryItem, info).ConfigureAwait(false); + await OnPlaybackProgress(user, libraryItem, info).ConfigureAwait(false); } } @@ -714,9 +709,9 @@ namespace MediaBrowser.Server.Implementations.Session StartIdleCheckTimer(); } - private async Task OnPlaybackProgress(User user, string userDataKey, BaseItem item, PlaybackProgressInfo info) + private async Task OnPlaybackProgress(User user, BaseItem item, PlaybackProgressInfo info) { - var data = _userDataRepository.GetUserData(user.Id, userDataKey); + var data = _userDataRepository.GetUserData(user.Id, item); var positionTicks = info.PositionTicks; @@ -811,11 +806,9 @@ namespace MediaBrowser.Server.Implementations.Session if (libraryItem != null) { - var key = libraryItem.GetUserDataKey(); - foreach (var user in users) { - playedToCompletion = await OnPlaybackStopped(user.Id, key, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false); + playedToCompletion = await OnPlaybackStopped(user.Id, libraryItem, info.PositionTicks, info.Failed).ConfigureAwait(false); } } @@ -848,13 +841,13 @@ namespace MediaBrowser.Server.Implementations.Session await SendPlaybackStoppedNotification(session, CancellationToken.None).ConfigureAwait(false); } - private async Task OnPlaybackStopped(Guid userId, string userDataKey, BaseItem item, long? positionTicks, bool playbackFailed) + private async Task OnPlaybackStopped(Guid userId, BaseItem item, long? positionTicks, bool playbackFailed) { bool playedToCompletion = false; if (!playbackFailed) { - var data = _userDataRepository.GetUserData(userId, userDataKey); + var data = _userDataRepository.GetUserData(userId, item); if (positionTicks.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs index c881591be..3edf23020 100644 --- a/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/DatePlayedComparer.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// DateTime. private DateTime GetDate(BaseItem x) { - var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(User, x); if (userdata != null && userdata.LastPlayedDate.HasValue) { diff --git a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs index 1bc5261b4..8b14efffc 100644 --- a/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs +++ b/MediaBrowser.Server.Implementations/Sorting/PlayCountComparer.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Sorting /// DateTime. private int GetValue(BaseItem x) { - var userdata = UserDataRepository.GetUserData(User.Id, x.GetUserDataKey()); + var userdata = UserDataRepository.GetUserData(User, x); return userdata == null ? 0 : userdata.PlayCount; } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index fe1a7fb28..38edc3024 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -687,7 +687,7 @@ namespace MediaBrowser.Server.Implementations.Sync private Task ReportOfflinePlayedItem(UserAction action) { var item = _libraryManager.GetItemById(action.ItemId); - var userData = _userDataManager.GetUserData(new Guid(action.UserId), item.GetUserDataKey()); + var userData = _userDataManager.GetUserData(action.UserId, item); userData.LastPlayedDate = action.Date; _userDataManager.UpdatePlayState(item, userData, action.PositionTicks); diff --git a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs index 3e43ebe9b..dc880d84b 100644 --- a/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs +++ b/MediaBrowser.Server.Implementations/TV/TVSeriesManager.cs @@ -85,7 +85,7 @@ namespace MediaBrowser.Server.Implementations.TV { var episode = i.Item1; - var seriesUserData = _userDataManager.GetUserData(user.Id, episode.Series.GetUserDataKey()); + var seriesUserData = _userDataManager.GetUserData(user, episode.Series); if (seriesUserData.IsFavorite) { @@ -128,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.TV // Go back starting with the most recent episodes foreach (var episode in allEpisodes) { - var userData = _userDataManager.GetUserData(user.Id, episode.GetUserDataKey()); + var userData = _userDataManager.GetUserData(user, episode); if (userData.Played) { diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 6d15d168d..d2e09d4eb 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -936,7 +936,7 @@ namespace MediaBrowser.XbmcMetadata.Savers return; } - var userdata = userDataRepo.GetUserData(user.Id, item.GetUserDataKey()); + var userdata = userDataRepo.GetUserData(user, item); writer.WriteElementString("isuserfavorite", userdata.IsFavorite.ToString().ToLower()); From 6330b13262bf24793f059a269fdba7ea2514efe0 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 19:05:21 -0400 Subject: [PATCH 230/852] support multiple user data keys --- .../Entities/Audio/Audio.cs | 34 +++++------ .../Entities/Audio/MusicAlbum.cs | 38 ++++++------ .../Entities/Audio/MusicArtist.cs | 19 +++--- .../Entities/Audio/MusicGenre.cs | 11 ++-- MediaBrowser.Controller/Entities/BaseItem.cs | 12 ++-- MediaBrowser.Controller/Entities/Game.cs | 7 ++- MediaBrowser.Controller/Entities/GameGenre.cs | 11 ++-- .../Entities/GameSystem.cs | 13 ++-- MediaBrowser.Controller/Entities/Genre.cs | 11 ++-- .../Entities/IHasUserData.cs | 5 +- .../Entities/Movies/Movie.cs | 28 --------- .../Entities/MusicVideo.cs | 9 --- MediaBrowser.Controller/Entities/Person.cs | 11 ++-- MediaBrowser.Controller/Entities/Studio.cs | 11 ++-- .../Entities/TV/Episode.cs | 22 ++++--- MediaBrowser.Controller/Entities/TV/Season.cs | 16 +++-- MediaBrowser.Controller/Entities/TV/Series.cs | 26 ++++---- MediaBrowser.Controller/Entities/Trailer.cs | 20 ------- MediaBrowser.Controller/Entities/Video.cs | 60 +++++++++++++++---- MediaBrowser.Controller/Entities/Year.cs | 11 ++-- .../Library/UserDataSaveEventArgs.cs | 7 +-- .../LiveTv/LiveTvAudioRecording.cs | 11 ---- .../LiveTv/LiveTvChannel.cs | 11 ++-- .../LiveTv/LiveTvProgram.cs | 30 ++++++---- .../LiveTv/LiveTvVideoRecording.cs | 26 -------- .../Library/UserDataManager.cs | 27 +++++---- 26 files changed, 219 insertions(+), 268 deletions(-) diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 929308ba0..fd56a6746 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Entities.Audio IArchivable { public List ChannelMediaSources { get; set; } - + public long? Size { get; set; } public string Container { get; set; } public int? TotalBitrate { get; set; } @@ -150,12 +150,10 @@ namespace MediaBrowser.Controller.Entities.Audio + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { + var list = base.GetUserDataKeys(); + if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) { var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty; @@ -165,7 +163,7 @@ namespace MediaBrowser.Controller.Entities.Audio { songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey; } - songKey+= Name; + songKey += Name; if (!string.IsNullOrWhiteSpace(Album)) { @@ -178,25 +176,25 @@ namespace MediaBrowser.Controller.Entities.Audio songKey = albumArtist + "-" + songKey; } - return songKey; + list.Insert(0, songKey); } - - var parent = AlbumEntity; - - if (parent != null) + else { - var parentKey = parent.GetUserDataKey(); + var parent = AlbumEntity; - if (IndexNumber.HasValue) + if (parent != null && IndexNumber.HasValue) { - var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "") - + IndexNumber.Value.ToString("0000 - "); + list.InsertRange(0, parent.GetUserDataKeys().Select(i => + { + var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "") + + IndexNumber.Value.ToString("0000 - "); - return parentKey + songKey; + return i + songKey; + })); } } - return base.CreateUserDataKey(); + return list; } public override UnratedItem GetBlockUnratedType() diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index e6178c183..5cb4e8c9d 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -96,36 +96,34 @@ namespace MediaBrowser.Controller.Entities.Audio public List Artists { get; set; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - var id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); - - if (!string.IsNullOrWhiteSpace(id)) - { - return "MusicAlbum-MusicBrainzReleaseGroup-" + id; - } - - id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); - - if (!string.IsNullOrWhiteSpace(id)) - { - return "MusicAlbum-Musicbrainz-" + id; - } + var list = base.GetUserDataKeys(); if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) { var albumArtist = AlbumArtist; if (!string.IsNullOrWhiteSpace(albumArtist)) { - return albumArtist + "-" + Name; + list.Insert(0, albumArtist + "-" + Name); } } - return base.CreateUserDataKey(); + var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); + + if (!string.IsNullOrWhiteSpace(id)) + { + list.Insert(0, "MusicAlbum-Musicbrainz-" + id); + } + + id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + + if (!string.IsNullOrWhiteSpace(id)) + { + list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id); + } + + return list; } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 02bcceada..2cca63217 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -80,13 +80,12 @@ namespace MediaBrowser.Controller.Entities.Audio ProductionLocations = new List(); } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return GetUserDataKey(this); + var list = base.GetUserDataKeys(); + + list.InsertRange(0, GetUserDataKeys(this)); + return list; } /// @@ -121,16 +120,18 @@ namespace MediaBrowser.Controller.Entities.Audio /// /// The item. /// System.String. - private static string GetUserDataKey(MusicArtist item) + private static List GetUserDataKeys(MusicArtist item) { + var list = new List(); var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!string.IsNullOrEmpty(id)) { - return "Artist-Musicbrainz-" + id; + list.Add("Artist-Musicbrainz-" + id); } - return "Artist-" + item.Name; + list.Add("Artist-" + item.Name); + return list; } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index 45304d47e..4d041264c 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities.Audio /// public class MusicGenre : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "MusicGenre-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "MusicGenre-" + Name); + return list; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 4828426fd..f91b6b31e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1158,7 +1158,7 @@ namespace MediaBrowser.Controller.Entities { if (string.IsNullOrWhiteSpace(_userDataKey)) { - var key = CreateUserDataKey(); + var key = GetUserDataKeys().First(); _userDataKey = key; return key; } @@ -1166,16 +1166,20 @@ namespace MediaBrowser.Controller.Entities return _userDataKey; } - protected virtual string CreateUserDataKey() + public virtual List GetUserDataKeys() { + var list = new List(); + if (SourceType == SourceType.Channel) { if (!string.IsNullOrWhiteSpace(ExternalId)) { - return ExternalId; + list.Add(ExternalId); } } - return Id.ToString(); + + list.Add(Id.ToString()); + return list; } internal virtual bool IsValidFromResolver(BaseItem newItem) diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index e597b2a15..9ed240046 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -76,15 +76,16 @@ namespace MediaBrowser.Controller.Entities /// public List MultiPartGameFiles { get; set; } - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { + var list = base.GetUserDataKeys(); var id = this.GetProviderId(MetadataProviders.Gamesdb); if (!string.IsNullOrEmpty(id)) { - return "Game-Gamesdb-" + id; + list.Insert(0, "Game-Gamesdb-" + id); } - return base.CreateUserDataKey(); + return list; } public override IEnumerable GetDeletePaths() diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index d2b6b4856..71028d4cf 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -7,13 +7,12 @@ namespace MediaBrowser.Controller.Entities { public class GameGenre : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "GameGenre-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "GameGenre-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs index bc35c4738..1c09ee507 100644 --- a/MediaBrowser.Controller/Entities/GameSystem.cs +++ b/MediaBrowser.Controller/Entities/GameSystem.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using System; +using System.Collections.Generic; using MediaBrowser.Model.Users; namespace MediaBrowser.Controller.Entities @@ -31,17 +32,15 @@ namespace MediaBrowser.Controller.Entities /// The game system. public string GameSystemName { get; set; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { + var list = base.GetUserDataKeys(); + if (!string.IsNullOrEmpty(GameSystemName)) { - return "GameSystem-" + GameSystemName; + list.Insert(0, "GameSystem-" + GameSystemName); } - return base.CreateUserDataKey(); + return list; } protected override bool GetBlockUnratedValue(UserPolicy config) diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 233e1e0fd..fa890ad9e 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities /// public class Genre : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Genre-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Genre-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs index faddc3778..3e0fa3f1d 100644 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ b/MediaBrowser.Controller/Entities/IHasUserData.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Model.Dto; +using System.Collections.Generic; +using MediaBrowser.Model.Dto; namespace MediaBrowser.Controller.Entities { @@ -13,6 +14,8 @@ namespace MediaBrowser.Controller.Entities /// System.String. string GetUserDataKey(); + List GetUserDataKeys(); + /// /// Fills the user data dto values. /// diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 6004992cc..5882b5f4d 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -75,34 +75,6 @@ namespace MediaBrowser.Controller.Entities.Movies get { return TmdbCollectionName; } set { TmdbCollectionName = value; } } - - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - var key = GetMovieUserDataKey(this); - - if (string.IsNullOrWhiteSpace(key)) - { - key = base.CreateUserDataKey(); - } - - return key; - } - - public static string GetMovieUserDataKey(BaseItem movie) - { - var key = movie.GetProviderId(MetadataProviders.Tmdb); - - if (string.IsNullOrWhiteSpace(key)) - { - key = movie.GetProviderId(MetadataProviders.Imdb); - } - - return key; - } protected override async Task RefreshedOwnedItems(MetadataRefreshOptions options, List fileSystemChildren, CancellationToken cancellationToken) { diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs index b52f16a46..bf4c2559c 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -44,15 +44,6 @@ namespace MediaBrowser.Controller.Entities } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey(); - } - public override UnratedItem GetBlockUnratedType() { return UnratedItem.Music; diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 560ea6e05..89581e967 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -18,13 +18,12 @@ namespace MediaBrowser.Controller.Entities /// The place of birth. public string PlaceOfBirth { get; set; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Person-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Person-" + Name); + return list; } public PersonLookupInfo GetLookupInfo() diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index a55527f37..7ceefbc6e 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -10,13 +10,12 @@ namespace MediaBrowser.Controller.Entities /// public class Studio : BaseItem, IItemByName, IHasTags { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Studio-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Studio-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index e1a91086b..3ad6170a5 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -98,20 +98,26 @@ namespace MediaBrowser.Controller.Entities.TV } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + [IgnoreDataMember] + protected override bool EnableDefaultVideoUserDataKeys { - var series = Series; + get + { + return false; + } + } + public override List GetUserDataKeys() + { + var list = base.GetUserDataKeys(); + + var series = Series; if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue) { - return series.GetUserDataKey() + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"); + list.InsertRange(0, series.GetUserDataKeys().Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000"))); } - return base.CreateUserDataKey(); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index acd02e8ab..ebd22c6c4 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -53,19 +53,17 @@ namespace MediaBrowser.Controller.Entities.TV }; } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - if (Series != null) + var list = base.GetUserDataKeys(); + + var series = Series; + if (series != null) { - var seasonNo = IndexNumber ?? 0; - return Series.GetUserDataKey() + seasonNo.ToString("000"); + list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000"))); } - return base.CreateUserDataKey(); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index ad4ee436e..c03eed6c9 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -95,21 +95,23 @@ namespace MediaBrowser.Controller.Entities.TV /// Gets the user data key. /// /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - var key = this.GetProviderId(MetadataProviders.Tvdb); + var list = base.GetUserDataKeys(); - if (string.IsNullOrWhiteSpace(key)) + var key = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(key)) { - key = this.GetProviderId(MetadataProviders.Imdb); + list.Insert(0, key); } - if (string.IsNullOrWhiteSpace(key)) + key = this.GetProviderId(MetadataProviders.Tvdb); + if (!string.IsNullOrWhiteSpace(key)) { - key = base.CreateUserDataKey(); + list.Insert(0, key); } - return key; + return list; } /// @@ -126,8 +128,8 @@ namespace MediaBrowser.Controller.Entities.TV // Studio, Genre and Rating will all be the same so makes no sense to index by these protected override IEnumerable GetIndexByOptions() { - return new List { - {"None"}, + return new List { + {"None"}, {"Performer"}, {"Director"}, {"Year"}, @@ -280,9 +282,9 @@ namespace MediaBrowser.Controller.Entities.TV if (episode != null && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh && !refreshOptions.ReplaceAllMetadata - && episode.IsMissingEpisode - && episode.LocationType == Model.Entities.LocationType.Virtual - && episode.PremiereDate.HasValue + && episode.IsMissingEpisode + && episode.LocationType == Model.Entities.LocationType.Virtual + && episode.PremiereDate.HasValue && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30) { skipItem = true; diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index fe8bf3ed3..3be2fc624 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -56,26 +56,6 @@ namespace MediaBrowser.Controller.Entities /// The revenue. public double? Revenue { get; set; } - protected override string CreateUserDataKey() - { - var key = Movie.GetMovieUserDataKey(this); - - if (!string.IsNullOrWhiteSpace(key)) - { - key = key + "-trailer"; - - // Make sure different trailers have their own data. - if (RunTimeTicks.HasValue) - { - key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); - } - - return key; - } - - return base.CreateUserDataKey(); - } - public override UnratedItem GetBlockUnratedType() { return UnratedItem.Trailer; diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index d81e6f0ff..cdabaa84e 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -131,27 +131,65 @@ namespace MediaBrowser.Controller.Entities return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video))); } - protected override string CreateUserDataKey() + [IgnoreDataMember] + protected virtual bool EnableDefaultVideoUserDataKeys { - if (ExtraType.HasValue) + get { - var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb); + return true; + } + } - if (!string.IsNullOrWhiteSpace(key)) + public override List GetUserDataKeys() + { + var list = base.GetUserDataKeys(); + + if (EnableDefaultVideoUserDataKeys) + { + if (ExtraType.HasValue) { - key = key + "-" + ExtraType.ToString().ToLower(); - - // Make sure different trailers have their own data. - if (RunTimeTicks.HasValue) + var key = this.GetProviderId(MetadataProviders.Tmdb); + if (!string.IsNullOrWhiteSpace(key)) { - key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); + list.Insert(0, GetUserDataKey(key)); } - return key; + key = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, GetUserDataKey(key)); + } + } + else + { + var key = this.GetProviderId(MetadataProviders.Imdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, key); + } + + key = this.GetProviderId(MetadataProviders.Tmdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, key); + } } } - return base.CreateUserDataKey(); + return list; + } + + private string GetUserDataKey(string providerId) + { + var key = providerId + "-" + ExtraType.ToString().ToLower(); + + // Make sure different trailers have their own data. + if (RunTimeTicks.HasValue) + { + key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); + } + + return key; } /// diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 163dcd667..f27ce79dd 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities /// public class Year : BaseItem, IItemByName { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return "Year-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, "Year-" + Name); + return list; } /// diff --git a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs index ba328ff75..654c6b581 100644 --- a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs +++ b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Entities; using System; +using System.Collections.Generic; namespace MediaBrowser.Controller.Library { @@ -15,11 +16,7 @@ namespace MediaBrowser.Controller.Library /// The user id. public Guid UserId { get; set; } - /// - /// Gets or sets the key. - /// - /// The key. - public string Key { get; set; } + public List Keys { get; set; } /// /// Gets or sets the save reason. diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 17a27eac1..e6f472414 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -45,17 +45,6 @@ namespace MediaBrowser.Controller.LiveTv set { } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - var name = GetClientTypeName(); - - return name + "-" + Name + (EpisodeTitle ?? string.Empty); - } - /// /// Gets a value indicating whether this instance is owned item. /// diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 2bb6cc182..50aeed27d 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.LiveTv { public class LiveTvChannel : BaseItem, IHasMediaSources { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - return GetClientTypeName() + "-" + Name; + var list = base.GetUserDataKeys(); + + list.Insert(0, GetClientTypeName() + "-" + Name); + return list; } public override UnratedItem GetBlockUnratedType() diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 59b921c6a..cc30709db 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -4,36 +4,40 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.LiveTv; using System; +using System.Collections.Generic; using System.Runtime.Serialization; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.LiveTv { public class LiveTvProgram : BaseItem, IHasLookupInfo, IHasStartDate, IHasProgramAttributes { - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() + public override List GetUserDataKeys() { - if (IsMovie) - { - var key = Movie.GetMovieUserDataKey(this); + var list = base.GetUserDataKeys(); + if (!IsSeries) + { + var key = this.GetProviderId(MetadataProviders.Imdb); if (!string.IsNullOrWhiteSpace(key)) { - return key; + list.Insert(0, key); + } + + key = this.GetProviderId(MetadataProviders.Tmdb); + if (!string.IsNullOrWhiteSpace(key)) + { + list.Insert(0, key); } } - - if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle)) + else if (!string.IsNullOrWhiteSpace(EpisodeTitle)) { var name = GetClientTypeName(); - return name + "-" + Name + (EpisodeTitle ?? string.Empty); + list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty)); } - return base.CreateUserDataKey(); + return list; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index f310a957c..a8c737673 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -45,32 +45,6 @@ namespace MediaBrowser.Controller.LiveTv set { } } - /// - /// Gets the user data key. - /// - /// System.String. - protected override string CreateUserDataKey() - { - if (IsMovie) - { - var key = Movie.GetMovieUserDataKey(this); - - if (!string.IsNullOrWhiteSpace(key)) - { - return key; - } - } - - if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle)) - { - var name = GetClientTypeName(); - - return name + "-" + Name + (EpisodeTitle ?? string.Empty); - } - - return base.CreateUserDataKey(); - } - [IgnoreDataMember] public override string MediaType { diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index c16beed8c..98f8abd40 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -56,27 +56,30 @@ namespace MediaBrowser.Server.Implementations.Library cancellationToken.ThrowIfCancellationRequested(); - var key = item.GetUserDataKey(); + var keys = item.GetUserDataKeys(); - try + foreach (var key in keys) { - await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); + try + { + await Repository.SaveUserData(userId, key, userData, cancellationToken).ConfigureAwait(false); - var newValue = userData; + var newValue = userData; - // Once it succeeds, put it into the dictionary to make it available to everyone else - _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; }); - } - catch (Exception ex) - { - _logger.ErrorException("Error saving user data", ex); + // Once it succeeds, put it into the dictionary to make it available to everyone else + _userData.AddOrUpdate(GetCacheKey(userId, key), newValue, delegate { return newValue; }); + } + catch (Exception ex) + { + _logger.ErrorException("Error saving user data", ex); - throw; + throw; + } } EventHelper.FireEventIfNotNull(UserDataSaved, this, new UserDataSaveEventArgs { - Key = key, + Keys = keys, UserData = userData, SaveReason = reason, UserId = userId, From 780d5b914cc22bdf88477761e60c5de64b20504d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 23:37:32 -0400 Subject: [PATCH 231/852] 3.0.5934 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ea90eda21..073260ad7 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5933")] +[assembly: AssemblyVersion("3.0.5934")] From 724aa4af40f7cf02efcdc6e8c847a0f8bcb5d7ff Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 23:41:41 -0400 Subject: [PATCH 232/852] fix merge conflict --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 2369b6a48..073260ad7 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5947")] +[assembly: AssemblyVersion("3.0.5934")] From e8965dbfbabd89cc8a1477e7460acf28fe262b3d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 23:47:34 -0400 Subject: [PATCH 233/852] restore version --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 073260ad7..2369b6a48 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5934")] +[assembly: AssemblyVersion("3.0.5947")] From ad3965a76992fe13e92a244fd70c08bdfb8d5191 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 16:56:06 -0400 Subject: [PATCH 234/852] update MediaSourceCount --- MediaBrowser.Server.Implementations/Dto/DtoService.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index b19f5727c..e8af0c3cb 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1363,9 +1363,10 @@ namespace MediaBrowser.Server.Implementations.Dto if (fields.Contains(ItemFields.MediaSourceCount)) { - if (video.MediaSourceCount != 1) + var mediaSourceCount = video.MediaSourceCount; + if (mediaSourceCount != 1) { - dto.MediaSourceCount = video.MediaSourceCount; + dto.MediaSourceCount = mediaSourceCount; } } From 324c6dc8db489cc19ab7ef75f458b68e193f9830 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 16:56:26 -0400 Subject: [PATCH 235/852] update embedded metadata extraction --- MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs index 621510028..e1ab61cbb 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs @@ -444,7 +444,11 @@ namespace MediaBrowser.Providers.MediaInfo { if (string.IsNullOrWhiteSpace(video.Name) || string.Equals(video.Name, Path.GetFileNameWithoutExtension(video.Path), StringComparison.OrdinalIgnoreCase)) { - video.Name = data.Name; + // Don't use the embedded name for extras because it will often be the same name as the movie + if (!video.ExtraType.HasValue && !video.IsOwnedItem) + { + video.Name = data.Name; + } } } From a4d1c9e6e48f63121cc51abda61ed46d7f6a72cf Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 17:48:37 -0400 Subject: [PATCH 236/852] update sqlite --- .../Notifications/INotificationsRepository.cs | 6 -- .../IDisplayPreferencesRepository.cs | 6 -- .../Persistence/IItemRepository.cs | 6 -- .../Persistence/IUserDataRepository.cs | 6 -- .../Providers/IProviderRepository.cs | 6 -- .../Activity/ActivityRepository.cs | 4 +- ...MediaBrowser.Server.Implementations.csproj | 6 +- .../SqliteNotificationsRepository.cs | 4 +- ...{SqliteExtensions.cs => DataExtensions.cs} | 46 ++------------ .../Persistence/IDbConnector.cs | 10 +++ .../SqliteDisplayPreferencesRepository.cs | 4 +- .../SqliteFileOrganizationRepository.cs | 4 +- .../SqliteProviderInfoRepository.cs | 4 +- .../Persistence/SqliteUserDataRepository.cs | 4 +- .../Persistence/SqliteUserRepository.cs | 6 +- .../Security/AuthenticationRepository.cs | 4 +- .../Social/SharingRepository.cs | 4 +- .../Sync/SyncRepository.cs | 4 +- .../MediaBrowser.Server.Mono.csproj | 5 ++ .../Native/BaseMonoApp.cs | 11 +++- MediaBrowser.Server.Mono/Native/NativeApp.cs | 7 ++- .../Native/SqliteExtensions.cs | 62 +++++++++++++++++++ MediaBrowser.Server.Mono/Program.cs | 2 +- .../ApplicationHost.cs | 55 ++++++---------- .../INativeApp.cs | 3 + .../MediaBrowser.ServerApplication.csproj | 25 ++++---- .../Native/SqliteExtensions.cs | 62 +++++++++++++++++++ .../Native/WindowsApp.cs | 6 ++ .../packages.config | 2 +- 29 files changed, 224 insertions(+), 150 deletions(-) rename MediaBrowser.Server.Implementations/Persistence/{SqliteExtensions.cs => DataExtensions.cs} (82%) create mode 100644 MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs create mode 100644 MediaBrowser.Server.Mono/Native/SqliteExtensions.cs create mode 100644 MediaBrowser.ServerApplication/Native/SqliteExtensions.cs diff --git a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs index 6ad4a5377..cd587a509 100644 --- a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs +++ b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs @@ -19,12 +19,6 @@ namespace MediaBrowser.Controller.Notifications /// Occurs when [notifications marked read]. /// event EventHandler NotificationsMarkedRead; - - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); /// /// Gets the notifications. diff --git a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs index 17de730cb..abf96994f 100644 --- a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs +++ b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs @@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence /// public interface IDisplayPreferencesRepository : IRepository { - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); - /// /// Saves display preferences for an item /// diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 15df1f649..7bcc36958 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -13,12 +13,6 @@ namespace MediaBrowser.Controller.Persistence /// public interface IItemRepository : IRepository { - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); - /// /// Saves an item /// diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs index 2a904be0d..2e165f416 100644 --- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs +++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs @@ -11,12 +11,6 @@ namespace MediaBrowser.Controller.Persistence /// public interface IUserDataRepository : IRepository { - /// - /// Opens the connection to the repository - /// - /// Task. - Task Initialize(); - /// /// Saves the user data. /// diff --git a/MediaBrowser.Controller/Providers/IProviderRepository.cs b/MediaBrowser.Controller/Providers/IProviderRepository.cs index 1f77d0ca1..891275d77 100644 --- a/MediaBrowser.Controller/Providers/IProviderRepository.cs +++ b/MediaBrowser.Controller/Providers/IProviderRepository.cs @@ -21,11 +21,5 @@ namespace MediaBrowser.Controller.Providers /// The cancellation token. /// Task. Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken); - - /// - /// Initializes this instance. - /// - /// Task. - Task Initialize(); } } diff --git a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs index 85ab76182..b0e05a5bc 100644 --- a/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs +++ b/MediaBrowser.Server.Implementations/Activity/ActivityRepository.cs @@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Activity _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "activitylog.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 43f5d741b..aff3a5e16 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -78,9 +78,6 @@ - - ..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll - @@ -261,6 +258,8 @@ + + @@ -275,7 +274,6 @@ - diff --git a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs index 7302431e1..cecf03ddf 100644 --- a/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs +++ b/MediaBrowser.Server.Implementations/Notifications/SqliteNotificationsRepository.cs @@ -32,11 +32,11 @@ namespace MediaBrowser.Server.Implementations.Notifications _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "notifications.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs similarity index 82% rename from MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs rename to MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs index 4fb1e07dd..103b75f84 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Implementations/Persistence/DataExtensions.cs @@ -3,16 +3,12 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using System; using System.Data; -using System.Data.SQLite; using System.IO; using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Persistence { - /// - /// Class SQLiteExtensions - /// - static class SqliteExtensions + static class DataExtensions { /// /// Determines whether the specified conn is open. @@ -28,11 +24,11 @@ namespace MediaBrowser.Server.Implementations.Persistence { return (IDataParameter)cmd.Parameters[index]; } - + public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name, DbType type) { var param = cmd.CreateParameter(); - + param.ParameterName = name; param.DbType = type; @@ -48,11 +44,11 @@ namespace MediaBrowser.Server.Implementations.Persistence param.ParameterName = name; paramCollection.Add(param); - + return param; } - + /// /// Gets a stream from a DataReader at a given ordinal /// @@ -122,38 +118,6 @@ namespace MediaBrowser.Server.Implementations.Persistence } } - /// - /// Connects to db. - /// - /// The db path. - /// The logger. - /// Task{IDbConnection}. - /// dbPath - public static async Task ConnectToDb(string dbPath, ILogger logger) - { - if (string.IsNullOrEmpty(dbPath)) - { - throw new ArgumentNullException("dbPath"); - } - - logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); - - var connectionstr = new SQLiteConnectionStringBuilder - { - PageSize = 4096, - CacheSize = 2000, - SyncMode = SynchronizationModes.Full, - DataSource = dbPath, - JournalMode = SQLiteJournalModeEnum.Wal - }; - - var connection = new SQLiteConnection(connectionstr.ConnectionString); - - await connection.OpenAsync().ConfigureAwait(false); - - return connection; - } - public static void Attach(IDbConnection db, string path, string alias) { using (var cmd = db.CreateCommand()) diff --git a/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs new file mode 100644 index 000000000..cac9fe983 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Persistence/IDbConnector.cs @@ -0,0 +1,10 @@ +using System.Data; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Persistence +{ + public interface IDbConnector + { + Task Connect(string dbPath); + } +} diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs index 45e0304c1..6077cfdba 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteDisplayPreferencesRepository.cs @@ -52,11 +52,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "displaypreferences.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs index 2d5aad04d..037776997 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteFileOrganizationRepository.cs @@ -35,11 +35,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "fileorganization.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs index dbceda727..40d5c9586 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteProviderInfoRepository.cs @@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "refreshinfo.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs index 63c41c71f..33a2b1187 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserDataRepository.cs @@ -37,11 +37,11 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "userdata_v2.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs index 9bd7e47f3..f7ca39a54 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteUserRepository.cs @@ -43,12 +43,12 @@ namespace MediaBrowser.Server.Implementations.Persistence /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "users.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); - + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); + string[] queries = { "create table if not exists users (guid GUID primary key, data BLOB)", diff --git a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs index b932f0cac..e8d9814ec 100644 --- a/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs +++ b/MediaBrowser.Server.Implementations/Security/AuthenticationRepository.cs @@ -27,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Security _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "authentication.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs index d6d7f021a..317743eb1 100644 --- a/MediaBrowser.Server.Implementations/Social/SharingRepository.cs +++ b/MediaBrowser.Server.Implementations/Social/SharingRepository.cs @@ -26,11 +26,11 @@ namespace MediaBrowser.Server.Implementations.Social /// Opens the connection to the database /// /// Task. - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "shares.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs index 965c081eb..6d31663b9 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncRepository.cs @@ -39,11 +39,11 @@ namespace MediaBrowser.Server.Implementations.Sync _appPaths = appPaths; } - public async Task Initialize() + public async Task Initialize(IDbConnector dbConnector) { var dbFile = Path.Combine(_appPaths.DataPath, "sync14.db"); - _connection = await SqliteExtensions.ConnectToDb(dbFile, Logger).ConfigureAwait(false); + _connection = await dbConnector.Connect(dbFile).ConfigureAwait(false); string[] queries = { diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index 48d2df7ce..b71877e17 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -76,12 +76,17 @@ ..\ThirdParty\MediaBrowser.IsoMounting.Linux\MediaBrowser.IsoMounting.Linux.dll + + + ..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll + Properties\SharedVersion.cs + diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index fbfef9a34..a012a19a3 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Reflection; using System.Text.RegularExpressions; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Startup.Common.FFMpeg; using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem; @@ -17,9 +18,12 @@ namespace MediaBrowser.Server.Mono.Native public abstract class BaseMonoApp : INativeApp { protected StartupOptions StartupOptions { get; private set; } - protected BaseMonoApp(StartupOptions startupOptions) + protected ILogger Logger { get; private set; } + + protected BaseMonoApp(StartupOptions startupOptions, ILogger logger) { StartupOptions = startupOptions; + Logger = logger; } /// @@ -227,6 +231,11 @@ namespace MediaBrowser.Server.Mono.Native throw new NotImplementedException(); } + public IDbConnector GetDbConnector() + { + return new DbConnector(Logger); + } + public static FFMpegInstallInfo GetInfo(NativeEnvironment environment) { var info = new FFMpegInstallInfo(); diff --git a/MediaBrowser.Server.Mono/Native/NativeApp.cs b/MediaBrowser.Server.Mono/Native/NativeApp.cs index c73a96497..c0874a1d8 100644 --- a/MediaBrowser.Server.Mono/Native/NativeApp.cs +++ b/MediaBrowser.Server.Mono/Native/NativeApp.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Server.Startup.Common; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Startup.Common; namespace MediaBrowser.Server.Mono.Native { @@ -7,8 +8,8 @@ namespace MediaBrowser.Server.Mono.Native /// internal class NativeApp : BaseMonoApp { - public NativeApp(StartupOptions startupOptions) - : base(startupOptions) + public NativeApp(StartupOptions startupOptions, ILogger logger) + : base(startupOptions, logger) { } diff --git a/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs b/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs new file mode 100644 index 000000000..385a7d0c5 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/SqliteExtensions.cs @@ -0,0 +1,62 @@ +using System; +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.Persistence; + +namespace MediaBrowser.Server.Mono.Native +{ + /// + /// Class SQLiteExtensions + /// + static class SqliteExtensions + { + /// + /// Connects to db. + /// + /// The db path. + /// The logger. + /// Task{IDbConnection}. + /// dbPath + public static async Task ConnectToDb(string dbPath, ILogger logger) + { + if (string.IsNullOrEmpty(dbPath)) + { + throw new ArgumentNullException("dbPath"); + } + + logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); + + var connectionstr = new SQLiteConnectionStringBuilder + { + PageSize = 4096, + CacheSize = 2000, + SyncMode = SynchronizationModes.Full, + DataSource = dbPath, + JournalMode = SQLiteJournalModeEnum.Wal + }; + + var connection = new SQLiteConnection(connectionstr.ConnectionString); + + await connection.OpenAsync().ConfigureAwait(false); + + return connection; + } + } + + public class DbConnector : IDbConnector + { + private readonly ILogger _logger; + + public DbConnector(ILogger logger) + { + _logger = logger; + } + + public Task Connect(string dbPath) + { + return SqliteExtensions.ConnectToDb(dbPath, _logger); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 2a0609449..32de45242 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -79,7 +79,7 @@ namespace MediaBrowser.Server.Mono var fileSystem = new ManagedFileSystem(new PatternsLogger(logManager.GetLogger("FileSystem")), false, false); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - var nativeApp = new NativeApp(options); + var nativeApp = new NativeApp(options, logManager.GetLogger("App")); _appHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "emby.mono.zip", nativeApp); diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index fd6dee0f6..2d56a1575 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -410,13 +410,16 @@ namespace MediaBrowser.Server.Startup.Common UserRepository = await GetUserRepository().ConfigureAwait(false); RegisterSingleInstance(UserRepository); - DisplayPreferencesRepository = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths); + var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths); + DisplayPreferencesRepository = displayPreferencesRepo; RegisterSingleInstance(DisplayPreferencesRepository); - ItemRepository = new SqliteItemRepository(ApplicationPaths, JsonSerializer, LogManager); + var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager); + ItemRepository = itemRepo; RegisterSingleInstance(ItemRepository); - ProviderRepository = new SqliteProviderInfoRepository(LogManager, ApplicationPaths); + var providerRepo = new SqliteProviderInfoRepository(LogManager, ApplicationPaths); + ProviderRepository = providerRepo; RegisterSingleInstance(ProviderRepository); FileOrganizationRepository = await GetFileOrganizationRepository().ConfigureAwait(false); @@ -541,7 +544,7 @@ namespace MediaBrowser.Server.Startup.Common RegisterSingleInstance(NativeApp.GetPowerManagement()); var sharingRepo = new SharingRepository(LogManager, ApplicationPaths); - await sharingRepo.Initialize().ConfigureAwait(false); + await sharingRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); RegisterSingleInstance(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this)); RegisterSingleInstance(new SsdpHandler(LogManager.GetLogger("SsdpHandler"), ServerConfigurationManager, this)); @@ -557,9 +560,11 @@ namespace MediaBrowser.Server.Startup.Common SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager); RegisterSingleInstance(SubtitleEncoder); - - await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false); - await ConfigureItemRepositories().ConfigureAwait(false); + + await displayPreferencesRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + await itemRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + await providerRepo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); + ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; await ConfigureUserDataRepositories().ConfigureAwait(false); await ConfigureNotificationsRepository().ConfigureAwait(false); progress.Report(100); @@ -658,7 +663,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -677,7 +682,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -686,7 +691,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -695,7 +700,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -704,7 +709,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SyncRepository(LogManager, JsonSerializer, ServerConfigurationManager.ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); return repo; } @@ -717,35 +722,13 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); NotificationsRepository = repo; RegisterSingleInstance(NotificationsRepository); } - /// - /// Configures the repositories. - /// - /// Task. - private async Task ConfigureDisplayPreferencesRepositories() - { - await DisplayPreferencesRepository.Initialize().ConfigureAwait(false); - } - - /// - /// Configures the item repositories. - /// - /// Task. - private async Task ConfigureItemRepositories() - { - await ItemRepository.Initialize().ConfigureAwait(false); - - await ProviderRepository.Initialize().ConfigureAwait(false); - - ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; - } - /// /// Configures the user data repositories. /// @@ -754,7 +737,7 @@ namespace MediaBrowser.Server.Startup.Common { var repo = new SqliteUserDataRepository(LogManager, ApplicationPaths); - await repo.Initialize().ConfigureAwait(false); + await repo.Initialize(NativeApp.GetDbConnector()).ConfigureAwait(false); ((UserDataManager)UserDataManager).Repository = repo; } diff --git a/MediaBrowser.Server.Startup.Common/INativeApp.cs b/MediaBrowser.Server.Startup.Common/INativeApp.cs index c0758b47f..c13d3624e 100644 --- a/MediaBrowser.Server.Startup.Common/INativeApp.cs +++ b/MediaBrowser.Server.Startup.Common/INativeApp.cs @@ -3,6 +3,7 @@ using MediaBrowser.Model.Logging; using System.Collections.Generic; using System.Reflection; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Startup.Common.FFMpeg; namespace MediaBrowser.Server.Startup.Common @@ -104,5 +105,7 @@ namespace MediaBrowser.Server.Startup.Common FFMpegInstallInfo GetFfmpegInstallInfo(); void LaunchUrl(string url); + + IDbConnector GetDbConnector(); } } diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 291e63dac..f544a149d 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -13,6 +13,8 @@ 512 ..\ + + AnyCPU @@ -81,9 +83,9 @@ - - False - ..\packages\System.Data.SQLite.Core.1.0.94.0\lib\net45\System.Data.SQLite.dll + + ..\packages\System.Data.SQLite.Core.1.0.101.0\lib\net46\System.Data.SQLite.dll + True @@ -112,6 +114,7 @@ + @@ -156,14 +159,6 @@ - - x64\SQLite.Interop.dll - PreserveNewest - - - x86\SQLite.Interop.dll - PreserveNewest - MediaBrowser.InstallUtil.dll PreserveNewest @@ -1116,6 +1111,13 @@ + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + - \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs b/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs new file mode 100644 index 000000000..1cde2ea13 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/SqliteExtensions.cs @@ -0,0 +1,62 @@ +using System; +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Implementations.Persistence; + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class SQLiteExtensions + /// + static class SqliteExtensions + { + /// + /// Connects to db. + /// + /// The db path. + /// The logger. + /// Task{IDbConnection}. + /// dbPath + public static async Task ConnectToDb(string dbPath, ILogger logger) + { + if (string.IsNullOrEmpty(dbPath)) + { + throw new ArgumentNullException("dbPath"); + } + + logger.Info("Sqlite {0} opening {1}", SQLiteConnection.SQLiteVersion, dbPath); + + var connectionstr = new SQLiteConnectionStringBuilder + { + PageSize = 4096, + CacheSize = 2000, + SyncMode = SynchronizationModes.Full, + DataSource = dbPath, + JournalMode = SQLiteJournalModeEnum.Wal + }; + + var connection = new SQLiteConnection(connectionstr.ConnectionString); + + await connection.OpenAsync().ConfigureAwait(false); + + return connection; + } + } + + public class DbConnector : IDbConnector + { + private readonly ILogger _logger; + + public DbConnector(ILogger logger) + { + _logger = logger; + } + + public Task Connect(string dbPath) + { + return SqliteExtensions.ConnectToDb(dbPath, _logger); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/Native/WindowsApp.cs index 10cd59436..808c7558e 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/Native/WindowsApp.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Windows.Forms; using CommonIO; using MediaBrowser.Controller.Power; +using MediaBrowser.Server.Implementations.Persistence; using MediaBrowser.Server.Startup.Common.FFMpeg; using OperatingSystem = MediaBrowser.Server.Startup.Common.OperatingSystem; @@ -191,6 +192,11 @@ namespace MediaBrowser.ServerApplication.Native } } + public IDbConnector GetDbConnector() + { + return new DbConnector(_logger); + } + /// /// Processes the exited. /// diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 1c86a02ae..2d4baae25 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -3,5 +3,5 @@ - + \ No newline at end of file From 4ddde2cdc2ad3a951120853825df9f3588bc36e4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 18:11:24 -0400 Subject: [PATCH 237/852] introduce presentation unique key --- MediaBrowser.Api/Movies/MoviesService.cs | 7 +- MediaBrowser.Api/VideosService.cs | 14 +- MediaBrowser.Controller/Entities/BaseItem.cs | 6 + MediaBrowser.Controller/Entities/TV/Series.cs | 6 + MediaBrowser.Controller/Entities/Video.cs | 76 +++++--- .../Configuration/ServerConfiguration.cs | 1 + .../Library/LibraryManager.cs | 24 +-- .../Persistence/CleanDatabaseScheduledTask.cs | 6 + .../Persistence/SqliteItemRepository.cs | 168 ++++++++++++++---- 9 files changed, 212 insertions(+), 96 deletions(-) diff --git a/MediaBrowser.Api/Movies/MoviesService.cs b/MediaBrowser.Api/Movies/MoviesService.cs index bfbb3a6d7..1f0133e73 100644 --- a/MediaBrowser.Api/Movies/MoviesService.cs +++ b/MediaBrowser.Api/Movies/MoviesService.cs @@ -197,12 +197,7 @@ namespace MediaBrowser.Api.Movies var parentIds = new string[] { }; var list = _libraryManager.GetItemList(query, parentIds) - .Where(i => - { - // Strip out secondary versions - var v = i as Video; - return v != null && !v.PrimaryVersionId.HasValue; - }) + .DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase) .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N")) .ToList(); diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index c6ec69c85..6cefda3a3 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -130,6 +130,7 @@ namespace MediaBrowser.Api var items = request.Ids.Split(',') .Select(i => new Guid(i)) .Select(i => _libraryManager.GetItemById(i)) + .OfType