aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs')
-rw-r--r--MediaBrowser.Server.Implementations/Library/LibraryManager.cs250
1 files changed, 200 insertions, 50 deletions
diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
index 63ced8559..e06720192 100644
--- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs
@@ -466,29 +466,54 @@ namespace MediaBrowser.Server.Implementations.Library
/// </summary>
/// <param name="args">The args.</param>
/// <returns>BaseItem.</returns>
- public BaseItem ResolveItem(ItemResolveArgs args)
+ private BaseItem ResolveItem(ItemResolveArgs args)
{
- var item = EntityResolvers.Select(r =>
+ var item = EntityResolvers.Select(r => Resolve(args, r))
+ .FirstOrDefault(i => i != null);
+
+ if (item != null)
{
- try
- {
- return r.ResolvePath(args);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error in {0} resolving {1}", ex, r.GetType().Name, args.Path);
+ ResolverHelper.SetInitialItemValues(item, args, _fileSystem, this);
+ }
- return null;
- }
+ return item;
+ }
- }).FirstOrDefault(i => i != null);
+ private BaseItem Resolve(ItemResolveArgs args, IItemResolver resolver)
+ {
+ try
+ {
+ return resolver.ResolvePath(args);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error in {0} resolving {1}", ex, resolver.GetType().Name, args.Path);
+ return null;
+ }
+ }
- if (item != null)
+ public Guid GetNewItemId(string key, Type type)
+ {
+ if (string.IsNullOrWhiteSpace(key))
+ {
+ throw new ArgumentNullException("key");
+ }
+ if (type == null)
{
- ResolverHelper.SetInitialItemValues(item, args, _fileSystem);
+ throw new ArgumentNullException("type");
}
- return item;
+ if (ConfigurationManager.Configuration.EnableLocalizedGuids && key.StartsWith(ConfigurationManager.ApplicationPaths.ProgramDataPath))
+ {
+ // Try to normalize paths located underneath program-data in an attempt to make them more portable
+ key = key.Substring(ConfigurationManager.ApplicationPaths.ProgramDataPath.Length)
+ .TrimStart(new[] { '/', '\\' })
+ .Replace("/", "\\");
+ }
+
+ key = type.FullName + key.ToLower();
+
+ return key.GetMD5();
}
public IEnumerable<BaseItem> ReplaceVideosWithPrimaryVersions(IEnumerable<BaseItem> items)
@@ -541,7 +566,7 @@ namespace MediaBrowser.Server.Implementations.Library
return ResolvePath(fileInfo, new DirectoryService(_logger), parent, collectionType);
}
- public BaseItem ResolvePath(FileSystemInfo fileInfo, IDirectoryService directoryService, Folder parent = null, string collectionType = null)
+ private BaseItem ResolvePath(FileSystemInfo fileInfo, IDirectoryService directoryService, Folder parent = null, string collectionType = null)
{
if (fileInfo == null)
{
@@ -621,23 +646,50 @@ namespace MediaBrowser.Server.Implementations.Library
return !args.ContainsFileSystemEntryByName(".ignore");
}
- public List<T> ResolvePaths<T>(IEnumerable<FileSystemInfo> files, IDirectoryService directoryService, Folder parent, string collectionType = null)
- where T : BaseItem
+ public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemInfo> files, IDirectoryService directoryService, Folder parent, string collectionType)
{
- return files.Select(f =>
+ var fileList = files.ToList();
+
+ if (parent != null)
+ {
+ var multiItemResolvers = EntityResolvers.OfType<IMultiItemResolver>();
+
+ foreach (var resolver in multiItemResolvers)
+ {
+ var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService);
+
+ if (result != null && result.Items.Count > 0)
+ {
+ var items = new List<BaseItem>();
+ items.AddRange(result.Items);
+
+ foreach (var item in items)
+ {
+ ResolverHelper.SetInitialItemValues(item, parent, _fileSystem, this, directoryService);
+ }
+ items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType));
+ return items;
+ }
+ }
+ }
+
+ return ResolveFileList(fileList, directoryService, parent, collectionType);
+ }
+
+ private IEnumerable<BaseItem> ResolveFileList(IEnumerable<FileSystemInfo> fileList, IDirectoryService directoryService, Folder parent, string collectionType)
+ {
+ return fileList.Select(f =>
{
try
{
- return ResolvePath(f, directoryService, parent, collectionType) as T;
+ return ResolvePath(f, directoryService, parent, collectionType);
}
catch (Exception ex)
{
_logger.ErrorException("Error resolving path {0}", ex, f.FullName);
return null;
}
-
- }).Where(i => i != null)
- .ToList();
+ }).Where(i => i != null);
}
/// <summary>
@@ -651,7 +703,7 @@ namespace MediaBrowser.Server.Implementations.Library
Directory.CreateDirectory(rootFolderPath);
- var rootFolder = GetItemById(rootFolderPath.GetMBId(typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(new DirectoryInfo(rootFolderPath));
+ var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ?? (AggregateFolder)ResolvePath(new DirectoryInfo(rootFolderPath));
// Add in the plug-in folders
foreach (var child in PluginFolderCreators)
@@ -662,7 +714,14 @@ namespace MediaBrowser.Server.Implementations.Library
{
if (folder.Id == Guid.Empty)
{
- folder.Id = (folder.Path ?? folder.GetType().Name).GetMBId(folder.GetType());
+ if (string.IsNullOrWhiteSpace(folder.Path))
+ {
+ folder.Id = GetNewItemId(folder.GetType().Name, folder.GetType());
+ }
+ else
+ {
+ folder.Id = GetNewItemId(folder.Path, folder.GetType());
+ }
}
folder = GetItemById(folder.Id) as BasePluginFolder ?? folder;
@@ -685,7 +744,7 @@ namespace MediaBrowser.Server.Implementations.Library
Directory.CreateDirectory(userRootPath);
- _userRootFolder = GetItemById(userRootPath.GetMBId(typeof(UserRootFolder))) as UserRootFolder ??
+ _userRootFolder = GetItemById(GetNewItemId(userRootPath, typeof(UserRootFolder))) as UserRootFolder ??
(UserRootFolder)ResolvePath(new DirectoryInfo(userRootPath));
}
@@ -801,7 +860,7 @@ namespace MediaBrowser.Server.Implementations.Library
Path.Combine(path, validFilename) :
Path.Combine(path, subFolderPrefix, validFilename);
- var id = fullPath.GetMBId(type);
+ var id = GetNewItemId(fullPath, type);
BaseItem obj;
@@ -1513,7 +1572,7 @@ namespace MediaBrowser.Server.Implementations.Library
path = Path.Combine(path, _fileSystem.GetValidFilename(type));
- var id = (path + "_namedview_" + name).GetMBId(typeof(UserView));
+ var id = GetNewItemId(path + "_namedview_" + name, typeof(UserView));
var item = GetItemById(id) as UserView;
@@ -1578,7 +1637,7 @@ namespace MediaBrowser.Server.Implementations.Library
throw new ArgumentNullException("viewType");
}
- var id = ("7_namedview_" + name + user.Id.ToString("N") + parentId).GetMBId(typeof(UserView));
+ var id = GetNewItemId("7_namedview_" + name + user.Id.ToString("N") + parentId, typeof(UserView));
var path = BaseItem.GetInternalMetadataPathForId(id);
@@ -1670,41 +1729,132 @@ namespace MediaBrowser.Server.Implementations.Library
};
}
- public IEnumerable<FileSystemInfo> GetAdditionalParts(string file,
- VideoType type,
- IEnumerable<FileSystemInfo> files)
+ public IEnumerable<Video> FindTrailers(BaseItem owner, List<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
{
- var resolver = new StackResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
+ var files = fileSystemChildren.OfType<DirectoryInfo>()
+ .Where(i => string.Equals(i.Name, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase))
+ .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
+ .ToList();
- StackResult result;
- List<FileSystemInfo> filteredFiles;
+ var videoListResolver = new VideoListResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
- if (type == VideoType.BluRay || type == VideoType.Dvd)
+ var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new PortableFileInfo
{
- filteredFiles = files.Where(i => (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
- .ToList();
+ FullName = i.FullName,
+ Type = GetFileType(i)
+
+ }).ToList());
+
+ var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files.First().Path, StringComparison.OrdinalIgnoreCase));
- result = resolver.ResolveDirectories(filteredFiles.Select(i => i.FullName));
+ if (currentVideo != null)
+ {
+ files.AddRange(currentVideo.Extras.Where(i => string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => new FileInfo(i.Path)));
}
- else
+
+ return ResolvePaths(files, directoryService, null, null)
+ .OfType<Video>()
+ .Select(video =>
{
- filteredFiles = files.Where(i => (i.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
- .ToList();
+ // Try to retrieve it from the db. If we don't find it, use the resolved version
+ var dbItem = GetItemById(video.Id) as Video;
- result = resolver.ResolveFiles(filteredFiles.Select(i => i.FullName));
+ if (dbItem != null)
+ {
+ video = dbItem;
+ }
+
+ video.ExtraType = ExtraType.Trailer;
+
+ return video;
+
+ // Sort them so that the list can be easily compared for changes
+ }).OrderBy(i => i.Path).ToList();
+ }
+
+ private FileInfoType GetFileType(FileSystemInfo info)
+ {
+ if ((info.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
+ {
+ return FileInfoType.Directory;
}
- var stack = result.Stacks
- .FirstOrDefault(i => i.Files.Contains(file, StringComparer.OrdinalIgnoreCase));
+ return FileInfoType.File;
+ }
+
+ public IEnumerable<Video> FindExtras(BaseItem owner, List<FileSystemInfo> fileSystemChildren, IDirectoryService directoryService)
+ {
+ var files = fileSystemChildren.OfType<DirectoryInfo>()
+ .Where(i => string.Equals(i.Name, "extras", StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, "specials", StringComparison.OrdinalIgnoreCase))
+ .SelectMany(i => i.EnumerateFiles("*", SearchOption.TopDirectoryOnly))
+ .ToList();
+
+ var videoListResolver = new VideoListResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger());
+
+ var videos = videoListResolver.Resolve(fileSystemChildren.Select(i => new PortableFileInfo
+ {
+ FullName = i.FullName,
+ Type = GetFileType(i)
+
+ }).ToList());
+
+ var currentVideo = videos.FirstOrDefault(i => string.Equals(owner.Path, i.Files.First().Path, StringComparison.OrdinalIgnoreCase));
- if (stack != null)
+ if (currentVideo != null)
{
- return stack.Files.Where(i => !string.Equals(i, file, StringComparison.OrdinalIgnoreCase))
- .Select(i => filteredFiles.FirstOrDefault(f => string.Equals(i, f.FullName, StringComparison.OrdinalIgnoreCase)))
- .Where(i => i != null);
+ files.AddRange(currentVideo.Extras.Where(i => !string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => new FileInfo(i.Path)));
}
- return new List<FileSystemInfo>();
+ return ResolvePaths(files, directoryService, null, null)
+ .OfType<Video>()
+ .Select(video =>
+ {
+ // Try to retrieve it from the db. If we don't find it, use the resolved version
+ var dbItem = GetItemById(video.Id) as Video;
+
+ if (dbItem != null)
+ {
+ video = dbItem;
+ }
+
+ SetExtraTypeFromFilename(video);
+
+ return video;
+
+ // Sort them so that the list can be easily compared for changes
+ }).OrderBy(i => i.Path).ToList();
+ }
+
+ private void SetExtraTypeFromFilename(Video item)
+ {
+ var resolver = new ExtraResolver(new ExtendedNamingOptions(), new Naming.Logging.NullLogger(), new RegexProvider());
+
+ var result = resolver.GetExtraInfo(item.Path);
+
+ if (string.Equals(result.ExtraType, "deletedscene", StringComparison.OrdinalIgnoreCase))
+ {
+ item.ExtraType = ExtraType.DeletedScene;
+ }
+ else if (string.Equals(result.ExtraType, "behindthescenes", StringComparison.OrdinalIgnoreCase))
+ {
+ item.ExtraType = ExtraType.BehindTheScenes;
+ }
+ else if (string.Equals(result.ExtraType, "interview", StringComparison.OrdinalIgnoreCase))
+ {
+ item.ExtraType = ExtraType.Interview;
+ }
+ else if (string.Equals(result.ExtraType, "scene", StringComparison.OrdinalIgnoreCase))
+ {
+ item.ExtraType = ExtraType.Scene;
+ }
+ else if (string.Equals(result.ExtraType, "sample", StringComparison.OrdinalIgnoreCase))
+ {
+ item.ExtraType = ExtraType.Sample;
+ }
+ else
+ {
+ item.ExtraType = ExtraType.Clip;
+ }
}
}
}