support backdrops from multiple sources

pull/702/head
Luke Pulverenti 11 years ago
parent 96fd6459b2
commit 32cb872b06

@ -699,11 +699,32 @@ namespace MediaBrowser.Api.Images
var temp1 = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".tmp");
var temp2 = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".tmp");
// Copying over will fail against hidden files
RemoveHiddenAttribute(file1);
RemoveHiddenAttribute(file2);
File.Copy(file1, temp1);
File.Copy(file2, temp2);
File.Copy(temp1, file2, true);
File.Copy(temp2, file1, true);
File.Delete(temp1);
File.Delete(temp2);
}
private void RemoveHiddenAttribute(string path)
{
var currentFile = new FileInfo(path);
// This will fail if the file is hidden
if (currentFile.Exists)
{
if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
{
currentFile.Attributes &= ~FileAttributes.Hidden;
}
}
}
/// <summary>
@ -854,7 +875,7 @@ namespace MediaBrowser.Api.Images
// Handle image/png; charset=utf-8
mimeType = mimeType.Split(';').FirstOrDefault();
await _providerManager.SaveImage(entity, memoryStream, mimeType, imageType, imageIndex, CancellationToken.None).ConfigureAwait(false);
await _providerManager.SaveImage(entity, memoryStream, mimeType, imageType, imageIndex, null, CancellationToken.None).ConfigureAwait(false);
await entity.RefreshMetadata(CancellationToken.None, forceRefresh: true, forceSave: true, allowSlowProviders: false).ConfigureAwait(false);
}

@ -47,6 +47,7 @@ namespace MediaBrowser.Controller.Entities
LockedFields = new List<MetadataFields>();
Taglines = new List<string>();
RemoteTrailers = new List<MediaUrl>();
ImageSources = new List<ImageSourceInfo>();
}
/// <summary>
@ -233,23 +234,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The locked fields.</value>
public List<MetadataFields> LockedFields { get; set; }
/// <summary>
/// Determines whether the item has a saved local image of the specified name (jpg or png).
/// </summary>
/// <param name="name">The name.</param>
/// <returns><c>true</c> if [has local image] [the specified item]; otherwise, <c>false</c>.</returns>
/// <exception cref="System.ArgumentNullException">name</exception>
public bool HasLocalImage(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
return ResolveArgs.ContainsMetaFileByName(name + ".jpg") ||
ResolveArgs.ContainsMetaFileByName(name + ".png");
}
/// <summary>
/// Should be overridden to return the proper folder where metadata lives
/// </summary>
@ -536,6 +520,12 @@ namespace MediaBrowser.Controller.Entities
/// <value>The backdrop image paths.</value>
public List<string> BackdropImagePaths { get; set; }
/// <summary>
/// Gets or sets the backdrop image sources.
/// </summary>
/// <value>The backdrop image sources.</value>
public List<ImageSourceInfo> ImageSources { get; set; }
/// <summary>
/// Gets or sets the screenshot image paths.
/// </summary>
@ -1508,8 +1498,10 @@ namespace MediaBrowser.Controller.Entities
BackdropImagePaths.Remove(file);
RemoveImageSourceForPath(file);
// Delete the source file
File.Delete(file);
DeleteImagePath(file);
}
else if (type == ImageType.Screenshot)
{
@ -1523,12 +1515,12 @@ namespace MediaBrowser.Controller.Entities
ScreenshotImagePaths.Remove(file);
// Delete the source file
File.Delete(file);
DeleteImagePath(file);
}
else
{
// Delete the source file
File.Delete(GetImage(type));
DeleteImagePath(GetImage(type));
// Remove it from the item
SetImage(type, null);
@ -1538,6 +1530,26 @@ namespace MediaBrowser.Controller.Entities
return RefreshMetadata(CancellationToken.None, forceSave: true);
}
/// <summary>
/// Deletes the image path.
/// </summary>
/// <param name="path">The path.</param>
private void DeleteImagePath(string path)
{
var currentFile = new FileInfo(path);
// This will fail if the file is hidden
if (currentFile.Exists)
{
if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
{
currentFile.Attributes &= ~FileAttributes.Hidden;
}
currentFile.Delete();
}
}
/// <summary>
/// Validates that images within the item are still on the file system
/// </summary>
@ -1570,7 +1582,83 @@ namespace MediaBrowser.Controller.Entities
foreach (var path in deletedImages)
{
BackdropImagePaths.Remove(path);
RemoveImageSourceForPath(path);
}
}
/// <summary>
/// Adds the image source.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="url">The URL.</param>
public void AddImageSource(string path, string url)
{
RemoveImageSourceForPath(path);
var pathMd5 = path.ToLower().GetMD5();
ImageSources.Add(new ImageSourceInfo
{
ImagePathMD5 = pathMd5,
ImageUrlMD5 = url.ToLower().GetMD5()
});
}
/// <summary>
/// Gets the image source info.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>ImageSourceInfo.</returns>
public ImageSourceInfo GetImageSourceInfo(string path)
{
if (ImageSources.Count == 0)
{
return null;
}
var pathMd5 = path.ToLower().GetMD5();
return ImageSources.FirstOrDefault(i => i.ImagePathMD5 == pathMd5);
}
/// <summary>
/// Removes the image source for path.
/// </summary>
/// <param name="path">The path.</param>
public void RemoveImageSourceForPath(string path)
{
if (ImageSources.Count == 0)
{
return;
}
var pathMd5 = path.ToLower().GetMD5();
// Remove existing
foreach (var entry in ImageSources
.Where(i => i.ImagePathMD5 == pathMd5)
.ToList())
{
ImageSources.Remove(entry);
}
}
/// <summary>
/// Determines whether [contains image with source URL] [the specified URL].
/// </summary>
/// <param name="url">The URL.</param>
/// <returns><c>true</c> if [contains image with source URL] [the specified URL]; otherwise, <c>false</c>.</returns>
public bool ContainsImageWithSourceUrl(string url)
{
if (ImageSources.Count == 0)
{
return false;
}
var md5 = url.ToLower().GetMD5();
return ImageSources.Any(i => i.ImageUrlMD5 == md5);
}
/// <summary>

@ -0,0 +1,10 @@
using System;
namespace MediaBrowser.Controller.Entities
{
public class ImageSourceInfo
{
public Guid ImagePathMD5 { get; set; }
public Guid ImageUrlMD5 { get; set; }
}
}

@ -91,6 +91,7 @@
<Compile Include="Entities\IByReferenceItem.cs" />
<Compile Include="Entities\IItemByName.cs" />
<Compile Include="Entities\ILibraryItem.cs" />
<Compile Include="Entities\ImageSourceInfo.cs" />
<Compile Include="Entities\LinkedChild.cs" />
<Compile Include="Entities\MusicVideo.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />

@ -43,9 +43,10 @@ namespace MediaBrowser.Controller.Providers
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="sourceUrl">The source URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken);
Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, string sourceUrl, CancellationToken cancellationToken);
/// <summary>
/// Adds the metadata providers.

@ -233,6 +233,12 @@ namespace MediaBrowser.Model.Configuration
/// <value>The width of the min movie backdrop.</value>
public int MinMovieBackdropWidth { get; set; }
/// <summary>
/// Gets or sets the width of the min series backdrop.
/// </summary>
/// <value>The width of the min series backdrop.</value>
public int MinSeriesBackdropWidth { get; set; }
/// <summary>
/// Gets or sets the width of the min movie poster.
/// </summary>
@ -286,6 +292,7 @@ namespace MediaBrowser.Model.Configuration
SeasonZeroDisplayName = "Specials";
MinMovieBackdropWidth = 1920;
MinSeriesBackdropWidth = 1920;
MinMoviePosterWidth = 1000;
}
}

@ -153,7 +153,7 @@ namespace MediaBrowser.Providers.Movies
item.HasImage(ImageType.Disc) &&
item.HasImage(ImageType.Banner) &&
item.HasImage(ImageType.Thumb) &&
item.BackdropImagePaths.Count > 0)
item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops)
{
return false;
}
@ -389,7 +389,8 @@ namespace MediaBrowser.Providers.Movies
}
}
if (ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count == 0)
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;
if (ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit)
{
var nodes = doc.SelectNodes("//fanart/movie/moviebackgrounds//@url");
@ -401,14 +402,14 @@ namespace MediaBrowser.Providers.Movies
{
path = node.Value;
if (!string.IsNullOrEmpty(path))
if (!string.IsNullOrEmpty(path) && !item.ContainsImageWithSourceUrl(path))
{
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken)
.ConfigureAwait(false);
numBackdrops++;
if (item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops) break;
if (item.BackdropImagePaths.Count >= backdropLimit) break;
}
}

@ -9,7 +9,6 @@ using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -135,7 +134,7 @@ namespace MediaBrowser.Providers.Movies
}
// Don't refresh if we already have both poster and backdrop and we're not refreshing images
if (item.HasImage(ImageType.Primary) && item.BackdropImagePaths.Count > 0)
if (item.HasImage(ImageType.Primary) && item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops)
{
return false;
}
@ -239,14 +238,16 @@ namespace MediaBrowser.Providers.Movies
if (poster != null)
{
var url = tmdbImageUrl + poster.file_path;
var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = tmdbImageUrl + poster.file_path,
Url = url,
CancellationToken = cancellationToken
}).ConfigureAwait(false);
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(poster.file_path), ImageType.Primary, null, cancellationToken)
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(poster.file_path), ImageType.Primary, null, url, cancellationToken)
.ConfigureAwait(false);
}
@ -258,8 +259,10 @@ namespace MediaBrowser.Providers.Movies
images.backdrops.Where(i => i.width >= ConfigurationManager.Configuration.MinMovieBackdropWidth)
.ToList();
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;
// backdrops - only download if earlier providers didn't find any (fanart)
if (eligibleBackdrops.Count > 0 && ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count == 0)
if (eligibleBackdrops.Count > 0 && ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit)
{
var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
@ -267,24 +270,22 @@ namespace MediaBrowser.Providers.Movies
for (var i = 0; i < eligibleBackdrops.Count; i++)
{
var bdName = "backdrop" + (i == 0 ? "" : i.ToString(CultureInfo.InvariantCulture));
var hasLocalBackdrop = item.LocationType == LocationType.FileSystem && ConfigurationManager.Configuration.SaveLocalMeta ? item.HasLocalImage(bdName) : item.BackdropImagePaths.Count > i;
var url = tmdbImageUrl + eligibleBackdrops[i].file_path;
if (!hasLocalBackdrop)
if (!item.ContainsImageWithSourceUrl(url))
{
var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
{
Url = tmdbImageUrl + eligibleBackdrops[i].file_path,
Url = url,
CancellationToken = cancellationToken
}).ConfigureAwait(false);
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(eligibleBackdrops[i].file_path), ImageType.Backdrop, item.BackdropImagePaths.Count, cancellationToken)
await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(eligibleBackdrops[i].file_path), ImageType.Backdrop, item.BackdropImagePaths.Count, url, cancellationToken)
.ConfigureAwait(false);
}
if (item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops)
if (item.BackdropImagePaths.Count >= backdropLimit)
{
break;
}

@ -513,7 +513,7 @@ namespace MediaBrowser.Providers.Movies
{
var isBoxSet = item is BoxSet;
var mainResult = await FetchMainResult(id, isBoxSet, cancellationToken).ConfigureAwait(false);
var mainResult = await FetchMainResult(id, isBoxSet, language, cancellationToken).ConfigureAwait(false);
if (mainResult == null) return;
@ -550,7 +550,7 @@ namespace MediaBrowser.Providers.Movies
{
var language = ConfigurationManager.Configuration.PreferredMetadataLanguage;
var mainResult = await FetchMainResult(id, isBoxSet, cancellationToken).ConfigureAwait(false);
var mainResult = await FetchMainResult(id, isBoxSet, language, cancellationToken).ConfigureAwait(false);
if (mainResult == null) return;
@ -588,13 +588,14 @@ namespace MediaBrowser.Providers.Movies
/// </summary>
/// <param name="id">The id.</param>
/// <param name="isBoxSet">if set to <c>true</c> [is box set].</param>
/// <param name="language">The language.</param>
/// <param name="cancellationToken">The cancellation token</param>
/// <returns>Task{CompleteMovieData}.</returns>
protected async Task<CompleteMovieData> FetchMainResult(string id, bool isBoxSet, CancellationToken cancellationToken)
protected async Task<CompleteMovieData> FetchMainResult(string id, bool isBoxSet, string language, CancellationToken cancellationToken)
{
var baseUrl = isBoxSet ? GetBoxSetInfo3 : GetMovieInfo3;
string url = string.Format(baseUrl, id, ApiKey, ConfigurationManager.Configuration.PreferredMetadataLanguage);
string url = string.Format(baseUrl, id, ApiKey, language);
CompleteMovieData mainResult;
cancellationToken.ThrowIfCancellationRequested();
@ -614,13 +615,13 @@ namespace MediaBrowser.Providers.Movies
if (mainResult != null && string.IsNullOrEmpty(mainResult.overview))
{
if (ConfigurationManager.Configuration.PreferredMetadataLanguage.ToLower() != "en")
if (language.ToLower() != "en")
{
Logger.Info("MovieDbProvider couldn't find meta for language " + ConfigurationManager.Configuration.PreferredMetadataLanguage + ". Trying English...");
Logger.Info("MovieDbProvider couldn't find meta for language " + language + ". Trying English...");
url = string.Format(baseUrl, id, ApiKey, "en");
using (Stream json = await GetMovieDbResponse(new HttpRequestOptions
using (var json = await GetMovieDbResponse(new HttpRequestOptions
{
Url = url,
CancellationToken = cancellationToken,

@ -390,7 +390,7 @@ namespace MediaBrowser.Providers.Movies
}).ConfigureAwait(false))
{
await ProviderManager.SaveImage(item, sourceStream, mimeType, ImageType.Primary, null, cancellationToken)
await ProviderManager.SaveImage(item, sourceStream, mimeType, ImageType.Primary, null, source, cancellationToken)
.ConfigureAwait(false);
Logger.Debug("TmdbPersonProvider downloaded and saved image for {0}", item.Name);

@ -1,5 +1,4 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;

@ -332,6 +332,8 @@ namespace MediaBrowser.Providers.Music
}
cancellationToken.ThrowIfCancellationRequested();
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;
if (ConfigurationManager.Configuration.DownloadMusicArtistImages.Backdrops && item.BackdropImagePaths.Count == 0)
{
var nodes = doc.SelectNodes("//fanart/music/artistbackgrounds//@url");
@ -342,14 +344,14 @@ namespace MediaBrowser.Providers.Music
foreach (XmlNode node in nodes)
{
path = node.Value;
if (!string.IsNullOrEmpty(path))
if (!string.IsNullOrEmpty(path) && !item.ContainsImageWithSourceUrl(path))
{
try
{
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken)
.ConfigureAwait(false);
numBackdrops++;
if (numBackdrops >= ConfigurationManager.Configuration.MaxBackdrops) break;
if (numBackdrops >= backdropLimit) break;
}
catch (HttpException ex)
{

@ -94,7 +94,7 @@ namespace MediaBrowser.Providers.TV
item.HasImage(ImageType.Logo) &&
item.HasImage(ImageType.Banner) &&
item.HasImage(ImageType.Thumb) &&
item.BackdropImagePaths.Count > 0)
item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops)
{
return false;
}
@ -298,7 +298,9 @@ namespace MediaBrowser.Providers.TV
}
}
if (ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count == 0)
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;
if (ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit)
{
var nodes = doc.SelectNodes("//fanart/series/showbackgrounds//@url");
@ -310,14 +312,14 @@ namespace MediaBrowser.Providers.TV
{
var path = node.Value;
if (!string.IsNullOrEmpty(path))
if (!string.IsNullOrEmpty(path) && !item.ContainsImageWithSourceUrl(path))
{
await _providerManager.SaveImage(item, path, FanArtResourcePool, ImageType.Backdrop, numBackdrops, cancellationToken)
.ConfigureAwait(false);
numBackdrops++;
if (item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops) break;
if (item.BackdropImagePaths.Count >= backdropLimit) break;
}
}

@ -121,6 +121,15 @@ namespace MediaBrowser.Providers.TV
return false;
}
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Banner) && item.BackdropImagePaths.Count > 0)
{
return false;
}
return base.NeedsRefreshInternal(item, providerInfo);
}
/// <summary>
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
/// </summary>
@ -146,7 +155,7 @@ namespace MediaBrowser.Providers.TV
try
{
var fanartData = FetchFanartXmlData(imagesXmlPath, seasonNumber.Value, cancellationToken);
await DownloadImages(item, fanartData, ConfigurationManager.Configuration.MaxBackdrops, cancellationToken).ConfigureAwait(false);
await DownloadImages(item, fanartData, 1, cancellationToken).ConfigureAwait(false);
}
catch (FileNotFoundException)
{
@ -186,13 +195,18 @@ namespace MediaBrowser.Providers.TV
}
}
if (ConfigurationManager.Configuration.DownloadSeasonImages.Backdrops && item.BackdropImagePaths.Count == 0)
if (ConfigurationManager.Configuration.DownloadSeasonImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit)
{
var bdNo = item.BackdropImagePaths.Count;
foreach (var backdrop in data.Backdrops)
{
var url = TVUtils.BannerUrl + backdrop;
var url = TVUtils.BannerUrl + backdrop.Url;
if (item.ContainsImageWithSourceUrl(url))
{
continue;
}
await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken)
.ConfigureAwait(false);
@ -260,6 +274,7 @@ namespace MediaBrowser.Providers.TV
string bannerType2 = null;
string url = null;
int? bannerSeason = null;
string resolution = null;
while (reader.Read())
{
@ -319,7 +334,11 @@ namespace MediaBrowser.Providers.TV
}
else if (string.Equals(bannerType, "fanart", StringComparison.OrdinalIgnoreCase))
{
data.Backdrops.Add(url);
data.Backdrops.Add(new ImageInfo
{
Url = url,
Resolution = resolution
});
}
}
}

@ -1,4 +1,5 @@
using MediaBrowser.Common.Net;
using System.Linq;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
@ -133,6 +134,15 @@ namespace MediaBrowser.Providers.TV
return base.CompareDate(item);
}
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Banner) && item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MaxBackdrops)
{
return false;
}
return base.NeedsRefreshInternal(item, providerInfo);
}
/// <summary>
/// Fetches metadata and returns true or false indicating if any work that requires persistence was done
/// </summary>
@ -154,10 +164,10 @@ namespace MediaBrowser.Providers.TV
var imagesXmlPath = Path.Combine(seriesDataPath, "banners.xml");
if (!series.HasImage(ImageType.Primary) || !series.HasImage(ImageType.Banner) || series.BackdropImagePaths.Count == 0)
{
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;
var backdropLimit = ConfigurationManager.Configuration.MaxBackdrops;
if (!series.HasImage(ImageType.Primary) || !series.HasImage(ImageType.Banner) || series.BackdropImagePaths.Count < backdropLimit)
{
Directory.CreateDirectory(seriesDataPath);
try
@ -171,13 +181,6 @@ namespace MediaBrowser.Providers.TV
}
}
BaseProviderInfo data;
if (!item.ProviderData.TryGetValue(Id, out data))
{
data = new BaseProviderInfo();
item.ProviderData[Id] = data;
}
SetLastRefreshed(item, DateTime.UtcNow);
return true;
}
@ -213,13 +216,39 @@ namespace MediaBrowser.Providers.TV
}
}
if (ConfigurationManager.Configuration.DownloadSeriesImages.Backdrops && item.BackdropImagePaths.Count == 0)
if (ConfigurationManager.Configuration.DownloadSeriesImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit)
{
var bdNo = item.BackdropImagePaths.Count;
foreach (var backdrop in data.Backdrops)
var eligibleBackdrops = data.Backdrops
.Where(i =>
{
if (string.IsNullOrEmpty(i.Resolution))
{
return true;
}
var parts = i.Resolution.Split('x');
int width;
if (int.TryParse(parts[0], NumberStyles.Any, UsCulture, out width))
{
return width >= ConfigurationManager.Configuration.MinSeriesBackdropWidth;
}
return true;
})
.ToList();
foreach (var backdrop in eligibleBackdrops)
{
var url = TVUtils.BannerUrl + backdrop;
var url = TVUtils.BannerUrl + backdrop.Url;
if (item.ContainsImageWithSourceUrl(url))
{
continue;
}
await _providerManager.SaveImage(item, url, RemoteSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, bdNo, cancellationToken)
.ConfigureAwait(false);
@ -285,6 +314,7 @@ namespace MediaBrowser.Providers.TV
string type = null;
string url = null;
string resolution = null;
while (reader.Read())
{
@ -312,13 +342,6 @@ namespace MediaBrowser.Providers.TV
return;
}
}
else if (string.Equals(type, "fanart", StringComparison.OrdinalIgnoreCase))
{
if (data.Backdrops.Count >= backdropLimit)
{
return;
}
}
else
{
return;
@ -333,6 +356,12 @@ namespace MediaBrowser.Providers.TV
break;
}
case "BannerType2":
{
resolution = reader.ReadElementContentAsString() ?? string.Empty;
break;
}
default:
reader.Skip();
break;
@ -352,7 +381,11 @@ namespace MediaBrowser.Providers.TV
}
else if (string.Equals(type, "fanart", StringComparison.OrdinalIgnoreCase))
{
data.Backdrops.Add(url);
data.Backdrops.Add(new ImageInfo
{
Url = url,
Resolution = resolution
});
}
}
}
@ -364,6 +397,12 @@ namespace MediaBrowser.Providers.TV
public string LanguageBanner { get; set; }
public string Poster { get; set; }
public string Banner { get; set; }
public List<string> Backdrops = new List<string>();
public List<ImageInfo> Backdrops = new List<ImageInfo>();
}
internal class ImageInfo
{
public string Url { get; set; }
public string Resolution { get; set; }
}
}

@ -90,10 +90,22 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
MergeImages(musicArtist.Images, artist.Images);
// Merge backdrops
var backdrops = musicArtist.BackdropImagePaths.ToList();
backdrops.InsertRange(0, artist.BackdropImagePaths);
artist.BackdropImagePaths = backdrops.Distinct(StringComparer.OrdinalIgnoreCase)
var additionalBackdrops = musicArtist
.BackdropImagePaths
.Except(artist.BackdropImagePaths)
.ToList();
var sources = additionalBackdrops
.Select(musicArtist.GetImageSourceInfo)
.ToList();
foreach (var path in additionalBackdrops)
{
artist.RemoveImageSourceForPath(path);
}
artist.BackdropImagePaths.AddRange(additionalBackdrops);
artist.ImageSources.AddRange(sources);
}
if (!artist.LockedFields.Contains(MetadataFields.Genres))

@ -56,9 +56,11 @@ namespace MediaBrowser.Server.Implementations.Providers
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="sourceUrl">The source URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public async Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
/// <exception cref="System.ArgumentNullException">mimeType</exception>
public async Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, string sourceUrl, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(mimeType))
{
@ -128,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Providers
}
// Set the path into the BaseItem
SetImagePath(item, type, imageIndex, paths[0]);
SetImagePath(item, type, imageIndex, paths[0], sourceUrl);
// Delete the current path
if (!string.IsNullOrEmpty(currentPath) && !paths.Contains(currentPath, StringComparer.OrdinalIgnoreCase))
@ -137,7 +139,18 @@ namespace MediaBrowser.Server.Implementations.Providers
try
{
File.Delete(currentPath);
var currentFile = new FileInfo(currentPath);
// This will fail if the file is hidden
if (currentFile.Exists)
{
if ((currentFile.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
{
currentFile.Attributes &= ~FileAttributes.Hidden;
}
currentFile.Delete();
}
}
finally
{
@ -244,12 +257,11 @@ namespace MediaBrowser.Server.Implementations.Providers
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="path">The path.</param>
/// <exception cref="System.ArgumentNullException">
/// imageIndex
/// <param name="sourceUrl">The source URL.</param>
/// <exception cref="System.ArgumentNullException">imageIndex
/// or
/// imageIndex
/// </exception>
private void SetImagePath(BaseItem item, ImageType type, int? imageIndex, string path)
/// imageIndex</exception>
private void SetImagePath(BaseItem item, ImageType type, int? imageIndex, string path, string sourceUrl)
{
switch (type)
{
@ -282,6 +294,15 @@ namespace MediaBrowser.Server.Implementations.Providers
{
item.BackdropImagePaths.Add(path);
}
if (string.IsNullOrEmpty(sourceUrl))
{
item.RemoveImageSourceForPath(path);
}
else
{
item.AddImageSource(path, sourceUrl);
}
break;
default:
item.SetImage(type, path);

@ -325,7 +325,7 @@ namespace MediaBrowser.Server.Implementations.Providers
}).ConfigureAwait(false);
await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken)
await SaveImage(item, response.Content, response.ContentType, type, imageIndex, url, cancellationToken)
.ConfigureAwait(false);
}
@ -337,11 +337,12 @@ namespace MediaBrowser.Server.Implementations.Providers
/// <param name="mimeType">Type of the MIME.</param>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="sourceUrl">The source URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, string sourceUrl, CancellationToken cancellationToken)
{
return new ImageSaver(ConfigurationManager, _directoryWatchers).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken);
return new ImageSaver(ConfigurationManager, _directoryWatchers).SaveImage(item, source, mimeType, type, imageIndex, sourceUrl, cancellationToken);
}
}
}

@ -174,6 +174,11 @@ namespace MediaBrowser.Server.Implementations.Session
/// <param name="item">The item.</param>
private void RemoveNowPlayingItem(SessionInfo session, BaseItem item)
{
if (item == null)
{
throw new ArgumentNullException("item");
}
if (session.NowPlayingItem != null && session.NowPlayingItem.Id == item.Id)
{
session.NowPlayingItem = null;
@ -319,6 +324,16 @@ namespace MediaBrowser.Server.Implementations.Session
throw new ArgumentNullException("info");
}
if (info.Item == null)
{
throw new ArgumentException("PlaybackStopInfo.Item cannot be null");
}
if (info.SessionId == Guid.Empty)
{
throw new ArgumentException("PlaybackStopInfo.SessionId cannot be Guid.Empty");
}
if (info.PositionTicks.HasValue && info.PositionTicks.Value < 0)
{
throw new ArgumentOutOfRangeException("positionTicks");

Loading…
Cancel
Save