public override T Resolve(ItemResolveArgs args) { return(ResolveVideo <T>(args, false)); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>Video.</returns> protected override Video Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); // Find movies with their own folders if (args.IsDirectory) { if (IsInvalid(args.Parent, collectionType)) { return(null); } var files = args.FileSystemChildren .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) .ToList(); if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <MusicVideo>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false)); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <Video>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false)); } if (string.IsNullOrEmpty(collectionType)) { // Owned items will be caught by the plain video resolver if (args.Parent == null) { //return FindMovie<Video>(args.Path, args.Parent, files, args.DirectoryService, collectionType); return(null); } if (args.HasParent <Series>()) { return(null); } { return(FindMovie <Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true)); } } if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true)); } return(null); } // Handle owned items if (args.Parent == null) { return(base.Resolve(args)); } if (IsInvalid(args.Parent, collectionType)) { return(null); } Video item = null; if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <MusicVideo>(args, false); } // To find a movie file, the collection type must be movies or boxsets else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <Movie>(args, true); } else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <Video>(args, false); } else if (string.IsNullOrEmpty(collectionType)) { if (args.HasParent <Series>()) { return(null); } item = ResolveVideo <Video>(args, false); } if (item != null) { item.IsInMixedFolder = true; } return(item); }
/// <summary> /// Finds a movie based on a child file system entries /// </summary> /// <param name="args">The args.</param> /// <returns>Movie.</returns> private Movie FindMovie(ItemResolveArgs args) { // Since the looping is expensive, this is an optimization to help us avoid it if (args.ContainsMetaFileByName("series.xml") || args.Path.IndexOf("[tvdbid", StringComparison.OrdinalIgnoreCase) != -1) { return(null); } // Optimization to avoid having to resolve every file bool?isKnownMovie = null; var movies = new List <Movie>(); // Loop through each child file/folder and see if we find a video foreach (var child in args.FileSystemChildren) { if (child.IsDirectory) { if (IsDvdDirectory(child.cFileName)) { return(new Movie { Path = args.Path, VideoType = VideoType.Dvd }); } if (IsBluRayDirectory(child.cFileName)) { return(new Movie { Path = args.Path, VideoType = VideoType.BluRay }); } if (IsHdDvdDirectory(child.cFileName)) { return(new Movie { Path = args.Path, VideoType = VideoType.HdDvd }); } continue; } var childArgs = new ItemResolveArgs(ApplicationPaths) { FileInfo = child, Path = child.Path }; var item = base.Resolve(childArgs); if (item != null) { // If we already know it's a movie, we can stop looping if (!isKnownMovie.HasValue) { isKnownMovie = args.ContainsMetaFileByName("movie.xml") || args.ContainsMetaFileByName(MovieDbProvider.LOCAL_META_FILE_NAME) || args.Path.IndexOf("[tmdbid", StringComparison.OrdinalIgnoreCase) != -1; } if (isKnownMovie.Value) { return(item); } movies.Add(item); } } // If there are multiple video files, return null, and let the VideoResolver catch them later as plain videos return(movies.Count == 1 ? movies[0] : null); }
/// <summary> /// Resolves the video. /// </summary> /// <typeparam name="TVideoType">The type of the T video type.</typeparam> /// <param name="args">The args.</param> /// <param name="parseName">if set to <c>true</c> [parse name].</param> /// <returns>``0.</returns> protected TVideoType ResolveVideo <TVideoType>(ItemResolveArgs args, bool parseName) where TVideoType : Video, new() { var namingOptions = ((LibraryManager)LibraryManager).GetNamingOptions(); // If the path is a file check for a matching extensions var parser = new VideoResolver(namingOptions); if (args.IsDirectory) { TVideoType video = null; VideoFileInfo videoInfo = null; // Loop through each child file/folder and see if we find a video foreach (var child in args.FileSystemChildren) { var filename = child.Name; if (child.IsDirectory) { if (IsDvdDirectory(child.FullName, filename, args.DirectoryService)) { videoInfo = parser.ResolveDirectory(args.Path); if (videoInfo == null) { return(null); } video = new TVideoType { Path = args.Path, VideoType = VideoType.Dvd, ProductionYear = videoInfo.Year }; break; } if (IsBluRayDirectory(child.FullName, filename, args.DirectoryService)) { videoInfo = parser.ResolveDirectory(args.Path); if (videoInfo == null) { return(null); } video = new TVideoType { Path = args.Path, VideoType = VideoType.BluRay, ProductionYear = videoInfo.Year }; break; } } else if (IsDvdFile(filename)) { videoInfo = parser.ResolveDirectory(args.Path); if (videoInfo == null) { return(null); } video = new TVideoType { Path = args.Path, VideoType = VideoType.Dvd, ProductionYear = videoInfo.Year }; break; } } if (video != null) { video.Name = parseName ? videoInfo.Name : Path.GetFileName(args.Path); Set3DFormat(video, videoInfo); } return(video); } else { var videoInfo = parser.Resolve(args.Path, false, false); if (videoInfo == null) { return(null); } if (LibraryManager.IsVideoFile(args.Path) || videoInfo.IsStub) { var path = args.Path; var video = new TVideoType { Path = path, IsInMixedFolder = true, ProductionYear = videoInfo.Year }; SetVideoType(video, videoInfo); video.Name = parseName ? videoInfo.Name : Path.GetFileNameWithoutExtension(args.Path); Set3DFormat(video, videoInfo); return(video); } } return(null); }
/// <summary> /// Sets initial values on the newly resolved item. /// </summary> /// <param name="item">The item.</param> /// <param name="args">The args.</param> protected virtual void SetInitialItemValues(T item, ItemResolveArgs args) { }
/// <summary> /// Gets the image. /// </summary> /// <param name="item">The item.</param> /// <param name="args">The args.</param> /// <param name="filenameWithoutExtension">The filename without extension.</param> /// <returns>FileSystemInfo.</returns> protected virtual FileSystemInfo GetImage(BaseItem item, ItemResolveArgs args, string filenameWithoutExtension) { return(BaseItem.SupportedImageExtensions .Select(i => args.GetMetaFileByPath(GetFullImagePath(item, args, filenameWithoutExtension, i))) .FirstOrDefault(i => i != null)); }
/// <summary> /// Gets the filtered file system entries. /// </summary> /// <param name="directoryService">The directory service.</param> /// <param name="path">The path.</param> /// <param name="fileSystem">The file system.</param> /// <param name="logger">The logger.</param> /// <param name="args">The args.</param> /// <param name="flattenFolderDepth">The flatten folder depth.</param> /// <param name="resolveShortcuts">if set to <c>true</c> [resolve shortcuts].</param> /// <returns>Dictionary{System.StringFileSystemInfo}.</returns> /// <exception cref="System.ArgumentNullException">path</exception> public static Dictionary <string, FileSystemMetadata> GetFilteredFileSystemEntries(IDirectoryService directoryService, string path, IFileSystem fileSystem, ILogger logger, ItemResolveArgs args, int flattenFolderDepth = 0, bool resolveShortcuts = true) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } if (args == null) { throw new ArgumentNullException("args"); } if (!resolveShortcuts && flattenFolderDepth == 0) { return(directoryService.GetFileSystemDictionary(path)); } var entries = directoryService.GetFileSystemEntries(path); var dict = new Dictionary <string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase); foreach (var entry in entries) { var isDirectory = entry.IsDirectory; var fullName = entry.FullName; if (resolveShortcuts && fileSystem.IsShortcut(fullName)) { try { var newPath = fileSystem.ResolveShortcut(fullName); if (string.IsNullOrWhiteSpace(newPath)) { //invalid shortcut - could be old or target could just be unavailable logger.Warn("Encountered invalid shortcut: " + fullName); continue; } // Don't check if it exists here because that could return false for network shares. var data = fileSystem.GetDirectoryInfo(newPath); // add to our physical locations args.AddAdditionalLocation(newPath); dict[newPath] = data; } catch (Exception ex) { logger.ErrorException("Error resolving shortcut from {0}", ex, fullName); } } else if (flattenFolderDepth > 0 && isDirectory) { foreach (var child in GetFilteredFileSystemEntries(directoryService, fullName, fileSystem, logger, args, flattenFolderDepth: flattenFolderDepth - 1, resolveShortcuts: resolveShortcuts)) { dict[child.Key] = child.Value; } } else { dict[fullName] = entry; } } return(dict); }
protected override FileSystemInfo GetImage(BaseItem item, ItemResolveArgs args, string filenameWithoutExtension) { return(item.ResolveArgs.PhysicalLocations .Select(i => GetImageFromLocation(i, filenameWithoutExtension)) .FirstOrDefault(i => i != null)); }
protected override MediaBrowser.Controller.Entities.Audio.Audio Resolve(ItemResolveArgs args) { // Return audio if the path is a file and has a matching extension var collectionType = args.GetCollectionType(); var isBooksCollectionType = string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase); if (args.IsDirectory) { if (!isBooksCollectionType) { return(null); } return(FindAudioBook(args, false)); } if (AudioFileParser.IsAudioFile(args.Path, _namingOptions)) { var extension = Path.GetExtension(args.Path); if (string.Equals(extension, ".cue", StringComparison.OrdinalIgnoreCase)) { // if audio file exists of same name, return null return(null); } var isMixedCollectionType = string.IsNullOrEmpty(collectionType); // For conflicting extensions, give priority to videos if (isMixedCollectionType && VideoResolver.IsVideoFile(args.Path, _namingOptions)) { return(null); } MediaBrowser.Controller.Entities.Audio.Audio item = null; var isMusicCollectionType = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); // Use regular audio type for mixed libraries, owned items and music if (isMixedCollectionType || args.Parent == null || isMusicCollectionType) { item = new MediaBrowser.Controller.Entities.Audio.Audio(); } else if (isBooksCollectionType) { item = new AudioBook(); } if (item != null) { item.IsShortcut = string.Equals(extension, ".strm", StringComparison.OrdinalIgnoreCase); item.IsInMixedFolder = true; } return(item); } return(null); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>Entities.Audio.Audio.</returns> protected override MediaBrowser.Controller.Entities.Audio.Audio Resolve(ItemResolveArgs args) { // Return audio if the path is a file and has a matching extension var libraryOptions = args.GetLibraryOptions(); var collectionType = args.GetCollectionType(); var isBooksCollectionType = string.Equals(collectionType, CollectionType.Books, StringComparison.OrdinalIgnoreCase); if (args.IsDirectory) { if (!isBooksCollectionType) { return(null); } var files = args.FileSystemChildren .Where(i => !LibraryManager.IgnoreFile(i, args.Parent)) .ToList(); if (isBooksCollectionType) { return(FindAudio <AudioBook>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false)); } return(null); } if (LibraryManager.IsAudioFile(args.Path, libraryOptions)) { if (string.Equals(Path.GetExtension(args.Path), ".cue", StringComparison.OrdinalIgnoreCase)) { // if audio file exists of same name, return null return(null); } var isMixedCollectionType = string.IsNullOrWhiteSpace(collectionType); // For conflicting extensions, give priority to videos if (isMixedCollectionType && LibraryManager.IsVideoFile(args.Path, libraryOptions)) { return(null); } MediaBrowser.Controller.Entities.Audio.Audio item = null; var isMusicCollectionType = string.Equals(collectionType, CollectionType.Music, StringComparison.OrdinalIgnoreCase); // Use regular audio type for mixed libraries, owned items and music if (isMixedCollectionType || args.Parent == null || isMusicCollectionType) { item = new MediaBrowser.Controller.Entities.Audio.Audio(); } else if (isBooksCollectionType) { item = new AudioBook(); } if (item != null) { item.IsInMixedFolder = true; } return(item); } return(null); }
/// <summary> /// Determines whether a path should be ignored based on its contents - called after the contents have been read /// </summary> /// <param name="args">The args.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> private static bool ShouldResolvePathContents(ItemResolveArgs args) { // Ignore any folders containing a file called .ignore return(!args.ContainsFileSystemEntryByName(".ignore")); }
/// <summary> /// Sets the initial item values. /// </summary> /// <param name="item">The item.</param> /// <param name="args">The args.</param> protected override void SetInitialItemValues(Season item, ItemResolveArgs args) { base.SetInitialItemValues(item, args); Season.AddMetadataFiles(args); }
public override Video Resolve(ItemResolveArgs args) { var collectionType = args.GetCollectionType(); // Find movies with their own folders if (args.IsDirectory) { if (IsInvalid(args.Parent, collectionType)) { return(null); } Video movie = null; var files = args.GetActualFileSystemChildren().ToList(); if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { movie = FindMovie <MusicVideo>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { movie = FindMovie <Video>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, false); } if (string.IsNullOrEmpty(collectionType)) { // Owned items will be caught by the video extra resolver if (args.Parent == null) { return(null); } if (args.HasParent <Series>()) { return(null); } movie = FindMovie <Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true); } if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { movie = FindMovie <Movie>(args, args.Path, args.Parent, files, args.DirectoryService, collectionType, true); } // ignore extras return(movie?.ExtraType == null ? movie : null); } if (args.Parent == null) { return(base.Resolve(args)); } if (IsInvalid(args.Parent, collectionType)) { return(null); } Video item = null; if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <MusicVideo>(args, false); } // To find a movie file, the collection type must be movies or boxsets else if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <Movie>(args, true); } else if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) || string.Equals(collectionType, CollectionType.Photos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <Video>(args, false); } else if (string.IsNullOrEmpty(collectionType)) { if (args.HasParent <Series>()) { return(null); } item = ResolveVideo <Video>(args, false); } // Ignore extras if (item?.ExtraType != null) { return(null); } if (item != null) { item.IsInMixedFolder = true; } return(item); }
protected virtual TVideoType ResolveVideo <TVideoType>(ItemResolveArgs args, bool parseName) where TVideoType : Video, new() { VideoFileInfo videoInfo = null; VideoType? videoType = null; // If the path is a file check for a matching extensions if (args.IsDirectory) { // Loop through each child file/folder and see if we find a video foreach (var child in args.FileSystemChildren) { var filename = child.Name; if (child.IsDirectory) { if (IsDvdDirectory(child.FullName, filename, args.DirectoryService)) { videoType = VideoType.Dvd; } else if (IsBluRayDirectory(filename)) { videoType = VideoType.BluRay; } } else if (IsDvdFile(filename)) { videoType = VideoType.Dvd; } if (videoType == null) { continue; } videoInfo = VideoResolver.ResolveDirectory(args.Path, NamingOptions, parseName); break; } } else { videoInfo = VideoResolver.Resolve(args.Path, false, NamingOptions, parseName); } if (videoInfo == null || (!videoInfo.IsStub && !VideoResolver.IsVideoFile(args.Path, NamingOptions))) { return(null); } var video = new TVideoType { Name = videoInfo.Name, Path = args.Path, ProductionYear = videoInfo.Year, ExtraType = videoInfo.ExtraType }; if (videoType.HasValue) { video.VideoType = videoType.Value; } else { SetVideoType(video, videoInfo); } Set3DFormat(video, videoInfo); return(video); }
private bool HasPhotos(ItemResolveArgs args) { return(args.FileSystemChildren.Any(i => (!i.IsDirectory) && PhotoResolver.IsImageFile(i.FullName, _imageProcessor))); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>`0.</returns> protected virtual T Resolve(ItemResolveArgs args) { return(null); }
/// <summary> /// Shoulds the ignore. /// </summary> /// <param name="args">The args.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> public bool ShouldIgnore(ItemResolveArgs args) { var filename = args.FileInfo.Name; // Handle mac .DS_Store // https://github.com/MediaBrowser/MediaBrowser/issues/427 if (filename.IndexOf("._", StringComparison.OrdinalIgnoreCase) == 0) { return(true); } // Ignore hidden files and folders if (args.IsHidden) { var parentFolderName = Path.GetFileName(Path.GetDirectoryName(args.Path)); if (string.Equals(parentFolderName, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) { return(false); } if (string.Equals(parentFolderName, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) { return(false); } // Drives will sometimes be hidden if (args.Path.EndsWith(Path.VolumeSeparatorChar + "\\", StringComparison.OrdinalIgnoreCase)) { return(false); } // Shares will sometimes be hidden if (args.Path.StartsWith("\\", StringComparison.OrdinalIgnoreCase)) { // Look for a share, e.g. \\server\movies // Is there a better way to detect if a path is a share without using native code? if (args.Path.Substring(2).Split(Path.DirectorySeparatorChar).Length == 2) { return(false); } } return(true); } if (args.IsDirectory) { // Ignore any folders in our list if (IgnoreFolders.ContainsKey(filename)) { return(true); } // Ignore trailer folders but allow it at the collection level if (string.Equals(filename, BaseItem.TrailerFolderName, StringComparison.OrdinalIgnoreCase) && !(args.Parent is AggregateFolder) && !(args.Parent is UserRootFolder)) { return(true); } if (string.Equals(filename, BaseItem.ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) { return(true); } if (string.Equals(filename, BaseItem.ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) { return(true); } } else { if (args.Parent != null) { // Don't resolve these into audio files if (string.Equals(Path.GetFileNameWithoutExtension(filename), BaseItem.ThemeSongFilename) && EntityResolutionHelper.IsAudioFile(filename)) { return(true); } } } return(false); }
private static bool HasPhotos(ItemResolveArgs args) { return(args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName))); }
/// <summary> /// Fills in image paths based on files win the folder /// </summary> /// <param name="item">The item.</param> /// <param name="args">The args.</param> private void PopulateBaseItemImages(BaseItem item, ItemResolveArgs args) { // Primary Image var image = GetImage(item, args, "folder") ?? GetImage(item, args, "poster") ?? GetImage(item, args, "cover") ?? GetImage(item, args, "default"); // Look for a file with the same name as the item if (image == null) { var name = Path.GetFileNameWithoutExtension(item.Path); if (!string.IsNullOrEmpty(name)) { image = GetImage(item, args, name); } } if (image != null) { item.SetImage(ImageType.Primary, image.FullName); } // Logo Image image = GetImage(item, args, "logo"); if (image != null) { item.SetImage(ImageType.Logo, image.FullName); } // Banner Image image = GetImage(item, args, "banner"); if (image != null) { item.SetImage(ImageType.Banner, image.FullName); } // Clearart image = GetImage(item, args, "clearart"); if (image != null) { item.SetImage(ImageType.Art, image.FullName); } // Disc image = GetImage(item, args, "disc"); if (image != null) { item.SetImage(ImageType.Disc, image.FullName); } // Thumbnail Image image = GetImage(item, args, "thumb"); if (image != null) { item.SetImage(ImageType.Thumb, image.FullName); } // Box Image image = GetImage(item, args, "box"); if (image != null) { item.SetImage(ImageType.Box, image.FullName); } // BoxRear Image image = GetImage(item, args, "boxrear"); if (image != null) { item.SetImage(ImageType.BoxRear, image.FullName); } // Thumbnail Image image = GetImage(item, args, "menu"); if (image != null) { item.SetImage(ImageType.Menu, image.FullName); } // Backdrop Image PopulateBackdrops(item, args); // Screenshot Image image = GetImage(item, args, "screenshot"); var screenshotFiles = new List <string>(); if (image != null) { screenshotFiles.Add(image.FullName); } var unfound = 0; for (var i = 1; i <= 20; i++) { // Screenshot Image image = GetImage(item, args, "screenshot" + i); if (image != null) { screenshotFiles.Add(image.FullName); } else { unfound++; if (unfound >= 3) { break; } } } if (screenshotFiles.Count > 0) { item.ScreenshotImagePaths = screenshotFiles; } }
protected override TVideoType ResolveVideo <TVideoType>(ItemResolveArgs args, bool parseName) => new ();
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>`0.</returns> protected override T Resolve(ItemResolveArgs args) { return(ResolveVideo <T>(args, false)); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>Episode.</returns> protected override Episode Resolve(ItemResolveArgs args) { var parent = args.Parent; if (parent == null) { return(null); } var season = parent as Season; // Just in case the user decided to nest episodes. // Not officially supported but in some cases we can handle it. if (season == null) { season = parent.Parents.OfType <Season>().FirstOrDefault(); } // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something if (season != null || parent is Series || parent.Parents.OfType <Series>().Any()) { Episode episode = null; if (args.IsDirectory) { if (args.ContainsFileSystemEntryByName("video_ts")) { episode = new Episode { Path = args.Path, VideoType = VideoType.Dvd }; } if (args.ContainsFileSystemEntryByName("bdmv")) { episode = new Episode { Path = args.Path, VideoType = VideoType.BluRay }; } } if (episode == null) { episode = base.Resolve(args); } if (episode != null) { // The base video resolver is going to fill these in, so null them out episode.ProductionYear = null; episode.Name = null; if (season != null) { episode.ParentIndexNumber = season.IndexNumber; } if (episode.ParentIndexNumber == null) { episode.ParentIndexNumber = SeriesResolver.GetSeasonNumberFromEpisodeFile(args.Path); } } return(episode); } return(null); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>`0.</returns> public virtual T Resolve(ItemResolveArgs args) { return(null); }
/// <summary> /// Gets the filtered file system entries. /// </summary> /// <param name="path">The path.</param> /// <param name="logger">The logger.</param> /// <param name="args">The args.</param> /// <param name="searchPattern">The search pattern.</param> /// <param name="flattenFolderDepth">The flatten folder depth.</param> /// <param name="resolveShortcuts">if set to <c>true</c> [resolve shortcuts].</param> /// <returns>Dictionary{System.StringFileSystemInfo}.</returns> /// <exception cref="System.ArgumentNullException">path</exception> public static Dictionary <string, FileSystemInfo> GetFilteredFileSystemEntries(string path, ILogger logger, ItemResolveArgs args, string searchPattern = "*", int flattenFolderDepth = 0, bool resolveShortcuts = true) { if (string.IsNullOrEmpty(path)) { throw new ArgumentNullException("path"); } if (args == null) { throw new ArgumentNullException("args"); } var entries = new DirectoryInfo(path).EnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly); if (!resolveShortcuts && flattenFolderDepth == 0) { // Seeing dupes on some users file system for some reason return(entries .DistinctBy(i => i.FullName, StringComparer.OrdinalIgnoreCase) .ToDictionary(i => i.FullName, StringComparer.OrdinalIgnoreCase)); } var dict = new Dictionary <string, FileSystemInfo>(StringComparer.OrdinalIgnoreCase); foreach (var entry in entries) { var isDirectory = (entry.Attributes & FileAttributes.Directory) == FileAttributes.Directory; var fullName = entry.FullName; if (resolveShortcuts && FileSystem.IsShortcut(fullName)) { var newPath = FileSystem.ResolveShortcut(fullName); if (string.IsNullOrWhiteSpace(newPath)) { //invalid shortcut - could be old or target could just be unavailable logger.Warn("Encountered invalid shortcut: " + fullName); continue; } // Don't check if it exists here because that could return false for network shares. var data = new DirectoryInfo(newPath); // add to our physical locations args.AddAdditionalLocation(newPath); dict[newPath] = data; } else if (flattenFolderDepth > 0 && isDirectory) { foreach (var child in GetFilteredFileSystemEntries(fullName, logger, args, flattenFolderDepth: flattenFolderDepth - 1, resolveShortcuts: resolveShortcuts)) { dict[child.Key] = child.Value; } } else { dict[fullName] = entry; } } return(dict); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>Series.</returns> protected override Series Resolve(ItemResolveArgs args) { if (args.IsDirectory) { if (args.HasParent <Series>() || args.HasParent <Season>()) { return(null); } var collectionType = args.GetCollectionType(); if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase)) { //if (args.ContainsFileSystemEntryByName("tvshow.nfo")) //{ // return new Series // { // Path = args.Path, // Name = Path.GetFileName(args.Path) // }; //} 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 (string.IsNullOrEmpty(collectionType)) { if (args.ContainsFileSystemEntryByName("tvshow.nfo")) { if (args.Parent != null && args.Parent.IsRoot) { // For now, return null, but if we want to allow this in the future then add some additional checks to guard against a misplaced tvshow.nfo return(null); } return(new Series { Path = args.Path, Name = Path.GetFileName(args.Path) }); } if (args.Parent != null && 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); }
/// <summary> /// Finds a movie based on a child file system entries /// </summary> /// <typeparam name="T"></typeparam> /// <param name="path">The path.</param> /// <param name="parent">The parent.</param> /// <param name="fileSystemEntries">The file system entries.</param> /// <param name="directoryService">The directory service.</param> /// <param name="supportMultiFileItems">if set to <c>true</c> [support multi file items].</param> /// <returns>Movie.</returns> private T FindMovie <T>(string path, Folder parent, IEnumerable <FileSystemInfo> fileSystemEntries, IDirectoryService directoryService, bool supportMultiFileItems, bool supportsMultipleSources) where T : Video, new() { var movies = new List <T>(); var multiDiscFolders = new List <FileSystemInfo>(); // Loop through each child file/folder and see if we find a video foreach (var child in fileSystemEntries) { var filename = child.Name; if ((child.Attributes & FileAttributes.Directory) == FileAttributes.Directory) { if (IsDvdDirectory(filename)) { return(new T { Path = path, VideoType = VideoType.Dvd }); } if (IsBluRayDirectory(filename)) { return(new T { Path = path, VideoType = VideoType.BluRay }); } if (EntityResolutionHelper.IsMultiPartFolder(filename)) { multiDiscFolders.Add(child); } continue; } // Don't misidentify xbmc trailers as a movie if (filename.IndexOf(BaseItem.XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) != -1) { continue; } var childArgs = new ItemResolveArgs(_applicationPaths, _libraryManager, directoryService) { FileInfo = child, Path = child.FullName, Parent = parent }; var item = ResolveVideo <T>(childArgs); if (item != null) { item.IsInMixedFolder = false; movies.Add(item); } } if (movies.Count > 1) { if (supportMultiFileItems) { var result = GetMultiFileMovie(movies); if (result != null) { return(result); } } if (supportsMultipleSources) { var result = GetMovieWithMultipleSources(movies); if (result != null) { return(result); } } return(null); } if (movies.Count == 1) { return(movies[0]); } if (multiDiscFolders.Count > 0) { var folders = fileSystemEntries.Where(child => (child.Attributes & FileAttributes.Directory) == FileAttributes.Directory); return(GetMultiDiscMovie <T>(multiDiscFolders, folders)); } return(null); }
/// <summary> /// Finds a movie based on a child file system entries /// </summary> /// <typeparam name="T"></typeparam> /// <returns>Movie.</returns> private T FindMovie <T>(ItemResolveArgs args, string path, Folder parent, List <FileSystemMetadata> fileSystemEntries, IDirectoryService directoryService, string collectionType, bool parseName) where T : Video, new() { var multiDiscFolders = new List <FileSystemMetadata>(); var libraryOptions = args.GetLibraryOptions(); var supportPhotos = string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase) && libraryOptions.EnablePhotos; var photos = new List <FileSystemMetadata>(); // Search for a folder rip foreach (var child in fileSystemEntries) { var filename = child.Name; if (child.IsDirectory) { if (IsDvdDirectory(child.FullName, filename, directoryService)) { var movie = new T { Path = path, VideoType = VideoType.Dvd }; Set3DFormat(movie); return(movie); } if (IsBluRayDirectory(child.FullName, filename, directoryService)) { var movie = new T { Path = path, VideoType = VideoType.BluRay }; Set3DFormat(movie); return(movie); } multiDiscFolders.Add(child); } else if (IsDvdFile(filename)) { var movie = new T { Path = path, VideoType = VideoType.Dvd }; Set3DFormat(movie); return(movie); } else if (supportPhotos && PhotoResolver.IsImageFile(child.FullName, _imageProcessor)) { photos.Add(child); } } // TODO: Allow GetMultiDiscMovie in here var supportsMultiVersion = true; var result = ResolveVideos <T>(parent, fileSystemEntries, directoryService, supportsMultiVersion, collectionType, parseName) ?? new MultiItemResolverResult(); if (result.Items.Count == 1) { var videoPath = result.Items[0].Path; var hasPhotos = photos.Any(i => !PhotoResolver.IsOwnedByResolvedMedia(LibraryManager, libraryOptions, videoPath, i.Name)); if (!hasPhotos) { var movie = (T)result.Items[0]; movie.IsInMixedFolder = false; movie.Name = Path.GetFileName(movie.ContainingFolderPath); return(movie); } } if (result.Items.Count == 0 && multiDiscFolders.Count > 0) { return(GetMultiDiscMovie <T>(multiDiscFolders, directoryService)); } return(null); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>Video.</returns> protected override Video Resolve(ItemResolveArgs args) { // Avoid expensive tests against VF's and all their children by not allowing this if (args.Parent != null) { if (args.Parent.IsRoot) { return(null); } } var isDirectory = args.IsDirectory; if (isDirectory) { // Since the looping is expensive, this is an optimization to help us avoid it if (args.ContainsMetaFileByName("series.xml")) { return(null); } } var collectionType = args.GetCollectionType(); // Find movies with their own folders if (isDirectory) { if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <Trailer>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false, false)); } if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <MusicVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, false, false)); } if (string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <AdultVideo>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true, false)); } if (string.Equals(collectionType, CollectionType.HomeVideos, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <Video>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true, false)); } if (string.IsNullOrEmpty(collectionType) || string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) || string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase)) { return(FindMovie <Movie>(args.Path, args.Parent, args.FileSystemChildren, args.DirectoryService, true, true)); } return(null); } var filename = Path.GetFileName(args.Path); // Don't misidentify xbmc trailers as a movie if (filename.IndexOf(BaseItem.XbmcTrailerFileSuffix, StringComparison.OrdinalIgnoreCase) != -1) { return(null); } // Find movies that are mixed in the same folder if (string.Equals(collectionType, CollectionType.Trailers, StringComparison.OrdinalIgnoreCase)) { return(ResolveVideo <Trailer>(args)); } Video item = null; if (string.Equals(collectionType, CollectionType.MusicVideos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <MusicVideo>(args); } if (string.Equals(collectionType, CollectionType.AdultVideos, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <AdultVideo>(args); } // To find a movie file, the collection type must be movies or boxsets // Otherwise we'll consider it a plain video and let the video resolver handle it if (string.Equals(collectionType, CollectionType.Movies, StringComparison.OrdinalIgnoreCase) || string.Equals(collectionType, CollectionType.BoxSets, StringComparison.OrdinalIgnoreCase)) { item = ResolveVideo <Movie>(args); } if (item != null) { item.IsInMixedFolder = true; } return(item); }
/// <summary> /// Sets the initial item values. /// </summary> /// <param name="item">The item.</param> /// <param name="args">The args.</param> protected override void SetInitialItemValues(Movie item, ItemResolveArgs args) { base.SetInitialItemValues(item, args); SetProviderIdFromPath(item); }
/// <summary> /// Resolves the specified args. /// </summary> /// <param name="args">The args.</param> /// <returns>Game.</returns> protected override Game Resolve(ItemResolveArgs args) { return(null); }