diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index e1f4799f18..5f86c71ece 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -1308,7 +1308,9 @@ namespace MediaBrowser.Api.Playback
RequestedUrl = url
};
- var item = DtoService.GetItemByDtoId(request.Id);
+ var item = string.IsNullOrEmpty(request.MediaVersionId) ?
+ DtoService.GetItemByDtoId(request.Id) :
+ DtoService.GetItemByDtoId(request.MediaVersionId);
if (user != null && item.GetPlayAccess(user) != PlayAccess.Full)
{
diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs
index 6b0375e2d2..89e38711fe 100644
--- a/MediaBrowser.Api/Playback/StreamRequest.cs
+++ b/MediaBrowser.Api/Playback/StreamRequest.cs
@@ -15,6 +15,9 @@ namespace MediaBrowser.Api.Playback
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
+ [ApiMember(Name = "MediaVersionId", Description = "The media version id, if playing an alternate version", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
+ public string MediaVersionId { get; set; }
+
[ApiMember(Name = "DeviceId", Description = "The device id of the client requesting. Used to stop encoding processes when needed.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceId { get; set; }
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index e026aec038..5173008f9f 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -241,6 +241,9 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string Id { get; set; }
+ [ApiMember(Name = "MediaVersionId", Description = "The id of the MediaVersion", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string MediaVersionId { get; set; }
+
///
/// Gets or sets a value indicating whether this is likes.
///
@@ -277,6 +280,9 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string Id { get; set; }
+ [ApiMember(Name = "MediaVersionId", Description = "The id of the MediaVersion", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
+ public string MediaVersionId { get; set; }
+
///
/// Gets or sets the position ticks.
///
@@ -312,6 +318,9 @@ namespace MediaBrowser.Api.UserLibrary
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
public string Id { get; set; }
+ [ApiMember(Name = "MediaVersionId", Description = "The id of the MediaVersion", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "DELETE")]
+ public string MediaVersionId { get; set; }
+
///
/// Gets or sets the position ticks.
///
@@ -736,7 +745,8 @@ namespace MediaBrowser.Api.UserLibrary
CanSeek = request.CanSeek,
Item = item,
SessionId = GetSession().Id,
- QueueableMediaTypes = queueableMediaTypes.Split(',').ToList()
+ QueueableMediaTypes = queueableMediaTypes.Split(',').ToList(),
+ MediaVersionId = request.MediaVersionId
};
_sessionManager.OnPlaybackStart(info);
@@ -758,7 +768,8 @@ namespace MediaBrowser.Api.UserLibrary
PositionTicks = request.PositionTicks,
IsMuted = request.IsMuted,
IsPaused = request.IsPaused,
- SessionId = GetSession().Id
+ SessionId = GetSession().Id,
+ MediaVersionId = request.MediaVersionId
};
var task = _sessionManager.OnPlaybackProgress(info);
@@ -782,7 +793,8 @@ namespace MediaBrowser.Api.UserLibrary
{
Item = item,
PositionTicks = request.PositionTicks,
- SessionId = session.Id
+ SessionId = session.Id,
+ MediaVersionId = request.MediaVersionId
};
var task = _sessionManager.OnPlaybackStopped(info);
diff --git a/MediaBrowser.Api/UserLibrary/YearsService.cs b/MediaBrowser.Api/UserLibrary/YearsService.cs
index b8b0aa9e94..8a3bc12b2b 100644
--- a/MediaBrowser.Api/UserLibrary/YearsService.cs
+++ b/MediaBrowser.Api/UserLibrary/YearsService.cs
@@ -14,8 +14,7 @@ namespace MediaBrowser.Api.UserLibrary
///
/// Class GetYears
///
- [Route("/Years", "GET")]
- [Api(Description = "Gets all years from a given item, folder, or the entire library")]
+ [Route("/Years", "GET", Summary = "Gets all years from a given item, folder, or the entire library")]
public class GetYears : GetItemsByName
{
}
@@ -23,8 +22,7 @@ namespace MediaBrowser.Api.UserLibrary
///
/// Class GetYear
///
- [Route("/Years/{Year}", "GET")]
- [Api(Description = "Gets a year")]
+ [Route("/Years/{Year}", "GET", Summary = "Gets a year")]
public class GetYear : IReturn
{
///
diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs
index fa4b22cea7..380f89bc73 100644
--- a/MediaBrowser.Api/VideosService.cs
+++ b/MediaBrowser.Api/VideosService.cs
@@ -13,8 +13,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Api
{
- [Route("/Videos/{Id}/AdditionalParts", "GET")]
- [Api(Description = "Gets additional parts for a video.")]
+ [Route("/Videos/{Id}/AdditionalParts", "GET", Summary = "Gets additional parts for a video.")]
public class GetAdditionalParts : IReturn
{
[ApiMember(Name = "UserId", Description = "Optional. Filter by user id, and attach user data", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
@@ -28,16 +27,14 @@ namespace MediaBrowser.Api
public string Id { get; set; }
}
- [Route("/Videos/{Id}/AlternateVersions", "DELETE")]
- [Api(Description = "Assigns videos as alternates of antoher.")]
+ [Route("/Videos/{Id}/AlternateVersions", "DELETE", Summary = "Assigns videos as alternates of another.")]
public class DeleteAlternateVersions : IReturnVoid
{
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "DELETE")]
public string Id { get; set; }
}
- [Route("/Videos/MergeVersions", "POST")]
- [Api(Description = "Merges videos into a single record")]
+ [Route("/Videos/MergeVersions", "POST", Summary = "Merges videos into a single record")]
public class MergeVersions : IReturnVoid
{
[ApiMember(Name = "Ids", Description = "Item id list. This allows multiple, comma delimited.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index 03039dc831..a02851a9ff 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -28,13 +28,6 @@ namespace MediaBrowser.Controller.Dto
/// SessionInfoDto.
SessionInfoDto GetSessionInfoDto(SessionInfo session);
- ///
- /// Gets the base item info.
- ///
- /// The item.
- /// BaseItemInfo.
- BaseItemInfo GetBaseItemInfo(BaseItem item);
-
///
/// Gets the dto id.
///
diff --git a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
index 2ec3d308e3..ca815c1141 100644
--- a/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
+++ b/MediaBrowser.Controller/Library/PlaybackProgressEventArgs.cs
@@ -12,6 +12,7 @@ namespace MediaBrowser.Controller.Library
public List Users { get; set; }
public long? PlaybackPositionTicks { get; set; }
public BaseItem Item { get; set; }
+ public string MediaVersionId { get; set; }
public PlaybackProgressEventArgs()
{
diff --git a/MediaBrowser.Controller/Session/PlaybackInfo.cs b/MediaBrowser.Controller/Session/PlaybackInfo.cs
index ab3111e766..5cb488ff1c 100644
--- a/MediaBrowser.Controller/Session/PlaybackInfo.cs
+++ b/MediaBrowser.Controller/Session/PlaybackInfo.cs
@@ -34,5 +34,11 @@ namespace MediaBrowser.Controller.Session
///
/// The session id.
public Guid SessionId { get; set; }
+
+ ///
+ /// Gets or sets the media version identifier.
+ ///
+ /// The media version identifier.
+ public string MediaVersionId { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Session/PlaybackProgressInfo.cs b/MediaBrowser.Controller/Session/PlaybackProgressInfo.cs
index a075432605..0c825932c8 100644
--- a/MediaBrowser.Controller/Session/PlaybackProgressInfo.cs
+++ b/MediaBrowser.Controller/Session/PlaybackProgressInfo.cs
@@ -34,5 +34,11 @@ namespace MediaBrowser.Controller.Session
///
/// The position ticks.
public long? PositionTicks { get; set; }
+
+ ///
+ /// Gets or sets the media version identifier.
+ ///
+ /// The media version identifier.
+ public string MediaVersionId { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Session/PlaybackStopInfo.cs b/MediaBrowser.Controller/Session/PlaybackStopInfo.cs
index 5d1ce01315..3391c96cf7 100644
--- a/MediaBrowser.Controller/Session/PlaybackStopInfo.cs
+++ b/MediaBrowser.Controller/Session/PlaybackStopInfo.cs
@@ -22,5 +22,11 @@ namespace MediaBrowser.Controller.Session
///
/// The position ticks.
public long? PositionTicks { get; set; }
+
+ ///
+ /// Gets or sets the media version identifier.
+ ///
+ /// The media version identifier.
+ public string MediaVersionId { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs
index 73e33d78c1..953d186e84 100644
--- a/MediaBrowser.Controller/Session/SessionInfo.cs
+++ b/MediaBrowser.Controller/Session/SessionInfo.cs
@@ -119,12 +119,24 @@ namespace MediaBrowser.Controller.Session
/// The now playing item.
public BaseItem NowPlayingItem { get; set; }
+ ///
+ /// Gets or sets the now playing media version identifier.
+ ///
+ /// The now playing media version identifier.
+ public string NowPlayingMediaVersionId { get; set; }
+
+
+ ///
+ /// Gets or sets the now playing run time ticks.
+ ///
+ /// The now playing run time ticks.
+ public long? NowPlayingRunTimeTicks { get; set; }
+
///
/// Gets or sets the now playing position ticks.
///
/// The now playing position ticks.
public long? NowPlayingPositionTicks { get; set; }
-
///
/// Gets or sets a value indicating whether this instance is paused.
///
@@ -161,6 +173,18 @@ namespace MediaBrowser.Controller.Session
/// true if [supports fullscreen toggle]; otherwise, false.
public bool SupportsFullscreenToggle { get; set; }
+ ///
+ /// Gets or sets a value indicating whether [supports osd toggle].
+ ///
+ /// true if [supports osd toggle]; otherwise, false.
+ public bool SupportsOsdToggle { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether [supports navigation commands].
+ ///
+ /// true if [supports navigation commands]; otherwise, false.
+ public bool SupportsNavigationControl { get; set; }
+
///
/// Gets a value indicating whether this instance is active.
///
diff --git a/MediaBrowser.Dlna/PlayTo/DlnaController.cs b/MediaBrowser.Dlna/PlayTo/DlnaController.cs
index cb4bda1277..bda737ad2d 100644
--- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs
+++ b/MediaBrowser.Dlna/PlayTo/DlnaController.cs
@@ -69,12 +69,12 @@ namespace MediaBrowser.Dlna.PlayTo
_device.CurrentIdChanged += Device_CurrentIdChanged;
_device.Start();
- _updateTimer = new System.Threading.Timer(updateTimer_Elapsed, null, UpdateTimerIntervalMs, UpdateTimerIntervalMs);
+ _updateTimer = new Timer(updateTimer_Elapsed, null, UpdateTimerIntervalMs, UpdateTimerIntervalMs);
}
#region Device EventHandlers & Update Timer
- System.Threading.Timer _updateTimer;
+ Timer _updateTimer;
async void Device_PlaybackChanged(object sender, TransportStateEventArgs e)
{
@@ -88,7 +88,7 @@ namespace MediaBrowser.Dlna.PlayTo
{
_playbackStarted = false;
- await _sessionManager.OnPlaybackStopped(new PlaybackStopInfo
+ await _sessionManager.OnPlaybackStopped(new Controller.Session.PlaybackStopInfo
{
Item = _currentItem,
SessionId = _session.Id,
@@ -164,7 +164,7 @@ namespace MediaBrowser.Dlna.PlayTo
var playlistItem = Playlist.FirstOrDefault(p => p.PlayState == 1);
if (playlistItem != null && playlistItem.Transcode)
{
- await _sessionManager.OnPlaybackProgress(new PlaybackProgressInfo
+ await _sessionManager.OnPlaybackProgress(new Controller.Session.PlaybackProgressInfo
{
Item = _currentItem,
SessionId = _session.Id,
@@ -176,7 +176,7 @@ namespace MediaBrowser.Dlna.PlayTo
}
else if (_currentItem != null)
{
- await _sessionManager.OnPlaybackProgress(new PlaybackProgressInfo
+ await _sessionManager.OnPlaybackProgress(new Controller.Session.PlaybackProgressInfo
{
Item = _currentItem,
SessionId = _session.Id,
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index c46e355df7..960b0f6358 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -428,6 +428,9 @@
Session\MessageCommand.cs
+
+ Session\PlaybackReports.cs
+
Session\PlayRequest.cs
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index 7ef8912091..b010ad9c99 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -415,6 +415,9 @@
Session\MessageCommand.cs
+
+ Session\PlaybackReports.cs
+
Session\PlayRequest.cs
diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs
index 46d3dcc3f5..91ac67a1f7 100644
--- a/MediaBrowser.Model/ApiClient/IApiClient.cs
+++ b/MediaBrowser.Model/ApiClient/IApiClient.cs
@@ -538,35 +538,26 @@ namespace MediaBrowser.Model.ApiClient
///
/// Reports to the server that the user has begun playing an item
///
- /// The item id.
- /// The user id.
- /// if set to true [is seekable].
- /// The list of media types that the client is capable of queuing onto the playlist. See MediaType class.
+ /// The information.
/// Task{UserItemDataDto}.
/// itemId
- Task ReportPlaybackStartAsync(string itemId, string userId, bool isSeekable, List queueableMediaTypes);
+ Task ReportPlaybackStartAsync(PlaybackStartInfo info);
///
/// Reports playback progress to the server
///
- /// The item id.
- /// The user id.
- /// The position ticks.
- /// if set to true [is paused].
- /// if set to true [is muted].
+ /// The information.
/// Task{UserItemDataDto}.
/// itemId
- Task ReportPlaybackProgressAsync(string itemId, string userId, long? positionTicks, bool isPaused, bool isMuted);
+ Task ReportPlaybackProgressAsync(PlaybackProgressInfo info);
///
/// Reports to the server that the user has stopped playing an item
///
- /// The item id.
- /// The user id.
- /// The position ticks.
+ /// The information.
/// Task{UserItemDataDto}.
/// itemId
- Task ReportPlaybackStoppedAsync(string itemId, string userId, long? positionTicks);
+ Task ReportPlaybackStoppedAsync(PlaybackStopInfo info);
///
/// Instructs antoher client to browse to a library item.
diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index c2765754e9..1f304112f5 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -147,7 +147,7 @@ namespace MediaBrowser.Model.Configuration
/// different directories and files.
///
/// The file watcher delay.
- public int RealtimeWatcherDelay { get; set; }
+ public int RealtimeMonitorDelay { get; set; }
///
/// Gets or sets a value indicating whether [enable dashboard response caching].
@@ -239,7 +239,7 @@ namespace MediaBrowser.Model.Configuration
MaxResumePct = 90;
MinResumeDurationSeconds = Convert.ToInt32(TimeSpan.FromMinutes(5).TotalSeconds);
- RealtimeWatcherDelay = 20;
+ RealtimeMonitorDelay = 30;
RecentItemDays = 10;
diff --git a/MediaBrowser.Model/Dto/MediaVersionInfo.cs b/MediaBrowser.Model/Dto/MediaVersionInfo.cs
index 3da5e2b8da..c2e0d83b2b 100644
--- a/MediaBrowser.Model/Dto/MediaVersionInfo.cs
+++ b/MediaBrowser.Model/Dto/MediaVersionInfo.cs
@@ -5,7 +5,7 @@ namespace MediaBrowser.Model.Dto
{
public class MediaVersionInfo
{
- public string ItemId { get; set; }
+ public string Id { get; set; }
public string Path { get; set; }
@@ -23,8 +23,6 @@ namespace MediaBrowser.Model.Dto
public List MediaStreams { get; set; }
- public List Chapters { get; set; }
-
public bool IsPrimaryVersion { get; set; }
}
}
diff --git a/MediaBrowser.Model/Entities/BaseItemInfo.cs b/MediaBrowser.Model/Entities/BaseItemInfo.cs
index b704bdb57c..0fac979490 100644
--- a/MediaBrowser.Model/Entities/BaseItemInfo.cs
+++ b/MediaBrowser.Model/Entities/BaseItemInfo.cs
@@ -69,6 +69,12 @@ namespace MediaBrowser.Model.Entities
///
/// The thumb item identifier.
public string BackdropItemId { get; set; }
+
+ ///
+ /// Gets or sets the media version identifier.
+ ///
+ /// The media version identifier.
+ public string MediaVersionId { get; set; }
///
/// Gets a value indicating whether this instance has primary image.
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 6a7e723a79..5e9b97939a 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -132,6 +132,7 @@
+
diff --git a/MediaBrowser.Model/Session/PlaybackReports.cs b/MediaBrowser.Model/Session/PlaybackReports.cs
new file mode 100644
index 0000000000..662dc57805
--- /dev/null
+++ b/MediaBrowser.Model/Session/PlaybackReports.cs
@@ -0,0 +1,56 @@
+
+namespace MediaBrowser.Model.Session
+{
+ ///
+ /// Class PlaybackStartInfo.
+ ///
+ public class PlaybackStartInfo
+ {
+ public string UserId { get; set; }
+
+ public string ItemId { get; set; }
+
+ public string MediaVersionId { get; set; }
+
+ public bool IsSeekable { get; set; }
+
+ public string[] QueueableMediaTypes { get; set; }
+
+ public PlaybackStartInfo()
+ {
+ QueueableMediaTypes = new string[] { };
+ }
+ }
+
+ ///
+ /// Class PlaybackProgressInfo.
+ ///
+ public class PlaybackProgressInfo
+ {
+ public string UserId { get; set; }
+
+ public string ItemId { get; set; }
+
+ public string MediaVersionId { get; set; }
+
+ public long? PositionTicks { get; set; }
+
+ public bool IsPaused { get; set; }
+
+ public bool IsMuted { get; set; }
+ }
+
+ ///
+ /// Class PlaybackStopInfo.
+ ///
+ public class PlaybackStopInfo
+ {
+ public string UserId { get; set; }
+
+ public string ItemId { get; set; }
+
+ public string MediaVersionId { get; set; }
+
+ public long? PositionTicks { get; set; }
+ }
+}
diff --git a/MediaBrowser.Model/Session/SessionCapabilities.cs b/MediaBrowser.Model/Session/SessionCapabilities.cs
index 731ebacccf..7b3b04ce92 100644
--- a/MediaBrowser.Model/Session/SessionCapabilities.cs
+++ b/MediaBrowser.Model/Session/SessionCapabilities.cs
@@ -7,6 +7,10 @@ namespace MediaBrowser.Model.Session
public bool SupportsFullscreenToggle { get; set; }
+ public bool SupportsOsdToggle { get; set; }
+
+ public bool SupportsNavigationControl { get; set; }
+
public SessionCapabilities()
{
PlayableMediaTypes = new string[] {};
diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs
index d44bbeaeb5..09a8375d81 100644
--- a/MediaBrowser.Model/Session/SessionInfoDto.cs
+++ b/MediaBrowser.Model/Session/SessionInfoDto.cs
@@ -1,8 +1,8 @@
-using System.Diagnostics;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
+using System.Diagnostics;
namespace MediaBrowser.Model.Session
{
@@ -147,6 +147,18 @@ namespace MediaBrowser.Model.Session
/// true if [supports remote control]; otherwise, false.
public bool SupportsRemoteControl { get; set; }
+ ///
+ /// Gets or sets a value indicating whether [supports osd toggle].
+ ///
+ /// true if [supports osd toggle]; otherwise, false.
+ public bool SupportsOsdToggle { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether [supports navigation commands].
+ ///
+ /// true if [supports navigation commands]; otherwise, false.
+ public bool SupportsNavigationControl { get; set; }
+
public event PropertyChangedEventHandler PropertyChanged;
public SessionInfoDto()
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index c94cdda846..520b01af22 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -267,12 +267,14 @@ namespace MediaBrowser.Server.Implementations.Dto
PlayableMediaTypes = session.PlayableMediaTypes,
RemoteEndPoint = session.RemoteEndPoint,
AdditionalUsers = session.AdditionalUsers,
- SupportsFullscreenToggle = session.SupportsFullscreenToggle
+ SupportsFullscreenToggle = session.SupportsFullscreenToggle,
+ SupportsNavigationControl = session.SupportsNavigationControl,
+ SupportsOsdToggle = session.SupportsOsdToggle
};
if (session.NowPlayingItem != null)
{
- dto.NowPlayingItem = GetBaseItemInfo(session.NowPlayingItem);
+ dto.NowPlayingItem = GetNowPlayingInfo(session.NowPlayingItem, session.NowPlayingMediaVersionId, session.NowPlayingRunTimeTicks);
}
if (session.UserId.HasValue)
@@ -288,9 +290,11 @@ namespace MediaBrowser.Server.Implementations.Dto
/// Converts a BaseItem to a BaseItemInfo
///
/// The item.
+ /// The media version identifier.
+ /// The now playing runtime ticks.
/// BaseItemInfo.
/// item
- public BaseItemInfo GetBaseItemInfo(BaseItem item)
+ private BaseItemInfo GetNowPlayingInfo(BaseItem item, string mediaVersionId, long? nowPlayingRuntimeTicks)
{
if (item == null)
{
@@ -303,7 +307,8 @@ namespace MediaBrowser.Server.Implementations.Dto
Name = item.Name,
MediaType = item.MediaType,
Type = item.GetClientTypeName(),
- RunTimeTicks = item.RunTimeTicks
+ RunTimeTicks = nowPlayingRuntimeTicks,
+ MediaVersionId = mediaVersionId
};
info.PrimaryImageTag = GetImageCacheTag(item, ImageType.Primary);
@@ -1103,9 +1108,7 @@ namespace MediaBrowser.Server.Implementations.Dto
if (dto.MediaVersions != null && dto.MediaVersions.Count > 0)
{
- chapters = dto.MediaVersions.Where(i => i.IsPrimaryVersion)
- .SelectMany(i => i.Chapters)
- .ToList();
+ chapters = _itemRepo.GetChapters(item.Id).Select(c => GetChapterInfoDto(c, item)).ToList();
}
else
{
@@ -1292,24 +1295,25 @@ namespace MediaBrowser.Server.Implementations.Dto
private List GetMediaVersions(Audio item)
{
- var result = new List();
-
- result.Add(GetVersionInfo(item, true));
+ var result = new List
+ {
+ GetVersionInfo(item, true)
+ };
return result;
}
private MediaVersionInfo GetVersionInfo(Video i, bool isPrimary)
{
+ var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery {ItemId = i.Id}).ToList();
+
return new MediaVersionInfo
{
- Chapters = _itemRepo.GetChapters(i.Id).Select(c => GetChapterInfoDto(c, i)).ToList(),
-
- ItemId = i.Id.ToString("N"),
+ Id = i.Id.ToString("N"),
IsoType = i.IsoType,
LocationType = i.LocationType,
- MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(),
- Name = GetAlternateVersionName(i),
+ MediaStreams = mediaStreams,
+ Name = GetAlternateVersionName(i, mediaStreams),
Path = GetMappedPath(i),
RunTimeTicks = i.RunTimeTicks,
Video3DFormat = i.Video3DFormat,
@@ -1322,7 +1326,7 @@ namespace MediaBrowser.Server.Implementations.Dto
{
return new MediaVersionInfo
{
- ItemId = i.Id.ToString("N"),
+ Id = i.Id.ToString("N"),
LocationType = i.LocationType,
MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(),
Name = i.Name,
@@ -1351,32 +1355,29 @@ namespace MediaBrowser.Server.Implementations.Dto
return path;
}
- private string GetAlternateVersionName(Video video)
+ private string GetAlternateVersionName(Video video, List mediaStreams)
{
- var name = "";
+ var terms = new List();
- var videoStream = video.GetDefaultVideoStream();
+ var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
+ var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
if (video.Video3DFormat.HasValue)
{
- name = "3D " + name;
- name = name.Trim();
+ terms.Add("3D");
}
if (video.VideoType == VideoType.BluRay)
{
- name = name + " " + "Bluray";
- name = name.Trim();
+ terms.Add("Bluray");
}
else if (video.VideoType == VideoType.Dvd)
{
- name = name + " " + "DVD";
- name = name.Trim();
+ terms.Add("DVD");
}
else if (video.VideoType == VideoType.HdDvd)
{
- name = name + " " + "HD-DVD";
- name = name.Trim();
+ terms.Add("HD-DVD");
}
else if (video.VideoType == VideoType.Iso)
{
@@ -1384,18 +1385,17 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (video.IsoType.Value == IsoType.BluRay)
{
- name = name + " " + "Bluray";
+ terms.Add("Bluray");
}
else if (video.IsoType.Value == IsoType.Dvd)
{
- name = name + " " + "DVD";
+ terms.Add("DVD");
}
}
else
{
- name = name + " " + "ISO";
+ terms.Add("ISO");
}
- name = name.Trim();
}
if (videoStream != null)
@@ -1404,44 +1404,45 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (videoStream.Width.Value >= 3800)
{
- name = name + " " + "4K";
- name = name.Trim();
+ terms.Add("4K");
}
else if (videoStream.Width.Value >= 1900)
{
- name = name + " " + "1080P";
- name = name.Trim();
+ terms.Add("1080P");
}
else if (videoStream.Width.Value >= 1270)
{
- name = name + " " + "720P";
- name = name.Trim();
+ terms.Add("720P");
}
else if (videoStream.Width.Value >= 700)
{
- name = name + " " + "480p";
- name = name.Trim();
+ terms.Add("480P");
}
else
{
- name = name + " " + "SD";
- name = name.Trim();
+ terms.Add("SD");
}
}
}
if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
{
- name = name + " " + videoStream.Codec.ToUpper();
- name = name.Trim();
+ terms.Add(videoStream.Codec.ToUpper());
}
- if (string.IsNullOrWhiteSpace(name))
+ if (audioStream != null)
{
- return video.Name;
+ var audioCodec = string.Equals(audioStream.Codec, "dca", StringComparison.OrdinalIgnoreCase)
+ ? audioStream.Profile
+ : audioStream.Codec;
+
+ if (!string.IsNullOrEmpty(audioCodec))
+ {
+ terms.Add(audioCodec.ToUpper());
+ }
}
- return name;
+ return string.Join("/", terms.ToArray());
}
private string GetMappedPath(string path)
diff --git a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
index 65bbb35bac..0a0b3f4bcd 100644
--- a/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
+++ b/MediaBrowser.Server.Implementations/IO/LibraryMonitor.cs
@@ -427,11 +427,11 @@ namespace MediaBrowser.Server.Implementations.IO
{
if (_updateTimer == null)
{
- _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeWatcherDelay), TimeSpan.FromMilliseconds(-1));
+ _updateTimer = new Timer(TimerStopped, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
else
{
- _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeWatcherDelay), TimeSpan.FromMilliseconds(-1));
+ _updateTimer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.RealtimeMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Roku/RokuControllerFactory.cs b/MediaBrowser.Server.Implementations/Roku/RokuControllerFactory.cs
index 71f70421a9..53f28e7ae7 100644
--- a/MediaBrowser.Server.Implementations/Roku/RokuControllerFactory.cs
+++ b/MediaBrowser.Server.Implementations/Roku/RokuControllerFactory.cs
@@ -1,8 +1,10 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Serialization;
using System;
+using System.Collections.Generic;
namespace MediaBrowser.Server.Implementations.Roku
{
@@ -23,6 +25,9 @@ namespace MediaBrowser.Server.Implementations.Roku
{
if (string.Equals(session.Client, "roku", StringComparison.OrdinalIgnoreCase))
{
+ session.PlayableMediaTypes = new List { MediaType.Video, MediaType.Audio };
+ session.SupportsFullscreenToggle = false;
+
return new RokuSessionController(_httpClient, _json, _appHost, session);
}
diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
index 1fb5af127c..c895062617 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs
@@ -218,15 +218,29 @@ namespace MediaBrowser.Server.Implementations.Session
///
/// The session.
/// The item.
+ /// The media version identifier.
/// if set to true [is paused].
+ /// if set to true [is muted].
/// The current position ticks.
- private void UpdateNowPlayingItem(SessionInfo session, BaseItem item, bool isPaused, bool isMuted, long? currentPositionTicks = null)
+ private void UpdateNowPlayingItem(SessionInfo session, BaseItem item, string mediaVersionId, bool isPaused, bool isMuted, long? currentPositionTicks = null)
{
session.IsMuted = isMuted;
session.IsPaused = isPaused;
session.NowPlayingPositionTicks = currentPositionTicks;
session.NowPlayingItem = item;
session.LastActivityDate = DateTime.UtcNow;
+ session.NowPlayingMediaVersionId = mediaVersionId;
+
+ if (string.IsNullOrWhiteSpace(mediaVersionId))
+ {
+ session.NowPlayingRunTimeTicks = item.RunTimeTicks;
+ }
+ else
+ {
+ var version = _libraryManager.GetItemById(new Guid(mediaVersionId));
+
+ session.NowPlayingRunTimeTicks = version.RunTimeTicks;
+ }
}
///
@@ -246,6 +260,8 @@ namespace MediaBrowser.Server.Implementations.Session
session.NowPlayingItem = null;
session.NowPlayingPositionTicks = null;
session.IsPaused = false;
+ session.NowPlayingRunTimeTicks = null;
+ session.NowPlayingMediaVersionId = null;
}
}
@@ -352,7 +368,9 @@ namespace MediaBrowser.Server.Implementations.Session
var item = info.Item;
- UpdateNowPlayingItem(session, item, false, false);
+ var mediaVersionId = GetMediaVersionId(item, info.MediaVersionId);
+
+ UpdateNowPlayingItem(session, item, mediaVersionId, false, false);
session.CanSeek = info.CanSeek;
session.QueueableMediaTypes = info.QueueableMediaTypes;
@@ -371,7 +389,8 @@ namespace MediaBrowser.Server.Implementations.Session
EventHelper.QueueEventIfNotNull(PlaybackStart, this, new PlaybackProgressEventArgs
{
Item = item,
- Users = users
+ Users = users,
+ MediaVersionId = info.MediaVersionId
}, _logger);
}
@@ -405,7 +424,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// Task.
///
/// positionTicks
- public async Task OnPlaybackProgress(PlaybackProgressInfo info)
+ public async Task OnPlaybackProgress(Controller.Session.PlaybackProgressInfo info)
{
if (info == null)
{
@@ -419,7 +438,9 @@ namespace MediaBrowser.Server.Implementations.Session
var session = Sessions.First(i => i.Id.Equals(info.SessionId));
- UpdateNowPlayingItem(session, info.Item, info.IsPaused, info.IsMuted, info.PositionTicks);
+ var mediaVersionId = GetMediaVersionId(info.Item, info.MediaVersionId);
+
+ UpdateNowPlayingItem(session, info.Item, mediaVersionId, info.IsPaused, info.IsMuted, info.PositionTicks);
var key = info.Item.GetUserDataKey();
@@ -434,7 +455,8 @@ namespace MediaBrowser.Server.Implementations.Session
{
Item = info.Item,
Users = users,
- PlaybackPositionTicks = info.PositionTicks
+ PlaybackPositionTicks = info.PositionTicks,
+ MediaVersionId = mediaVersionId
}, _logger);
}
@@ -458,7 +480,7 @@ namespace MediaBrowser.Server.Implementations.Session
/// Task.
/// info
/// positionTicks
- public async Task OnPlaybackStopped(PlaybackStopInfo info)
+ public async Task OnPlaybackStopped(Controller.Session.PlaybackStopInfo info)
{
if (info == null)
{
@@ -494,16 +516,32 @@ namespace MediaBrowser.Server.Implementations.Session
playedToCompletion = await OnPlaybackStopped(user.Id, key, info.Item, info.PositionTicks).ConfigureAwait(false);
}
+ var mediaVersionId = GetMediaVersionId(info.Item, info.MediaVersionId);
+
EventHelper.QueueEventIfNotNull(PlaybackStopped, this, new PlaybackStopEventArgs
{
Item = info.Item,
Users = users,
PlaybackPositionTicks = info.PositionTicks,
- PlayedToCompletion = playedToCompletion
+ PlayedToCompletion = playedToCompletion,
+ MediaVersionId = mediaVersionId
}, _logger);
}
+ private string GetMediaVersionId(BaseItem item, string reportedMediaVersionId)
+ {
+ if (string.IsNullOrWhiteSpace(reportedMediaVersionId))
+ {
+ if (item is Video || item is Audio)
+ {
+ reportedMediaVersionId = item.Id.ToString("N");
+ }
+ }
+
+ return reportedMediaVersionId;
+ }
+
private async Task OnPlaybackStopped(Guid userId, string userDataKey, BaseItem item, long? positionTicks)
{
var data = _userDataRepository.GetUserData(userId, userDataKey);
@@ -899,6 +937,8 @@ namespace MediaBrowser.Server.Implementations.Session
session.PlayableMediaTypes = capabilities.PlayableMediaTypes.ToList();
session.SupportsFullscreenToggle = capabilities.SupportsFullscreenToggle;
+ session.SupportsOsdToggle = capabilities.SupportsOsdToggle;
+ session.SupportsNavigationControl = capabilities.SupportsNavigationControl;
}
}
}
\ No newline at end of file
diff --git a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
index e5fbc7d9fa..5c4c00e7d2 100644
--- a/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
+++ b/MediaBrowser.Server.Implementations/Session/SessionWebSocketListener.cs
@@ -223,6 +223,11 @@ namespace MediaBrowser.Server.Implementations.Session
QueueableMediaTypes = queueableMediaTypes.Split(',').ToList()
};
+ if (vals.Length > 3)
+ {
+ info.MediaVersionId = vals[3];
+ }
+
_sessionManager.OnPlaybackStart(info);
}
}
@@ -265,6 +270,11 @@ namespace MediaBrowser.Server.Implementations.Session
SessionId = session.Id
};
+ if (vals.Length > 4)
+ {
+ info.MediaVersionId = vals[4];
+ }
+
_sessionManager.OnPlaybackProgress(info);
}
}
@@ -304,6 +314,11 @@ namespace MediaBrowser.Server.Implementations.Session
SessionId = session.Id
};
+ if (vals.Length > 2)
+ {
+ info.MediaVersionId = vals[2];
+ }
+
_sessionManager.OnPlaybackStopped(info);
}
}
diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js
index 97c26ec78a..47719df8d2 100644
--- a/MediaBrowser.WebDashboard/ApiClient.js
+++ b/MediaBrowser.WebDashboard/ApiClient.js
@@ -2191,20 +2191,6 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
});
};
- /**
- * Gets a list of all available conrete BaseItem types from the server
- */
- self.getItemTypes = function (options) {
-
- var url = self.getUrl("Library/ItemTypes", options);
-
- return self.ajax({
- type: "GET",
- url: url,
- dataType: "json"
- });
- };
-
/**
* Constructs a url for a user image
* @param {String} userId
@@ -3805,7 +3791,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
* @param {String} userId
* @param {String} itemId
*/
- self.reportPlaybackStart = function (userId, itemId, canSeek, queueableMediaTypes) {
+ self.reportPlaybackStart = function (userId, itemId, mediaVersionId, canSeek, queueableMediaTypes) {
if (!userId) {
throw new Error("null userId");
@@ -3823,6 +3809,10 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
var deferred = $.Deferred();
var msg = [itemId, canSeek, queueableMediaTypes];
+
+ if (mediaVersionId) {
+ msg.push(mediaVersionId);
+ }
self.sendWebSocketMessage("PlaybackStart", msg.join('|'));
@@ -3830,10 +3820,16 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
return deferred.promise();
}
- var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId, {
+ var params = {
CanSeek: canSeek,
QueueableMediaTypes: queueableMediaTypes
- });
+ };
+
+ if (mediaVersionId) {
+ params.mediaVersionId = mediaVersionId;
+ }
+
+ var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId, params);
return self.ajax({
type: "POST",
@@ -3846,7 +3842,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
* @param {String} userId
* @param {String} itemId
*/
- self.reportPlaybackProgress = function (userId, itemId, positionTicks, isPaused, isMuted) {
+ self.reportPlaybackProgress = function (userId, itemId, mediaVersionId, positionTicks, isPaused, isMuted) {
if (!userId) {
throw new Error("null userId");
@@ -3860,7 +3856,12 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
var deferred = $.Deferred();
- var msgData = itemId + "|" + (positionTicks == null ? "" : positionTicks) + "|" + (isPaused == null ? "" : isPaused) + "|" + (isMuted == null ? "" : isMuted);
+ var msgData = itemId;
+
+ msgData += "|" + (positionTicks == null ? "" : positionTicks);
+ msgData += "|" + (isPaused == null ? "" : isPaused);
+ msgData += "|" + (isMuted == null ? "" : isMuted);
+ msgData += "|" + (mediaVersionId == null ? "" : mediaVersionId);
self.sendWebSocketMessage("PlaybackProgress", msgData);
@@ -3877,6 +3878,10 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
params.positionTicks = positionTicks;
}
+ if (mediaVersionId) {
+ params.mediaVersionId = mediaVersionId;
+ }
+
var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId + "/Progress", params);
return self.ajax({
@@ -3890,7 +3895,7 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
* @param {String} userId
* @param {String} itemId
*/
- self.reportPlaybackStopped = function (userId, itemId, positionTicks) {
+ self.reportPlaybackStopped = function (userId, itemId, mediaVersionId, positionTicks) {
if (!userId) {
throw new Error("null userId");
@@ -3904,20 +3909,26 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
var deferred = $.Deferred();
- self.sendWebSocketMessage("PlaybackStopped", itemId + "|" + (positionTicks == null ? "" : positionTicks));
+ var msg = itemId;
+ msg += "|" + (positionTicks == null ? "" : positionTicks);
+ msg += "|" + (mediaVersionId == null ? "" : mediaVersionId);
+
+ self.sendWebSocketMessage("PlaybackStopped", msg);
deferred.resolveWith(null, []);
return deferred.promise();
}
- var params = {
-
- };
+ var params = {};
if (positionTicks) {
params.positionTicks = positionTicks;
}
+ if (mediaVersionId) {
+ params.mediaVersionId = mediaVersionId;
+ }
+
var url = self.getUrl("Users/" + userId + "/PlayingItems/" + itemId, params);
return self.ajax({
diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
index 16eec26408..a0dbae3d4c 100644
--- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
+++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj
@@ -84,9 +84,7 @@
-
- PreserveNewest
-
+
PreserveNewest
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 0bdea523e3..bbc2c0f068 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file