diff options
Diffstat (limited to 'MediaBrowser.Server.Implementations/Library/LibraryManager.cs')
| -rw-r--r-- | MediaBrowser.Server.Implementations/Library/LibraryManager.cs | 250 |
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; + } } } } |
