diff --git a/MediaBrowser.Api/HttpHandlers/GenreHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemsWithGenreHandler.cs
similarity index 87%
rename from MediaBrowser.Api/HttpHandlers/GenreHandler.cs
rename to MediaBrowser.Api/HttpHandlers/ItemsWithGenreHandler.cs
index 477705e82..16bb56196 100644
--- a/MediaBrowser.Api/HttpHandlers/GenreHandler.cs
+++ b/MediaBrowser.Api/HttpHandlers/ItemsWithGenreHandler.cs
@@ -7,7 +7,7 @@ namespace MediaBrowser.Api.HttpHandlers
///
/// Gets all items within a Genre
///
- public class GenreHandler : ItemListHandler
+ public class ItemsWithGenreHandler : ItemListHandler
{
protected override IEnumerable ItemsToSerialize
{
diff --git a/MediaBrowser.Api/HttpHandlers/StudioHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemsWithStudioHandler.cs
similarity index 87%
rename from MediaBrowser.Api/HttpHandlers/StudioHandler.cs
rename to MediaBrowser.Api/HttpHandlers/ItemsWithStudioHandler.cs
index 019ced028..30120d524 100644
--- a/MediaBrowser.Api/HttpHandlers/StudioHandler.cs
+++ b/MediaBrowser.Api/HttpHandlers/ItemsWithStudioHandler.cs
@@ -7,7 +7,7 @@ namespace MediaBrowser.Api.HttpHandlers
///
/// Gets all items within containing a studio
///
- public class StudioHandler : ItemListHandler
+ public class ItemsWithStudioHandler : ItemListHandler
{
protected override IEnumerable ItemsToSerialize
{
diff --git a/MediaBrowser.Api/HttpHandlers/ItemsWithYearHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemsWithYearHandler.cs
new file mode 100644
index 000000000..d5d4df444
--- /dev/null
+++ b/MediaBrowser.Api/HttpHandlers/ItemsWithYearHandler.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Api.HttpHandlers
+{
+ ///
+ /// Gets all items within containing a studio
+ ///
+ public class ItemsWithYearHandler : ItemListHandler
+ {
+ protected override IEnumerable ItemsToSerialize
+ {
+ get
+ {
+ Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
+
+ return Kernel.Instance.GetItemsWithYear(parent, int.Parse(QueryString["name"]), UserId);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs
new file mode 100644
index 000000000..6f4787028
--- /dev/null
+++ b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs
@@ -0,0 +1,20 @@
+using System;
+using MediaBrowser.Controller;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Api.HttpHandlers
+{
+ public class YearsHandler : JsonHandler
+ {
+ protected override object ObjectToSerialize
+ {
+ get
+ {
+ Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
+ Guid userId = Guid.Parse(QueryString["userid"]);
+
+ return Kernel.Instance.GetAllYears(parent, userId);
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 544dec6a9..0a295fba4 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -49,7 +49,7 @@
-
+
@@ -60,11 +60,13 @@
-
+
+
+
diff --git a/MediaBrowser.Api/Plugin.cs b/MediaBrowser.Api/Plugin.cs
index 353325316..efbd9725e 100644
--- a/MediaBrowser.Api/Plugin.cs
+++ b/MediaBrowser.Api/Plugin.cs
@@ -49,17 +49,25 @@ namespace MediaBrowser.Api
{
return new UsersHandler();
}
- else if (localPath.EndsWith("/api/genre", StringComparison.OrdinalIgnoreCase))
+ else if (localPath.EndsWith("/api/itemswithgenre", StringComparison.OrdinalIgnoreCase))
{
- return new GenreHandler();
+ return new ItemsWithGenreHandler();
}
else if (localPath.EndsWith("/api/genres", StringComparison.OrdinalIgnoreCase))
{
return new GenresHandler();
}
- else if (localPath.EndsWith("/api/studio", StringComparison.OrdinalIgnoreCase))
+ else if (localPath.EndsWith("/api/itemswithyear", StringComparison.OrdinalIgnoreCase))
{
- return new StudioHandler();
+ return new ItemsWithYearHandler();
+ }
+ else if (localPath.EndsWith("/api/years", StringComparison.OrdinalIgnoreCase))
+ {
+ return new YearsHandler();
+ }
+ else if (localPath.EndsWith("/api/itemswithstudio", StringComparison.OrdinalIgnoreCase))
+ {
+ return new ItemsWithStudioHandler();
}
else if (localPath.EndsWith("/api/studios", StringComparison.OrdinalIgnoreCase))
{
diff --git a/MediaBrowser.ApiInteraction/ApiClient.cs b/MediaBrowser.ApiInteraction/ApiClient.cs
index 5770ee2a4..f8c9170a7 100644
--- a/MediaBrowser.ApiInteraction/ApiClient.cs
+++ b/MediaBrowser.ApiInteraction/ApiClient.cs
@@ -184,15 +184,41 @@ namespace MediaBrowser.ApiInteraction
}
///
- /// Gets a Genre
+ /// Gets all Years
///
- public async Task> GetGenreAsync(string name, Guid userId)
+ public async Task>> GetAllYearsAsync(Guid userId)
{
- string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name;
+ string url = ApiUrl + "/years?userId=" + userId.ToString();
using (Stream stream = await HttpClient.GetStreamAsync(url))
{
- return JsonSerializer.DeserializeFromStream>(stream);
+ return JsonSerializer.DeserializeFromStream>>(stream);
+ }
+ }
+
+ ///
+ /// Gets a Year
+ ///
+ public async Task>> GetItemsWithYearAsync(string name, Guid userId)
+ {
+ string url = ApiUrl + "/itemswithyear?userId=" + userId.ToString() + "&name=" + name;
+
+ using (Stream stream = await HttpClient.GetStreamAsync(url))
+ {
+ return JsonSerializer.DeserializeFromStream>>(stream);
+ }
+ }
+
+ ///
+ /// Gets a Genre
+ ///
+ public async Task>> GetItemsWithGenreAsync(string name, Guid userId)
+ {
+ string url = ApiUrl + "/itemswithgenre?userId=" + userId.ToString() + "&name=" + name;
+
+ using (Stream stream = await HttpClient.GetStreamAsync(url))
+ {
+ return JsonSerializer.DeserializeFromStream>>(stream);
}
}
@@ -225,13 +251,13 @@ namespace MediaBrowser.ApiInteraction
///
/// Gets a Studio
///
- public async Task> GetStudioAsync(string name, Guid userId)
+ public async Task>> GetItemsWithStudioAsync(string name, Guid userId)
{
- string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name;
+ string url = ApiUrl + "/itemswithstudio?userId=" + userId.ToString() + "&name=" + name;
using (Stream stream = await HttpClient.GetStreamAsync(url))
{
- return JsonSerializer.DeserializeFromStream>(stream);
+ return JsonSerializer.DeserializeFromStream>>(stream);
}
}
}
diff --git a/MediaBrowser.Common/Configuration/ApplicationPaths.cs b/MediaBrowser.Common/Configuration/ApplicationPaths.cs
index 43cf4cf88..dc87749cf 100644
--- a/MediaBrowser.Common/Configuration/ApplicationPaths.cs
+++ b/MediaBrowser.Common/Configuration/ApplicationPaths.cs
@@ -175,7 +175,7 @@ namespace MediaBrowser.Common.Configuration
///
/// Gets the path to the Images By Name directory
///
- public static string IBNPath
+ public static string ImagesByNamePath
{
get
{
@@ -192,6 +192,90 @@ namespace MediaBrowser.Common.Configuration
}
}
+ private static string _PeoplePath;
+ ///
+ /// Gets the path to the People directory
+ ///
+ public static string PeoplePath
+ {
+ get
+ {
+ if (_PeoplePath == null)
+ {
+ _PeoplePath = Path.Combine(ImagesByNamePath, "People");
+ if (!Directory.Exists(_PeoplePath))
+ {
+ Directory.CreateDirectory(_PeoplePath);
+ }
+ }
+
+ return _PeoplePath;
+ }
+ }
+
+ private static string _GenrePath;
+ ///
+ /// Gets the path to the Genre directory
+ ///
+ public static string GenrePath
+ {
+ get
+ {
+ if (_GenrePath == null)
+ {
+ _GenrePath = Path.Combine(ImagesByNamePath, "Genre");
+ if (!Directory.Exists(_GenrePath))
+ {
+ Directory.CreateDirectory(_GenrePath);
+ }
+ }
+
+ return _GenrePath;
+ }
+ }
+
+ private static string _StudioPath;
+ ///
+ /// Gets the path to the Studio directory
+ ///
+ public static string StudioPath
+ {
+ get
+ {
+ if (_StudioPath == null)
+ {
+ _StudioPath = Path.Combine(ImagesByNamePath, "Studio");
+ if (!Directory.Exists(_StudioPath))
+ {
+ Directory.CreateDirectory(_StudioPath);
+ }
+ }
+
+ return _StudioPath;
+ }
+ }
+
+ private static string _yearPath;
+ ///
+ /// Gets the path to the Year directory
+ ///
+ public static string YearPath
+ {
+ get
+ {
+ if (_yearPath == null)
+ {
+ _yearPath = Path.Combine(ImagesByNamePath, "Year");
+ if (!Directory.Exists(_yearPath))
+ {
+ Directory.CreateDirectory(_yearPath);
+ }
+ }
+
+ return _yearPath;
+ }
+ }
+
///
/// Gets the path to the application's ProgramDataFolder
///
diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs
index 8eed678ba..a8baec835 100644
--- a/MediaBrowser.Controller/Kernel.cs
+++ b/MediaBrowser.Controller/Kernel.cs
@@ -314,6 +314,14 @@ namespace MediaBrowser.Controller
return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.Genres != null && f.Genres.Any(s => s.Equals(genre, StringComparison.OrdinalIgnoreCase)));
}
+ ///
+ /// Finds all recursive items within a top-level parent that contain the given year and are allowed for the current user
+ ///
+ public IEnumerable GetItemsWithYear(Folder parent, int year, Guid userId)
+ {
+ return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.ProductionYear.HasValue && f.ProductionYear == year);
+ }
+
///
/// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user
///
@@ -322,6 +330,57 @@ namespace MediaBrowser.Controller
return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.People != null && f.People.Any(s => s.Name.Equals(personName, StringComparison.OrdinalIgnoreCase)));
}
+ ///
+ /// Gets all years from all recursive children of a folder
+ /// The CategoryInfo class is used to keep track of the number of times each year appears
+ ///
+ public IEnumerable> GetAllYears(Folder parent, Guid userId)
+ {
+ Dictionary data = new Dictionary();
+
+ // Get all the allowed recursive children
+ IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId);
+
+ foreach (var item in allItems)
+ {
+ // Add the year from the item to the data dictionary
+ // If the year already exists, increment the count
+ if (item.ProductionYear == null)
+ {
+ continue;
+ }
+
+ if (!data.ContainsKey(item.ProductionYear.Value))
+ {
+ data.Add(item.ProductionYear.Value, 1);
+ }
+ else
+ {
+ data[item.ProductionYear.Value]++;
+ }
+ }
+
+ // Now go through the dictionary and create a Category for each studio
+ List> list = new List>();
+
+ foreach (int key in data.Keys)
+ {
+ // Get the original entity so that we can also supply the PrimaryImagePath
+ Year entity = Kernel.Instance.ItemController.GetYear(key);
+
+ if (entity != null)
+ {
+ list.Add(new CategoryInfo()
+ {
+ Item = entity,
+ ItemCount = data[key]
+ });
+ }
+ }
+
+ return list;
+ }
+
///
/// Gets all studios from all recursive children of a folder
/// The CategoryInfo class is used to keep track of the number of times each studio appears
@@ -441,7 +500,7 @@ namespace MediaBrowser.Controller
User user = new User();
user.Name = "Default User";
- user.Id = Guid.NewGuid();
+ user.Id = Guid.Parse("5d1cf7fce25943b790d140095457a42b");
list.Add(user);
diff --git a/MediaBrowser.Controller/Library/ItemController.cs b/MediaBrowser.Controller/Library/ItemController.cs
index cfca9e2cc..0c62ce7d9 100644
--- a/MediaBrowser.Controller/Library/ItemController.cs
+++ b/MediaBrowser.Controller/Library/ItemController.cs
@@ -8,6 +8,7 @@ using MediaBrowser.Controller.Events;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Common.Configuration;
namespace MediaBrowser.Controller.Library
{
@@ -57,41 +58,41 @@ namespace MediaBrowser.Controller.Library
}
#endregion
- #region Item Events
+ #region BaseItem Events
///
/// Called when an item is being created.
/// This should be used to fill item values, such as metadata
///
- public event EventHandler> ItemCreating;
+ public event EventHandler> BaseItemCreating;
///
/// Called when an item has been created.
/// This should be used to process or modify item values.
///
- public event EventHandler> ItemCreated;
+ public event EventHandler> BaseItemCreated;
#endregion
///
/// Called when an item has been created
///
- private void OnItemCreated(BaseItem item, Folder parent)
+ private void OnBaseItemCreated(BaseItem item, Folder parent)
{
GenericItemEventArgs args = new GenericItemEventArgs { Item = item };
- if (ItemCreating != null)
+ if (BaseItemCreating != null)
{
- ItemCreating(this, args);
+ BaseItemCreating(this, args);
}
- if (ItemCreated != null)
+ if (BaseItemCreated != null)
{
- ItemCreated(this, args);
+ BaseItemCreated(this, args);
}
}
private void FireCreateEventsRecursive(Folder folder, Folder parent)
{
- OnItemCreated(folder, parent);
+ OnBaseItemCreated(folder, parent);
int count = folder.Children.Length;
@@ -107,7 +108,7 @@ namespace MediaBrowser.Controller.Library
}
else
{
- OnItemCreated(item, folder);
+ OnBaseItemCreated(item, folder);
}
});
}
@@ -153,7 +154,7 @@ namespace MediaBrowser.Controller.Library
}
else
{
- OnItemCreated(item, parent);
+ OnBaseItemCreated(item, parent);
}
}
@@ -299,28 +300,98 @@ namespace MediaBrowser.Controller.Library
return returnFiles;
}
+ ///
+ /// Gets a Person
+ ///
public Person GetPerson(string name)
{
- // not yet implemented
- return null;
+ string path = Path.Combine(ApplicationPaths.PeoplePath, name);
+
+ return GetImagesByNameItem(path, name);
}
+ ///
+ /// Gets a Studio
+ ///
public Studio GetStudio(string name)
{
- // not yet implemented
- return null;
+ string path = Path.Combine(ApplicationPaths.StudioPath, name);
+
+ return GetImagesByNameItem(path, name);
}
+ ///
+ /// Gets a Genre
+ ///
public Genre GetGenre(string name)
{
- // not yet implemented
- return null;
+ string path = Path.Combine(ApplicationPaths.GenrePath, name);
+
+ return GetImagesByNameItem(path, name);
}
+ ///
+ /// Gets a Year
+ ///
public Year GetYear(int value)
{
- // not yet implemented
- return null;
+ string path = Path.Combine(ApplicationPaths.YearPath, value.ToString());
+
+ return GetImagesByNameItem(path, value.ToString());
+ }
+
+ private Dictionary ImagesByNameItemCache = new Dictionary();
+
+ ///
+ /// Generically retrieves an IBN item
+ ///
+ private T GetImagesByNameItem(string path, string name)
+ where T : BaseEntity, new()
+ {
+ string key = path.ToLower();
+
+ // Look for it in the cache, if it's not there, create it
+ if (!ImagesByNameItemCache.ContainsKey(key))
+ {
+ ImagesByNameItemCache[key] = CreateImagesByNameItem(path, name);
+ }
+
+ return ImagesByNameItemCache[key] as T;
+ }
+
+ ///
+ /// Creates an IBN item based on a given path
+ ///
+ private T CreateImagesByNameItem(string path, string name)
+ where T : BaseEntity, new ()
+ {
+ T item = new T();
+
+ item.Name = name;
+ item.Id = Kernel.GetMD5(path);
+
+ if (Directory.Exists(path))
+ {
+ item.DateCreated = Directory.GetCreationTime(path);
+ item.DateModified = Directory.GetLastAccessTime(path);
+ if (File.Exists(Path.Combine(path, "folder.jpg")))
+ {
+ item.PrimaryImagePath = Path.Combine(path, "folder.jpg");
+ }
+ else if (File.Exists(Path.Combine(path, "folder.png")))
+ {
+ item.PrimaryImagePath = Path.Combine(path, "folder.png");
+ }
+ }
+ else
+ {
+ DateTime now = DateTime.Now;
+
+ item.DateCreated = now;
+ item.DateModified = now;
+ }
+
+ return item;
}
}
}