From 6bd18c6e72d1c4ba9c371d37411ebd918d8c6d9e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 16 Apr 2015 10:59:39 -0400 Subject: [PATCH] xbox one dlna fixes --- MediaBrowser.Api/Images/ImageService.cs | 28 +- .../ContentDirectory/ControlHandler.cs | 2 +- MediaBrowser.Dlna/Didl/DidlBuilder.cs | 50 +++- MediaBrowser.Dlna/MediaBrowser.Dlna.csproj | 5 +- MediaBrowser.Dlna/PlayTo/PlayToController.cs | 2 +- .../Profiles/DishHopperJoeyProfile.cs | 2 +- .../Profiles/PopcornHourProfile.cs | 23 +- .../Profiles/SonyBravia2010Profile.cs | 44 ++- .../Profiles/SonyBravia2011Profile.cs | 44 ++- .../Profiles/WindowsMediaCenterProfile.cs | 274 ------------------ MediaBrowser.Dlna/Profiles/XboxOneProfile.cs | 98 +++++-- .../Profiles/Xml/Dish Hopper-Joey.xml | 4 +- .../Profiles/Xml/Popcorn Hour.xml | 9 +- .../Profiles/Xml/Sony Bravia (2010).xml | 14 +- .../Profiles/Xml/Sony Bravia (2011).xml | 14 +- MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml | 26 +- MediaBrowser.Model/Dlna/StreamInfo.cs | 18 +- .../TV/TvdbSeriesProvider.cs | 24 +- .../Library/LibraryManager.cs | 6 + .../Photos/BaseDynamicImageProvider.cs | 22 +- SharedVersion.cs | 4 +- 21 files changed, 338 insertions(+), 375 deletions(-) delete mode 100644 MediaBrowser.Dlna/Profiles/WindowsMediaCenterProfile.cs diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index ec9b2571e1..7da11a405c 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -40,8 +40,8 @@ namespace MediaBrowser.Api.Images [Route("/Items/{Id}/Images/{Type}/{Index}", "GET")] [Route("/Items/{Id}/Images/{Type}", "HEAD")] [Route("/Items/{Id}/Images/{Type}/{Index}", "HEAD")] - [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "GET")] - [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}", "HEAD")] + [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}/{UnplayedCount}", "GET")] + [Route("/Items/{Id}/Images/{Type}/{Index}/{Tag}/{Format}/{MaxWidth}/{MaxHeight}/{PercentPlayed}/{UnplayedCount}", "HEAD")] public class GetItemImage : ImageRequest { /// @@ -511,6 +511,30 @@ namespace MediaBrowser.Api.Images /// public object GetImage(ImageRequest request, IHasImages item, bool isHeadRequest) { + if (request.PercentPlayed.HasValue) + { + if (request.PercentPlayed.Value <= 0) + { + request.PercentPlayed = null; + } + else if (request.PercentPlayed.Value >= 100) + { + request.PercentPlayed = null; + request.AddPlayedIndicator = true; + } + } + if (request.PercentPlayed.HasValue) + { + request.UnplayedCount = null; + } + if (request.UnplayedCount.HasValue) + { + if (request.UnplayedCount.Value <= 0) + { + request.UnplayedCount = null; + } + } + var imageInfo = GetImageInfo(request, item); if (imageInfo == null) diff --git a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs index abd649ad7b..3d7ae8cc4d 100644 --- a/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs +++ b/MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs @@ -58,7 +58,7 @@ namespace MediaBrowser.Dlna.ContentDirectory _profile = profile; _config = config; - _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager); + _didlBuilder = new DidlBuilder(profile, user, imageProcessor, serverAddress, accessToken, userDataManager, localization, mediaSourceManager, Logger); } protected override IEnumerable> GetResult(string methodName, Headers methodParams) diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs index 629b95f67e..52791822bb 100644 --- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs +++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs @@ -39,8 +39,9 @@ namespace MediaBrowser.Dlna.Didl private readonly IUserDataManager _userDataManager; private readonly ILocalizationManager _localization; private readonly IMediaSourceManager _mediaSourceManager; + private readonly ILogger _logger; - public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) + public DidlBuilder(DeviceProfile profile, User user, IImageProcessor imageProcessor, string serverAddress, string accessToken, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager, ILogger logger) { _profile = profile; _imageProcessor = imageProcessor; @@ -48,6 +49,7 @@ namespace MediaBrowser.Dlna.Didl _userDataManager = userDataManager; _localization = localization; _mediaSourceManager = mediaSourceManager; + _logger = logger; _accessToken = accessToken; _user = user; } @@ -127,7 +129,7 @@ namespace MediaBrowser.Dlna.Didl { var sources = _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList(); - streamInfo = new StreamBuilder(new NullLogger()).BuildVideoItem(new VideoOptions + streamInfo = new StreamBuilder(_logger).BuildVideoItem(new VideoOptions { ItemId = GetClientId(video), MediaSources = sources, @@ -780,19 +782,33 @@ namespace MediaBrowser.Dlna.Didl var result = element.OwnerDocument; var playbackPercentage = 0; + var unplayedCount = 0; if (item is Video) { var userData = _userDataManager.GetUserDataDto(item, _user); playbackPercentage = Convert.ToInt32(userData.PlayedPercentage ?? 0); - if (playbackPercentage >= 100) + if (playbackPercentage >= 100 || userData.Played) { - playbackPercentage = 0; + playbackPercentage = 100; + } + } + else if (item is Series || item is Season || item is BoxSet) + { + var userData = _userDataManager.GetUserDataDto(item, _user); + + if (userData.Played) + { + playbackPercentage = 100; + } + else + { + unplayedCount = userData.UnplayedItemCount ?? 0; } } - var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight, playbackPercentage, "jpg"); + var albumartUrlInfo = GetImageUrl(imageInfo, _profile.MaxAlbumArtWidth, _profile.MaxAlbumArtHeight, playbackPercentage, unplayedCount, "jpg"); var icon = result.CreateElement("upnp", "albumArtURI", NS_UPNP); var profile = result.CreateAttribute("dlna", "profileID", NS_DLNA); @@ -802,7 +818,7 @@ namespace MediaBrowser.Dlna.Didl element.AppendChild(icon); // TOOD: Remove these default values - var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, playbackPercentage, "jpg"); + var iconUrlInfo = GetImageUrl(imageInfo, _profile.MaxIconWidth ?? 48, _profile.MaxIconHeight ?? 48, playbackPercentage, unplayedCount, "jpg"); icon = result.CreateElement("upnp", "icon", NS_UPNP); icon.InnerText = iconUrlInfo.Url; element.AppendChild(icon); @@ -819,15 +835,15 @@ namespace MediaBrowser.Dlna.Didl } } - AddImageResElement(item, element, 160, 160, playbackPercentage, "jpg", "JPEG_TN"); + AddImageResElement(item, element, 160, 160, playbackPercentage, unplayedCount, "jpg", "JPEG_TN"); if (!_profile.EnableSingleAlbumArtLimit) { - AddImageResElement(item, element, 4096, 4096, playbackPercentage, "jpg", "JPEG_LRG"); - AddImageResElement(item, element, 1024, 768, playbackPercentage, "jpg", "JPEG_MED"); - AddImageResElement(item, element, 640, 480, playbackPercentage, "jpg", "JPEG_SM"); - AddImageResElement(item, element, 4096, 4096, playbackPercentage, "png", "PNG_LRG"); - AddImageResElement(item, element, 160, 160, playbackPercentage, "png", "PNG_TN"); + AddImageResElement(item, element, 4096, 4096, playbackPercentage, unplayedCount, "jpg", "JPEG_LRG"); + AddImageResElement(item, element, 1024, 768, playbackPercentage, unplayedCount, "jpg", "JPEG_MED"); + AddImageResElement(item, element, 640, 480, playbackPercentage, unplayedCount, "jpg", "JPEG_SM"); + AddImageResElement(item, element, 4096, 4096, playbackPercentage, unplayedCount, "png", "PNG_LRG"); + AddImageResElement(item, element, 160, 160, playbackPercentage, unplayedCount, "png", "PNG_TN"); } } @@ -852,6 +868,7 @@ namespace MediaBrowser.Dlna.Didl int maxWidth, int maxHeight, int playbackPercentage, + int unplayedCount, string format, string org_Pn) { @@ -864,7 +881,7 @@ namespace MediaBrowser.Dlna.Didl var result = element.OwnerDocument; - var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, playbackPercentage, format); + var albumartUrlInfo = GetImageUrl(imageInfo, maxWidth, maxHeight, playbackPercentage, unplayedCount, format); var res = result.CreateElement(string.Empty, "res", NS_DIDL); @@ -1005,9 +1022,9 @@ namespace MediaBrowser.Dlna.Didl return id; } - private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, int playbackPercentage, string format) + private ImageUrlInfo GetImageUrl(ImageDownloadInfo info, int maxWidth, int maxHeight, int playbackPercentage, int unplayedCount, string format) { - var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/{7}", + var url = string.Format("{0}/Items/{1}/Images/{2}/0/{3}/{4}/{5}/{6}/{7}/{8}", _serverAddress, info.ItemId, info.Type, @@ -1015,7 +1032,8 @@ namespace MediaBrowser.Dlna.Didl format, maxWidth.ToString(CultureInfo.InvariantCulture), maxHeight.ToString(CultureInfo.InvariantCulture), - playbackPercentage.ToString(CultureInfo.InvariantCulture) + playbackPercentage.ToString(CultureInfo.InvariantCulture), + unplayedCount.ToString(CultureInfo.InvariantCulture) ); var width = info.Width; diff --git a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj index 2f4d444188..0cbe363982 100644 --- a/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj +++ b/MediaBrowser.Dlna/MediaBrowser.Dlna.csproj @@ -94,7 +94,6 @@ - @@ -167,7 +166,9 @@ - + + Designer + diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs index 9df69b1157..66cdc51afe 100644 --- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs +++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs @@ -478,7 +478,7 @@ namespace MediaBrowser.Dlna.PlayTo playlistItem.StreamUrl = playlistItem.StreamInfo.ToDlnaUrl(_serverAddress, _accessToken); - var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager) + var itemXml = new DidlBuilder(profile, user, _imageProcessor, _serverAddress, _accessToken, _userDataManager, _localization, _mediaSourceManager, _logger) .GetItemDidl(item, null, _session.DeviceId, new Filter(), playlistItem.StreamInfo); playlistItem.Didl = itemXml; diff --git a/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs b/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs index 07936688d4..ab887a3bff 100644 --- a/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs +++ b/MediaBrowser.Dlna/Profiles/DishHopperJoeyProfile.cs @@ -95,6 +95,7 @@ namespace MediaBrowser.Dlna.Profiles new CodecProfile { Type = CodecType.Video, + Codec = "h264", Conditions = new [] { new ProfileCondition @@ -138,7 +139,6 @@ namespace MediaBrowser.Dlna.Profiles new CodecProfile { Type = CodecType.Video, - Codec = "mpeg2video", Conditions = new [] { new ProfileCondition diff --git a/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs b/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs index 6cf06d41ff..883af57d29 100644 --- a/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs +++ b/MediaBrowser.Dlna/Profiles/PopcornHourProfile.cs @@ -93,8 +93,10 @@ namespace MediaBrowser.Dlna.Profiles new CodecProfile { Type = CodecType.Video, + Codec="h264", Conditions = new [] { + new ProfileCondition(ProfileConditionType.EqualsAny, ProfileConditionValue.VideoProfile, "baseline|constrained baseline"), new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -120,10 +122,27 @@ namespace MediaBrowser.Dlna.Profiles new CodecProfile { Type = CodecType.Video, - Codec="h264", Conditions = new [] { - new ProfileCondition(ProfileConditionType.EqualsAny, ProfileConditionValue.VideoProfile, "baseline|constrained baseline") + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Width, + Value = "1920" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Height, + Value = "1080" + }, + new ProfileCondition + { + Condition = ProfileConditionType.NotEquals, + Property = ProfileConditionValue.IsAnamorphic, + Value = "true", + IsRequired = false + } } }, diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs index 6f175ccd6c..46549040f3 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2010Profile.cs @@ -209,6 +209,7 @@ namespace MediaBrowser.Dlna.Profiles new CodecProfile { Type = CodecType.Video, + Codec = "h264", Conditions = new [] { new ProfileCondition @@ -222,16 +223,7 @@ namespace MediaBrowser.Dlna.Profiles Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080" - } - } - }, - - new CodecProfile - { - Type = CodecType.Video, - Codec = "h264", - Conditions = new [] - { + }, new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -259,6 +251,18 @@ namespace MediaBrowser.Dlna.Profiles Codec = "mpeg2video", Conditions = new [] { + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Width, + Value = "1920" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Height, + Value = "1080" + }, new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -274,6 +278,26 @@ namespace MediaBrowser.Dlna.Profiles } }, + new CodecProfile + { + Type = CodecType.Video, + Conditions = new [] + { + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Width, + Value = "1920" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Height, + Value = "1080" + } + } + }, + new CodecProfile { Type = CodecType.VideoAudio, diff --git a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs index 32cf8b5542..d9891e87be 100644 --- a/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs +++ b/MediaBrowser.Dlna/Profiles/SonyBravia2011Profile.cs @@ -226,6 +226,7 @@ namespace MediaBrowser.Dlna.Profiles new CodecProfile { Type = CodecType.Video, + Codec = "h264", Conditions = new [] { new ProfileCondition @@ -239,16 +240,7 @@ namespace MediaBrowser.Dlna.Profiles Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080" - } - } - }, - - new CodecProfile - { - Type = CodecType.Video, - Codec = "h264", - Conditions = new [] - { + }, new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -276,6 +268,18 @@ namespace MediaBrowser.Dlna.Profiles Codec = "mpeg2video", Conditions = new [] { + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Width, + Value = "1920" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Height, + Value = "1080" + }, new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -291,6 +295,26 @@ namespace MediaBrowser.Dlna.Profiles } }, + new CodecProfile + { + Type = CodecType.Video, + Conditions = new [] + { + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Width, + Value = "1920" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.Height, + Value = "1080" + } + } + }, + new CodecProfile { Type = CodecType.VideoAudio, diff --git a/MediaBrowser.Dlna/Profiles/WindowsMediaCenterProfile.cs b/MediaBrowser.Dlna/Profiles/WindowsMediaCenterProfile.cs deleted file mode 100644 index a318b193b6..0000000000 --- a/MediaBrowser.Dlna/Profiles/WindowsMediaCenterProfile.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System.Xml.Serialization; -using MediaBrowser.Model.Dlna; -using MediaBrowser.Model.Dlna.Profiles; - -namespace MediaBrowser.Dlna.Profiles -{ - [XmlRoot("Profile")] - public class WindowsMediaCenterProfile : DefaultProfile - { - public WindowsMediaCenterProfile() - { - Name = "Windows Media Center"; - - TranscodingProfiles = new[] - { - new TranscodingProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - new TranscodingProfile - { - Container = "asf", - VideoCodec = "msmpeg4", - AudioCodec = "wmav2", - Type = DlnaProfileType.Video - } - }; - - DirectPlayProfiles = new[] - { - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "mpeg4", - AudioCodec = "ac3,mp3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "avi", - VideoCodec = "h264", - AudioCodec = "aac", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "mp4,mov", - VideoCodec = "h264,mpeg4", - AudioCodec = "aac,ac3", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "asf", - VideoCodec = "wmv2,wmv3,vc1", - AudioCodec = "wmav2,wmapro", - Type = DlnaProfileType.Video - }, - new DirectPlayProfile - { - Container = "asf", - AudioCodec = "wmav2,wmapro,wmavoice", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "mp3", - AudioCodec = "mp3", - Type = DlnaProfileType.Audio - }, - new DirectPlayProfile - { - Container = "jpeg", - Type = DlnaProfileType.Photo - } - }; - - ResponseProfiles = new[] - { - new ResponseProfile - { - Container = "avi", - MimeType = "video/avi", - Type = DlnaProfileType.Video - } - }; - - ContainerProfiles = new[] - { - new ContainerProfile - { - Type = DlnaProfileType.Video, - Container = "mp4,mov", - - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.Has64BitOffsets, - Value = "false", - IsRequired = false - } - } - } - }; - - CodecProfiles = new[] - { - new CodecProfile - { - Type = CodecType.Video, - Codec = "mpeg4", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1280" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "720" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoFramerate, - Value = "30", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitrate, - Value = "5120000", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.Video, - Codec = "h264", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1920" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "1080" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoLevel, - Value = "41", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitrate, - Value = "10240000", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.Video, - Codec = "wmv2,wmv3,vc1", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Width, - Value = "1920" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.Height, - Value = "1080" - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoFramerate, - Value = "30", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.VideoBitrate, - Value = "15360000", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "ac3", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "6", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "wmav2,wmapro", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "2", - IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.VideoAudio, - Codec = "aac", - Conditions = new [] - { - new ProfileCondition - { - Condition = ProfileConditionType.LessThanEqual, - Property = ProfileConditionValue.AudioChannels, - Value = "2", - IsRequired = false - }, - new ProfileCondition - { - Condition = ProfileConditionType.Equals, - Property = ProfileConditionValue.AudioProfile, - Value = "lc", - IsRequired = false - } - } - } - }; - } - } -} diff --git a/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs index 4399462cf0..3427d75f70 100644 --- a/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs +++ b/MediaBrowser.Dlna/Profiles/XboxOneProfile.cs @@ -12,18 +12,27 @@ namespace MediaBrowser.Dlna.Profiles Name = "Xbox One"; TimelineOffsetSeconds = 40; - + Identification = new DeviceIdentification { - ModelName = "Xbox One", - FriendlyName = "Xbox-SystemOS", + FriendlyName = "XboxOne", Headers = new[] { - new HttpHeaderInfo {Name = "User-Agent", Value = "NSPlayer", Match = HeaderMatchType.Substring} + new HttpHeaderInfo + { + Name = "FriendlyName.DLNA.ORG", Value = "XboxOne", Match = HeaderMatchType.Substring + }, + new HttpHeaderInfo + { + Name = "User-Agent", Value = "NSPlayer/12", Match = HeaderMatchType.Substring + } } }; + var videoProfile = "high|main|baseline|constrained baseline"; + var videoLevel = "41"; + TranscodingProfiles = new[] { new TranscodingProfile @@ -43,8 +52,7 @@ namespace MediaBrowser.Dlna.Profiles Container = "ts", VideoCodec = "h264", AudioCodec = "aac", - Type = DlnaProfileType.Video, - EstimateContentLength = true + Type = DlnaProfileType.Video } }; @@ -129,6 +137,7 @@ namespace MediaBrowser.Dlna.Profiles new CodecProfile { Type = CodecType.Video, + Codec = "mpeg4", Conditions = new [] { new ProfileCondition @@ -144,16 +153,7 @@ namespace MediaBrowser.Dlna.Profiles Property = ProfileConditionValue.VideoBitDepth, Value = "8", IsRequired = false - } - } - }, - - new CodecProfile - { - Type = CodecType.Video, - Codec = "mpeg4", - Conditions = new [] - { + }, new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -189,6 +189,20 @@ namespace MediaBrowser.Dlna.Profiles Codec = "h264", Conditions = new [] { + new ProfileCondition + { + Condition = ProfileConditionType.NotEquals, + Property = ProfileConditionValue.IsAnamorphic, + Value = "true", + IsRequired = false + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoBitDepth, + Value = "8", + IsRequired = false + }, new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -200,6 +214,20 @@ namespace MediaBrowser.Dlna.Profiles Condition = ProfileConditionType.LessThanEqual, Property = ProfileConditionValue.Height, Value = "1080" + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoLevel, + Value = videoLevel, + IsRequired = false + }, + new ProfileCondition + { + Condition = ProfileConditionType.EqualsAny, + Property = ProfileConditionValue.VideoProfile, + Value = videoProfile, + IsRequired = false } } }, @@ -210,6 +238,20 @@ namespace MediaBrowser.Dlna.Profiles Codec = "wmv2,wmv3,vc1", Conditions = new [] { + new ProfileCondition + { + Condition = ProfileConditionType.NotEquals, + Property = ProfileConditionValue.IsAnamorphic, + Value = "true", + IsRequired = false + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoBitDepth, + Value = "8", + IsRequired = false + }, new ProfileCondition { Condition = ProfileConditionType.LessThanEqual, @@ -239,6 +281,28 @@ namespace MediaBrowser.Dlna.Profiles } }, + new CodecProfile + { + Type = CodecType.Video, + Conditions = new [] + { + new ProfileCondition + { + Condition = ProfileConditionType.NotEquals, + Property = ProfileConditionValue.IsAnamorphic, + Value = "true", + IsRequired = false + }, + new ProfileCondition + { + Condition = ProfileConditionType.LessThanEqual, + Property = ProfileConditionValue.VideoBitDepth, + Value = "8", + IsRequired = false + } + } + }, + new CodecProfile { Type = CodecType.VideoAudio, @@ -278,7 +342,7 @@ namespace MediaBrowser.Dlna.Profiles } } }; - + ResponseProfiles = new[] { new ResponseProfile diff --git a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml index d7ad1ac301..21f2b1ad5d 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml @@ -49,7 +49,7 @@ - + @@ -58,7 +58,7 @@ - + diff --git a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml index 8470f601ac..2df2da98b6 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml @@ -44,16 +44,19 @@ - + + - + - + + + diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml index ba993ca3e5..19cb5670a7 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml @@ -58,14 +58,10 @@ - + - - - - @@ -73,10 +69,18 @@ + + + + + + + + diff --git a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml index 271cf1132d..78c99d3663 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml @@ -61,14 +61,10 @@ - + - - - - @@ -76,10 +72,18 @@ + + + + + + + + diff --git a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml index 2595ffbdfc..d22356646b 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml @@ -2,10 +2,10 @@ Xbox One - Xbox-SystemOS - Xbox One + XboxOne - + + Emby @@ -48,7 +48,7 @@ - + @@ -58,14 +58,10 @@ - + - - - - @@ -74,18 +70,30 @@ + + + + + + + + + + + + diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index f6ff79b115..b062bc240f 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -102,7 +102,7 @@ namespace MediaBrowser.Model.Dlna } List list = new List(); - foreach (NameValuePair pair in BuildParams(this, accessToken)) + foreach (NameValuePair pair in BuildParams(this, accessToken, false)) { if (string.IsNullOrEmpty(pair.Value)) { @@ -173,7 +173,7 @@ namespace MediaBrowser.Model.Dlna { List list = new List(); - foreach (NameValuePair pair in BuildParams(item, accessToken)) + foreach (NameValuePair pair in BuildParams(item, accessToken, true)) { list.Add(pair.Value); } @@ -181,7 +181,7 @@ namespace MediaBrowser.Model.Dlna return string.Format("Params={0}", string.Join(";", list.ToArray())); } - private static List BuildParams(StreamInfo item, string accessToken) + private static List BuildParams(StreamInfo item, string accessToken, bool isDlna) { List list = new List(); @@ -211,7 +211,17 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("Level", item.VideoLevel.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoLevel.Value) : string.Empty)); - list.Add(new NameValuePair("ClientTime", item.IsDirectStream ? string.Empty : DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture))); + if (isDlna) + { + // The player may see it as separate resources due to url differences + // And then try to request more than one at playback + list.Add(new NameValuePair("ClientTime", string.Empty)); + } + else + { + list.Add(new NameValuePair("ClientTime", item.IsDirectStream ? string.Empty : DateTime.UtcNow.Ticks.ToString(CultureInfo.InvariantCulture))); + } + list.Add(new NameValuePair("MaxRefFrames", item.MaxRefFrames.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxRefFrames.Value) : string.Empty)); list.Add(new NameValuePair("MaxVideoBitDepth", item.MaxVideoBitDepth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxVideoBitDepth.Value) : string.Empty)); list.Add(new NameValuePair("Profile", item.VideoProfile ?? string.Empty)); diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs index c644da0b82..de1a4c6f93 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs @@ -10,6 +10,7 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; @@ -190,6 +191,27 @@ namespace MediaBrowser.Providers.TV /// The cancellation token. /// Task. internal async Task DownloadSeriesZip(string seriesId, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, CancellationToken cancellationToken) + { + try + { + await DownloadSeriesZip(seriesId, seriesDataPath, lastTvDbUpdateTime, preferredMetadataLanguage, preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); + return; + } + catch (HttpException ex) + { + if (!ex.StatusCode.HasValue || ex.StatusCode.Value != HttpStatusCode.NotFound) + { + throw; + } + } + + if (!string.Equals(preferredMetadataLanguage, "en", StringComparison.OrdinalIgnoreCase)) + { + await DownloadSeriesZip(seriesId, seriesDataPath, lastTvDbUpdateTime, "en", preferredMetadataLanguage, cancellationToken).ConfigureAwait(false); + } + } + + private async Task DownloadSeriesZip(string seriesId, string seriesDataPath, long? lastTvDbUpdateTime, string preferredMetadataLanguage, string saveAsMetadataLanguage, CancellationToken cancellationToken) { var url = string.Format(SeriesGetZip, TVUtils.TvdbApiKey, seriesId, preferredMetadataLanguage); @@ -221,7 +243,7 @@ namespace MediaBrowser.Providers.TV await SanitizeXmlFile(file).ConfigureAwait(false); } - await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, preferredMetadataLanguage + ".xml"), lastTvDbUpdateTime).ConfigureAwait(false); + await ExtractEpisodes(seriesDataPath, Path.Combine(seriesDataPath, saveAsMetadataLanguage + ".xml"), lastTvDbUpdateTime).ConfigureAwait(false); } public TvdbOptions GetTvDbOptions() diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 8285fb7e5c..313985d9df 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1637,6 +1637,12 @@ namespace MediaBrowser.Server.Implementations.Library refresh = true; } + if (!string.Equals(viewType, item.ViewType, StringComparison.OrdinalIgnoreCase)) + { + item.ViewType = viewType; + await item.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false); + } + if (!refresh && item != null) { refresh = (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 24; diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 4b7bfad3fa..f84b165108 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -94,7 +94,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected abstract Task> GetItemsWithImages(IHasImages item); - private const string Version = "29"; + private const string Version = "31"; protected string GetConfigurationCacheKey(List items, string itemName) { var parts = Version + "_" + (itemName ?? string.Empty) + "_" + @@ -103,9 +103,9 @@ namespace MediaBrowser.Server.Implementations.Photos return parts.GetMD5().ToString("N"); } - protected void CreateThumbCollage(IHasImages primaryItem, List items, string outputPath) + protected void CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 960, 540, true, primaryItem.Name); + CreateCollage(primaryItem, items, outputPath, 960, 540, drawText, primaryItem.Name); } protected virtual IEnumerable GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable items) @@ -120,9 +120,9 @@ namespace MediaBrowser.Server.Implementations.Photos CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name); } - protected void CreateSquareCollage(IHasImages primaryItem, List items, string outputPath) + protected void CreateSquareCollage(IHasImages primaryItem, List items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 800, 800, true, primaryItem.Name); + CreateCollage(primaryItem, items, outputPath, 800, 800, drawText, primaryItem.Name); } protected void CreateThumbCollage(IHasImages primaryItem, List items, string outputPath, int width, int height, bool drawText, string text) @@ -162,17 +162,23 @@ namespace MediaBrowser.Server.Implementations.Photos return false; } + var drawText = !(item is UserView); + if (imageType == ImageType.Thumb) { - CreateThumbCollage(item, itemsWithImages, outputPath); + CreateThumbCollage(item, itemsWithImages, outputPath, drawText); return true; } if (imageType == ImageType.Primary) { - if (item is PhotoAlbum || item is Playlist) + if (item is UserView) + { + CreateSquareCollage(item, itemsWithImages, outputPath, drawText); + } + else if (item is PhotoAlbum || item is Playlist) { - CreateSquareCollage(item, itemsWithImages, outputPath); + CreateSquareCollage(item, itemsWithImages, outputPath, drawText); } else { diff --git a/SharedVersion.cs b/SharedVersion.cs index e922d75910..8c5b01420c 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -//[assembly: AssemblyVersion("3.0.*")] -[assembly: AssemblyVersion("3.0.5582.2")] +[assembly: AssemblyVersion("3.0.*")] +//[assembly: AssemblyVersion("3.0.5582.2")]