aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs4
-rw-r--r--MediaBrowser.Controller/Entities/IHasMetadata.cs6
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj2
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs11
-rw-r--r--MediaBrowser.Controller/Providers/ItemIdentifier.cs73
-rw-r--r--MediaBrowser.Controller/Providers/ItemIdentities.cs43
-rw-r--r--MediaBrowser.Controller/Providers/ItemLookupInfo.cs76
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs51
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs26
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj1
-rw-r--r--MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs64
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs29
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs5
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeriesProvider.cs26
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs12
-rw-r--r--MediaBrowser.sln4
16 files changed, 381 insertions, 52 deletions
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index b7edbfc60..a2ff1b4fd 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -32,6 +32,7 @@ namespace MediaBrowser.Controller.Entities
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
LockedFields = new List<MetadataFields>();
ImageInfos = new List<ItemImageInfo>();
+ Identities = new List<IItemIdentity>();
}
/// <summary>
@@ -244,6 +245,9 @@ namespace MediaBrowser.Controller.Entities
public bool IsUnidentified { get; set; }
+ [IgnoreDataMember]
+ public List<IItemIdentity> Identities { get; set; }
+
/// <summary>
/// Gets or sets the locked fields.
/// </summary>
diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs
index 91f37135f..4e90fb155 100644
--- a/MediaBrowser.Controller/Entities/IHasMetadata.cs
+++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs
@@ -1,4 +1,5 @@
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
@@ -55,5 +56,10 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value><c>true</c> if this instance is unidentified; otherwise, <c>false</c>.</value>
bool IsUnidentified { get; set; }
+
+ /// <summary>
+ /// Gets the item identities.
+ /// </summary>
+ List<IItemIdentity> Identities { get; set; }
}
}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 7bc82f76d..addcaea8d 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -225,6 +225,8 @@
<Compile Include="Security\IEncryptionManager.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />
+ <Compile Include="Providers\ItemIdentifier.cs" />
+ <Compile Include="Providers\ItemIdentities.cs" />
<Compile Include="Providers\ItemLookupInfo.cs" />
<Compile Include="Providers\MetadataRefreshOptions.cs" />
<Compile Include="Providers\NameParser.cs" />
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 94b19498a..883fa12b4 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -54,11 +54,13 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="imageProviders">The image providers.</param>
/// <param name="metadataServices">The metadata services.</param>
+ /// <param name="identityProviders">The identity providers.</param>
+ /// <param name="identityConverters">The identity converters.</param>
/// <param name="metadataProviders">The metadata providers.</param>
/// <param name="savers">The savers.</param>
/// <param name="imageSavers">The image savers.</param>
/// <param name="externalIds">The external ids.</param>
- void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders,
+ void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters, IEnumerable<IMetadataProvider> metadataProviders,
IEnumerable<IMetadataSaver> savers,
IEnumerable<IImageSaver> imageSavers,
IEnumerable<IExternalId> externalIds);
@@ -136,5 +138,12 @@ namespace MediaBrowser.Controller.Providers
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
+
+ IEnumerable<IItemIdentityProvider<TLookupInfo, TIdentity>> GetItemIdentityProviders<TLookupInfo, TIdentity>()
+ where TLookupInfo : ItemLookupInfo
+ where TIdentity : IItemIdentity;
+
+ IEnumerable<IItemIdentityConverter<TIdentity>> GetItemIdentityConverters<TIdentity>()
+ where TIdentity : IItemIdentity;
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/ItemIdentifier.cs b/MediaBrowser.Controller/Providers/ItemIdentifier.cs
new file mode 100644
index 000000000..13e4f137f
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/ItemIdentifier.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public class ItemIdentifier<TLookupInfo, TIdentity>
+ where TLookupInfo : ItemLookupInfo
+ where TIdentity : IItemIdentity
+ {
+ public async Task<IEnumerable<TIdentity>> FindIdentities(TLookupInfo item, IProviderManager providerManager, CancellationToken cancellationToken)
+ {
+ var providers = providerManager.GetItemIdentityProviders<TLookupInfo, TIdentity>();
+ var converters = providerManager.GetItemIdentityConverters<TIdentity>();
+
+ var identities = new List<IdentityPair>();
+
+ foreach (var provider in providers)
+ {
+ var result = new IdentityPair
+ {
+ Identity = await provider.FindIdentity(item),
+ Order = provider.Order
+ };
+
+ if (!Equals(result.Identity, default(TIdentity)))
+ {
+ identities.Add(result);
+ }
+ }
+
+ var convertersAvailable = new List<IItemIdentityConverter<TIdentity>>(converters);
+ bool changesMade;
+
+ do
+ {
+ changesMade = false;
+
+ for (int i = convertersAvailable.Count - 1; i >= 0; i--)
+ {
+ var converter = convertersAvailable[i];
+ var input = identities.FirstOrDefault(id => id.Identity.Type == converter.SourceType);
+ var existing = identities.Where(id => id.Identity.Type == converter.ResultType);
+
+ if (input != null && !existing.Any(id => id.Order <= converter.Order))
+ {
+ var result = new IdentityPair
+ {
+ Identity = await converter.Convert(input.Identity).ConfigureAwait(false),
+ Order = converter.Order
+ };
+
+ if (!Equals(result.Identity, default(TIdentity)))
+ {
+ identities.Add(result);
+ convertersAvailable.RemoveAt(i);
+ changesMade = true;
+ }
+ }
+ }
+ } while (changesMade);
+
+ return identities.OrderBy(id => id.Order).Select(id => id.Identity);
+ }
+
+ private class IdentityPair
+ {
+ public TIdentity Identity;
+ public int Order;
+ }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/ItemIdentities.cs b/MediaBrowser.Controller/Providers/ItemIdentities.cs
new file mode 100644
index 000000000..93d468af0
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/ItemIdentities.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Providers
+{
+ public interface IItemIdentity
+ {
+ string Type { get; }
+ }
+
+ public interface IHasIdentities<out TIdentity>
+ where TIdentity : IItemIdentity
+ {
+ IEnumerable<TIdentity> Identities { get; }
+
+ Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken);
+ }
+
+ public interface IItemIdentityProvider : IHasOrder { }
+
+ public interface IItemIdentityProvider<in TLookupInfo, TIdentity> : IItemIdentityProvider
+ where TLookupInfo : ItemLookupInfo
+ where TIdentity : IItemIdentity
+ {
+ Task<TIdentity> FindIdentity(TLookupInfo info);
+ }
+
+ public interface IItemIdentityConverter : IHasOrder { }
+
+ public interface IItemIdentityConverter<TIdentity> : IItemIdentityConverter
+ where TIdentity : IItemIdentity
+ {
+ Task<TIdentity> Convert(TIdentity identity);
+
+ string SourceType { get; }
+
+ string ResultType { get; }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
index 65ee94556..20bc572b4 100644
--- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
+++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs
@@ -1,4 +1,7 @@
-using MediaBrowser.Model.Entities;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
@@ -96,8 +99,10 @@ namespace MediaBrowser.Controller.Providers
public string Path { get; set; }
}
- public class EpisodeInfo : ItemLookupInfo
+ public class EpisodeInfo : ItemLookupInfo, IHasIdentities<EpisodeIdentity>
{
+ private List<EpisodeIdentity> _identities = new List<EpisodeIdentity>();
+
public Dictionary<string, string> SeriesProviderIds { get; set; }
public int? IndexNumberEnd { get; set; }
@@ -107,6 +112,27 @@ namespace MediaBrowser.Controller.Providers
{
SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
+
+ public IEnumerable<EpisodeIdentity> Identities
+ {
+ get { return _identities; }
+ }
+
+ public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken)
+ {
+ var identifier = new ItemIdentifier<EpisodeInfo, EpisodeIdentity>();
+ _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList();
+ }
+ }
+
+ public class EpisodeIdentity : IItemIdentity
+ {
+ public string Type { get; set; }
+
+ public string SeriesId { get; set; }
+ public int? SeasonIndex { get; set; }
+ public int IndexNumber { get; set; }
+ public int? IndexNumberEnd { get; set; }
}
public class SongInfo : ItemLookupInfo
@@ -116,9 +142,29 @@ namespace MediaBrowser.Controller.Providers
public List<string> Artists { get; set; }
}
- public class SeriesInfo : ItemLookupInfo
+ public class SeriesInfo : ItemLookupInfo, IHasIdentities<SeriesIdentity>
{
+ private List<SeriesIdentity> _identities = new List<SeriesIdentity>();
+
public int? AnimeSeriesIndex { get; set; }
+
+ public IEnumerable<SeriesIdentity> Identities
+ {
+ get { return _identities; }
+ }
+
+ public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken)
+ {
+ var identifier = new ItemIdentifier<SeriesInfo, SeriesIdentity>();
+ _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList();
+ }
+ }
+
+ public class SeriesIdentity : IItemIdentity
+ {
+ public string Type { get; set; }
+
+ public string Id { get; set; }
}
public class PersonLookupInfo : ItemLookupInfo
@@ -151,8 +197,10 @@ namespace MediaBrowser.Controller.Providers
public string SeriesName { get; set; }
}
- public class SeasonInfo : ItemLookupInfo
+ public class SeasonInfo : ItemLookupInfo, IHasIdentities<SeasonIdentity>
{
+ private List<SeasonIdentity> _identities = new List<SeasonIdentity>();
+
public Dictionary<string, string> SeriesProviderIds { get; set; }
public int? AnimeSeriesIndex { get; set; }
@@ -160,5 +208,25 @@ namespace MediaBrowser.Controller.Providers
{
SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
+
+ public IEnumerable<SeasonIdentity> Identities
+ {
+ get { return _identities; }
+ }
+
+ public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken)
+ {
+ var identifier = new ItemIdentifier<SeasonInfo, SeasonIdentity>();
+ _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList();
+ }
+ }
+
+ public class SeasonIdentity : IItemIdentity
+ {
+ public string Type { get; set; }
+
+ public string SeriesId { get; set; }
+
+ public int SeasonIndex { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index e40f49acf..717b93524 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -104,6 +104,9 @@ namespace MediaBrowser.Providers.Manager
refreshResult.AddStatus(ProviderRefreshStatus.Failure, ex.Message);
}
+ // Identify item
+ TIdType id = null;
+
// Next run metadata providers
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
{
@@ -120,7 +123,8 @@ namespace MediaBrowser.Providers.Manager
if (providers.Count > 0)
{
- var result = await RefreshWithProviders(itemOfType, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false);
+ id = await CreateInitialLookupInfo(itemOfType, cancellationToken).ConfigureAwait(false);
+ var result = await RefreshWithProviders(itemOfType, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false);
updateType = updateType | result.UpdateType;
refreshResult.AddStatus(result.Status, result.ErrorMessage);
@@ -129,6 +133,13 @@ namespace MediaBrowser.Providers.Manager
}
}
+ if (id == null)
+ {
+ id = await CreateInitialLookupInfo(itemOfType, cancellationToken).ConfigureAwait(false);
+ }
+
+ MergeIdentities(itemOfType, id);
+
// Next run remote image providers, but only if local image providers didn't throw an exception
if (!localImagesFailed && refreshOptions.ImageRefreshMode != ImageRefreshMode.ValidationOnly)
{
@@ -162,6 +173,15 @@ namespace MediaBrowser.Providers.Manager
}
}
+ private void MergeIdentities(TItemType item, TIdType id)
+ {
+ var hasIdentity = id as IHasIdentities<IItemIdentity>;
+ if (hasIdentity != null)
+ {
+ item.Identities = hasIdentity.Identities.ToList();
+ }
+ }
+
/// <summary>
/// Befores the save.
/// </summary>
@@ -259,7 +279,7 @@ namespace MediaBrowser.Providers.Manager
return item is TItemType;
}
- protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, MetadataRefreshOptions options, List<IMetadataProvider> providers, ItemImageProvider imageService, CancellationToken cancellationToken)
+ protected virtual async Task<RefreshResult> RefreshWithProviders(TItemType item, TIdType id, MetadataRefreshOptions options, List<IMetadataProvider> providers, ItemImageProvider imageService, CancellationToken cancellationToken)
{
var refreshResult = new RefreshResult
{
@@ -280,7 +300,7 @@ namespace MediaBrowser.Providers.Manager
// If replacing all metadata, run internet providers first
if (options.ReplaceAllMetadata)
{
- await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false);
+ await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false);
}
var hasLocalMetadata = false;
@@ -333,7 +353,7 @@ namespace MediaBrowser.Providers.Manager
// Local metadata is king - if any is found don't run remote providers
if (!options.ReplaceAllMetadata && (!hasLocalMetadata || options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh))
{
- await ExecuteRemoteProviders(item, temp, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false);
+ await ExecuteRemoteProviders(item, temp, id, providers.OfType<IRemoteMetadataProvider<TItemType, TIdType>>(), refreshResult, cancellationToken).ConfigureAwait(false);
}
if (refreshResult.UpdateType > ItemUpdateType.None)
@@ -374,10 +394,8 @@ namespace MediaBrowser.Providers.Manager
return new TItemType();
}
- private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, IEnumerable<IRemoteMetadataProvider<TItemType, TIdType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken)
+ private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, TIdType id, IEnumerable<IRemoteMetadataProvider<TItemType, TIdType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken)
{
- TIdType id = null;
-
var unidentifiedCount = 0;
var identifiedCount = 0;
@@ -386,11 +404,7 @@ namespace MediaBrowser.Providers.Manager
var providerName = provider.GetType().Name;
Logger.Debug("Running {0} for {1}", providerName, item.Path ?? item.Name);
- if (id == null)
- {
- id = item.GetLookupInfo();
- }
- else
+ if (id != null)
{
MergeNewData(temp, id);
}
@@ -435,6 +449,19 @@ namespace MediaBrowser.Providers.Manager
}
}
+ private async Task<TIdType> CreateInitialLookupInfo(TItemType item, CancellationToken cancellationToken)
+ {
+ var info = item.GetLookupInfo();
+
+ var hasIdentity = info as IHasIdentities<IItemIdentity>;
+ if (hasIdentity != null)
+ {
+ await hasIdentity.FindIdentities(ProviderManager, cancellationToken).ConfigureAwait(false);
+ }
+
+ return info;
+ }
+
private void MergeNewData(TItemType source, TIdType lookupInfo)
{
// Copy new provider id's that may have been obtained
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 864435e40..6f33de67f 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -53,6 +53,8 @@ namespace MediaBrowser.Providers.Manager
private readonly IFileSystem _fileSystem;
private IMetadataService[] _metadataServices = { };
+ private IItemIdentityProvider[] _identityProviders = { };
+ private IItemIdentityConverter[] _identityConverters = { };
private IMetadataProvider[] _metadataProviders = { };
private IEnumerable<IMetadataSaver> _savers;
private IImageSaver[] _imageSavers;
@@ -81,17 +83,22 @@ namespace MediaBrowser.Providers.Manager
/// </summary>
/// <param name="imageProviders">The image providers.</param>
/// <param name="metadataServices">The metadata services.</param>
+ /// <param name="identityProviders">The identity providers.</param>
+ /// <param name="identityConverters">The identity converters.</param>
/// <param name="metadataProviders">The metadata providers.</param>
/// <param name="metadataSavers">The metadata savers.</param>
/// <param name="imageSavers">The image savers.</param>
/// <param name="externalIds">The external ids.</param>
- public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers,
- IEnumerable<IImageSaver> imageSavers,
- IEnumerable<IExternalId> externalIds)
+ public void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices,
+ IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters,
+ IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers,
+ IEnumerable<IImageSaver> imageSavers, IEnumerable<IExternalId> externalIds)
{
ImageProviders = imageProviders.ToArray();
_metadataServices = metadataServices.OrderBy(i => i.Order).ToArray();
+ _identityProviders = identityProviders.ToArray();
+ _identityConverters = identityConverters.ToArray();
_metadataProviders = metadataProviders.ToArray();
_savers = metadataSavers.ToArray();
_imageSavers = imageSavers.ToArray();
@@ -257,6 +264,19 @@ namespace MediaBrowser.Providers.Manager
.ThenBy(GetDefaultOrder);
}
+ public IEnumerable<IItemIdentityProvider<TLookupInfo, TIdentity>> GetItemIdentityProviders<TLookupInfo, TIdentity>()
+ where TLookupInfo : ItemLookupInfo
+ where TIdentity : IItemIdentity
+ {
+ return _identityProviders.OfType<IItemIdentityProvider<TLookupInfo, TIdentity>>();
+ }
+
+ public IEnumerable<IItemIdentityConverter<TIdentity>> GetItemIdentityConverters<TIdentity>()
+ where TIdentity : IItemIdentity
+ {
+ return _identityConverters.OfType<IItemIdentityConverter<TIdentity>>();
+ }
+
private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(IHasImages item, bool includeDisabled)
{
var options = GetMetadataOptions(item);
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 3ad4a608a..3978b36bb 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -205,6 +205,7 @@
<Compile Include="TV\SeriesMetadataService.cs" />
<Compile Include="TV\TvdbEpisodeImageProvider.cs" />
<Compile Include="People\TvdbPersonImageProvider.cs" />
+ <Compile Include="TV\TvdbSeasonIdentityProvider.cs" />
<Compile Include="TV\TvdbSeasonImageProvider.cs" />
<Compile Include="TV\TvdbSeriesImageProvider.cs" />
<Compile Include="TV\SeasonMetadataService.cs" />
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
index ba7455e23..dd9f3af8b 100644
--- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
@@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.TV
/// <summary>
/// Class RemoteEpisodeProvider
/// </summary>
- class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IHasChangeMonitor
+ class TvdbEpisodeProvider : IRemoteMetadataProvider<Episode, EpisodeInfo>, IItemIdentityProvider<EpisodeInfo, EpisodeIdentity>, IHasChangeMonitor
{
internal static TvdbEpisodeProvider Current;
private readonly IFileSystem _fileSystem;
@@ -40,19 +40,18 @@ namespace MediaBrowser.Providers.TV
{
var list = new List<RemoteSearchResult>();
- string seriesTvdbId;
- searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId);
+ var identity = searchInfo.Identities.FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString()) ?? await FindIdentity(searchInfo).ConfigureAwait(false);
- if (!string.IsNullOrEmpty(seriesTvdbId))
+ if (identity != null)
{
- await TvdbSeriesProvider.Current.EnsureSeriesInfo(seriesTvdbId, searchInfo.MetadataLanguage,
+ await TvdbSeriesProvider.Current.EnsureSeriesInfo(identity.SeriesId, searchInfo.MetadataLanguage,
cancellationToken).ConfigureAwait(false);
- var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesTvdbId);
+ var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, identity.SeriesId);
try
{
- var item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
+ var item = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
if (item != null)
{
@@ -83,20 +82,19 @@ namespace MediaBrowser.Providers.TV
get { return "TheTVDB"; }
}
- public Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken)
+ public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken)
{
- string seriesTvdbId;
- searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId);
+ var identity = searchInfo.Identities.FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString()) ?? await FindIdentity(searchInfo).ConfigureAwait(false);
var result = new MetadataResult<Episode>();
- if (!string.IsNullOrEmpty(seriesTvdbId))
+ if (identity != null)
{
- var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesTvdbId);
+ var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, identity.SeriesId);
try
{
- result.Item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
+ result.Item = FetchEpisodeData(searchInfo, identity, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
result.HasMetadata = result.Item != null;
}
catch (FileNotFoundException)
@@ -105,7 +103,7 @@ namespace MediaBrowser.Providers.TV
}
}
- return Task.FromResult(result);
+ return result;
}
public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date)
@@ -211,18 +209,14 @@ namespace MediaBrowser.Providers.TV
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="seriesDataPath">The series data path.</param>
+ /// <param name="seriesProviderIds"></param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns>
- private Episode FetchEpisodeData(EpisodeInfo id, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
+ private Episode FetchEpisodeData(EpisodeInfo id, EpisodeIdentity identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
{
- if (id.IndexNumber == null)
- {
- return null;
- }
-
- var episodeNumber = id.IndexNumber.Value;
+ var episodeNumber = identity.IndexNumber;
var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(seriesProviderIds) ?? 0;
- var seasonNumber = id.ParentIndexNumber + seasonOffset;
+ var seasonNumber = identity.SeasonIndex + seasonOffset;
if (seasonNumber == null)
{
@@ -263,7 +257,7 @@ namespace MediaBrowser.Providers.TV
usingAbsoluteData = true;
}
- var end = id.IndexNumberEnd ?? episodeNumber;
+ var end = identity.IndexNumberEnd ?? episodeNumber;
episodeNumber++;
while (episodeNumber <= end)
@@ -726,5 +720,29 @@ namespace MediaBrowser.Providers.TV
{
throw new NotImplementedException();
}
+
+ public Task<EpisodeIdentity> FindIdentity(EpisodeInfo info)
+ {
+ string seriesTvdbId;
+ info.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId);
+
+ if (string.IsNullOrEmpty(seriesTvdbId) || info.IndexNumber == null)
+ {
+ return Task.FromResult<EpisodeIdentity>(null);
+ }
+
+ var id = new EpisodeIdentity
+ {
+ Type = MetadataProviders.Tvdb.ToString(),
+ SeriesId = seriesTvdbId,
+ SeasonIndex = info.ParentIndexNumber,
+ IndexNumber = info.IndexNumber.Value,
+ IndexNumberEnd = info.IndexNumberEnd
+ };
+
+ return Task.FromResult(id);
+ }
+
+ public int Order { get { return 0; } }
}
}
diff --git a/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs
new file mode 100644
index 000000000..5876c9998
--- /dev/null
+++ b/MediaBrowser.Providers/TV/TvdbSeasonIdentityProvider.cs
@@ -0,0 +1,29 @@
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class TvdbSeasonIdentityProvider : IItemIdentityProvider<SeasonInfo, SeasonIdentity>
+ {
+ public Task<SeasonIdentity> FindIdentity(SeasonInfo info)
+ {
+ string tvdbSeriesId;
+ if (!info.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out tvdbSeriesId) || string.IsNullOrEmpty(tvdbSeriesId) || info.IndexNumber == null)
+ {
+ return Task.FromResult<SeasonIdentity>(null);
+ }
+
+ var result = new SeasonIdentity
+ {
+ Type = MetadataProviders.Tvdb.ToString(),
+ SeriesId = tvdbSeriesId,
+ SeasonIndex = info.IndexNumber.Value
+ };
+
+ return Task.FromResult(result);
+ }
+
+ public int Order { get { return 0; } }
+ }
+} \ No newline at end of file
diff --git a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
index 5a9981c6e..af1edeed0 100644
--- a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
@@ -65,7 +65,8 @@ namespace MediaBrowser.Providers.TV
var season = (Season)item;
var series = season.Series;
- var seriesId = series != null ? series.GetProviderId(MetadataProviders.Tvdb) : null;
+ var identity = season.Identities.OfType<SeasonIdentity>().FirstOrDefault(id => id.Type == MetadataProviders.Tvdb.ToString());
+ var seriesId = identity != null ? identity.SeriesId : null;
if (!string.IsNullOrEmpty(seriesId) && season.IndexNumber.HasValue)
{
@@ -78,7 +79,7 @@ namespace MediaBrowser.Providers.TV
try
{
- int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value);
+ int seasonNumber = AdjustForSeriesOffset(series, identity.SeasonIndex);
return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken);
}
catch (FileNotFoundException)
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
index f9ebaddf8..6ca548829 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
@@ -23,7 +23,7 @@ using System.Xml;
namespace MediaBrowser.Providers.TV
{
- public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
+ public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IItemIdentityProvider<SeriesInfo, SeriesIdentity>, IHasOrder
{
private const string TvdbSeriesOffset = "TvdbSeriesOffset";
private const string TvdbSeriesOffsetFormat = "{0}-{1}";
@@ -72,7 +72,15 @@ namespace MediaBrowser.Providers.TV
if (string.IsNullOrEmpty(seriesId))
{
- seriesId = await FindSeries(itemId.Name, cancellationToken).ConfigureAwait(false);
+ seriesId = itemId.Identities
+ .Where(id => id.Type == MetadataProviders.Tvdb.ToString())
+ .Select(id => id.Id)
+ .FirstOrDefault();
+
+ if (string.IsNullOrEmpty(seriesId))
+ {
+ seriesId = await FindSeries(itemId.Name, cancellationToken).ConfigureAwait(false);
+ }
if (string.IsNullOrEmpty(seriesId))
{
@@ -1121,6 +1129,20 @@ namespace MediaBrowser.Providers.TV
get { return "TheTVDB"; }
}
+ public async Task<SeriesIdentity> FindIdentity(SeriesInfo info)
+ {
+ string tvdbId;
+ if (!info.ProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out tvdbId))
+ tvdbId = await FindSeries(info.Name, CancellationToken.None);
+
+ if (!string.IsNullOrEmpty(tvdbId))
+ {
+ return new SeriesIdentity {Type = MetadataProviders.Tvdb.ToString(), Id = tvdbId};
+ }
+
+ return null;
+ }
+
public int Order
{
get
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 675e67041..1c1595093 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -722,10 +722,14 @@ namespace MediaBrowser.ServerApplication
GetExports<IBaseItemComparer>(),
GetExports<ILibraryPostScanTask>());
- ProviderManager.AddParts(GetExports<IImageProvider>(), GetExports<IMetadataService>(), GetExports<IMetadataProvider>(),
- GetExports<IMetadataSaver>(),
- GetExports<IImageSaver>(),
- GetExports<IExternalId>());
+ ProviderManager.AddParts(GetExports<IImageProvider>(),
+ GetExports<IMetadataService>(),
+ GetExports<IItemIdentityProvider>(),
+ GetExports<IItemIdentityConverter>(),
+ GetExports<IMetadataProvider>(),
+ GetExports<IMetadataSaver>(),
+ GetExports<IImageSaver>(),
+ GetExports<IExternalId>());
SeriesOrderManager.AddParts(GetExports<ISeriesOrderProvider>());
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index f2b7a612c..1b132e07f 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -1,6 +1,8 @@

Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 2012
+# Visual Studio 2013
+VisualStudioVersion = 12.0.21005.1
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}"