diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 6a7557e3a..6d09fe163 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -194,6 +194,7 @@ + diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 94b19498a..242a16ee9 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -54,11 +54,13 @@ namespace MediaBrowser.Controller.Providers /// /// The image providers. /// The metadata services. + /// The identity providers. + /// The identity converters. /// The metadata providers. /// The savers. /// The image savers. /// The external ids. - void AddParts(IEnumerable imageProviders, IEnumerable metadataServices, IEnumerable metadataProviders, + void AddParts(IEnumerable imageProviders, IEnumerable metadataServices, IEnumerable identityProviders, IEnumerable identityConverters, IEnumerable metadataProviders, IEnumerable savers, IEnumerable imageSavers, IEnumerable externalIds); 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 + where TIdentity : IItemIdentity + { + IEnumerable Identities { get; } + + Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken); + } + + public interface IItemIdentityProvider : IHasOrder { } + + public interface IItemIdentityProvider : IItemIdentityProvider + where TLookupInfo : ItemLookupInfo + where TIdentity : IItemIdentity + { + Task FindIdentity(TLookupInfo info); + } + + public interface IItemIdentityConverter : IHasOrder { } + + public interface IItemIdentityConverter : IItemIdentityConverter + where TIdentity : IItemIdentity + { + Task Convert(TIdentity identity); + + string SourceType { get; } + + string ResultType { get; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Providers/Manager/ItemIdentifier.cs b/MediaBrowser.Providers/Manager/ItemIdentifier.cs new file mode 100644 index 000000000..0bf983b69 --- /dev/null +++ b/MediaBrowser.Providers/Manager/ItemIdentifier.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Providers; + +namespace MediaBrowser.Providers.Manager +{ + public class ItemIdentifier + where TLookupInfo : ItemLookupInfo + where TIdentity : IItemIdentity + { + public async Task> FindIdentities(TLookupInfo item, ProviderManager providerManager, CancellationToken cancellationToken) + { + var providers = providerManager.GetItemIdentityProviders(); + var converters = providerManager.GetItemIdentityConverters(); + + var identities = new List(); + + foreach (var provider in providers) + { + var result = new IdentityPair + { + Identity = await provider.FindIdentity(item), + Order = provider.Order + }; + + identities.Add(result); + } + + var convertersAvailable = new List>(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 + }; + + identities.Add(result); + convertersAvailable.RemoveAt(i); + changesMade = true; + } + } + } while (changesMade); + + return identities.Select(id => id.Identity); + } + + private class IdentityPair + { + public TIdentity Identity; + public int Order; + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index b2e23682b..c0ef7e144 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -389,7 +389,7 @@ namespace MediaBrowser.Providers.Manager private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, IEnumerable> providers, RefreshResult refreshResult, CancellationToken cancellationToken) { - TIdType id = null; + TIdType id = await CreateInitialLookupInfo(item, cancellationToken).ConfigureAwait(false); var unidentifiedCount = 0; var identifiedCount = 0; @@ -399,11 +399,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); } @@ -448,6 +444,19 @@ namespace MediaBrowser.Providers.Manager } } + private async Task CreateInitialLookupInfo(TItemType item, CancellationToken cancellationToken) + { + var info = item.GetLookupInfo(); + + var hasIdentity = info as IHasIdentities; + 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 414d7f064..4630da83f 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 _savers; private IImageSaver[] _imageSavers; @@ -81,17 +83,22 @@ namespace MediaBrowser.Providers.Manager /// /// The image providers. /// The metadata services. + /// The identity providers. + /// The identity converters. /// The metadata providers. /// The metadata savers. /// The image savers. /// The external ids. - public void AddParts(IEnumerable imageProviders, IEnumerable metadataServices, IEnumerable metadataProviders, IEnumerable metadataSavers, - IEnumerable imageSavers, - IEnumerable externalIds) + public void AddParts(IEnumerable imageProviders, IEnumerable metadataServices, + IEnumerable identityProviders, IEnumerable identityConverters, + IEnumerable metadataProviders, IEnumerable metadataSavers, + IEnumerable imageSavers, IEnumerable 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> GetItemIdentityProviders() + where TLookupInfo : ItemLookupInfo + where TIdentity : IItemIdentity + { + return _identityProviders.OfType>(); + } + + public IEnumerable> GetItemIdentityConverters() + where TIdentity : IItemIdentity + { + return _identityConverters.OfType>(); + } + private IEnumerable GetRemoteImageProviders(IHasImages item, bool includeDisabled) { var options = GetMetadataOptions(item); diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 43402123c..0549da557 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -95,6 +95,7 @@ + diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 9de319851..e6306f934 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -708,10 +708,14 @@ namespace MediaBrowser.ServerApplication GetExports(), GetExports()); - ProviderManager.AddParts(GetExports(), GetExports(), GetExports(), - GetExports(), - GetExports(), - GetExports()); + ProviderManager.AddParts(GetExports(), + GetExports(), + GetExports(), + GetExports(), + GetExports(), + GetExports(), + GetExports(), + GetExports()); SeriesOrderManager.AddParts(GetExports());