From 360e666cc630c2200111a68f027c0ef6a176f73a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 14 Oct 2016 12:22:04 -0400 Subject: [PATCH 01/12] update recording dialogs --- .../EntryPoints/ExternalPortForwarding.cs | 54 +++++++++++-------- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/TunerHosts/M3uParser.cs | 2 +- .../MediaBrowser.WebDashboard.csproj | 3 -- 4 files changed, 35 insertions(+), 26 deletions(-) diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 1021d8823..3274231ee 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -122,43 +122,55 @@ namespace MediaBrowser.Server.Implementations.EntryPoints var identifier = string.IsNullOrWhiteSpace(usn) ? nt : usn; - if (info.Location != null && !_usnsHandled.Contains(identifier)) + if (info.Location == null) { - _usnsHandled.Add(identifier); + return; + } - _logger.Debug("Calling Nat.Handle on " + identifier); - - IPAddress address; - if (IPAddress.TryParse(info.Location.Host, out address)) + lock (_usnsHandled) + { + if (_usnsHandled.Contains(identifier)) { - // The Handle method doesn't need the port - var endpoint = new IPEndPoint(address, info.Location.Port); + return; + } + _usnsHandled.Add(identifier); + } - IPAddress localAddress = null; + _logger.Debug("Calling Nat.Handle on " + identifier); - try - { - var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false); + IPAddress address; + if (IPAddress.TryParse(info.Location.Host, out address)) + { + // The Handle method doesn't need the port + var endpoint = new IPEndPoint(address, info.Location.Port); - if (!IPAddress.TryParse(localAddressString, out localAddress)) - { - return; - } - } - catch + IPAddress localAddress = null; + + try + { + var localAddressString = await _appHost.GetLocalApiUrl().ConfigureAwait(false); + + if (!IPAddress.TryParse(localAddressString, out localAddress)) { return; } - - NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp); } + catch + { + return; + } + + NatUtility.Handle(localAddress, info, endpoint, NatProtocol.Upnp); } } private void ClearCreatedRules(object state) { _createdRules = new List(); - _usnsHandled = new List(); + lock (_usnsHandled) + { + _usnsHandled.Clear(); + } } void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 86d77982c..2e58c6b30 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -741,7 +741,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV { PostPaddingSeconds = Math.Max(config.PostPaddingSeconds, 0), PrePaddingSeconds = Math.Max(config.PrePaddingSeconds, 0), - RecordAnyChannel = true, + RecordAnyChannel = false, RecordAnyTime = true, RecordNewOnly = true, diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index c07c448db..38eb9bdd1 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -114,8 +114,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts channel.ImageUrl = FindProperty("tvg-logo", extInf, null); channel.Number = FindProperty("channel-id", extInf, channel.Number); channel.Number = FindProperty("tvg-id", extInf, channel.Number); - channel.Name = FindProperty("tvg-name", extInf, channel.Name); channel.Name = FindProperty("tvg-id", extInf, channel.Name); + channel.Name = FindProperty("tvg-name", extInf, channel.Name); return channel; } diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index b57416fab..1d49a31c9 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -515,9 +515,6 @@ PreserveNewest - - PreserveNewest - PreserveNewest From ddd68776242233a3c92eb5adab34e2df14c8e41c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 14 Oct 2016 12:28:19 -0400 Subject: [PATCH 02/12] 3.1.189 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 013a0a589..ebb797fb0 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.1.*")] -[assembly: AssemblyVersion("3.1.188")] +[assembly: AssemblyVersion("3.1.189")] From d517aadc1c79337fe0e1e7d1de3f72484b2fb91c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 14 Oct 2016 12:31:51 -0400 Subject: [PATCH 03/12] update project --- MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index 1d49a31c9..36dd12651 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -164,6 +164,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From ac2ca1fec211d7793c3cacc219204515aa4defe8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 15 Oct 2016 18:12:16 -0400 Subject: [PATCH 04/12] update recording dialogs --- .../Entities/InternalItemsQuery.cs | 2 +- MediaBrowser.Model/Entities/MediaStream.cs | 15 +++++++++++++-- .../Library/MediaSourceManager.cs | 1 + .../Library/Resolvers/TV/SeriesResolver.cs | 6 ++++++ .../LiveTv/LiveTvManager.cs | 9 ++++----- .../Persistence/SqliteItemRepository.cs | 13 ++++++------- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index fec703b94..3fb118a9c 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -182,7 +182,7 @@ namespace MediaBrowser.Controller.Entities case ItemFields.HomePageUrl: case ItemFields.VoteCount: case ItemFields.DisplayMediaType: - case ItemFields.ServiceName: + //case ItemFields.ServiceName: case ItemFields.Genres: case ItemFields.Studios: case ItemFields.Settings: diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs index 990de332e..6d3e2ce4c 100644 --- a/MediaBrowser.Model/Entities/MediaStream.cs +++ b/MediaBrowser.Model/Entities/MediaStream.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Extensions; using System.Diagnostics; @@ -47,7 +48,7 @@ namespace MediaBrowser.Model.Entities { if (!string.IsNullOrEmpty(Title)) { - return Title; + return AddLanguageIfNeeded(Title); } if (Type == MediaStreamType.Audio) @@ -115,6 +116,16 @@ namespace MediaBrowser.Model.Entities } } + private string AddLanguageIfNeeded(string title) + { + if (!string.IsNullOrEmpty(Language) && title.IndexOf(Language, StringComparison.OrdinalIgnoreCase) == -1) + { + title = StringHelper.FirstToUpper(Language) + " " + title; + } + + return title; + } + public string NalLengthSize { get; set; } /// diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index e7bfe56f2..716d627a9 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -360,6 +360,7 @@ namespace MediaBrowser.Server.Implementations.Library public async Task OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken) { + enableAutoClose = false; await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs index 1e480e265..3217cd67b 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs @@ -85,6 +85,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV { if (args.ContainsFileSystemEntryByName("tvshow.nfo")) { + if (args.Parent.IsRoot) + { + // For now, return null, but if we want to allow this in the future then add some additional checks to guard against a misplaced tvshow.nfo + return null; + } + return new Series { Path = args.Path, diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index bac9789b5..aa404b37c 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -1752,7 +1752,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv public async Task AddInfoToProgramDto(List> tuples, List fields, User user = null) { - var recordingTuples = new List>(); + var programTuples = new List>(); foreach (var tuple in tuples) { @@ -1812,18 +1812,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - var service = GetService(program); - var serviceName = service == null ? null : service.Name; + var serviceName = program.ServiceName; if (fields.Contains(ItemFields.ServiceName)) { dto.ServiceName = serviceName; } - recordingTuples.Add(new Tuple(dto, serviceName, program.ExternalId, program.ExternalSeriesIdLegacy)); + programTuples.Add(new Tuple(dto, serviceName, program.ExternalId, program.ExternalSeriesIdLegacy)); } - await AddRecordingInfo(recordingTuples, CancellationToken.None).ConfigureAwait(false); + await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false); } public void AddInfoToRecordingDto(BaseItem item, BaseItemDto dto, User user = null) diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 2235bfe0d..f33b18389 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1188,7 +1188,7 @@ namespace MediaBrowser.Server.Implementations.Persistence public ItemImageInfo ItemImageInfoFromValueString(string value) { - var parts = value.Split(new[] { '*' }, StringSplitOptions.RemoveEmptyEntries); + var parts = value.Split(new[] { '*' }, StringSplitOptions.None); var image = new ItemImageInfo(); @@ -1633,14 +1633,13 @@ namespace MediaBrowser.Server.Implementations.Persistence } index++; - if (query.HasField(ItemFields.ServiceName)) + // TODO: Even if not needed by apps, the server needs it internally + // But get this excluded from contexts where it is not needed + if (!reader.IsDBNull(index)) { - if (!reader.IsDBNull(index)) - { - item.ServiceName = reader.GetString(index); - } - index++; + item.ServiceName = reader.GetString(index); } + index++; if (!reader.IsDBNull(index)) { From e9a0b284fcaa6095d1df640163653af9c82c1f2b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 15 Oct 2016 18:19:18 -0400 Subject: [PATCH 05/12] 3.1.190 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index ebb797fb0..af67f7e6d 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.1.*")] -[assembly: AssemblyVersion("3.1.189")] +[assembly: AssemblyVersion("3.1.190")] From 79463d112cec6ec34dcff5776b87bbf6d823fbbc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 15 Oct 2016 18:29:16 -0400 Subject: [PATCH 06/12] update recording delete --- MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs | 2 +- MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index e6fefbf72..02d3118ef 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -113,7 +113,7 @@ namespace MediaBrowser.Controller.LiveTv public override bool CanDelete() { - return Status == RecordingStatus.Completed; + return Status == RecordingStatus.Completed || Status == RecordingStatus.New; } public override bool IsAuthorizedToDelete(User user) diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index c255630f5..d54f93a07 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -130,7 +130,7 @@ namespace MediaBrowser.Controller.LiveTv public override bool CanDelete() { - return Status == RecordingStatus.Completed; + return Status == RecordingStatus.Completed || Status == RecordingStatus.New; } public override bool IsAuthorizedToDelete(User user) From 401dc39e4cfa9d9eea51003187a39ea5c7f1aba8 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 16 Oct 2016 12:17:32 -0400 Subject: [PATCH 07/12] update translations --- Nuget/MediaBrowser.Common.Internal.nuspec | 4 ++-- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 1259a759b..31d946691 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.662 + 3.0.663 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Emby Theater and Emby Server. Not intended for plugin developer consumption. Copyright © Emby 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 931db69fa..86524c2b6 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.662 + 3.0.663 MediaBrowser.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index b3d929f59..860a19436 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.662 + 3.0.663 Media Browser.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + From 55f47d21204bd166ab214256c7b8dd05c4d7ccd4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 16 Oct 2016 13:11:32 -0400 Subject: [PATCH 08/12] update recording defaults --- .../Playback/BaseStreamingService.cs | 8 ++ .../Playback/Hls/DynamicHlsService.cs | 13 ++- MediaBrowser.Api/Playback/StreamRequest.cs | 1 + MediaBrowser.Controller/Entities/BaseItem.cs | 95 ++++++++++++++++--- .../Entities/Movies/Movie.cs | 2 +- MediaBrowser.Controller/Entities/Video.cs | 4 +- .../LiveTv/LiveTvAudioRecording.cs | 6 +- .../LiveTv/LiveTvVideoRecording.cs | 6 +- .../Encoder/EncoderValidator.cs | 2 + .../Encoder/MediaEncoder.cs | 5 + MediaBrowser.Model/Dlna/StreamBuilder.cs | 1 + MediaBrowser.Model/Dlna/StreamInfo.cs | 2 + MediaBrowser.Model/Dlna/TranscodingProfile.cs | 3 + .../Intros/DefaultIntroProvider.cs | 9 +- .../LiveTv/EmbyTV/EmbyTV.cs | 2 +- .../LiveTv/TunerHosts/M3UTunerHost.cs | 4 + 16 files changed, 139 insertions(+), 24 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 0e91c0b9e..eb80ae89e 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1735,6 +1735,13 @@ namespace MediaBrowser.Api.Playback { request.Tag = val; } + else if (i == 29) + { + if (videoRequest != null) + { + videoRequest.EnableSplittingOnNonKeyFrames = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); + } + } } } @@ -2354,6 +2361,7 @@ namespace MediaBrowser.Api.Playback { state.VideoRequest.CopyTimestamps = transcodingProfile.CopyTimestamps; state.VideoRequest.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; + state.VideoRequest.EnableSplittingOnNonKeyFrames = transcodingProfile.EnableSplittingOnNonKeyFrames; } } } diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 51455c141..121ab95eb 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -886,13 +886,11 @@ namespace MediaBrowser.Api.Playback.Hls var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty; - var enableGenericSegmenter = false; - - if (enableGenericSegmenter) + if (state.VideoRequest.EnableSplittingOnNonKeyFrames) { 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}\"", + 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} -break_non_keyframes 1 -segment_format mpegts -segment_list_type m3u8 -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", inputModifier, GetInputArgument(state), threads, @@ -908,7 +906,11 @@ namespace MediaBrowser.Api.Playback.Hls } // TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time - 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}\"", + var supportsSplitByTime = false; + var splitByTime = supportsSplitByTime && state.VideoRequest.EnableSplittingOnNonKeyFrames; + var splitByTimeArg = splitByTime ? " -hls_flags split_by_time" : ""; + + return string.Format("{0}{12} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7}{8} -start_number {9} -hls_list_size {10} -y \"{11}\"", inputModifier, GetInputArgument(state), threads, @@ -917,6 +919,7 @@ namespace MediaBrowser.Api.Playback.Hls timestampOffsetParam, GetAudioArguments(state), state.SegmentLength.ToString(UsCulture), + splitByTimeArg, startNumberParam, state.HlsListSize.ToString(UsCulture), outputPath, diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 8cdf846ed..5b936f718 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -194,6 +194,7 @@ namespace MediaBrowser.Api.Playback public bool CopyTimestamps { get; set; } public bool EnableSubtitlesInManifest { get; set; } + public bool EnableSplittingOnNonKeyFrames { get; set; } public VideoStreamRequest() { diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 7eb84fc80..3ebefa217 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1188,7 +1188,7 @@ namespace MediaBrowser.Controller.Entities var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds); - var tasks = newItems.Select(i => i.RefreshMetadata(options, cancellationToken)); + var tasks = newItems.Select(i => RefreshMetadataForOwnedItem(i, true, options, cancellationToken)); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -1197,7 +1197,7 @@ namespace MediaBrowser.Controller.Entities return itemsChanged; } - private static async Task RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable fileSystemChildren, CancellationToken cancellationToken) + private async Task RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable fileSystemChildren, CancellationToken cancellationToken) { var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService).ToList(); @@ -1215,7 +1215,7 @@ namespace MediaBrowser.Controller.Entities subOptions.ForceSave = true; } - return i.RefreshMetadata(subOptions, cancellationToken); + return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); }); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -1228,7 +1228,7 @@ namespace MediaBrowser.Controller.Entities /// /// Refreshes the theme songs. /// - private static async Task RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List fileSystemChildren, CancellationToken cancellationToken) + private async Task RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List fileSystemChildren, CancellationToken cancellationToken) { var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService).ToList(); var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToList(); @@ -1245,7 +1245,7 @@ namespace MediaBrowser.Controller.Entities subOptions.ForceSave = true; } - return i.RefreshMetadata(subOptions, cancellationToken); + return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); }); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -2203,14 +2203,85 @@ namespace MediaBrowser.Controller.Entities return Task.FromResult(true); } - protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, string path, CancellationToken cancellationToken) + protected Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken) { - var newOptions = new MetadataRefreshOptions(options.DirectoryService) + var newOptions = new MetadataRefreshOptions(options); + newOptions.SearchResult = null; + + var item = this; + + if (copyTitleMetadata) { - ImageRefreshMode = options.ImageRefreshMode, - MetadataRefreshMode = options.MetadataRefreshMode, - ReplaceAllMetadata = options.ReplaceAllMetadata - }; + // Take some data from the main item, for querying purposes + if (!item.Genres.SequenceEqual(ownedItem.Genres, StringComparer.Ordinal)) + { + newOptions.ForceSave = true; + ownedItem.Genres = item.Genres.ToList(); + } + if (!item.Studios.SequenceEqual(ownedItem.Studios, StringComparer.Ordinal)) + { + newOptions.ForceSave = true; + ownedItem.Studios = item.Studios.ToList(); + } + if (!item.ProductionLocations.SequenceEqual(ownedItem.ProductionLocations, StringComparer.Ordinal)) + { + newOptions.ForceSave = true; + ownedItem.ProductionLocations = item.ProductionLocations.ToList(); + } + if (!item.Keywords.SequenceEqual(ownedItem.Keywords, StringComparer.Ordinal)) + { + newOptions.ForceSave = true; + ownedItem.Keywords = item.Keywords.ToList(); + } + if (item.CommunityRating != ownedItem.CommunityRating) + { + ownedItem.CommunityRating = item.CommunityRating; + newOptions.ForceSave = true; + } + if (item.CriticRating != ownedItem.CriticRating) + { + ownedItem.CriticRating = item.CriticRating; + newOptions.ForceSave = true; + } + if (!string.Equals(item.Overview, ownedItem.Overview, StringComparison.Ordinal)) + { + ownedItem.Overview = item.Overview; + newOptions.ForceSave = true; + } + if (!string.Equals(item.ShortOverview, ownedItem.ShortOverview, StringComparison.Ordinal)) + { + ownedItem.ShortOverview = item.ShortOverview; + newOptions.ForceSave = true; + } + if (!string.Equals(item.OfficialRating, ownedItem.OfficialRating, StringComparison.Ordinal)) + { + ownedItem.OfficialRating = item.OfficialRating; + newOptions.ForceSave = true; + } + if (!string.Equals(item.CustomRating, ownedItem.CustomRating, StringComparison.Ordinal)) + { + ownedItem.CustomRating = item.CustomRating; + newOptions.ForceSave = true; + } + if (!string.Equals(item.CriticRatingSummary, ownedItem.CriticRatingSummary, StringComparison.Ordinal)) + { + ownedItem.CriticRatingSummary = item.CriticRatingSummary; + newOptions.ForceSave = true; + } + if (!string.Equals(item.OfficialRatingDescription, ownedItem.OfficialRatingDescription, StringComparison.Ordinal)) + { + ownedItem.OfficialRatingDescription = item.OfficialRatingDescription; + newOptions.ForceSave = true; + } + } + + return ownedItem.RefreshMetadata(newOptions, cancellationToken); + } + + protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken) + { + var newOptions = new MetadataRefreshOptions(options); + newOptions.SearchResult = null; var id = LibraryManager.GetNewItemId(path, typeof(Video)); @@ -2229,7 +2300,7 @@ namespace MediaBrowser.Controller.Entities return Task.FromResult(true); } - return video.RefreshMetadata(newOptions, cancellationToken); + return RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken); } public string GetEtag(User user) diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 22cc0316a..dea42c463 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -103,7 +103,7 @@ namespace MediaBrowser.Controller.Entities.Movies var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds); - var tasks = newItems.Select(i => i.RefreshMetadata(options, cancellationToken)); + var tasks = newItems.Select(i => RefreshMetadataForOwnedItem(i, false, options, cancellationToken)); await Task.WhenAll(tasks).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 5aaff6fef..e87b726b2 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -427,7 +427,7 @@ namespace MediaBrowser.Controller.Entities if (IsStacked) { var tasks = AdditionalParts - .Select(i => RefreshMetadataForOwnedVideo(options, i, cancellationToken)); + .Select(i => RefreshMetadataForOwnedVideo(options, true, i, cancellationToken)); await Task.WhenAll(tasks).ConfigureAwait(false); } @@ -442,7 +442,7 @@ namespace MediaBrowser.Controller.Entities RefreshLinkedAlternateVersions(); var tasks = LocalAlternateVersions - .Select(i => RefreshMetadataForOwnedVideo(options, i, cancellationToken)); + .Select(i => RefreshMetadataForOwnedVideo(options, false, i, cancellationToken)); await Task.WhenAll(tasks).ConfigureAwait(false); } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 02d3118ef..de5ffcd58 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -113,7 +113,11 @@ namespace MediaBrowser.Controller.LiveTv public override bool CanDelete() { - return Status == RecordingStatus.Completed || Status == RecordingStatus.New; + if (string.Equals(ServiceName, "Emby", StringComparison.OrdinalIgnoreCase)) + { + return Status == RecordingStatus.Completed; + } + return true; } public override bool IsAuthorizedToDelete(User user) diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index d54f93a07..2c0ced0e6 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -130,7 +130,11 @@ namespace MediaBrowser.Controller.LiveTv public override bool CanDelete() { - return Status == RecordingStatus.Completed || Status == RecordingStatus.New; + if (string.Equals(ServiceName, "Emby", StringComparison.OrdinalIgnoreCase)) + { + return Status == RecordingStatus.Completed; + } + return true; } public override bool IsAuthorizedToDelete(User user) diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 24de4e77e..7acff8fc8 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -154,6 +154,8 @@ namespace MediaBrowser.MediaEncoding.Encoder } }; + _logger.Info("Running {0} {1}", path, arguments); + using (process) { process.Start(); diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index fc1444e1b..340990373 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -610,6 +610,11 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (video.Protocol != MediaProtocol.File) { + // If it's mpeg based, assume true + if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1) + { + return true; + } return false; } diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 52b7fd43a..18e46b84c 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -478,6 +478,7 @@ namespace MediaBrowser.Model.Dlna playlistItem.VideoCodec = transcodingProfile.VideoCodec; playlistItem.CopyTimestamps = transcodingProfile.CopyTimestamps; playlistItem.EnableSubtitlesInManifest = transcodingProfile.EnableSubtitlesInManifest; + playlistItem.EnableSplittingOnNonKeyFrames = transcodingProfile.EnableSplittingOnNonKeyFrames; if (!string.IsNullOrEmpty(transcodingProfile.MaxAudioChannels)) { diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index c9cb873e1..b8db8a10c 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -37,6 +37,7 @@ namespace MediaBrowser.Model.Dlna public bool CopyTimestamps { get; set; } public bool EnableSubtitlesInManifest { get; set; } + public bool EnableSplittingOnNonKeyFrames { get; set; } public string[] AudioCodecs { get; set; } public int? AudioStreamIndex { get; set; } @@ -264,6 +265,7 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("EnableSubtitlesInManifest", item.EnableSubtitlesInManifest.ToString().ToLower())); list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty)); + list.Add(new NameValuePair("EnableSplittingOnNonKeyFrames", item.EnableSplittingOnNonKeyFrames.ToString().ToLower())); return list; } diff --git a/MediaBrowser.Model/Dlna/TranscodingProfile.cs b/MediaBrowser.Model/Dlna/TranscodingProfile.cs index beb83b053..eeab99678 100644 --- a/MediaBrowser.Model/Dlna/TranscodingProfile.cs +++ b/MediaBrowser.Model/Dlna/TranscodingProfile.cs @@ -38,6 +38,9 @@ namespace MediaBrowser.Model.Dlna [XmlAttribute("enableSubtitlesInManifest")] public bool EnableSubtitlesInManifest { get; set; } + [XmlAttribute("enableSplittingOnNonKeyFrames")] + public bool EnableSplittingOnNonKeyFrames { get; set; } + [XmlAttribute("maxAudioChannels")] public string MaxAudioChannels { get; set; } diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 9b23d5be4..a1638f722 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -66,10 +66,12 @@ namespace MediaBrowser.Server.Implementations.Intros var candidates = new List(); var trailerTypes = new List(); + var sourceTypes = new List(); if (config.EnableIntrosFromMoviesInLibrary) { trailerTypes.Add(TrailerType.LocalTrailer); + sourceTypes.Add(SourceType.Library); } if (IsSupporter) @@ -77,18 +79,22 @@ namespace MediaBrowser.Server.Implementations.Intros if (config.EnableIntrosFromUpcomingTrailers) { trailerTypes.Add(TrailerType.ComingSoonToTheaters); + sourceTypes.Clear(); } if (config.EnableIntrosFromUpcomingDvdMovies) { trailerTypes.Add(TrailerType.ComingSoonToDvd); + sourceTypes.Clear(); } if (config.EnableIntrosFromUpcomingStreamingMovies) { trailerTypes.Add(TrailerType.ComingSoonToStreaming); + sourceTypes.Clear(); } if (config.EnableIntrosFromSimilarMovies) { trailerTypes.Add(TrailerType.Archive); + sourceTypes.Clear(); } } @@ -102,7 +108,8 @@ namespace MediaBrowser.Server.Implementations.Intros IsPlayed = config.EnableIntrosForWatchedContent ? (bool?)null : false, MaxParentalRating = config.EnableIntrosParentalControl ? ratingLevel : null, BlockUnratedItems = config.EnableIntrosParentalControl ? new[] { UnratedItem.Trailer } : new UnratedItem[] { }, - Limit = config.TrailerLimit + Limit = config.TrailerLimit, + SourceTypes = sourceTypes.ToArray() }); candidates.AddRange(trailerResult.Select(i => new ItemWithTrailer diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 2e58c6b30..9b69b84d3 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -764,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV defaults.RecordNewOnly = !program.IsRepeat; } - defaults.SkipEpisodesInLibrary = true; + defaults.SkipEpisodesInLibrary = defaults.RecordNewOnly; defaults.KeepUntil = KeepUntil.UntilDeleted; return Task.FromResult(defaults); diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index b03feefe4..cedaf7ad8 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -114,6 +114,10 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts { protocol = MediaProtocol.Rtsp; } + else if (path.StartsWith("udp", StringComparison.OrdinalIgnoreCase)) + { + protocol = MediaProtocol.Udp; + } var mediaSource = new MediaSourceInfo { From 5af8b02013c972da980a271c8e1a6e74f1a64904 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 16 Oct 2016 13:16:45 -0400 Subject: [PATCH 09/12] 3.1.191 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index af67f7e6d..a07f3db13 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.1.*")] -[assembly: AssemblyVersion("3.1.190")] +[assembly: AssemblyVersion("3.1.191")] From eb65dd812691c44d0413473a688c565fe6eebe31 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 16 Oct 2016 20:00:13 -0400 Subject: [PATCH 10/12] fix video getting marked unplayed when watching --- .../Session/SessionManager.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index e898a6abd..9326c4f43 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -633,9 +633,12 @@ namespace MediaBrowser.Server.Implementations.Session data.PlayCount++; data.LastPlayedDate = DateTime.UtcNow; - if (!(item is Video) && item.SupportsPlayedStatus) + if (item.SupportsPlayedStatus) { - data.Played = true; + if (!(item is Video)) + { + data.Played = true; + } } else { From 438871d6f4b45cbf3ce61b93f92354996678f978 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 16 Oct 2016 20:07:51 -0400 Subject: [PATCH 11/12] 3.1.192 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index a07f3db13..697d0fa9f 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; //[assembly: AssemblyVersion("3.1.*")] -[assembly: AssemblyVersion("3.1.191")] +[assembly: AssemblyVersion("3.1.192")] From ba613d567102bd2c3ec2ce2c5f7f94dcd04f1c73 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 17 Oct 2016 12:18:12 -0400 Subject: [PATCH 12/12] disable split by time --- .../Playback/Hls/DynamicHlsService.cs | 11 ++++++---- .../Savers/BaseNfoSaver.cs | 22 +++++++------------ 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 121ab95eb..270b068fd 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -885,8 +885,13 @@ namespace MediaBrowser.Api.Playback.Hls } var mapArgs = state.IsOutputVideo ? GetMapArgs(state) : string.Empty; + var enableSplittingOnNonKeyFrames = state.VideoRequest.EnableSplittingOnNonKeyFrames && string.Equals(state.OutputVideoCodec, "copy", StringComparison.OrdinalIgnoreCase); + enableSplittingOnNonKeyFrames = false; - if (state.VideoRequest.EnableSplittingOnNonKeyFrames) + // TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time + var hlsProtocolSupportsSplittingByTime = false; + + if (enableSplittingOnNonKeyFrames && !hlsProtocolSupportsSplittingByTime) { var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state); @@ -905,9 +910,7 @@ namespace MediaBrowser.Api.Playback.Hls ).Trim(); } - // TODO: check libavformat version for 57 50.100 and use -hls_flags split_by_time - var supportsSplitByTime = false; - var splitByTime = supportsSplitByTime && state.VideoRequest.EnableSplittingOnNonKeyFrames; + var splitByTime = hlsProtocolSupportsSplittingByTime && enableSplittingOnNonKeyFrames; var splitByTimeArg = splitByTime ? " -hls_flags split_by_time" : ""; return string.Format("{0}{12} {1} -map_metadata -1 -threads {2} {3} {4}{5} {6} -max_delay 5000000 -avoid_negative_ts disabled -start_at_zero -hls_time {7}{8} -start_number {9} -hls_list_size {10} -y \"{11}\"", diff --git a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 0b071fceb..ab71f321c 100644 --- a/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -449,10 +449,9 @@ namespace MediaBrowser.XbmcMetadata.Savers writer.WriteElementString("plot", overview); } - var hasShortOverview = item as IHasShortOverview; - if (hasShortOverview != null) + if (item is Video) { - var outline = (hasShortOverview.ShortOverview ?? string.Empty) + var outline = (item.ShortOverview ?? string.Empty) .StripHtml() .Replace(""", "'"); @@ -658,19 +657,14 @@ namespace MediaBrowser.XbmcMetadata.Savers } } - var hasCriticRating = item as IHasCriticRating; - - if (hasCriticRating != null) + if (item.CriticRating.HasValue) { - if (hasCriticRating.CriticRating.HasValue) - { - writer.WriteElementString("criticrating", hasCriticRating.CriticRating.Value.ToString(UsCulture)); - } + writer.WriteElementString("criticrating", item.CriticRating.Value.ToString(UsCulture)); + } - if (!string.IsNullOrEmpty(hasCriticRating.CriticRatingSummary)) - { - writer.WriteElementString("criticratingsummary", hasCriticRating.CriticRatingSummary); - } + if (!string.IsNullOrEmpty(item.CriticRatingSummary)) + { + writer.WriteElementString("criticratingsummary", item.CriticRatingSummary); } var hasDisplayOrder = item as IHasDisplayOrder;