diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 6ac1ab84e6..2df8f8e3c5 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -162,6 +162,7 @@
+
diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
new file mode 100644
index 0000000000..294c7e20f8
--- /dev/null
+++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
@@ -0,0 +1,121 @@
+using MediaBrowser.Common.Extensions;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Localization;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class DummySeasonProvider
+ {
+ private readonly IServerConfigurationManager _config;
+ private readonly ILogger _logger;
+ private readonly ILocalizationManager _localization;
+
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+
+ public DummySeasonProvider(IServerConfigurationManager config, ILogger logger, ILocalizationManager localization)
+ {
+ _config = config;
+ _logger = logger;
+ _localization = localization;
+ }
+
+ public async Task Run(Series series, CancellationToken cancellationToken)
+ {
+ var hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
+
+ if (hasNewSeasons)
+ {
+ var directoryService = new DirectoryService();
+
+ //await series.RefreshMetadata(new MetadataRefreshOptions(directoryService), cancellationToken).ConfigureAwait(false);
+
+ //await series.ValidateChildren(new Progress(), cancellationToken, new MetadataRefreshOptions(directoryService))
+ // .ConfigureAwait(false);
+ }
+ }
+
+ private async Task AddDummySeasonFolders(Series series, CancellationToken cancellationToken)
+ {
+ var episodesInSeriesFolder = series.RecursiveChildren
+ .OfType()
+ .Where(i => !i.IsInSeasonFolder)
+ .ToList();
+
+ var hasChanges = false;
+
+ // Loop through the unique season numbers
+ foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1)
+ .Where(i => i >= 0)
+ .Distinct()
+ .ToList())
+ {
+ var hasSeason = series.Children.OfType()
+ .Any(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber);
+
+ if (!hasSeason)
+ {
+ await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
+
+ hasChanges = true;
+ }
+ }
+
+ // Unknown season - create a dummy season to put these under
+ if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue))
+ {
+ var hasSeason = series.Children.OfType()
+ .Any(i => !i.IndexNumber.HasValue);
+
+ if (!hasSeason)
+ {
+ await AddSeason(series, null, cancellationToken).ConfigureAwait(false);
+
+ hasChanges = true;
+ }
+ }
+
+ return hasChanges;
+ }
+
+ ///
+ /// Adds the season.
+ ///
+ /// The series.
+ /// The season number.
+ /// The cancellation token.
+ /// Task{Season}.
+ public async Task AddSeason(Series series,
+ int? seasonNumber,
+ CancellationToken cancellationToken)
+ {
+ var seasonName = seasonNumber == 0 ?
+ _config.Configuration.SeasonZeroDisplayName :
+ (seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(_usCulture)) : _localization.GetLocalizedString("NameSeasonUnknown"));
+
+ _logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name);
+
+ var season = new Season
+ {
+ Name = seasonName,
+ IndexNumber = seasonNumber,
+ Parent = series,
+ DisplayMediaType = typeof(Season).Name,
+ Id = (series.Id + (seasonNumber ?? -1).ToString(_usCulture) + seasonName).GetMBId(typeof(Season))
+ };
+
+ await series.AddChild(season, cancellationToken).ConfigureAwait(false);
+
+ await season.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken).ConfigureAwait(false);
+
+ return season;
+ }
+ }
+}
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 0b52956de5..707fa6e216 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.TV
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localization;
- private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
+ private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization)
{
@@ -78,11 +78,11 @@ namespace MediaBrowser.Providers.TV
{
int seasonNumber;
- if (int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out seasonNumber))
+ if (int.TryParse(parts[1], NumberStyles.Integer, _usCulture, out seasonNumber))
{
int episodeNumber;
- if (int.TryParse(parts[2], NumberStyles.Integer, UsCulture, out episodeNumber))
+ if (int.TryParse(parts[2], NumberStyles.Integer, _usCulture, out episodeNumber))
{
return new Tuple(seasonNumber, episodeNumber);
}
@@ -103,12 +103,6 @@ namespace MediaBrowser.Providers.TV
.ConfigureAwait(false);
var hasNewEpisodes = false;
- var hasNewSeasons = false;
-
- foreach (var series in group)
- {
- hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
- }
if (_config.Configuration.EnableInternetProviders)
{
@@ -121,7 +115,7 @@ namespace MediaBrowser.Providers.TV
}
}
- if (hasNewSeasons || hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
+ if (hasNewEpisodes || anySeasonsRemoved || anyEpisodesRemoved)
{
foreach (var series in group)
{
@@ -160,55 +154,6 @@ namespace MediaBrowser.Providers.TV
});
}
- ///
- /// For series with episodes directly under the series folder, this adds dummy seasons to enable regular browsing and metadata
- ///
- ///
- ///
- ///
- private async Task AddDummySeasonFolders(Series series, CancellationToken cancellationToken)
- {
- var episodesInSeriesFolder = series.RecursiveChildren
- .OfType()
- .Where(i => !i.IsInSeasonFolder)
- .ToList();
-
- var hasChanges = false;
-
- // Loop through the unique season numbers
- foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1)
- .Where(i => i >= 0)
- .Distinct()
- .ToList())
- {
- var hasSeason = series.Children.OfType()
- .Any(i => i.IndexNumber.HasValue && i.IndexNumber.Value == seasonNumber);
-
- if (!hasSeason)
- {
- await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
-
- hasChanges = true;
- }
- }
-
- // Unknown season - create a dummy season to put these under
- if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue))
- {
- var hasSeason = series.Children.OfType()
- .Any(i => !i.IndexNumber.HasValue);
-
- if (!hasSeason)
- {
- await AddSeason(series, null, cancellationToken).ConfigureAwait(false);
-
- hasChanges = true;
- }
- }
-
- return hasChanges;
- }
-
///
/// Adds the missing episodes.
///
@@ -449,10 +394,11 @@ namespace MediaBrowser.Providers.TV
if (season == null)
{
- season = await AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
+ var provider = new DummySeasonProvider(_config, _logger, _localization);
+ season = await provider.AddSeason(series, seasonNumber, cancellationToken).ConfigureAwait(false);
}
- var name = string.Format("Episode {0}", episodeNumber.ToString(UsCulture));
+ var name = string.Format("Episode {0}", episodeNumber.ToString(_usCulture));
var episode = new Episode
{
@@ -461,7 +407,7 @@ namespace MediaBrowser.Providers.TV
ParentIndexNumber = seasonNumber,
Parent = season,
DisplayMediaType = typeof(Episode).Name,
- Id = (series.Id + seasonNumber.ToString(UsCulture) + name).GetMBId(typeof(Episode))
+ Id = (series.Id + seasonNumber.ToString(_usCulture) + name).GetMBId(typeof(Episode))
};
await season.AddChild(episode, cancellationToken).ConfigureAwait(false);
@@ -471,39 +417,6 @@ namespace MediaBrowser.Providers.TV
}, cancellationToken).ConfigureAwait(false);
}
- ///
- /// Adds the season.
- ///
- /// The series.
- /// The season number.
- /// The cancellation token.
- /// Task{Season}.
- private async Task AddSeason(Series series,
- int? seasonNumber,
- CancellationToken cancellationToken)
- {
- var seasonName = seasonNumber == 0 ?
- _config.Configuration.SeasonZeroDisplayName :
- (seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(UsCulture)) : _localization.GetLocalizedString("NameSeasonUnknown"));
-
- _logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name);
-
- var season = new Season
- {
- Name = seasonName,
- IndexNumber = seasonNumber,
- Parent = series,
- DisplayMediaType = typeof(Season).Name,
- Id = (series.Id + (seasonNumber ?? -1).ToString(UsCulture) + seasonName).GetMBId(typeof(Season))
- };
-
- await series.AddChild(season, cancellationToken).ConfigureAwait(false);
-
- await season.RefreshMetadata(new MetadataRefreshOptions(), cancellationToken).ConfigureAwait(false);
-
- return season;
- }
-
///
/// Gets the existing episode.
///
@@ -551,7 +464,7 @@ namespace MediaBrowser.Providers.TV
private DateTime? GetAirDate(string seriesDataPath, int seasonNumber, int episodeNumber)
{
// First open up the tvdb xml file and make sure it has valid data
- var filename = string.Format("episode-{0}-{1}.xml", seasonNumber.ToString(UsCulture), episodeNumber.ToString(UsCulture));
+ var filename = string.Format("episode-{0}-{1}.xml", seasonNumber.ToString(_usCulture), episodeNumber.ToString(_usCulture));
var xmlPath = Path.Combine(seriesDataPath, filename);
diff --git a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
index 17a219f521..222438485e 100644
--- a/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
+++ b/MediaBrowser.Providers/TV/SeriesPostScanTask.cs
@@ -48,6 +48,13 @@ namespace MediaBrowser.Providers.TV
.OfType()
.ToList();
+ var provider = new DummySeasonProvider(_config, _logger, _localization);
+
+ foreach (var series in seriesList)
+ {
+ await provider.Run(series, cancellationToken).ConfigureAwait(false);
+ }
+
var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 4c0767b08a..96ae281b90 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
Items = videos
};
- var isInMixedFolder = resolverResult.Count > 0;
+ var isInMixedFolder = resolverResult.Count > 1;
foreach (var video in resolverResult)
{
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index 7bd42507d2..35d58837cb 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -300,7 +300,7 @@
"LabelCachePath": "Cache path:",
"LabelCachePathHelp": "Specify a custom location for server cache files, such as images.",
"LabelImagesByNamePath": "Images by name path:",
- "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, artist, genre and studio images.",
+ "LabelImagesByNamePathHelp": "Specify a custom location for downloaded actor, genre and studio images.",
"LabelMetadataPath": "Metadata path:",
"LabelMetadataPathHelp": "Specify a custom location for downloaded artwork and metadata, if not saving within media folders.",
"LabelTranscodingTempPath": "Transcoding temporary path:",