Merge
This commit is contained in:
commit
5b7063e7c6
|
@ -1,8 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Threading.Tasks;
|
||||||
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;
|
||||||
|
@ -21,7 +20,7 @@ namespace MediaBrowser.Api
|
||||||
return Kernel.Instance.GetItemById(guid);
|
return Kernel.Instance.GetItemById(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DTOBaseItem GetDTOBaseItem(BaseItem item, User user,
|
public async static Task<DTOBaseItem> GetDTOBaseItem(BaseItem item, User user,
|
||||||
bool includeChildren = true,
|
bool includeChildren = true,
|
||||||
bool includePeople = true)
|
bool includePeople = true)
|
||||||
{
|
{
|
||||||
|
@ -79,16 +78,16 @@ namespace MediaBrowser.Api
|
||||||
|
|
||||||
dto.UserData = item.GetUserData(user);
|
dto.UserData = item.GetUserData(user);
|
||||||
|
|
||||||
AttachStudios(dto, item);
|
await AttachStudios(dto, item);
|
||||||
|
|
||||||
if (includeChildren)
|
if (includeChildren)
|
||||||
{
|
{
|
||||||
AttachChildren(dto, item, user);
|
await AttachChildren(dto, item, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includePeople)
|
if (includePeople)
|
||||||
{
|
{
|
||||||
AttachPeople(dto, item);
|
await AttachPeople(dto, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
Folder folder = item as Folder;
|
Folder folder = item as Folder;
|
||||||
|
@ -104,18 +103,20 @@ namespace MediaBrowser.Api
|
||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AttachStudios(DTOBaseItem dto, BaseItem item)
|
private static async Task 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)
|
||||||
{
|
{
|
||||||
|
IEnumerable<Studio> entities = await Task.WhenAll<Studio>(item.Studios.Select(c => Kernel.Instance.ItemController.GetStudio(c)));
|
||||||
|
|
||||||
dto.Studios = item.Studios.Select(s =>
|
dto.Studios = item.Studios.Select(s =>
|
||||||
{
|
{
|
||||||
BaseItemStudio baseItemStudio = new BaseItemStudio();
|
BaseItemStudio baseItemStudio = new BaseItemStudio();
|
||||||
|
|
||||||
baseItemStudio.Name = s;
|
baseItemStudio.Name = s;
|
||||||
|
|
||||||
Studio ibnObject = Kernel.Instance.ItemController.GetStudio(s);
|
Studio ibnObject = entities.First(i => i.Name.Equals(s, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (ibnObject != null)
|
if (ibnObject != null)
|
||||||
{
|
{
|
||||||
|
@ -127,30 +128,34 @@ namespace MediaBrowser.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AttachChildren(DTOBaseItem dto, BaseItem item, User user)
|
private static async Task AttachChildren(DTOBaseItem dto, BaseItem item, User user)
|
||||||
{
|
{
|
||||||
var folder = item as Folder;
|
var folder = item as Folder;
|
||||||
|
|
||||||
if (folder != null)
|
if (folder != null)
|
||||||
{
|
{
|
||||||
dto.Children = folder.GetParentalAllowedChildren(user).Select(c => GetDTOBaseItem(c, user, false, false));
|
IEnumerable<BaseItem> children = folder.GetParentalAllowedChildren(user);
|
||||||
|
|
||||||
|
dto.Children = await Task.WhenAll<DTOBaseItem>(children.Select(c => GetDTOBaseItem(c, user, false, false)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dto.LocalTrailers = item.LocalTrailers;
|
dto.LocalTrailers = item.LocalTrailers;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AttachPeople(DTOBaseItem dto, BaseItem item)
|
private static async Task AttachPeople(DTOBaseItem dto, BaseItem item)
|
||||||
{
|
{
|
||||||
// Attach People by transforming them into BaseItemPerson (DTO)
|
// Attach People by transforming them into BaseItemPerson (DTO)
|
||||||
if (item.People != null)
|
if (item.People != null)
|
||||||
{
|
{
|
||||||
|
IEnumerable<Person> entities = await Task.WhenAll<Person>(item.People.Select(c => Kernel.Instance.ItemController.GetPerson(c.Name)));
|
||||||
|
|
||||||
dto.People = item.People.Select(p =>
|
dto.People = item.People.Select(p =>
|
||||||
{
|
{
|
||||||
BaseItemPerson baseItemPerson = new BaseItemPerson();
|
BaseItemPerson baseItemPerson = new BaseItemPerson();
|
||||||
|
|
||||||
baseItemPerson.PersonInfo = p;
|
baseItemPerson.PersonInfo = p;
|
||||||
|
|
||||||
Person ibnObject = Kernel.Instance.ItemController.GetPerson(p.Name);
|
Person ibnObject = entities.First(i => i.Name.Equals(p.Name, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
if (ibnObject != null)
|
if (ibnObject != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,7 +5,6 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
|
||||||
using MediaBrowser.Common.Logging;
|
using MediaBrowser.Common.Logging;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
|
@ -91,20 +90,17 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ContentType
|
public override Task<string> GetContentType()
|
||||||
{
|
{
|
||||||
get
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
return MimeTypes.GetMimeType("." + GetConversionOutputFormat());
|
return MimeTypes.GetMimeType("." + GetConversionOutputFormat());
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CompressResponse
|
public override bool ShouldCompressResponse(string contentType)
|
||||||
{
|
{
|
||||||
get
|
return false;
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task ProcessRequest(HttpListenerContext ctx)
|
public override async Task ProcessRequest(HttpListenerContext ctx)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -13,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenreHandler : BaseJsonHandler<IBNItem<Genre>>
|
public class GenreHandler : BaseJsonHandler<IBNItem<Genre>>
|
||||||
{
|
{
|
||||||
protected override IBNItem<Genre> GetObjectToSerialize()
|
protected override async Task<IBNItem<Genre>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
|
@ -21,13 +22,13 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
|
|
||||||
string name = QueryString["name"];
|
string name = QueryString["name"];
|
||||||
|
|
||||||
return GetGenre(parent, user, name);
|
return await GetGenre(parent, user, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Genre
|
/// Gets a Genre
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IBNItem<Genre> GetGenre(Folder parent, User user, string name)
|
private async Task<IBNItem<Genre>> GetGenre(Folder parent, User user, string name)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
// Get the original entity so that we can also supply the PrimaryImagePath
|
// Get the original entity so that we can also supply the PrimaryImagePath
|
||||||
return new IBNItem<Genre>()
|
return new IBNItem<Genre>()
|
||||||
{
|
{
|
||||||
Item = Kernel.Instance.ItemController.GetGenre(name),
|
Item = await Kernel.Instance.ItemController.GetGenre(name),
|
||||||
BaseItemCount = count
|
BaseItemCount = count
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -10,20 +11,20 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
{
|
{
|
||||||
public class GenresHandler : BaseJsonHandler<IEnumerable<IBNItem<Genre>>>
|
public class GenresHandler : BaseJsonHandler<IEnumerable<IBNItem<Genre>>>
|
||||||
{
|
{
|
||||||
protected override IEnumerable<IBNItem<Genre>> GetObjectToSerialize()
|
protected override async Task<IEnumerable<IBNItem<Genre>>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
||||||
|
|
||||||
return GetAllGenres(parent, user);
|
return await GetAllGenres(parent, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all genres from all recursive children of a folder
|
/// Gets all genres from all recursive children of a folder
|
||||||
/// The CategoryInfo class is used to keep track of the number of times each genres appears
|
/// The CategoryInfo class is used to keep track of the number of times each genres appears
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IEnumerable<IBNItem<Genre>> GetAllGenres(Folder parent, User user)
|
private async Task<IEnumerable<IBNItem<Genre>>> GetAllGenres(Folder parent, User user)
|
||||||
{
|
{
|
||||||
Dictionary<string, int> data = new Dictionary<string, int>();
|
Dictionary<string, int> data = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
@ -52,25 +53,9 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now go through the dictionary and create a Category for each genre
|
IEnumerable<Genre> entities = await Task.WhenAll<Genre>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetGenre(key); }));
|
||||||
List<IBNItem<Genre>> list = new List<IBNItem<Genre>>();
|
|
||||||
|
|
||||||
foreach (string key in data.Keys)
|
return entities.Select(e => new IBNItem<Genre>() { Item = e, BaseItemCount = data[e.Name] });
|
||||||
{
|
|
||||||
// Get the original entity so that we can also supply the PrimaryImagePath
|
|
||||||
Genre entity = Kernel.Instance.ItemController.GetGenre(key);
|
|
||||||
|
|
||||||
if (entity != null)
|
|
||||||
{
|
|
||||||
list.Add(new IBNItem<Genre>()
|
|
||||||
{
|
|
||||||
Item = entity,
|
|
||||||
BaseItemCount = data[key]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,39 +13,57 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
public class ImageHandler : BaseHandler
|
public class ImageHandler : BaseHandler
|
||||||
{
|
{
|
||||||
private string _ImagePath = null;
|
private string _ImagePath = null;
|
||||||
private string ImagePath
|
private async Task<string> GetImagePath()
|
||||||
{
|
{
|
||||||
get
|
if (_ImagePath == null)
|
||||||
{
|
{
|
||||||
if (_ImagePath == null)
|
_ImagePath = await DiscoverImagePath();
|
||||||
{
|
|
||||||
_ImagePath = GetImagePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _ImagePath;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return _ImagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> DiscoverImagePath()
|
||||||
|
{
|
||||||
|
string path = QueryString["path"] ?? string.Empty;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
string personName = QueryString["personname"];
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(personName))
|
||||||
|
{
|
||||||
|
Person person = await Kernel.Instance.ItemController.GetPerson(personName);
|
||||||
|
|
||||||
|
return person.PrimaryImagePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseItem item = ApiService.GetItemById(QueryString["id"]);
|
||||||
|
|
||||||
|
string imageIndex = QueryString["index"];
|
||||||
|
int index = string.IsNullOrEmpty(imageIndex) ? 0 : int.Parse(imageIndex);
|
||||||
|
|
||||||
|
return GetImagePathFromTypes(item, ImageType, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream _SourceStream = null;
|
private Stream _SourceStream = null;
|
||||||
private Stream SourceStream
|
private async Task<Stream> GetSourceStream()
|
||||||
{
|
{
|
||||||
get
|
await EnsureSourceStream();
|
||||||
{
|
return _SourceStream;
|
||||||
EnsureSourceStream();
|
|
||||||
|
|
||||||
return _SourceStream;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private bool _SourceStreamEnsured = false;
|
private bool _SourceStreamEnsured = false;
|
||||||
private void EnsureSourceStream()
|
private async Task EnsureSourceStream()
|
||||||
{
|
{
|
||||||
if (!_SourceStreamEnsured)
|
if (!_SourceStreamEnsured)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_SourceStream = File.OpenRead(ImagePath);
|
_SourceStream = File.OpenRead(await GetImagePath());
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException ex)
|
catch (FileNotFoundException ex)
|
||||||
{
|
{
|
||||||
|
@ -68,20 +86,17 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ContentType
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
EnsureSourceStream();
|
|
||||||
|
|
||||||
if (SourceStream == null)
|
public async override Task<string> GetContentType()
|
||||||
{
|
{
|
||||||
return null;
|
await EnsureSourceStream();
|
||||||
}
|
|
||||||
|
if (await GetSourceStream() == null)
|
||||||
return MimeTypes.GetMimeType(ImagePath);
|
{
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MimeTypes.GetMimeType(await GetImagePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
public override TimeSpan CacheDuration
|
public override TimeSpan CacheDuration
|
||||||
|
@ -92,16 +107,16 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DateTime? GetLastDateModified()
|
protected async override Task<DateTime?> GetLastDateModified()
|
||||||
{
|
{
|
||||||
EnsureSourceStream();
|
await EnsureSourceStream();
|
||||||
|
|
||||||
if (SourceStream == null)
|
if (await GetSourceStream() == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return File.GetLastWriteTime(ImagePath);
|
return File.GetLastWriteTime(await GetImagePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int? Height
|
private int? Height
|
||||||
|
@ -194,36 +209,9 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Task WriteResponseToOutputStream(Stream stream)
|
protected override async Task WriteResponseToOutputStream(Stream stream)
|
||||||
{
|
{
|
||||||
return Task.Run(() =>
|
ImageProcessor.ProcessImage(await GetSourceStream(), stream, Width, Height, MaxWidth, MaxHeight, Quality);
|
||||||
{
|
|
||||||
ImageProcessor.ProcessImage(SourceStream, stream, Width, Height, MaxWidth, MaxHeight, Quality);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetImagePath()
|
|
||||||
{
|
|
||||||
string path = QueryString["path"] ?? string.Empty;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(path))
|
|
||||||
{
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
string personName = QueryString["personname"];
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(personName))
|
|
||||||
{
|
|
||||||
return Kernel.Instance.ItemController.GetPerson(personName).PrimaryImagePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
BaseItem item = ApiService.GetItemById(QueryString["id"]);
|
|
||||||
|
|
||||||
string imageIndex = QueryString["index"];
|
|
||||||
int index = string.IsNullOrEmpty(imageIndex) ? 0 : int.Parse(imageIndex);
|
|
||||||
|
|
||||||
return GetImagePathFromTypes(item, ImageType, index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetImagePathFromTypes(BaseItem item, ImageType imageType, int imageIndex)
|
private string GetImagePathFromTypes(BaseItem item, ImageType imageType, int imageIndex)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -9,7 +10,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
{
|
{
|
||||||
public class ItemHandler : BaseJsonHandler<DTOBaseItem>
|
public class ItemHandler : BaseJsonHandler<DTOBaseItem>
|
||||||
{
|
{
|
||||||
protected sealed override DTOBaseItem GetObjectToSerialize()
|
protected async override Task<DTOBaseItem> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
||||||
|
@ -21,7 +22,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ApiService.GetDTOBaseItem(item, user);
|
return await ApiService.GetDTOBaseItem(item, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual BaseItem ItemToSerialize
|
protected virtual BaseItem ItemToSerialize
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -10,14 +11,14 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
{
|
{
|
||||||
public class ItemListHandler : BaseJsonHandler<IEnumerable<DTOBaseItem>>
|
public class ItemListHandler : BaseJsonHandler<IEnumerable<DTOBaseItem>>
|
||||||
{
|
{
|
||||||
protected override IEnumerable<DTOBaseItem> GetObjectToSerialize()
|
protected override async Task<IEnumerable<DTOBaseItem>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
User user = Kernel.Instance.Users.First(u => u.Id == UserId);
|
User user = Kernel.Instance.Users.First(u => u.Id == UserId);
|
||||||
|
|
||||||
return ItemsToSerialize.Select(i =>
|
return await Task.WhenAll<DTOBaseItem>(ItemsToSerialize.Select(i =>
|
||||||
{
|
{
|
||||||
return ApiService.GetDTOBaseItem(i, user, includeChildren: false, includePeople: false);
|
return ApiService.GetDTOBaseItem(i, user, includeChildren: false, includePeople: false);
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected IEnumerable<BaseItem> ItemsToSerialize
|
protected IEnumerable<BaseItem> ItemsToSerialize
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -13,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PersonHandler : BaseJsonHandler<IBNItem<Person>>
|
public class PersonHandler : BaseJsonHandler<IBNItem<Person>>
|
||||||
{
|
{
|
||||||
protected override IBNItem<Person> GetObjectToSerialize()
|
protected async override Task<IBNItem<Person>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
|
@ -21,13 +22,13 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
|
|
||||||
string name = QueryString["name"];
|
string name = QueryString["name"];
|
||||||
|
|
||||||
return GetPerson(parent, user, name);
|
return await GetPerson(parent, user, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Person
|
/// Gets a Person
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IBNItem<Person> GetPerson(Folder parent, User user, string name)
|
private async Task<IBNItem<Person>> GetPerson(Folder parent, User user, string name)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
// Get the original entity so that we can also supply the PrimaryImagePath
|
// Get the original entity so that we can also supply the PrimaryImagePath
|
||||||
return new IBNItem<Person>()
|
return new IBNItem<Person>()
|
||||||
{
|
{
|
||||||
Item = Kernel.Instance.ItemController.GetPerson(name),
|
Item = await Kernel.Instance.ItemController.GetPerson(name),
|
||||||
BaseItemCount = count
|
BaseItemCount = count
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
|
@ -8,11 +9,14 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
{
|
{
|
||||||
public class PluginConfigurationHandler : BaseJsonHandler<BasePluginConfiguration>
|
public class PluginConfigurationHandler : BaseJsonHandler<BasePluginConfiguration>
|
||||||
{
|
{
|
||||||
protected override BasePluginConfiguration GetObjectToSerialize()
|
protected override Task<BasePluginConfiguration> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
string pluginName = QueryString["name"];
|
return Task.Run(() =>
|
||||||
|
{
|
||||||
|
string pluginName = QueryString["name"];
|
||||||
|
|
||||||
return Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
|
return Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -11,26 +12,29 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PluginsHandler : BaseJsonHandler<IEnumerable<PluginInfo>>
|
public class PluginsHandler : BaseJsonHandler<IEnumerable<PluginInfo>>
|
||||||
{
|
{
|
||||||
protected override IEnumerable<PluginInfo> GetObjectToSerialize()
|
protected override Task<IEnumerable<PluginInfo>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
var plugins = Kernel.Instance.Plugins.Select(p =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
return new PluginInfo()
|
var plugins = Kernel.Instance.Plugins.Select(p =>
|
||||||
{
|
{
|
||||||
Path = p.Path,
|
return new PluginInfo()
|
||||||
Name = p.Name,
|
{
|
||||||
Enabled = p.Enabled,
|
Path = p.Path,
|
||||||
DownloadToUI = p.DownloadToUI,
|
Name = p.Name,
|
||||||
Version = p.Version
|
Enabled = p.Enabled,
|
||||||
};
|
DownloadToUI = p.DownloadToUI,
|
||||||
|
Version = p.Version
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
if (QueryString["uionly"] == "1")
|
||||||
|
{
|
||||||
|
plugins = plugins.Where(p => p.DownloadToUI);
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugins;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (QueryString["uionly"] == "1")
|
|
||||||
{
|
|
||||||
plugins = plugins.Where(p => p.DownloadToUI);
|
|
||||||
}
|
|
||||||
|
|
||||||
return plugins;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -13,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StudioHandler : BaseJsonHandler<IBNItem<Studio>>
|
public class StudioHandler : BaseJsonHandler<IBNItem<Studio>>
|
||||||
{
|
{
|
||||||
protected override IBNItem<Studio> GetObjectToSerialize()
|
protected async override Task<IBNItem<Studio>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
|
@ -21,13 +22,13 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
|
|
||||||
string name = QueryString["name"];
|
string name = QueryString["name"];
|
||||||
|
|
||||||
return GetStudio(parent, user, name);
|
return await GetStudio(parent, user, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Studio
|
/// Gets a Studio
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IBNItem<Studio> GetStudio(Folder parent, User user, string name)
|
private async Task<IBNItem<Studio>> GetStudio(Folder parent, User user, string name)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
// Get the original entity so that we can also supply the PrimaryImagePath
|
// Get the original entity so that we can also supply the PrimaryImagePath
|
||||||
return new IBNItem<Studio>()
|
return new IBNItem<Studio>()
|
||||||
{
|
{
|
||||||
Item = Kernel.Instance.ItemController.GetStudio(name),
|
Item = await Kernel.Instance.ItemController.GetStudio(name),
|
||||||
BaseItemCount = count
|
BaseItemCount = count
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -10,20 +11,20 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
{
|
{
|
||||||
public class StudiosHandler : BaseJsonHandler<IEnumerable<IBNItem<Studio>>>
|
public class StudiosHandler : BaseJsonHandler<IEnumerable<IBNItem<Studio>>>
|
||||||
{
|
{
|
||||||
protected override IEnumerable<IBNItem<Studio>> GetObjectToSerialize()
|
protected override async Task<IEnumerable<IBNItem<Studio>>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
||||||
|
|
||||||
return GetAllStudios(parent, user);
|
return await GetAllStudios(parent, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all studios from all recursive children of a folder
|
/// 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
|
/// The CategoryInfo class is used to keep track of the number of times each studio appears
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IEnumerable<IBNItem<Studio>> GetAllStudios(Folder parent, User user)
|
private async Task<IEnumerable<IBNItem<Studio>>> GetAllStudios(Folder parent, User user)
|
||||||
{
|
{
|
||||||
Dictionary<string, int> data = new Dictionary<string, int>();
|
Dictionary<string, int> data = new Dictionary<string, int>();
|
||||||
|
|
||||||
|
@ -52,25 +53,9 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now go through the dictionary and create a Category for each studio
|
IEnumerable<Studio> entities = await Task.WhenAll<Studio>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetStudio(key); }));
|
||||||
List<IBNItem<Studio>> list = new List<IBNItem<Studio>>();
|
|
||||||
|
|
||||||
foreach (string key in data.Keys)
|
return entities.Select(e => new IBNItem<Studio>() { Item = e, BaseItemCount = data[e.Name] });
|
||||||
{
|
|
||||||
// Get the original entity so that we can also supply the PrimaryImagePath
|
|
||||||
Studio entity = Kernel.Instance.ItemController.GetStudio(key);
|
|
||||||
|
|
||||||
if (entity != null)
|
|
||||||
{
|
|
||||||
list.Add(new IBNItem<Studio>()
|
|
||||||
{
|
|
||||||
Item = entity,
|
|
||||||
BaseItemCount = data[key]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
@ -7,9 +8,12 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
{
|
{
|
||||||
class UsersHandler : BaseJsonHandler<IEnumerable<User>>
|
class UsersHandler : BaseJsonHandler<IEnumerable<User>>
|
||||||
{
|
{
|
||||||
protected override IEnumerable<User> GetObjectToSerialize()
|
protected override Task<IEnumerable<User>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
return Kernel.Instance.Users;
|
return Task.Run(() =>
|
||||||
|
{
|
||||||
|
return Kernel.Instance.Users;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -13,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class YearHandler : BaseJsonHandler<IBNItem<Year>>
|
public class YearHandler : BaseJsonHandler<IBNItem<Year>>
|
||||||
{
|
{
|
||||||
protected override IBNItem<Year> GetObjectToSerialize()
|
protected override async Task<IBNItem<Year>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
|
@ -21,13 +22,13 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
|
|
||||||
string year = QueryString["year"];
|
string year = QueryString["year"];
|
||||||
|
|
||||||
return GetYear(parent, user, int.Parse(year));
|
return await GetYear(parent, user, int.Parse(year));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Year
|
/// Gets a Year
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IBNItem<Year> GetYear(Folder parent, User user, int year)
|
private async Task<IBNItem<Year>> GetYear(Folder parent, User user, int year)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
// Get the original entity so that we can also supply the PrimaryImagePath
|
// Get the original entity so that we can also supply the PrimaryImagePath
|
||||||
return new IBNItem<Year>()
|
return new IBNItem<Year>()
|
||||||
{
|
{
|
||||||
Item = Kernel.Instance.ItemController.GetYear(year),
|
Item = await Kernel.Instance.ItemController.GetYear(year),
|
||||||
BaseItemCount = count
|
BaseItemCount = count
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Net.Handlers;
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.DTO;
|
using MediaBrowser.Model.DTO;
|
||||||
|
@ -10,20 +11,20 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
{
|
{
|
||||||
public class YearsHandler : BaseJsonHandler<IEnumerable<IBNItem<Year>>>
|
public class YearsHandler : BaseJsonHandler<IEnumerable<IBNItem<Year>>>
|
||||||
{
|
{
|
||||||
protected override IEnumerable<IBNItem<Year>> GetObjectToSerialize()
|
protected override async Task<IEnumerable<IBNItem<Year>>> GetObjectToSerialize()
|
||||||
{
|
{
|
||||||
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder;
|
||||||
Guid userId = Guid.Parse(QueryString["userid"]);
|
Guid userId = Guid.Parse(QueryString["userid"]);
|
||||||
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
User user = Kernel.Instance.Users.First(u => u.Id == userId);
|
||||||
|
|
||||||
return GetAllYears(parent, user);
|
return await GetAllYears(parent, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets all years from all recursive children of a folder
|
/// 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
|
/// The CategoryInfo class is used to keep track of the number of times each year appears
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private IEnumerable<IBNItem<Year>> GetAllYears(Folder parent, User user)
|
private async Task<IEnumerable<IBNItem<Year>>> GetAllYears(Folder parent, User user)
|
||||||
{
|
{
|
||||||
Dictionary<int, int> data = new Dictionary<int, int>();
|
Dictionary<int, int> data = new Dictionary<int, int>();
|
||||||
|
|
||||||
|
@ -49,25 +50,9 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now go through the dictionary and create a Category for each studio
|
IEnumerable<Year> entities = await Task.WhenAll<Year>(data.Keys.Select(key => { return Kernel.Instance.ItemController.GetYear(key); }));
|
||||||
List<IBNItem<Year>> list = new List<IBNItem<Year>>();
|
|
||||||
|
|
||||||
foreach (int key in data.Keys)
|
return entities.Select(e => new IBNItem<Year>() { Item = e, BaseItemCount = data[int.Parse(e.Name)] });
|
||||||
{
|
|
||||||
// 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 IBNItem<Year>()
|
|
||||||
{
|
|
||||||
Item = entity,
|
|
||||||
BaseItemCount = data[key]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,16 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.Composition;
|
using System.ComponentModel.Composition;
|
||||||
using System.ComponentModel.Composition.Hosting;
|
using System.ComponentModel.Composition.Hosting;
|
||||||
using System.Configuration;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Logging;
|
using MediaBrowser.Common.Logging;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Common.Plugins;
|
using MediaBrowser.Common.Plugins;
|
||||||
using MediaBrowser.Common.Serialization;
|
using MediaBrowser.Common.Serialization;
|
||||||
using MediaBrowser.Model.Progress;
|
using MediaBrowser.Model.Progress;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Common.Kernel
|
namespace MediaBrowser.Common.Kernel
|
||||||
{
|
{
|
||||||
|
@ -93,6 +92,8 @@ namespace MediaBrowser.Common.Kernel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected void ReloadComposableParts()
|
protected void ReloadComposableParts()
|
||||||
{
|
{
|
||||||
|
DisposeComposableParts();
|
||||||
|
|
||||||
// Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that
|
// Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that
|
||||||
// This will prevent the .dll file from getting locked, and allow us to replace it when needed
|
// This will prevent the .dll file from getting locked, and allow us to replace it when needed
|
||||||
IEnumerable<Assembly> pluginAssemblies = Directory.GetFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.AllDirectories).Select(f => Assembly.Load(File.ReadAllBytes((f))));
|
IEnumerable<Assembly> pluginAssemblies = Directory.GetFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.AllDirectories).Select(f => Assembly.Load(File.ReadAllBytes((f))));
|
||||||
|
@ -203,10 +204,33 @@ namespace MediaBrowser.Common.Kernel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public virtual void Dispose()
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
|
DisposeComposableParts();
|
||||||
DisposeHttpServer();
|
DisposeHttpServer();
|
||||||
DisposeLogger();
|
DisposeLogger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes all objects gathered through MEF composable parts
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void DisposeComposableParts()
|
||||||
|
{
|
||||||
|
DisposePlugins();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes all plugins
|
||||||
|
/// </summary>
|
||||||
|
private void DisposePlugins()
|
||||||
|
{
|
||||||
|
if (Plugins != null)
|
||||||
|
{
|
||||||
|
foreach (BasePlugin plugin in Plugins)
|
||||||
|
{
|
||||||
|
plugin.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disposes the current HttpServer
|
/// Disposes the current HttpServer
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -14,9 +14,9 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
|
|
||||||
protected string ResourcePath { get; set; }
|
protected string ResourcePath { get; set; }
|
||||||
|
|
||||||
public override string ContentType
|
public override Task<string> GetContentType()
|
||||||
{
|
{
|
||||||
get
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
string extension = Path.GetExtension(ResourcePath);
|
string extension = Path.GetExtension(ResourcePath);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
return "text/plain; charset=utf-8";
|
return "text/plain; charset=utf-8";
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Task WriteResponseToOutputStream(Stream stream)
|
protected override Task WriteResponseToOutputStream(Stream stream)
|
||||||
|
|
|
@ -111,7 +111,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the MIME type to include in the response headers
|
/// Gets the MIME type to include in the response headers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract string ContentType { get; }
|
public abstract Task<string> GetContentType();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the status code to include in the response headers
|
/// Gets the status code to include in the response headers
|
||||||
|
@ -129,31 +129,9 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _LastDateModifiedDiscovered = false;
|
public virtual bool ShouldCompressResponse(string contentType)
|
||||||
private DateTime? _LastDateModified = null;
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the last date modified of the content being returned, if this can be determined.
|
|
||||||
/// This will be used to invalidate the cache, so it's not needed if CacheDuration is 0.
|
|
||||||
/// </summary>
|
|
||||||
public DateTime? LastDateModified
|
|
||||||
{
|
{
|
||||||
get
|
return true;
|
||||||
{
|
|
||||||
if (!_LastDateModifiedDiscovered)
|
|
||||||
{
|
|
||||||
_LastDateModified = GetLastDateModified();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _LastDateModified;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CompressResponse
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ClientSupportsCompression
|
private bool ClientSupportsCompression
|
||||||
|
@ -207,10 +185,12 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
// When serving a range request, we need to return status code 206 to indicate a partial response body
|
// When serving a range request, we need to return status code 206 to indicate a partial response body
|
||||||
StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200;
|
StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200;
|
||||||
|
|
||||||
ctx.Response.ContentType = ContentType;
|
ctx.Response.ContentType = await GetContentType();
|
||||||
|
|
||||||
TimeSpan cacheDuration = CacheDuration;
|
TimeSpan cacheDuration = CacheDuration;
|
||||||
|
|
||||||
|
DateTime? lastDateModified = await GetLastDateModified();
|
||||||
|
|
||||||
if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since"))
|
if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since"))
|
||||||
{
|
{
|
||||||
DateTime ifModifiedSince;
|
DateTime ifModifiedSince;
|
||||||
|
@ -218,18 +198,20 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
if (DateTime.TryParse(ctx.Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince))
|
if (DateTime.TryParse(ctx.Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince))
|
||||||
{
|
{
|
||||||
// If the cache hasn't expired yet just return a 304
|
// If the cache hasn't expired yet just return a 304
|
||||||
if (IsCacheValid(ifModifiedSince, cacheDuration, LastDateModified))
|
if (IsCacheValid(ifModifiedSince, cacheDuration, lastDateModified))
|
||||||
{
|
{
|
||||||
StatusCode = 304;
|
StatusCode = 304;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PrepareResponse();
|
await PrepareResponse();
|
||||||
|
|
||||||
if (IsResponseValid)
|
if (IsResponseValid)
|
||||||
{
|
{
|
||||||
await ProcessUncachedRequest(ctx, cacheDuration);
|
bool compressResponse = ShouldCompressResponse(ctx.Response.ContentType) && ClientSupportsCompression;
|
||||||
|
|
||||||
|
await ProcessUncachedRequest(ctx, compressResponse, cacheDuration, lastDateModified);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -241,7 +223,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
{
|
{
|
||||||
// It might be too late if some response data has already been transmitted, but try to set this
|
// It might be too late if some response data has already been transmitted, but try to set this
|
||||||
ctx.Response.StatusCode = 500;
|
ctx.Response.StatusCode = 500;
|
||||||
|
|
||||||
Logger.LogException(ex);
|
Logger.LogException(ex);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
@ -250,7 +232,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessUncachedRequest(HttpListenerContext ctx, TimeSpan cacheDuration)
|
private async Task ProcessUncachedRequest(HttpListenerContext ctx, bool compressResponse, TimeSpan cacheDuration, DateTime? lastDateModified)
|
||||||
{
|
{
|
||||||
long? totalContentLength = TotalContentLength;
|
long? totalContentLength = TotalContentLength;
|
||||||
|
|
||||||
|
@ -270,7 +252,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the compression header
|
// Add the compression header
|
||||||
if (CompressResponse && ClientSupportsCompression)
|
if (compressResponse)
|
||||||
{
|
{
|
||||||
ctx.Response.AddHeader("Content-Encoding", CompressionMethod);
|
ctx.Response.AddHeader("Content-Encoding", CompressionMethod);
|
||||||
}
|
}
|
||||||
|
@ -278,7 +260,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
// Add caching headers
|
// Add caching headers
|
||||||
if (cacheDuration.Ticks > 0)
|
if (cacheDuration.Ticks > 0)
|
||||||
{
|
{
|
||||||
CacheResponse(ctx.Response, cacheDuration, LastDateModified);
|
CacheResponse(ctx.Response, cacheDuration, lastDateModified);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the status code
|
// Set the status code
|
||||||
|
@ -289,7 +271,7 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
// Finally, write the response data
|
// Finally, write the response data
|
||||||
Stream outputStream = ctx.Response.OutputStream;
|
Stream outputStream = ctx.Response.OutputStream;
|
||||||
|
|
||||||
if (CompressResponse && ClientSupportsCompression)
|
if (compressResponse)
|
||||||
{
|
{
|
||||||
if (CompressionMethod.Equals("deflate", StringComparison.OrdinalIgnoreCase))
|
if (CompressionMethod.Equals("deflate", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
|
@ -321,10 +303,11 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gives subclasses a chance to do and prep work, and also to validate data and set an error status code, if needed
|
/// Gives subclasses a chance to do any prep work, and also to validate data and set an error status code, if needed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void PrepareResponse()
|
protected virtual Task PrepareResponse()
|
||||||
{
|
{
|
||||||
|
return Task.Run(() => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Task WriteResponseToOutputStream(Stream stream);
|
protected abstract Task WriteResponseToOutputStream(Stream stream);
|
||||||
|
@ -372,9 +355,11 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual DateTime? GetLastDateModified()
|
protected virtual Task<DateTime?> GetLastDateModified()
|
||||||
{
|
{
|
||||||
return null;
|
DateTime? value = null;
|
||||||
|
|
||||||
|
return Task.Run<DateTime?>(() => { return value; });
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsResponseValid
|
private bool IsResponseValid
|
||||||
|
|
|
@ -6,19 +6,22 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
{
|
{
|
||||||
public abstract class BaseJsonHandler<T> : BaseHandler
|
public abstract class BaseJsonHandler<T> : BaseHandler
|
||||||
{
|
{
|
||||||
public override string ContentType
|
public override Task<string> GetContentType()
|
||||||
{
|
{
|
||||||
get { return MimeTypes.JsonMimeType; }
|
return Task.Run(() =>
|
||||||
|
{
|
||||||
|
return MimeTypes.JsonMimeType;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _ObjectToSerializeEnsured = false;
|
private bool _ObjectToSerializeEnsured = false;
|
||||||
private T _ObjectToSerialize;
|
private T _ObjectToSerialize;
|
||||||
|
|
||||||
private void EnsureObjectToSerialize()
|
private async Task EnsureObjectToSerialize()
|
||||||
{
|
{
|
||||||
if (!_ObjectToSerializeEnsured)
|
if (!_ObjectToSerializeEnsured)
|
||||||
{
|
{
|
||||||
_ObjectToSerialize = GetObjectToSerialize();
|
_ObjectToSerialize = await GetObjectToSerialize();
|
||||||
|
|
||||||
if (_ObjectToSerialize == null)
|
if (_ObjectToSerialize == null)
|
||||||
{
|
{
|
||||||
|
@ -29,30 +32,18 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private T ObjectToSerialize
|
protected abstract Task<T> GetObjectToSerialize();
|
||||||
|
|
||||||
|
protected override async Task PrepareResponse()
|
||||||
{
|
{
|
||||||
get
|
await EnsureObjectToSerialize();
|
||||||
{
|
|
||||||
EnsureObjectToSerialize();
|
|
||||||
return _ObjectToSerialize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract T GetObjectToSerialize();
|
protected async override Task WriteResponseToOutputStream(Stream stream)
|
||||||
|
|
||||||
protected override void PrepareResponse()
|
|
||||||
{
|
{
|
||||||
base.PrepareResponse();
|
await EnsureObjectToSerialize();
|
||||||
|
|
||||||
EnsureObjectToSerialize();
|
JsonSerializer.SerializeToStream<T>(_ObjectToSerialize, stream);
|
||||||
}
|
|
||||||
|
|
||||||
protected override Task WriteResponseToOutputStream(Stream stream)
|
|
||||||
{
|
|
||||||
return Task.Run(() =>
|
|
||||||
{
|
|
||||||
JsonSerializer.SerializeToStream<T>(ObjectToSerialize, stream);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,27 +77,22 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CompressResponse
|
public override bool ShouldCompressResponse(string contentType)
|
||||||
{
|
{
|
||||||
get
|
// Can't compress these
|
||||||
|
if (IsRangeRequest)
|
||||||
{
|
{
|
||||||
// Can't compress these
|
|
||||||
if (IsRangeRequest)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string contentType = ContentType;
|
|
||||||
|
|
||||||
// Don't compress media
|
|
||||||
if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// It will take some work to support compression within this handler
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't compress media
|
||||||
|
if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It will take some work to support compression within this handler
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override long? GetTotalContentLength()
|
protected override long? GetTotalContentLength()
|
||||||
|
@ -105,31 +100,32 @@ namespace MediaBrowser.Common.Net.Handlers
|
||||||
return SourceStream.Length;
|
return SourceStream.Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DateTime? GetLastDateModified()
|
protected override Task<DateTime?> GetLastDateModified()
|
||||||
{
|
{
|
||||||
EnsureSourceStream();
|
return Task.Run<DateTime?>(() =>
|
||||||
|
|
||||||
if (SourceStream == null)
|
|
||||||
{
|
{
|
||||||
return null;
|
EnsureSourceStream();
|
||||||
}
|
|
||||||
|
|
||||||
return File.GetLastWriteTime(Path);
|
if (SourceStream == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return File.GetLastWriteTime(Path);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ContentType
|
public override Task<string> GetContentType()
|
||||||
{
|
{
|
||||||
get
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
return MimeTypes.GetMimeType(Path);
|
return MimeTypes.GetMimeType(Path);
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void PrepareResponse()
|
protected override Task PrepareResponse()
|
||||||
{
|
{
|
||||||
base.PrepareResponse();
|
return Task.Run(() => { EnsureSourceStream(); });
|
||||||
|
|
||||||
EnsureSourceStream();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async override Task WriteResponseToOutputStream(Stream stream)
|
protected async override Task WriteResponseToOutputStream(Stream stream)
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace MediaBrowser.Controller.IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TimerStopped(object stateInfo)
|
private async void TimerStopped(object stateInfo)
|
||||||
{
|
{
|
||||||
updateTimer.Dispose();
|
updateTimer.Dispose();
|
||||||
updateTimer = null;
|
updateTimer = null;
|
||||||
|
@ -83,7 +83,7 @@ namespace MediaBrowser.Controller.IO
|
||||||
List<string> paths = affectedPaths;
|
List<string> paths = affectedPaths;
|
||||||
affectedPaths = new List<string>();
|
affectedPaths = new List<string>();
|
||||||
|
|
||||||
//ProcessPathChanges(paths);
|
await ProcessPathChanges(paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessPathChanges(IEnumerable<string> paths)
|
private async Task ProcessPathChanges(IEnumerable<string> paths)
|
||||||
|
@ -109,10 +109,7 @@ namespace MediaBrowser.Controller.IO
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*Parallel.For(0, itemsToRefresh.Count, i =>
|
await Task.WhenAll(itemsToRefresh.Select(i => Kernel.Instance.ReloadItem(i)));
|
||||||
{
|
|
||||||
Kernel.Instance.ReloadItem(itemsToRefresh[i]);
|
|
||||||
});*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -248,5 +248,47 @@ namespace MediaBrowser.Controller
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal async Task ExecuteMetadataProviders(BaseEntity item, ItemResolveEventArgs args)
|
||||||
|
{
|
||||||
|
var supportedProviders = Kernel.Instance.MetadataProviders.Where(i => i.Supports(item));
|
||||||
|
|
||||||
|
// Start with non-internet providers. Run them sequentially
|
||||||
|
foreach (BaseMetadataProvider provider in supportedProviders.Where(i => !i.RequiresInternet))
|
||||||
|
{
|
||||||
|
await provider.Fetch(item, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
var internetProviders = supportedProviders.Where(i => i.RequiresInternet);
|
||||||
|
|
||||||
|
if (internetProviders.Any())
|
||||||
|
{
|
||||||
|
// Now execute internet providers in parallel
|
||||||
|
await Task.WhenAll(
|
||||||
|
internetProviders.Select(i => i.Fetch(item, args))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DisposeComposableParts()
|
||||||
|
{
|
||||||
|
base.DisposeComposableParts();
|
||||||
|
|
||||||
|
DisposeProviders();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes all providers
|
||||||
|
/// </summary>
|
||||||
|
private void DisposeProviders()
|
||||||
|
{
|
||||||
|
if (MetadataProviders != null)
|
||||||
|
{
|
||||||
|
foreach (var provider in MetadataProviders)
|
||||||
|
{
|
||||||
|
provider.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -217,49 +218,49 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Person
|
/// Gets a Person
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Person GetPerson(string name)
|
public async Task<Person> GetPerson(string name)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(Kernel.Instance.ApplicationPaths.PeoplePath, name);
|
string path = Path.Combine(Kernel.Instance.ApplicationPaths.PeoplePath, name);
|
||||||
|
|
||||||
return GetImagesByNameItem<Person>(path, name);
|
return await GetImagesByNameItem<Person>(path, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Studio
|
/// Gets a Studio
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Studio GetStudio(string name)
|
public async Task<Studio> GetStudio(string name)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(Kernel.Instance.ApplicationPaths.StudioPath, name);
|
string path = Path.Combine(Kernel.Instance.ApplicationPaths.StudioPath, name);
|
||||||
|
|
||||||
return GetImagesByNameItem<Studio>(path, name);
|
return await GetImagesByNameItem<Studio>(path, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Genre
|
/// Gets a Genre
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Genre GetGenre(string name)
|
public async Task<Genre> GetGenre(string name)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(Kernel.Instance.ApplicationPaths.GenrePath, name);
|
string path = Path.Combine(Kernel.Instance.ApplicationPaths.GenrePath, name);
|
||||||
|
|
||||||
return GetImagesByNameItem<Genre>(path, name);
|
return await GetImagesByNameItem<Genre>(path, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a Year
|
/// Gets a Year
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Year GetYear(int value)
|
public async Task<Year> GetYear(int value)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(Kernel.Instance.ApplicationPaths.YearPath, value.ToString());
|
string path = Path.Combine(Kernel.Instance.ApplicationPaths.YearPath, value.ToString());
|
||||||
|
|
||||||
return GetImagesByNameItem<Year>(path, value.ToString());
|
return await GetImagesByNameItem<Year>(path, value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, object> ImagesByNameItemCache = new Dictionary<string, object>();
|
private ConcurrentDictionary<string, object> ImagesByNameItemCache = new ConcurrentDictionary<string, object>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generically retrieves an IBN item
|
/// Generically retrieves an IBN item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private T GetImagesByNameItem<T>(string path, string name)
|
private async Task<T> GetImagesByNameItem<T>(string path, string name)
|
||||||
where T : BaseEntity, new()
|
where T : BaseEntity, new()
|
||||||
{
|
{
|
||||||
string key = path.ToLower();
|
string key = path.ToLower();
|
||||||
|
@ -267,7 +268,9 @@ namespace MediaBrowser.Controller.Library
|
||||||
// Look for it in the cache, if it's not there, create it
|
// Look for it in the cache, if it's not there, create it
|
||||||
if (!ImagesByNameItemCache.ContainsKey(key))
|
if (!ImagesByNameItemCache.ContainsKey(key))
|
||||||
{
|
{
|
||||||
ImagesByNameItemCache[key] = CreateImagesByNameItem<T>(path, name);
|
T obj = await CreateImagesByNameItem<T>(path, name);
|
||||||
|
ImagesByNameItemCache[key] = obj;
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ImagesByNameItemCache[key] as T;
|
return ImagesByNameItemCache[key] as T;
|
||||||
|
@ -276,7 +279,7 @@ namespace MediaBrowser.Controller.Library
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates an IBN item based on a given path
|
/// Creates an IBN item based on a given path
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private T CreateImagesByNameItem<T>(string path, string name)
|
private async Task<T> CreateImagesByNameItem<T>(string path, string name)
|
||||||
where T : BaseEntity, new()
|
where T : BaseEntity, new()
|
||||||
{
|
{
|
||||||
T item = new T();
|
T item = new T();
|
||||||
|
@ -284,25 +287,28 @@ namespace MediaBrowser.Controller.Library
|
||||||
item.Name = name;
|
item.Name = name;
|
||||||
item.Id = Kernel.GetMD5(path);
|
item.Id = Kernel.GetMD5(path);
|
||||||
|
|
||||||
if (Directory.Exists(path))
|
if (!Directory.Exists(path))
|
||||||
{
|
{
|
||||||
item.DateCreated = Directory.GetCreationTime(path);
|
Directory.CreateDirectory(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.DateCreated = Directory.GetCreationTime(path);
|
||||||
item.DateModified = now;
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
var b = false;
|
||||||
|
|
||||||
|
if (b)
|
||||||
|
{
|
||||||
|
await Kernel.Instance.ExecuteMetadataProviders(item, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|
|
@ -12,12 +12,12 @@ namespace MediaBrowser.Controller.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class AudioInfoProvider : BaseMetadataProvider
|
public class AudioInfoProvider : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public override bool Supports(BaseItem item)
|
public override bool Supports(BaseEntity item)
|
||||||
{
|
{
|
||||||
return item is Audio;
|
return item is Audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
Audio audio = item as Audio;
|
Audio audio = item as Audio;
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
{
|
{
|
||||||
base.Init();
|
base.Init();
|
||||||
|
|
||||||
|
// Do this now so that we don't have to do this on every operation, which would require us to create a lock in order to maintain thread-safety
|
||||||
for (int i = 0; i <= 9; i++)
|
for (int i = 0; i <= 9; i++)
|
||||||
{
|
{
|
||||||
EnsureDirectory(Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, i.ToString()));
|
EnsureDirectory(Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, i.ToString()));
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
using System.Threading.Tasks;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Events;
|
using MediaBrowser.Controller.Events;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Providers
|
namespace MediaBrowser.Controller.Providers
|
||||||
{
|
{
|
||||||
public abstract class BaseMetadataProvider
|
public abstract class BaseMetadataProvider : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// If the provider needs any startup routines, add them here
|
/// If the provider needs any startup routines, add them here
|
||||||
|
@ -13,11 +14,23 @@ namespace MediaBrowser.Controller.Providers
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool Supports(BaseItem item)
|
/// <summary>
|
||||||
|
/// Disposes anything created during Init
|
||||||
|
/// </summary>
|
||||||
|
public virtual void Dispose()
|
||||||
{
|
{
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Task Fetch(BaseItem item, ItemResolveEventArgs args);
|
public abstract bool Supports(BaseEntity item);
|
||||||
|
|
||||||
|
public virtual bool RequiresInternet
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Task Fetch(BaseEntity item, ItemResolveEventArgs args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,12 @@ namespace MediaBrowser.Controller.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class FolderProviderFromXml : BaseMetadataProvider
|
public class FolderProviderFromXml : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public override bool Supports(BaseItem item)
|
public override bool Supports(BaseEntity item)
|
||||||
{
|
{
|
||||||
return item is Folder;
|
return item is Folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
var metadataFile = args.GetFileByName("folder.xml");
|
var metadataFile = args.GetFileByName("folder.xml");
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,18 @@ namespace MediaBrowser.Controller.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class ImageFromMediaLocationProvider : BaseMetadataProvider
|
public class ImageFromMediaLocationProvider : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public override bool Supports(BaseEntity item)
|
||||||
|
{
|
||||||
|
return item is BaseItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
if (args.IsFolder)
|
if (args.IsFolder)
|
||||||
{
|
{
|
||||||
PopulateImages(item, args);
|
PopulateImages(item as BaseItem, args);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,15 @@ namespace MediaBrowser.Controller.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class LocalTrailerProvider : BaseMetadataProvider
|
public class LocalTrailerProvider : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public async override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public override bool Supports(BaseEntity item)
|
||||||
{
|
{
|
||||||
|
return item is BaseItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
|
{
|
||||||
|
BaseItem baseItem = item as BaseItem;
|
||||||
|
|
||||||
var trailerPath = args.GetFolderByName("trailers");
|
var trailerPath = args.GetFolderByName("trailers");
|
||||||
|
|
||||||
if (trailerPath.HasValue)
|
if (trailerPath.HasValue)
|
||||||
|
@ -32,7 +39,7 @@ namespace MediaBrowser.Controller.Providers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item.LocalTrailers = localTrailers;
|
baseItem.LocalTrailers = localTrailers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,12 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Controller.Events;
|
using MediaBrowser.Controller.Events;
|
||||||
using MediaBrowser.Controller.Providers;
|
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Resolvers
|
namespace MediaBrowser.Controller.Resolvers
|
||||||
{
|
{
|
||||||
public abstract class BaseItemResolver<T> : IBaseItemResolver
|
public abstract class BaseItemResolver<T> : IBaseItemResolver
|
||||||
where T : BaseItem, new ()
|
where T : BaseItem, new()
|
||||||
{
|
{
|
||||||
protected virtual T Resolve(ItemResolveEventArgs args)
|
protected virtual T Resolve(ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
|
@ -18,7 +17,7 @@ namespace MediaBrowser.Controller.Resolvers
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets initial values on the newly resolved item
|
/// Sets initial values on the newly resolved item
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected virtual void SetItemValues(T item, ItemResolveEventArgs args)
|
protected virtual void SetInitialItemValues(T item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
// If the subclass didn't specify this
|
// If the subclass didn't specify this
|
||||||
if (string.IsNullOrEmpty(item.Path))
|
if (string.IsNullOrEmpty(item.Path))
|
||||||
|
@ -38,35 +37,24 @@ namespace MediaBrowser.Controller.Resolvers
|
||||||
public async Task<BaseItem> ResolvePath(ItemResolveEventArgs args)
|
public async Task<BaseItem> ResolvePath(ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
T item = Resolve(args);
|
T item = Resolve(args);
|
||||||
|
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
// Set initial values on the newly resolved item
|
// Set initial values on the newly resolved item
|
||||||
SetItemValues(item, args);
|
SetInitialItemValues(item, args);
|
||||||
|
|
||||||
// Make sure the item has a name
|
// Make sure the item has a name
|
||||||
EnsureName(item);
|
EnsureName(item);
|
||||||
|
|
||||||
// Make sure DateCreated and DateModified have values
|
// Make sure DateCreated and DateModified have values
|
||||||
EnsureDates(item);
|
EnsureDates(item);
|
||||||
|
|
||||||
await FetchMetadataFromProviders(item, args);
|
await Kernel.Instance.ExecuteMetadataProviders(item, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FetchMetadataFromProviders(T item, ItemResolveEventArgs args)
|
|
||||||
{
|
|
||||||
foreach (BaseMetadataProvider provider in Kernel.Instance.MetadataProviders)
|
|
||||||
{
|
|
||||||
if (provider.Supports(item))
|
|
||||||
{
|
|
||||||
await provider.Fetch(item, args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EnsureName(T item)
|
private void EnsureName(T item)
|
||||||
{
|
{
|
||||||
// If the subclass didn't supply a name, add it here
|
// If the subclass didn't supply a name, add it here
|
||||||
|
|
|
@ -21,9 +21,9 @@ namespace MediaBrowser.Controller.Resolvers
|
||||||
public abstract class BaseFolderResolver<TItemType> : BaseItemResolver<TItemType>
|
public abstract class BaseFolderResolver<TItemType> : BaseItemResolver<TItemType>
|
||||||
where TItemType : Folder, new()
|
where TItemType : Folder, new()
|
||||||
{
|
{
|
||||||
protected override void SetItemValues(TItemType item, ItemResolveEventArgs args)
|
protected override void SetInitialItemValues(TItemType item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
base.SetItemValues(item, args);
|
base.SetInitialItemValues(item, args);
|
||||||
|
|
||||||
item.IsRoot = args.Parent == null;
|
item.IsRoot = args.Parent == null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Resolvers
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SetItemValues(VirtualFolder item, ItemResolveEventArgs args)
|
protected override void SetInitialItemValues(VirtualFolder item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
// Set the name initially by stripping off the [CollectionType=...]
|
// Set the name initially by stripping off the [CollectionType=...]
|
||||||
// The name can always be overridden later by folder.xml
|
// The name can always be overridden later by folder.xml
|
||||||
|
@ -34,7 +34,7 @@ namespace MediaBrowser.Controller.Resolvers
|
||||||
item.CollectionType = pathName.Substring(index + srch.Length).TrimEnd(']');
|
item.CollectionType = pathName.Substring(index + srch.Length).TrimEnd(']');
|
||||||
}
|
}
|
||||||
|
|
||||||
base.SetItemValues(item, args);
|
base.SetInitialItemValues(item, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Xml
|
namespace MediaBrowser.Controller.Xml
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,12 +11,12 @@ namespace MediaBrowser.Movies.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class MovieProviderFromXml : BaseMetadataProvider
|
public class MovieProviderFromXml : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public override bool Supports(BaseItem item)
|
public override bool Supports(BaseEntity item)
|
||||||
{
|
{
|
||||||
return item is Movie;
|
return item is Movie;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
var metadataFile = args.GetFileByName("movie.xml");
|
var metadataFile = args.GetFileByName("movie.xml");
|
||||||
|
|
||||||
|
|
|
@ -88,9 +88,9 @@ namespace MediaBrowser.Movies.Resolvers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SetItemValues(Movie item, ItemResolveEventArgs args)
|
protected override void SetInitialItemValues(Movie item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
base.SetItemValues(item, args);
|
base.SetInitialItemValues(item, args);
|
||||||
|
|
||||||
PopulateBonusFeatures(item, args);
|
PopulateBonusFeatures(item, args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using MediaBrowser.Common.Logging;
|
using MediaBrowser.Common.Logging;
|
||||||
|
using MediaBrowser.Common.UI;
|
||||||
using MediaBrowser.Controller;
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.Progress;
|
using MediaBrowser.Model.Progress;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using MediaBrowser.Common.UI;
|
|
||||||
|
|
||||||
namespace MediaBrowser.ServerApplication
|
namespace MediaBrowser.ServerApplication
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,22 +13,24 @@ namespace MediaBrowser.TV.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class EpisodeImageFromMediaLocationProvider : BaseMetadataProvider
|
public class EpisodeImageFromMediaLocationProvider : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public override bool Supports(BaseItem item)
|
public override bool Supports(BaseEntity item)
|
||||||
{
|
{
|
||||||
return item is Episode;
|
return item is Episode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
Episode episode = item as Episode;
|
||||||
|
|
||||||
string metadataFolder = Path.Combine(args.Parent.Path, "metadata");
|
string metadataFolder = Path.Combine(args.Parent.Path, "metadata");
|
||||||
|
|
||||||
string episodeFileName = Path.GetFileName(item.Path);
|
string episodeFileName = Path.GetFileName(episode.Path);
|
||||||
|
|
||||||
Season season = args.Parent as Season;
|
Season season = args.Parent as Season;
|
||||||
|
|
||||||
SetPrimaryImagePath(item as Episode, season, metadataFolder, episodeFileName);
|
SetPrimaryImagePath(episode, season, metadataFolder, episodeFileName);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,20 +14,22 @@ namespace MediaBrowser.TV.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class EpisodeProviderFromXml : BaseMetadataProvider
|
public class EpisodeProviderFromXml : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public override bool Supports(BaseItem item)
|
public override bool Supports(BaseEntity item)
|
||||||
{
|
{
|
||||||
return item is Episode;
|
return item is Episode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
string metadataFolder = Path.Combine(args.Parent.Path, "metadata");
|
string metadataFolder = Path.Combine(args.Parent.Path, "metadata");
|
||||||
|
|
||||||
string episodeFileName = Path.GetFileName(item.Path);
|
Episode episode = item as Episode;
|
||||||
|
|
||||||
|
string episodeFileName = Path.GetFileName(episode.Path);
|
||||||
|
|
||||||
string metadataFile = Path.Combine(metadataFolder, Path.ChangeExtension(episodeFileName, ".xml"));
|
string metadataFile = Path.Combine(metadataFolder, Path.ChangeExtension(episodeFileName, ".xml"));
|
||||||
|
|
||||||
await FetchMetadata(item as Episode, args.Parent as Season, metadataFile);
|
await FetchMetadata(episode, args.Parent as Season, metadataFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task FetchMetadata(Episode item, Season season, string metadataFile)
|
private async Task FetchMetadata(Episode item, Season season, string metadataFile)
|
||||||
|
|
|
@ -11,12 +11,12 @@ namespace MediaBrowser.TV.Providers
|
||||||
[Export(typeof(BaseMetadataProvider))]
|
[Export(typeof(BaseMetadataProvider))]
|
||||||
public class SeriesProviderFromXml : BaseMetadataProvider
|
public class SeriesProviderFromXml : BaseMetadataProvider
|
||||||
{
|
{
|
||||||
public override bool Supports(BaseItem item)
|
public override bool Supports(BaseEntity item)
|
||||||
{
|
{
|
||||||
return item is Series;
|
return item is Series;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async override Task Fetch(BaseItem item, ItemResolveEventArgs args)
|
public async override Task Fetch(BaseEntity item, ItemResolveEventArgs args)
|
||||||
{
|
{
|
||||||
var metadataFile = args.GetFileByName("series.xml");
|
var metadataFile = args.GetFileByName("series.xml");
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user