From 0b5019ed1b8c7624eae27aebe715132e07f8a417 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 17 Apr 2017 14:40:42 -0400 Subject: [PATCH 1/4] support automatic progress reporting --- .../Session/SessionManager.cs | 8 +- .../Session/SessionInfo.cs | 95 ++++++++++++++++++- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 05a240ceab..ed0a47121e 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(); } /// @@ -415,7 +417,7 @@ namespace Emby.Server.Implementations.Session if (!_activeConnections.TryGetValue(key, out sessionInfo)) { - sessionInfo = new SessionInfo + sessionInfo = new SessionInfo(this, _logger) { Client = appName, DeviceId = deviceId, @@ -609,6 +611,7 @@ namespace Emby.Server.Implementations.Session ClearTranscodingInfo(session.DeviceId); } + session.StopAutomaticProgress(); session.QueueableMediaTypes = info.QueueableMediaTypes; var users = GetUsers(session); @@ -727,6 +730,7 @@ namespace Emby.Server.Implementations.Session }, _logger); + session.StartAutomaticProgress(_timerFactory, info); StartIdleCheckTimer(); } @@ -788,6 +792,8 @@ namespace Emby.Server.Implementations.Session var session = GetSession(info.SessionId); + session.StopAutomaticProgress(); + var libraryItem = string.IsNullOrWhiteSpace(info.ItemId) ? null : GetNowPlayingItem(session, info.ItemId); diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 343b15a04f..6cb6f4bb69 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -4,16 +4,23 @@ 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 { /// /// Class SessionInfo /// - public class SessionInfo + public class SessionInfo : IDisposable { - public SessionInfo() + private ISessionManager _sessionManager; + private readonly ILogger _logger; + + public SessionInfo(ISessionManager sessionManager, ILogger logger) { + _sessionManager = sessionManager; + _logger = logger; QueueableMediaTypes = new List(); AdditionalUsers = new List(); @@ -21,7 +28,7 @@ namespace MediaBrowser.Controller.Session } public PlayerStateInfo PlayState { get; set; } - + public List AdditionalUsers { get; set; } public ClientCapabilities Capabilities { get; set; } @@ -133,7 +140,7 @@ namespace MediaBrowser.Controller.Session /// /// The application icon URL. public string AppIconUrl { get; set; } - + /// /// Gets or sets the supported commands. /// @@ -196,5 +203,85 @@ 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) + { + return; + } + + _progressTimer = timerFactory.Create(OnProgressTimerCallback, null, 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) + { + return; + } + + 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).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; + } } } From 561028c90734b911ebb5eec26aa071fb6851a2a6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 17 Apr 2017 15:01:16 -0400 Subject: [PATCH 2/4] update automated checkins --- .../Library/MediaSourceManager.cs | 98 +------------------ .../LiveTv/LiveTvMediaSourceProvider.cs | 2 +- .../Session/SessionManager.cs | 38 +++---- MediaBrowser.Api/ApiEntryPoint.cs | 12 --- .../Playback/BaseStreamingService.cs | 2 +- MediaBrowser.Api/Playback/MediaInfoService.cs | 2 +- MediaBrowser.Api/SuggestionsService.cs | 35 +------ MediaBrowser.Api/TvShowsService.cs | 34 +------ .../Library/IMediaSourceManager.cs | 11 +-- .../Session/ISessionManager.cs | 2 + .../Session/SessionInfo.cs | 2 +- .../Encoder/BaseEncoder.cs | 2 +- 12 files changed, 28 insertions(+), 212 deletions(-) diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index ccd4c3631e..4857008f35 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 _openStreams = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1); - public async Task OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken) + public async Task 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(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(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 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); - } - } - } - } - /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// 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 93996f5da5..329f5b8a4b 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 ed0a47121e..63556c1ce1 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -310,10 +310,7 @@ namespace Emby.Server.Implementations.Session /// /// Updates the now playing item id. /// - /// The session. - /// The information. - /// The library item. - 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)) { @@ -352,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; @@ -604,7 +605,7 @@ 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) { @@ -671,14 +672,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); + } + /// /// Used to report playback progress for an item /// - /// The info. - /// Task. - /// - /// positionTicks - public async Task OnPlaybackProgress(PlaybackProgressInfo info) + public async Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated) { if (info == null) { @@ -691,7 +693,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); @@ -703,18 +705,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, diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index b62af554e7..a59ab33a97 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); - } - } } /// diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 480508e6ff..699c4bbb2f 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 0ee0dab300..fcd18bfe47 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 3e901e303d..99411ffdcb 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> { 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 Post(GetSuggestedItems request) - { - var result = await GetResultItems(request).ConfigureAwait(false); - - return ToOptimizedResult(result); - } - private async Task> GetResultItems(GetSuggestedItems request) { var user = !string.IsNullOrWhiteSpace(request.UserId) ? _userManager.GetUserById(request.UserId) : null; @@ -86,29 +77,6 @@ namespace MediaBrowser.Api private QueryResult 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(); - } - } - 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 13adceed54..126f1c7539 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, IHasItemFields, IHasDtoOptions { /// @@ -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, IHasItemFields, IHasDtoOptions { /// @@ -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; } } /// @@ -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 Post(GetSeasons request) - { - return Get(request); - } - - public Task 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().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.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 1ab0e4cb06..2f8f377896 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. /// /// The request. - /// if set to true [enable automatic close]. /// The cancellation token. /// Task<MediaSourceInfo>. - Task OpenLiveStream(LiveStreamRequest request, bool enableAutoClose, CancellationToken cancellationToken); + Task OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken); /// /// Gets the live stream. @@ -82,14 +81,6 @@ namespace MediaBrowser.Controller.Library Task GetLiveStream(string id, CancellationToken cancellationToken); Task> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken); - - /// - /// Pings the media source. - /// - /// The live stream identifier. - /// The cancellation token. - /// Task. - Task PingLiveStream(string id, CancellationToken cancellationToken); /// /// Closes the media source. diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 3871952450..956d4cc95f 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -99,6 +99,8 @@ namespace MediaBrowser.Controller.Session /// Task OnPlaybackProgress(PlaybackProgressInfo info); + Task OnPlaybackProgress(PlaybackProgressInfo info, bool isAutomated); + /// /// Used to report that playback has ended for an item /// diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 6cb6f4bb69..4cb08de9fe 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -257,7 +257,7 @@ namespace MediaBrowser.Controller.Session try { - await _sessionManager.OnPlaybackProgress(progressInfo).ConfigureAwait(false); + await _sessionManager.OnPlaybackProgress(progressInfo, true).ConfigureAwait(false); } catch (Exception ex) { diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs index c0440e1321..e402c2bac8 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); From eb9b63c7a711528089b6d418f98a2b63870392e7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 17 Apr 2017 16:33:07 -0400 Subject: [PATCH 3/4] update playback progress reporting --- Emby.Dlna/PlayTo/PlayToController.cs | 3 +-- .../Session/SessionManager.cs | 24 +++++++------------ .../Session/SessionWebSocketListener.cs | 6 ++--- .../UserLibrary/PlaystateService.cs | 10 -------- .../Session/SessionInfo.cs | 22 +++++++---------- .../Session/PlaybackStartInfo.cs | 13 +--------- MediaBrowser.Model/Session/SessionInfoDto.cs | 7 ------ 7 files changed, 21 insertions(+), 64 deletions(-) diff --git a/Emby.Dlna/PlayTo/PlayToController.cs b/Emby.Dlna/PlayTo/PlayToController.cs index b73332c4bd..3a7e753819 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 { mediaInfo.MediaType } + PlayMethod = info.IsDirectStream ? PlayMethod.DirectStream : PlayMethod.Transcode }; } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index 63556c1ce1..0a2312735f 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -612,8 +612,7 @@ namespace Emby.Server.Implementations.Session ClearTranscodingInfo(session.DeviceId); } - session.StopAutomaticProgress(); - session.QueueableMediaTypes = info.QueueableMediaTypes; + session.StartAutomaticProgress(_timerFactory, info); var users = GetUsers(session); @@ -720,7 +719,11 @@ namespace Emby.Server.Implementations.Session }, _logger); - session.StartAutomaticProgress(_timerFactory, info); + if (!isAutomated) + { + session.StartAutomaticProgress(_timerFactory, info); + } + StartIdleCheckTimer(); } @@ -1005,19 +1008,9 @@ namespace Emby.Server.Implementations.Session } } - if (command.PlayCommand != PlayCommand.PlayNow) + if (items.Any(i => !session.PlayableMediaTypes.Contains(i.MediaType, StringComparer.OrdinalIgnoreCase))) { - 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))) - { - 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) @@ -1597,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 336c2caee4..478f9da716 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/UserLibrary/PlaystateService.cs b/MediaBrowser.Api/UserLibrary/PlaystateService.cs index 504dd29a73..c4cc90955e 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; } - /// - /// Gets or sets the id. - /// - /// The id. - [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 /// The request. 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/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index 4cb08de9fe..5cef56d1cd 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -21,7 +21,6 @@ namespace MediaBrowser.Controller.Session { _sessionManager = sessionManager; _logger = logger; - QueueableMediaTypes = new List(); AdditionalUsers = new List(); PlayState = new PlayerStateInfo(); @@ -39,12 +38,6 @@ namespace MediaBrowser.Controller.Session /// The remote end point. public string RemoteEndPoint { get; set; } - /// - /// Gets or sets the queueable media types. - /// - /// The queueable media types. - public List QueueableMediaTypes { get; set; } - /// /// Gets or sets the playable media types. /// @@ -214,12 +207,14 @@ namespace MediaBrowser.Controller.Session { _lastProgressInfo = progressInfo; - if (_progressTimer != null) + if (_progressTimer == null) { - return; + _progressTimer = timerFactory.Create(OnProgressTimerCallback, null, 1000, 1000); + } + else + { + _progressTimer.Change(1000, 1000); } - - _progressTimer = timerFactory.Create(OnProgressTimerCallback, null, 1000, 1000); } } @@ -237,10 +232,11 @@ namespace MediaBrowser.Controller.Session { return; } + var positionTicks = progressInfo.PositionTicks ?? 0; - if (positionTicks <= 0) + if (positionTicks < 0) { - return; + positionTicks = 0; } var newPositionTicks = positionTicks + ProgressIncrement; diff --git a/MediaBrowser.Model/Session/PlaybackStartInfo.cs b/MediaBrowser.Model/Session/PlaybackStartInfo.cs index d1ea2841e5..f6f496e4ea 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 { /// @@ -7,15 +6,5 @@ namespace MediaBrowser.Model.Session /// public class PlaybackStartInfo : PlaybackProgressInfo { - public PlaybackStartInfo() - { - QueueableMediaTypes = new List(); - } - - /// - /// Gets or sets the queueable media types. - /// - /// The queueable media types. - public List QueueableMediaTypes { get; set; } } } diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs index 42263c6442..0909d255ae 100644 --- a/MediaBrowser.Model/Session/SessionInfoDto.cs +++ b/MediaBrowser.Model/Session/SessionInfoDto.cs @@ -14,12 +14,6 @@ namespace MediaBrowser.Model.Session /// The supported commands. public List SupportedCommands { get; set; } - /// - /// Gets or sets the queueable media types. - /// - /// The queueable media types. - public List QueueableMediaTypes { get; set; } - /// /// Gets or sets the playable media types. /// @@ -119,7 +113,6 @@ namespace MediaBrowser.Model.Session AdditionalUsers = new List(); PlayableMediaTypes = new List(); - QueueableMediaTypes = new List(); SupportedCommands = new List(); } } From 6a66aef608a0caa567f603edbd9a4e3466fda469 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 17 Apr 2017 16:33:29 -0400 Subject: [PATCH 4/4] 3.2.12.8 --- SharedVersion.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 105fb90776..d89e17deae 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")]