From 11c37780531791a898afd36bc186b4b60d1dce9b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 15 Aug 2013 15:09:52 -0400 Subject: [PATCH] completed multiple movie in folder support --- MediaBrowser.Controller/Entities/BaseItem.cs | 2 + MediaBrowser.Controller/Entities/Game.cs | 18 +-- MediaBrowser.Controller/Entities/Video.cs | 2 - .../ImageFromMediaLocationProvider.cs | 137 +++++++++++++----- .../ImageFromMixedMediaLocationProvider.cs | 95 ------------ .../ImagesByNameProvider.cs | 3 +- .../MediaBrowser.Providers.csproj | 1 - .../Providers/ImageSaver.cs | 23 +-- 8 files changed, 119 insertions(+), 162 deletions(-) delete mode 100644 MediaBrowser.Providers/ImageFromMixedMediaLocationProvider.cs diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 87aa471ea8..cc2e82b1f0 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -55,6 +55,8 @@ namespace MediaBrowser.Controller.Entities public const string ThemeVideosFolderName = "backdrops"; public const string XbmcTrailerFileSuffix = "-trailer"; + public bool IsInMixedFolder { get; set; } + private string _name; /// /// Gets or sets the name. diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index 63a04e5207..9a787b3d38 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -24,11 +24,6 @@ namespace MediaBrowser.Controller.Entities /// The game system. public string GameSystem { get; set; } - /// - /// Returns true if the game is combined with other games in the same folder - /// - public bool IsInMixedFolder { get; set; } - /// /// /// @@ -36,18 +31,7 @@ namespace MediaBrowser.Controller.Entities { get { - var directoryName = System.IO.Path.GetDirectoryName(Path); - - if (IsInMixedFolder) - { - // It's a file - var baseMetaPath = System.IO.Path.Combine(directoryName, "metadata"); - var fileName = System.IO.Path.GetFileNameWithoutExtension(Path); - - return fileName != null ? System.IO.Path.Combine(baseMetaPath, fileName) : null; - } - - return directoryName; + return System.IO.Path.GetDirectoryName(Path); } } diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 8bc519a437..e8896db6fe 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -65,8 +65,6 @@ namespace MediaBrowser.Controller.Entities return GetPlayableStreamFiles(Path); } - public bool IsInMixedFolder { get; set; } - /// /// Should be overridden to return the proper folder where metadata lives /// diff --git a/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs b/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs index bbd8a784e1..9c991a496f 100644 --- a/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs +++ b/MediaBrowser.Providers/ImageFromMediaLocationProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; @@ -38,7 +39,16 @@ namespace MediaBrowser.Providers /// true if XXXX, false otherwise public override bool Supports(BaseItem item) { - return item.LocationType == LocationType.FileSystem && item.ResolveArgs.IsDirectory; + if (item.LocationType == LocationType.FileSystem) + { + if (item.ResolveArgs.IsDirectory) + { + return true; + } + + return item.IsInMixedFolder && !(item is Episode); + } + return false; } /// @@ -85,34 +95,48 @@ namespace MediaBrowser.Providers { cancellationToken.ThrowIfCancellationRequested(); + var args = GetResolveArgsContainingImages(item); + // Make sure current image paths still exist - ValidateImages(item); + ValidateImages(item, args); cancellationToken.ThrowIfCancellationRequested(); // Make sure current backdrop paths still exist - ValidateBackdrops(item); + ValidateBackdrops(item, args); + ValidateScreenshots(item, args); cancellationToken.ThrowIfCancellationRequested(); - PopulateBaseItemImages(item); + PopulateBaseItemImages(item, args); SetLastRefreshed(item, DateTime.UtcNow); return TrueTaskResult; } + private ItemResolveArgs GetResolveArgsContainingImages(BaseItem item) + { + if (item.IsInMixedFolder) + { + return item.Parent.ResolveArgs; + } + + return item.ResolveArgs; + } + /// /// Validates that images within the item are still on the file system /// /// The item. - private void ValidateImages(BaseItem item) + /// The args. + private void ValidateImages(BaseItem item, ItemResolveArgs args) { // Only validate paths from the same directory - need to copy to a list because we are going to potentially modify the collection below var deletedKeys = item.Images.ToList().Where(image => { var path = image.Value; - return IsInMetaLocation(item, path) && item.ResolveArgs.GetMetaFileByPath(path) == null; + return IsInMetaLocation(item, path) && args.GetMetaFileByPath(path) == null; }).Select(i => i.Key).ToList(); @@ -127,20 +151,33 @@ namespace MediaBrowser.Providers /// Validates that backdrops within the item are still on the file system /// /// The item. - private void ValidateBackdrops(BaseItem item) + /// The args. + private void ValidateBackdrops(BaseItem item, ItemResolveArgs args) { - if (item.BackdropImagePaths == null) + // Only validate paths from the same directory - need to copy to a list because we are going to potentially modify the collection below + var deletedImages = item.BackdropImagePaths.Where(path => IsInMetaLocation(item, path) && args.GetMetaFileByPath(path) == null).ToList(); + + // Now remove them from the dictionary + foreach (var path in deletedImages) { - return; + item.BackdropImagePaths.Remove(path); } + } + /// + /// Validates the screenshots. + /// + /// The item. + /// The args. + private void ValidateScreenshots(BaseItem item, ItemResolveArgs args) + { // Only validate paths from the same directory - need to copy to a list because we are going to potentially modify the collection below - var deletedImages = item.BackdropImagePaths.Where(path => IsInMetaLocation(item, path) && item.ResolveArgs.GetMetaFileByPath(path) == null).ToList(); + var deletedImages = item.ScreenshotImagePaths.Where(path => IsInMetaLocation(item, path) && args.GetMetaFileByPath(path) == null).ToList(); // Now remove them from the dictionary foreach (var path in deletedImages) { - item.BackdropImagePaths.Remove(path); + item.ScreenshotImagePaths.Remove(path); } } @@ -159,24 +196,48 @@ namespace MediaBrowser.Providers /// Gets the image. /// /// The item. + /// The args. /// The filename without extension. /// FileSystemInfo. - protected virtual FileSystemInfo GetImage(BaseItem item, string filenameWithoutExtension) + 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); + } + + protected virtual string GetFullImagePath(BaseItem item, ItemResolveArgs args, string filenameWithoutExtension, string extension) { - return BaseItem.SupportedImageExtensions.Select(i => item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.ResolveArgs.Path, filenameWithoutExtension + i))).FirstOrDefault(i => i != null); + var path = item.MetaLocation; + + if (item.IsInMixedFolder) + { + var pathFilenameWithoutExtension = Path.GetFileNameWithoutExtension(item.Path); + + // If the image filename and path file name match, just look for an image using the same full path as the item + if (string.Equals(pathFilenameWithoutExtension, filenameWithoutExtension)) + { + return Path.ChangeExtension(item.Path, extension); + } + + return Path.Combine(path, pathFilenameWithoutExtension + "-" + filenameWithoutExtension + extension); + } + + return Path.Combine(path, filenameWithoutExtension + extension); } /// /// Fills in image paths based on files win the folder /// /// The item. - private void PopulateBaseItemImages(BaseItem item) + /// The args. + private void PopulateBaseItemImages(BaseItem item, ItemResolveArgs args) { // Primary Image - var image = GetImage(item, "folder") ?? - GetImage(item, "poster") ?? - GetImage(item, "cover") ?? - GetImage(item, "default"); + 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) @@ -185,7 +246,7 @@ namespace MediaBrowser.Providers if (!string.IsNullOrEmpty(name)) { - image = GetImage(item, name); + image = GetImage(item, args, name); } } @@ -195,7 +256,7 @@ namespace MediaBrowser.Providers } // Logo Image - image = GetImage(item, "logo"); + image = GetImage(item, args, "logo"); if (image != null) { @@ -203,7 +264,7 @@ namespace MediaBrowser.Providers } // Banner Image - image = GetImage(item, "banner"); + image = GetImage(item, args, "banner"); if (image != null) { @@ -211,7 +272,7 @@ namespace MediaBrowser.Providers } // Clearart - image = GetImage(item, "clearart"); + image = GetImage(item, args, "clearart"); if (image != null) { @@ -219,7 +280,7 @@ namespace MediaBrowser.Providers } // Disc - image = GetImage(item, "disc"); + image = GetImage(item, args, "disc"); if (image != null) { @@ -227,7 +288,7 @@ namespace MediaBrowser.Providers } // Thumbnail Image - image = GetImage(item, "thumb"); + image = GetImage(item, args, "thumb"); if (image != null) { @@ -235,7 +296,7 @@ namespace MediaBrowser.Providers } // Box Image - image = GetImage(item, "box"); + image = GetImage(item, args, "box"); if (image != null) { @@ -243,7 +304,7 @@ namespace MediaBrowser.Providers } // BoxRear Image - image = GetImage(item, "boxrear"); + image = GetImage(item, args, "boxrear"); if (image != null) { @@ -251,7 +312,7 @@ namespace MediaBrowser.Providers } // Thumbnail Image - image = GetImage(item, "menu"); + image = GetImage(item, args, "menu"); if (image != null) { @@ -259,10 +320,10 @@ namespace MediaBrowser.Providers } // Backdrop Image - PopulateBackdrops(item); + PopulateBackdrops(item, args); // Screenshot Image - image = GetImage(item, "screenshot"); + image = GetImage(item, args, "screenshot"); var screenshotFiles = new List(); @@ -275,7 +336,7 @@ namespace MediaBrowser.Providers for (var i = 1; i <= 20; i++) { // Screenshot Image - image = GetImage(item, "screenshot" + i); + image = GetImage(item, args, "screenshot" + i); if (image != null) { @@ -302,15 +363,16 @@ namespace MediaBrowser.Providers /// Populates the backdrops. /// /// The item. - private void PopulateBackdrops(BaseItem item) + /// The args. + private void PopulateBackdrops(BaseItem item, ItemResolveArgs args) { var backdropFiles = new List(); - PopulateBackdrops(item, backdropFiles, "backdrop", "backdrop"); + PopulateBackdrops(item, args, backdropFiles, "backdrop", "backdrop"); // Support plex/xbmc conventions - PopulateBackdrops(item, backdropFiles, "fanart", "fanart-"); - PopulateBackdrops(item, backdropFiles, "background", "background-"); + PopulateBackdrops(item, args, backdropFiles, "fanart", "fanart-"); + PopulateBackdrops(item, args, backdropFiles, "background", "background-"); if (backdropFiles.Count > 0) { @@ -322,12 +384,13 @@ namespace MediaBrowser.Providers /// Populates the backdrops. /// /// The item. + /// The args. /// The backdrop files. /// The filename. /// The numbered suffix. - private void PopulateBackdrops(BaseItem item, List backdropFiles, string filename, string numberedSuffix) + private void PopulateBackdrops(BaseItem item, ItemResolveArgs args, List backdropFiles, string filename, string numberedSuffix) { - var image = GetImage(item, filename); + var image = GetImage(item, args, filename); if (image != null) { @@ -338,7 +401,7 @@ namespace MediaBrowser.Providers for (var i = 1; i <= 20; i++) { // Backdrop Image - image = GetImage(item, numberedSuffix + i); + image = GetImage(item, args, numberedSuffix + i); if (image != null) { diff --git a/MediaBrowser.Providers/ImageFromMixedMediaLocationProvider.cs b/MediaBrowser.Providers/ImageFromMixedMediaLocationProvider.cs deleted file mode 100644 index 1539c9ddca..0000000000 --- a/MediaBrowser.Providers/ImageFromMixedMediaLocationProvider.cs +++ /dev/null @@ -1,95 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers -{ - class ImageFromMixedMediaLocationProvider : BaseMetadataProvider - { - public ImageFromMixedMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager) - : base(logManager, configurationManager) - { - } - - public override ItemUpdateType ItemUpdateType - { - get - { - return ItemUpdateType.ImageUpdate; - } - } - - /// - /// Supportses the specified item. - /// - /// The item. - /// true if XXXX, false otherwise - public override bool Supports(BaseItem item) - { - if (item.LocationType != LocationType.FileSystem || item.ResolveArgs.IsDirectory) - { - return false; - } - - var video = item as Video; - - if (video != null && !(item is Episode)) - { - return video.IsInMixedFolder; - } - - var game = item as Game; - - if (game != null) - { - return game.IsInMixedFolder; - } - - return false; - } - - /// - /// Gets the priority. - /// - /// The priority. - public override MetadataProviderPriority Priority - { - get { return MetadataProviderPriority.First; } - } - - /// - /// Returns true or false indicating if the provider should refresh when the contents of it's directory changes - /// - /// true if [refresh on file system stamp change]; otherwise, false. - protected override bool RefreshOnFileSystemStampChange - { - get - { - return true; - } - } - - /// - /// Gets the filestamp extensions. - /// - /// The filestamp extensions. - protected override string[] FilestampExtensions - { - get - { - return BaseItem.SupportedImageExtensions; - } - } - - public override Task FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken) - { - return TrueTaskResult; - } - } -} diff --git a/MediaBrowser.Providers/ImagesByNameProvider.cs b/MediaBrowser.Providers/ImagesByNameProvider.cs index 228ca94c58..e4bfee6e33 100644 --- a/MediaBrowser.Providers/ImagesByNameProvider.cs +++ b/MediaBrowser.Providers/ImagesByNameProvider.cs @@ -159,9 +159,10 @@ namespace MediaBrowser.Providers /// Gets the image. /// /// The item. + /// The args. /// The filename without extension. /// FileSystemInfo. - protected override FileSystemInfo GetImage(BaseItem item, string filenameWithoutExtension) + protected override FileSystemInfo GetImage(BaseItem item, ItemResolveArgs args, string filenameWithoutExtension) { var location = GetLocation(item); diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 1b429890a0..28e6173789 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -52,7 +52,6 @@ - diff --git a/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs b/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs index 4a3e7e7a60..cbdec63c8d 100644 --- a/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs +++ b/MediaBrowser.Server.Implementations/Providers/ImageSaver.cs @@ -242,16 +242,9 @@ namespace MediaBrowser.Server.Implementations.Providers if (saveLocally) { - if (!(item is Episode)) + if (item.IsInMixedFolder && !(item is Episode)) { - var video = item as Video; - - if (video != null && video.IsInMixedFolder) - { - var folder = Path.GetDirectoryName(video.Path); - - path = Path.Combine(folder, Path.GetFileNameWithoutExtension(video.Path) + "-" + filename); - } + path = GetSavePathForItemInMixedFolder(item, type, filename, extension); } if (string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(item.MetaLocation)) @@ -260,6 +253,7 @@ namespace MediaBrowser.Server.Implementations.Providers } } + // None of the save local conditions passed, so store it in our internal folders if (string.IsNullOrEmpty(path)) { path = _remoteImageCache.GetResourcePath(item.GetType().FullName + item.Id, filename); @@ -274,5 +268,16 @@ namespace MediaBrowser.Server.Implementations.Providers return path; } + + private string GetSavePathForItemInMixedFolder(BaseItem item, ImageType type, string imageFilename, string extension) + { + if (type == ImageType.Primary) + { + return Path.ChangeExtension(item.Path, extension); + } + var folder = Path.GetDirectoryName(item.Path); + + return Path.Combine(folder, Path.GetFileNameWithoutExtension(item.Path) + "-" + imageFilename); + } } }