diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 38955f728e..9915ac0441 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -188,6 +188,7 @@
+
diff --git a/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs b/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs
new file mode 100644
index 0000000000..a3adab1b90
--- /dev/null
+++ b/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs
@@ -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 FindSeriesIndex(string seriesName);
+ }
+
+ public static class SeriesOrderTypes
+ {
+ public const string Anime = "Anime";
+ }
+
+ public interface ISeriesOrderManager
+ {
+ Task FindSeriesIndex(string orderType, string seriesName);
+ void AddParts(IEnumerable orderProviders);
+ }
+}
diff --git a/MediaBrowser.Providers/Manager/SeriesOrderManager.cs b/MediaBrowser.Providers/Manager/SeriesOrderManager.cs
new file mode 100644
index 0000000000..39175d1f94
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/SeriesOrderManager.cs
@@ -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 _providers;
+
+ public void AddParts(IEnumerable orderProviders)
+ {
+ _providers = orderProviders
+ .GroupBy(p => p.OrderType)
+ .ToDictionary(g => g.Key, g => g.ToArray());
+ }
+
+ public async Task 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index f347e72290..ff39ec70d7 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -103,6 +103,7 @@
+
diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
index 470bd7b3a9..5bc58af915 100644
--- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs
@@ -77,7 +77,8 @@ namespace MediaBrowser.Providers.TV
try
{
- AddImages(list, season.IndexNumber.Value, xmlPath, cancellationToken);
+ int seasonNumber = AdjustForSeriesOffset(series, season.IndexNumber.Value);
+ AddImages(list, seasonNumber, xmlPath, cancellationToken);
}
catch (FileNotFoundException)
{
@@ -115,6 +116,15 @@ namespace MediaBrowser.Providers.TV
.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 list, int seasonNumber, string xmlPath, CancellationToken cancellationToken)
{
using (var streamReader = new StreamReader(xmlPath, Encoding.UTF8))
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
index 36e349f600..ef37784501 100644
--- a/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeImageProvider.cs
@@ -62,8 +62,9 @@ namespace MediaBrowser.Providers.TV
{
// Process images
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))
.Where(i => i != null);
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
index 5f6bdfa042..922c29fe97 100644
--- a/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeProvider.cs
@@ -52,7 +52,7 @@ namespace MediaBrowser.Providers.TV
try
{
- var item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken);
+ var item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
if (item != null)
{
@@ -96,7 +96,7 @@ namespace MediaBrowser.Providers.TV
try
{
- result.Item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken);
+ result.Item = FetchEpisodeData(searchInfo, seriesDataPath, searchInfo.SeriesProviderIds, cancellationToken);
result.HasMetadata = result.Item != null;
}
catch (FileNotFoundException)
@@ -213,7 +213,7 @@ namespace MediaBrowser.Providers.TV
/// The series data path.
/// The cancellation token.
/// Task{System.Boolean}.
- private Episode FetchEpisodeData(EpisodeInfo id, string seriesDataPath, CancellationToken cancellationToken)
+ private Episode FetchEpisodeData(EpisodeInfo id, string seriesDataPath, Dictionary seriesProviderIds, CancellationToken cancellationToken)
{
if (id.IndexNumber == null)
{
@@ -221,7 +221,8 @@ namespace MediaBrowser.Providers.TV
}
var episodeNumber = id.IndexNumber.Value;
- var seasonNumber = id.ParentIndexNumber;
+ var seasonOffset = TvdbSeriesProvider.GetSeriesOffset(seriesProviderIds) ?? 0;
+ var seasonNumber = id.ParentIndexNumber + seasonOffset;
if (seasonNumber == null)
{
diff --git a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
index c0c103b7fb..5a9981c6e6 100644
--- a/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeasonImageProvider.cs
@@ -22,8 +22,9 @@ namespace MediaBrowser.Providers.TV
{
public class TvdbSeasonImageProvider : IRemoteImageProvider, IHasOrder, IHasChangeMonitor
{
+ private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+
private readonly IServerConfigurationManager _config;
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IHttpClient _httpClient;
private readonly IFileSystem _fileSystem;
@@ -77,7 +78,8 @@ namespace MediaBrowser.Providers.TV
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)
{
@@ -88,7 +90,16 @@ namespace MediaBrowser.Providers.TV
return new RemoteImageInfo[] { };
}
- private IEnumerable 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 GetImages(string xmlPath, string preferredLanguage, int seasonNumber, CancellationToken cancellationToken)
{
var settings = new XmlReaderSettings
{
@@ -159,7 +170,7 @@ namespace MediaBrowser.Providers.TV
.ToList();
}
- private void AddImage(XmlReader reader, List images, int seasonNumber)
+ private static void AddImage(XmlReader reader, List images, int seasonNumber)
{
reader.MoveToContent();
@@ -186,7 +197,7 @@ namespace MediaBrowser.Providers.TV
double rval;
- if (double.TryParse(val, NumberStyles.Any, _usCulture, out rval))
+ if (double.TryParse(val, NumberStyles.Any, UsCulture, out rval))
{
rating = rval;
}
@@ -200,7 +211,7 @@ namespace MediaBrowser.Providers.TV
int rval;
- if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
+ if (int.TryParse(val, NumberStyles.Integer, UsCulture, out rval))
{
voteCount = rval;
}
@@ -237,12 +248,12 @@ namespace MediaBrowser.Providers.TV
{
int rval;
- if (int.TryParse(resolutionParts[0], NumberStyles.Integer, _usCulture, out rval))
+ if (int.TryParse(resolutionParts[0], NumberStyles.Integer, UsCulture, out 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;
}
@@ -285,7 +296,7 @@ namespace MediaBrowser.Providers.TV
CommunityRating = rating,
VoteCount = voteCount,
Url = TVUtils.BannerUrl + url,
- ProviderName = Name,
+ ProviderName = ProviderName,
Language = language,
Width = width,
Height = height
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
index 761c774435..d1171f34bf 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs
@@ -77,6 +77,10 @@ namespace MediaBrowser.Providers.TV
try
{
+ var seriesOffset = TvdbSeriesProvider.GetSeriesOffset(series.ProviderIds);
+ if (seriesOffset != null)
+ return TvdbSeasonImageProvider.GetImages(path, language, seriesOffset.Value + 1, cancellationToken);
+
return GetImages(path, language, cancellationToken);
}
catch (FileNotFoundException)
diff --git a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
index 4b78c1a962..a76e101113 100644
--- a/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/TV/TvdbSeriesProvider.cs
@@ -25,6 +25,8 @@ namespace MediaBrowser.Providers.TV
{
public class TvdbSeriesProvider : IRemoteMetadataProvider, IHasOrder
{
+ internal const string TvdbSeriesOffset = "TvdbSeriesOffset";
+
internal readonly SemaphoreSlim TvDbResourcePool = new SemaphoreSlim(2, 2);
internal static TvdbSeriesProvider Current { get; private set; }
private readonly IZipClient _zipClient;
@@ -33,14 +35,16 @@ namespace MediaBrowser.Providers.TV
private readonly IServerConfigurationManager _config;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
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;
_httpClient = httpClient;
_fileSystem = fileSystem;
_config = config;
_logger = logger;
+ _seriesOrder = seriesOrder;
Current = this;
}
@@ -92,11 +96,35 @@ namespace MediaBrowser.Providers.TV
result.HasMetadata = true;
FetchSeriesData(result.Item, seriesId, cancellationToken);
+ await FindAnimeSeriesIndex(result.Item, itemId).ConfigureAwait(false);
}
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 seriesProviderIds)
+ {
+ string offsetString;
+ if (!seriesProviderIds.TryGetValue(TvdbSeriesOffset, out offsetString))
+ return null;
+
+ int offset;
+ if (int.TryParse(offsetString, out offset))
+ return offset;
+
+ return null;
+ }
+
///
/// Fetches the series data.
///
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index dff6242d1a..6083158bcc 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -158,6 +158,7 @@ namespace MediaBrowser.ServerApplication
private IHttpServer HttpServer { get; set; }
private IDtoService DtoService { get; set; }
private IImageProcessor ImageProcessor { get; set; }
+ private ISeriesOrderManager SeriesOrderManager { get; set; }
///
/// Gets or sets the media encoder.
@@ -454,6 +455,9 @@ namespace MediaBrowser.ServerApplication
ProviderManager = new ProviderManager(HttpClient, ServerConfigurationManager, LibraryMonitor, LogManager, FileSystemManager);
RegisterSingleInstance(ProviderManager);
+ SeriesOrderManager = new SeriesOrderManager();
+ RegisterSingleInstance(SeriesOrderManager);
+
RegisterSingleInstance(() => new SearchEngine(LogManager, LibraryManager, UserManager));
SessionManager = new SessionManager(UserDataManager, ServerConfigurationManager, Logger, UserRepository, LibraryManager, UserManager);
@@ -681,6 +685,8 @@ namespace MediaBrowser.ServerApplication
GetExports(),
GetExports());
+ SeriesOrderManager.AddParts(GetExports());
+
ImageProcessor.AddParts(GetExports());
LiveTvManager.AddParts(GetExports());
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 7dc06fb0ce..c2f9dff59c 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -267,7 +267,4 @@ Global
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
- GlobalSection(Performance) = preSolution
- HasPerformanceSessions = true
- EndGlobalSection
EndGlobal