beginning manual image providers

pull/702/head
Luke Pulverenti 11 years ago
parent 2f99b2e1e6
commit 524150331c

@ -5,8 +5,10 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Querying;
using ServiceStack.ServiceHost;
using System;
@ -32,6 +34,21 @@ namespace MediaBrowser.Api
public string Id { get; set; }
}
[Route("/Items/{Id}/RemoteImages/{Type}", "GET")]
[Api(Description = "Gets available remote images for an item")]
public class GetRemoteImages : IReturn<List<RemoteImageInfo>>
{
/// <summary>
/// Gets or sets the id.
/// </summary>
/// <value>The id.</value>
[ApiMember(Name = "Id", Description = "Item Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public string Id { get; set; }
[ApiMember(Name = "Type", Description = "The image type", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
public ImageType Type { get; set; }
}
/// <summary>
/// Class GetCriticReviews
/// </summary>
@ -208,6 +225,7 @@ namespace MediaBrowser.Api
private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataManager;
private readonly IProviderManager _providerManager;
private readonly IDtoService _dtoService;
@ -215,13 +233,14 @@ namespace MediaBrowser.Api
/// Initializes a new instance of the <see cref="LibraryService" /> class.
/// </summary>
public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
IDtoService dtoService, IUserDataManager userDataManager)
IDtoService dtoService, IUserDataManager userDataManager, IProviderManager providerManager)
{
_itemRepo = itemRepo;
_libraryManager = libraryManager;
_userManager = userManager;
_dtoService = dtoService;
_userDataManager = userDataManager;
_providerManager = providerManager;
}
public object Get(GetFile request)
@ -240,6 +259,15 @@ namespace MediaBrowser.Api
return ToStaticFileResult(item.Path);
}
public object Get(GetRemoteImages request)
{
var item = _dtoService.GetItemByDtoId(request.Id);
var result = _providerManager.GetAvailableRemoteImages(item, request.Type, CancellationToken.None).Result;
return ToOptimizedResult(result);
}
/// <summary>
/// Gets the specified request.
/// </summary>

@ -109,6 +109,7 @@
<Compile Include="Notifications\INotificationsRepository.cs" />
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
<Compile Include="Providers\IDynamicInfoProvider.cs" />
<Compile Include="Providers\IImageProvider.cs" />
<Compile Include="Session\ISessionManager.cs" />
<Compile Include="Drawing\ImageExtensions.cs" />
<Compile Include="Entities\AggregateFolder.cs" />

@ -0,0 +1,38 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Providers
{
/// <summary>
/// Interface IImageProvider
/// </summary>
public interface IImageProvider
{
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
string Name { get; }
/// <summary>
/// Supportses the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="imageType">Type of the image.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
bool Supports(BaseItem item, ImageType imageType);
/// <summary>
/// Gets the available images.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="imageType">Type of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
Task<IEnumerable<RemoteImageInfo>> GetAvailableImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken);
}
}

@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@ -52,6 +53,16 @@ namespace MediaBrowser.Controller.Providers
/// Adds the metadata providers.
/// </summary>
/// <param name="providers">The providers.</param>
void AddParts(IEnumerable<BaseMetadataProvider> providers);
/// <param name="imageProviders">The image providers.</param>
void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders);
/// <summary>
/// Gets the available remote images.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="type">The type.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, ImageType type, CancellationToken cancellationToken);
}
}

@ -287,6 +287,9 @@
<Compile Include="..\MediaBrowser.Model\Plugins\PluginInfo.cs">
<Link>Plugins\PluginInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageInfo.cs">
<Link>Providers\RemoteImageInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
<Link>Querying\ArtistsQuery.cs</Link>
</Compile>

@ -274,6 +274,9 @@
<Compile Include="..\MediaBrowser.Model\Plugins\PluginInfo.cs">
<Link>Plugins\PluginInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageInfo.cs">
<Link>Providers\RemoteImageInfo.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
<Link>Querying\ArtistsQuery.cs</Link>
</Compile>

@ -59,6 +59,7 @@
<Compile Include="Dto\ItemByNameCounts.cs" />
<Compile Include="Dto\ItemCounts.cs" />
<Compile Include="Dto\ItemIndex.cs" />
<Compile Include="Providers\RemoteImageInfo.cs" />
<Compile Include="Dto\StudioDto.cs" />
<Compile Include="Entities\CollectionType.cs" />
<Compile Include="Entities\ItemReview.cs" />

@ -0,0 +1,51 @@

namespace MediaBrowser.Model.Providers
{
/// <summary>
/// Class RemoteImageInfo
/// </summary>
public class RemoteImageInfo
{
/// <summary>
/// Gets or sets the name of the provider.
/// </summary>
/// <value>The name of the provider.</value>
public string ProviderName { get; set; }
/// <summary>
/// Gets or sets the URL.
/// </summary>
/// <value>The URL.</value>
public string Url { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
public int? Height { get; set; }
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>The width.</value>
public int? Width { get; set; }
/// <summary>
/// Gets or sets the community rating.
/// </summary>
/// <value>The community rating.</value>
public double? CommunityRating { get; set; }
/// <summary>
/// Gets or sets the vote count.
/// </summary>
/// <value>The vote count.</value>
public int? VoteCount { get; set; }
/// <summary>
/// Gets or sets the language.
/// </summary>
/// <value>The language.</value>
public string Language { get; set; }
}
}

@ -60,6 +60,7 @@
<Compile Include="MediaInfo\FFProbeVideoInfoProvider.cs" />
<Compile Include="MediaInfo\VideoImageProvider.cs" />
<Compile Include="Movies\BoxSetProviderFromXml.cs" />
<Compile Include="Movies\ManualMovieDbImageProvider.cs" />
<Compile Include="Movies\MovieUpdatesPrescanTask.cs" />
<Compile Include="Movies\MovieXmlParser.cs" />
<Compile Include="Movies\FanArtMovieProvider.cs" />

@ -0,0 +1,133 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Movies
{
class ManualMovieDbImageProvider : IImageProvider
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerConfigurationManager _config;
public ManualMovieDbImageProvider(IJsonSerializer jsonSerializer, IServerConfigurationManager config)
{
_jsonSerializer = jsonSerializer;
_config = config;
}
public string Name
{
get { return "TheMovieDB"; }
}
public bool Supports(BaseItem item, ImageType imageType)
{
if (MovieDbImagesProvider.SupportsItem(item))
{
return imageType == ImageType.Primary || imageType == ImageType.Backdrop;
}
return false;
}
public async Task<IEnumerable<RemoteImageInfo>> GetAvailableImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken)
{
var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
var results = MovieDbImagesProvider.FetchImages(item, _jsonSerializer);
var tmdbImageUrl = tmdbSettings.images.base_url + "original";
if (imageType == ImageType.Primary)
{
var sources = GetPosters(results, item);
return sources.Select(i => new RemoteImageInfo
{
Url = tmdbImageUrl + i.file_path,
CommunityRating = i.vote_average,
VoteCount = i.vote_count,
Width = i.width,
Height = i.height,
Language = i.iso_639_1,
ProviderName = Name
});
}
if (imageType == ImageType.Backdrop)
{
var sources = GetBackdrops(results, item);
return sources.Select(i => new RemoteImageInfo
{
Url = tmdbImageUrl + i.file_path,
CommunityRating = i.vote_average,
VoteCount = i.vote_count,
Width = i.width,
Height = i.height,
ProviderName = Name
});
}
throw new ArgumentException("Unrecognized ImageType: " + imageType);
}
/// <summary>
/// Gets the posters.
/// </summary>
/// <param name="images">The images.</param>
/// <param name="item">The item.</param>
/// <returns>IEnumerable{MovieDbProvider.Poster}.</returns>
public IEnumerable<MovieDbProvider.Poster> GetPosters(MovieDbProvider.Images images, BaseItem item)
{
var language = _config.Configuration.PreferredMetadataLanguage;
var eligiblePosters = images.posters == null ?
new List<MovieDbProvider.Poster>() :
images.posters.Where(i => i.width >= _config.Configuration.MinMoviePosterWidth)
.ToList();
return eligiblePosters.OrderByDescending(i => i.vote_average)
.ThenByDescending(i =>
{
if (string.Equals(language, i.iso_639_1, StringComparison.OrdinalIgnoreCase))
{
return 3;
}
if (string.Equals("en", i.iso_639_1, StringComparison.OrdinalIgnoreCase))
{
return 2;
}
if (string.IsNullOrEmpty(i.iso_639_1))
{
return 1;
}
return 0;
})
.ToList();
}
/// <summary>
/// Gets the backdrops.
/// </summary>
/// <param name="images">The images.</param>
/// <param name="item">The item.</param>
/// <returns>IEnumerable{MovieDbProvider.Backdrop}.</returns>
public IEnumerable<MovieDbProvider.Backdrop> GetBackdrops(MovieDbProvider.Images images, BaseItem item)
{
var eligibleBackdrops = images.backdrops == null ? new List<MovieDbProvider.Backdrop>() :
images.backdrops.Where(i => i.width >= _config.Configuration.MinMovieBackdropWidth)
.ToList();
return eligibleBackdrops.OrderByDescending(i => i.vote_average);
}
}
}

@ -65,6 +65,11 @@ namespace MediaBrowser.Providers.Movies
/// <param name="item">The item.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item)
{
return SupportsItem(item);
}
public static bool SupportsItem(BaseItem item)
{
var trailer = item as Trailer;
@ -180,7 +185,7 @@ namespace MediaBrowser.Providers.Movies
if (!string.IsNullOrEmpty(id))
{
var images = FetchImages(item);
var images = FetchImages(item, _jsonSerializer);
if (images != null)
{
@ -196,8 +201,9 @@ namespace MediaBrowser.Providers.Movies
/// Fetches the images.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="jsonSerializer">The json serializer.</param>
/// <returns>Task{MovieImages}.</returns>
private MovieDbProvider.Images FetchImages(BaseItem item)
internal static MovieDbProvider.Images FetchImages(BaseItem item, IJsonSerializer jsonSerializer)
{
var path = MovieDbProvider.Current.GetDataFilePath(item, "default");
@ -207,7 +213,7 @@ namespace MediaBrowser.Providers.Movies
if (fileInfo.Exists)
{
return _jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(path).images;
return jsonSerializer.DeserializeFromFile<MovieDbProvider.CompleteMovieData>(path).images;
}
}
@ -227,13 +233,9 @@ namespace MediaBrowser.Providers.Movies
var status = ProviderRefreshStatus.Success;
var eligiblePosters = images.posters == null ?
new List<MovieDbProvider.Poster>() :
images.posters.Where(i => i.width >= ConfigurationManager.Configuration.MinMoviePosterWidth)
var eligiblePosters = new ManualMovieDbImageProvider(_jsonSerializer, ConfigurationManager).GetPosters(images, item)
.ToList();
eligiblePosters = eligiblePosters.OrderByDescending(i => i.vote_average).ToList();
// poster
if (eligiblePosters.Count > 0 && !item.HasImage(ImageType.Primary))
{
@ -242,48 +244,24 @@ namespace MediaBrowser.Providers.Movies
var tmdbImageUrl = tmdbSettings.images.base_url + "original";
// get highest rated poster for our language
var poster = eligiblePosters.FirstOrDefault(p => string.Equals(p.iso_639_1, ConfigurationManager.Configuration.PreferredMetadataLanguage, StringComparison.OrdinalIgnoreCase));
if (poster == null)
{
// couldn't find our specific language, find english
poster = eligiblePosters.FirstOrDefault(p => string.Equals(p.iso_639_1, "en", StringComparison.OrdinalIgnoreCase));
}
if (poster == null)
{
//still couldn't find it - try highest rated null one
poster = eligiblePosters.FirstOrDefault(p => p.iso_639_1 == null);
}
var poster = eligiblePosters[0];
if (poster == null)
{
//finally - just get the highest rated one
poster = eligiblePosters.FirstOrDefault();
}
var url = tmdbImageUrl + poster.file_path;
if (poster != null)
var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
var url = tmdbImageUrl + poster.file_path;
Url = url,
CancellationToken = cancellationToken
var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken
}).ConfigureAwait(false);
}).ConfigureAwait(false);
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(poster.file_path), ImageType.Primary, null, url, cancellationToken)
.ConfigureAwait(false);
}
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(poster.file_path), ImageType.Primary, null, url, cancellationToken)
.ConfigureAwait(false);
}
cancellationToken.ThrowIfCancellationRequested();
var eligibleBackdrops = images.backdrops == null ? new List<MovieDbProvider.Backdrop>() :
images.backdrops.Where(i => i.width >= ConfigurationManager.Configuration.MinMovieBackdropWidth)
.ToList();
var eligibleBackdrops = new ManualMovieDbImageProvider(_jsonSerializer, ConfigurationManager).GetBackdrops(images, item).ToList();
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;

@ -13,6 +13,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Server.Implementations.Providers
{
@ -48,6 +49,8 @@ namespace MediaBrowser.Server.Implementations.Providers
/// <value>The metadata providers enumerable.</value>
private BaseMetadataProvider[] MetadataProviders { get; set; }
private IImageProvider[] ImageProviders { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="ProviderManager" /> class.
/// </summary>
@ -55,8 +58,7 @@ namespace MediaBrowser.Server.Implementations.Providers
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="directoryWatchers">The directory watchers.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="libraryManager">The library manager.</param>
public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, IDirectoryWatchers directoryWatchers, ILogManager logManager, ILibraryManager libraryManager)
public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, IDirectoryWatchers directoryWatchers, ILogManager logManager)
{
_logger = logManager.GetLogger("ProviderManager");
_httpClient = httpClient;
@ -68,9 +70,12 @@ namespace MediaBrowser.Server.Implementations.Providers
/// Adds the metadata providers.
/// </summary>
/// <param name="providers">The providers.</param>
public void AddParts(IEnumerable<BaseMetadataProvider> providers)
/// <param name="imageProviders">The image providers.</param>
public void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders)
{
MetadataProviders = providers.OrderBy(e => e.Priority).ToArray();
ImageProviders = imageProviders.ToArray();
}
/// <summary>
@ -344,5 +349,58 @@ namespace MediaBrowser.Server.Implementations.Providers
{
return new ImageSaver(ConfigurationManager, _directoryWatchers).SaveImage(item, source, mimeType, type, imageIndex, sourceUrl, cancellationToken);
}
/// <summary>
/// Gets the available remote images.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="type">The type.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns>
public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, ImageType type, CancellationToken cancellationToken)
{
var providers = GetSupportedImageProviders(item, type);
var tasks = providers.Select(i => Task.Run(async () =>
{
try
{
var result = await i.GetAvailableImages(item, type, cancellationToken).ConfigureAwait(false);
return result.ToList();
}
catch (Exception ex)
{
_logger.ErrorException("{0} failed in GetAvailableImages for type {1}", ex, i.GetType().Name, item.GetType().Name);
return new List<RemoteImageInfo>();
}
}));
var results = await Task.WhenAll(tasks).ConfigureAwait(false);
return results.SelectMany(i => i);
}
/// <summary>
/// Gets the supported image providers.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="type">The type.</param>
/// <returns>IEnumerable{IImageProvider}.</returns>
private IEnumerable<IImageProvider> GetSupportedImageProviders(BaseItem item, ImageType type)
{
return ImageProviders.Where(i =>
{
try
{
return i.Supports(item, type);
}
catch (Exception ex)
{
_logger.ErrorException("{0} failed in Supports for type {1}", ex, i.GetType().Name, item.GetType().Name);
return false;
}
});
}
}
}

@ -275,7 +275,7 @@ namespace MediaBrowser.ServerApplication
DirectoryWatchers = new DirectoryWatchers(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager);
RegisterSingleInstance(DirectoryWatchers);
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, DirectoryWatchers, LogManager, LibraryManager);
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, DirectoryWatchers, LogManager);
RegisterSingleInstance(ProviderManager);
RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager));
@ -449,7 +449,7 @@ namespace MediaBrowser.ServerApplication
GetExports<IPeoplePrescanTask>(),
GetExports<IMetadataSaver>());
ProviderManager.AddParts(GetExports<BaseMetadataProvider>());
ProviderManager.AddParts(GetExports<BaseMetadataProvider>(), GetExports<IImageProvider>());
ImageProcessor.AddParts(GetExports<IImageEnhancer>());

Loading…
Cancel
Save