diff options
| author | Luke <luke.pulverenti@gmail.com> | 2017-04-17 16:33:52 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-04-17 16:33:52 -0400 |
| commit | f0f3ca8c181b4144cbd21fb545d0629e92a9529b (patch) | |
| tree | ebf4e2680ef00483b38618d97e7df26ea3da2fcd | |
| parent | 315541a686858eeab84f73a4fcad1a11c1ee15c7 (diff) | |
| parent | 6a66aef608a0caa567f603edbd9a4e3466fda469 (diff) | |
Merge pull request #2584 from MediaBrowser/dev
Dev
18 files changed, 139 insertions, 273 deletions
diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index b73332c4b..3a7e75381 100644 --- a/Emby.Dlna/PlayTo/PlayToController.cs +++ b/Emby.Dlna/PlayTo/PlayToController.cs @@ -318,8 +318,7 @@ namespace Emby.Dlna.PlayTo CanSeek = info.MediaSource == null ? _device.Duration.HasValue : info.MediaSource.RunTimeTicks.HasValue, - PlayMethod = info.IsDirectStream ? PlayMethod.DirectStream : PlayMethod.Transcode, - QueueableMediaTypes = new List<string> { mediaInfo.MediaType } + PlayMethod = info.IsDirectStream ? PlayMethod.DirectStream : PlayMethod.Transcode }; } diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index ccd4c3631..4857008f3 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -9,13 +9,10 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Serialization; using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Threading; @@ -365,12 +362,10 @@ namespace Emby.Server.Implementations.Library private readonly Dictionary<string, LiveStreamInfo> _openStreams = new Dictionary<string, LiveStreamInfo>(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); - public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken) + public async Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken) { await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - enableAutoClose = false; - try { var tuple = GetProvider(request.OpenToken); @@ -389,8 +384,6 @@ namespace Emby.Server.Implementations.Library var info = new LiveStreamInfo { - Date = DateTime.UtcNow, - EnableCloseTimer = enableAutoClose, Id = mediaSource.LiveStreamId, MediaSource = mediaSource, DirectStreamProvider = mediaSourceTuple.Item2 @@ -398,11 +391,6 @@ namespace Emby.Server.Implementations.Library _openStreams[mediaSource.LiveStreamId] = info; - if (enableAutoClose) - { - StartCloseTimer(); - } - var json = _jsonSerializer.SerializeToString(mediaSource); _logger.Debug("Live stream opened: " + json); var clone = _jsonSerializer.DeserializeFromString<MediaSourceInfo>(json); @@ -462,28 +450,6 @@ namespace Emby.Server.Implementations.Library return result.Item1; } - public async Task PingLiveStream(string id, CancellationToken cancellationToken) - { - await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - LiveStreamInfo info; - if (_openStreams.TryGetValue(id, out info)) - { - info.Date = DateTime.UtcNow; - } - else - { - _logger.Error("Failed to ping live stream {0}", id); - } - } - finally - { - _liveStreamSemaphore.Release(); - } - } - private async Task CloseLiveStreamWithProvider(IMediaSourceProvider provider, string streamId) { _logger.Info("Closing live stream {0} with provider {1}", streamId, provider.GetType().Name); @@ -525,11 +491,6 @@ namespace Emby.Server.Implementations.Library await CloseLiveStreamWithProvider(tuple.Item1, tuple.Item2).ConfigureAwait(false); } - - if (_openStreams.Count == 0) - { - StopCloseTimer(); - } } } finally @@ -558,66 +519,11 @@ namespace Emby.Server.Implementations.Library return new Tuple<IMediaSourceProvider, string>(provider, keyId); } - private ITimer _closeTimer; - private readonly TimeSpan _openStreamMaxAge = TimeSpan.FromSeconds(180); - - private void StartCloseTimer() - { - StopCloseTimer(); - - _closeTimer = _timerFactory.Create(CloseTimerCallback, null, _openStreamMaxAge, _openStreamMaxAge); - } - - private void StopCloseTimer() - { - var timer = _closeTimer; - - if (timer != null) - { - _closeTimer = null; - timer.Dispose(); - } - } - - private async void CloseTimerCallback(object state) - { - List<LiveStreamInfo> infos; - await _liveStreamSemaphore.WaitAsync().ConfigureAwait(false); - - try - { - infos = _openStreams - .Values - .Where(i => i.EnableCloseTimer && DateTime.UtcNow - i.Date > _openStreamMaxAge) - .ToList(); - } - finally - { - _liveStreamSemaphore.Release(); - } - - foreach (var info in infos) - { - if (!info.Closed) - { - try - { - await CloseLiveStream(info.Id).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error closing media source", ex); - } - } - } - } - /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { - StopCloseTimer(); Dispose(true); } @@ -644,8 +550,6 @@ namespace Emby.Server.Implementations.Library private class LiveStreamInfo { - public DateTime Date; - public bool EnableCloseTimer; public string Id; public bool Closed; public MediaSourceInfo MediaSource; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 93996f5da..329f5b8a4 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -190,7 +190,7 @@ namespace Emby.Server.Implementations.LiveTv else if (width >= 1260) { - videoStream.BitRate = 3000000; + videoStream.BitRate = 4000000; } else if (width >= 700) diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 05a240cea..0a2312735 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -197,6 +197,8 @@ namespace Emby.Server.Implementations.Session _logger.ErrorException("Error disposing session controller", ex); } } + + info.Dispose(); } /// <summary> @@ -308,10 +310,7 @@ namespace Emby.Server.Implementations.Session /// <summary> /// Updates the now playing item id. /// </summary> - /// <param name="session">The session.</param> - /// <param name="info">The information.</param> - /// <param name="libraryItem">The library item.</param> - private async Task UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInfo info, BaseItem libraryItem) + private async Task UpdateNowPlayingItem(SessionInfo session, PlaybackProgressInfo info, BaseItem libraryItem, bool updateLastCheckInTime) { if (string.IsNullOrWhiteSpace(info.MediaSourceId)) { @@ -350,7 +349,11 @@ namespace Emby.Server.Implementations.Session session.NowPlayingItem = info.Item; session.LastActivityDate = DateTime.UtcNow; - session.LastPlaybackCheckIn = DateTime.UtcNow; + + if (updateLastCheckInTime) + { + session.LastPlaybackCheckIn = DateTime.UtcNow; + } session.PlayState.IsPaused = info.IsPaused; session.PlayState.PositionTicks = info.PositionTicks; @@ -415,7 +418,7 @@ namespace Emby.Server.Implementations.Session if (!_activeConnections.TryGetValue(key, out sessionInfo)) { - sessionInfo = new SessionInfo + sessionInfo = new SessionInfo(this, _logger) { Client = appName, DeviceId = deviceId, @@ -602,14 +605,14 @@ namespace Emby.Server.Implementations.Session ? null : GetNowPlayingItem(session, info.ItemId); - await UpdateNowPlayingItem(session, info, libraryItem).ConfigureAwait(false); + await UpdateNowPlayingItem(session, info, libraryItem, true).ConfigureAwait(false); if (!string.IsNullOrEmpty(session.DeviceId) && info.PlayMethod != PlayMethod.Transcode) { ClearTranscodingInfo(session.DeviceId); } - session.QueueableMediaTypes = info.QueueableMediaTypes; + session.StartAutomaticProgress(_timerFactory, info); var users = GetUsers(session); @@ -668,14 +671,15 @@ namespace Emby.Server.Implementations.Session await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false); } + public Task OnPlaybackProgress(PlaybackProgressInfo info) + { + return OnPlaybackProgress(info, false); + } + /// <summary> /// Used to report playback progress for an item /// </summary> - /// <param name="info">The info.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - /// <exception cref="System.ArgumentOutOfRangeException">positionTicks</exception> - public async Task OnPlaybackProgress(PlaybackProgressInfo info) + public async Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated) { if (info == null) { @@ -688,7 +692,7 @@ namespace Emby.Server.Implementations.Session ? null : GetNowPlayingItem(session, info.ItemId); - await UpdateNowPlayingItem(session, info, libraryItem).ConfigureAwait(false); + await UpdateNowPlayingItem(session, info, libraryItem, !isAutomated).ConfigureAwait(false); var users = GetUsers(session); @@ -700,18 +704,6 @@ namespace Emby.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, @@ -727,6 +719,11 @@ namespace Emby.Server.Implementations.Session }, _logger); + if (!isAutomated) + { + session.StartAutomaticProgress(_timerFactory, info); + } + StartIdleCheckTimer(); } @@ -788,6 +785,8 @@ namespace Emby.Server.Implementations.Session var session = GetSession(info.SessionId); + session.StopAutomaticProgress(); + var libraryItem = string.IsNullOrWhiteSpace(info.ItemId) ? null : GetNowPlayingItem(session, info.ItemId); @@ -1009,19 +1008,9 @@ namespace Emby.Server.Implementations.Session } } - if (command.PlayCommand != PlayCommand.PlayNow) - { - if (items.Any(i => !session.QueueableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) - { - throw new ArgumentException(string.Format("{0} is unable to queue the requested media type.", session.DeviceName ?? session.Id)); - } - } - else + if (items.Any(i => !session.PlayableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) { - if (items.Any(i => !session.PlayableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) - { - throw new ArgumentException(string.Format("{0} is unable to play the requested media type.", session.DeviceName ?? session.Id)); - } + throw new ArgumentException(string.Format("{0} is unable to play the requested media type.", session.DeviceName ?? session.Id)); } if (user != null && command.ItemIds.Length == 1 && user.Configuration.EnableNextEpisodeAutoPlay) @@ -1601,7 +1590,6 @@ namespace Emby.Server.Implementations.Session LastActivityDate = session.LastActivityDate, NowViewingItem = session.NowViewingItem, ApplicationVersion = session.ApplicationVersion, - QueueableMediaTypes = session.QueueableMediaTypes, PlayableMediaTypes = session.PlayableMediaTypes, AdditionalUsers = session.AdditionalUsers, SupportedCommands = session.SupportedCommands, diff --git a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs index 336c2caee..478f9da71 100644 --- a/Emby.Server.Implementations/Session/SessionWebSocketListener.cs +++ b/Emby.Server.Implementations/Session/SessionWebSocketListener.cs @@ -289,7 +289,6 @@ namespace Emby.Server.Implementations.Session var itemId = vals[0]; - var queueableMediaTypes = string.Empty; var canSeek = true; if (vals.Length > 1) @@ -298,15 +297,14 @@ namespace Emby.Server.Implementations.Session } if (vals.Length > 2) { - queueableMediaTypes = vals[2]; + // vals[2] used to be QueueableMediaTypes } var info = new PlaybackStartInfo { CanSeek = canSeek, ItemId = itemId, - SessionId = session.Id, - QueueableMediaTypes = queueableMediaTypes.Split(',').ToList() + SessionId = session.Id }; if (vals.Length > 3) diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index b62af554e..a59ab33a9 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -426,18 +426,6 @@ namespace MediaBrowser.Api { job.ChangeKillTimerIfStarted(); } - - if (!string.IsNullOrWhiteSpace(job.LiveStreamId)) - { - try - { - await _mediaSourceManager.PingLiveStream(job.LiveStreamId, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error closing live stream", ex); - } - } } /// <summary> diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 480508e6f..699c4bbb2 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -169,7 +169,7 @@ namespace MediaBrowser.Api.Playback { OpenToken = state.MediaSource.OpenToken - }, false, cancellationTokenSource.Token).ConfigureAwait(false); + }, cancellationTokenSource.Token).ConfigureAwait(false); EncodingHelper.AttachMediaSourceInfo(state, liveStreamResponse.MediaSource, state.RequestedUrl); diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index 0ee0dab30..fcd18bfe4 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -109,7 +109,7 @@ namespace MediaBrowser.Api.Playback { var authInfo = _authContext.GetAuthorizationInfo(Request); - var result = await _mediaSourceManager.OpenLiveStream(request, true, CancellationToken.None).ConfigureAwait(false); + var result = await _mediaSourceManager.OpenLiveStream(request, CancellationToken.None).ConfigureAwait(false); var profile = request.DeviceProfile; if (profile == null) diff --git a/MediaBrowser.Api/SuggestionsService.cs b/MediaBrowser.Api/SuggestionsService.cs index 3e901e303..99411ffdc 100644 --- a/MediaBrowser.Api/SuggestionsService.cs +++ b/MediaBrowser.Api/SuggestionsService.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Library; namespace MediaBrowser.Api { [Route("/Users/{UserId}/Suggestions", "GET", Summary = "Gets items based on a query.")] - [Route("/Users/{UserId}/Suggestions", "POST", Summary = "Gets items based on a query.")] public class GetSuggestedItems : IReturn<QueryResult<BaseItem>> { public string MediaType { get; set; } @@ -21,7 +20,6 @@ namespace MediaBrowser.Api public bool EnableTotalRecordCount { get; set; } public int? StartIndex { get; set; } public int? Limit { get; set; } - public string Name { get; set; } public string[] GetMediaTypes() { @@ -56,13 +54,6 @@ namespace MediaBrowser.Api return ToOptimizedResult(result); } - public async Task<object> Post(GetSuggestedItems request) - { - var result = await GetResultItems(request).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - private async Task<QueryResult<BaseItemDto>> GetResultItems(GetSuggestedItems request) { var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; @@ -86,29 +77,6 @@ namespace MediaBrowser.Api private QueryResult<BaseItem> GetItems(GetSuggestedItems request, User user, DtoOptions dtoOptions) { - BaseItem similarToItem = null; - - if (!string.IsNullOrWhiteSpace(request.Name)) - { - // get item by name, then get similar items from that - similarToItem = _libraryManager.GetItemList(new InternalItemsQuery(user) - { - SortBy = new string[] {ItemSortBy.Random}, - MediaTypes = request.GetMediaTypes(), - IncludeItemTypes = request.GetIncludeItemTypes(), - IsVirtualItem = false, - Name = request.Name, - Recursive = true, - Limit = 1 - - }).FirstOrDefault(); - - if (similarToItem == null) - { - return new QueryResult<BaseItem>(); - } - } - return _libraryManager.GetItemsResult(new InternalItemsQuery(user) { SortBy = new string[] { ItemSortBy.Random }, @@ -119,8 +87,7 @@ namespace MediaBrowser.Api Limit = request.Limit, DtoOptions = dtoOptions, EnableTotalRecordCount = request.EnableTotalRecordCount, - Recursive = true, - SimilarTo = similarToItem + Recursive = true }); } } diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index 13adceed5..126f1c753 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -137,7 +137,6 @@ namespace MediaBrowser.Api } [Route("/Shows/{Id}/Episodes", "GET", Summary = "Gets episodes for a tv season")] - [Route("/Shows/Episodes", "POST", Summary = "Gets episodes for a tv season")] public class GetEpisodes : IReturn<ItemsResult>, IHasItemFields, IHasDtoOptions { /// <summary> @@ -200,12 +199,9 @@ namespace MediaBrowser.Api [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool? EnableUserData { get; set; } - - public string SeriesName { get; set; } } [Route("/Shows/{Id}/Seasons", "GET", Summary = "Gets seasons for a tv series")] - [Route("/Shows/Seasons", "POST", Summary = "Gets seasons for a tv series")] public class GetSeasons : IReturn<ItemsResult>, IHasItemFields, IHasDtoOptions { /// <summary> @@ -248,8 +244,6 @@ namespace MediaBrowser.Api [ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")] public bool? EnableUserData { get; set; } - - public string SeriesName { get; set; } } /// <summary> @@ -431,7 +425,7 @@ namespace MediaBrowser.Api { var user = _userManager.GetUserById(request.UserId); - var series = GetSeries(request.Id, request.SeriesName, user); + var series = GetSeries(request.Id, user); if (series == null) { @@ -459,33 +453,13 @@ namespace MediaBrowser.Api }; } - public Task<object> Post(GetSeasons request) - { - return Get(request); - } - - public Task<object> Post(GetEpisodes request) - { - return Get(request); - } - - private Series GetSeries(string seriesId, string seriesName, User user) + private Series GetSeries(string seriesId, User user) { if (!string.IsNullOrWhiteSpace(seriesId)) { return _libraryManager.GetItemById(seriesId) as Series; } - if (!string.IsNullOrWhiteSpace(seriesName)) - { - return _libraryManager.GetItemList(new InternalItemsQuery(user) - { - Name = seriesName, - IncludeItemTypes = new string[] { typeof(Series).Name } - - }).OfType<Series>().FirstOrDefault(); - } - return null; } @@ -508,7 +482,7 @@ namespace MediaBrowser.Api } else if (request.Season.HasValue) { - var series = GetSeries(request.Id, request.SeriesName, user); + var series = GetSeries(request.Id, user); if (series == null) { @@ -528,7 +502,7 @@ namespace MediaBrowser.Api } else { - var series = GetSeries(request.Id, request.SeriesName, user); + var series = GetSeries(request.Id, user); if (series == null) { diff --git a/MediaBrowser.Api/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index 504dd29a7..c4cc90955 100644 --- a/MediaBrowser.Api/UserLibrary/PlaystateService.cs +++ b/MediaBrowser.Api/UserLibrary/PlaystateService.cs @@ -109,13 +109,6 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "CanSeek", Description = "Indicates if the client can seek", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "POST")] public bool CanSeek { get; set; } - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [ApiMember(Name = "QueueableMediaTypes", Description = "A list of media types that can be queued from this item, comma delimited. Audio,Video,Book,Game", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)] - public string QueueableMediaTypes { get; set; } - [ApiMember(Name = "AudioStreamIndex", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "POST")] public int? AudioStreamIndex { get; set; } @@ -292,13 +285,10 @@ namespace MediaBrowser.Api.UserLibrary /// <param name="request">The request.</param> public void Post(OnPlaybackStart request) { - var queueableMediaTypes = request.QueueableMediaTypes ?? string.Empty; - Post(new ReportPlaybackStart { CanSeek = request.CanSeek, ItemId = request.Id, - QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(), MediaSourceId = request.MediaSourceId, AudioStreamIndex = request.AudioStreamIndex, SubtitleStreamIndex = request.SubtitleStreamIndex, diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 1ab0e4cb0..2f8f37789 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -68,10 +68,9 @@ namespace MediaBrowser.Controller.Library /// Opens the media source. /// </summary> /// <param name="request">The request.</param> - /// <param name="enableAutoClose">if set to <c>true</c> [enable automatic close].</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task<MediaSourceInfo>.</returns> - Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken); + Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken); /// <summary> /// Gets the live stream. @@ -82,14 +81,6 @@ namespace MediaBrowser.Controller.Library Task<MediaSourceInfo> GetLiveStream(string id, CancellationToken cancellationToken); Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken); - - /// <summary> - /// Pings the media source. - /// </summary> - /// <param name="id">The live stream identifier.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task PingLiveStream(string id, CancellationToken cancellationToken); /// <summary> /// Closes the media source. diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 387195245..956d4cc95 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -99,6 +99,8 @@ namespace MediaBrowser.Controller.Session /// <exception cref="System.ArgumentNullException"></exception> Task OnPlaybackProgress(PlaybackProgressInfo info); + Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated); + /// <summary> /// Used to report that playback has ended for an item /// </summary> diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 343b15a04..5cef56d1c 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -4,24 +4,30 @@ using System; using System.Collections.Generic; using System.Linq; using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Threading; namespace MediaBrowser.Controller.Session { /// <summary> /// Class SessionInfo /// </summary> - public class SessionInfo + public class SessionInfo : IDisposable { - public SessionInfo() + private ISessionManager _sessionManager; + private readonly ILogger _logger; + + public SessionInfo(ISessionManager sessionManager, ILogger logger) { - QueueableMediaTypes = new List<string>(); + _sessionManager = sessionManager; + _logger = logger; AdditionalUsers = new List<SessionUserInfo>(); PlayState = new PlayerStateInfo(); } public PlayerStateInfo PlayState { get; set; } - + public List<SessionUserInfo> AdditionalUsers { get; set; } public ClientCapabilities Capabilities { get; set; } @@ -33,12 +39,6 @@ namespace MediaBrowser.Controller.Session public string RemoteEndPoint { get; set; } /// <summary> - /// Gets or sets the queueable media types. - /// </summary> - /// <value>The queueable media types.</value> - public List<string> QueueableMediaTypes { get; set; } - - /// <summary> /// Gets or sets the playable media types. /// </summary> /// <value>The playable media types.</value> @@ -133,7 +133,7 @@ namespace MediaBrowser.Controller.Session /// </summary> /// <value>The application icon URL.</value> public string AppIconUrl { get; set; } - + /// <summary> /// Gets or sets the supported commands. /// </summary> @@ -196,5 +196,88 @@ namespace MediaBrowser.Controller.Session { return (UserId ?? Guid.Empty) == userId || AdditionalUsers.Any(i => userId == new Guid(i.UserId)); } + + private readonly object _progressLock = new object(); + private ITimer _progressTimer; + private PlaybackProgressInfo _lastProgressInfo; + + public void StartAutomaticProgress(ITimerFactory timerFactory, PlaybackProgressInfo progressInfo) + { + lock (_progressLock) + { + _lastProgressInfo = progressInfo; + + if (_progressTimer == null) + { + _progressTimer = timerFactory.Create(OnProgressTimerCallback, null, 1000, 1000); + } + else + { + _progressTimer.Change(1000, 1000); + } + } + } + + // 1 second + private const long ProgressIncrement = 10000000; + + private async void OnProgressTimerCallback(object state) + { + var progressInfo = _lastProgressInfo; + if (progressInfo == null) + { + return; + } + if (progressInfo.IsPaused) + { + return; + } + + var positionTicks = progressInfo.PositionTicks ?? 0; + if (positionTicks < 0) + { + positionTicks = 0; + } + + var newPositionTicks = positionTicks + ProgressIncrement; + var item = progressInfo.Item; + long? runtimeTicks = item == null ? null : item.RunTimeTicks; + + // Don't report beyond the runtime + if (runtimeTicks.HasValue && newPositionTicks >= runtimeTicks.Value) + { + return; + } + + progressInfo.PositionTicks = newPositionTicks; + + try + { + await _sessionManager.OnPlaybackProgress(progressInfo, true).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error reporting playback progress", ex); + } + } + + public void StopAutomaticProgress() + { + lock (_progressLock) + { + if (_progressTimer != null) + { + _progressTimer.Dispose(); + _progressTimer = null; + } + _lastProgressInfo = null; + } + } + + public void Dispose() + { + StopAutomaticProgress(); + _sessionManager = null; + } } } diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index c0440e132..e402c2bac 100644 --- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs @@ -356,7 +356,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { OpenToken = state.MediaSource.OpenToken - }, false, cancellationToken).ConfigureAwait(false); + }, cancellationToken).ConfigureAwait(false); EncodingHelper.AttachMediaSourceInfo(state, liveStreamResponse.MediaSource, null); diff --git a/MediaBrowser.Model/Session/PlaybackStartInfo.cs b/MediaBrowser.Model/Session/PlaybackStartInfo.cs index d1ea2841e..f6f496e4e 100644 --- a/MediaBrowser.Model/Session/PlaybackStartInfo.cs +++ b/MediaBrowser.Model/Session/PlaybackStartInfo.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; - + namespace MediaBrowser.Model.Session { /// <summary> @@ -7,15 +6,5 @@ namespace MediaBrowser.Model.Session /// </summary> public class PlaybackStartInfo : PlaybackProgressInfo { - public PlaybackStartInfo() - { - QueueableMediaTypes = new List<string>(); - } - - /// <summary> - /// Gets or sets the queueable media types. - /// </summary> - /// <value>The queueable media types.</value> - public List<string> QueueableMediaTypes { get; set; } } } diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs index 42263c644..0909d255a 100644 --- a/MediaBrowser.Model/Session/SessionInfoDto.cs +++ b/MediaBrowser.Model/Session/SessionInfoDto.cs @@ -15,12 +15,6 @@ namespace MediaBrowser.Model.Session public List<string> SupportedCommands { get; set; } /// <summary> - /// Gets or sets the queueable media types. - /// </summary> - /// <value>The queueable media types.</value> - public List<string> QueueableMediaTypes { get; set; } - - /// <summary> /// Gets or sets the playable media types. /// </summary> /// <value>The playable media types.</value> @@ -119,7 +113,6 @@ namespace MediaBrowser.Model.Session AdditionalUsers = new List<SessionUserInfo>(); PlayableMediaTypes = new List<string>(); - QueueableMediaTypes = new List<string>(); SupportedCommands = new List<string>(); } } diff --git a/SharedVersion.cs b/SharedVersion.cs index 105fb9077..d89e17dea 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.12.7")] +[assembly: AssemblyVersion("3.2.12.8")] |
