Merge pull request #756 from thogil/anime_series_offset

Support anime series ordering within core providers
This commit is contained in:
Luke 2014-03-27 19:03:05 -04:00
commit 5a7a67404e
12 changed files with 141 additions and 19 deletions

View File

@ -187,6 +187,7 @@
<Compile Include="Providers\MetadataRefreshOptions.cs" /> <Compile Include="Providers\MetadataRefreshOptions.cs" />
<Compile Include="Providers\NameParser.cs" /> <Compile Include="Providers\NameParser.cs" />
<Compile Include="Providers\MetadataStatus.cs" /> <Compile Include="Providers\MetadataStatus.cs" />
<Compile Include="Providers\ISeriesOrderManager.cs" />
<Compile Include="Session\ISessionManager.cs" /> <Compile Include="Session\ISessionManager.cs" />
<Compile Include="Drawing\ImageExtensions.cs" /> <Compile Include="Drawing\ImageExtensions.cs" />
<Compile Include="Entities\AggregateFolder.cs" /> <Compile Include="Entities\AggregateFolder.cs" />

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Common;
namespace MediaBrowser.Controller.Providers
{
public interface ISeriesOrderProvider
{
string OrderType { get; }
Task<int?> FindSeriesIndex(string seriesName);
}
public static class SeriesOrderTypes
{
public const string Anime = "Anime";
}
public interface ISeriesOrderManager
{
Task<int?> FindSeriesIndex(string orderType, string seriesName);
void AddParts(IEnumerable<ISeriesOrderProvider> orderProviders);
}
}

View File

@ -0,0 +1,36 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Common;
using MediaBrowser.Controller.Providers;
namespace MediaBrowser.Providers.Manager
{
public class SeriesOrderManager : ISeriesOrderManager
{
private Dictionary<string, ISeriesOrderProvider[]> _providers;
public void AddParts(IEnumerable<ISeriesOrderProvider> orderProviders)
{
_providers = orderProviders
.GroupBy(p => p.OrderType)
.ToDictionary(g => g.Key, g => g.ToArray());
}
public async Task<int?> FindSeriesIndex(string orderType, string seriesName)
{
ISeriesOrderProvider[] providers;
if (!_providers.TryGetValue(orderType, out providers))
return null;
foreach (ISeriesOrderProvider provider in providers)
{
int? index = await provider.FindSeriesIndex(seriesName);
if (index != null)
return index;
}
return null;
}
}
}

View File

@ -103,6 +103,7 @@
<Compile Include="Games\GameXmlParser.cs" /> <Compile Include="Games\GameXmlParser.cs" />
<Compile Include="Games\GameXmlProvider.cs" /> <Compile Include="Games\GameXmlProvider.cs" />
<Compile Include="Games\GameSystemXmlProvider.cs" /> <Compile Include="Games\GameSystemXmlProvider.cs" />
<Compile Include="Manager\SeriesOrderManager.cs" />
<Compile Include="MediaInfo\FFProbeAudioInfo.cs" /> <Compile Include="MediaInfo\FFProbeAudioInfo.cs" />
<Compile Include="MediaInfo\FFProbeHelpers.cs" /> <Compile Include="MediaInfo\FFProbeHelpers.cs" />
<Compile Include="MediaInfo\FFProbeProvider.cs" /> <Compile Include="MediaInfo\FFProbeProvider.cs" />

View File

@ -77,7 +77,8 @@ namespace MediaBrowser.Providers.TV
try try
{ {
AddImages(list, season.IndexNumber.Value, xmlPath, cancellationToken); int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value);
AddImages(list, seasonNumber, xmlPath, cancellationToken);
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@ -115,6 +116,15 @@ namespace MediaBrowser.Providers.TV
.ThenByDescending(i => i.VoteCount ?? 0); .ThenByDescending(i => i.VoteCount ?? 0);
} }
private int AdjustForSeriesOffset(Series series, int seasonNumber)
{
var offset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds);
if (offset != null)
return (int)(seasonNumber + offset);
return seasonNumber;
}
private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string xmlPath, CancellationToken cancellationToken) private void AddImages(List<RemoteImageInfo> list, int seasonNumber, string xmlPath, CancellationToken cancellationToken)
{ {
using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8)) using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))

View File

@ -62,8 +62,9 @@ namespace MediaBrowser.Providers.TV
{ {
// Process images // Process images
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId); var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesId);
var indexOffset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds) ?? 0;
var files = TvdbEpisodeProvider.Current.GetEpisodeXmlFiles(episode.ParentIndexNumber, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath); var files = TvdbEpisodeProvider.Current.GetEpisodeXmlFiles(episode.ParentIndexNumber + indexOffset, episode.IndexNumber, episode.IndexNumberEnd, seriesDataPath);
var result = files.Select(i => GetImageInfo(i, cancellationToken)) var result = files.Select(i => GetImageInfo(i, cancellationToken))
.Where(i => i != null); .Where(i => i != null);

View File

@ -52,7 +52,7 @@ namespace MediaBrowser.Providers.TV
try try
{ {
var item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken); var item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
if (item != null) if (item != null)
{ {
@ -96,7 +96,7 @@ namespace MediaBrowser.Providers.TV
try try
{ {
result.Item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken); result.Item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
result.HasMetadata = result.Item != null; result.HasMetadata = result.Item != null;
} }
catch (FileNotFoundException) catch (FileNotFoundException)
@ -213,7 +213,7 @@ namespace MediaBrowser.Providers.TV
/// <param name="seriesDataPath">The series data path.</param> /// <param name="seriesDataPath">The series data path.</param>
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{System.Boolean}.</returns> /// <returns>Task{System.Boolean}.</returns>
private Episode FetchEpisodeData(EpisodeInfo id, string seriesDataPath, CancellationToken cancellationToken) private Episode FetchEpisodeData(EpisodeInfo id, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
{ {
if (id.IndexNumber == null) if (id.IndexNumber == null)
{ {
@ -221,7 +221,8 @@ namespace MediaBrowser.Providers.TV
} }
var episodeNumber = id.IndexNumber.Value; var episodeNumber = id.IndexNumber.Value;
var seasonNumber = id.ParentIndexNumber; var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(seriesProviderIds) ?? 0;
var seasonNumber = id.ParentIndexNumber + seasonOffset;
if (seasonNumber == null) if (seasonNumber == null)
{ {

View File

@ -22,8 +22,9 @@ namespace MediaBrowser.Providers.TV
{ {
public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor
{ {
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
@ -77,7 +78,8 @@ namespace MediaBrowser.Providers.TV
try try
{ {
return GetImages(path, item.GetPreferredMetadataLanguage(), season.IndexNumber.Value, cancellationToken); int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value);
return GetImages(path, item.GetPreferredMetadataLanguage(), seasonNumber, cancellationToken);
} }
catch (FileNotFoundException) catch (FileNotFoundException)
{ {
@ -88,7 +90,16 @@ namespace MediaBrowser.Providers.TV
return new RemoteImageInfo[] { }; return new RemoteImageInfo[] { };
} }
private IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, int seasonNumber, CancellationToken cancellationToken) private int AdjustForSeriesOffset(Series series, int seasonNumber)
{
var offset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds);
if (offset != null)
return (int) (seasonNumber + offset);
return seasonNumber;
}
internal static IEnumerable<RemoteImageInfo> GetImages(string xmlPath, string preferredLanguage, int seasonNumber, CancellationToken cancellationToken)
{ {
var settings = new XmlReaderSettings var settings = new XmlReaderSettings
{ {
@ -159,7 +170,7 @@ namespace MediaBrowser.Providers.TV
.ToList(); .ToList();
} }
private void AddImage(XmlReader reader, List<RemoteImageInfo> images, int seasonNumber) private static void AddImage(XmlReader reader, List<RemoteImageInfo> images, int seasonNumber)
{ {
reader.MoveToContent(); reader.MoveToContent();
@ -186,7 +197,7 @@ namespace MediaBrowser.Providers.TV
double rval; double rval;
if (double.TryParse(val, NumberStyles.Any, _usCulture, out rval)) if (double.TryParse(val, NumberStyles.Any, UsCulture, out rval))
{ {
rating = rval; rating = rval;
} }
@ -200,7 +211,7 @@ namespace MediaBrowser.Providers.TV
int rval; int rval;
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval)) if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
{ {
voteCount = rval; voteCount = rval;
} }
@ -237,12 +248,12 @@ namespace MediaBrowser.Providers.TV
{ {
int rval; int rval;
if (int.TryParse(resolutionParts[0], NumberStyles.Integer, _usCulture, out rval)) if (int.TryParse(resolutionParts[0], NumberStyles.Integer, UsCulture, out rval))
{ {
width = rval; width = rval;
} }
if (int.TryParse(resolutionParts[1], NumberStyles.Integer, _usCulture, out rval)) if (int.TryParse(resolutionParts[1], NumberStyles.Integer, UsCulture, out rval))
{ {
height = rval; height = rval;
} }
@ -285,7 +296,7 @@ namespace MediaBrowser.Providers.TV
CommunityRating = rating, CommunityRating = rating,
VoteCount = voteCount, VoteCount = voteCount,
Url = TVUtils.BannerUrl + url, Url = TVUtils.BannerUrl + url,
ProviderName = Name, ProviderName = ProviderName,
Language = language, Language = language,
Width = width, Width = width,
Height = height Height = height

View File

@ -77,6 +77,10 @@ namespace MediaBrowser.Providers.TV
try try
{ {
var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds);
if (seriesOffset != null)
return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, cancellationToken);
return GetImages(path, language, cancellationToken); return GetImages(path, language, cancellationToken);
} }
catch (FileNotFoundException) catch (FileNotFoundException)

View File

@ -25,6 +25,8 @@ namespace MediaBrowser.Providers.TV
{ {
public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder public class TvdbSeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo>, IHasOrder
{ {
internal const string TvdbSeriesOffset = "TvdbSeriesOffset";
internal readonly SemaphoreSlim TvDbResourcePool = new SemaphoreSlim(2, 2); internal readonly SemaphoreSlim TvDbResourcePool = new SemaphoreSlim(2, 2);
internal static TvdbSeriesProvider Current { get; private set; } internal static TvdbSeriesProvider Current { get; private set; }
private readonly IZipClient _zipClient; private readonly IZipClient _zipClient;
@ -33,14 +35,16 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ISeriesOrderManager _seriesOrder;
public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger) public TvdbSeriesProvider(IZipClient zipClient, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config, ILogger logger, ISeriesOrderManager seriesOrder)
{ {
_zipClient = zipClient; _zipClient = zipClient;
_httpClient = httpClient; _httpClient = httpClient;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_config = config; _config = config;
_logger = logger; _logger = logger;
_seriesOrder = seriesOrder;
Current = this; Current = this;
} }
@ -92,11 +96,35 @@ namespace MediaBrowser.Providers.TV
result.HasMetadata = true; result.HasMetadata = true;
FetchSeriesData(result.Item, seriesId, cancellationToken); FetchSeriesData(result.Item, seriesId, cancellationToken);
await FindAnimeSeriesIndex(result.Item, itemId).ConfigureAwait(false);
} }
return result; return result;
} }
private async Task FindAnimeSeriesIndex(Series series, SeriesInfo info)
{
var index = await _seriesOrder.FindSeriesIndex(SeriesOrderTypes.Anime, series.Name);
if (index == null)
return;
var offset = info.AnimeSeriesIndex - index;
series.SetProviderId(TvdbSeriesOffset, offset.ToString());
}
internal static int? GetSeriesOffset(Dictionary<string, string> seriesProviderIds)
{
string offsetString;
if (!seriesProviderIds.TryGetValue(TvdbSeriesOffset, out offsetString))
return null;
int offset;
if (int.TryParse(offsetString, out offset))
return offset;
return null;
}
/// <summary> /// <summary>
/// Fetches the series data. /// Fetches the series data.
/// </summary> /// </summary>

View File

@ -157,6 +157,7 @@ namespace MediaBrowser.ServerApplication
private IHttpServer HttpServer { get; set; } private IHttpServer HttpServer { get; set; }
private IDtoService DtoService { get; set; } private IDtoService DtoService { get; set; }
private IImageProcessor ImageProcessor { get; set; } private IImageProcessor ImageProcessor { get; set; }
private ISeriesOrderManager SeriesOrderManager { get; set; }
/// <summary> /// <summary>
/// Gets or sets the media encoder. /// Gets or sets the media encoder.
@ -453,6 +454,9 @@ namespace MediaBrowser.ServerApplication
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager); ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager);
RegisterSingleInstance(ProviderManager); RegisterSingleInstance(ProviderManager);
SeriesOrderManager = new SeriesOrderManager();
RegisterSingleInstance(SeriesOrderManager);
RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager)); RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LogManager, LibraryManager, UserManager));
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager); SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager);
@ -680,6 +684,8 @@ namespace MediaBrowser.ServerApplication
GetExports<IImageSaver>(), GetExports<IImageSaver>(),
GetExports<IExternalId>()); GetExports<IExternalId>());
SeriesOrderManager.AddParts(GetExports<ISeriesOrderProvider>());
ImageProcessor.AddParts(GetExports<IImageEnhancer>()); ImageProcessor.AddParts(GetExports<IImageEnhancer>());
LiveTvManager.AddParts(GetExports<ILiveTvService>()); LiveTvManager.AddParts(GetExports<ILiveTvService>());

View File

@ -251,7 +251,4 @@ Global
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal EndGlobal