aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-02-19 00:21:03 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-02-19 00:21:03 -0500
commit4e38c3537398b01776f6e1c5e1c08bce73eec82e (patch)
tree3fc399f51419d6aae3ae8d96769995cc28191d1f /MediaBrowser.Providers
parentcf4ae16f18376c38fed7a8fcaefdc883893473a2 (diff)
fixed remote control flyout
Diffstat (limited to 'MediaBrowser.Providers')
-rw-r--r--MediaBrowser.Providers/Genres/GenreMetadataService.cs8
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs185
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj1
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs3
-rw-r--r--MediaBrowser.Providers/People/MovieDbPersonProvider.cs94
-rw-r--r--MediaBrowser.Providers/Savers/XmlSaverHelpers.cs5
-rw-r--r--MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs272
7 files changed, 429 insertions, 139 deletions
diff --git a/MediaBrowser.Providers/Genres/GenreMetadataService.cs b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
index b19241095f..f408d026b1 100644
--- a/MediaBrowser.Providers/Genres/GenreMetadataService.cs
+++ b/MediaBrowser.Providers/Genres/GenreMetadataService.cs
@@ -1,25 +1,19 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Providers.Manager;
using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
namespace MediaBrowser.Providers.Genres
{
public class GenreMetadataService : MetadataService<Genre, ItemLookupInfo>
{
- private readonly ILibraryManager _libraryManager;
-
- public GenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager)
+ public GenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem)
: base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem)
{
- _libraryManager = libraryManager;
}
/// <summary>
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index ced9e48680..19d1e3ba2f 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -52,11 +52,10 @@ namespace MediaBrowser.Providers.Manager
private readonly IFileSystem _fileSystem;
- private readonly IProviderRepository _providerRepo;
-
private IMetadataService[] _metadataServices = { };
private IMetadataProvider[] _metadataProviders = { };
private IEnumerable<IMetadataSaver> _savers;
+ private IImageSaver[] _imageSavers;
/// <summary>
/// Initializes a new instance of the <see cref="ProviderManager" /> class.
@@ -66,15 +65,13 @@ namespace MediaBrowser.Providers.Manager
/// <param name="libraryMonitor">The directory watchers.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="fileSystem">The file system.</param>
- /// <param name="providerRepo">The provider repo.</param>
- public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IProviderRepository providerRepo)
+ public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem)
{
_logger = logManager.GetLogger("ProviderManager");
_httpClient = httpClient;
ConfigurationManager = configurationManager;
_libraryMonitor = libraryMonitor;
_fileSystem = fileSystem;
- _providerRepo = providerRepo;
}
/// <summary>
@@ -84,13 +81,16 @@ namespace MediaBrowser.Providers.Manager
/// <param name="metadataServices">The metadata services.</param>
/// <param name="metadataProviders">The metadata providers.</param>
/// <param name="metadataSavers">The metadata savers.</param>
- public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers)
+ /// <param name="imageSavers">The image savers.</param>
+ public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers,
+ IEnumerable<IImageSaver> imageSavers)
{
ImageProviders = imageProviders.ToArray();
_metadataServices = metadataServices.OrderBy(i => i.Order).ToArray();
_metadataProviders = metadataProviders.ToArray();
_savers = metadataSavers.ToArray();
+ _imageSavers = imageSavers.ToArray();
}
public Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken)
@@ -107,62 +107,6 @@ namespace MediaBrowser.Providers.Manager
}
/// <summary>
- /// Saves to library filesystem.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="path">The path.</param>
- /// <param name="dataToSave">The data to save.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException"></exception>
- public async Task SaveToLibraryFilesystem(BaseItem item, string path, Stream dataToSave, CancellationToken cancellationToken)
- {
- if (item == null)
- {
- throw new ArgumentNullException();
- }
- if (string.IsNullOrEmpty(path))
- {
- throw new ArgumentNullException();
- }
- if (dataToSave == null)
- {
- throw new ArgumentNullException();
- }
-
- if (cancellationToken.IsCancellationRequested)
- {
- dataToSave.Dispose();
- cancellationToken.ThrowIfCancellationRequested();
- }
-
- //Tell the watchers to ignore
- _libraryMonitor.ReportFileSystemChangeBeginning(path);
-
- if (dataToSave.CanSeek)
- {
- dataToSave.Position = 0;
- }
-
- try
- {
- using (dataToSave)
- {
- using (var fs = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
- {
- await dataToSave.CopyToAsync(fs, StreamDefaults.DefaultCopyToBufferSize, cancellationToken).ConfigureAwait(false);
- }
- }
- }
- finally
- {
- //Remove the ignore
- _libraryMonitor.ReportFileSystemChangeComplete(path, false);
- }
- }
-
-
- /// <summary>
/// Saves the image.
/// </summary>
/// <param name="item">The item.</param>
@@ -252,8 +196,13 @@ namespace MediaBrowser.Providers.Manager
result = result.Where(i => i.Type == type.Value);
}
- return string.IsNullOrEmpty(preferredLanguage) ? result :
- FilterImages(result, preferredLanguage);
+ if (string.Equals(preferredLanguage, "en", StringComparison.OrdinalIgnoreCase))
+ {
+ result = result.Where(i => string.IsNullOrEmpty(i.Language) ||
+ string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase));
+ }
+
+ return result;
}
catch (Exception ex)
{
@@ -262,17 +211,6 @@ namespace MediaBrowser.Providers.Manager
}
}
- private IEnumerable<RemoteImageInfo> FilterImages(IEnumerable<RemoteImageInfo> images, string preferredLanguage)
- {
- if (string.Equals(preferredLanguage, "en", StringComparison.OrdinalIgnoreCase))
- {
- images = images.Where(i => string.IsNullOrEmpty(i.Language) ||
- string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase));
- }
-
- return images;
- }
-
/// <summary>
/// Gets the supported image providers.
/// </summary>
@@ -294,13 +232,16 @@ namespace MediaBrowser.Providers.Manager
private IEnumerable<IImageProvider> GetImageProviders(IHasImages item, MetadataOptions options, bool includeDisabled)
{
+ // Avoid implicitly captured closure
+ var currentOptions = options;
+
return ImageProviders.Where(i => CanRefresh(i, item, options, includeDisabled))
.OrderBy(i =>
{
// See if there's a user-defined order
if (!(i is ILocalImageProvider))
{
- var index = Array.IndexOf(options.ImageFetcherOrder, i.Name);
+ var index = Array.IndexOf(currentOptions.ImageFetcherOrder, i.Name);
if (index != -1)
{
@@ -325,36 +266,13 @@ namespace MediaBrowser.Providers.Manager
private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, MetadataOptions options, bool includeDisabled)
where T : IHasMetadata
{
- return _metadataProviders.OfType<IMetadataProvider<T>>()
- .Where(i => CanRefresh(i, item, options, includeDisabled))
- .OrderBy(i =>
- {
- // See if there's a user-defined order
- if (i is ILocalMetadataProvider)
- {
- var index = Array.IndexOf(options.LocalMetadataReaderOrder, i.Name);
-
- if (index != -1)
- {
- return index;
- }
- }
-
- // See if there's a user-defined order
- if (i is IRemoteMetadataProvider)
- {
- var index = Array.IndexOf(options.MetadataFetcherOrder, i.Name);
-
- if (index != -1)
- {
- return index;
- }
- }
+ // Avoid implicitly captured closure
+ var currentOptions = options;
- // Not configured. Just return some high number to put it at the end.
- return 100;
- })
- .ThenBy(GetOrder);
+ return _metadataProviders.OfType<IMetadataProvider<T>>()
+ .Where(i => CanRefresh(i, item, currentOptions, includeDisabled))
+ .OrderBy(i => GetConfiguredOrder(i, options))
+ .ThenBy(GetDefaultOrder);
}
private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(IHasImages item, bool includeDisabled)
@@ -368,6 +286,12 @@ namespace MediaBrowser.Providers.Manager
{
if (!includeDisabled)
{
+ // If locked only allow local providers
+ if (item.IsLocked && !(provider is ILocalMetadataProvider) && !(provider is IForcedProvider))
+ {
+ return false;
+ }
+
if (provider is IRemoteMetadataProvider)
{
if (Array.IndexOf(options.DisabledMetadataFetchers, provider.Name) != -1)
@@ -398,6 +322,12 @@ namespace MediaBrowser.Providers.Manager
{
if (!includeDisabled)
{
+ // If locked only allow local providers
+ if (item.IsLocked && !(provider is ILocalImageProvider))
+ {
+ return false;
+ }
+
if (provider is IRemoteImageProvider)
{
if (Array.IndexOf(options.DisabledImageFetchers, provider.Name) != -1)
@@ -440,12 +370,35 @@ namespace MediaBrowser.Providers.Manager
return hasOrder.Order;
}
- /// <summary>
- /// Gets the order.
- /// </summary>
- /// <param name="provider">The provider.</param>
- /// <returns>System.Int32.</returns>
- private int GetOrder(IMetadataProvider provider)
+ private int GetConfiguredOrder(IMetadataProvider provider, MetadataOptions options)
+ {
+ // See if there's a user-defined order
+ if (provider is ILocalMetadataProvider)
+ {
+ var index = Array.IndexOf(options.LocalMetadataReaderOrder, provider.Name);
+
+ if (index != -1)
+ {
+ return index;
+ }
+ }
+
+ // See if there's a user-defined order
+ if (provider is IRemoteMetadataProvider)
+ {
+ var index = Array.IndexOf(options.MetadataFetcherOrder, provider.Name);
+
+ if (index != -1)
+ {
+ return index;
+ }
+ }
+
+ // Not configured. Just return some high number to put it at the end.
+ return 100;
+ }
+
+ private int GetDefaultOrder(IMetadataProvider provider)
{
var hasOrder = provider as IHasOrder;
@@ -578,6 +531,7 @@ namespace MediaBrowser.Providers.Manager
}
private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
+
/// <summary>
/// Saves the metadata.
/// </summary>
@@ -658,5 +612,14 @@ namespace MediaBrowser.Providers.Manager
return false;
}
}
+
+ //private IEnumerable<TLookupType> GetRemoteSearchResults<TLookupType>(TLookupType searchInfo,
+ // CancellationToken cancellationToken)
+ // where TLookupType : ItemLookupInfo
+ //{
+ // var providers = _metadataProviders.OfType<IRemoteSearchProvider<TLookupType>>();
+
+
+ //}
}
} \ No newline at end of file
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 3a7fcd918d..724a60b97c 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -198,6 +198,7 @@
<Compile Include="TV\TvdbPrescanTask.cs" />
<Compile Include="Users\UserMetadataService.cs" />
<Compile Include="Videos\VideoMetadataService.cs" />
+ <Compile Include="Xbmc\XbmcImageSaver.cs" />
<Compile Include="Years\YearMetadataService.cs" />
</ItemGroup>
<ItemGroup>
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index 7ac48655a9..161532fd31 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -31,7 +31,8 @@ namespace MediaBrowser.Providers.MediaInfo
ICustomMetadataProvider<Video>,
ICustomMetadataProvider<Audio>,
IHasChangeMonitor,
- IHasOrder
+ IHasOrder,
+ IForcedProvider
{
private readonly ILogger _logger;
private readonly IIsoManager _isoManager;
diff --git a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
index f439f4bc5c..5691190dc5 100644
--- a/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
+++ b/MediaBrowser.Providers/People/MovieDbPersonProvider.cs
@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
+using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
@@ -21,9 +22,9 @@ namespace MediaBrowser.Providers.People
public class MovieDbPersonProvider : IRemoteMetadataProvider<Person, PersonLookupInfo>
{
const string DataFileName = "info.json";
-
+
internal static MovieDbPersonProvider Current { get; private set; }
-
+
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
@@ -41,6 +42,73 @@ namespace MediaBrowser.Providers.People
get { return "TheMovieDb"; }
}
+ public async Task<IEnumerable<SearchResult<PersonLookupInfo>>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken)
+ {
+ var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb);
+
+ var tmdbSettings = await MovieDbProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
+
+ var tmdbImageUrl = tmdbSettings.images.base_url + "original";
+
+ if (!string.IsNullOrEmpty(tmdbId))
+ {
+ await EnsurePersonInfo(tmdbId, cancellationToken).ConfigureAwait(false);
+
+ var dataFilePath = GetPersonDataFilePath(_configurationManager.ApplicationPaths, tmdbId);
+ var info = _jsonSerializer.DeserializeFromFile<PersonResult>(dataFilePath);
+
+ var images = (info.images ?? new Images()).profiles ?? new List<Profile>();
+
+ var result = new SearchResult<PersonLookupInfo>
+ {
+ Item = new PersonLookupInfo
+ {
+ Name = info.name
+ },
+
+ ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path)
+ };
+
+ result.Item.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
+ result.Item.SetProviderId(MetadataProviders.Imdb, info.imdb_id.ToString(_usCulture));
+
+ return new[] { result };
+ }
+
+ var url = string.Format(@"http://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(searchInfo.Name), MovieDbProvider.ApiKey);
+
+ using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
+ {
+ Url = url,
+ CancellationToken = cancellationToken,
+ AcceptHeader = MovieDbProvider.AcceptHeader
+
+ }).ConfigureAwait(false))
+ {
+ var result = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json) ??
+ new PersonSearchResults();
+
+ return result.Results.Select(i => GetSearchResult(i, tmdbImageUrl));
+ }
+ }
+
+ private SearchResult<PersonLookupInfo> GetSearchResult(PersonSearchResult i, string baseImageUrl)
+ {
+ var result = new SearchResult<PersonLookupInfo>
+ {
+ Item = new PersonLookupInfo
+ {
+ Name = i.Name
+ },
+
+ ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : (baseImageUrl + i.Profile_Path)
+ };
+
+ result.Item.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture));
+
+ return result;
+ }
+
public async Task<MetadataResult<Person>> GetMetadata(PersonLookupInfo id, CancellationToken cancellationToken)
{
var tmdbId = id.GetProviderId(MetadataProviders.Tmdb);
@@ -48,7 +116,7 @@ namespace MediaBrowser.Providers.People
// We don't already have an Id, need to fetch it
if (string.IsNullOrEmpty(tmdbId))
{
- tmdbId = await GetTmdbId(id.Name, cancellationToken).ConfigureAwait(false);
+ tmdbId = await GetTmdbId(id, cancellationToken).ConfigureAwait(false);
}
var result = new MetadataResult<Person>();
@@ -100,26 +168,14 @@ namespace MediaBrowser.Providers.People
/// <summary>
/// Gets the TMDB id.
/// </summary>
- /// <param name="name">The name.</param>
+ /// <param name="info">The information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.String}.</returns>
- private async Task<string> GetTmdbId(string name, CancellationToken cancellationToken)
+ private async Task<string> GetTmdbId(PersonLookupInfo info, CancellationToken cancellationToken)
{
- string url = string.Format(@"http://api.themoviedb.org/3/search/person?api_key={1}&query={0}", WebUtility.UrlEncode(name), MovieDbProvider.ApiKey);
- PersonSearchResults searchResult = null;
-
- using (var json = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions
- {
- Url = url,
- CancellationToken = cancellationToken,
- AcceptHeader = MovieDbProvider.AcceptHeader
-
- }).ConfigureAwait(false))
- {
- searchResult = _jsonSerializer.DeserializeFromStream<PersonSearchResults>(json);
- }
+ var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
- return searchResult != null && searchResult.Total_Results > 0 ? searchResult.Results[0].Id.ToString(_usCulture) : null;
+ return results.Select(i => i.Item.GetProviderId(MetadataProviders.Tmdb)).FirstOrDefault();
}
internal async Task EnsurePersonInfo(string id, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
index 6a3d7d8372..eed91dfaa1 100644
--- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
+++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs
@@ -22,6 +22,8 @@ namespace MediaBrowser.Providers.Savers
"Added",
"AspectRatio",
+ "AudioDbAlbumId",
+ "AudioDbArtistId",
"AwardSummary",
"BirthDate",
"Budget",
@@ -73,6 +75,7 @@ namespace MediaBrowser.Providers.Savers
"TVcomId",
"TvDbId",
"Type",
+ "TVRageId",
"VoteCount",
"Website",
"Zap2ItId"
@@ -477,7 +480,7 @@ namespace MediaBrowser.Providers.Savers
if (!string.IsNullOrEmpty(externalId))
{
- builder.Append("<TvRageId>" + SecurityElement.Escape(externalId) + "</TvRageId>");
+ builder.Append("<TVRageId>" + SecurityElement.Escape(externalId) + "</TVRageId>");
}
var hasTagline = item as IHasTaglines;
diff --git a/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs b/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs
new file mode 100644
index 0000000000..5a4408f1b9
--- /dev/null
+++ b/MediaBrowser.Providers/Xbmc/XbmcImageSaver.cs
@@ -0,0 +1,272 @@
+using MediaBrowser.Controller.Drawing;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace MediaBrowser.Providers.Xbmc
+{
+ public class XbmcImageSaver : IImageFileSaver
+ {
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ public IEnumerable<string> GetSavePaths(IHasImages item, ImageType type, ImageFormat format, int index)
+ {
+ var season = item as Season;
+
+ if (!SupportsItem(item, type, season))
+ {
+ return new string[] { };
+ }
+
+ var extension = "." + format.ToString().ToLower();
+
+ // Backdrop paths
+ if (type == ImageType.Backdrop)
+ {
+ if (index == 0)
+ {
+ if (item.IsInMixedFolder)
+ {
+ return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart", extension) };
+ }
+
+ if (season != null && season.IndexNumber.HasValue)
+ {
+ var seriesFolder = season.SeriesPath;
+
+ var seasonMarker = season.IndexNumber.Value == 0
+ ? "-specials"
+ : season.IndexNumber.Value.ToString("00", _usCulture);
+
+ var imageFilename = "season" + seasonMarker + "-fanart" + extension;
+
+ return new[] { Path.Combine(seriesFolder, imageFilename) };
+ }
+
+ return new[]
+ {
+ Path.Combine(item.ContainingFolderPath, "fanart" + extension)
+ };
+ }
+
+ if (item.IsInMixedFolder)
+ {
+ return new[] { GetSavePathForItemInMixedFolder(item, type, "fanart" + index.ToString(_usCulture), extension) };
+ }
+
+ var extraFanartFilename = GetBackdropSaveFilename(item.GetImages(ImageType.Backdrop), "fanart", "fanart", index);
+
+ return new[]
+ {
+ Path.Combine(item.ContainingFolderPath, "extrafanart", extraFanartFilename + extension),
+ Path.Combine(item.ContainingFolderPath, "extrathumbs", "thumb" + index.ToString(_usCulture) + extension)
+ };
+ }
+
+ if (type == ImageType.Primary)
+ {
+ if (season != null && season.IndexNumber.HasValue)
+ {
+ var seriesFolder = season.SeriesPath;
+
+ var seasonMarker = season.IndexNumber.Value == 0
+ ? "-specials"
+ : season.IndexNumber.Value.ToString("00", _usCulture);
+
+ var imageFilename = "season" + seasonMarker + "-poster" + extension;
+
+ return new[] { Path.Combine(seriesFolder, imageFilename) };
+ }
+
+ if (item is Episode)
+ {
+ var seasonFolder = Path.GetDirectoryName(item.Path);
+
+ var imageFilename = Path.GetFileNameWithoutExtension(item.Path) + "-thumb" + extension;
+
+ return new[] { Path.Combine(seasonFolder, imageFilename) };
+ }
+
+ if (item.IsInMixedFolder || item is MusicVideo)
+ {
+ return new[] { GetSavePathForItemInMixedFolder(item, type, string.Empty, extension) };
+ }
+
+ if (item is MusicAlbum || item is MusicArtist)
+ {
+ return new[] { Path.Combine(item.ContainingFolderPath, "folder" + extension) };
+ }
+
+ return new[] { Path.Combine(item.ContainingFolderPath, "poster" + extension) };
+ }
+
+ if (type == ImageType.Banner)
+ {
+ if (season != null && season.IndexNumber.HasValue)
+ {
+ var seriesFolder = season.SeriesPath;
+
+ var seasonMarker = season.IndexNumber.Value == 0
+ ? "-specials"
+ : season.IndexNumber.Value.ToString("00", _usCulture);
+
+ var imageFilename = "season" + seasonMarker + "-banner" + extension;
+
+ return new[] { Path.Combine(seriesFolder, imageFilename) };
+ }
+ }
+
+ if (type == ImageType.Thumb)
+ {
+ if (season != null && season.IndexNumber.HasValue)
+ {
+ var seriesFolder = season.SeriesPath;
+
+ var seasonMarker = season.IndexNumber.Value == 0
+ ? "-specials"
+ : season.IndexNumber.Value.ToString("00", _usCulture);
+
+ var imageFilename = "season" + seasonMarker + "-landscape" + extension;
+
+ return new[] { Path.Combine(seriesFolder, imageFilename) };
+ }
+
+ if (item.IsInMixedFolder)
+ {
+ return new[] { GetSavePathForItemInMixedFolder(item, type, "landscape", extension) };
+ }
+
+ return new[] { Path.Combine(item.ContainingFolderPath, "landscape" + extension) };
+ }
+
+ return GetStandardSavePaths(item, type, index, extension);
+ }
+
+ private IEnumerable<string> GetStandardSavePaths(IHasImages item, ImageType type, int imageIndex, string extension)
+ {
+ string filename;
+
+ switch (type)
+ {
+ case ImageType.Art:
+ filename = "clearart";
+ break;
+ case ImageType.BoxRear:
+ filename = "back";
+ break;
+ case ImageType.Disc:
+ filename = item is MusicAlbum ? "cdart" : "disc";
+ break;
+ case ImageType.Screenshot:
+ filename = GetBackdropSaveFilename(item.GetImages(type), "screenshot", "screenshot", imageIndex);
+ break;
+ default:
+ filename = type.ToString().ToLower();
+ break;
+ }
+
+ string path = null;
+
+ if (item.IsInMixedFolder)
+ {
+ path = GetSavePathForItemInMixedFolder(item, type, filename, extension);
+ }
+
+ if (string.IsNullOrEmpty(path))
+ {
+ path = Path.Combine(item.ContainingFolderPath, filename + extension);
+ }
+
+ if (string.IsNullOrEmpty(path))
+ {
+ return new string[] { };
+ }
+
+ return new[] { path };
+ }
+
+
+ private string GetSavePathForItemInMixedFolder(IHasImages item, ImageType type, string imageFilename, string extension)
+ {
+ if (type == ImageType.Primary)
+ {
+ imageFilename = "poster";
+ }
+ var folder = Path.GetDirectoryName(item.Path);
+
+ return Path.Combine(folder, Path.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename + extension);
+ }
+
+ private bool SupportsItem(IHasImages item, ImageType type, Season season)
+ {
+ if (item.IsOwnedItem || item is Audio || item is User)
+ {
+ return false;
+ }
+
+ if (type != ImageType.Primary && item is Episode)
+ {
+ return false;
+ }
+
+ if (!item.SupportsLocalMetadata)
+ {
+ return false;
+ }
+
+ var locationType = item.LocationType;
+ if (locationType == LocationType.Remote || locationType == LocationType.Virtual)
+ {
+ var allowSaving = false;
+
+ // If season is virtual under a physical series, save locally if using compatible convention
+ if (season != null)
+ {
+ var series = season.Series;
+
+ if (series != null && series.SupportsLocalMetadata)
+ {
+ allowSaving = true;
+ }
+ }
+
+ if (!allowSaving)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private string GetBackdropSaveFilename(IEnumerable<ItemImageInfo> images, string zeroIndexFilename, string numberedIndexPrefix, int? index)
+ {
+ if (index.HasValue && index.Value == 0)
+ {
+ return zeroIndexFilename;
+ }
+
+ var filenames = images.Select(i => Path.GetFileNameWithoutExtension(i.Path)).ToList();
+
+ var current = 1;
+ while (filenames.Contains(numberedIndexPrefix + current.ToString(_usCulture), StringComparer.OrdinalIgnoreCase))
+ {
+ current++;
+ }
+
+ return numberedIndexPrefix + current.ToString(_usCulture);
+ }
+
+ public string Name
+ {
+ get { return "MB3/Plex/Xbmc Images"; }
+ }
+ }
+}