diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs
index 272dff3ecc..98c259825e 100644
--- a/MediaBrowser.Api/ItemUpdateService.cs
+++ b/MediaBrowser.Api/ItemUpdateService.cs
@@ -76,11 +76,13 @@ namespace MediaBrowser.Api
{
if (!(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder) && !(item is LiveTvChannel) && !(item is IItemByName))
{
- var collectionType = _libraryManager.GetInheritedContentType(item);
- if (string.IsNullOrWhiteSpace(collectionType))
+ var inheritedContentType = _libraryManager.GetInheritedContentType(item);
+ var configuredContentType = _libraryManager.GetConfiguredContentType(item);
+
+ if (string.IsNullOrWhiteSpace(inheritedContentType) || string.Equals(inheritedContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) || !string.IsNullOrWhiteSpace(configuredContentType))
{
info.ContentTypeOptions = GetContentTypeOptions(true);
- info.ContentType = _libraryManager.GetContentType(item);
+ info.ContentType = configuredContentType;
}
}
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index 8573f32e0b..2ebd1cab93 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -265,6 +265,20 @@ namespace MediaBrowser.Controller.Library
/// The item.
/// System.String.
string GetInheritedContentType(BaseItem item);
+
+ ///
+ /// Gets the type of the configured content.
+ ///
+ /// The item.
+ /// System.String.
+ string GetConfiguredContentType(BaseItem item);
+
+ ///
+ /// Gets the type of the configured content.
+ ///
+ /// The path.
+ /// System.String.
+ string GetConfiguredContentType(string path);
///
/// Normalizes the root path list.
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 37a68b52b8..48bddd6a81 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -13,6 +13,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Naming.Audio;
@@ -200,7 +201,7 @@ namespace MediaBrowser.Server.Implementations.Library
MultiItemResolvers = EntityResolvers.OfType().ToArray();
IntroProviders = introProviders.ToArray();
Comparers = itemComparers.ToArray();
-
+
PostscanTasks = postscanTasks.OrderBy(i =>
{
var hasOrder = i as IHasOrder;
@@ -578,7 +579,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (string.IsNullOrWhiteSpace(collectionType))
{
- collectionType = GetConfiguredContentType(fullPath);
+ collectionType = GetContentTypeOverride(fullPath, true);
}
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, this, directoryService)
@@ -1554,16 +1555,17 @@ namespace MediaBrowser.Server.Implementations.Library
public string GetContentType(BaseItem item)
{
- // Types cannot be overridden, so go from the top down until we find a configured content type
-
- var type = GetInheritedContentType(item);
-
- if (!string.IsNullOrWhiteSpace(type))
+ string configuredContentType = GetConfiguredContentType(item, false);
+ if (!string.IsNullOrWhiteSpace(configuredContentType))
{
- return type;
+ return configuredContentType;
}
-
- return GetConfiguredContentType(item);
+ configuredContentType = GetConfiguredContentType(item, true);
+ if (!string.IsNullOrWhiteSpace(configuredContentType))
+ {
+ return configuredContentType;
+ }
+ return GetInheritedContentType(item);
}
public string GetInheritedContentType(BaseItem item)
@@ -1580,19 +1582,36 @@ namespace MediaBrowser.Server.Implementations.Library
.LastOrDefault(i => !string.IsNullOrWhiteSpace(i));
}
- private string GetConfiguredContentType(BaseItem item)
+ public string GetConfiguredContentType(BaseItem item)
{
- return GetConfiguredContentType(item.ContainingFolderPath);
+ return GetConfiguredContentType(item, false);
}
- private string GetConfiguredContentType(string path)
+ public string GetConfiguredContentType(string path)
{
- var type = ConfigurationManager.Configuration.ContentTypes
- .FirstOrDefault(i => string.Equals(i.Name, path, StringComparison.OrdinalIgnoreCase) || _fileSystem.ContainsSubPath(i.Name, path));
+ return GetContentTypeOverride(path, false);
+ }
- return type == null ? null : type.Value;
+ public string GetConfiguredContentType(BaseItem item, bool inheritConfiguredPath)
+ {
+ ICollectionFolder collectionFolder = item as ICollectionFolder;
+ if (collectionFolder != null)
+ {
+ return collectionFolder.CollectionType;
+ }
+ return GetContentTypeOverride(item.ContainingFolderPath, inheritConfiguredPath);
}
+ private string GetContentTypeOverride(string path, bool inherit)
+ {
+ var nameValuePair = ConfigurationManager.Configuration.ContentTypes.FirstOrDefault(i => string.Equals(i.Name, path, StringComparison.OrdinalIgnoreCase) || (inherit && _fileSystem.ContainsSubPath(i.Name, path)));
+ if (nameValuePair != null)
+ {
+ return nameValuePair.Value;
+ }
+ return null;
+ }
+
private string GetTopFolderContentType(BaseItem item)
{
while (!(item.Parent is AggregateFolder) && item.Parent != null)
@@ -1747,7 +1766,7 @@ namespace MediaBrowser.Server.Implementations.Library
public int? GetSeasonNumberFromPath(string path)
{
- return new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, true).SeasonNumber;
+ return new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, true, true).SeasonNumber;
}
public bool FillMissingEpisodeNumbersFromPath(Episode episode)
@@ -1755,8 +1774,8 @@ namespace MediaBrowser.Server.Implementations.Library
var resolver = new EpisodeResolver(new ExtendedNamingOptions(),
new Naming.Logging.NullLogger());
- var fileType = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || episode.VideoType == VideoType.HdDvd ?
- FileInfoType.Directory :
+ var fileType = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || episode.VideoType == VideoType.HdDvd ?
+ FileInfoType.Directory :
FileInfoType.File;
var locationType = episode.LocationType;
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index a1c762283b..d1a6cbbf84 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -129,17 +129,26 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
{
var path = fileSystemInfo.FullName;
var isMultiDisc = IsMultiDiscFolder(path);
- var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
- if (isMultiDisc && hasMusic)
+ if (isMultiDisc)
{
- logger.Debug("Found multi-disc folder: " + path);
- discSubfolderCount++;
+ var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
+
+ if (hasMusic)
+ {
+ logger.Debug("Found multi-disc folder: " + path);
+ discSubfolderCount++;
+ }
}
- else if (hasMusic)
+ else
{
- // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album
- notMultiDisc = true;
+ var hasMusic = ContainsMusic(directoryService.GetFileSystemEntries(path), false, directoryService, logger, fileSystem, libraryManager);
+
+ if (hasMusic)
+ {
+ // If there are folders underneath with music that are not multidisc, then this can't be a multi-disc album
+ notMultiDisc = true;
+ }
}
}
}
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
index 80477e5671..fe4832d48b 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
@@ -36,7 +36,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
var season = new Season
{
- IndexNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(args.Path, true).SeasonNumber
+ IndexNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(args.Path, true, true).SeasonNumber
};
if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)
diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
index 7f1416ad65..ee0fe6b948 100644
--- a/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
+++ b/MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -1,9 +1,17 @@
-using MediaBrowser.Controller.Entities.TV;
+using System.Collections.Generic;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Entities;
using System;
using System.IO;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Naming.Common;
+using MediaBrowser.Naming.IO;
+using MediaBrowser.Naming.TV;
+using EpisodeInfo = MediaBrowser.Controller.Providers.EpisodeInfo;
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
{
@@ -12,6 +20,17 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
///
public class SeriesResolver : FolderResolver
{
+ private readonly IFileSystem _fileSystem;
+ private readonly ILogger _logger;
+ private readonly ILibraryManager _libraryManager;
+
+ public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
+ {
+ _fileSystem = fileSystem;
+ _logger = logger;
+ _libraryManager = libraryManager;
+ }
+
///
/// Gets the priority.
///
@@ -34,26 +53,139 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
if (args.IsDirectory)
{
var collectionType = args.GetCollectionType();
-
- // If there's a collection type and it's not tv, it can't be a series
if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
{
if (args.HasParent())
{
return null;
- }
-
- return new Series
+ }
+
+ var configuredContentType = _libraryManager.GetConfiguredContentType(args.Path);
+ if (!string.Equals(configuredContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+ {
+ return new Series
+ {
+ Path = args.Path,
+ Name = Path.GetFileName(args.Path)
+ };
+ }
+ }
+ else
+ {
+ if (args.HasParent())
+ {
+ return null;
+ }
+
+ if (string.IsNullOrWhiteSpace(collectionType))
{
- Path = args.Path,
- Name = Path.GetFileName(args.Path)
- };
+ if (args.Parent.IsRoot)
+ {
+ return null;
+ }
+ if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, false))
+ {
+ return new Series
+ {
+ Path = args.Path,
+ Name = Path.GetFileName(args.Path)
+ };
+ }
+ }
}
}
return null;
}
+ public static bool IsSeriesFolder(string path,
+ IEnumerable fileSystemChildren,
+ IDirectoryService directoryService,
+ IFileSystem fileSystem,
+ ILogger logger,
+ ILibraryManager libraryManager,
+ bool isTvContentType)
+ {
+ foreach (var child in fileSystemChildren)
+ {
+ var attributes = child.Attributes;
+
+ if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ {
+ //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName);
+ continue;
+ }
+
+ // Can't enforce this because files saved by Bitcasa are always marked System
+ //if ((attributes & FileAttributes.System) == FileAttributes.System)
+ //{
+ // logger.Debug("Igoring series subfolder marked system: {0}", child.FullName);
+ // continue;
+ //}
+
+ if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
+ {
+ if (IsSeasonFolder(child.FullName, isTvContentType))
+ {
+ //logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
+ return true;
+ }
+ }
+ else
+ {
+ string fullName = child.FullName;
+ if (libraryManager.IsVideoFile(fullName))
+ {
+ if (isTvContentType)
+ {
+ return true;
+ }
+
+ var episodeResolver = new Naming.TV.EpisodeResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
+ var episodeInfo = episodeResolver.Resolve(fullName, FileInfoType.File, false);
+ if (episodeInfo != null && episodeInfo.EpisodeNumber.HasValue)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ logger.Debug("{0} is not a series folder.", path);
+ return false;
+ }
+
+ ///
+ /// Determines whether [is place holder] [the specified path].
+ ///
+ /// The path.
+ /// true if [is place holder] [the specified path]; otherwise, false.
+ /// path
+ private static bool IsVideoPlaceHolder(string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ {
+ throw new ArgumentNullException("path");
+ }
+
+ var extension = Path.GetExtension(path);
+
+ return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase);
+ }
+
+ ///
+ /// Determines whether [is season folder] [the specified path].
+ ///
+ /// The path.
+ /// if set to true [is tv content type].
+ /// true if [is season folder] [the specified path]; otherwise, false.
+ private static bool IsSeasonFolder(string path, bool isTvContentType)
+ {
+ var seasonNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, isTvContentType, isTvContentType).SeasonNumber;
+
+ return seasonNumber.HasValue;
+ }
+
///
/// Sets the initial item values.
///
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index 81054b3c5a..f32e33be0a 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -51,7 +51,7 @@
False
- ..\packages\MediaBrowser.Naming.1.0.0.25\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll
+ ..\packages\MediaBrowser.Naming.1.0.0.27\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll
False
diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config
index aba7d0e330..e838757dc6 100644
--- a/MediaBrowser.Server.Implementations/packages.config
+++ b/MediaBrowser.Server.Implementations/packages.config
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/SharedVersion.cs b/SharedVersion.cs
index 70c7bbf8c4..65f786cebb 100644
--- a/SharedVersion.cs
+++ b/SharedVersion.cs
@@ -1,4 +1,4 @@
using System.Reflection;
[assembly: AssemblyVersion("3.0.*")]
-//[assembly: AssemblyVersion("3.0.5482.1")]
+//[assembly: AssemblyVersion("3.0.5482.3")]