diff options
Diffstat (limited to 'MediaBrowser.Providers')
5 files changed, 322 insertions, 64 deletions
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 7a8975937d..e944787c6d 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -61,6 +61,7 @@ <Compile Include="MediaInfo\VideoImageProvider.cs" /> <Compile Include="Movies\BoxSetProviderFromXml.cs" /> <Compile Include="Movies\ManualMovieDbImageProvider.cs" /> + <Compile Include="Movies\ManualFanartMovieImageProvider.cs" /> <Compile Include="Movies\MovieUpdatesPrescanTask.cs" /> <Compile Include="Movies\MovieXmlParser.cs" /> <Compile Include="Movies\FanArtMovieProvider.cs" /> diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs index 3458622d34..355d3df0d1 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs @@ -4,7 +4,6 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -35,11 +34,6 @@ namespace MediaBrowser.Providers.Movies /// </summary> private readonly IProviderManager _providerManager; - /// <summary> - /// The us culture - /// </summary> - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - internal static FanArtMovieProvider Current { get; private set; } private readonly IFileSystem _fileSystem; @@ -139,28 +133,6 @@ namespace MediaBrowser.Providers.Movies return false; } - if (!ConfigurationManager.Configuration.DownloadMovieImages.Art && - !ConfigurationManager.Configuration.DownloadMovieImages.Logo && - !ConfigurationManager.Configuration.DownloadMovieImages.Disc && - !ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && - !ConfigurationManager.Configuration.DownloadMovieImages.Banner && - !ConfigurationManager.Configuration.DownloadMovieImages.Thumb && - !ConfigurationManager.Configuration.DownloadMovieImages.Primary) - { - return false; - } - - if (item.HasImage(ImageType.Primary) && - item.HasImage(ImageType.Art) && - item.HasImage(ImageType.Logo) && - item.HasImage(ImageType.Disc) && - item.HasImage(ImageType.Banner) && - item.HasImage(ImageType.Thumb) && - item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops) - { - return false; - } - return base.NeedsRefreshInternal(item, providerInfo); } @@ -171,24 +143,11 @@ namespace MediaBrowser.Providers.Movies if (!string.IsNullOrEmpty(id)) { // Process images - var path = GetMovieDataPath(ConfigurationManager.ApplicationPaths, id); + var xmlPath = GetFanartXmlPath(id); - try - { - var files = new DirectoryInfo(path) - .EnumerateFiles("*.xml", SearchOption.TopDirectoryOnly) - .Select(i => _fileSystem.GetLastWriteTimeUtc(i)) - .ToList(); + var fileInfo = new FileInfo(xmlPath); - if (files.Count > 0) - { - return files.Max() > providerInfo.LastRefreshed; - } - } - catch (DirectoryNotFoundException) - { - return true; - } + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed; } return base.NeedsRefreshBasedOnCompareDate(item, providerInfo); @@ -253,6 +212,12 @@ namespace MediaBrowser.Providers.Movies return true; } + public string GetFanartXmlPath(string tmdbId) + { + var movieDataPath = GetMovieDataPath(ConfigurationManager.ApplicationPaths, tmdbId); + return Path.Combine(movieDataPath, "fanart.xml"); + } + /// <summary> /// Downloads the movie XML. /// </summary> diff --git a/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs new file mode 100644 index 0000000000..85dd13936a --- /dev/null +++ b/MediaBrowser.Providers/Movies/ManualFanartMovieImageProvider.cs @@ -0,0 +1,291 @@ +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Providers; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; + +namespace MediaBrowser.Providers.Movies +{ + public class ManualFanartMovieImageProvider : IImageProvider + { + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); + private readonly IServerConfigurationManager _config; + + public ManualFanartMovieImageProvider(IServerConfigurationManager config) + { + _config = config; + } + + public string Name + { + get { return "FanArt"; } + } + + public bool Supports(BaseItem item) + { + return FanArtMovieProvider.Current.Supports(item); + } + + public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + { + var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); + + return images.Where(i => i.Type == imageType); + } + + public Task<IEnumerable<RemoteImageInfo>> GetAllImages(BaseItem item, CancellationToken cancellationToken) + { + var list = new List<RemoteImageInfo>(); + + var movieId = item.GetProviderId(MetadataProviders.Tmdb); + + if (!string.IsNullOrEmpty(movieId)) + { + var xmlPath = FanArtMovieProvider.Current.GetFanartXmlPath(movieId); + + try + { + AddImages(list, xmlPath, cancellationToken); + } + catch (FileNotFoundException) + { + // No biggie. Don't blow up + } + } + + var language = _config.Configuration.PreferredMetadataLanguage; + + var isLanguageEn = string.Equals(language, "en", StringComparison.OrdinalIgnoreCase); + + list = list.OrderByDescending(i => i.Width ?? 0) + .ThenByDescending(i => + { + if (string.Equals(language, i.Language, StringComparison.OrdinalIgnoreCase)) + { + return 3; + } + if (!isLanguageEn) + { + if (string.Equals("en", i.Language, StringComparison.OrdinalIgnoreCase)) + { + return 2; + } + } + if (string.IsNullOrEmpty(i.Language)) + { + return isLanguageEn ? 3 : 2; + } + return 0; + }) + .ThenByDescending(i => i.CommunityRating ?? 0) + .ToList(); + + return Task.FromResult<IEnumerable<RemoteImageInfo>>(list); + } + + private void AddImages(List<RemoteImageInfo> list, string xmlPath, CancellationToken cancellationToken) + { + using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8)) + { + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + })) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "movie": + { + using (var subReader = reader.ReadSubtree()) + { + AddImages(list, subReader, cancellationToken); + } + break; + } + + default: + reader.Skip(); + break; + } + } + } + } + } + } + + private void AddImages(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken) + { + reader.MoveToContent(); + + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "hdmoviecleararts": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 1000, 562); + } + break; + } + case "hdmovielogos": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 800, 310); + } + break; + } + case "moviediscs": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Disc, 1000, 1000); + } + break; + } + case "movieposters": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Primary, 1000, 1426); + } + break; + } + case "movielogos": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Logo, 400, 155); + } + break; + } + case "moviearts": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Art, 500, 281); + } + break; + } + case "moviethumbs": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Thumb, 1000, 562); + } + break; + } + case "moviebanners": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Banner, 1000, 185); + } + break; + } + case "moviebackgrounds": + { + using (var subReader = reader.ReadSubtree()) + { + PopulateImageCategory(list, subReader, cancellationToken, ImageType.Backdrop, 1920, 1080); + } + break; + } + default: + reader.Skip(); + break; + } + } + } + } + + private void PopulateImageCategory(List<RemoteImageInfo> list, XmlReader reader, CancellationToken cancellationToken, ImageType type, int width, int height) + { + reader.MoveToContent(); + + while (reader.Read()) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (reader.NodeType == XmlNodeType.Element) + { + switch (reader.Name) + { + case "hdmovielogo": + case "moviedisc": + case "hdmovieclearart": + case "movieposter": + case "movielogo": + case "movieart": + case "moviethumb": + case "moviebanner": + case "moviebackground": + { + var url = reader.GetAttribute("url"); + + if (!string.IsNullOrEmpty(url)) + { + var likesString = reader.GetAttribute("likes"); + int likes; + + var info = new RemoteImageInfo + { + RatingType = RatingType.Likes, + Type = type, + Width = width, + Height = height, + ProviderName = Name, + Url = url, + Language = reader.GetAttribute("lang") + }; + + if (!string.IsNullOrEmpty(likesString) && int.TryParse(likesString, NumberStyles.Any, _usCulture, out likes)) + { + info.CommunityRating = likes; + } + + list.Add(info); + } + break; + } + default: + reader.Skip(); + break; + } + } + } + } + + public int Priority + { + get { return 1; } + } + } +} diff --git a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs index f84845af7d..c02c60f754 100644 --- a/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs +++ b/MediaBrowser.Providers/Movies/ManualMovieDbImageProvider.cs @@ -1,6 +1,7 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; using MediaBrowser.Model.Serialization; @@ -26,20 +27,15 @@ namespace MediaBrowser.Providers.Movies public string Name { - get { return "TheMovieDB"; } + get { return "TheMovieDb"; } } - public bool Supports(BaseItem item, ImageType imageType) + public bool Supports(BaseItem item) { - if (MovieDbImagesProvider.SupportsItem(item)) - { - return imageType == ImageType.Primary || imageType == ImageType.Backdrop; - } - - return false; + return MovieDbImagesProvider.SupportsItem(item); } - public async Task<IEnumerable<RemoteImageInfo>> GetAvailableImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) + public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) { var images = await GetAllImages(item, cancellationToken).ConfigureAwait(false); @@ -70,7 +66,8 @@ namespace MediaBrowser.Providers.Movies Height = i.height, Language = i.iso_639_1, ProviderName = Name, - Type = ImageType.Primary + Type = ImageType.Primary, + RatingType = RatingType.Score })); list.AddRange(GetBackdrops(results, item).Select(i => new RemoteImageInfo @@ -81,7 +78,8 @@ namespace MediaBrowser.Providers.Movies Width = i.width, Height = i.height, ProviderName = Name, - Type = ImageType.Backdrop + Type = ImageType.Backdrop, + RatingType = RatingType.Score })); return list; @@ -124,6 +122,7 @@ namespace MediaBrowser.Providers.Movies return 0; }) .ThenByDescending(i => i.vote_average) + .ThenByDescending(i => i.vote_count) .ToList(); } @@ -139,7 +138,7 @@ namespace MediaBrowser.Providers.Movies images.backdrops.Where(i => i.width >= _config.Configuration.MinMovieBackdropWidth) .ToList(); - return eligibleBackdrops.OrderByDescending(i => i.vote_average); + return eligibleBackdrops.OrderByDescending(i => i.vote_average).ThenByDescending(i => i.vote_count); } /// <summary> @@ -164,5 +163,10 @@ namespace MediaBrowser.Providers.Movies return null; } + + public int Priority + { + get { return 2; } + } } } diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index d7b7faeea7..50adda6bbe 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -216,16 +216,13 @@ namespace MediaBrowser.Providers.Movies if (!string.IsNullOrEmpty(path)) { var fileInfo = new FileInfo(path); + var defaultFileInfo = new FileInfo(Path.Combine(Path.GetDirectoryName(path), "default.json")); - if (fileInfo.Exists) - { - return _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed; - } - - return true; + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > providerInfo.LastRefreshed || + !defaultFileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(defaultFileInfo) > providerInfo.LastRefreshed; } - return base.NeedsRefreshBasedOnCompareDate(item, providerInfo); + return true; } /// <summary> @@ -510,7 +507,7 @@ namespace MediaBrowser.Providers.Movies var dataFilePath = GetDataFilePath(item, language); - if (string.IsNullOrEmpty(dataFilePath) || !File.Exists(dataFilePath)) + if (string.IsNullOrEmpty(dataFilePath) || !File.Exists(dataFilePath) || !File.Exists(Path.Combine(Path.GetDirectoryName(dataFilePath), "default.json"))) { var isBoxSet = item is BoxSet; |
