From 2b4dece54afbe8dff04b18ef454abd60af0ab826 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 17 Apr 2016 23:50:44 -0400 Subject: [PATCH 01/73] 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 65e2365256..fa8f0c009b 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 5f427146e3..5709ca15ae 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 b0d87c975b..6054a245ba 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 41bfb3b965..3a0526f43b 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 6ec9e64359..38528d8456 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 bdc043e9a7..fa7a51291c 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 211c771074..5186599306 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 746321e70d..590279db44 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 02/73] 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 5186599306..debcd054fe 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 590279db44..fb655c9cbe 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 03/73] 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 ec65221bc9..e1a91086b2 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 28abd636a2..b879040f8c 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 3d584e8581..eeec4ea56a 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 785efc3b65..5da1fcf279 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 42254f3603..9bab3d3801 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 04/73] update version --- SharedVersion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 6785f5f0d7..6b1c9e6bb6 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 05/73] 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 f7b550a13c..ad714c6ca0 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 06/73] 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 fa8f0c009b..bc155ff458 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 5709ca15ae..87b1c4248c 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 6054a245ba..3319fbaec7 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 3a0526f43b..b8efedf09d 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 d40f2a141d..ab2b59d482 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 4c140602d2..469767c658 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 07/73] 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 c900e4d069..e991565ad2 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 5bdfe2b44e3620821d3fe38eb5be30c6d0585020 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 16:14:27 -0400 Subject: [PATCH 08/73] 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 3a69c96660..3769787901 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 57b5fa73eedbd588600755dc2937d530d3df1ccb Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Apr 2016 23:14:45 -0400 Subject: [PATCH 09/73] 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 05b1ebc80c..98580396d2 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 10/73] 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 06db8a2378..3199ed12b9 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 894750c812..1b8ecd5211 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 11/73] 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 ad714c6ca0..f84fe058a7 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 12/73] 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 f9060d184e..1014fc2ee9 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 13/73] 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 f378747749..5bb4ed5f00 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 04371c13b6..959334d785 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 4d2ca9ffea..6004992ccb 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 9eeb89a1fa..7eabff072d 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 c3e24090c3..fe8bf3ed31 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 7928d0bf94..49ec9f8ef4 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 1540f178a4..cea638a395 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 278d8ed710..59a2da4603 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 50ae195809..2ee55edb98 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 14/73] 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 ba8a3bdf5c..e37b83f4b5 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 a38086126fc08bc64e9c73a259334807614ec874 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 20 Apr 2016 14:51:47 -0400 Subject: [PATCH 15/73] 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 901554973b..4b05a5ee68 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 cb344690cd..49d3c37eac 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 bc155ff458..7ed8a9490e 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 87b1c4248c..8a14948d21 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 3319fbaec7..be3995aeb6 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 371dbbda2a..14fdb1197d 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 ed8a27fafe..061afed6d9 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 b8efedf09d..3ab55168d5 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 1e6b7c729d..f44f89f22c 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 644f732a74..a2867dcc9f 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 bf6bf092f3..e59ee6d634 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 16/73] 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 4b05a5ee68..901554973b 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 49d3c37eac..49f50735f6 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 7ed8a9490e..f857a43e44 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 14fdb1197d..371dbbda2a 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 f44f89f22c..1e6b7c729d 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 a2867dcc9f..644f732a74 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 e59ee6d634..36c357926c 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 17/73] 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 02a8d69387..9bb5b4fd7d 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 18/73] 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 25463b660e..c5cb810e53 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 8719f54489..33d1069162 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 ac1b7ca996..f83c7d545d 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 19/73] 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 e45df3f4a2..270f01b2b4 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 ad6bde6355ab4a8cf9d4d6a51c62844bdc029fcb Mon Sep 17 00:00:00 2001 From: softworkz Date: Sat, 23 Apr 2016 06:30:05 +0200 Subject: [PATCH 20/73] 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 7eabff072d..ad4ee436e3 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 21/73] 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 53a573bd1e..a280a897a0 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 d207e6e7c6..5262f8e3b1 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 a1dbc19679..343586ea56 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 6c6f6f0eb0..77d6f617da 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 51051e41d6..9da717b7ed 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 e8eeab9c53..8f3c4668f1 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 02c3302679..3bceb976e7 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 7fa7e0d15d..f7f0fd6cc5 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 b715803ea9..9e58b4608c 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 30507b8917..3b829af9eb 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 e73a98b6f9..e41982ef67 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 c04f805495..ad900123ed 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 bcafdc6f62..814488df17 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 ae563b287e..a1e038374c 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 1b8ecd5211..cec74c68ad 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 b68f93cf6b..44e250350c 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 2b37d0462d..bec70294f7 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 049ffd7d8f..37e76531b1 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 517951cb8c..1168bfeee0 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 d22827c25e..36800202fd 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 fe0bda8288..2e51393e39 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 98580396d2..7d30042dc0 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 1c83d73fb3..672ebc95d7 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 f66e9254ef..ee1505b46c 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 82baae2507..f5a26ba0ae 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 2ae116521b..d26c76b7cb 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 22/73] 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 2017b40f4a..8da1beb687 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 64b3372212..6d7d861823 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 60d8f737fe..43f5d741b4 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 66aede029f..dce839b572 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 0ae08c4ad3..a561dbf4b3 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -13,8 +13,8 @@ Copyright © Emby 2013 - - + + From 9807448fce0bba3b1aaf9fcb249efc5efe7b3146 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 23 Apr 2016 14:38:36 -0400 Subject: [PATCH 23/73] 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 2b37d0462d..40ce6ad475 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 6d19c32759..72c191121a 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 20d4c6b2a4..dbfd6f4e88 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 121d4192ed..00f987d3cd 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 f83c7d545d..4dc8a47f5b 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 274c72b254..919709538f 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 146a4372b9..ff5fe4d840 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 673c6cdddf..2146274af2 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 24/73] 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 f84fe058a7..7aad3b91ab 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 25/73] 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 e4eecec18f..65eed1a235 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 72c191121a..fbfef9a34d 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 93dbe2945c..2e2b42ba2b 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 a4504f25a6..db48d1110e 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 854fa44c1e..f9d173c595 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 00f987d3cd..c0758b47f5 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 4dc8a47f5b..454c415a13 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 ff5fe4d840..10cd59436d 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 2146274af2..27816db5a4 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 26/73] 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 901554973b..9278de3be3 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 27/73] 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 7aad3b91ab..7565c8dfbb 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 28/73] 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 3199ed12b9..c95d58a421 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 cec74c68ad..a0d60c1669 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 2e2b42ba2b..01575e71f6 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 5401641e2b4c0eb35a308a952e5370dd968b9621 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 25 Apr 2016 13:35:49 -0400 Subject: [PATCH 29/73] 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 959334d785..f5fb72de54 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 fb655c9cbe..fb91a2dd24 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 30/73] 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 498602ddf9..1e7aa3de5a 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 3c7ee55b7d..98249f5ac9 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 60ff23b04b..d85e8ba3f9 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 469767c658..a3e5589e88 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 523f14dfc8..c874e51b61 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 ffd85fd18a..1e571c84fb 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 31/73] 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 c8b3d51317..0f6b10b43a 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 ad55c186a5..8ae9aa5bb2 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 5428e6c920..0fd6fa56f2 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 ccba293a38..17c4f59ba0 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 0ace5b38c353781b056e17191b00df714594ec8f Mon Sep 17 00:00:00 2001 From: nfnty Date: Tue, 26 Apr 2016 10:26:41 +0200 Subject: [PATCH 32/73] 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 f8039b2cf2..29421ebafc 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 75b5498c56..d020a73fe0 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 e37b83f4b5..6d15d168d1 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 33/73] 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 7565c8dfbb..5534b95a9f 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 34/73] 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 a280a897a0..74e668754a 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 35/73] 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 f5fb72de54..f9f03a9c5f 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 71019e0ade..e84b66c5a7 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 5534b95a9f..bfa4995cf7 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -1712,6 +1712,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 8499183d77a5351e4dd0a9b200b8f82a6d303fe7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 13:43:09 -0400 Subject: [PATCH 36/73] 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 61a5d98a32..e271fbcb25 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 37/73] 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 c3af09cd56..cb16158268 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 cfdc40bb2d..7d2029cabe 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 38/73] 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 fb91a2dd24..fcc39deb50 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 39/73] 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 0d5b5c4aa9..5e2f98c093 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 40/73] 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 f9f03a9c5f..908d659776 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 4297003277..5e0cf6e88b 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 0f6b10b43a..5388b8668f 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 13a06afc23..09ca134d1a 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 17c4f59ba0..e1bcfa861e 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 41/73] 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 a2eac41ec3..5e0baa1f67 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 42/73] 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 908d659776..9171c2a716 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 34a8208533..faddc37786 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 35b9a1959e..2bb6cc182b 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 95f5cb0e10..092b797ce7 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 43/73] 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 9278de3be3..45f1a64c9b 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 070aae3a70..ff5a3010e4 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 38528d8456..c7c001cee7 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 fa7a51291c..25252956b2 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 debcd054fe..76682c63b8 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 fcc39deb50..783bd5ff43 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 d0aece61e7e74833a3f53050d2fc0fdd5a91e200 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 15:41:12 -0400 Subject: [PATCH 44/73] 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 5cf9966e8f..2c6e27294d 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 8ae9aa5bb2..e79ad2dfbd 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 f7128c7f8f04a39272ec10c699f3a05dac1a8e67 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:24:53 -0400 Subject: [PATCH 45/73] 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 77464be58d..1c72ccd523 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 33874b4d4a..0bec528bb6 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 044c8b93a7..fe1a7fb28f 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 464e8aa58e..249c4212e3 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 46/73] 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 0bec528bb6..10b8727533 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 249c4212e3..965c081ebd 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 9ec3b6c0ebc27c25f4837f4d79fc2415bf25409c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 27 Apr 2016 16:52:09 -0400 Subject: [PATCH 47/73] 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 343586ea56..b174de4555 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 444046208e..5b3bd87db0 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 9e58b4608c..37b51da5a3 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 e683907c46..673663d7f1 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 5e7ce9f7ed..54d729eb7f 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 48/73] 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 eeec4ea56a..cb5e6c88f2 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 e091cddc63..51db77bf6a 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 9da717b7ed..872deba347 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 336968a840..5fb3ea3696 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 55dcc99f58..d031b3d6b2 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 1168bfeee0..3c831dbbca 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 f7c19988c3..2c6b09ade6 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 7d30042dc0..407ff762a7 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 49/73] 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 46f630fe04..fc2b155ecd 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 d85e8ba3f9..351bc05af6 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 442f151dd0..63d0846fc1 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 50/73] 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 2c7d3856b3..d81e6f0ff7 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 4fc1d210d3..4b64295ea6 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 cb5e6c88f2..ae48c996a0 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 49d41e06cc..ca3320cc60 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 291214fcd3..5c88c87d86 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 4a69646f8e..acb1227e40 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 5ce8d30add..c1dd929877 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 51/73] 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 454c415a13..dc61dcda8e 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 52/73] 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 bfa4995cf7..b2627562a1 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 53/73] 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 1e6b7c729d..98d246980b 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 a12ec7167ead1ce5387919a0cefc92fc5bf46f47 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 28 Apr 2016 23:10:48 -0400 Subject: [PATCH 54/73] 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 b2627562a1..6bc9f9b1b3 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 55/73] 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 ff3d5a5b24..b3e73740d9 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 74e668754a..ab05c959e8 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 77d6f617da..d13716cba1 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 51db77bf6a..5958c3a0ad 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 872deba347..c588a9a690 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 8f3c4668f1..ceb41178e1 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 59e8f7cef6..12bb77afc9 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 2ac9fdfa0a..93eee69ae7 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 ca7c08608d..bb17b83ec8 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 9d16849482..719779674b 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 2c6b09ade6..65ac12adf0 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 407ff762a7..7d0f499550 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 56/73] 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 b174de4555..775e6dfb9c 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 57/73] 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 968d703bef..2d5225344e 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 b23bd16f35..490a51128d 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 ff5a3010e4..1544a78b66 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 58/73] 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 63d0846fc1..fa4f821364 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 59/73] 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 45f1a64c9b..dce29f6de2 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 60/73] 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 fbf246b3ab..f3b4f40534 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 9ebae5d913..49012c65af 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 96d570ef9e..5fc9c31689 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 783bd5ff43..4f724fe40b 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 61/73] 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 98249f5ac9..54443d9ca3 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 fa4f821364..d589b2bc38 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 62/73] 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 dce29f6de2..800f246c4d 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 263efbb629..0ea48fab62 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 04ba2d57aca90ade64fafac0f3cd474645c79154 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 14:22:54 -0400 Subject: [PATCH 63/73] 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 2ee55edb98..7adde5c273 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 64/73] 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 ffe7c50c8e..2d9cc40c0a 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 d2feb41169..7c3959f6e8 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 21289970e2..093b37df3e 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 01c7c33b6f..34fb2a6df7 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 89d00eb32b..af833a85cf 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 37584f006f..733bda9ae6 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 db5e0ee293..80bb756ef5 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 18daef331a..bbb9bf6de9 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 01fb31d0c5..399fdead9c 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 55e11ec4b7..9de360023e 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 98d246980b..07a4b89953 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 10b8727533..d95a4fefb9 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 01575e71f6..fd6dee0f6e 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 5ba5fb44ac..0ae021407b 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 65/73] 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 4f724fe40b..a44d66c739 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 1f9d32afc52e9bd133ddf22d12bdc468adaf9ebe Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 30 Apr 2016 18:05:13 -0400 Subject: [PATCH 66/73] 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 065f882687..bfbb3a6d75 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 6ae2b08322..b3164ce3f7 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 c2c481cb6f..8cc5cab358 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 9171c2a716..4828426fdc 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 f4cdc8fa1b..41f0c02bdc 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 db669ca37d..5a0e0b614b 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 56ac14e9df..4ff0f6439f 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 34fb2a6df7..bc9fa1d7e7 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 c9956c68a5..6a9842cb2e 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 7adde5c273..b19f5727c8 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 092b797ce7..a47fcdf4f8 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 ae737d2446..c16beed8cc 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 ab2b59d482..eec8328f89 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 88f11c3685..014e8babf9 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 c881591beb..3edf23020a 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 1bc5261b44..8b14efffcf 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 fe1a7fb28f..38edc30240 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 3e43ebe9b8..dc880d84b5 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 6d15d168d1..d2e09d4ebf 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 67/73] 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 929308ba08..fd56a6746a 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 e6178c183b..5cb4e8c9d1 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 02bcceada4..2cca632179 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 45304d47ee..4d041264c0 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 4828426fdc..f91b6b31e1 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 e597b2a152..9ed2400469 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 d2b6b48568..71028d4cf7 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 bc35c4738a..1c09ee5075 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 233e1e0fd1..fa890ad9eb 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 faddc37786..3e0fa3f1dc 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 6004992ccb..5882b5f4dd 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 b52f16a462..bf4c2559c5 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 560ea6e05e..89581e967d 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 a55527f37b..7ceefbc6e7 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 e1a91086b2..3ad6170a53 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 acd02e8ab9..ebd22c6c4e 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 ad4ee436e3..c03eed6c9d 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 fe8bf3ed31..3be2fc6243 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 d81e6f0ff7..cdabaa84e8 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 163dcd667c..f27ce79dd3 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 ba328ff754..654c6b581b 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 17a27eac1e..e6f472414e 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 2bb6cc182b..50aeed27d4 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 59b921c6a9..cc30709db2 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 f310a957cc..a8c7376734 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 c16beed8cc..98f8abd405 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 ad3965a76992fe13e92a244fd70c08bdfb8d5191 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 1 May 2016 16:56:06 -0400 Subject: [PATCH 68/73] 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 b19f5727c8..e8af0c3cb6 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 69/73] 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 6215100285..e1ab61cbbe 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 70/73] 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 6ad4a5377e..cd587a5099 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 17de730cb8..abf96994f1 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 15df1f6492..7bcc36958a 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 2a904be0d9..2e165f4163 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 1f77d0ca1c..891275d775 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 85ab761823..b0e05a5bc8 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 43f5d741b4..aff3a5e160 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 7302431e17..cecf03ddfe 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 4fb1e07dd7..103b75f840 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 0000000000..cac9fe9835 --- /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 45e0304c1c..6077cfdba4 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 2d5aad04df..037776997e 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 dbceda727b..40d5c9586e 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 63c41c71fe..33a2b11877 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 9bd7e47f39..f7ca39a548 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 b932f0cac4..e8d9814ecb 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 d6d7f021a3..317743eb1b 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 965c081ebd..6d31663b97 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 48d2df7cef..b71877e17a 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 fbfef9a34d..a012a19a3d 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 c73a964970..c0874a1d82 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 0000000000..385a7d0c58 --- /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 2a06094493..32de452421 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 fd6dee0f6e..2d56a15753 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 c0758b47f5..c13d3624e3 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 291e63dac7..f544a149d8 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 0000000000..1cde2ea139 --- /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 10cd59436d..808c7558ec 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 1c86a02ae6..2d4baae256 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 71/73] 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 bfbb3a6d75..1f0133e73c 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 c6ec69c858..6cefda3a35 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