From 7835d690a1ade4739171036cff335c86b5232d0e Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Sat, 18 Aug 2012 04:22:54 -0400 Subject: [PATCH] Added a completely separate DTOBaseItem to remove the ApiBaseItemWrapper mess and shrink json output size. --- MediaBrowser.Api/ApiService.cs | 147 ++++++++++++------ .../HttpHandlers/GenresHandler.cs | 1 - MediaBrowser.Api/HttpHandlers/ItemHandler.cs | 9 +- .../HttpHandlers/ItemListHandler.cs | 14 +- .../HttpHandlers/StudiosHandler.cs | 1 - MediaBrowser.Api/HttpHandlers/UsersHandler.cs | 2 +- MediaBrowser.Api/HttpHandlers/VideoHandler.cs | 16 +- MediaBrowser.Api/HttpHandlers/YearsHandler.cs | 1 - MediaBrowser.ApiInteraction/ApiClient.cs | 67 +++++--- MediaBrowser.ApiInteraction/IHttpClient.cs | 11 -- .../MediaBrowser.ApiInteraction.csproj | 1 - .../Configuration/ServerConfiguration.cs | 1 - MediaBrowser.Controller/Kernel.cs | 3 +- .../Resolvers/BaseItemResolver.cs | 5 +- .../Xml/BaseItemXmlParser.cs | 132 ++++++++++------ MediaBrowser.Model/DTO/ApiBaseItem.cs | 67 -------- MediaBrowser.Model/DTO/DTOBaseItem.cs | 86 ++++++++++ MediaBrowser.Model/DTO/IBNItem.cs | 4 +- MediaBrowser.Model/Entities/BaseItem.cs | 65 ++++---- MediaBrowser.Model/Entities/Folder.cs | 144 ++++++++++++----- .../Entities/IHasProviderIds.cs | 57 +++++++ .../Entities/ItemSpecialCounts.cs | 14 ++ MediaBrowser.Model/Entities/Person.cs | 11 +- MediaBrowser.Model/Entities/User.cs | 15 ++ .../{Users => Entities}/UserItemData.cs | 7 +- MediaBrowser.Model/Entities/Video.cs | 17 +- MediaBrowser.Model/MediaBrowser.Model.csproj | 8 +- MediaBrowser.Model/Users/User.cs | 34 ---- MediaBrowser.Movies/Entities/Movie.cs | 2 - MediaBrowser.TV/Entities/Season.cs | 1 - MediaBrowser.TV/Metadata/SeriesXmlParser.cs | 2 +- 31 files changed, 581 insertions(+), 364 deletions(-) delete mode 100644 MediaBrowser.ApiInteraction/IHttpClient.cs delete mode 100644 MediaBrowser.Model/DTO/ApiBaseItem.cs create mode 100644 MediaBrowser.Model/DTO/DTOBaseItem.cs create mode 100644 MediaBrowser.Model/Entities/IHasProviderIds.cs create mode 100644 MediaBrowser.Model/Entities/ItemSpecialCounts.cs create mode 100644 MediaBrowser.Model/Entities/User.cs rename MediaBrowser.Model/{Users => Entities}/UserItemData.cs (59%) delete mode 100644 MediaBrowser.Model/Users/User.cs diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index 5a787c0e42..be99ef239d 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -6,7 +6,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; namespace MediaBrowser.Api { @@ -22,72 +21,91 @@ namespace MediaBrowser.Api return Kernel.Instance.GetItemById(guid); } - /// - /// Takes a BaseItem and returns the actual object that will be serialized by the api - /// - public static BaseItemContainer GetSerializationObject(BaseItem item, bool includeChildren, Guid userId) + public static DTOBaseItem GetDTOBaseItem(BaseItem item, User user, + bool includeChildren = true, + bool includePeople = true) { - User user = Kernel.Instance.Users.First(u => u.Id == userId); - - BaseItemContainer wrapper = new BaseItemContainer() - { - Item = item, - UserItemData = user.GetItemData(item.Id), - Type = item.GetType().Name, - IsFolder = (item is Folder) - }; - - if (string.IsNullOrEmpty(item.LogoImagePath)) - { - wrapper.ParentLogoItemId = GetParentLogoItemId(item); - } - - if (item.BackdropImagePaths == null || !item.BackdropImagePaths.Any()) + DTOBaseItem dto = new DTOBaseItem(); + + dto.AspectRatio = item.AspectRatio; + dto.BackdropCount = item.BackdropImagePaths == null ? 0 : item.BackdropImagePaths.Count(); + dto.DateCreated = item.DateCreated; + dto.DisplayMediaType = item.DisplayMediaType; + dto.Genres = item.Genres; + dto.HasArt = !string.IsNullOrEmpty(item.ArtImagePath); + dto.HasBanner = !string.IsNullOrEmpty(item.BannerImagePath); + dto.HasLogo = !string.IsNullOrEmpty(item.LogoImagePath); + dto.HasPrimaryImage = !string.IsNullOrEmpty(item.LogoImagePath); + dto.HasThumb = !string.IsNullOrEmpty(item.ThumbnailImagePath); + dto.Id = item.Id; + dto.IndexNumber = item.IndexNumber; + dto.IsFolder = item is Folder; + dto.LocalTrailerCount = item.LocalTrailers == null ? 0 : item.LocalTrailers.Count(); + dto.Name = item.Name; + dto.OfficialRating = item.OfficialRating; + dto.Overview = item.Overview; + + // If there are no backdrops, indicate what parent has them in case the UI wants to allow inheritance + if (dto.BackdropCount == 0) { int backdropCount; - wrapper.ParentBackdropItemId = GetParentBackdropItemId(item, out backdropCount); - wrapper.ParentBackdropCount = backdropCount; + dto.ParentBackdropItemId = GetParentBackdropItemId(item, out backdropCount); + dto.ParentBackdropCount = backdropCount; } if (item.Parent != null) { - wrapper.ParentId = item.Parent.Id; + dto.ParentId = item.Parent.Id; } - if (includeChildren) + // If there is no logo, indicate what parent has one in case the UI wants to allow inheritance + if (!dto.HasLogo) { - var folder = item as Folder; + dto.ParentLogoItemId = GetParentLogoItemId(item); + } - if (folder != null) - { - wrapper.Children = folder.GetParentalAllowedChildren(user).Select(c => GetSerializationObject(c, false, userId)); - } + dto.Path = item.Path; - // Attach People by transforming them into BaseItemPerson (DTO) - if (item.People != null) - { - wrapper.People = item.People.Select(p => - { - BaseItemPerson baseItemPerson = new BaseItemPerson(); + dto.PremiereDate = item.PremiereDate; + dto.ProductionYear = item.ProductionYear; + dto.ProviderIds = item.ProviderIds; + dto.RunTimeTicks = item.RunTimeTicks; + dto.SortName = item.SortName; + dto.Taglines = item.Taglines; + dto.TrailerUrl = item.TrailerUrl; + dto.Type = item.GetType().Name; + dto.UserRating = item.UserRating; - baseItemPerson.PersonInfo = p; + dto.UserData = item.GetUserData(user); - Person ibnObject = Kernel.Instance.ItemController.GetPerson(p.Name); + AttachStudios(dto, item); - if (ibnObject != null) - { - baseItemPerson.PrimaryImagePath = ibnObject.PrimaryImagePath; - } + if (includeChildren) + { + AttachChildren(dto, item, user); + } - return baseItemPerson; - }); - } + if (includePeople) + { + AttachPeople(dto, item); } + Folder folder = item as Folder; + + if (folder != null) + { + dto.SpecialCounts = folder.GetSpecialCounts(user); + } + + return dto; + } + + private static void AttachStudios(DTOBaseItem dto, BaseItem item) + { // Attach Studios by transforming them into BaseItemStudio (DTO) if (item.Studios != null) { - wrapper.Studios = item.Studios.Select(s => + dto.Studios = item.Studios.Select(s => { BaseItemStudio baseItemStudio = new BaseItemStudio(); @@ -97,14 +115,47 @@ namespace MediaBrowser.Api if (ibnObject != null) { - baseItemStudio.PrimaryImagePath = ibnObject.PrimaryImagePath; + baseItemStudio.HasImage = !string.IsNullOrEmpty(ibnObject.PrimaryImagePath); } return baseItemStudio; }); } + } + + private static void AttachChildren(DTOBaseItem dto, BaseItem item, User user) + { + var folder = item as Folder; + + if (folder != null) + { + dto.Children = folder.GetParentalAllowedChildren(user).Select(c => GetDTOBaseItem(c, user, false, false)); + } - return wrapper; + dto.LocalTrailers = item.LocalTrailers; + } + + private static void AttachPeople(DTOBaseItem dto, BaseItem item) + { + // Attach People by transforming them into BaseItemPerson (DTO) + if (item.People != null) + { + dto.People = item.People.Select(p => + { + BaseItemPerson baseItemPerson = new BaseItemPerson(); + + baseItemPerson.PersonInfo = p; + + Person ibnObject = Kernel.Instance.ItemController.GetPerson(p.Name); + + if (ibnObject != null) + { + baseItemPerson.HasImage = !string.IsNullOrEmpty(ibnObject.PrimaryImagePath); + } + + return baseItemPerson; + }); + } } private static Guid? GetParentBackdropItemId(BaseItem item, out int backdropCount) diff --git a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs index f7d259e456..c0f2e9eb3b 100644 --- a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs @@ -5,7 +5,6 @@ using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs index 3df8e914fb..dcbdf2a900 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs @@ -1,15 +1,18 @@ using System; +using System.Linq; using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { - public class ItemHandler : BaseJsonHandler> + public class ItemHandler : BaseJsonHandler { - protected sealed override BaseItemContainer GetObjectToSerialize() + protected sealed override DTOBaseItem GetObjectToSerialize() { Guid userId = Guid.Parse(QueryString["userid"]); + User user = Kernel.Instance.Users.First(u => u.Id == userId); BaseItem item = ItemToSerialize; @@ -18,7 +21,7 @@ namespace MediaBrowser.Api.HttpHandlers return null; } - return ApiService.GetSerializationObject(item, true, userId); + return ApiService.GetDTOBaseItem(item, user); } protected virtual BaseItem ItemToSerialize diff --git a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs index b4c13540c8..84141a6bf5 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs @@ -5,18 +5,18 @@ using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { - public class ItemListHandler : BaseJsonHandler>> + public class ItemListHandler : BaseJsonHandler> { - protected override IEnumerable> GetObjectToSerialize() + protected override IEnumerable GetObjectToSerialize() { + User user = Kernel.Instance.Users.First(u => u.Id == UserId); + return ItemsToSerialize.Select(i => { - return ApiService.GetSerializationObject(i, false, UserId); - + return ApiService.GetDTOBaseItem(i, user, includeChildren: false, includePeople: false); }); } @@ -27,7 +27,7 @@ namespace MediaBrowser.Api.HttpHandlers Folder parent = ApiService.GetItemById(ItemId) as Folder; User user = Kernel.Instance.Users.First(u => u.Id == UserId); - + if (ListType.Equals("inprogressitems", StringComparison.OrdinalIgnoreCase)) { return parent.GetInProgressItems(user); @@ -76,7 +76,7 @@ namespace MediaBrowser.Api.HttpHandlers return Guid.Parse(QueryString["userid"]); } } - + private string ListType { get diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs index 54c33416dc..bef381000a 100644 --- a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -5,7 +5,6 @@ using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs index 64239005fc..e1fe638ca8 100644 --- a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; -using MediaBrowser.Model.Users; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs index 343fcc70bd..33a1a9c13b 100644 --- a/MediaBrowser.Api/HttpHandlers/VideoHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/VideoHandler.cs @@ -48,11 +48,11 @@ namespace MediaBrowser.Api.HttpHandlers return true; } - AudioStream audio = LibraryItem.AudioStreams.FirstOrDefault(); + AudioStream audioStream = (LibraryItem.AudioStreams ?? new AudioStream[] { }).FirstOrDefault(); - if (audio != null) + if (audioStream != null) { - if (RequiresAudioConversion(audio)) + if (RequiresAudioConversion(audioStream)) { return true; } @@ -121,7 +121,7 @@ namespace MediaBrowser.Api.HttpHandlers private string GetAudioArguments(string outputFormat) { - AudioStream audioStream = LibraryItem.AudioStreams.FirstOrDefault(); + AudioStream audioStream = (LibraryItem.AudioStreams ?? new AudioStream[] { }).FirstOrDefault(); if (audioStream == null) { @@ -261,7 +261,7 @@ namespace MediaBrowser.Api.HttpHandlers } } - if (LibraryItem.VideoCodec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 || LibraryItem.VideoCodec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1) + if (LibraryItem.Codec.IndexOf("264", StringComparison.OrdinalIgnoreCase) != -1 || LibraryItem.Codec.IndexOf("avc", StringComparison.OrdinalIgnoreCase) != -1) { return false; } @@ -279,15 +279,15 @@ namespace MediaBrowser.Api.HttpHandlers } } - if (audio.AudioFormat.IndexOf("aac", StringComparison.OrdinalIgnoreCase) != -1) + if (audio.Format.IndexOf("aac", StringComparison.OrdinalIgnoreCase) != -1) { return false; } - if (audio.AudioFormat.IndexOf("ac-3", StringComparison.OrdinalIgnoreCase) != -1 || audio.AudioFormat.IndexOf("ac3", StringComparison.OrdinalIgnoreCase) != -1) + if (audio.Format.IndexOf("ac-3", StringComparison.OrdinalIgnoreCase) != -1 || audio.Format.IndexOf("ac3", StringComparison.OrdinalIgnoreCase) != -1) { return false; } - if (audio.AudioFormat.IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1 || audio.AudioFormat.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1) + if (audio.Format.IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) != -1 || audio.Format.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1) { return false; } diff --git a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs index 071b980a7d..3d9ae59f2d 100644 --- a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs @@ -5,7 +5,6 @@ using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.ApiInteraction/ApiClient.cs b/MediaBrowser.ApiInteraction/ApiClient.cs index af79513e09..c30e677474 100644 --- a/MediaBrowser.ApiInteraction/ApiClient.cs +++ b/MediaBrowser.ApiInteraction/ApiClient.cs @@ -1,16 +1,23 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; +using System.Net; +using System.Net.Http; using System.Threading.Tasks; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; namespace MediaBrowser.ApiInteraction { public class ApiClient : IDisposable { + public ApiClient(HttpClientHandler handler) + { + handler.AutomaticDecompression = DecompressionMethods.Deflate; + + HttpClient = new HttpClient(handler); + } + /// /// Gets or sets the server host name (myserver or 192.168.x.x) /// @@ -32,7 +39,7 @@ namespace MediaBrowser.ApiInteraction } } - public IHttpClient HttpClient { get; set; } + public HttpClient HttpClient { get; private set; } public IJsonSerializer JsonSerializer { get; set; } /// @@ -84,26 +91,26 @@ namespace MediaBrowser.ApiInteraction /// /// This is a helper to get a list of backdrop url's from a given ApiBaseItemWrapper. If the actual item does not have any backdrops it will return backdrops from the first parent that does. /// - /// A given item. + /// A given item. /// Use if a fixed width is required. Aspect ratio will be preserved. /// Use if a fixed height is required. Aspect ratio will be preserved. /// Use if a max width is required. Aspect ratio will be preserved. /// Use if a max height is required. Aspect ratio will be preserved. /// Quality level, from 0-100. Currently only applies to JPG. The default value should suffice. - public IEnumerable GetBackdropImageUrls(ApiBaseItemContainer itemWrapper, int? width = null, int? height = null, int? maxWidth = null, int? maxHeight = null, int? quality = null) + public IEnumerable GetBackdropImageUrls(DTOBaseItem item, int? width = null, int? height = null, int? maxWidth = null, int? maxHeight = null, int? quality = null) { Guid? backdropItemId = null; int backdropCount = 0; - if (itemWrapper.Item.BackdropImagePaths == null || !itemWrapper.Item.BackdropImagePaths.Any()) + if (item.BackdropCount == 0) { - backdropItemId = itemWrapper.ParentBackdropItemId; - backdropCount = itemWrapper.ParentBackdropCount ?? 0; + backdropItemId = item.ParentBackdropItemId; + backdropCount = item.ParentBackdropCount ?? 0; } else { - backdropItemId = itemWrapper.Item.Id; - backdropCount = itemWrapper.Item.BackdropImagePaths.Count(); + backdropItemId = item.Id; + backdropCount = item.BackdropCount; } if (backdropItemId == null) @@ -124,15 +131,15 @@ namespace MediaBrowser.ApiInteraction /// /// This is a helper to get the logo image url from a given ApiBaseItemWrapper. If the actual item does not have a logo, it will return the logo from the first parent that does, or null. /// - /// A given item. + /// A given item. /// Use if a fixed width is required. Aspect ratio will be preserved. /// Use if a fixed height is required. Aspect ratio will be preserved. /// Use if a max width is required. Aspect ratio will be preserved. /// Use if a max height is required. Aspect ratio will be preserved. /// Quality level, from 0-100. Currently only applies to JPG. The default value should suffice. - public string GetLogoImageUrl(ApiBaseItemContainer itemWrapper, int? width = null, int? height = null, int? maxWidth = null, int? maxHeight = null, int? quality = null) + public string GetLogoImageUrl(DTOBaseItem item, int? width = null, int? height = null, int? maxWidth = null, int? maxHeight = null, int? quality = null) { - Guid? logoItemId = !string.IsNullOrEmpty(itemWrapper.Item.LogoImagePath) ? itemWrapper.Item.Id : itemWrapper.ParentLogoItemId; + Guid? logoItemId = item.HasLogo ? item.Id : item.ParentLogoItemId; if (logoItemId.HasValue) { @@ -153,7 +160,7 @@ namespace MediaBrowser.ApiInteraction /// /// Gets a BaseItem /// - public async Task GetItemAsync(Guid id, Guid userId) + public async Task GetItemAsync(Guid id, Guid userId) { string url = ApiUrl + "/item?userId=" + userId.ToString(); @@ -164,7 +171,7 @@ namespace MediaBrowser.ApiInteraction using (Stream stream = await HttpClient.GetStreamAsync(url)) { - return JsonSerializer.DeserializeFromStream(stream); + return JsonSerializer.DeserializeFromStream(stream); } } @@ -210,44 +217,54 @@ namespace MediaBrowser.ApiInteraction /// /// Gets all items that contain a given Year /// - public async Task> GetItemsWithYearAsync(string name, Guid userId) + public async Task> GetItemsWithYearAsync(string name, Guid userId) { string url = ApiUrl + "/itemlist?listtype=itemswithyear&userId=" + userId.ToString() + "&name=" + name; using (Stream stream = await HttpClient.GetStreamAsync(url)) { - return JsonSerializer.DeserializeFromStream>(stream); + return JsonSerializer.DeserializeFromStream>(stream); } } /// /// Gets all items that contain a given Genre /// - public async Task> GetItemsWithGenreAsync(string name, Guid userId) + public async Task> GetItemsWithGenreAsync(string name, Guid userId) { string url = ApiUrl + "/itemlist?listtype=itemswithgenre&userId=" + userId.ToString() + "&name=" + name; using (Stream stream = await HttpClient.GetStreamAsync(url)) { - return JsonSerializer.DeserializeFromStream>(stream); + return JsonSerializer.DeserializeFromStream>(stream); } } /// /// Gets all items that contain a given Person /// - public async Task> GetItemsWithPersonAsync(string name, PersonType? personType, Guid userId) + public async Task> GetItemsWithPersonAsync(string name, Guid userId) { string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name; - if (personType.HasValue) + using (Stream stream = await HttpClient.GetStreamAsync(url)) { - url += "&persontype=" + personType.Value.ToString(); + return JsonSerializer.DeserializeFromStream>(stream); } + } + + /// + /// Gets all items that contain a given Person + /// + public async Task> GetItemsWithPersonAsync(string name, string personType, Guid userId) + { + string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name; + + url += "&persontype=" + personType; using (Stream stream = await HttpClient.GetStreamAsync(url)) { - return JsonSerializer.DeserializeFromStream>(stream); + return JsonSerializer.DeserializeFromStream>(stream); } } @@ -267,13 +284,13 @@ namespace MediaBrowser.ApiInteraction /// /// Gets all items that contain a given Studio /// - public async Task> GetItemsWithStudioAsync(string name, Guid userId) + public async Task> GetItemsWithStudioAsync(string name, Guid userId) { string url = ApiUrl + "/itemlist?listtype=itemswithstudio&userId=" + userId.ToString() + "&name=" + name; using (Stream stream = await HttpClient.GetStreamAsync(url)) { - return JsonSerializer.DeserializeFromStream>(stream); + return JsonSerializer.DeserializeFromStream>(stream); } } diff --git a/MediaBrowser.ApiInteraction/IHttpClient.cs b/MediaBrowser.ApiInteraction/IHttpClient.cs deleted file mode 100644 index 40659e0191..0000000000 --- a/MediaBrowser.ApiInteraction/IHttpClient.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.IO; -using System.Threading.Tasks; - -namespace MediaBrowser.ApiInteraction -{ - public interface IHttpClient : IDisposable - { - Task GetStreamAsync(string url); - } -} diff --git a/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj b/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj index 965b4487da..71b5d9d38e 100644 --- a/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj +++ b/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj @@ -40,7 +40,6 @@ - diff --git a/MediaBrowser.Controller/Configuration/ServerConfiguration.cs b/MediaBrowser.Controller/Configuration/ServerConfiguration.cs index 88d1012b18..d58a81db9c 100644 --- a/MediaBrowser.Controller/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Controller/Configuration/ServerConfiguration.cs @@ -5,6 +5,5 @@ namespace MediaBrowser.Controller.Configuration { public class ServerConfiguration : BaseApplicationConfiguration { - public string ImagesByNamePath { get; set; } } } diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 9bf7021e14..22ccfecc17 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -14,7 +14,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Progress; -using MediaBrowser.Model.Users; namespace MediaBrowser.Controller { @@ -193,7 +192,7 @@ namespace MediaBrowser.Controller return RootFolder; } - return RootFolder.FindById(id); + return RootFolder.FindItemById(id); } /// diff --git a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs index dccdf57e1b..200a2444df 100644 --- a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs @@ -137,7 +137,10 @@ namespace MediaBrowser.Controller.Resolvers } } - item.BackdropImagePaths = backdropFiles; + if (backdropFiles.Any()) + { + item.BackdropImagePaths = backdropFiles; + } } protected virtual void PopulateLocalTrailers(T item, ItemResolveEventArgs args) diff --git a/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs b/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs index 30bf3d367b..de00adbef5 100644 --- a/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs @@ -101,8 +101,24 @@ namespace MediaBrowser.Controller.Xml break; case "TagLine": - item.Tagline = reader.ReadString(); - break; + { + var list = (item.Taglines ?? new string[] { }).ToList(); + var tagline = reader.ReadString(); + + if (!list.Contains(tagline)) + { + list.Add(tagline); + } + + item.Taglines = list; + break; + } + + case "TagLines": + { + FetchFromTaglinesNode(reader.ReadSubtree(), item); + break; + } case "ContentRating": case "MPAARating": @@ -138,7 +154,7 @@ namespace MediaBrowser.Controller.Xml case "Director": { var list = (item.People ?? new PersonInfo[] { }).ToList(); - list.AddRange(GetSplitValues(reader.ReadString(), '|').Select(v => new PersonInfo() { Name = v, PersonType = PersonType.Director })); + list.AddRange(GetSplitValues(reader.ReadString(), '|').Select(v => new PersonInfo() { Name = v, Type = "Director" })); item.People = list; break; @@ -146,7 +162,7 @@ namespace MediaBrowser.Controller.Xml case "Writer": { var list = (item.People ?? new PersonInfo[] { }).ToList(); - list.AddRange(GetSplitValues(reader.ReadString(), '|').Select(v => new PersonInfo() { Name = v, PersonType = PersonType.Writer })); + list.AddRange(GetSplitValues(reader.ReadString(), '|').Select(v => new PersonInfo() { Name = v, Type = "Writer" })); item.People = list; break; @@ -156,7 +172,7 @@ namespace MediaBrowser.Controller.Xml case "GuestStars": { var list = (item.People ?? new PersonInfo[] { }).ToList(); - list.AddRange(GetSplitValues(reader.ReadString(), '|').Select(v => new PersonInfo() { Name = v, PersonType = PersonType.Actor })); + list.AddRange(GetSplitValues(reader.ReadString(), '|').Select(v => new PersonInfo() { Name = v, Type = "Actor" })); item.People = list; break; @@ -287,7 +303,7 @@ namespace MediaBrowser.Controller.Xml { AudioStream stream = FetchMediaInfoAudio(reader.ReadSubtree()); - List streams = item.AudioStreams.ToList(); + List streams = (item.AudioStreams ?? new AudioStream[] { }).ToList(); streams.Add(stream); item.AudioStreams = streams; @@ -322,6 +338,14 @@ namespace MediaBrowser.Controller.Xml { switch (reader.Name) { + case "Default": + stream.IsDefault = reader.ReadString() == "True"; + break; + + case "Forced": + stream.IsForced = reader.ReadString() == "True"; + break; + case "BitRate": stream.BitRate = reader.ReadIntSafe(); break; @@ -343,40 +367,40 @@ namespace MediaBrowser.Controller.Xml case "dts-es": case "dts-es matrix": case "dts-es discrete": - stream.AudioFormat = "DTS"; - stream.AudioProfile = "ES"; + stream.Format = "DTS"; + stream.Profile = "ES"; break; case "dts-hd hra": case "dts-hd high resolution": - stream.AudioFormat = "DTS"; - stream.AudioProfile = "HRA"; + stream.Format = "DTS"; + stream.Profile = "HRA"; break; case "dts ma": case "dts-hd ma": case "dts-hd master": - stream.AudioFormat = "DTS"; - stream.AudioProfile = "MA"; + stream.Format = "DTS"; + stream.Profile = "MA"; break; case "dolby digital": case "dolby digital surround ex": case "dolby surround": - stream.AudioFormat = "AC-3"; + stream.Format = "AC-3"; break; case "dolby digital plus": - stream.AudioFormat = "E-AC-3"; + stream.Format = "E-AC-3"; break; case "dolby truehd": - stream.AudioFormat = "AC-3"; - stream.AudioProfile = "TrueHD"; + stream.Format = "AC-3"; + stream.Profile = "TrueHD"; break; case "mp2": - stream.AudioFormat = "MPEG Audio"; - stream.AudioProfile = "Layer 2"; + stream.Format = "MPEG Audio"; + stream.Profile = "Layer 2"; break; case "other": break; default: - stream.AudioFormat = codec; + stream.Format = codec; break; } @@ -412,7 +436,7 @@ namespace MediaBrowser.Controller.Xml break; case "BitRate": - item.VideoBitRate = reader.ReadIntSafe(); + item.BitRate = reader.ReadIntSafe(); break; case "FrameRate": @@ -424,14 +448,14 @@ namespace MediaBrowser.Controller.Xml break; case "Duration": - item.RunTimeInMilliseconds = reader.ReadIntSafe() * 60000; + item.RunTimeTicks = TimeSpan.FromMinutes(reader.ReadIntSafe()).Ticks; break; case "DurationSeconds": int seconds = reader.ReadIntSafe(); if (seconds > 0) { - item.RunTimeInMilliseconds = seconds * 1000; + item.RunTimeTicks = TimeSpan.FromSeconds(seconds).Ticks; } break; @@ -442,16 +466,16 @@ namespace MediaBrowser.Controller.Xml switch (videoCodec.ToLower()) { case "sorenson h.263": - item.VideoCodec = "Sorenson H263"; + item.Codec = "Sorenson H263"; break; case "h.262": - item.VideoCodec = "MPEG-2 Video"; + item.Codec = "MPEG-2 Video"; break; case "h.264": - item.VideoCodec = "AVC"; + item.Codec = "AVC"; break; default: - item.VideoCodec = videoCodec; + item.Codec = videoCodec; break; } @@ -499,6 +523,39 @@ namespace MediaBrowser.Controller.Xml item.Subtitles = list; } + private void FetchFromTaglinesNode(XmlReader reader, T item) + { + List list = (item.Taglines ?? new string[] { }).ToList(); + + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "Tagline": + { + string val = reader.ReadString(); + + if (!string.IsNullOrWhiteSpace(val)) + { + list.Add(val); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + + item.Taglines = list; + } + private void FetchFromGenresNode(XmlReader reader, T item) { List list = (item.Genres ?? new string[] { }).ToList(); @@ -668,27 +725,8 @@ namespace MediaBrowser.Controller.Xml break; case "Type": - { - string type = reader.ReadString(); - - if (type.Equals("Director", StringComparison.OrdinalIgnoreCase)) - { - person.PersonType = PersonType.Director; - } - else if (type.Equals("Actor", StringComparison.OrdinalIgnoreCase)) - { - person.PersonType = PersonType.Actor; - } - else if (type.Equals("Writer", StringComparison.OrdinalIgnoreCase)) - { - person.PersonType = PersonType.Writer; - } - else if (type.Equals("Producer", StringComparison.OrdinalIgnoreCase)) - { - person.PersonType = PersonType.Producer; - } - break; - } + person.Type = reader.ReadString(); + break; case "Role": person.Overview = reader.ReadString(); diff --git a/MediaBrowser.Model/DTO/ApiBaseItem.cs b/MediaBrowser.Model/DTO/ApiBaseItem.cs deleted file mode 100644 index eca45c9f8b..0000000000 --- a/MediaBrowser.Model/DTO/ApiBaseItem.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; - -namespace MediaBrowser.Model.DTO -{ - /// - /// This is a concrete class that the UI can use to deserialize - /// It is flat in the sense that it will be used regardless of the type of BaseItem involved - /// - public class ApiBaseItem : BaseItem - { - // Series properties - public string Status { get; set; } - public IEnumerable AirDays { get; set; } - public string AirTime { get; set; } - } - - /// - /// This is the full return object when requesting an Item - /// - public class BaseItemContainer - where TItemType : BaseItem - { - public TItemType Item { get; set; } - - public UserItemData UserItemData { get; set; } - - public IEnumerable> Children { get; set; } - - public bool IsFolder { get; set; } - - public Guid? ParentId { get; set; } - - public string Type { get; set; } - - public bool IsType(Type type) - { - return IsType(type.Name); - } - - public bool IsType(string type) - { - return Type.Equals(type, StringComparison.OrdinalIgnoreCase); - } - - public IEnumerable People { get; set; } - public IEnumerable Studios { get; set; } - - /// - /// If the item does not have a logo, this will hold the Id of the Parent that has one. - /// - public Guid? ParentLogoItemId { get; set; } - - public Guid? ParentBackdropItemId { get; set; } - - public int? ParentBackdropCount { get; set; } - } - - /// - /// This is strictly for convenience so the UI's don't have to use the verbose generic syntax of BaseItemWrapper - /// - public class ApiBaseItemContainer : BaseItemContainer - { - } -} diff --git a/MediaBrowser.Model/DTO/DTOBaseItem.cs b/MediaBrowser.Model/DTO/DTOBaseItem.cs new file mode 100644 index 0000000000..6f41ac578a --- /dev/null +++ b/MediaBrowser.Model/DTO/DTOBaseItem.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Model.DTO +{ + public class DTOBaseItem : IHasProviderIds + { + public string Name { get; set; } + public Guid Id { get; set; } + public DateTime DateCreated { get; set; } + + public string SortName { get; set; } + public DateTime? PremiereDate { get; set; } + public string Path { get; set; } + public string OfficialRating { get; set; } + public string Overview { get; set; } + public IEnumerable Taglines { get; set; } + + public IEnumerable Genres { get; set; } + + public string DisplayMediaType { get; set; } + + public float? UserRating { get; set; } + public long? RunTimeTicks { get; set; } + + public string AspectRatio { get; set; } + public int? ProductionYear { get; set; } + + public int? IndexNumber { get; set; } + + public string TrailerUrl { get; set; } + + public Dictionary ProviderIds { get; set; } + + public bool HasBanner { get; set; } + public bool HasArt { get; set; } + public bool HasLogo { get; set; } + public bool HasThumb { get; set; } + public bool HasPrimaryImage { get; set; } + + public int BackdropCount { get; set; } + + public IEnumerable Children { get; set; } + + public bool IsFolder { get; set; } + + public Guid? ParentId { get; set; } + + public string Type { get; set; } + + public IEnumerable People { get; set; } + public IEnumerable Studios { get; set; } + + /// + /// If the item does not have a logo, this will hold the Id of the Parent that has one. + /// + public Guid? ParentLogoItemId { get; set; } + + /// + /// If the item does not have any backdrops, this will hold the Id of the Parent that has one. + /// + public Guid? ParentBackdropItemId { get; set; } + public int? ParentBackdropCount { get; set; } + + public IEnumerable