diff --git a/MediaBrowser.Api/Movies/CollectionService.cs b/MediaBrowser.Api/Movies/CollectionService.cs index 456449b7b6..f09992e00f 100644 --- a/MediaBrowser.Api/Movies/CollectionService.cs +++ b/MediaBrowser.Api/Movies/CollectionService.cs @@ -6,8 +6,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Api.Movies { - [Route("/Collections", "POST")] - [Api(Description = "Creates a new collection")] + [Route("/Collections", "POST", Summary = "Creates a new collection")] public class CreateCollection : IReturnVoid { [ApiMember(Name = "IsLocked", Description = "Whether or not to lock the new collection.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] @@ -20,8 +19,7 @@ namespace MediaBrowser.Api.Movies public Guid? ParentId { get; set; } } - [Route("/Collections/{Id}/Items", "POST")] - [Api(Description = "Adds items to a collection")] + [Route("/Collections/{Id}/Items", "POST", Summary = "Adds items to a collection")] public class AddToCollection : IReturnVoid { [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] @@ -31,8 +29,7 @@ namespace MediaBrowser.Api.Movies public Guid Id { get; set; } } - [Route("/Collections/{Id}/Items", "DELETE")] - [Api(Description = "Removes items from a collection")] + [Route("/Collections/{Id}/Items", "DELETE", Summary = "Removes items from a collection")] public class RemoveFromCollection : IReturnVoid { [ApiMember(Name = "Ids", Description = "Item id, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")] diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index df35c93a02..9ed9bd49e2 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -210,6 +210,9 @@ namespace MediaBrowser.Api [ApiMember(Name = "PlayableMediaTypes", Description = "A list of playable media types, comma delimited. Audio, Video, Book, Game, Photo.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")] public string PlayableMediaTypes { get; set; } + + [ApiMember(Name = "SupportsFullscreenToggle", Description = "Whether or not the session supports fullscreen toggle", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "POST")] + public bool SupportsFullscreenToggle { get; set; } } /// @@ -361,11 +364,12 @@ namespace MediaBrowser.Api public void Post(PostCapabilities request) { - var session = _sessionManager.Sessions.First(i => i.Id == request.Id); + _sessionManager.ReportCapabilities(request.Id, new SessionCapabilities + { + PlayableMediaTypes = request.PlayableMediaTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries), - session.PlayableMediaTypes = request.PlayableMediaTypes - .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) - .ToList(); + SupportsFullscreenToggle = request.SupportsFullscreenToggle + }); } private SessionInfo GetSession() diff --git a/MediaBrowser.Api/VideosService.cs b/MediaBrowser.Api/VideosService.cs index f7f864d7e5..fa4b22cea7 100644 --- a/MediaBrowser.Api/VideosService.cs +++ b/MediaBrowser.Api/VideosService.cs @@ -4,12 +4,9 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using ServiceStack; using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -31,18 +28,6 @@ namespace MediaBrowser.Api public string Id { get; set; } } - [Route("/Videos/{Id}/Versions", "GET")] - [Api(Description = "Gets all versions of a video.")] - public class GetMediaVersions : IReturn> - { - /// - /// Gets or sets the id. - /// - /// The id. - [ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")] - public string Id { get; set; } - } - [Route("/Videos/{Id}/AlternateVersions", "DELETE")] [Api(Description = "Assigns videos as alternates of antoher.")] public class DeleteAlternateVersions : IReturnVoid @@ -113,169 +98,6 @@ namespace MediaBrowser.Api return ToOptimizedSerializedResultUsingCache(result); } - public object Get(GetMediaVersions request) - { - var item = _libraryManager.GetItemById(new Guid(request.Id)); - - var video = (Video)item; - - var result = video.GetAlternateVersions().Select(GetVersionInfo).ToList(); - - result.Add(GetVersionInfo(video)); - - result = result.OrderBy(i => - { - if (video.VideoType == VideoType.VideoFile) - { - return 0; - } - - return 1; - - }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) - .ThenByDescending(i => - { - var stream = i.MediaStreams.FirstOrDefault(m => m.Type == MediaStreamType.Video); - - return stream == null || stream.Width == null ? 0 : stream.Width.Value; - }) - .ToList(); - - return ToOptimizedSerializedResultUsingCache(result); - } - - private MediaVersionInfo GetVersionInfo(Video i) - { - return new MediaVersionInfo - { - Chapters = _itemRepo.GetChapters(i.Id).Select(c => _dtoService.GetChapterInfoDto(c, i)).ToList(), - - Id = i.Id.ToString("N"), - IsoType = i.IsoType, - LocationType = i.LocationType, - MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery {ItemId = i.Id}).ToList(), - Name = GetAlternateVersionName(i), - Path = GetMappedPath(i), - RunTimeTicks = i.RunTimeTicks, - Video3DFormat = i.Video3DFormat, - VideoType = i.VideoType - }; - } - - private string GetMappedPath(Video video) - { - var path = video.Path; - - var locationType = video.LocationType; - - if (locationType != LocationType.FileSystem && locationType != LocationType.Offline) - { - return path; - } - - foreach (var map in _config.Configuration.PathSubstitutions) - { - path = _fileSystem.SubstitutePath(path, map.From, map.To); - } - - return path; - } - - private string GetAlternateVersionName(Video video) - { - var name = ""; - - var stream = video.GetDefaultVideoStream(); - - if (video.Video3DFormat.HasValue) - { - name = "3D " + name; - name = name.Trim(); - } - - if (video.VideoType == VideoType.BluRay) - { - name = name + " " + "Bluray"; - name = name.Trim(); - } - else if (video.VideoType == VideoType.Dvd) - { - name = name + " " + "DVD"; - name = name.Trim(); - } - else if (video.VideoType == VideoType.HdDvd) - { - name = name + " " + "HD-DVD"; - name = name.Trim(); - } - else if (video.VideoType == VideoType.Iso) - { - if (video.IsoType.HasValue) - { - if (video.IsoType.Value == IsoType.BluRay) - { - name = name + " " + "Bluray"; - } - else if (video.IsoType.Value == IsoType.Dvd) - { - name = name + " " + "DVD"; - } - } - else - { - name = name + " " + "ISO"; - } - name = name.Trim(); - } - else if (video.VideoType == VideoType.VideoFile) - { - if (stream != null) - { - if (stream.Width.HasValue) - { - if (stream.Width.Value >= 3800) - { - name = name + " " + "4K"; - name = name.Trim(); - } - else if (stream.Width.Value >= 1900) - { - name = name + " " + "1080P"; - name = name.Trim(); - } - else if (stream.Width.Value >= 1270) - { - name = name + " " + "720P"; - name = name.Trim(); - } - else if (stream.Width.Value >= 700) - { - name = name + " " + "480p"; - name = name.Trim(); - } - else - { - name = name + " " + "SD"; - name = name.Trim(); - } - } - } - } - - if (stream != null && !string.IsNullOrWhiteSpace(stream.Codec)) - { - name = name + " " + stream.Codec.ToUpper(); - name = name.Trim(); - } - - if (string.IsNullOrWhiteSpace(name)) - { - return video.Name; - } - - return name; - } - public void Delete(DeleteAlternateVersions request) { var task = RemoveAlternateVersions(request); diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 2a09536c03..b3d73dc34a 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -90,7 +90,9 @@ namespace MediaBrowser.Controller.Entities if (!string.IsNullOrWhiteSpace(key)) { - return key + "-trailer"; + key = key + "-trailer"; + + return key; } return base.GetUserDataKey(); diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index 6ca15585ad..459e43d081 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -180,5 +180,12 @@ namespace MediaBrowser.Controller.Session /// The remote end point. /// Task{SessionInfo}. Task AuthenticateNewSession(User user, string password, string clientType, string appVersion, string deviceId, string deviceName, string remoteEndPoint); + + /// + /// Reports the capabilities. + /// + /// The session identifier. + /// The capabilities. + void ReportCapabilities(Guid sessionId, SessionCapabilities capabilities); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Session/SessionInfo.cs b/MediaBrowser.Controller/Session/SessionInfo.cs index f84204d11b..73e33d78c1 100644 --- a/MediaBrowser.Controller/Session/SessionInfo.cs +++ b/MediaBrowser.Controller/Session/SessionInfo.cs @@ -155,6 +155,12 @@ namespace MediaBrowser.Controller.Session /// The session controller. public ISessionController SessionController { get; set; } + /// + /// Gets or sets a value indicating whether [supports fullscreen toggle]. + /// + /// true if [supports fullscreen toggle]; otherwise, false. + public bool SupportsFullscreenToggle { 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 4180154a40..cb4bda1277 100644 --- a/MediaBrowser.Dlna/PlayTo/DlnaController.cs +++ b/MediaBrowser.Dlna/PlayTo/DlnaController.cs @@ -13,7 +13,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Timers; namespace MediaBrowser.Dlna.PlayTo { @@ -32,7 +31,7 @@ namespace MediaBrowser.Dlna.PlayTo private readonly IServerApplicationHost _appHost; private bool _playbackStarted = false; - private int UpdateTimerIntervalMs = 1000; + private const int UpdateTimerIntervalMs = 1000; public bool SupportsMediaRemoteControl { diff --git a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs index d18ed595f8..d02da303b6 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToManager.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToManager.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Dlna; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; using System.Collections.Concurrent; @@ -15,6 +16,7 @@ using System.Net.Sockets; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Model.Session; namespace MediaBrowser.Dlna.PlayTo { @@ -226,6 +228,12 @@ namespace MediaBrowser.Dlna.PlayTo var sessionInfo = await _sessionManager.LogSessionActivity(device.Properties.ClientType, device.Properties.Name, device.Properties.UUID, device.Properties.DisplayName, uri.OriginalString, null) .ConfigureAwait(false); + _sessionManager.ReportCapabilities(sessionInfo.Id, new SessionCapabilities + { + PlayableMediaTypes = new[] { MediaType.Audio, MediaType.Video, MediaType.Photo }, + SupportsFullscreenToggle = false + }); + var controller = sessionInfo.SessionController as PlayToController; if (controller == null) diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 2b32dc1d83..c46e355df7 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -434,6 +434,9 @@ Session\PlaystateCommand.cs + + Session\SessionCapabilities.cs + Session\SessionInfoDto.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index baf1fc4514..7ef8912091 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -421,6 +421,9 @@ Session\PlaystateCommand.cs + + Session\SessionCapabilities.cs + Session\SessionInfoDto.cs diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index aba7e217e2..379e757bb6 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -500,7 +500,7 @@ namespace MediaBrowser.Model.Dto /// /// The part count. public int? PartCount { get; set; } - public int? AlternateVersionCount { get; set; } + public int? MediaVersionCount { get; set; } /// /// Determines whether the specified type is type. diff --git a/MediaBrowser.Model/Dto/MediaVersionInfo.cs b/MediaBrowser.Model/Dto/MediaVersionInfo.cs index dfbf81416f..3da5e2b8da 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 Id { get; set; } + public string ItemId { get; set; } public string Path { get; set; } @@ -24,5 +24,7 @@ namespace MediaBrowser.Model.Dto public List MediaStreams { get; set; } public List Chapters { get; set; } + + public bool IsPrimaryVersion { get; set; } } } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 12a4625897..6a7e723a79 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -166,6 +166,7 @@ + diff --git a/MediaBrowser.Model/Session/BrowseRequest.cs b/MediaBrowser.Model/Session/BrowseRequest.cs index e2cdcc1b28..bcf72e1431 100644 --- a/MediaBrowser.Model/Session/BrowseRequest.cs +++ b/MediaBrowser.Model/Session/BrowseRequest.cs @@ -32,12 +32,4 @@ namespace MediaBrowser.Model.Session /// The context. public string Context { get; set; } } - - public class ItemContext - { - public const string Music = "Music"; - public const string Movies = "Movies"; - public const string TvShows = "TvShows"; - public const string Games = "Games"; - } } \ No newline at end of file diff --git a/MediaBrowser.Model/Session/SessionCapabilities.cs b/MediaBrowser.Model/Session/SessionCapabilities.cs new file mode 100644 index 0000000000..731ebacccf --- /dev/null +++ b/MediaBrowser.Model/Session/SessionCapabilities.cs @@ -0,0 +1,15 @@ + +namespace MediaBrowser.Model.Session +{ + public class SessionCapabilities + { + public string[] PlayableMediaTypes { get; set; } + + public bool SupportsFullscreenToggle { get; set; } + + public SessionCapabilities() + { + PlayableMediaTypes = new string[] {}; + } + } +} diff --git a/MediaBrowser.Model/Session/SessionInfoDto.cs b/MediaBrowser.Model/Session/SessionInfoDto.cs index 083d1ef79e..d44bbeaeb5 100644 --- a/MediaBrowser.Model/Session/SessionInfoDto.cs +++ b/MediaBrowser.Model/Session/SessionInfoDto.cs @@ -135,6 +135,12 @@ namespace MediaBrowser.Model.Session /// The device id. public string DeviceId { get; set; } + /// + /// Gets or sets a value indicating whether [supports fullscreen toggle]. + /// + /// true if [supports fullscreen toggle]; otherwise, false. + public bool SupportsFullscreenToggle { get; set; } + /// /// Gets or sets a value indicating whether [supports remote control]. /// diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index c03f327edc..f6753fc007 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -266,7 +266,8 @@ namespace MediaBrowser.Server.Implementations.Dto QueueableMediaTypes = session.QueueableMediaTypes, PlayableMediaTypes = session.PlayableMediaTypes, RemoteEndPoint = session.RemoteEndPoint, - AdditionalUsers = session.AdditionalUsers + AdditionalUsers = session.AdditionalUsers, + SupportsFullscreenToggle = session.SupportsFullscreenToggle }; if (session.NowPlayingItem != null) @@ -1052,6 +1053,9 @@ namespace MediaBrowser.Server.Implementations.Dto dto.AlbumPrimaryImageTag = GetImageCacheTag(albumParent, ImageType.Primary); } + + dto.MediaVersions = GetMediaVersions(audio); + dto.MediaVersionCount = 1; } var album = item as MusicAlbum; @@ -1082,16 +1086,31 @@ namespace MediaBrowser.Server.Implementations.Dto dto.IsHD = video.IsHD; dto.PartCount = video.AdditionalPartIds.Count + 1; - dto.AlternateVersionCount = video.AlternateVersionCount; - - if (fields.Contains(ItemFields.Chapters)) - { - dto.Chapters = _itemRepo.GetChapters(video.Id).Select(c => GetChapterInfoDto(c, item)).ToList(); - } + dto.MediaVersionCount = video.AlternateVersionCount + 1; if (fields.Contains(ItemFields.MediaVersions)) { - //dto.MediaVersions = GetMediaVersions(video); + dto.MediaVersions = GetMediaVersions(video); + } + + if (fields.Contains(ItemFields.Chapters)) + { + List chapters; + + if (dto.MediaVersions != null && dto.MediaVersions.Count > 0) + { + chapters = dto.MediaVersions.Where(i => i.IsPrimaryVersion) + .SelectMany(i => i.Chapters) + .ToList(); + } + else + { + chapters = _itemRepo.GetChapters(video.Id) + .Select(c => GetChapterInfoDto(c, item)) + .ToList(); + } + + dto.Chapters = chapters; } } @@ -1102,11 +1121,24 @@ namespace MediaBrowser.Server.Implementations.Dto if (iHasMediaStreams != null) { - dto.MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery - { - ItemId = item.Id + List mediaStreams; - }).ToList(); + if (dto.MediaVersions != null && dto.MediaVersions.Count > 0) + { + mediaStreams = dto.MediaVersions.Where(i => i.IsPrimaryVersion) + .SelectMany(i => i.MediaStreams) + .ToList(); + } + else + { + mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery + { + ItemId = item.Id + + }).ToList(); + } + + dto.MediaStreams = mediaStreams; } } @@ -1228,15 +1260,15 @@ namespace MediaBrowser.Server.Implementations.Dto } } - private List GetMediaVersions(Video video) + private List GetMediaVersions(Video item) { - var result = video.GetAlternateVersions().Select(GetVersionInfo).ToList(); + var result = item.GetAlternateVersions().Select(i => GetVersionInfo(i, false)).ToList(); - result.Add(GetVersionInfo(video)); + result.Add(GetVersionInfo(item, true)); return result.OrderBy(i => { - if (video.VideoType == VideoType.VideoFile) + if (item.VideoType == VideoType.VideoFile) { return 0; } @@ -1250,16 +1282,26 @@ namespace MediaBrowser.Server.Implementations.Dto return stream == null || stream.Width == null ? 0 : stream.Width.Value; }) + .ThenBy(i => i.IsPrimaryVersion ? 0 : 1) .ToList(); } - private MediaVersionInfo GetVersionInfo(Video i) + private List GetMediaVersions(Audio item) + { + var result = new List(); + + result.Add(GetVersionInfo(item, true)); + + return result; + } + + private MediaVersionInfo GetVersionInfo(Video i, bool isPrimary) { return new MediaVersionInfo { Chapters = _itemRepo.GetChapters(i.Id).Select(c => GetChapterInfoDto(c, i)).ToList(), - Id = i.Id.ToString("N"), + ItemId = i.Id.ToString("N"), IsoType = i.IsoType, LocationType = i.LocationType, MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(), @@ -1267,15 +1309,30 @@ namespace MediaBrowser.Server.Implementations.Dto Path = GetMappedPath(i), RunTimeTicks = i.RunTimeTicks, Video3DFormat = i.Video3DFormat, - VideoType = i.VideoType + VideoType = i.VideoType, + IsPrimaryVersion = isPrimary }; } - private string GetMappedPath(Video video) + private MediaVersionInfo GetVersionInfo(Audio i, bool isPrimary) { - var path = video.Path; + return new MediaVersionInfo + { + ItemId = i.Id.ToString("N"), + LocationType = i.LocationType, + MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(), + Name = i.Name, + Path = GetMappedPath(i), + RunTimeTicks = i.RunTimeTicks, + IsPrimaryVersion = isPrimary + }; + } - var locationType = video.LocationType; + private string GetMappedPath(IHasMetadata item) + { + var path = item.Path; + + var locationType = item.LocationType; if (locationType != LocationType.FileSystem && locationType != LocationType.Offline) { diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 3acc5e892c..1fb5af127c 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -887,5 +887,18 @@ namespace MediaBrowser.Server.Implementations.Session return await LogSessionActivity(clientType, appVersion, deviceId, deviceName, remoteEndPoint, user).ConfigureAwait(false); } + + /// + /// Reports the capabilities. + /// + /// The session identifier. + /// The capabilities. + public void ReportCapabilities(Guid sessionId, SessionCapabilities capabilities) + { + var session = GetSession(sessionId); + + session.PlayableMediaTypes = capabilities.PlayableMediaTypes.ToList(); + session.SupportsFullscreenToggle = capabilities.SupportsFullscreenToggle; + } } } \ No newline at end of file