2
0
Эх сурвалжийг харах

All calls to get items now require passing in a userId. Made the model project portable. Also filled in more api calls.

LukePulverenti Luke Pulverenti luke pulverenti 13 жил өмнө
parent
commit
6fbd5cf464
46 өөрчлөгдсөн 983 нэмэгдсэн , 407 устгасан
  1. 70 31
      MediaBrowser.Api/ApiService.cs
  2. 2 2
      MediaBrowser.Api/HttpHandlers/GenreHandler.cs
  3. 4 2
      MediaBrowser.Api/HttpHandlers/GenresHandler.cs
  4. 3 2
      MediaBrowser.Api/HttpHandlers/ImageHandler.cs
  5. 2 1
      MediaBrowser.Api/HttpHandlers/InProgressItemsHandler.cs
  6. 21 14
      MediaBrowser.Api/HttpHandlers/ItemHandler.cs
  7. 11 2
      MediaBrowser.Api/HttpHandlers/ItemListHandler.cs
  8. 2 1
      MediaBrowser.Api/HttpHandlers/PersonHandler.cs
  9. 3 2
      MediaBrowser.Api/HttpHandlers/RecentlyAddedItemsHandler.cs
  10. 28 0
      MediaBrowser.Api/HttpHandlers/StudioHandler.cs
  11. 26 0
      MediaBrowser.Api/HttpHandlers/StudiosHandler.cs
  12. 22 0
      MediaBrowser.Api/HttpHandlers/UsersHandler.cs
  13. 6 1
      MediaBrowser.Api/MediaBrowser.Api.csproj
  14. 15 0
      MediaBrowser.Api/Model/BaseItemInfo.cs
  15. 6 1
      MediaBrowser.Api/Plugin.cs
  16. 113 0
      MediaBrowser.Common/ApiInteraction/ApiController.cs
  17. 412 0
      MediaBrowser.Common/ApiInteraction/DictionaryBaseItem.cs
  18. 3 2
      MediaBrowser.Common/MediaBrowser.Common.csproj
  19. 0 227
      MediaBrowser.Common/Model/DictionaryBaseItem.cs
  20. 0 4
      MediaBrowser.Configuration/MediaBrowser.Configuration.csproj
  21. 126 1
      MediaBrowser.Controller/Kernel.cs
  22. 18 0
      MediaBrowser.Controller/Library/ItemController.cs
  23. 1 1
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  24. 1 1
      MediaBrowser.HtmlBrowser/MediaBrowser.HtmlBrowser.csproj
  25. 0 4
      MediaBrowser.InternetProviders/MediaBrowser.InternetProviders.csproj
  26. 2 0
      MediaBrowser.Model/Configuration/Configuration.cs
  27. 1 6
      MediaBrowser.Model/Entities/Audio.cs
  28. 1 11
      MediaBrowser.Model/Entities/BaseItem.cs
  29. 21 0
      MediaBrowser.Model/Entities/CategoryInfo.cs
  30. 0 13
      MediaBrowser.Model/Entities/Folder.cs
  31. 7 0
      MediaBrowser.Model/Entities/Genre.cs
  32. 5 9
      MediaBrowser.Model/Entities/Person.cs
  33. 0 12
      MediaBrowser.Model/Entities/PlaybackStatus.cs
  34. 7 0
      MediaBrowser.Model/Entities/Studio.cs
  35. 4 8
      MediaBrowser.Model/Entities/Video.cs
  36. 7 0
      MediaBrowser.Model/Entities/Year.cs
  37. 0 4
      MediaBrowser.Model/Logging/LogSeverity.cs
  38. 12 14
      MediaBrowser.Model/MediaBrowser.Model.csproj
  39. 3 9
      MediaBrowser.Model/Properties/AssemblyInfo.cs
  40. 0 4
      MediaBrowser.Model/Users/User.cs
  41. 5 7
      MediaBrowser.Model/Users/UserItemData.cs
  42. 3 2
      MediaBrowser.Movies/Entities/Movie.cs
  43. 2 1
      MediaBrowser.Movies/MediaBrowser.Movies.csproj
  44. 1 1
      MediaBrowser.Program/MediaBrowser.Program.csproj
  45. 1 1
      MediaBrowser.TV/MediaBrowser.TV.csproj
  46. 6 6
      MediaBrowser.sln

+ 70 - 31
MediaBrowser.Api/ApiService.cs

@@ -9,52 +9,91 @@ namespace MediaBrowser.Api
     {
         public static BaseItem GetItemById(string id)
         {
-            if (string.IsNullOrEmpty(id))
-            {
-                return Kernel.Instance.RootFolder;
-            }
+            Guid guid = string.IsNullOrEmpty(id) ? Guid.Empty : new Guid(id);
 
-            return GetItemById(new Guid(id));
+            return Kernel.Instance.GetItemById(guid);
         }
 
-        public static BaseItem GetItemById(Guid id)
+        public static IEnumerable<CategoryInfo> GetAllStudios(Folder parent, Guid userId)
         {
-            if (id == Guid.Empty)
+            Dictionary<string, int> data = new Dictionary<string, int>();
+            
+            IEnumerable<BaseItem> allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId);
+
+            foreach (var item in allItems)
             {
-                return Kernel.Instance.RootFolder;
+                if (item.Studios == null)
+                {
+                    continue;
+                }
+
+                foreach (string val in item.Studios)
+                {
+                    if (!data.ContainsKey(val))
+                    {
+                        data.Add(val, 1);
+                    }
+                    else
+                    {
+                        data[val]++;
+                    }
+                }
             }
 
-            return Kernel.Instance.RootFolder.FindById(id);
-        }
+            List<CategoryInfo> list = new List<CategoryInfo>();
 
-        public static Person GetPersonByName(string name)
-        {
-            return null;
-        }
+            foreach (string key in data.Keys)
+            {
+                list.Add(new CategoryInfo()
+                {
+                    Name = key,
+                    ItemCount = data[key]
 
-        public static IEnumerable<BaseItem> GetItemsWithGenre(Folder parent, string genre)
-        {
-            return new BaseItem[] { };
+                });
+            }
+            
+            return list;
         }
 
-        public static IEnumerable<string> GetAllGenres(Folder parent)
+        public static IEnumerable<CategoryInfo> GetAllGenres(Folder parent, Guid userId)
         {
-            return new string[] { };
-        }
+            Dictionary<string, int> data = new Dictionary<string, int>();
 
-        public static IEnumerable<BaseItem> GetRecentlyAddedItems(Folder parent)
-        {
-            return new BaseItem[] { };
-        }
+            IEnumerable<BaseItem> allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId);
 
-        public static IEnumerable<BaseItem> GetRecentlyAddedUnplayedItems(Folder parent)
-        {
-            return new BaseItem[] { };
-        }
+            foreach (var item in allItems)
+            {
+                if (item.Genres == null)
+                {
+                    continue;
+                }
 
-        public static IEnumerable<BaseItem> GetInProgressItems(Folder parent)
-        {
-            return new BaseItem[] { };
+                foreach (string val in item.Genres)
+                {
+                    if (!data.ContainsKey(val))
+                    {
+                        data.Add(val, 1);
+                    }
+                    else
+                    {
+                        data[val]++;
+                    }
+                }
+            }
+
+            List<CategoryInfo> list = new List<CategoryInfo>();
+
+            foreach (string key in data.Keys)
+            {
+                list.Add(new CategoryInfo()
+                {
+                    Name = key,
+                    ItemCount = data[key]
+
+                });
+            }
+
+            return list;
         }
     }
 }

+ 2 - 2
MediaBrowser.Api/HttpHandlers/GenreHandler.cs

@@ -1,7 +1,7 @@
 using System.Collections.Generic;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Api;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
@@ -21,7 +21,7 @@ namespace MediaBrowser.Api.HttpHandlers
             {
                 Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
 
-                return ApiService.GetItemsWithGenre(parent, QueryString["name"]);
+                return Kernel.Instance.GetItemsWithGenre(parent, QueryString["name"], UserId);
             }
         }
     }

+ 4 - 2
MediaBrowser.Api/HttpHandlers/GenresHandler.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Net;
+using System;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net.Handlers;
 using MediaBrowser.Model.Entities;
 
@@ -16,8 +17,9 @@ namespace MediaBrowser.Api.HttpHandlers
             get
             {
                 Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
+                Guid userId = Guid.Parse(QueryString["userid"]);
 
-                return ApiService.GetAllGenres(parent);
+                return ApiService.GetAllGenres(parent, userId);
             }
         }
     }

+ 3 - 2
MediaBrowser.Api/HttpHandlers/ImageHandler.cs

@@ -1,9 +1,10 @@
 using System;
 using System.IO;
+using System.IO.Compression;
 using System.Linq;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
-using System.IO.Compression;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
@@ -174,7 +175,7 @@ namespace MediaBrowser.Api.HttpHandlers
 
             if (!string.IsNullOrEmpty(personName))
             {
-                item = ApiService.GetPersonByName(personName);
+                item = Kernel.Instance.ItemController.GetPerson(personName);
             }
             else
             {

+ 2 - 1
MediaBrowser.Api/HttpHandlers/InProgressItemsHandler.cs

@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Api.HttpHandlers
@@ -17,7 +18,7 @@ namespace MediaBrowser.Api.HttpHandlers
             {
                 Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
 
-                return ApiService.GetInProgressItems(parent);
+                return Kernel.Instance.GetInProgressItems(parent, UserId);
             }
         }
     }

+ 21 - 14
MediaBrowser.Api/HttpHandlers/ItemHandler.cs

@@ -1,7 +1,9 @@
-using MediaBrowser.Common.Net;
+using System;
+using MediaBrowser.Api.Model;
+using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
-using MediaBrowser.Common.Json;
 
 namespace MediaBrowser.Api.HttpHandlers
 {
@@ -16,26 +18,31 @@ namespace MediaBrowser.Api.HttpHandlers
         {
             get
             {
-                return GetSerializationObject(ItemToSerialize, true);
+                Guid userId = Guid.Parse(QueryString["userid"]);
+
+                return GetSerializationObject(ItemToSerialize, true, userId);
             }
         }
 
-        public static object GetSerializationObject(BaseItem item, bool includeChildren)
+        public static object GetSerializationObject(BaseItem item, bool includeChildren, Guid userId)
         {
-            if (includeChildren && item.IsFolder)
+            BaseItemInfo wrapper = new BaseItemInfo()
             {
-                Folder folder = item as Folder;
+                Item = item,
+                UserItemData = Kernel.Instance.GetUserItemData(userId, item.Id)
+            };
 
-                return new
-                {
-                    BaseItem = item,
-                    Children = folder.Children
-                };
-            }
-            else
+            if (includeChildren)
             {
-                return item;
+                var folder = item as Folder;
+
+                if (folder != null)
+                {
+                    wrapper.Children = Kernel.Instance.GetParentalAllowedChildren(folder, userId);
+                }
             }
+
+            return wrapper;
         }
 
         protected virtual BaseItem ItemToSerialize

+ 11 - 2
MediaBrowser.Api/HttpHandlers/ItemListHandler.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Common.Net.Handlers;
@@ -19,7 +20,7 @@ namespace MediaBrowser.Api.HttpHandlers
             {
                 return ItemsToSerialize.Select(i =>
                 {
-                    return ItemHandler.GetSerializationObject(i, false);
+                    return ItemHandler.GetSerializationObject(i, false, UserId);
 
                 });
             }
@@ -29,5 +30,13 @@ namespace MediaBrowser.Api.HttpHandlers
         {
             get;
         }
+
+        protected Guid UserId
+        {
+            get
+            {
+                return Guid.Parse(QueryString["userid"]);
+            }
+        }
     }
 }

+ 2 - 1
MediaBrowser.Api/HttpHandlers/PersonHandler.cs

@@ -1,4 +1,5 @@
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Api.HttpHandlers
@@ -14,7 +15,7 @@ namespace MediaBrowser.Api.HttpHandlers
         {
             get
             {
-                return ApiService.GetPersonByName(QueryString["name"]);
+                return Kernel.Instance.ItemController.GetPerson(QueryString["name"]);
             }
         }
     }

+ 3 - 2
MediaBrowser.Api/HttpHandlers/RecentlyAddedItemsHandler.cs

@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
 using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Api.HttpHandlers
@@ -19,10 +20,10 @@ namespace MediaBrowser.Api.HttpHandlers
 
                 if (QueryString["unplayed"] == "1")
                 {
-                    return ApiService.GetRecentlyAddedUnplayedItems(parent);
+                    return Kernel.Instance.GetRecentlyAddedUnplayedItems(parent, UserId);
                 }
 
-                return ApiService.GetRecentlyAddedItems(parent);
+                return Kernel.Instance.GetRecentlyAddedItems(parent, UserId);
             }
         }
     }

+ 28 - 0
MediaBrowser.Api/HttpHandlers/StudioHandler.cs

@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Api.HttpHandlers
+{
+    /// <summary>
+    /// Gets all items within containing a studio
+    /// </summary>
+    public class StudioHandler : ItemListHandler
+    {
+        public StudioHandler(RequestContext ctx)
+            : base(ctx)
+        {
+        }
+
+        protected override IEnumerable<BaseItem> ItemsToSerialize
+        {
+            get
+            {
+                Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
+
+                return Kernel.Instance.GetItemsWithStudio(parent, QueryString["name"], UserId);
+            }
+        }
+    }
+}

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

@@ -0,0 +1,26 @@
+using System;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Api.HttpHandlers
+{
+    public class StudiosHandler : JsonHandler
+    {
+        public StudiosHandler(RequestContext ctx)
+            : base(ctx)
+        {
+        }
+
+        protected sealed override object ObjectToSerialize
+        {
+            get
+            {
+                Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
+                Guid userId = Guid.Parse(QueryString["userid"]);
+
+                return ApiService.GetAllStudios(parent, userId);
+            }
+        }
+    }
+}

+ 22 - 0
MediaBrowser.Api/HttpHandlers/UsersHandler.cs

@@ -0,0 +1,22 @@
+using MediaBrowser.Common.Net;
+using MediaBrowser.Common.Net.Handlers;
+using MediaBrowser.Controller;
+
+namespace MediaBrowser.Api.HttpHandlers
+{
+    class UsersHandler : JsonHandler
+    {
+        public UsersHandler(RequestContext ctx)
+            : base(ctx)
+        {
+        }
+
+        protected override object ObjectToSerialize
+        {
+            get
+            {
+                return Kernel.Instance.Users;
+            }
+        }
+    }
+}

+ 6 - 1
MediaBrowser.Api/MediaBrowser.Api.csproj

@@ -53,8 +53,12 @@
     <Compile Include="HttpHandlers\ItemListHandler.cs" />
     <Compile Include="HttpHandlers\PersonHandler.cs" />
     <Compile Include="HttpHandlers\RecentlyAddedItemsHandler.cs" />
+    <Compile Include="HttpHandlers\StudioHandler.cs" />
+    <Compile Include="HttpHandlers\StudiosHandler.cs" />
+    <Compile Include="HttpHandlers\UsersHandler.cs" />
     <Compile Include="ImageProcessor.cs" />
     <Compile Include="HttpHandlers\MediaHandler.cs" />
+    <Compile Include="Model\BaseItemInfo.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
@@ -68,13 +72,14 @@
       <Name>MediaBrowser.Controller</Name>
     </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
+      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <PropertyGroup>
     <PostBuildEvent>xcopy "$(TargetPath)" "$(SolutionDir)\ProgramData\Plugins\$(ProjectName)\" /y</PostBuildEvent>

+ 15 - 0
MediaBrowser.Api/Model/BaseItemInfo.cs

@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Users;
+
+namespace MediaBrowser.Api.Model
+{
+    public class BaseItemInfo
+    {
+        public BaseItem Item { get; set; }
+
+        public UserItemData UserItemData { get; set; }
+
+        public IEnumerable<BaseItem> Children { get; set; }
+    }
+}

+ 6 - 1
MediaBrowser.Api/Plugin.cs

@@ -1,5 +1,4 @@
 using System;
-using System.Collections.Generic;
 using System.Reactive.Linq;
 using MediaBrowser.Api.HttpHandlers;
 using MediaBrowser.Common.Plugins;
@@ -13,6 +12,8 @@ namespace MediaBrowser.Api
         {
             var httpServer = Kernel.Instance.HttpServer;
 
+            httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/users", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new UsersHandler(ctx)));
+
             httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/media", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new MediaHandler(ctx)));
 
             httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/item", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new ItemHandler(ctx)));
@@ -23,6 +24,10 @@ namespace MediaBrowser.Api
 
             httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/genres", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new GenresHandler(ctx)));
 
+            httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/studio", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new StudioHandler(ctx)));
+
+            httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/studios", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new StudiosHandler(ctx)));
+
             httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/recentlyaddeditems", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new RecentlyAddedItemsHandler(ctx)));
 
             httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/inprogressitems", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new InProgressItemsHandler(ctx)));

+ 113 - 0
MediaBrowser.Common/ApiInteraction/ApiController.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.IO.Compression;
+using System.Net;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Json;
+using MediaBrowser.Model.Users;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Common.ApiInteraction
+{
+    public class ApiController
+    {
+        public string ApiUrl { get; set; }
+
+        private WebClient WebClient { get; set; }
+
+        public ApiController()
+        {
+            WebClient = new WebClient();
+        }
+
+        public async Task<DictionaryBaseItem> GetRootItem(Guid userId)
+        {
+            string url = ApiUrl + "/item?userId=" + userId.ToString();
+
+            Stream stream = await WebClient.OpenReadTaskAsync(url);
+
+            using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
+            {
+                return DictionaryBaseItem.FromApiOutput(gzipStream);
+            }
+        }
+
+        public async Task<DictionaryBaseItem> GetItem(Guid id, Guid userId)
+        {
+            string url = ApiUrl + "/item?userId=" + userId.ToString();
+
+            if (id != Guid.Empty)
+            {
+                url += "&id=" + id.ToString();
+            }
+
+            Stream stream = await WebClient.OpenReadTaskAsync(url);
+
+            using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
+            {
+                return DictionaryBaseItem.FromApiOutput(gzipStream);
+            }
+        }
+
+        public async Task<IEnumerable<User>> GetAllUsers()
+        {
+            string url = ApiUrl + "/users";
+
+            Stream stream = await WebClient.OpenReadTaskAsync(url);
+
+            using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
+            {
+                return JsonSerializer.DeserializeFromStream<IEnumerable<User>>(gzipStream);
+            }
+        }
+
+        public async Task<IEnumerable<CategoryInfo>> GetAllGenres(Guid userId)
+        {
+            string url = ApiUrl + "/genres?userId=" + userId.ToString();
+
+            Stream stream = await WebClient.OpenReadTaskAsync(url);
+
+            using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
+            {
+                return JsonSerializer.DeserializeFromStream<IEnumerable<CategoryInfo>>(gzipStream);
+            }
+        }
+
+        public async Task<CategoryInfo> GetGenre(string name, Guid userId)
+        {
+            string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name;
+
+            Stream stream = await WebClient.OpenReadTaskAsync(url);
+
+            using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
+            {
+                return JsonSerializer.DeserializeFromStream<CategoryInfo>(gzipStream);
+            }
+        }
+
+        public async Task<IEnumerable<CategoryInfo>> GetAllStudios(Guid userId)
+        {
+            string url = ApiUrl + "/studios?userId=" + userId.ToString();
+
+            Stream stream = await WebClient.OpenReadTaskAsync(url);
+
+            using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
+            {
+                return JsonSerializer.DeserializeFromStream<IEnumerable<CategoryInfo>>(gzipStream);
+            }
+        }
+
+        public async Task<CategoryInfo> GetStudio(string name, Guid userId)
+        {
+            string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name;
+
+            Stream stream = await WebClient.OpenReadTaskAsync(url);
+
+            using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false))
+            {
+                return JsonSerializer.DeserializeFromStream<CategoryInfo>(gzipStream);
+            }
+        }
+    }
+}

+ 412 - 0
MediaBrowser.Common/ApiInteraction/DictionaryBaseItem.cs

@@ -0,0 +1,412 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using MediaBrowser.Common.Json;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Users;
+using System.Linq;
+
+namespace MediaBrowser.Common.ApiInteraction
+{
+    public class DictionaryBaseItem : BaseItem
+    {
+        private Dictionary<string, object> Dictionary { get; set; }
+
+        public UserItemData UserItemData { get; set; }
+        public IEnumerable<DictionaryBaseItem> Children { get; set; }
+
+        public DictionaryBaseItem(Dictionary<string, object> dictionary)
+        {
+            Dictionary = dictionary;
+        }
+
+        public override string Name
+        {
+            get
+            {
+                return GetString("Name");
+            }
+            set
+            {
+                SetValue("Name", value);
+            }
+        }
+
+        public override string ArtImagePath
+        {
+            get
+            {
+                return GetString("ArtImagePath");
+            }
+            set
+            {
+                SetValue("ArtImagePath", value);
+            }
+        }
+
+        public override string AspectRatio
+        {
+            get
+            {
+                return GetString("AspectRatio");
+            }
+            set
+            {
+                SetValue("AspectRatio", value);
+            }
+        }
+
+        public override string BannerImagePath
+        {
+            get
+            {
+                return GetString("BannerImagePath");
+            }
+            set
+            {
+                SetValue("BannerImagePath", value);
+            }
+        }
+
+        public override string CustomPin
+        {
+            get
+            {
+                return GetString("CustomPin");
+            }
+            set
+            {
+                SetValue("CustomPin", value);
+            }
+        }
+
+        public override string CustomRating
+        {
+            get
+            {
+                return GetString("CustomRating");
+            }
+            set
+            {
+                SetValue("CustomRating", value);
+            }
+        }
+
+        public override string DisplayMediaType
+        {
+            get
+            {
+                return GetString("DisplayMediaType");
+            }
+            set
+            {
+                SetValue("DisplayMediaType", value);
+            }
+        }
+
+        public override string LogoImagePath
+        {
+            get
+            {
+                return GetString("LogoImagePath");
+            }
+            set
+            {
+                SetValue("LogoImagePath", value);
+            }
+        }
+
+        public override string OfficialRating
+        {
+            get
+            {
+                return GetString("OfficialRating");
+            }
+            set
+            {
+                SetValue("OfficialRating", value);
+            }
+        }
+
+        public override string Overview
+        {
+            get
+            {
+                return GetString("Overview");
+            }
+            set
+            {
+                SetValue("Overview", value);
+            }
+        }
+
+        public override string Path
+        {
+            get
+            {
+                return GetString("Path");
+            }
+            set
+            {
+                SetValue("Path", value);
+            }
+        }
+
+        public override string PrimaryImagePath
+        {
+            get
+            {
+                return GetString("PrimaryImagePath");
+            }
+            set
+            {
+                SetValue("PrimaryImagePath", value);
+            }
+        }
+
+        public override string SortName
+        {
+            get
+            {
+                return GetString("SortName");
+            }
+            set
+            {
+                SetValue("SortName", value);
+            }
+        }
+
+        public override string Tagline
+        {
+            get
+            {
+                return GetString("Tagline");
+            }
+            set
+            {
+                SetValue("Tagline", value);
+            }
+        }
+
+        public override string TrailerUrl
+        {
+            get
+            {
+                return GetString("TrailerUrl");
+            }
+            set
+            {
+                SetValue("TrailerUrl", value);
+            }
+        }
+
+        public override DateTime DateCreated
+        {
+            get
+            {
+                return GetDateTime("DateCreated");
+            }
+            set
+            {
+                SetValue("DateCreated", value);
+            }
+        }
+
+        public override DateTime DateModified
+        {
+            get
+            {
+                return GetDateTime("DateModified");
+            }
+            set
+            {
+                SetValue("DateModified", value);
+            }
+        }
+
+        public override float? UserRating
+        {
+            get
+            {
+                return GetNullableFloat("UserRating");
+            }
+            set
+            {
+                SetValue("UserRating", value);
+            }
+        }
+
+        public override string ThumbnailImagePath
+        {
+            get
+            {
+                return GetString("ThumbnailImagePath");
+            }
+            set
+            {
+                SetValue("ThumbnailImagePath", value);
+            }
+        }
+
+        public override int? ProductionYear
+        {
+            get
+            {
+                return GetNullableInt("ProductionYear");
+            }
+            set
+            {
+                SetValue("ProductionYear", value);
+            }
+        }
+
+        public override TimeSpan? RunTime
+        {
+            get
+            {
+                return GetNullableTimeSpan("RunTime");
+            }
+            set
+            {
+                SetValue("RunTime", value);
+            }
+        }
+
+        public bool IsFolder
+        {
+            get
+            {
+                return GetBool("IsFolder");
+            }
+        }
+
+        public override Guid Id
+        {
+            get
+            {
+                return GetGuid("Id");
+            }
+            set
+            {
+                SetValue("Id", value);
+            }
+        }
+
+        public TimeSpan? GetNullableTimeSpan(string name)
+        {
+            string val = Dictionary[name] as string;
+
+            if (string.IsNullOrEmpty(val))
+            {
+                return null;
+            }
+
+            return TimeSpan.Parse(val);
+        }
+
+        public int? GetNullableInt(string name)
+        {
+            string val = Dictionary[name] as string;
+
+            if (string.IsNullOrEmpty(val))
+            {
+                return null;
+            }
+
+            return int.Parse(val);
+        }
+
+        public float? GetNullableFloat(string name)
+        {
+            string val = Dictionary[name] as string;
+
+            if (string.IsNullOrEmpty(val))
+            {
+                return null;
+            }
+
+            return float.Parse(val);
+        }
+
+        public DateTime? GetNullableDateTime(string name)
+        {
+            string val = Dictionary[name] as string;
+
+            if (string.IsNullOrEmpty(val))
+            {
+                return null;
+            }
+
+            return DateTime.Parse(val);
+        }
+
+        public DateTime GetDateTime(string name)
+        {
+            DateTime? val = GetNullableDateTime(name);
+
+            return val ?? DateTime.MinValue;
+        }
+
+        public bool? GetNullableBool(string name)
+        {
+            string val = Dictionary[name] as string;
+
+            if (string.IsNullOrEmpty(val))
+            {
+                return null;
+            }
+
+            return val != "false";
+        }
+
+        public Guid GetGuid(string name)
+        {
+            string val = GetString(name);
+
+            if (string.IsNullOrEmpty(val))
+            {
+                return Guid.Empty;
+            }
+
+            return Guid.Parse(val);
+        }
+
+        public bool GetBool(string name)
+        {
+            bool? val = GetNullableBool(name);
+
+            return val ?? false;
+        }
+
+        public string GetString(string name)
+        {
+            return Dictionary[name] as string;
+        }
+
+        private void SetValue<T>(string name, T value)
+        {
+            Dictionary[name] = value;
+        }
+
+        public static DictionaryBaseItem FromApiOutput(Stream stream)
+        {
+            Dictionary<string, object> data = JsonSerializer.DeserializeFromStream<Dictionary<string, object>>(stream);
+
+            string baseItem = data["Item"] as string;
+
+            DictionaryBaseItem item = new DictionaryBaseItem(JsonSerializer.DeserializeFromString<Dictionary<string, object>>(baseItem));
+
+            if (data.ContainsKey("UserItemData"))
+            {
+                item.UserItemData = JsonSerializer.DeserializeFromString<UserItemData>(data["UserItemData"].ToString());
+            }
+
+            if (data.ContainsKey("Children"))
+            {
+                item.Children = JsonSerializer.DeserializeFromString<IEnumerable<Dictionary<string, object>>>(data["Children"].ToString()).Select(c => new DictionaryBaseItem(c));
+            }
+
+            return item;
+        }
+    }
+}

+ 3 - 2
MediaBrowser.Common/MediaBrowser.Common.csproj

@@ -45,9 +45,10 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ApiInteraction\ApiController.cs" />
     <Compile Include="Events\GenericItemEventArgs.cs" />
     <Compile Include="Json\JsonSerializer.cs" />
-    <Compile Include="Model\DictionaryBaseItem.cs" />
+    <Compile Include="ApiInteraction\DictionaryBaseItem.cs" />
     <Compile Include="Net\CollectionExtensions.cs" />
     <Compile Include="Net\Handlers\BaseEmbeddedResourceHandler.cs" />
     <Compile Include="Net\Handlers\JsonHandler.cs" />
@@ -70,7 +71,7 @@
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
+      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>

+ 0 - 227
MediaBrowser.Common/Model/DictionaryBaseItem.cs

@@ -1,227 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Entities;
-using System.IO;
-using MediaBrowser.Common.Json;
-
-namespace MediaBrowser.Common.Model
-{
-    public class DictionaryBaseItem : BaseItem
-    {
-        private Dictionary<string, object> Dictionary { get; set; }
-
-        public DictionaryBaseItem(Dictionary<string, object> dictionary)
-        {
-            Dictionary = dictionary;
-        }
-
-        public override string Name
-        {
-            get
-            {
-                return GetString("Name");
-            }
-            set
-            {
-                SetValue("Name", value);
-            }
-        }
-
-        public override string ArtImagePath
-        {
-            get
-            {
-                return GetString("ArtImagePath");
-            }
-            set
-            {
-                SetValue("ArtImagePath", value);
-            }
-        }
-
-        public override string AspectRatio
-        {
-            get
-            {
-                return GetString("AspectRatio");
-            }
-            set
-            {
-                SetValue("AspectRatio", value);
-            }
-        }
-
-        public override string BannerImagePath
-        {
-            get
-            {
-                return GetString("BannerImagePath");
-            }
-            set
-            {
-                SetValue("BannerImagePath", value);
-            }
-        }
-
-        public override string CustomPin
-        {
-            get
-            {
-                return GetString("CustomPin");
-            }
-            set
-            {
-                SetValue("CustomPin", value);
-            }
-        }
-
-        public override string CustomRating
-        {
-            get
-            {
-                return GetString("CustomRating");
-            }
-            set
-            {
-                SetValue("CustomRating", value);
-            }
-        }
-
-        public override string DisplayMediaType
-        {
-            get
-            {
-                return GetString("DisplayMediaType");
-            }
-            set
-            {
-                SetValue("DisplayMediaType", value);
-            }
-        }
-
-        public override string LogoImagePath
-        {
-            get
-            {
-                return GetString("LogoImagePath");
-            }
-            set
-            {
-                SetValue("LogoImagePath", value);
-            }
-        }
-
-        public override string OfficialRating
-        {
-            get
-            {
-                return GetString("OfficialRating");
-            }
-            set
-            {
-                SetValue("OfficialRating", value);
-            }
-        }
-
-        public override string Overview
-        {
-            get
-            {
-                return GetString("Overview");
-            }
-            set
-            {
-                SetValue("Overview", value);
-            }
-        }
-
-        public override string Path
-        {
-            get
-            {
-                return GetString("Path");
-            }
-            set
-            {
-                SetValue("Path", value);
-            }
-        }
-
-        public override string PrimaryImagePath
-        {
-            get
-            {
-                return GetString("PrimaryImagePath");
-            }
-            set
-            {
-                SetValue("PrimaryImagePath", value);
-            }
-        }
-
-        public override string SortName
-        {
-            get
-            {
-                return GetString("SortName");
-            }
-            set
-            {
-                SetValue("SortName", value);
-            }
-        }
-
-        public override string Tagline
-        {
-            get
-            {
-                return GetString("Tagline");
-            }
-            set
-            {
-                SetValue("Tagline", value);
-            }
-        }
-
-        public override string TrailerUrl
-        {
-            get
-            {
-                return GetString("TrailerUrl");
-            }
-            set
-            {
-                SetValue("TrailerUrl", value);
-            }
-        }
-
-        private string GetString(string name)
-        {
-            return Dictionary[name] as string;
-        }
-
-        private void SetValue<T>(string name, T value)
-        {
-            Dictionary[name] = value;
-        }
-
-        public static DictionaryBaseItem FromApiOutput(Stream stream)
-        {
-            Dictionary<string,object> data = JsonSerializer.DeserializeFromStream<Dictionary<string, object>>(stream);
-
-            if (data.ContainsKey("BaseItem"))
-            {
-                string baseItem = data["BaseItem"] as string;
-
-                data = JsonSerializer.DeserializeFromString<Dictionary<string, object>>(baseItem);
-
-                return new DictionaryBaseItem(data);
-            }
-
-            return new DictionaryBaseItem(data);
-        }
-    }
-}

+ 0 - 4
MediaBrowser.Configuration/MediaBrowser.Configuration.csproj

@@ -55,10 +55,6 @@
       <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
       <Name>MediaBrowser.Controller</Name>
     </ProjectReference>
-    <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
-      <Name>MediaBrowser.Model</Name>
-    </ProjectReference>
   </ItemGroup>
   <ItemGroup>
     <None Include="packages.config" />

+ 126 - 1
MediaBrowser.Controller/Kernel.cs

@@ -84,7 +84,6 @@ namespace MediaBrowser.Controller
             // Get users from users folder
             // Load root media folder
             Parallel.Invoke(ReloadUsers, ReloadRoot);
-            var b = true;
         }
 
         private void ReloadConfiguration()
@@ -234,5 +233,131 @@ namespace MediaBrowser.Controller
                 item.Parent.Children = children.ToArray();
             }
         }
+
+        /// <summary>
+        /// Finds a library item by Id
+        /// </summary>
+        public BaseItem GetItemById(Guid id)
+        {
+            if (id == Guid.Empty)
+            {
+                return RootFolder;
+            }
+
+            return RootFolder.FindById(id);
+        }
+
+        /// <summary>
+        /// Determines if an item is allowed for a given user
+        /// </summary>
+        public bool IsParentalAllowed(BaseItem item, Guid userId)
+        {
+            // not yet implemented
+            return true;
+        }
+
+        /// <summary>
+        /// Gets allowed children of an item
+        /// </summary>
+        public IEnumerable<BaseItem> GetParentalAllowedChildren(Folder folder, Guid userId)
+        {
+            return folder.Children.ToList().Where(i => IsParentalAllowed(i, userId));
+        }
+
+        /// <summary>
+        /// Gets allowed recursive children of an item
+        /// </summary>
+        public IEnumerable<BaseItem> GetParentalAllowedRecursiveChildren(Folder folder, Guid userId)
+        {
+            foreach (var item in GetParentalAllowedChildren(folder, userId))
+            {
+                yield return item;
+
+                var subFolder = item as Folder;
+
+                if (subFolder != null)
+                {
+                    foreach (var subitem in GetParentalAllowedRecursiveChildren(subFolder, userId))
+                    {
+                        yield return subitem;
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets user data for an item, if there is any
+        /// </summary>
+        public UserItemData GetUserItemData(Guid userId, Guid itemId)
+        {
+            User user = Users.First(u => u.Id == userId);
+
+            if (user.ItemData.ContainsKey(itemId))
+            {
+                return user.ItemData[itemId];
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Gets all recently added items (recursive) within a folder, based on configuration and parental settings
+        /// </summary>
+        public IEnumerable<BaseItem> GetRecentlyAddedItems(Folder parent, Guid userId)
+        {
+            DateTime now = DateTime.Now;
+
+            return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => (now - i.DateCreated).TotalDays < Configuration.RecentItemDays);
+        }
+
+        /// <summary>
+        /// Gets all recently added unplayed items (recursive) within a folder, based on configuration and parental settings
+        /// </summary>
+        public IEnumerable<BaseItem> GetRecentlyAddedUnplayedItems(Folder parent, Guid userId)
+        {
+            return GetRecentlyAddedItems(parent, userId).Where(i =>
+            {
+                var userdata = GetUserItemData(userId, i.Id);
+
+                return userdata == null || userdata.PlayCount == 0;
+            });
+        }
+
+        /// <summary>
+        /// Gets all in-progress items (recursive) within a folder
+        /// </summary>
+        public IEnumerable<BaseItem> GetInProgressItems(Folder parent, Guid userId)
+        {
+            return GetParentalAllowedRecursiveChildren(parent, userId).Where(i =>
+            {
+                var userdata = GetUserItemData(userId, i.Id);
+
+                return userdata != null && userdata.PlaybackPosition.Ticks > 0;
+            });
+        }
+
+        /// <summary>
+        /// Finds all recursive items within a top-level parent that contain the given studio and are allowed for the current user
+        /// </summary>
+        public IEnumerable<BaseItem> GetItemsWithStudio(Folder parent, string studio, Guid userId)
+        {
+            return GetParentalAllowedRecursiveChildren(parent, userId).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 genre and are allowed for the current user
+        /// </summary>
+        public IEnumerable<BaseItem> GetItemsWithGenre(Folder parent, string genre, Guid userId)
+        {
+            return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.Genres != null && f.Genres.Any(s => s.Equals(genre, 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(Folder parent, string personName, Guid userId)
+        {
+            return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.People != null && f.People.Any(s => s.Name.Equals(personName, StringComparison.OrdinalIgnoreCase)));
+        }
     }
 }

+ 18 - 0
MediaBrowser.Controller/Library/ItemController.cs

@@ -310,5 +310,23 @@ namespace MediaBrowser.Controller.Library
 
             return returnFiles;
         }
+
+        public Person GetPerson(string name)
+        {
+            // not yet implemented
+            return null;
+        }
+
+        public Studio GetStudio(string name)
+        {
+            // not yet implemented
+            return null;
+        }
+
+        public Year GetYear(int value)
+        {
+            // not yet implemented
+            return null;
+        }
     }
 }

+ 1 - 1
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -63,7 +63,7 @@
       <Name>MediaBrowser.Common</Name>
     </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
+      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>

+ 1 - 1
MediaBrowser.HtmlBrowser/MediaBrowser.HtmlBrowser.csproj

@@ -56,7 +56,7 @@
       <Name>MediaBrowser.Controller</Name>
     </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
+      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>

+ 0 - 4
MediaBrowser.InternetProviders/MediaBrowser.InternetProviders.csproj

@@ -52,10 +52,6 @@
       <Project>{17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2}</Project>
       <Name>MediaBrowser.Controller</Name>
     </ProjectReference>
-    <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
-      <Name>MediaBrowser.Model</Name>
-    </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Movies\MediaBrowser.Movies.csproj">
       <Project>{92b9f802-4415-438f-90e1-44602135ea41}</Project>
       <Name>MediaBrowser.Movies</Name>

+ 2 - 0
MediaBrowser.Model/Configuration/Configuration.cs

@@ -6,11 +6,13 @@ namespace MediaBrowser.Model.Configuration
     {
         public string ImagesByNamePath { get; set; }
         public int HttpServerPortNumber { get; set; }
+        public int RecentItemDays { get; set; }
         public LogSeverity LogSeverity { get; set; }
 
         public Configuration()
         {
             HttpServerPortNumber = 8096;
+            RecentItemDays = 14;
             LogSeverity = LogSeverity.Info;
         }
     }

+ 1 - 6
MediaBrowser.Model/Entities/Audio.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
+
 namespace MediaBrowser.Model.Entities
 {
     public class Audio : BaseItem

+ 1 - 11
MediaBrowser.Model/Entities/BaseItem.cs

@@ -51,6 +51,7 @@ namespace MediaBrowser.Model.Entities
         public virtual string AspectRatio { get; set; }
         public virtual int? ProductionYear { get; set; }
 
+        [IgnoreDataMember]
         public virtual IEnumerable<Video> LocalTrailers { get; set; }
 
         public virtual string TrailerUrl { get; set; }
@@ -60,17 +61,6 @@ namespace MediaBrowser.Model.Entities
             return Name;
         }
 
-        /// <summary>
-        /// This is strictly to enhance json output, until I can find a way to customize service stack to add this without having to use a property
-        /// </summary>
-        public virtual bool IsFolder
-        {
-            get
-            {
-                return false;
-            }
-        }
-
         /// <summary>
         /// This is strictly to enhance json output, until I can find a way to customize service stack to add this without having to use a property
         /// </summary>

+ 21 - 0
MediaBrowser.Model/Entities/CategoryInfo.cs

@@ -0,0 +1,21 @@
+
+namespace MediaBrowser.Model.Entities
+{
+    /// <summary>
+    /// This is a stub class used by the api to get IBN types in a compact format
+    /// </summary>
+    public class CategoryInfo
+    {
+        /// <summary>
+        /// The name of the genre, year, studio, etc
+        /// </summary>
+        public string Name { get; set; }
+
+        public string PrimaryImagePath { get; set; }
+
+        /// <summary>
+        /// The number of items that have the genre, year, studio, etc
+        /// </summary>
+        public int ItemCount { get; set; }
+    }
+}

+ 0 - 13
MediaBrowser.Model/Entities/Folder.cs

@@ -18,25 +18,12 @@ namespace MediaBrowser.Model.Entities
             }
         }
 
-        public override bool IsFolder
-        {
-            get
-            {
-                return true;
-            }
-        }
-
         [IgnoreDataMember]
         public BaseItem[] Children { get; set; }
 
         [IgnoreDataMember]
         public IEnumerable<Folder> FolderChildren { get { return Children.OfType<Folder>(); } }
 
-        public Folder GetFolderByName(string name)
-        {
-            return FolderChildren.FirstOrDefault(f => System.IO.Path.GetFileName(f.Path).Equals(name, StringComparison.OrdinalIgnoreCase));
-        }
-
         /// <summary>
         /// Finds an item by ID, recursively
         /// </summary>

+ 7 - 0
MediaBrowser.Model/Entities/Genre.cs

@@ -0,0 +1,7 @@
+
+namespace MediaBrowser.Model.Entities
+{
+    public class Genre : BaseItem
+    {
+    }
+}

+ 5 - 9
MediaBrowser.Model/Entities/Person.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
+
 namespace MediaBrowser.Model.Entities
 {
     /// <summary>
@@ -26,8 +21,9 @@ namespace MediaBrowser.Model.Entities
 
     public enum PersonType
     {
-        Actor = 1,
-        Director = 2,
-        Writer = 3
+        Actor,
+        Director,
+        Writer,
+        Producer
     }
 }

+ 0 - 12
MediaBrowser.Model/Entities/PlaybackStatus.cs

@@ -1,12 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Model.Entities
-{
-    public class PlaybackStatus
-    {
-    }
-}

+ 7 - 0
MediaBrowser.Model/Entities/Studio.cs

@@ -0,0 +1,7 @@
+
+namespace MediaBrowser.Model.Entities
+{
+    public class Studio : BaseItem
+    {
+    }
+}

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

@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Generic;
 
 namespace MediaBrowser.Model.Entities
 {
@@ -35,8 +31,8 @@ namespace MediaBrowser.Model.Entities
 
     public enum VideoType
     {
-        VideoFile = 1,
-        DVD = 2,
-        BluRay = 3
+        VideoFile,
+        DVD,
+        BluRay
     }
 }

+ 7 - 0
MediaBrowser.Model/Entities/Year.cs

@@ -0,0 +1,7 @@
+
+namespace MediaBrowser.Model.Entities
+{
+    public class Year : BaseItem
+    {
+    }
+}

+ 0 - 4
MediaBrowser.Model/Logging/LogSeverity.cs

@@ -1,8 +1,4 @@
 using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace MediaBrowser.Model.Logging
 {

+ 12 - 14
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -4,13 +4,15 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{9B1DDD79-5134-4DF3-ACE3-D1957A7350D8}</ProjectGuid>
+    <ProjectGuid>{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}</ProjectGuid>
     <OutputType>Library</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>MediaBrowser.Model</RootNamespace>
     <AssemblyName>MediaBrowser.Model</AssemblyName>
-    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>Profile4</TargetFrameworkProfile>
     <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <DebugSymbols>true</DebugSymbols>
@@ -30,29 +32,25 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="System" />
-    <Reference Include="System.Core" />
-    <Reference Include="System.Runtime.Serialization" />
-    <Reference Include="System.Xml.Linq" />
-    <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Xml" />
+    <!-- A reference to the entire .NET Framework is automatically included -->
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Configuration\Configuration.cs" />
-    <Compile Include="Entities\Person.cs" />
     <Compile Include="Entities\Audio.cs" />
     <Compile Include="Entities\BaseItem.cs" />
+    <Compile Include="Entities\CategoryInfo.cs" />
     <Compile Include="Entities\Folder.cs" />
-    <Compile Include="Entities\PlaybackStatus.cs" />
+    <Compile Include="Entities\Genre.cs" />
+    <Compile Include="Entities\Person.cs" />
+    <Compile Include="Entities\Studio.cs" />
+    <Compile Include="Entities\Video.cs" />
+    <Compile Include="Entities\Year.cs" />
     <Compile Include="Logging\LogSeverity.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Users\User.cs" />
     <Compile Include="Users\UserItemData.cs" />
-    <Compile Include="Entities\Video.cs" />
   </ItemGroup>
-  <Import Project="$(MSBuildToolsPath)\Microsoft.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. 
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

+ 3 - 9
MediaBrowser.Model/Properties/AssemblyInfo.cs

@@ -1,4 +1,5 @@
-using System.Reflection;
+using System.Resources;
+using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
@@ -13,14 +14,7 @@ using System.Runtime.InteropServices;
 [assembly: AssemblyCopyright("Copyright ©  2012")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("4478b410-9582-4c22-b890-2a309708b9f1")]
+[assembly: NeutralResourcesLanguage("en")]
 
 // Version information for an assembly consists of the following four values:
 //

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

@@ -1,8 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using MediaBrowser.Model.Entities;
 
 namespace MediaBrowser.Model.Users
@@ -11,7 +8,6 @@ namespace MediaBrowser.Model.Users
     {
         public string Password { get; set; }
         public string MaxParentalRating { get; set; }
-        public bool HideBlockedContent { get; set; }
 
         private Dictionary<Guid, UserItemData> _ItemData = new Dictionary<Guid, UserItemData>();
         public Dictionary<Guid, UserItemData> ItemData { get { return _ItemData; } set { _ItemData = value; } }

+ 5 - 7
MediaBrowser.Model/Users/UserItemData.cs

@@ -1,9 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Entities;
+using System;
 
 namespace MediaBrowser.Model.Users
 {
@@ -11,7 +7,9 @@ namespace MediaBrowser.Model.Users
     {
         public UserItemRating Rating { get; set; }
 
-        public PlaybackStatus PlaybackStatus { get; set; }
+        public TimeSpan PlaybackPosition { get; set; }
+
+        public int PlayCount { get; set; }
     }
 
     public enum UserItemRating

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

@@ -1,6 +1,6 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using MediaBrowser.Model.Entities;
+using System.Runtime.Serialization;
 
 namespace MediaBrowser.Movies.Entities
 {
@@ -9,6 +9,7 @@ namespace MediaBrowser.Movies.Entities
         public string TmdbId { get; set; }
         public string ImdbId { get; set; }
 
+        [IgnoreDataMember]
         public IEnumerable<Video> SpecialFeatures { get; set; }
     }
 }

+ 2 - 1
MediaBrowser.Movies/MediaBrowser.Movies.csproj

@@ -32,6 +32,7 @@
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core" />
+    <Reference Include="System.Runtime.Serialization" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
     <Reference Include="Microsoft.CSharp" />
@@ -57,7 +58,7 @@
       <Name>MediaBrowser.Controller</Name>
     </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
+      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>

+ 1 - 1
MediaBrowser.Program/MediaBrowser.Program.csproj

@@ -58,7 +58,7 @@
       <Name>MediaBrowser.Controller</Name>
     </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
+      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>

+ 1 - 1
MediaBrowser.TV/MediaBrowser.TV.csproj

@@ -62,7 +62,7 @@
       <Name>MediaBrowser.Controller</Name>
     </ProjectReference>
     <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj">
-      <Project>{9b1ddd79-5134-4df3-ace3-d1957a7350d8}</Project>
+      <Project>{7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b}</Project>
       <Name>MediaBrowser.Model</Name>
     </ProjectReference>
   </ItemGroup>

+ 6 - 6
MediaBrowser.sln

@@ -1,8 +1,6 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 2012
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{9B1DDD79-5134-4DF3-ACE3-D1957A7350D8}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Movies", "MediaBrowser.Movies\MediaBrowser.Movies.csproj", "{92B9F802-4415-438F-90E1-44602135EA41}"
@@ -21,6 +19,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.HtmlBrowser",
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common", "MediaBrowser.Common\MediaBrowser.Common.csproj", "{9142EEFA-7570-41E1-BFCC-468BB571AF2F}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -47,6 +47,10 @@ Global
 		{78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU
 		{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -63,10 +67,6 @@ Global
 		{99B4CFE8-1441-4F0D-8C40-A70D0DD372ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{99B4CFE8-1441-4F0D-8C40-A70D0DD372ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{99B4CFE8-1441-4F0D-8C40-A70D0DD372ED}.Release|Any CPU.Build.0 = Release|Any CPU
-		{9B1DDD79-5134-4DF3-ACE3-D1957A7350D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{9B1DDD79-5134-4DF3-ACE3-D1957A7350D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{9B1DDD79-5134-4DF3-ACE3-D1957A7350D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{9B1DDD79-5134-4DF3-ACE3-D1957A7350D8}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE