ソースを参照

Added a completely separate DTOBaseItem to remove the ApiBaseItemWrapper mess and shrink json output size.

LukePulverenti Luke Pulverenti luke pulverenti 12 年 前
コミット
7835d690a1
31 ファイル変更581 行追加364 行削除
  1. 99 48
      MediaBrowser.Api/ApiService.cs
  2. 0 1
      MediaBrowser.Api/HttpHandlers/GenresHandler.cs
  3. 6 3
      MediaBrowser.Api/HttpHandlers/ItemHandler.cs
  4. 7 7
      MediaBrowser.Api/HttpHandlers/ItemListHandler.cs
  5. 0 1
      MediaBrowser.Api/HttpHandlers/StudiosHandler.cs
  6. 1 1
      MediaBrowser.Api/HttpHandlers/UsersHandler.cs
  7. 8 8
      MediaBrowser.Api/HttpHandlers/VideoHandler.cs
  8. 0 1
      MediaBrowser.Api/HttpHandlers/YearsHandler.cs
  9. 42 25
      MediaBrowser.ApiInteraction/ApiClient.cs
  10. 0 11
      MediaBrowser.ApiInteraction/IHttpClient.cs
  11. 0 1
      MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj
  12. 0 1
      MediaBrowser.Controller/Configuration/ServerConfiguration.cs
  13. 1 2
      MediaBrowser.Controller/Kernel.cs
  14. 4 1
      MediaBrowser.Controller/Resolvers/BaseItemResolver.cs
  15. 85 47
      MediaBrowser.Controller/Xml/BaseItemXmlParser.cs
  16. 0 67
      MediaBrowser.Model/DTO/ApiBaseItem.cs
  17. 86 0
      MediaBrowser.Model/DTO/DTOBaseItem.cs
  18. 2 2
      MediaBrowser.Model/DTO/IBNItem.cs
  19. 31 34
      MediaBrowser.Model/Entities/BaseItem.cs
  20. 105 39
      MediaBrowser.Model/Entities/Folder.cs
  21. 57 0
      MediaBrowser.Model/Entities/IHasProviderIds.cs
  22. 14 0
      MediaBrowser.Model/Entities/ItemSpecialCounts.cs
  23. 1 10
      MediaBrowser.Model/Entities/Person.cs
  24. 15 0
      MediaBrowser.Model/Entities/User.cs
  25. 3 4
      MediaBrowser.Model/Entities/UserItemData.cs
  26. 8 9
      MediaBrowser.Model/Entities/Video.cs
  27. 5 3
      MediaBrowser.Model/MediaBrowser.Model.csproj
  28. 0 34
      MediaBrowser.Model/Users/User.cs
  29. 0 2
      MediaBrowser.Movies/Entities/Movie.cs
  30. 0 1
      MediaBrowser.TV/Entities/Season.cs
  31. 1 1
      MediaBrowser.TV/Metadata/SeriesXmlParser.cs

+ 99 - 48
MediaBrowser.Api/ApiService.cs

@@ -6,7 +6,6 @@ using MediaBrowser.Common.Configuration;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Api
 namespace MediaBrowser.Api
 {
 {
@@ -22,72 +21,91 @@ namespace MediaBrowser.Api
             return Kernel.Instance.GetItemById(guid);
             return Kernel.Instance.GetItemById(guid);
         }
         }
 
 
-        /// <summary>
-        /// Takes a BaseItem and returns the actual object that will be serialized by the api
-        /// </summary>
-        public static BaseItemContainer<BaseItem> 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<BaseItem> wrapper = new BaseItemContainer<BaseItem>()
-            {
-                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;
                 int backdropCount;
-                wrapper.ParentBackdropItemId = GetParentBackdropItemId(item, out backdropCount);
-                wrapper.ParentBackdropCount = backdropCount;
+                dto.ParentBackdropItemId = GetParentBackdropItemId(item, out backdropCount);
+                dto.ParentBackdropCount = backdropCount;
             }
             }
 
 
             if (item.Parent != null)
             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)
             // Attach Studios by transforming them into BaseItemStudio (DTO)
             if (item.Studios != null)
             if (item.Studios != null)
             {
             {
-                wrapper.Studios = item.Studios.Select(s =>
+                dto.Studios = item.Studios.Select(s =>
                 {
                 {
                     BaseItemStudio baseItemStudio = new BaseItemStudio();
                     BaseItemStudio baseItemStudio = new BaseItemStudio();
 
 
@@ -97,14 +115,47 @@ namespace MediaBrowser.Api
 
 
                     if (ibnObject != null)
                     if (ibnObject != null)
                     {
                     {
-                        baseItemStudio.PrimaryImagePath = ibnObject.PrimaryImagePath;
+                        baseItemStudio.HasImage = !string.IsNullOrEmpty(ibnObject.PrimaryImagePath);
                     }
                     }
 
 
                     return baseItemStudio;
                     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)
         private static Guid? GetParentBackdropItemId(BaseItem item, out int backdropCount)

+ 0 - 1
MediaBrowser.Api/HttpHandlers/GenresHandler.cs

@@ -5,7 +5,6 @@ using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {

+ 6 - 3
MediaBrowser.Api/HttpHandlers/ItemHandler.cs

@@ -1,15 +1,18 @@
 using System;
 using System;
+using System.Linq;
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
-    public class ItemHandler : BaseJsonHandler<BaseItemContainer<BaseItem>>
+    public class ItemHandler : BaseJsonHandler<DTOBaseItem>
     {
     {
-        protected sealed override BaseItemContainer<BaseItem> GetObjectToSerialize()
+        protected sealed override DTOBaseItem GetObjectToSerialize()
         {
         {
             Guid userId = Guid.Parse(QueryString["userid"]);
             Guid userId = Guid.Parse(QueryString["userid"]);
+            User user = Kernel.Instance.Users.First(u => u.Id == userId);
 
 
             BaseItem item = ItemToSerialize;
             BaseItem item = ItemToSerialize;
 
 
@@ -18,7 +21,7 @@ namespace MediaBrowser.Api.HttpHandlers
                 return null;
                 return null;
             }
             }
 
 
-            return ApiService.GetSerializationObject(item, true, userId);
+            return ApiService.GetDTOBaseItem(item, user);
         }
         }
 
 
         protected virtual BaseItem ItemToSerialize
         protected virtual BaseItem ItemToSerialize

+ 7 - 7
MediaBrowser.Api/HttpHandlers/ItemListHandler.cs

@@ -5,18 +5,18 @@ using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {
-    public class ItemListHandler : BaseJsonHandler<IEnumerable<BaseItemContainer<BaseItem>>>
+    public class ItemListHandler : BaseJsonHandler<IEnumerable<DTOBaseItem>>
     {
     {
-        protected override IEnumerable<BaseItemContainer<BaseItem>> GetObjectToSerialize()
+        protected override IEnumerable<DTOBaseItem> GetObjectToSerialize()
         {
         {
+            User user = Kernel.Instance.Users.First(u => u.Id == UserId);
+
             return ItemsToSerialize.Select(i =>
             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;
                 Folder parent = ApiService.GetItemById(ItemId) as Folder;
 
 
                 User user = Kernel.Instance.Users.First(u => u.Id == UserId);
                 User user = Kernel.Instance.Users.First(u => u.Id == UserId);
-                
+
                 if (ListType.Equals("inprogressitems", StringComparison.OrdinalIgnoreCase))
                 if (ListType.Equals("inprogressitems", StringComparison.OrdinalIgnoreCase))
                 {
                 {
                     return parent.GetInProgressItems(user);
                     return parent.GetInProgressItems(user);
@@ -76,7 +76,7 @@ namespace MediaBrowser.Api.HttpHandlers
                 return Guid.Parse(QueryString["userid"]);
                 return Guid.Parse(QueryString["userid"]);
             }
             }
         }
         }
-        
+
         private string ListType
         private string ListType
         {
         {
             get
             get

+ 0 - 1
MediaBrowser.Api/HttpHandlers/StudiosHandler.cs

@@ -5,7 +5,6 @@ using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {

+ 1 - 1
MediaBrowser.Api/HttpHandlers/UsersHandler.cs

@@ -1,7 +1,7 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
-using MediaBrowser.Model.Users;
+using MediaBrowser.Model.Entities;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {

+ 8 - 8
MediaBrowser.Api/HttpHandlers/VideoHandler.cs

@@ -48,11 +48,11 @@ namespace MediaBrowser.Api.HttpHandlers
                 return true;
                 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;
                     return true;
                 }
                 }
@@ -121,7 +121,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
 
         private string GetAudioArguments(string outputFormat)
         private string GetAudioArguments(string outputFormat)
         {
         {
-            AudioStream audioStream = LibraryItem.AudioStreams.FirstOrDefault();
+            AudioStream audioStream = (LibraryItem.AudioStreams ?? new AudioStream[] { }).FirstOrDefault();
 
 
             if (audioStream == null)
             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;
                 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;
                 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;
                 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;
                 return false;
             }
             }

+ 0 - 1
MediaBrowser.Api/HttpHandlers/YearsHandler.cs

@@ -5,7 +5,6 @@ using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Controller;
 using MediaBrowser.Controller;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Api.HttpHandlers
 namespace MediaBrowser.Api.HttpHandlers
 {
 {

+ 42 - 25
MediaBrowser.ApiInteraction/ApiClient.cs

@@ -1,16 +1,23 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.IO;
 using System.IO;
-using System.Linq;
+using System.Net;
+using System.Net.Http;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.DTO;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.ApiInteraction
 namespace MediaBrowser.ApiInteraction
 {
 {
     public class ApiClient : IDisposable
     public class ApiClient : IDisposable
     {
     {
+        public ApiClient(HttpClientHandler handler)
+        {
+            handler.AutomaticDecompression = DecompressionMethods.Deflate;
+
+            HttpClient = new HttpClient(handler);
+        }
+
         /// <summary>
         /// <summary>
         /// Gets or sets the server host name (myserver or 192.168.x.x)
         /// Gets or sets the server host name (myserver or 192.168.x.x)
         /// </summary>
         /// </summary>
@@ -32,7 +39,7 @@ namespace MediaBrowser.ApiInteraction
             }
             }
         }
         }
 
 
-        public IHttpClient HttpClient { get; set; }
+        public HttpClient HttpClient { get; private set; }
         public IJsonSerializer JsonSerializer { get; set; }
         public IJsonSerializer JsonSerializer { get; set; }
 
 
         /// <summary>
         /// <summary>
@@ -84,26 +91,26 @@ namespace MediaBrowser.ApiInteraction
         /// <summary>
         /// <summary>
         /// 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.
         /// 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.
         /// </summary>
         /// </summary>
-        /// <param name="itemWrapper">A given item.</param>
+        /// <param name="item">A given item.</param>
         /// <param name="width">Use if a fixed width is required. Aspect ratio will be preserved.</param>
         /// <param name="width">Use if a fixed width is required. Aspect ratio will be preserved.</param>
         /// <param name="height">Use if a fixed height is required. Aspect ratio will be preserved.</param>
         /// <param name="height">Use if a fixed height is required. Aspect ratio will be preserved.</param>
         /// <param name="maxWidth">Use if a max width is required. Aspect ratio will be preserved.</param>
         /// <param name="maxWidth">Use if a max width is required. Aspect ratio will be preserved.</param>
         /// <param name="maxHeight">Use if a max height is required. Aspect ratio will be preserved.</param>
         /// <param name="maxHeight">Use if a max height is required. Aspect ratio will be preserved.</param>
         /// <param name="quality">Quality level, from 0-100. Currently only applies to JPG. The default value should suffice.</param>
         /// <param name="quality">Quality level, from 0-100. Currently only applies to JPG. The default value should suffice.</param>
-        public IEnumerable<string> GetBackdropImageUrls(ApiBaseItemContainer itemWrapper, int? width = null, int? height = null, int? maxWidth = null, int? maxHeight = null, int? quality = null)
+        public IEnumerable<string> GetBackdropImageUrls(DTOBaseItem item, int? width = null, int? height = null, int? maxWidth = null, int? maxHeight = null, int? quality = null)
         {
         {
             Guid? backdropItemId = null;
             Guid? backdropItemId = null;
             int backdropCount = 0;
             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
             else
             {
             {
-                backdropItemId = itemWrapper.Item.Id;
-                backdropCount = itemWrapper.Item.BackdropImagePaths.Count();
+                backdropItemId = item.Id;
+                backdropCount = item.BackdropCount;
             }
             }
 
 
             if (backdropItemId == null)
             if (backdropItemId == null)
@@ -124,15 +131,15 @@ namespace MediaBrowser.ApiInteraction
         /// <summary>
         /// <summary>
         /// 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.
         /// 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.
         /// </summary>
         /// </summary>
-        /// <param name="itemWrapper">A given item.</param>
+        /// <param name="item">A given item.</param>
         /// <param name="width">Use if a fixed width is required. Aspect ratio will be preserved.</param>
         /// <param name="width">Use if a fixed width is required. Aspect ratio will be preserved.</param>
         /// <param name="height">Use if a fixed height is required. Aspect ratio will be preserved.</param>
         /// <param name="height">Use if a fixed height is required. Aspect ratio will be preserved.</param>
         /// <param name="maxWidth">Use if a max width is required. Aspect ratio will be preserved.</param>
         /// <param name="maxWidth">Use if a max width is required. Aspect ratio will be preserved.</param>
         /// <param name="maxHeight">Use if a max height is required. Aspect ratio will be preserved.</param>
         /// <param name="maxHeight">Use if a max height is required. Aspect ratio will be preserved.</param>
         /// <param name="quality">Quality level, from 0-100. Currently only applies to JPG. The default value should suffice.</param>
         /// <param name="quality">Quality level, from 0-100. Currently only applies to JPG. The default value should suffice.</param>
-        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)
             if (logoItemId.HasValue)
             {
             {
@@ -153,7 +160,7 @@ namespace MediaBrowser.ApiInteraction
         /// <summary>
         /// <summary>
         /// Gets a BaseItem
         /// Gets a BaseItem
         /// </summary>
         /// </summary>
-        public async Task<ApiBaseItemContainer> GetItemAsync(Guid id, Guid userId)
+        public async Task<DTOBaseItem> GetItemAsync(Guid id, Guid userId)
         {
         {
             string url = ApiUrl + "/item?userId=" + userId.ToString();
             string url = ApiUrl + "/item?userId=" + userId.ToString();
 
 
@@ -164,7 +171,7 @@ namespace MediaBrowser.ApiInteraction
 
 
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             {
             {
-                return JsonSerializer.DeserializeFromStream<ApiBaseItemContainer>(stream);
+                return JsonSerializer.DeserializeFromStream<DTOBaseItem>(stream);
             }
             }
         }
         }
 
 
@@ -210,44 +217,54 @@ namespace MediaBrowser.ApiInteraction
         /// <summary>
         /// <summary>
         /// Gets all items that contain a given Year
         /// Gets all items that contain a given Year
         /// </summary>
         /// </summary>
-        public async Task<IEnumerable<ApiBaseItemContainer>> GetItemsWithYearAsync(string name, Guid userId)
+        public async Task<IEnumerable<DTOBaseItem>> GetItemsWithYearAsync(string name, Guid userId)
         {
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithyear&userId=" + userId.ToString() + "&name=" + name;
             string url = ApiUrl + "/itemlist?listtype=itemswithyear&userId=" + userId.ToString() + "&name=" + name;
 
 
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             {
             {
-                return JsonSerializer.DeserializeFromStream<IEnumerable<ApiBaseItemContainer>>(stream);
+                return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
             }
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Gets all items that contain a given Genre
         /// Gets all items that contain a given Genre
         /// </summary>
         /// </summary>
-        public async Task<IEnumerable<ApiBaseItemContainer>> GetItemsWithGenreAsync(string name, Guid userId)
+        public async Task<IEnumerable<DTOBaseItem>> GetItemsWithGenreAsync(string name, Guid userId)
         {
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithgenre&userId=" + userId.ToString() + "&name=" + name;
             string url = ApiUrl + "/itemlist?listtype=itemswithgenre&userId=" + userId.ToString() + "&name=" + name;
 
 
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             {
             {
-                return JsonSerializer.DeserializeFromStream<IEnumerable<ApiBaseItemContainer>>(stream);
+                return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
             }
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// Gets all items that contain a given Person
         /// Gets all items that contain a given Person
         /// </summary>
         /// </summary>
-        public async Task<IEnumerable<ApiBaseItemContainer>> GetItemsWithPersonAsync(string name, PersonType? personType, Guid userId)
+        public async Task<IEnumerable<DTOBaseItem>> GetItemsWithPersonAsync(string name, Guid userId)
         {
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithperson&userId=" + userId.ToString() + "&name=" + name;
             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<IEnumerable<DTOBaseItem>>(stream);
             }
             }
+        }
+        
+        /// <summary>
+        /// Gets all items that contain a given Person
+        /// </summary>
+        public async Task<IEnumerable<DTOBaseItem>> 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))
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             {
             {
-                return JsonSerializer.DeserializeFromStream<IEnumerable<ApiBaseItemContainer>>(stream);
+                return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
             }
         }
         }
 
 
@@ -267,13 +284,13 @@ namespace MediaBrowser.ApiInteraction
         /// <summary>
         /// <summary>
         /// Gets all items that contain a given Studio
         /// Gets all items that contain a given Studio
         /// </summary>
         /// </summary>
-        public async Task<IEnumerable<ApiBaseItemContainer>> GetItemsWithStudioAsync(string name, Guid userId)
+        public async Task<IEnumerable<DTOBaseItem>> GetItemsWithStudioAsync(string name, Guid userId)
         {
         {
             string url = ApiUrl + "/itemlist?listtype=itemswithstudio&userId=" + userId.ToString() + "&name=" + name;
             string url = ApiUrl + "/itemlist?listtype=itemswithstudio&userId=" + userId.ToString() + "&name=" + name;
 
 
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             using (Stream stream = await HttpClient.GetStreamAsync(url))
             {
             {
-                return JsonSerializer.DeserializeFromStream<IEnumerable<ApiBaseItemContainer>>(stream);
+                return JsonSerializer.DeserializeFromStream<IEnumerable<DTOBaseItem>>(stream);
             }
             }
         }
         }
 
 

+ 0 - 11
MediaBrowser.ApiInteraction/IHttpClient.cs

@@ -1,11 +0,0 @@
-using System;
-using System.IO;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.ApiInteraction
-{
-    public interface IHttpClient : IDisposable  
-    {
-        Task<Stream> GetStreamAsync(string url);
-    }
-}

+ 0 - 1
MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj

@@ -40,7 +40,6 @@
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <Compile Include="ApiClient.cs" />
     <Compile Include="ApiClient.cs" />
-    <Compile Include="IHttpClient.cs" />
     <Compile Include="IJsonSerializer.cs" />
     <Compile Include="IJsonSerializer.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   </ItemGroup>

+ 0 - 1
MediaBrowser.Controller/Configuration/ServerConfiguration.cs

@@ -5,6 +5,5 @@ namespace MediaBrowser.Controller.Configuration
 {
 {
     public class ServerConfiguration : BaseApplicationConfiguration
     public class ServerConfiguration : BaseApplicationConfiguration
     {
     {
-        public string ImagesByNamePath { get; set; }
     }
     }
 }
 }

+ 1 - 2
MediaBrowser.Controller/Kernel.cs

@@ -14,7 +14,6 @@ using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Progress;
 using MediaBrowser.Model.Progress;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Controller
 namespace MediaBrowser.Controller
 {
 {
@@ -193,7 +192,7 @@ namespace MediaBrowser.Controller
                 return RootFolder;
                 return RootFolder;
             }
             }
 
 
-            return RootFolder.FindById(id);
+            return RootFolder.FindItemById(id);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 4 - 1
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)
         protected virtual void PopulateLocalTrailers(T item, ItemResolveEventArgs args)

+ 85 - 47
MediaBrowser.Controller/Xml/BaseItemXmlParser.cs

@@ -101,8 +101,24 @@ namespace MediaBrowser.Controller.Xml
                     break;
                     break;
 
 
                 case "TagLine":
                 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 "ContentRating":
                 case "MPAARating":
                 case "MPAARating":
@@ -138,7 +154,7 @@ namespace MediaBrowser.Controller.Xml
                 case "Director":
                 case "Director":
                     {
                     {
                         var list = (item.People ?? new PersonInfo[] { }).ToList();
                         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;
                         item.People = list;
                         break;
                         break;
@@ -146,7 +162,7 @@ namespace MediaBrowser.Controller.Xml
                 case "Writer":
                 case "Writer":
                     {
                     {
                         var list = (item.People ?? new PersonInfo[] { }).ToList();
                         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;
                         item.People = list;
                         break;
                         break;
@@ -156,7 +172,7 @@ namespace MediaBrowser.Controller.Xml
                 case "GuestStars":
                 case "GuestStars":
                     {
                     {
                         var list = (item.People ?? new PersonInfo[] { }).ToList();
                         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;
                         item.People = list;
                         break;
                         break;
@@ -287,7 +303,7 @@ namespace MediaBrowser.Controller.Xml
                             {
                             {
                                 AudioStream stream = FetchMediaInfoAudio(reader.ReadSubtree());
                                 AudioStream stream = FetchMediaInfoAudio(reader.ReadSubtree());
 
 
-                                List<AudioStream> streams = item.AudioStreams.ToList();
+                                List<AudioStream> streams = (item.AudioStreams ?? new AudioStream[] { }).ToList();
                                 streams.Add(stream);
                                 streams.Add(stream);
                                 item.AudioStreams = streams;
                                 item.AudioStreams = streams;
 
 
@@ -322,6 +338,14 @@ namespace MediaBrowser.Controller.Xml
                 {
                 {
                     switch (reader.Name)
                     switch (reader.Name)
                     {
                     {
+                        case "Default":
+                            stream.IsDefault = reader.ReadString() == "True";
+                            break;
+
+                        case "Forced":
+                            stream.IsForced = reader.ReadString() == "True";
+                            break;
+
                         case "BitRate":
                         case "BitRate":
                             stream.BitRate = reader.ReadIntSafe();
                             stream.BitRate = reader.ReadIntSafe();
                             break;
                             break;
@@ -343,40 +367,40 @@ namespace MediaBrowser.Controller.Xml
                                     case "dts-es":
                                     case "dts-es":
                                     case "dts-es matrix":
                                     case "dts-es matrix":
                                     case "dts-es discrete":
                                     case "dts-es discrete":
-                                        stream.AudioFormat = "DTS";
-                                        stream.AudioProfile = "ES";
+                                        stream.Format = "DTS";
+                                        stream.Profile = "ES";
                                         break;
                                         break;
                                     case "dts-hd hra":
                                     case "dts-hd hra":
                                     case "dts-hd high resolution":
                                     case "dts-hd high resolution":
-                                        stream.AudioFormat = "DTS";
-                                        stream.AudioProfile = "HRA";
+                                        stream.Format = "DTS";
+                                        stream.Profile = "HRA";
                                         break;
                                         break;
                                     case "dts ma":
                                     case "dts ma":
                                     case "dts-hd ma":
                                     case "dts-hd ma":
                                     case "dts-hd master":
                                     case "dts-hd master":
-                                        stream.AudioFormat = "DTS";
-                                        stream.AudioProfile = "MA";
+                                        stream.Format = "DTS";
+                                        stream.Profile = "MA";
                                         break;
                                         break;
                                     case "dolby digital":
                                     case "dolby digital":
                                     case "dolby digital surround ex":
                                     case "dolby digital surround ex":
                                     case "dolby surround":
                                     case "dolby surround":
-                                        stream.AudioFormat = "AC-3";
+                                        stream.Format = "AC-3";
                                         break;
                                         break;
                                     case "dolby digital plus":
                                     case "dolby digital plus":
-                                        stream.AudioFormat = "E-AC-3";
+                                        stream.Format = "E-AC-3";
                                         break;
                                         break;
                                     case "dolby truehd":
                                     case "dolby truehd":
-                                        stream.AudioFormat = "AC-3";
-                                        stream.AudioProfile = "TrueHD";
+                                        stream.Format = "AC-3";
+                                        stream.Profile = "TrueHD";
                                         break;
                                         break;
                                     case "mp2":
                                     case "mp2":
-                                        stream.AudioFormat = "MPEG Audio";
-                                        stream.AudioProfile = "Layer 2";
+                                        stream.Format = "MPEG Audio";
+                                        stream.Profile = "Layer 2";
                                         break;
                                         break;
                                     case "other":
                                     case "other":
                                         break;
                                         break;
                                     default:
                                     default:
-                                        stream.AudioFormat = codec;
+                                        stream.Format = codec;
                                         break;
                                         break;
                                 }
                                 }
 
 
@@ -412,7 +436,7 @@ namespace MediaBrowser.Controller.Xml
                             break;
                             break;
 
 
                         case "BitRate":
                         case "BitRate":
-                            item.VideoBitRate = reader.ReadIntSafe();
+                            item.BitRate = reader.ReadIntSafe();
                             break;
                             break;
 
 
                         case "FrameRate":
                         case "FrameRate":
@@ -424,14 +448,14 @@ namespace MediaBrowser.Controller.Xml
                             break;
                             break;
 
 
                         case "Duration":
                         case "Duration":
-                            item.RunTimeInMilliseconds = reader.ReadIntSafe() * 60000;
+                            item.RunTimeTicks = TimeSpan.FromMinutes(reader.ReadIntSafe()).Ticks;
                             break;
                             break;
 
 
                         case "DurationSeconds":
                         case "DurationSeconds":
                             int seconds = reader.ReadIntSafe();
                             int seconds = reader.ReadIntSafe();
                             if (seconds > 0)
                             if (seconds > 0)
                             {
                             {
-                                item.RunTimeInMilliseconds = seconds * 1000;
+                                item.RunTimeTicks = TimeSpan.FromSeconds(seconds).Ticks;
                             }
                             }
                             break;
                             break;
 
 
@@ -442,16 +466,16 @@ namespace MediaBrowser.Controller.Xml
                                 switch (videoCodec.ToLower())
                                 switch (videoCodec.ToLower())
                                 {
                                 {
                                     case "sorenson h.263":
                                     case "sorenson h.263":
-                                        item.VideoCodec = "Sorenson H263";
+                                        item.Codec = "Sorenson H263";
                                         break;
                                         break;
                                     case "h.262":
                                     case "h.262":
-                                        item.VideoCodec = "MPEG-2 Video";
+                                        item.Codec = "MPEG-2 Video";
                                         break;
                                         break;
                                     case "h.264":
                                     case "h.264":
-                                        item.VideoCodec = "AVC";
+                                        item.Codec = "AVC";
                                         break;
                                         break;
                                     default:
                                     default:
-                                        item.VideoCodec = videoCodec;
+                                        item.Codec = videoCodec;
                                         break;
                                         break;
                                 }
                                 }
 
 
@@ -499,6 +523,39 @@ namespace MediaBrowser.Controller.Xml
             item.Subtitles = list;
             item.Subtitles = list;
         }
         }
 
 
+        private void FetchFromTaglinesNode(XmlReader reader, T item)
+        {
+            List<string> 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)
         private void FetchFromGenresNode(XmlReader reader, T item)
         {
         {
             List<string> list = (item.Genres ?? new string[] { }).ToList();
             List<string> list = (item.Genres ?? new string[] { }).ToList();
@@ -668,27 +725,8 @@ namespace MediaBrowser.Controller.Xml
                             break;
                             break;
 
 
                         case "Type":
                         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":
                         case "Role":
                             person.Overview = reader.ReadString();
                             person.Overview = reader.ReadString();

+ 0 - 67
MediaBrowser.Model/DTO/ApiBaseItem.cs

@@ -1,67 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Users;
-
-namespace MediaBrowser.Model.DTO
-{
-    /// <summary>
-    /// 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
-    /// </summary>
-    public class ApiBaseItem : BaseItem
-    {
-        // Series properties
-        public string Status { get; set; }
-        public IEnumerable<DayOfWeek> AirDays { get; set; }
-        public string AirTime { get; set; }
-    }
-
-    /// <summary>
-    /// This is the full return object when requesting an Item
-    /// </summary>
-    public class BaseItemContainer<TItemType>
-        where TItemType : BaseItem
-    {
-        public TItemType Item { get; set; }
-
-        public UserItemData UserItemData { get; set; }
-
-        public IEnumerable<BaseItemContainer<TItemType>> 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<BaseItemPerson> People { get; set; }
-        public IEnumerable<BaseItemStudio> Studios { get; set; }
-
-        /// <summary>
-        /// If the item does not have a logo, this will hold the Id of the Parent that has one.
-        /// </summary>
-        public Guid? ParentLogoItemId { get; set; }
-
-        public Guid? ParentBackdropItemId { get; set; }
-
-        public int? ParentBackdropCount { get; set; }
-    }
-
-    /// <summary>
-    /// This is strictly for convenience so the UI's don't have to use the verbose generic syntax of BaseItemWrapper<ApiBaseItem>
-    /// </summary>
-    public class ApiBaseItemContainer : BaseItemContainer<ApiBaseItem>
-    {
-    }
-}

+ 86 - 0
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<string> Taglines { get; set; }
+
+        public IEnumerable<string> 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<string, string> 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<DTOBaseItem> Children { get; set; }
+
+        public bool IsFolder { get; set; }
+
+        public Guid? ParentId { get; set; }
+
+        public string Type { get; set; }
+
+        public IEnumerable<BaseItemPerson> People { get; set; }
+        public IEnumerable<BaseItemStudio> Studios { get; set; }
+
+        /// <summary>
+        /// If the item does not have a logo, this will hold the Id of the Parent that has one.
+        /// </summary>
+        public Guid? ParentLogoItemId { get; set; }
+
+        /// <summary>
+        /// If the item does not have any backdrops, this will hold the Id of the Parent that has one.
+        /// </summary>
+        public Guid? ParentBackdropItemId { get; set; }
+        public int? ParentBackdropCount { get; set; }
+
+        public IEnumerable<Video> LocalTrailers { get; set; }
+        public int LocalTrailerCount { get; set; }
+
+        /// <summary>
+        /// User data for this item based on the user it's being requested for
+        /// </summary>
+        public UserItemData UserData { get; set; }
+
+        public ItemSpecialCounts SpecialCounts { get; set; }
+
+        public bool IsType(Type type)
+        {
+            return IsType(type.Name);
+        }
+
+        public bool IsType(string type)
+        {
+            return Type.Equals(type, StringComparison.OrdinalIgnoreCase);
+        }
+    }
+}

+ 2 - 2
MediaBrowser.Model/DTO/IBNItem.cs

@@ -24,7 +24,7 @@ namespace MediaBrowser.Model.DTO
     public class BaseItemPerson
     public class BaseItemPerson
     {
     {
         public PersonInfo PersonInfo { get; set; }
         public PersonInfo PersonInfo { get; set; }
-        public string PrimaryImagePath { get; set; }
+        public bool HasImage { get; set; }
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -33,6 +33,6 @@ namespace MediaBrowser.Model.DTO
     public class BaseItemStudio
     public class BaseItemStudio
     {
     {
         public string Name { get; set; }
         public string Name { get; set; }
-        public string PrimaryImagePath { get; set; }
+        public bool HasImage { get; set; }
     }
     }
 }
 }

+ 31 - 34
MediaBrowser.Model/Entities/BaseItem.cs

@@ -1,11 +1,10 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Runtime.Serialization;
-using MediaBrowser.Model.Users;
+using System.Linq;
 
 
 namespace MediaBrowser.Model.Entities
 namespace MediaBrowser.Model.Entities
 {
 {
-    public abstract class BaseItem : BaseEntity
+    public abstract class BaseItem : BaseEntity, IHasProviderIds
     {
     {
         public string SortName { get; set; }
         public string SortName { get; set; }
 
 
@@ -16,25 +15,25 @@ namespace MediaBrowser.Model.Entities
 
 
         public string Path { get; set; }
         public string Path { get; set; }
 
 
-        [IgnoreDataMember]
         public Folder Parent { get; set; }
         public Folder Parent { get; set; }
 
 
         public string LogoImagePath { get; set; }
         public string LogoImagePath { get; set; }
+
         public string ArtImagePath { get; set; }
         public string ArtImagePath { get; set; }
+
         public string ThumbnailImagePath { get; set; }
         public string ThumbnailImagePath { get; set; }
+
         public string BannerImagePath { get; set; }
         public string BannerImagePath { get; set; }
 
 
         public IEnumerable<string> BackdropImagePaths { get; set; }
         public IEnumerable<string> BackdropImagePaths { get; set; }
 
 
         public string OfficialRating { get; set; }
         public string OfficialRating { get; set; }
         
         
-        [IgnoreDataMember]
         public string CustomRating { get; set; }
         public string CustomRating { get; set; }
 
 
         public string Overview { get; set; }
         public string Overview { get; set; }
-        public string Tagline { get; set; }
+        public IEnumerable<string> Taglines { get; set; }
 
 
-        [IgnoreDataMember]
         public IEnumerable<PersonInfo> People { get; set; }
         public IEnumerable<PersonInfo> People { get; set; }
 
 
         public IEnumerable<string> Studios { get; set; }
         public IEnumerable<string> Studios { get; set; }
@@ -44,7 +43,7 @@ namespace MediaBrowser.Model.Entities
         public string DisplayMediaType { get; set; }
         public string DisplayMediaType { get; set; }
 
 
         public float? UserRating { get; set; }
         public float? UserRating { get; set; }
-        public int? RunTimeInMilliseconds { get; set; }
+        public long? RunTimeTicks { get; set; }
 
 
         public string AspectRatio { get; set; }
         public string AspectRatio { get; set; }
         public int? ProductionYear { get; set; }
         public int? ProductionYear { get; set; }
@@ -61,54 +60,52 @@ namespace MediaBrowser.Model.Entities
 
 
         public Dictionary<string, string> ProviderIds { get; set; }
         public Dictionary<string, string> ProviderIds { get; set; }
 
 
-        /// <summary>
-        /// Gets a provider id
-        /// </summary>
-        public string GetProviderId(MetadataProviders provider)
-        {
-            return GetProviderId(provider.ToString());
-        }
+        public Dictionary<Guid, UserItemData> UserData { get; set; }
 
 
-        /// <summary>
-        /// Gets a provider id
-        /// </summary>
-        public string GetProviderId(string name)
+        public UserItemData GetUserData(User user)
         {
         {
-            if (ProviderIds == null)
+            if (UserData == null || !UserData.ContainsKey(user.Id))
             {
             {
                 return null;
                 return null;
             }
             }
 
 
-            return ProviderIds[name];
+            return UserData[user.Id];
         }
         }
 
 
-        /// <summary>
-        /// Sets a provider id
-        /// </summary>
-        public void SetProviderId(string name, string value)
+        public void AddUserData(User user, UserItemData data)
         {
         {
-            if (ProviderIds == null)
+            if (UserData == null)
             {
             {
-                ProviderIds = new Dictionary<string, string>();
+                UserData = new Dictionary<Guid, UserItemData>();
             }
             }
 
 
-            ProviderIds[name] = value;
+            UserData[user.Id] = data;
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Sets a provider id
+        /// Determines if a given user has access to this item
         /// </summary>
         /// </summary>
-        public void SetProviderId(MetadataProviders provider, string value)
+        internal bool IsParentalAllowed(User user)
         {
         {
-            SetProviderId(provider.ToString(), value);
+            return true;
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// Determines if a given user has access to this item
+        /// Finds an item by ID, recursively
         /// </summary>
         /// </summary>
-        internal bool IsParentalAllowed(User user)
+        public virtual BaseItem FindItemById(Guid id)
         {
         {
-            return true;
+            if (Id == id)
+            {
+                return this;
+            }
+
+            if (LocalTrailers != null)
+            {
+                return LocalTrailers.FirstOrDefault(i => i.Id == id);
+            }
+
+            return null;
         }
         }
     }
     }
 }
 }

+ 105 - 39
MediaBrowser.Model/Entities/Folder.cs

@@ -1,8 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
-using System.Runtime.Serialization;
-using MediaBrowser.Model.Users;
 
 
 namespace MediaBrowser.Model.Entities
 namespace MediaBrowser.Model.Entities
 {
 {
@@ -18,7 +16,6 @@ namespace MediaBrowser.Model.Entities
             }
             }
         }
         }
 
 
-        [IgnoreDataMember]
         public BaseItem[] Children { get; set; }
         public BaseItem[] Children { get; set; }
 
 
         /// <summary>
         /// <summary>
@@ -50,6 +47,23 @@ namespace MediaBrowser.Model.Entities
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// Since it can be slow to make all of these calculations at once, this method will provide a way to get them all back together
+        /// </summary>
+        public ItemSpecialCounts GetSpecialCounts(User user)
+        {
+            ItemSpecialCounts counts = new ItemSpecialCounts();
+
+            IEnumerable<BaseItem> recursiveChildren = GetParentalAllowedRecursiveChildren(user);
+
+            counts.RecentlyAddedItemCount = GetRecentlyAddedItems(recursiveChildren, user).Count();
+            counts.RecentlyAddedUnPlayedItemCount = GetRecentlyAddedUnplayedItems(recursiveChildren, user).Count();
+            counts.InProgressItemCount = GetInProgressItems(recursiveChildren, user).Count();
+            counts.WatchedPercentage = GetWatchedPercentage(recursiveChildren, user);
+
+            return counts;
+        }
+
         /// <summary>
         /// <summary>
         /// Finds all recursive items within a top-level parent that contain the given genre and are allowed for the current user
         /// Finds all recursive items within a top-level parent that contain the given genre and are allowed for the current user
         /// </summary>
         /// </summary>
@@ -74,24 +88,33 @@ namespace MediaBrowser.Model.Entities
             return GetParentalAllowedRecursiveChildren(user).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase)));
             return GetParentalAllowedRecursiveChildren(user).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase)));
         }
         }
 
 
+        /// <summary>
+        /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user
+        /// </summary>
+        public IEnumerable<BaseItem> GetItemsWithPerson(string person, User user)
+        {
+            return GetParentalAllowedRecursiveChildren(user).Where(c =>
+            {
+                if (c.People != null)
+                {
+                    return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase));
+                }
+
+                return false;
+            });
+        }
+
         /// <summary>
         /// <summary>
         /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user
         /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user
         /// </summary>
         /// </summary>
         /// <param name="personType">Specify this to limit results to a specific PersonType</param>
         /// <param name="personType">Specify this to limit results to a specific PersonType</param>
-        public IEnumerable<BaseItem> GetItemsWithPerson(string person, PersonType? personType, User user)
+        public IEnumerable<BaseItem> GetItemsWithPerson(string person, string personType, User user)
         {
         {
             return GetParentalAllowedRecursiveChildren(user).Where(c =>
             return GetParentalAllowedRecursiveChildren(user).Where(c =>
             {
             {
                 if (c.People != null)
                 if (c.People != null)
                 {
                 {
-                    if (personType.HasValue)
-                    {
-                        return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase) && p.PersonType == personType.Value);
-                    }
-                    else
-                    {
-                        return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase));
-                    }
+                    return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase) && p.Type == personType);
                 }
                 }
 
 
                 return false;
                 return false;
@@ -103,9 +126,7 @@ namespace MediaBrowser.Model.Entities
         /// </summary>
         /// </summary>
         public IEnumerable<BaseItem> GetRecentlyAddedItems(User user)
         public IEnumerable<BaseItem> GetRecentlyAddedItems(User user)
         {
         {
-            DateTime now = DateTime.Now;
-
-            return GetParentalAllowedRecursiveChildren(user).Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < user.RecentItemDays);
+            return GetRecentlyAddedItems(GetParentalAllowedRecursiveChildren(user), user);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -113,12 +134,7 @@ namespace MediaBrowser.Model.Entities
         /// </summary>
         /// </summary>
         public IEnumerable<BaseItem> GetRecentlyAddedUnplayedItems(User user)
         public IEnumerable<BaseItem> GetRecentlyAddedUnplayedItems(User user)
         {
         {
-            return GetRecentlyAddedItems(user).Where(i =>
-            {
-                var userdata = user.GetItemData(i.Id);
-
-                return userdata == null || userdata.PlayCount == 0;
-            });
+            return GetRecentlyAddedUnplayedItems(GetParentalAllowedRecursiveChildren(user), user);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -126,45 +142,95 @@ namespace MediaBrowser.Model.Entities
         /// </summary>
         /// </summary>
         public IEnumerable<BaseItem> GetInProgressItems(User user)
         public IEnumerable<BaseItem> GetInProgressItems(User user)
         {
         {
-            return GetParentalAllowedRecursiveChildren(user).Where(i =>
+            return GetInProgressItems(GetParentalAllowedRecursiveChildren(user), user);
+        }
+
+        private static IEnumerable<BaseItem> GetRecentlyAddedItems(IEnumerable<BaseItem> itemSet, User user)
+        {
+            DateTime now = DateTime.Now;
+
+            return itemSet.Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < user.RecentItemDays);
+        }
+
+        private static IEnumerable<BaseItem> GetRecentlyAddedUnplayedItems(IEnumerable<BaseItem> itemSet, User user)
+        {
+            return GetRecentlyAddedItems(itemSet, user).Where(i =>
+            {
+                var userdata = i.GetUserData(user);
+
+                return userdata == null || userdata.PlayCount == 0;
+            });
+        }
+
+        private static IEnumerable<BaseItem> GetInProgressItems(IEnumerable<BaseItem> itemSet, User user)
+        {
+            return itemSet.Where(i =>
             {
             {
                 if (i is Folder)
                 if (i is Folder)
                 {
                 {
                     return false;
                     return false;
                 }
                 }
 
 
-                var userdata = user.GetItemData(i.Id);
+                var userdata = i.GetUserData(user);
 
 
-                return userdata != null && userdata.PlaybackPosition.Ticks > 0;
+                return userdata != null && userdata.PlaybackPositionTicks > 0;
             });
             });
         }
         }
 
 
+        private static decimal GetWatchedPercentage(IEnumerable<BaseItem> itemSet, User user)
+        {
+            itemSet = itemSet.Where(i => !(i is Folder));
+
+            if (!itemSet.Any())
+            {
+                return 0;
+            }
+
+            decimal totalPercent = 0;
+
+            foreach (BaseItem item in itemSet)
+            {
+                UserItemData data = item.GetUserData(user);
+
+                if (data == null)
+                {
+                    continue;
+                }
+
+                if (data.PlayCount > 0)
+                {
+                    totalPercent += 100;
+                }
+                else if (data.PlaybackPositionTicks > 0 && item.RunTimeTicks.HasValue)
+                {
+                    decimal itemPercent = data.PlaybackPositionTicks;
+                    itemPercent /= item.RunTimeTicks.Value;
+                    totalPercent += itemPercent;
+                }
+            }
+
+            return totalPercent / itemSet.Count();
+        }
+        
         /// <summary>
         /// <summary>
         /// Finds an item by ID, recursively
         /// Finds an item by ID, recursively
         /// </summary>
         /// </summary>
-        public BaseItem FindById(Guid id)
+        public override BaseItem FindItemById(Guid id)
         {
         {
-            if (Id == id)
+            var result = base.FindItemById(id);
+
+            if (result != null)
             {
             {
-                return this;
+                return result;
             }
             }
 
 
             foreach (BaseItem item in Children)
             foreach (BaseItem item in Children)
             {
             {
-                var folder = item as Folder;
+                result = item.FindItemById(id);
 
 
-                if (folder != null)
+                if (result != null)
                 {
                 {
-                    var foundItem = folder.FindById(id);
-
-                    if (foundItem != null)
-                    {
-                        return foundItem;
-                    }
-                }
-                else if (item.Id == id)
-                {
-                    return item;
+                    return result;
                 }
                 }
             }
             }
 
 

+ 57 - 0
MediaBrowser.Model/Entities/IHasProviderIds.cs

@@ -0,0 +1,57 @@
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.Entities
+{
+    /// <summary>
+    /// Since BaseItem and DTOBaseItem both have ProviderIds, this interface helps avoid code repition using extension methods
+    /// </summary>
+    public interface IHasProviderIds
+    {
+        Dictionary<string, string> ProviderIds { get; set; }
+    }
+
+    public static class IProviderIdsExtensions
+    {
+        /// <summary>
+        /// Gets a provider id
+        /// </summary>
+        public static string GetProviderId(this IHasProviderIds instance, MetadataProviders provider)
+        {
+            return instance.GetProviderId(provider.ToString());
+        }
+
+        /// <summary>
+        /// Gets a provider id
+        /// </summary>
+        public static string GetProviderId(this IHasProviderIds instance, string name)
+        {
+            if (instance.ProviderIds == null)
+            {
+                return null;
+            }
+
+            return instance.ProviderIds[name];
+        }
+
+        /// <summary>
+        /// Sets a provider id
+        /// </summary>
+        public static void SetProviderId(this IHasProviderIds instance, string name, string value)
+        {
+            if (instance.ProviderIds == null)
+            {
+                instance.ProviderIds = new Dictionary<string, string>();
+            }
+
+            instance.ProviderIds[name] = value;
+        }
+
+        /// <summary>
+        /// Sets a provider id
+        /// </summary>
+        public static void SetProviderId(this IHasProviderIds instance, MetadataProviders provider, string value)
+        {
+            instance.SetProviderId(provider.ToString(), value);
+        }
+    }
+}

+ 14 - 0
MediaBrowser.Model/Entities/ItemSpecialCounts.cs

@@ -0,0 +1,14 @@
+
+namespace MediaBrowser.Model.Entities
+{
+    /// <summary>
+    /// Since it can be slow to collect this data. This class helps provide a way to calculate them all at once.
+    /// </summary>
+    public class ItemSpecialCounts
+    {
+        public int RecentlyAddedItemCount { get; set; }
+        public int RecentlyAddedUnPlayedItemCount { get; set; }
+        public int InProgressItemCount { get; set; }
+        public decimal WatchedPercentage { get; set; }
+    }
+}

+ 1 - 10
MediaBrowser.Model/Entities/Person.cs

@@ -15,20 +15,11 @@ namespace MediaBrowser.Model.Entities
     {
     {
         public string Name { get; set; }
         public string Name { get; set; }
         public string Overview { get; set; }
         public string Overview { get; set; }
-        public PersonType PersonType { get; set; }
+        public string Type { get; set; }
 
 
         public override string ToString()
         public override string ToString()
         {
         {
             return Name;
             return Name;
         }
         }
     }
     }
-
-    public enum PersonType
-    {
-        Other,
-        Actor,
-        Director,
-        Writer,
-        Producer
-    }
 }
 }

+ 15 - 0
MediaBrowser.Model/Entities/User.cs

@@ -0,0 +1,15 @@
+
+namespace MediaBrowser.Model.Entities
+{
+    public class User : BaseEntity
+    {
+        public string MaxParentalRating { get; set; }
+
+        public int RecentItemDays { get; set; }
+
+        public User()
+        {
+            RecentItemDays = 14;
+        }
+    }
+}

+ 3 - 4
MediaBrowser.Model/Users/UserItemData.cs → MediaBrowser.Model/Entities/UserItemData.cs

@@ -1,13 +1,12 @@
-using MediaBrowser.Model.Entities;
-using System;
+using System;
 
 
-namespace MediaBrowser.Model.Users
+namespace MediaBrowser.Model.Entities
 {
 {
     public class UserItemData
     public class UserItemData
     {
     {
         public UserItemRating Rating { get; set; }
         public UserItemRating Rating { get; set; }
 
 
-        public TimeSpan PlaybackPosition { get; set; }
+        public long PlaybackPositionTicks { get; set; }
 
 
         public int PlayCount { get; set; }
         public int PlayCount { get; set; }
     }
     }

+ 8 - 9
MediaBrowser.Model/Entities/Video.cs

@@ -6,28 +6,27 @@ namespace MediaBrowser.Model.Entities
     {
     {
         public VideoType VideoType { get; set; }
         public VideoType VideoType { get; set; }
 
 
-        private IEnumerable<string> _Subtitles = new string[] { };
-        public IEnumerable<string> Subtitles { get { return _Subtitles; } set { _Subtitles = value; } }
-
-        private IEnumerable<AudioStream> _AudioStreams = new AudioStream[] { };
-        public IEnumerable<AudioStream> AudioStreams { get { return _AudioStreams; } set { _AudioStreams = value; } }
+        public IEnumerable<string> Subtitles { get; set; }
+        public IEnumerable<AudioStream> AudioStreams { get; set; }
 
 
         public int Height { get; set; }
         public int Height { get; set; }
         public int Width { get; set; }
         public int Width { get; set; }
         public string ScanType { get; set; }
         public string ScanType { get; set; }
         public string FrameRate { get; set; }
         public string FrameRate { get; set; }
-        public int VideoBitRate { get; set; }
-        public string VideoCodec { get; set; }
+        public int BitRate { get; set; }
+        public string Codec { get; set; }
     }
     }
 
 
     public class AudioStream
     public class AudioStream
     {
     {
-        public string AudioFormat { get; set; }
-        public string AudioProfile { get; set; }
+        public string Format { get; set; }
+        public string Profile { get; set; }
         public string Language { get; set; }
         public string Language { get; set; }
         public int BitRate { get; set; }
         public int BitRate { get; set; }
         public int Channels { get; set; }
         public int Channels { get; set; }
         public int SampleRate { get; set; }
         public int SampleRate { get; set; }
+        public bool IsDefault { get; set; }
+        public bool IsForced { get; set; }
     }
     }
 
 
     public enum VideoType
     public enum VideoType

+ 5 - 3
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -32,7 +32,7 @@
     <WarningLevel>4</WarningLevel>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   </PropertyGroup>
   <ItemGroup>
   <ItemGroup>
-    <Compile Include="DTO\ApiBaseItem.cs" />
+    <Compile Include="DTO\DTOBaseItem.cs" />
     <Compile Include="Entities\Audio.cs" />
     <Compile Include="Entities\Audio.cs" />
     <Compile Include="Entities\BaseEntity.cs" />
     <Compile Include="Entities\BaseEntity.cs" />
     <Compile Include="Entities\BaseItem.cs" />
     <Compile Include="Entities\BaseItem.cs" />
@@ -40,6 +40,8 @@
     <Compile Include="Entities\Folder.cs" />
     <Compile Include="Entities\Folder.cs" />
     <Compile Include="Entities\Genre.cs" />
     <Compile Include="Entities\Genre.cs" />
     <Compile Include="Entities\ImageType.cs" />
     <Compile Include="Entities\ImageType.cs" />
+    <Compile Include="Entities\IHasProviderIds.cs" />
+    <Compile Include="Entities\ItemSpecialCounts.cs" />
     <Compile Include="Entities\MetadataProviders.cs" />
     <Compile Include="Entities\MetadataProviders.cs" />
     <Compile Include="Entities\Person.cs" />
     <Compile Include="Entities\Person.cs" />
     <Compile Include="Entities\Studio.cs" />
     <Compile Include="Entities\Studio.cs" />
@@ -49,8 +51,8 @@
     <Compile Include="DTO\PluginInfo.cs" />
     <Compile Include="DTO\PluginInfo.cs" />
     <Compile Include="Progress\TaskProgress.cs" />
     <Compile Include="Progress\TaskProgress.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
-    <Compile Include="Users\User.cs" />
-    <Compile Include="Users\UserItemData.cs" />
+    <Compile Include="Entities\User.cs" />
+    <Compile Include="Entities\UserItemData.cs" />
   </ItemGroup>
   </ItemGroup>
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
   <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 0 - 34
MediaBrowser.Model/Users/User.cs

@@ -1,34 +0,0 @@
-using System;
-using System.Collections.Generic;
-using MediaBrowser.Model.Entities;
-
-namespace MediaBrowser.Model.Users
-{
-    public class User : BaseEntity
-    {
-        public string MaxParentalRating { get; set; }
-
-        private Dictionary<Guid, UserItemData> _ItemData = new Dictionary<Guid, UserItemData>();
-        public Dictionary<Guid, UserItemData> ItemData { get { return _ItemData; } set { _ItemData = value; } }
-
-        public int RecentItemDays { get; set; }
-
-        public User()
-        {
-            RecentItemDays = 14;
-        }
-
-        /// <summary>
-        /// Gets user data for an item, if there is any
-        /// </summary>
-        public UserItemData GetItemData(Guid itemId)
-        {
-            if (ItemData.ContainsKey(itemId))
-            {
-                return ItemData[itemId];
-            }
-
-            return null;
-        }
-    }
-}

+ 0 - 2
MediaBrowser.Movies/Entities/Movie.cs

@@ -1,12 +1,10 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Runtime.Serialization;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 
 
 namespace MediaBrowser.Movies.Entities
 namespace MediaBrowser.Movies.Entities
 {
 {
     public class Movie : Video
     public class Movie : Video
     {
     {
-        [IgnoreDataMember]
         public IEnumerable<Video> SpecialFeatures { get; set; }
         public IEnumerable<Video> SpecialFeatures { get; set; }
     }
     }
 }
 }

+ 0 - 1
MediaBrowser.TV/Entities/Season.cs

@@ -9,7 +9,6 @@ namespace MediaBrowser.TV.Entities
         /// <summary>
         /// <summary>
         /// Store these to reduce disk access in Episode Resolver
         /// Store these to reduce disk access in Episode Resolver
         /// </summary>
         /// </summary>
-        [IgnoreDataMember]
         internal IEnumerable<string> MetadataFiles { get; set; }
         internal IEnumerable<string> MetadataFiles { get; set; }
     }
     }
 }
 }

+ 1 - 1
MediaBrowser.TV/Metadata/SeriesXmlParser.cs

@@ -71,7 +71,7 @@ namespace MediaBrowser.TV.Metadata
                             int runtime;
                             int runtime;
                             if (int.TryParse(text.Split(' ')[0], out runtime))
                             if (int.TryParse(text.Split(' ')[0], out runtime))
                             {
                             {
-                                item.RunTimeInMilliseconds = runtime * 60000;
+                                item.RunTimeTicks = TimeSpan.FromMinutes(runtime).Ticks;
                             }
                             }
                         }
                         }
                         break;
                         break;