From 348b8c44142ce14a8395552f8d429fb9d0b24a36 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 Mar 2015 12:58:02 -0400 Subject: use server to build initial stream url's --- MediaBrowser.Model/ApiClient/IApiClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'MediaBrowser.Model/ApiClient') diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 14cdbdc9ab..19d6acf339 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -251,7 +251,7 @@ namespace MediaBrowser.Model.ApiClient /// The item identifier. /// The user identifier. /// Task<LiveMediaInfoResult>. - Task GetPlaybackInfo(string itemId, string userId); + Task GetPlaybackInfo(string itemId, string userId); /// /// Gets the users async. -- cgit v1.2.3 From d8cbd649176566dbdcc49e72d0fa2ddd4f25d536 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 27 Mar 2015 16:55:31 -0400 Subject: fix mp4 sync encoding --- .../Channels/ChannelMediaInfo.cs | 5 ++- MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs | 9 +++-- MediaBrowser.Model/ApiClient/ServerCredentials.cs | 21 +++++++--- MediaBrowser.Model/ApiClient/ServerInfo.cs | 8 +++- MediaBrowser.Model/Dlna/StreamInfoSorter.cs | 2 +- .../LiveTv/LiveTvManager.cs | 46 +++++++++++++++------- .../Sync/MediaSync.cs | 15 ++++--- MediaBrowser.Server.Mono/Native/BaseMonoApp.cs | 1 - Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- SharedVersion.cs | 4 +- 13 files changed, 82 insertions(+), 41 deletions(-) (limited to 'MediaBrowser.Model/ApiClient') diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs index 94fa1ac02f..1672b75fac 100644 --- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs +++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs @@ -38,6 +38,7 @@ namespace MediaBrowser.Controller.Channels public string Id { get; set; } public bool ReadAtNativeFramerate { get; set; } + public bool SupportsDirectPlay { get; set; } public ChannelMediaInfo() { @@ -45,6 +46,7 @@ namespace MediaBrowser.Controller.Channels // This is most common Protocol = MediaProtocol.Http; + SupportsDirectPlay = true; } public MediaSourceInfo ToMediaSource() @@ -63,7 +65,8 @@ namespace MediaBrowser.Controller.Channels Name = id, Id = id, ReadAtNativeFramerate = ReadAtNativeFramerate, - SupportsDirectStream = Protocol == MediaProtocol.File || Protocol == MediaProtocol.Http + SupportsDirectStream = Protocol == MediaProtocol.File || Protocol == MediaProtocol.Http, + SupportsDirectPlay = SupportsDirectPlay }; var bitrate = (AudioBitrate ?? 0) + (VideoBitrate ?? 0); diff --git a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs index a714b160ec..b8ed97b1fc 100644 --- a/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/VideoEncoder.cs @@ -73,10 +73,13 @@ namespace MediaBrowser.MediaEncoding.Encoder args; } - var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})", - 5.ToString(UsCulture)); + if (state.Options.Context == EncodingContext.Streaming) + { + var keyFrameArg = string.Format(" -force_key_frames expr:gte(t,n_forced*{0})", + 5.ToString(UsCulture)); - args += keyFrameArg; + args += keyFrameArg; + } var hasGraphicalSubs = state.SubtitleStream != null && !state.SubtitleStream.IsTextSubtitleStream; diff --git a/MediaBrowser.Model/ApiClient/ServerCredentials.cs b/MediaBrowser.Model/ApiClient/ServerCredentials.cs index d911f81211..6ba2a80c87 100644 --- a/MediaBrowser.Model/ApiClient/ServerCredentials.cs +++ b/MediaBrowser.Model/ApiClient/ServerCredentials.cs @@ -1,7 +1,6 @@ using MediaBrowser.Model.Extensions; using System; using System.Collections.Generic; -using System.Linq; namespace MediaBrowser.Model.ApiClient { @@ -24,7 +23,12 @@ namespace MediaBrowser.Model.ApiClient throw new ArgumentNullException("server"); } - var list = Servers.ToList(); + // Clone the existing list of servers + var list = new List(); + foreach (ServerInfo serverInfo in Servers) + { + list.Add(serverInfo); + } var index = FindIndex(list, server.Id); @@ -32,8 +36,11 @@ namespace MediaBrowser.Model.ApiClient { var existing = list[index]; - // Merge the data - existing.DateLastAccessed = new[] { existing.DateLastAccessed, server.DateLastAccessed }.Max(); + // Take the most recent DateLastAccessed + if (server.DateLastAccessed > existing.DateLastAccessed) + { + existing.DateLastAccessed = server.DateLastAccessed; + } existing.UserLinkType = server.UserLinkType; @@ -64,7 +71,11 @@ namespace MediaBrowser.Model.ApiClient } if (server.WakeOnLanInfos != null && server.WakeOnLanInfos.Count > 0) { - existing.WakeOnLanInfos = server.WakeOnLanInfos.ToList(); + existing.WakeOnLanInfos = new List(); + foreach (WakeOnLanInfo info in server.WakeOnLanInfos) + { + existing.WakeOnLanInfos.Add(info); + } } if (server.LastConnectionMode.HasValue) { diff --git a/MediaBrowser.Model/ApiClient/ServerInfo.cs b/MediaBrowser.Model/ApiClient/ServerInfo.cs index cc062f2f60..e1fa581d7b 100644 --- a/MediaBrowser.Model/ApiClient/ServerInfo.cs +++ b/MediaBrowser.Model/ApiClient/ServerInfo.cs @@ -3,7 +3,6 @@ using MediaBrowser.Model.Extensions; using MediaBrowser.Model.System; using System; using System.Collections.Generic; -using System.Linq; namespace MediaBrowser.Model.ApiClient { @@ -83,7 +82,12 @@ namespace MediaBrowser.Model.ApiClient throw new ArgumentNullException("user"); } - var list = Users.ToList(); + // Clone the existing list of users + var list = new List(); + foreach (ServerUserInfo serverUserInfo in Users) + { + list.Add(serverUserInfo); + } var index = FindIndex(list, user.Id); diff --git a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs index 87c6615480..0cccd80804 100644 --- a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs +++ b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Model.Dlna case PlayMethod.DirectPlay: return 0; default: - return 2; + return 1; } }).ThenBy(i => diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 2bc6cbadfe..59daa4921a 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -333,10 +333,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv try { MediaSourceInfo info; + var isVideo = true; if (isChannel) { var channel = GetInternalChannel(id); + isVideo = channel.ChannelType == ChannelType.TV; var service = GetService(channel); _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId); info = await service.GetChannelStream(channel.ExternalId, null, cancellationToken).ConfigureAwait(false); @@ -344,6 +346,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv else { var recording = await GetInternalRecording(id, cancellationToken).ConfigureAwait(false); + isVideo = !string.Equals(recording.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase); var service = GetService(recording); _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.RecordingInfo.Id); @@ -351,7 +354,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv } _logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info)); - Sanitize(info); + Normalize(info, isVideo); var data = new LiveStreamData { @@ -377,25 +380,40 @@ namespace MediaBrowser.Server.Implementations.LiveTv } } - private void Sanitize(MediaSourceInfo mediaSource) + private void Normalize(MediaSourceInfo mediaSource, bool isVideo) { if (mediaSource.MediaStreams.Count == 0) { - mediaSource.MediaStreams.AddRange(new List + if (isVideo) { - new MediaStream + mediaSource.MediaStreams.AddRange(new List { - Type = MediaStreamType.Video, - // Set the index to -1 because we don't know the exact index of the video stream within the container - Index = -1 - }, - new MediaStream + new MediaStream + { + Type = MediaStreamType.Video, + // Set the index to -1 because we don't know the exact index of the video stream within the container + Index = -1 + }, + new MediaStream + { + Type = MediaStreamType.Audio, + // Set the index to -1 because we don't know the exact index of the audio stream within the container + Index = -1 + } + }); + } + else + { + mediaSource.MediaStreams.AddRange(new List { - Type = MediaStreamType.Audio, - // Set the index to -1 because we don't know the exact index of the audio stream within the container - Index = -1 - } - }); + new MediaStream + { + Type = MediaStreamType.Audio, + // Set the index to -1 because we don't know the exact index of the audio stream within the container + Index = -1 + } + }); + } } // Clean some bad data coming from providers diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs index 936f1b1fe8..cac0e15546 100644 --- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs +++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs @@ -1,5 +1,4 @@ -using System.IO; -using MediaBrowser.Common.IO; +using MediaBrowser.Common.IO; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; using MediaBrowser.Controller.Sync; @@ -10,6 +9,7 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Sync; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -140,9 +140,6 @@ namespace MediaBrowser.Server.Implementations.Sync var libraryItem = jobItem.Item; var internalSyncJobItem = _syncManager.GetJobItem(jobItem.SyncJobItemId); - var fileTransferProgress = new ActionableProgress(); - fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92)); - var localItem = CreateLocalItem(provider, jobItem, target, libraryItem, serverId, jobItem.OriginalFileName); await _syncManager.ReportSyncJobItemTransferBeginning(internalSyncJobItem.Id); @@ -152,6 +149,9 @@ namespace MediaBrowser.Server.Implementations.Sync try { + var fileTransferProgress = new ActionableProgress(); + fileTransferProgress.RegisterAction(pct => progress.Report(pct * .92)); + var sendFileResult = await SendFile(provider, internalSyncJobItem.OutputPath, localItem.LocalPath, target, fileTransferProgress, cancellationToken).ConfigureAwait(false); if (localItem.Item.MediaSources != null) @@ -342,7 +342,10 @@ namespace MediaBrowser.Server.Implementations.Sync private string GetSyncJobFolderName(SyncedItem syncedItem, IServerSyncProvider provider) { - var name = syncedItem.SyncJobName + syncedItem.SyncJobDateCreated.ToLocalTime().ToString("g"); + var name = syncedItem.SyncJobName + "-" + syncedItem.SyncJobDateCreated + .ToLocalTime() + .ToString("g") + .Replace(" ", "-"); name = GetValidFilename(provider, name); diff --git a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs index 1ec0109ad8..aea6d73679 100644 --- a/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs +++ b/MediaBrowser.Server.Mono/Native/BaseMonoApp.cs @@ -139,7 +139,6 @@ namespace MediaBrowser.Server.Mono.Native } else if (string.Equals(sysName, "BSD", StringComparison.OrdinalIgnoreCase)) { - // TODO: How to detect BSD? info.OperatingSystem = Startup.Common.OperatingSystem.Bsd; } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index d229302bde..dccef68ed4 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.599 + 3.0.600 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 65205fa250..b35ce68d6d 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.599 + 3.0.600 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index 2e829b436a..ea45fdfe19 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.599 + 3.0.600 MediaBrowser.Model - Signed Edition Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index f5d5b788bb..6fc7e46393 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.599 + 3.0.600 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + diff --git a/SharedVersion.cs b/SharedVersion.cs index fa4ca1ac7e..621b97a63d 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("3.0.*")] -//[assembly: AssemblyVersion("3.0.5557.20000")] +//[assembly: AssemblyVersion("3.0.*")] +[assembly: AssemblyVersion("3.0.5557.30000")] -- cgit v1.2.3 From a79962b7ebfe59d837970581ac1b5f184b0aa42d Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 12:45:16 -0400 Subject: update live stream generation --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 9 ++-- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 4 +- MediaBrowser.Api/Playback/MediaInfoService.cs | 45 ++++++++++++----- .../Library/IMediaSourceManager.cs | 5 +- .../MediaBrowser.Model.Portable.csproj | 6 +++ .../MediaBrowser.Model.net35.csproj | 6 +++ MediaBrowser.Model/ApiClient/IConnectionManager.cs | 6 +++ MediaBrowser.Model/MediaBrowser.Model.csproj | 2 + MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs | 16 ++++++ MediaBrowser.Model/MediaInfo/LiveStreamResponse.cs | 9 ++++ .../Library/MediaSourceManager.cs | 27 ++++++---- .../Session/SessionManager.cs | 57 ++++++++++++++-------- .../ApplicationHost.cs | 2 +- 13 files changed, 145 insertions(+), 49 deletions(-) create mode 100644 MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs create mode 100644 MediaBrowser.Model/MediaInfo/LiveStreamResponse.cs (limited to 'MediaBrowser.Model/ApiClient') diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 2e7c9a5a7b..5a4cdaaa93 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -936,10 +936,13 @@ namespace MediaBrowser.Api.Playback if (state.MediaSource.RequiresOpening) { - var mediaSource = await MediaSourceManager.OpenLiveStream(state.MediaSource.OpenToken, false, cancellationTokenSource.Token) - .ConfigureAwait(false); + var liveStreamResponse = await MediaSourceManager.OpenLiveStream(new LiveStreamRequest + { + OpenToken = state.MediaSource.OpenToken + + }, false, cancellationTokenSource.Token).ConfigureAwait(false); - AttachMediaSourceInfo(state, mediaSource, state.VideoRequest, state.RequestedUrl); + AttachMediaSourceInfo(state, liveStreamResponse.MediaSource, state.VideoRequest, state.RequestedUrl); if (state.VideoRequest != null) { diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index b166bc319f..4f7c0444b2 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -698,7 +698,7 @@ namespace MediaBrowser.Api.Playback.Hls { var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d.ts"; - return string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -copyts -flags -global_header {5} -f segment -segment_time {6} -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", + return string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -copyts -flags -global_header -sc_threshold 0 {5} -f segment -segment_time {6} -segment_start_number {7} -segment_list \"{8}\" -y \"{9}\"", inputModifier, GetInputArgument(state), threads, @@ -712,7 +712,7 @@ namespace MediaBrowser.Api.Playback.Hls ).Trim(); } - return string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -copyts -flags -global_header {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"", + return string.Format("{0} {1} -map_metadata -1 -threads {2} {3} {4} -copyts -flags -global_header -sc_threshold 0 {5} -hls_time {6} -start_number {7} -hls_list_size {8} -y \"{9}\"", inputModifier, GetInputArgument(state), threads, diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index d954c5b197..6f8c2cc505 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -61,14 +61,12 @@ namespace MediaBrowser.Api.Playback public string MediaSourceId { get; set; } } - [Route("/MediaSources/Open", "POST", Summary = "Opens a media source")] - public class OpenMediaSource : IReturn + [Route("/LiveStreams/Open", "POST", Summary = "Opens a media source")] + public class OpenMediaSource : LiveStreamRequest, IReturn { - [ApiMember(Name = "OpenToken", Description = "OpenToken", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string OpenToken { get; set; } } - [Route("/MediaSources/Close", "POST", Summary = "Closes a media source")] + [Route("/LiveStreams/Close", "POST", Summary = "Closes a media source")] public class CloseMediaSource : IReturnVoid { [ApiMember(Name = "LiveStreamId", Description = "LiveStreamId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] @@ -103,7 +101,32 @@ namespace MediaBrowser.Api.Playback public async Task Post(OpenMediaSource request) { - var result = await _mediaSourceManager.OpenLiveStream(request.OpenToken, false, CancellationToken.None).ConfigureAwait(false); + var authInfo = AuthorizationContext.GetAuthorizationInfo(Request); + + var result = await _mediaSourceManager.OpenLiveStream(request, false, CancellationToken.None).ConfigureAwait(false); + + var profile = request.DeviceProfile; + if (profile == null) + { + var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); + if (caps != null) + { + profile = caps.DeviceProfile; + } + } + + if (profile != null) + { + var item = _libraryManager.GetItemById(request.ItemId); + + SetDeviceSpecificData(item, result.MediaSource, profile, authInfo, request.MaxStreamingBitrate, request.StartTimeTicks ?? 0, result.MediaSource.Id, request.AudioStreamIndex, request.SubtitleStreamIndex); + } + + if (!string.IsNullOrWhiteSpace(result.MediaSource.TranscodingUrl)) + { + result.MediaSource.TranscodingUrl += "&LiveStreamId=" + result.MediaSource.LiveStreamId; + } + return ToOptimizedResult(result); } @@ -177,11 +200,11 @@ namespace MediaBrowser.Api.Playback return result; } - private void SetDeviceSpecificData(string itemId, - PlaybackInfoResponse result, - DeviceProfile profile, - AuthorizationInfo auth, - int? maxBitrate, + private void SetDeviceSpecificData(string itemId, + PlaybackInfoResponse result, + DeviceProfile profile, + AuthorizationInfo auth, + int? maxBitrate, long startTimeTicks, string mediaSourceId, int? audioStreamIndex, diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 292205c033..9cbbabc8db 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; using System.Threading; @@ -84,11 +85,11 @@ namespace MediaBrowser.Controller.Library /// /// Opens the media source. /// - /// The open token. + /// The request. /// if set to true [enable automatic close]. /// The cancellation token. /// Task<MediaSourceInfo>. - Task OpenLiveStream(string openToken, bool enableAutoClose, CancellationToken cancellationToken); + Task OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken); /// /// Gets the live stream. diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index ab77dc271b..fdedc51a21 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -803,6 +803,12 @@ MediaInfo\IBlurayExaminer.cs + + MediaInfo\LiveStreamRequest.cs + + + MediaInfo\LiveStreamResponse.cs + MediaInfo\MediaProtocol.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index b772e17539..3618aa9728 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -759,6 +759,12 @@ MediaInfo\IBlurayExaminer.cs + + MediaInfo\LiveStreamRequest.cs + + + MediaInfo\LiveStreamResponse.cs + MediaInfo\MediaProtocol.cs diff --git a/MediaBrowser.Model/ApiClient/IConnectionManager.cs b/MediaBrowser.Model/ApiClient/IConnectionManager.cs index 84a815dfc0..f8837f15de 100644 --- a/MediaBrowser.Model/ApiClient/IConnectionManager.cs +++ b/MediaBrowser.Model/ApiClient/IConnectionManager.cs @@ -172,5 +172,11 @@ namespace MediaBrowser.Model.ApiClient /// if set to true [remember credentials]. /// Task. Task AuthenticateOffline(UserDto user, string password, bool rememberCredentials); + + /// + /// Gets the offline users. + /// + /// Task<List<UserDto>>. + Task> GetOfflineUsers(); } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index fe67038df9..0673095125 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -141,6 +141,8 @@ + + diff --git a/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs new file mode 100644 index 0000000000..8078219d82 --- /dev/null +++ b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs @@ -0,0 +1,16 @@ +using MediaBrowser.Model.Dlna; + +namespace MediaBrowser.Model.MediaInfo +{ + public class LiveStreamRequest + { + public string OpenToken { get; set; } + public string UserId { get; set; } + public int? MaxStreamingBitrate { get; set; } + public long? StartTimeTicks { get; set; } + public int? AudioStreamIndex { get; set; } + public int? SubtitleStreamIndex { get; set; } + public string ItemId { get; set; } + public DeviceProfile DeviceProfile { get; set; } + } +} diff --git a/MediaBrowser.Model/MediaInfo/LiveStreamResponse.cs b/MediaBrowser.Model/MediaInfo/LiveStreamResponse.cs new file mode 100644 index 0000000000..e79e37a717 --- /dev/null +++ b/MediaBrowser.Model/MediaInfo/LiveStreamResponse.cs @@ -0,0 +1,9 @@ +using MediaBrowser.Model.Dto; + +namespace MediaBrowser.Model.MediaInfo +{ + public class LiveStreamResponse + { + public MediaSourceInfo MediaSource { get; set; } + } +} diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 3dbcf4aad4..64b1f2c89a 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -1,5 +1,4 @@ -using System.Collections.Concurrent; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; @@ -8,13 +7,14 @@ using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Serialization; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Server.Implementations.LiveTv; namespace MediaBrowser.Server.Implementations.Library { @@ -23,16 +23,18 @@ namespace MediaBrowser.Server.Implementations.Library private readonly IItemRepository _itemRepo; private readonly IUserManager _userManager; private readonly ILibraryManager _libraryManager; + private readonly IJsonSerializer _jsonSerializer; private IMediaSourceProvider[] _providers; private readonly ILogger _logger; - public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, ILogger logger) + public MediaSourceManager(IItemRepository itemRepo, IUserManager userManager, ILibraryManager libraryManager, ILogger logger, IJsonSerializer jsonSerializer) { _itemRepo = itemRepo; _userManager = userManager; _libraryManager = libraryManager; _logger = logger; + _jsonSerializer = jsonSerializer; } public void AddParts(IEnumerable providers) @@ -317,13 +319,13 @@ namespace MediaBrowser.Server.Implementations.Library private readonly ConcurrentDictionary _openStreams = new ConcurrentDictionary(); private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); - public async Task OpenLiveStream(string openToken, bool enableAutoClose, CancellationToken cancellationToken) + public async Task OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken) { await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { - var tuple = GetProvider(openToken); + var tuple = GetProvider(request.OpenToken); var provider = tuple.Item1; var mediaSource = await provider.OpenMediaSource(tuple.Item2, cancellationToken).ConfigureAwait(false); @@ -344,12 +346,19 @@ namespace MediaBrowser.Server.Implementations.Library StartCloseTimer(); } - if (!string.IsNullOrWhiteSpace(mediaSource.TranscodingUrl)) + var json = _jsonSerializer.SerializeToString(mediaSource); + var clone = _jsonSerializer.DeserializeFromString(json); + + if (!string.IsNullOrWhiteSpace(request.UserId)) { - mediaSource.TranscodingUrl += "&LiveStreamId=" + mediaSource.LiveStreamId; + var user = _userManager.GetUserById(request.UserId); + SetUserProperties(clone, user); } - return mediaSource; + return new LiveStreamResponse + { + MediaSource = clone + }; } finally { diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index ec93ae8766..16fc420639 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -14,6 +14,7 @@ using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Devices; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; using MediaBrowser.Model.Library; @@ -304,13 +305,21 @@ namespace MediaBrowser.Server.Implementations.Session } } + private async Task GetMediaSource(BaseItem item, string mediaSourceId) + { + var sources = await _mediaSourceManager.GetPlayackMediaSources(item.Id.ToString("N"), false, CancellationToken.None) + .ConfigureAwait(false); + + return sources.FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); + } + /// /// Updates the now playing item id. /// /// The session. /// The information. /// The library item. - private void UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInfo info, BaseItem libraryItem) + private async Task UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInfo info, BaseItem libraryItem) { if (string.IsNullOrWhiteSpace(info.MediaSourceId)) { @@ -319,29 +328,27 @@ namespace MediaBrowser.Server.Implementations.Session if (!string.IsNullOrWhiteSpace(info.ItemId) && info.Item == null && libraryItem != null) { - var runtimeTicks = libraryItem.RunTimeTicks; + var current = session.NowPlayingItem; - if (!string.Equals(info.ItemId, info.MediaSourceId) && - !string.IsNullOrWhiteSpace(info.MediaSourceId)) + if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase)) { - var runtimeItem = _libraryManager.GetItemById(new Guid(info.MediaSourceId)) ?? - _libraryManager.GetItemById(info.ItemId); + var runtimeTicks = libraryItem.RunTimeTicks; - runtimeTicks = runtimeItem.RunTimeTicks; - } + var mediaSource = await GetMediaSource(libraryItem, info.MediaSourceId).ConfigureAwait(false); - var current = session.NowPlayingItem; + if (mediaSource != null) + { + runtimeTicks = mediaSource.RunTimeTicks; + } - if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase)) - { - info.Item = GetItemInfo(libraryItem, libraryItem, info.MediaSourceId); + info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource); + + info.Item.RunTimeTicks = runtimeTicks; } else { info.Item = current; } - - info.Item.RunTimeTicks = runtimeTicks; } session.NowPlayingItem = info.Item; @@ -432,6 +439,12 @@ namespace MediaBrowser.Server.Implementations.Session device = device ?? _deviceManager.GetDevice(deviceId); + if (device == null) + { + var userIdString = userId.HasValue ? userId.Value.ToString("N") : null; + device = await _deviceManager.RegisterDevice(deviceId, deviceName, appName, appVersion, userIdString).ConfigureAwait(false); + } + if (device != null) { if (!string.IsNullOrEmpty(device.CustomName)) @@ -570,7 +583,7 @@ namespace MediaBrowser.Server.Implementations.Session ? null : _libraryManager.GetItemById(new Guid(info.ItemId)); - UpdateNowPlayingItem(session, info, libraryItem); + await UpdateNowPlayingItem(session, info, libraryItem).ConfigureAwait(false); if (!string.IsNullOrEmpty(session.DeviceId) && info.PlayMethod != PlayMethod.Transcode) { @@ -652,7 +665,7 @@ namespace MediaBrowser.Server.Implementations.Session ? null : _libraryManager.GetItemById(new Guid(info.ItemId)); - UpdateNowPlayingItem(session, info, libraryItem); + await UpdateNowPlayingItem(session, info, libraryItem).ConfigureAwait(false); var users = GetUsers(session); @@ -731,7 +744,9 @@ namespace MediaBrowser.Server.Implementations.Session if (current == null || !string.Equals(current.Id, info.ItemId, StringComparison.OrdinalIgnoreCase)) { - info.Item = GetItemInfo(libraryItem, libraryItem, info.MediaSourceId); + var mediaSource = await GetMediaSource(libraryItem, info.MediaSourceId).ConfigureAwait(false); + + info.Item = GetItemInfo(libraryItem, libraryItem, mediaSource); } else { @@ -1439,10 +1454,10 @@ namespace MediaBrowser.Server.Implementations.Session /// /// The item. /// The chapter owner. - /// The media source identifier. + /// The media source. /// BaseItemInfo. /// item - private BaseItemInfo GetItemInfo(BaseItem item, BaseItem chapterOwner, string mediaSourceId) + private BaseItemInfo GetItemInfo(BaseItem item, BaseItem chapterOwner, MediaSourceInfo mediaSource) { if (item == null) { @@ -1593,9 +1608,9 @@ namespace MediaBrowser.Server.Implementations.Session info.Chapters = _dtoService.GetChapterInfoDtos(chapterOwner).ToList(); } - if (!string.IsNullOrWhiteSpace(mediaSourceId)) + if (mediaSource != null) { - info.MediaStreams = _mediaSourceManager.GetMediaStreams(mediaSourceId).ToList(); + info.MediaStreams = mediaSource.MediaStreams; } return info; diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs index 039c5edf38..aad88d022f 100644 --- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs +++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs @@ -472,7 +472,7 @@ namespace MediaBrowser.Server.Startup.Common ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LogManager.GetLogger("ChannelManager"), ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager, HttpClient); RegisterSingleInstance(ChannelManager); - MediaSourceManager = new MediaSourceManager(ItemRepository, UserManager, LibraryManager, LogManager.GetLogger("MediaSourceManager")); + MediaSourceManager = new MediaSourceManager(ItemRepository, UserManager, LibraryManager, LogManager.GetLogger("MediaSourceManager"), JsonSerializer); RegisterSingleInstance(MediaSourceManager); SessionManager = new SessionManager(UserDataManager, LogManager.GetLogger("SessionManager"), UserRepository, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager); -- cgit v1.2.3 From dd8dd1938a990d9c4c9bac384665dc9d82c4bc35 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 29 Mar 2015 14:16:40 -0400 Subject: update live stream generation --- MediaBrowser.Api/ApiEntryPoint.cs | 2 +- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 ++++ MediaBrowser.Controller/LiveTv/LiveTvChannel.cs | 9 ++++++++ MediaBrowser.Model/ApiClient/IApiClient.cs | 7 +++++++ MediaBrowser.Model/Dlna/StreamInfo.cs | 3 +++ MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs | 19 +++++++++++++++++ MediaBrowser.Model/Session/PlaybackProgressInfo.cs | 5 +++++ MediaBrowser.Model/Session/PlaybackStopInfo.cs | 5 +++++ .../LiveTv/LiveTvManager.cs | 12 +++++++++-- .../Session/SessionManager.cs | 24 ++++++++++++++++++++++ Nuget/MediaBrowser.Common.Internal.nuspec | 4 ++-- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 ++-- 14 files changed, 93 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Model/ApiClient') diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index a6958b95d3..9f4ad58937 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -187,7 +187,7 @@ namespace MediaBrowser.Api if (!string.IsNullOrWhiteSpace(deviceId)) { - var audioCodec = state.ActualOutputVideoCodec; + var audioCodec = state.ActualOutputAudioCodec; var videoCodec = state.ActualOutputVideoCodec; _sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 5a4cdaaa93..34c5e5f7c8 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1513,6 +1513,10 @@ namespace MediaBrowser.Api.Playback { request.StreamId = val; } + else if (i == 22) + { + request.LiveStreamId = val; + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 1e13d8f3f4..cb10003ed8 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -82,6 +82,15 @@ namespace MediaBrowser.Controller.LiveTv /// null if [has image] contains no value, true if [has image]; otherwise, false. public bool? HasProviderImage { get; set; } + public override LocationType LocationType + { + get + { + // TODO: This should be removed + return LocationType.Remote; + } + } + protected override string CreateSortName() { double number = 0; diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 19d6acf339..58af016150 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -1486,5 +1486,12 @@ namespace MediaBrowser.Model.ApiClient /// The query. /// Task<List<RecommendationDto>>. Task> GetMovieRecommendations(MovieRecommendationQuery query); + /// + /// Opens the live stream. + /// + /// The request. + /// The cancellation token. + /// Task<LiveStreamResponse>. + Task OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index 60615d1da9..dc24627960 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -210,6 +210,9 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("StreamId", streamId ?? string.Empty)); list.Add(new NameValuePair("api_key", accessToken ?? string.Empty)); + string liveStreamId = item.MediaSource == null ? null : item.MediaSource.LiveStreamId; + list.Add(new NameValuePair("LiveStreamId", liveStreamId ?? string.Empty)); + return list; } diff --git a/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs index 8078219d82..563006a4df 100644 --- a/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs +++ b/MediaBrowser.Model/MediaInfo/LiveStreamRequest.cs @@ -12,5 +12,24 @@ namespace MediaBrowser.Model.MediaInfo public int? SubtitleStreamIndex { get; set; } public string ItemId { get; set; } public DeviceProfile DeviceProfile { get; set; } + + public LiveStreamRequest() + { + + } + + public LiveStreamRequest(AudioOptions options) + { + MaxStreamingBitrate = options.MaxBitrate; + ItemId = options.ItemId; + DeviceProfile = options.Profile; + + VideoOptions videoOptions = options as VideoOptions; + if (videoOptions != null) + { + AudioStreamIndex = videoOptions.AudioStreamIndex; + SubtitleStreamIndex = videoOptions.SubtitleStreamIndex; + } + } } } diff --git a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs index f04dea1eac..a029df4a93 100644 --- a/MediaBrowser.Model/Session/PlaybackProgressInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackProgressInfo.cs @@ -78,5 +78,10 @@ namespace MediaBrowser.Model.Session /// /// The play method. public PlayMethod PlayMethod { get; set; } + /// + /// Gets or sets the live stream identifier. + /// + /// The live stream identifier. + public string LiveStreamId { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Model/Session/PlaybackStopInfo.cs b/MediaBrowser.Model/Session/PlaybackStopInfo.cs index 38025f1832..a3bdc9a960 100644 --- a/MediaBrowser.Model/Session/PlaybackStopInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackStopInfo.cs @@ -36,5 +36,10 @@ namespace MediaBrowser.Model.Session /// /// The position ticks. public long? PositionTicks { get; set; } + /// + /// Gets or sets the live stream identifier. + /// + /// The live stream identifier. + public string LiveStreamId { get; set; } } } \ No newline at end of file diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index 86b31e0e5d..b30db60927 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -356,7 +356,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId); info = await service.GetChannelStream(channel.ExternalId, null, cancellationToken).ConfigureAwait(false); info.RequiresClosing = true; - info.LiveStreamId = info.Id; + + if (info.RequiresClosing) + { + info.LiveStreamId = info.Id; + } } else { @@ -367,7 +371,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.RecordingInfo.Id); info = await service.GetRecordingStream(recording.RecordingInfo.Id, null, cancellationToken).ConfigureAwait(false); info.RequiresClosing = true; - info.LiveStreamId = info.Id; + + if (info.RequiresClosing) + { + info.LiveStreamId = info.Id; + } } _logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info)); diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 16fc420639..cc5aef54aa 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -679,6 +679,18 @@ namespace MediaBrowser.Server.Implementations.Session } } + if (!string.IsNullOrWhiteSpace(info.LiveStreamId)) + { + try + { + await _mediaSourceManager.PingLiveStream(info.LiveStreamId, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error closing live stream", ex); + } + } + EventHelper.FireEventIfNotNull(PlaybackProgress, this, new PlaybackProgressEventArgs { Item = libraryItem, @@ -769,6 +781,18 @@ namespace MediaBrowser.Server.Implementations.Session } } + if (!string.IsNullOrWhiteSpace(info.LiveStreamId)) + { + try + { + await _mediaSourceManager.CloseLiveStream(info.LiveStreamId, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error closing live stream", ex); + } + } + EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackStopEventArgs { Item = libraryItem, diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index e1659bfb28..ee3bdd2b6b 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.603 + 3.0.606 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 294bc519eb..a8f3ea1f38 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.603 + 3.0.606 MediaBrowser.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index bcbd1d5bea..7bd4a090dd 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.603 + 3.0.606 MediaBrowser.Model - Signed Edition Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index ee3925db5b..3f39ace9dd 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.603 + 3.0.606 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 - + -- cgit v1.2.3 From 5965afecde2536c0a2ec566fd6afdb21add8aa50 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 31 Mar 2015 14:50:08 -0400 Subject: live tv fix --- MediaBrowser.Api/Playback/MediaInfoService.cs | 23 ------ MediaBrowser.Api/Playback/TranscodingThrottler.cs | 2 +- .../HttpClientManager/HttpClientManager.cs | 32 +++++--- MediaBrowser.Controller/LiveTv/LiveTvProgram.cs | 6 ++ MediaBrowser.Controller/Sync/ISyncDataProvider.cs | 16 ++++ MediaBrowser.Model/ApiClient/IApiClient.cs | 5 +- .../MediaInfo/PlaybackInfoRequest.cs | 16 ++++ MediaBrowser.Model/Sync/LocalItem.cs | 5 ++ MediaBrowser.Model/Sync/SyncDataRequest.cs | 1 + .../Channels/ChannelImageProvider.cs | 1 - .../Library/MediaSourceManager.cs | 10 +-- .../LiveTv/LiveTvDtoService.cs | 2 +- .../LiveTv/LiveTvManager.cs | 6 +- .../Sync/MediaSync.cs | 11 +-- .../Sync/SyncManager.cs | 95 +++++++++++++++++++++- .../Sync/TargetDataProvider.cs | 30 ++++++- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Model.Signed.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 20 files changed, 207 insertions(+), 66 deletions(-) (limited to 'MediaBrowser.Model/ApiClient') diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 0930c00024..ca735f0684 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -39,29 +39,6 @@ namespace MediaBrowser.Api.Playback [Route("/Items/{Id}/PlaybackInfo", "POST", Summary = "Gets live playback media info for an item")] public class GetPostedPlaybackInfo : PlaybackInfoRequest, IReturn { - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string Id { get; set; } - - [ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] - public string UserId { get; set; } - - [ApiMember(Name = "MaxStreamingBitrate", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")] - public int? MaxStreamingBitrate { get; set; } - - [ApiMember(Name = "StartTimeTicks", Description = "Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")] - public long? StartTimeTicks { get; set; } - - [ApiMember(Name = "AudioStreamIndex", Description = "Optional. The index of the audio stream to use. If omitted the first audio stream will be used.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")] - public int? AudioStreamIndex { get; set; } - - [ApiMember(Name = "SubtitleStreamIndex", Description = "Optional. The index of the subtitle stream to use. If omitted no subtitles will be used.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")] - public int? SubtitleStreamIndex { get; set; } - - [ApiMember(Name = "MediaSourceId", Description = "The media version id, if playing an alternate version", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string MediaSourceId { get; set; } - - [ApiMember(Name = "LiveStreamId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")] - public string LiveStreamId { get; set; } } [Route("/LiveStreams/Open", "POST", Summary = "Opens a media source")] diff --git a/MediaBrowser.Api/Playback/TranscodingThrottler.cs b/MediaBrowser.Api/Playback/TranscodingThrottler.cs index ff79bb48f4..58cfa086e3 100644 --- a/MediaBrowser.Api/Playback/TranscodingThrottler.cs +++ b/MediaBrowser.Api/Playback/TranscodingThrottler.cs @@ -42,7 +42,7 @@ namespace MediaBrowser.Api.Playback var options = GetOptions(); - if (/*options.EnableThrottling &&*/ IsThrottleAllowed(_job, options.ThrottleThresholdSeconds)) + if (options.EnableThrottling && IsThrottleAllowed(_job, options.ThrottleThresholdSeconds)) { PauseTranscoding(); } diff --git a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs index b925649fce..94c91c55aa 100644 --- a/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs +++ b/MediaBrowser.Common.Implementations/HttpClientManager/HttpClientManager.cs @@ -107,30 +107,40 @@ namespace MediaBrowser.Common.Implementations.HttpClientManager private WebRequest GetRequest(HttpRequestOptions options, string method, bool enableHttpCompression) { - var request = (HttpWebRequest)WebRequest.Create(options.Url); + var request = WebRequest.Create(options.Url); + var httpWebRequest = request as HttpWebRequest; - AddRequestHeaders(request, options); + if (httpWebRequest != null) + { + AddRequestHeaders(httpWebRequest, options); - request.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None; + httpWebRequest.AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None; + } request.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache); - if (options.EnableKeepAlive) + if (httpWebRequest != null) { - request.KeepAlive = true; + if (options.EnableKeepAlive) + { + httpWebRequest.KeepAlive = true; + } } request.Method = method; request.Timeout = options.TimeoutMs; - if (!string.IsNullOrEmpty(options.Host)) + if (httpWebRequest != null) { - request.Host = options.Host; - } + if (!string.IsNullOrEmpty(options.Host)) + { + httpWebRequest.Host = options.Host; + } - if (!string.IsNullOrEmpty(options.Referer)) - { - request.Referer = options.Referer; + if (!string.IsNullOrEmpty(options.Referer)) + { + httpWebRequest.Referer = options.Referer; + } } //request.ServicePoint.BindIPEndPointDelegate = BindIPEndPointCallback; diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 0b07d8b6d1..0609df4c6b 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -34,6 +34,12 @@ namespace MediaBrowser.Controller.LiveTv /// The channel identifier. public string ExternalChannelId { get; set; } + /// + /// Gets or sets the original air date. + /// + /// The original air date. + public DateTime? OriginalAirDate { get; set; } + /// /// Gets or sets the type of the channel. /// diff --git a/MediaBrowser.Controller/Sync/ISyncDataProvider.cs b/MediaBrowser.Controller/Sync/ISyncDataProvider.cs index f84748b971..04101fd465 100644 --- a/MediaBrowser.Controller/Sync/ISyncDataProvider.cs +++ b/MediaBrowser.Controller/Sync/ISyncDataProvider.cs @@ -14,6 +14,14 @@ namespace MediaBrowser.Controller.Sync /// Task<List<System.String>>. Task> GetServerItemIds(SyncTarget target, string serverId); + /// + /// Gets the synchronize job item ids. + /// + /// The target. + /// The server identifier. + /// Task<List<System.String>>. + Task> GetSyncJobItemIds(SyncTarget target, string serverId); + /// /// Adds the or update. /// @@ -46,5 +54,13 @@ namespace MediaBrowser.Controller.Sync /// The item identifier. /// Task<LocalItem>. Task> GetCachedItems(SyncTarget target, string serverId, string itemId); + /// + /// Gets the cached items by synchronize job item identifier. + /// + /// The target. + /// The server identifier. + /// The synchronize job item identifier. + /// Task<List<LocalItem>>. + Task> GetCachedItemsBySyncJobItemId(SyncTarget target, string serverId, string syncJobItemId); } } diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 58af016150..9675de38b0 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -248,10 +248,9 @@ namespace MediaBrowser.Model.ApiClient /// /// Gets the playback information. /// - /// The item identifier. - /// The user identifier. + /// The request. /// Task<LiveMediaInfoResult>. - Task GetPlaybackInfo(string itemId, string userId); + Task GetPlaybackInfo(PlaybackInfoRequest request); /// /// Gets the users async. diff --git a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs index ffd4995ad9..124739073a 100644 --- a/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs +++ b/MediaBrowser.Model/MediaInfo/PlaybackInfoRequest.cs @@ -4,6 +4,22 @@ namespace MediaBrowser.Model.MediaInfo { public class PlaybackInfoRequest { + public string Id { get; set; } + + public string UserId { get; set; } + + public int? MaxStreamingBitrate { get; set; } + + public long? StartTimeTicks { get; set; } + + public int? AudioStreamIndex { get; set; } + + public int? SubtitleStreamIndex { get; set; } + + public string MediaSourceId { get; set; } + + public string LiveStreamId { get; set; } + public DeviceProfile DeviceProfile { get; set; } } } diff --git a/MediaBrowser.Model/Sync/LocalItem.cs b/MediaBrowser.Model/Sync/LocalItem.cs index 37f605a590..dbbecaf057 100644 --- a/MediaBrowser.Model/Sync/LocalItem.cs +++ b/MediaBrowser.Model/Sync/LocalItem.cs @@ -31,6 +31,11 @@ namespace MediaBrowser.Model.Sync /// The item identifier. public string ItemId { get; set; } /// + /// Gets or sets the synchronize job item identifier. + /// + /// The synchronize job item identifier. + public string SyncJobItemId { get; set; } + /// /// Gets or sets the user ids with access. /// /// The user ids with access. diff --git a/MediaBrowser.Model/Sync/SyncDataRequest.cs b/MediaBrowser.Model/Sync/SyncDataRequest.cs index dc33239a04..0df4de86d1 100644 --- a/MediaBrowser.Model/Sync/SyncDataRequest.cs +++ b/MediaBrowser.Model/Sync/SyncDataRequest.cs @@ -6,6 +6,7 @@ namespace MediaBrowser.Model.Sync { public List LocalItemIds { get; set; } public List OfflineUserIds { get; set; } + public List SyncJobItemIds { get; set; } public string TargetId { get; set; } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs b/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs index 5c033e6bdc..f13c71c6df 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelImageProvider.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using System; using System.Collections.Generic; using System.Linq; using System.Threading; diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs index 66eeb61f72..4fab95263f 100644 --- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs @@ -129,6 +129,11 @@ namespace MediaBrowser.Server.Implementations.Library return list; } + public Task> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken) + { + return GetPlayackMediaSources(id, null, enablePathSubstitution, cancellationToken); + } + public async Task> GetPlayackMediaSources(string id, string userId, bool enablePathSubstitution, CancellationToken cancellationToken) { var item = _libraryManager.GetItemById(id); @@ -225,11 +230,6 @@ namespace MediaBrowser.Server.Implementations.Library } } - public Task> GetPlayackMediaSources(string id, bool enablePathSubstitution, CancellationToken cancellationToken) - { - return GetPlayackMediaSources(id, null, enablePathSubstitution, cancellationToken); - } - public MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution) { return GetStaticMediaSources(item, enablePathSubstitution).FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase)); diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs index 7f4440fbce..401cf87657 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -373,7 +373,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv StartDate = item.StartDate, OfficialRating = item.OfficialRating, IsHD = item.IsHD, - OriginalAirDate = item.PremiereDate, + OriginalAirDate = item.OriginalAirDate, Audio = item.Audio, CommunityRating = GetClientCommunityRating(item.CommunityRating), IsRepeat = item.IsRepeat, diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs index f676918593..a39781d6a3 100644 --- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs @@ -589,13 +589,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv item.Name = info.Name; item.OfficialRating = info.OfficialRating; item.Overview = info.Overview; - item.PremiereDate = info.OriginalAirDate; + item.OriginalAirDate = info.OriginalAirDate; item.ProviderImagePath = info.ImagePath; item.ProviderImageUrl = info.ImageUrl; item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks; item.StartDate = info.StartDate; - item.ProductionYear = info.ProductionYear; + item.ProductionYear = info.ProductionYear; + item.PremiereDate = item.PremiereDate ?? info.OriginalAirDate; + await item.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); return item; diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs index e7333939e3..5bc8b80887 100644 --- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs +++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs @@ -67,12 +67,12 @@ namespace MediaBrowser.Server.Implementations.Sync SyncTarget target, CancellationToken cancellationToken) { - var localIds = await dataProvider.GetServerItemIds(target, serverId).ConfigureAwait(false); + var jobItemIds = await dataProvider.GetSyncJobItemIds(target, serverId).ConfigureAwait(false); var result = await _syncManager.SyncData(new SyncDataRequest { TargetId = target.Id, - LocalItemIds = localIds + SyncJobItemIds = jobItemIds }).ConfigureAwait(false); @@ -285,11 +285,11 @@ namespace MediaBrowser.Server.Implementations.Sync private async Task RemoveItem(IServerSyncProvider provider, ISyncDataProvider dataProvider, string serverId, - string itemId, + string syncJobItemId, SyncTarget target, CancellationToken cancellationToken) { - var localItems = await dataProvider.GetCachedItems(target, serverId, itemId); + var localItems = await dataProvider.GetCachedItemsBySyncJobItemId(target, serverId, syncJobItemId); foreach (var localItem in localItems) { @@ -350,7 +350,8 @@ namespace MediaBrowser.Server.Implementations.Sync ItemId = libraryItem.Id, ServerId = serverId, LocalPath = localPath, - Id = GetLocalId(syncedItem.SyncJobItemId, libraryItem.Id) + Id = GetLocalId(syncedItem.SyncJobItemId, libraryItem.Id), + SyncJobItemId = syncedItem.SyncJobItemId }; } diff --git a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs index 3acc79088d..102218979c 100644 --- a/MediaBrowser.Server.Implementations/Sync/SyncManager.cs +++ b/MediaBrowser.Server.Implementations/Sync/SyncManager.cs @@ -3,6 +3,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; +using MediaBrowser.Controller; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; @@ -42,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly ILogger _logger; private readonly IUserManager _userManager; private readonly Func _dtoService; - private readonly IApplicationHost _appHost; + private readonly IServerApplicationHost _appHost; private readonly ITVSeriesManager _tvSeriesManager; private readonly Func _mediaEncoder; private readonly IFileSystem _fileSystem; @@ -60,7 +61,7 @@ namespace MediaBrowser.Server.Implementations.Sync public event EventHandler> SyncJobItemUpdated; public event EventHandler> SyncJobItemCreated; - public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func dtoService, IApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func mediaEncoder, IFileSystem fileSystem, Func subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func mediaSourceManager, IJsonSerializer json) + public SyncManager(ILibraryManager libraryManager, ISyncRepository repo, IImageProcessor imageProcessor, ILogger logger, IUserManager userManager, Func dtoService, IServerApplicationHost appHost, ITVSeriesManager tvSeriesManager, Func mediaEncoder, IFileSystem fileSystem, Func subtitleEncoder, IConfigurationManager config, IUserDataManager userDataManager, Func mediaSourceManager, IJsonSerializer json) { _libraryManager = libraryManager; _repo = repo; @@ -94,7 +95,7 @@ namespace MediaBrowser.Server.Implementations.Sync public ISyncDataProvider GetDataProvider(IServerSyncProvider provider, SyncTarget target) { - return _dataProviders.GetOrAdd(target.Id, key => new TargetDataProvider(provider, target, _appHost.SystemId, _logger, _json, _fileSystem, _config.CommonApplicationPaths)); + return _dataProviders.GetOrAdd(target.Id, key => new TargetDataProvider(provider, target, _appHost, _logger, _json, _fileSystem, _config.CommonApplicationPaths)); } public async Task CreateJob(SyncJobRequest request) @@ -737,10 +738,15 @@ namespace MediaBrowser.Server.Implementations.Sync public async Task SyncData(SyncDataRequest request) { + if (request.SyncJobItemIds != null) + { + return await SyncDataUsingSyncJobItemIds(request).ConfigureAwait(false); + } + var jobItemResult = GetJobItems(new SyncJobItemQuery { TargetId = request.TargetId, - Statuses = new SyncJobItemStatus[] { SyncJobItemStatus.Synced } + Statuses = new[] { SyncJobItemStatus.Synced } }); var response = new SyncDataResponse(); @@ -816,6 +822,87 @@ namespace MediaBrowser.Server.Implementations.Sync return response; } + private async Task SyncDataUsingSyncJobItemIds(SyncDataRequest request) + { + var jobItemResult = GetJobItems(new SyncJobItemQuery + { + TargetId = request.TargetId, + Statuses = new[] { SyncJobItemStatus.Synced } + }); + + var response = new SyncDataResponse(); + + foreach (var jobItem in jobItemResult.Items) + { + if (request.SyncJobItemIds.Contains(jobItem.Id, StringComparer.OrdinalIgnoreCase)) + { + var job = _repo.GetJob(jobItem.JobId); + var user = _userManager.GetUserById(job.UserId); + + if (jobItem.IsMarkedForRemoval) + { + // Tell the device to remove it since it has been marked for removal + response.ItemIdsToRemove.Add(jobItem.Id); + } + else if (user == null) + { + // Tell the device to remove it since the user is gone now + response.ItemIdsToRemove.Add(jobItem.Id); + } + else if (job.UnwatchedOnly) + { + var libraryItem = _libraryManager.GetItemById(jobItem.ItemId); + + if (IsLibraryItemAvailable(libraryItem)) + { + if (libraryItem.IsPlayed(user) && libraryItem is Video) + { + // Tell the device to remove it since it has been played + response.ItemIdsToRemove.Add(jobItem.Id); + } + } + else + { + // Tell the device to remove it since it's no longer available + response.ItemIdsToRemove.Add(jobItem.Id); + } + } + } + else + { + // Content is no longer on the device + jobItem.Status = SyncJobItemStatus.RemovedFromDevice; + await UpdateSyncJobItemInternal(jobItem).ConfigureAwait(false); + } + } + + // Now check each item that's on the device + foreach (var syncJobItemId in request.SyncJobItemIds) + { + // See if it's already marked for removal + if (response.ItemIdsToRemove.Contains(syncJobItemId, StringComparer.OrdinalIgnoreCase)) + { + continue; + } + + // If there isn't a sync job for this item, mark it for removal + if (!jobItemResult.Items.Any(i => string.Equals(syncJobItemId, i.Id, StringComparison.OrdinalIgnoreCase))) + { + response.ItemIdsToRemove.Add(syncJobItemId); + } + } + + response.ItemIdsToRemove = response.ItemIdsToRemove.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); + + var itemsOnDevice = request.LocalItemIds + .Except(response.ItemIdsToRemove) + .ToList(); + + SetUserAccess(request, response, itemsOnDevice); + + return response; + } + private void SetUserAccess(SyncDataRequest request, SyncDataResponse response, List itemIds) { var users = request.OfflineUserIds diff --git a/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs b/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs index ca9d96c12f..dea8688482 100644 --- a/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs +++ b/MediaBrowser.Server.Implementations/Sync/TargetDataProvider.cs @@ -1,6 +1,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; +using MediaBrowser.Controller; using MediaBrowser.Controller.Sync; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; @@ -26,11 +27,11 @@ namespace MediaBrowser.Server.Implementations.Sync private readonly IJsonSerializer _json; private readonly IFileSystem _fileSystem; private readonly IApplicationPaths _appPaths; - private readonly string _serverId; + private readonly IServerApplicationHost _appHost; private readonly SemaphoreSlim _cacheFileLock = new SemaphoreSlim(1, 1); - public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, string serverId, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths) + public TargetDataProvider(IServerSyncProvider provider, SyncTarget target, IServerApplicationHost appHost, ILogger logger, IJsonSerializer json, IFileSystem fileSystem, IApplicationPaths appPaths) { _logger = logger; _json = json; @@ -38,7 +39,7 @@ namespace MediaBrowser.Server.Implementations.Sync _target = target; _fileSystem = fileSystem; _appPaths = appPaths; - _serverId = serverId; + _appHost = appHost; } private string GetCachePath() @@ -50,13 +51,21 @@ namespace MediaBrowser.Server.Implementations.Sync { var parts = new List { - _serverId, + _appHost.FriendlyName, "data.json" }; + parts = parts.Select(i => GetValidFilename(_provider, i)).ToList(); + return _provider.GetFullPath(parts, _target); } + private string GetValidFilename(IServerSyncProvider provider, string filename) + { + // We can always add this method to the sync provider if it's really needed + return _fileSystem.GetValidFilename(filename); + } + private async Task CacheData(Stream stream) { var cachePath = GetCachePath(); @@ -167,6 +176,11 @@ namespace MediaBrowser.Server.Implementations.Sync return GetData(items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase)).Select(i => i.ItemId).ToList()); } + public Task> GetSyncJobItemIds(SyncTarget target, string serverId) + { + return GetData(items => items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase)).Select(i => i.SyncJobItemId).Where(i => !string.IsNullOrWhiteSpace(i)).ToList()); + } + public Task AddOrUpdate(SyncTarget target, LocalItem item) { return UpdateData(items => @@ -239,5 +253,13 @@ namespace MediaBrowser.Server.Implementations.Sync return items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase) && string.Equals(i.ItemId, itemId, StringComparison.OrdinalIgnoreCase)) .ToList(); } + + public async Task> GetCachedItemsBySyncJobItemId(SyncTarget target, string serverId, string syncJobItemId) + { + var items = await GetCachedData().ConfigureAwait(false); + + return items.Where(i => string.Equals(i.ServerId, serverId, StringComparison.OrdinalIgnoreCase) && string.Equals(i.SyncJobItemId, syncJobItemId, StringComparison.OrdinalIgnoreCase)) + .ToList(); + } } } diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 40da3899c5..c5acc0a42d 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.609 + 3.0.611 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 7aa9d30551..1b29b02729 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.609 + 3.0.611 MediaBrowser.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Model.Signed.nuspec b/Nuget/MediaBrowser.Model.Signed.nuspec index 8d65ec4315..6ee79dd8c9 100644 --- a/Nuget/MediaBrowser.Model.Signed.nuspec +++ b/Nuget/MediaBrowser.Model.Signed.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Model.Signed - 3.0.609 + 3.0.611 MediaBrowser.Model - Signed Edition Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 9a5264da95..c8b062f3f3 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.609 + 3.0.611 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 - + -- cgit v1.2.3