diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
index 664fe86da1..72a80ffadc 100644
--- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs
@@ -44,6 +44,12 @@ namespace MediaBrowser.Model.Configuration
///
/// The item by name path.
public string ItemsByNamePath { get; set; }
+
+ ///
+ /// Gets or sets the display name of the season zero.
+ ///
+ /// The display name of the season zero.
+ public string SeasonZeroDisplayName { get; set; }
///
/// Gets or sets the weather unit to use when displaying weather
@@ -260,6 +266,8 @@ namespace MediaBrowser.Model.Configuration
SortReplaceCharacters = new[] { ".", "+", "%" };
SortRemoveCharacters = new[] { ",", "&", "-", "{", "}", "'" };
SortRemoveWords = new[] { "the", "a", "an" };
+
+ SeasonZeroDisplayName = "Specials";
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index fbf2dfc70b..13857a656e 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -4,6 +4,7 @@ using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
@@ -159,6 +160,7 @@ namespace MediaBrowser.Server.Implementations.Library
/// The resolvers.
/// The intro providers.
/// The item comparers.
+ /// The prescan tasks.
public void AddParts(IEnumerable rules,
IEnumerable pluginFolders,
IEnumerable resolvers,
@@ -211,9 +213,11 @@ namespace MediaBrowser.Server.Implementations.Library
private bool _internetProvidersEnabled;
private bool _peopleImageFetchingEnabled;
private string _itemsByNamePath;
+ private string _seasonZeroDisplayName;
private void RecordConfigurationValues(ServerConfiguration configuration)
{
+ _seasonZeroDisplayName = ConfigurationManager.Configuration.SeasonZeroDisplayName;
_itemsByNamePath = ConfigurationManager.ApplicationPaths.ItemsByNamePath;
_internetProvidersEnabled = configuration.EnableInternetProviders;
_peopleImageFetchingEnabled = configuration.InternetProviderExcludeTypes == null || !configuration.InternetProviderExcludeTypes.Contains(typeof(Person).Name, StringComparer.OrdinalIgnoreCase);
@@ -239,17 +243,25 @@ namespace MediaBrowser.Server.Implementations.Library
refreshPeopleAfterUpdate = newConfigurationFetchesPeopleImages && !_peopleImageFetchingEnabled;
}
- var ibnPathChanged = !string.Equals(_itemsByNamePath, ConfigurationManager.ApplicationPaths.ItemsByNamePath);
+ var ibnPathChanged = !string.Equals(_itemsByNamePath, ConfigurationManager.ApplicationPaths.ItemsByNamePath, StringComparison.CurrentCulture);
if (ibnPathChanged)
{
_itemsByName.Clear();
}
+ var newSeasonZeroName = ConfigurationManager.Configuration.SeasonZeroDisplayName;
+ var seasonZeroNameChanged = !string.Equals(_seasonZeroDisplayName, newSeasonZeroName, StringComparison.CurrentCulture);
+
RecordConfigurationValues(config);
- Task.Run(() =>
+ Task.Run(async () =>
{
+ if (seasonZeroNameChanged)
+ {
+ await UpdateSeasonZeroNames(newSeasonZeroName, CancellationToken.None).ConfigureAwait(false);
+ }
+
// Any number of configuration settings could change the way the library is refreshed, so do that now
_taskManager.CancelIfRunningAndQueue();
@@ -260,6 +272,27 @@ namespace MediaBrowser.Server.Implementations.Library
});
}
+ ///
+ /// Updates the season zero names.
+ ///
+ /// The new name.
+ /// The cancellation token.
+ /// Task.
+ private Task UpdateSeasonZeroNames(string newName, CancellationToken cancellationToken)
+ {
+ var seasons = RootFolder.RecursiveChildren
+ .OfType()
+ .Where(i => i.IndexNumber.HasValue && i.IndexNumber.Value == 0 && !string.Equals(i.Name, newName, StringComparison.CurrentCulture))
+ .ToList();
+
+ foreach (var season in seasons)
+ {
+ season.Name = newName;
+ }
+
+ return UpdateItems(seasons, cancellationToken);
+ }
+
///
/// Creates the library items cache.
///
@@ -1075,30 +1108,49 @@ namespace MediaBrowser.Server.Implementations.Library
}
///
- /// Updates the item.
+ /// Updates the items.
///
- /// The item.
+ /// The items.
/// The cancellation token.
/// Task.
- public async Task UpdateItem(BaseItem item, CancellationToken cancellationToken)
+ private async Task UpdateItems(IEnumerable items, CancellationToken cancellationToken)
{
- await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false);
+ var list = items.ToList();
+
+ await ItemRepository.SaveItems(list, cancellationToken).ConfigureAwait(false);
- UpdateItemInLibraryCache(item);
+ foreach (var item in list)
+ {
+ UpdateItemInLibraryCache(item);
+ }
if (ItemUpdated != null)
{
- try
- {
- ItemUpdated(this, new ItemChangeEventArgs { Item = item });
- }
- catch (Exception ex)
+ foreach (var item in list)
{
- _logger.ErrorException("Error in ItemUpdated event handler", ex);
+ try
+ {
+ ItemUpdated(this, new ItemChangeEventArgs { Item = item });
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in ItemUpdated event handler", ex);
+ }
}
}
}
+ ///
+ /// Updates the item.
+ ///
+ /// The item.
+ /// The cancellation token.
+ /// Task.
+ public Task UpdateItem(BaseItem item, CancellationToken cancellationToken)
+ {
+ return UpdateItems(new[] { item }, cancellationToken);
+ }
+
///
/// Reports the item removed.
///
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
index 07fb2f4864..7ad5d08db6 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using System;
@@ -9,6 +10,20 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
///
public class SeasonResolver : FolderResolver
{
+ ///
+ /// The _config
+ ///
+ private readonly IServerConfigurationManager _config;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The config.
+ public SeasonResolver(IServerConfigurationManager config)
+ {
+ _config = config;
+ }
+
///
/// Resolves the specified args.
///
@@ -18,10 +33,17 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
if (args.Parent is Series && args.IsDirectory)
{
- return new Season
+ var season = new Season
{
IndexNumber = TVUtils.GetSeasonNumberFromPath(args.Path)
};
+
+ if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)
+ {
+ season.Name = _config.Configuration.SeasonZeroDisplayName;
+ }
+
+ return season;
}
return null;