aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2017-04-17 16:33:52 -0400
committerGitHub <noreply@github.com>2017-04-17 16:33:52 -0400
commitf0f3ca8c181b4144cbd21fb545d0629e92a9529b (patch)
treeebf4e2680ef00483b38618d97e7df26ea3da2fcd
parent315541a686858eeab84f73a4fcad1a11c1ee15c7 (diff)
parent6a66aef608a0caa567f603edbd9a4e3466fda469 (diff)
Merge pull request #2584 from MediaBrowser/dev
Dev
-rw-r--r--Emby.Dlna/PlayTo/PlayToController.cs3
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs98
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs2
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs66
-rw-r--r--Emby.Server.Implementations/Session/SessionWebSocketListener.cs6
-rw-r--r--MediaBrowser.Api/ApiEntryPoint.cs12
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs2
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs2
-rw-r--r--MediaBrowser.Api/SuggestionsService.cs35
-rw-r--r--MediaBrowser.Api/TvShowsService.cs34
-rw-r--r--MediaBrowser.Api/UserLibrary/PlaystateService.cs10
-rw-r--r--MediaBrowser.Controller/Library/IMediaSourceManager.cs11
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs2
-rw-r--r--MediaBrowser.Controller/Session/SessionInfo.cs105
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs2
-rw-r--r--MediaBrowser.Model/Session/PlaybackStartInfo.cs13
-rw-r--r--MediaBrowser.Model/Session/SessionInfoDto.cs7
-rw-r--r--SharedVersion.cs2
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&lt;MediaSourceInfo&gt;.</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")]