diff options
83 files changed, 1353 insertions, 965 deletions
diff --git a/MediaBrowser.Api/ConfigurationService.cs b/MediaBrowser.Api/ConfigurationService.cs new file mode 100644 index 000000000..206d0c265 --- /dev/null +++ b/MediaBrowser.Api/ConfigurationService.cs @@ -0,0 +1,110 @@ +using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Serialization; +using ServiceStack; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Api +{ + /// <summary> + /// Class GetConfiguration + /// </summary> + [Route("/System/Configuration", "GET")] + [Api(("Gets application configuration"))] + public class GetConfiguration : IReturn<ServerConfiguration> + { + + } + + /// <summary> + /// Class UpdateConfiguration + /// </summary> + [Route("/System/Configuration", "POST")] + [Api(("Updates application configuration"))] + public class UpdateConfiguration : ServerConfiguration, IReturnVoid + { + } + + [Route("/System/Configuration/MetadataOptions/Default", "GET")] + [Api(("Gets a default MetadataOptions object"))] + public class GetDefaultMetadataOptions : IReturn<MetadataOptions> + { + + } + + [Route("/System/Configuration/MetadataPlugins", "GET")] + [Api(("Gets all available metadata plugins"))] + public class GetMetadataPlugins : IReturn<List<MetadataPluginSummary>> + { + + } + + public class ConfigurationService : BaseApiService + { + /// <summary> + /// The _json serializer + /// </summary> + private readonly IJsonSerializer _jsonSerializer; + + /// <summary> + /// The _configuration manager + /// </summary> + private readonly IServerConfigurationManager _configurationManager; + + private readonly IFileSystem _fileSystem; + private readonly IProviderManager _providerManager; + + public ConfigurationService(IJsonSerializer jsonSerializer, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IProviderManager providerManager) + { + _jsonSerializer = jsonSerializer; + _configurationManager = configurationManager; + _fileSystem = fileSystem; + _providerManager = providerManager; + } + + /// <summary> + /// Gets the specified request. + /// </summary> + /// <param name="request">The request.</param> + /// <returns>System.Object.</returns> + public object Get(GetConfiguration request) + { + var configPath = _configurationManager.ApplicationPaths.SystemConfigurationFilePath; + + var dateModified = _fileSystem.GetLastWriteTimeUtc(configPath); + + var cacheKey = (configPath + dateModified.Ticks).GetMD5(); + + return ToOptimizedResultUsingCache(cacheKey, dateModified, null, () => _configurationManager.Configuration); + } + + /// <summary> + /// Posts the specified configuraiton. + /// </summary> + /// <param name="request">The request.</param> + public void Post(UpdateConfiguration request) + { + // Silly, but we need to serialize and deserialize or the XmlSerializer will write the xml with an element name of UpdateConfiguration + + var json = _jsonSerializer.SerializeToString(request); + + var config = _jsonSerializer.DeserializeFromString<ServerConfiguration>(json); + + _configurationManager.ReplaceConfiguration(config); + } + + public object Get(GetDefaultMetadataOptions request) + { + return ToOptimizedResult(new MetadataOptions()); + } + + public object Get(GetMetadataPlugins request) + { + return ToOptimizedResult(_providerManager.GetAllMetadataPlugins().ToList()); + } + } +} diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index f4b68810b..e105b41ce 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -72,6 +72,7 @@ </Compile> <Compile Include="AlbumsService.cs" /> <Compile Include="BaseApiService.cs" /> + <Compile Include="ConfigurationService.cs" /> <Compile Include="DefaultTheme\DefaultThemeService.cs" /> <Compile Include="DefaultTheme\Models.cs" /> <Compile Include="DisplayPreferencesService.cs" /> diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 9c5acb7a0..c975d7e31 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -161,7 +161,7 @@ namespace MediaBrowser.Api.Playback.Progressive if (!string.IsNullOrEmpty(contentFeatures)) { - responseHeaders["ContentFeatures.DLNA.ORG"] = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); + responseHeaders["contentFeatures.dlna.org"] = (contentFeatures + orgOp + orgCi + dlnaflags).Trim(';'); } foreach (var item in responseHeaders) diff --git a/MediaBrowser.Api/SystemService.cs b/MediaBrowser.Api/SystemService.cs index 23d64e89b..9f5f3716e 100644 --- a/MediaBrowser.Api/SystemService.cs +++ b/MediaBrowser.Api/SystemService.cs @@ -1,14 +1,6 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Serialization; +using MediaBrowser.Controller; using MediaBrowser.Model.System; using ServiceStack; -using System; -using System.IO; using System.Threading.Tasks; namespace MediaBrowser.Api @@ -39,70 +31,24 @@ namespace MediaBrowser.Api } /// <summary> - /// Class GetConfiguration - /// </summary> - [Route("/System/Configuration", "GET")] - [Api(("Gets application configuration"))] - public class GetConfiguration : IReturn<ServerConfiguration> - { - - } - - /// <summary> - /// Class UpdateConfiguration - /// </summary> - [Route("/System/Configuration", "POST")] - [Api(("Updates application configuration"))] - public class UpdateConfiguration : ServerConfiguration, IReturnVoid - { - } - - /// <summary> /// Class SystemInfoService /// </summary> public class SystemService : BaseApiService { /// <summary> - /// The _json serializer - /// </summary> - private readonly IJsonSerializer _jsonSerializer; - - /// <summary> /// The _app host /// </summary> private readonly IServerApplicationHost _appHost; - /// <summary> - /// The _configuration manager - /// </summary> - private readonly IServerConfigurationManager _configurationManager; - - private readonly IFileSystem _fileSystem; - /// <summary> /// Initializes a new instance of the <see cref="SystemService" /> class. /// </summary> - /// <param name="jsonSerializer">The json serializer.</param> /// <param name="appHost">The app host.</param> - /// <param name="configurationManager">The configuration manager.</param> /// <exception cref="System.ArgumentNullException">jsonSerializer</exception> - public SystemService(IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IServerConfigurationManager configurationManager, IFileSystem fileSystem) - : base() + public SystemService(IServerApplicationHost appHost) { - if (jsonSerializer == null) - { - throw new ArgumentNullException("jsonSerializer"); - } - if (appHost == null) - { - throw new ArgumentNullException("appHost"); - } - _appHost = appHost; - _configurationManager = configurationManager; - _fileSystem = fileSystem; - _jsonSerializer = jsonSerializer; } /// <summary> @@ -118,22 +64,6 @@ namespace MediaBrowser.Api } /// <summary> - /// Gets the specified request. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>System.Object.</returns> - public object Get(GetConfiguration request) - { - var configPath = _configurationManager.ApplicationPaths.SystemConfigurationFilePath; - - var dateModified = _fileSystem.GetLastWriteTimeUtc(configPath); - - var cacheKey = (configPath + dateModified.Ticks).GetMD5(); - - return ToOptimizedResultUsingCache(cacheKey, dateModified, null, () => _configurationManager.Configuration); - } - - /// <summary> /// Posts the specified request. /// </summary> /// <param name="request">The request.</param> @@ -159,19 +89,5 @@ namespace MediaBrowser.Api }); } - /// <summary> - /// Posts the specified configuraiton. - /// </summary> - /// <param name="request">The request.</param> - public void Post(UpdateConfiguration request) - { - // Silly, but we need to serialize and deserialize or the XmlSerializer will write the xml with an element name of UpdateConfiguration - - var json = _jsonSerializer.SerializeToString(request); - - var config = _jsonSerializer.DeserializeFromString<ServerConfiguration>(json); - - _configurationManager.ReplaceConfiguration(config); - } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index f12532204..d9579d79f 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -34,7 +34,6 @@ namespace MediaBrowser.Controller.Entities Images = new Dictionary<ImageType, string>(); ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); LockedFields = new List<MetadataFields>(); - ImageSources = new List<ImageSourceInfo>(); } /// <summary> @@ -475,12 +474,6 @@ namespace MediaBrowser.Controller.Entities public List<string> BackdropImagePaths { get; set; } /// <summary> - /// Gets or sets the backdrop image sources. - /// </summary> - /// <value>The backdrop image sources.</value> - public List<ImageSourceInfo> ImageSources { get; set; } - - /// <summary> /// Gets or sets the official rating. /// </summary> /// <value>The official rating.</value> @@ -1458,8 +1451,6 @@ namespace MediaBrowser.Controller.Entities BackdropImagePaths.Remove(file); - RemoveImageSourceForPath(file); - // Delete the source file DeleteImagePath(file); } @@ -1567,8 +1558,6 @@ namespace MediaBrowser.Controller.Entities { BackdropImagePaths.Remove(path); - RemoveImageSourceForPath(path); - changed = true; } @@ -1576,80 +1565,6 @@ namespace MediaBrowser.Controller.Entities } /// <summary> - /// Adds the image source. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="url">The URL.</param> - public void AddImageSource(string path, string url) - { - RemoveImageSourceForPath(path); - - var pathMd5 = path.ToLower().GetMD5(); - - ImageSources.Add(new ImageSourceInfo - { - ImagePathMD5 = pathMd5, - ImageUrlMD5 = url.ToLower().GetMD5() - }); - } - - /// <summary> - /// Gets the image source info. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>ImageSourceInfo.</returns> - public ImageSourceInfo GetImageSourceInfo(string path) - { - if (ImageSources.Count == 0) - { - return null; - } - - var pathMd5 = path.ToLower().GetMD5(); - - return ImageSources.FirstOrDefault(i => i.ImagePathMD5 == pathMd5); - } - - /// <summary> - /// Removes the image source for path. - /// </summary> - /// <param name="path">The path.</param> - public void RemoveImageSourceForPath(string path) - { - if (ImageSources.Count == 0) - { - return; - } - - var pathMd5 = path.ToLower().GetMD5(); - - // Remove existing - foreach (var entry in ImageSources - .Where(i => i.ImagePathMD5 == pathMd5) - .ToList()) - { - ImageSources.Remove(entry); - } - } - - /// <summary> - /// Determines whether [contains image with source URL] [the specified URL]. - /// </summary> - /// <param name="url">The URL.</param> - /// <returns><c>true</c> if [contains image with source URL] [the specified URL]; otherwise, <c>false</c>.</returns> - public bool ContainsImageWithSourceUrl(string url) - { - if (ImageSources.Count == 0) - { - return false; - } - - var md5 = url.ToLower().GetMD5(); - - return ImageSources.Any(i => i.ImageUrlMD5 == md5); - } - - /// <summary> /// Validates the screenshots. /// </summary> private bool ValidateScreenshots() diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs index 18e6afcd1..1aa299c2a 100644 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ b/MediaBrowser.Controller/Entities/IHasImages.cs @@ -99,13 +99,6 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The backdrop image paths.</value> List<string> BackdropImagePaths { get; set; } - - /// <summary> - /// Determines whether [contains image with source URL] [the specified URL]. - /// </summary> - /// <param name="url">The URL.</param> - /// <returns><c>true</c> if [contains image with source URL] [the specified URL]; otherwise, <c>false</c>.</returns> - bool ContainsImageWithSourceUrl(string url); } public static class HasImagesExtensions diff --git a/MediaBrowser.Controller/Entities/IHasScreenshots.cs b/MediaBrowser.Controller/Entities/IHasScreenshots.cs index 70d154a95..341d6403f 100644 --- a/MediaBrowser.Controller/Entities/IHasScreenshots.cs +++ b/MediaBrowser.Controller/Entities/IHasScreenshots.cs @@ -12,12 +12,5 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The screenshot image paths.</value> List<string> ScreenshotImagePaths { get; set; } - - /// <summary> - /// Determines whether [contains image with source URL] [the specified URL]. - /// </summary> - /// <param name="url">The URL.</param> - /// <returns><c>true</c> if [contains image with source URL] [the specified URL]; otherwise, <c>false</c>.</returns> - bool ContainsImageWithSourceUrl(string url); } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index c3a87fc31..d8ba019db 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -165,7 +165,6 @@ namespace MediaBrowser.Controller.Library /// <param name="prescanTasks">The prescan tasks.</param> /// <param name="postscanTasks">The postscan tasks.</param> /// <param name="peoplePrescanTasks">The people prescan tasks.</param> - /// <param name="savers">The savers.</param> void AddParts(IEnumerable<IResolverIgnoreRule> rules, IEnumerable<IVirtualFolderCreator> pluginFolders, IEnumerable<IItemResolver> resolvers, @@ -173,8 +172,7 @@ namespace MediaBrowser.Controller.Library IEnumerable<IBaseItemComparer> itemComparers, IEnumerable<ILibraryPrescanTask> prescanTasks, IEnumerable<ILibraryPostScanTask> postscanTasks, - IEnumerable<IPeoplePrescanTask> peoplePrescanTasks, - IEnumerable<IMetadataSaver> savers); + IEnumerable<IPeoplePrescanTask> peoplePrescanTasks); /// <summary> /// Sorts the specified items. @@ -301,14 +299,6 @@ namespace MediaBrowser.Controller.Library string FindCollectionType(BaseItem item); /// <summary> - /// Saves the metadata. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="updateType">Type of the update.</param> - /// <returns>Task.</returns> - Task SaveMetadata(BaseItem item, ItemUpdateType updateType); - - /// <summary> /// Gets all artists. /// </summary> /// <returns>IEnumerable{System.String}.</returns> diff --git a/MediaBrowser.Controller/Library/IMetadataSaver.cs b/MediaBrowser.Controller/Library/IMetadataSaver.cs index 15671af4d..0c75e7edc 100644 --- a/MediaBrowser.Controller/Library/IMetadataSaver.cs +++ b/MediaBrowser.Controller/Library/IMetadataSaver.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; using System.Threading; namespace MediaBrowser.Controller.Library @@ -9,19 +9,25 @@ namespace MediaBrowser.Controller.Library public interface IMetadataSaver { /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + string Name { get; } + + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - bool IsEnabledFor(BaseItem item, ItemUpdateType updateType); + bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType); /// <summary> /// Gets the save path. /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - string GetSavePath(BaseItem item); + string GetSavePath(IHasMetadata item); /// <summary> /// Saves the specified item. @@ -29,6 +35,6 @@ namespace MediaBrowser.Controller.Library /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - void Save(BaseItem item, CancellationToken cancellationToken); + void Save(IHasMetadata item, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index b05f14a13..6b4228524 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -143,6 +143,7 @@ <Compile Include="Notifications\NotificationUpdateEventArgs.cs" /> <Compile Include="Persistence\IFileOrganizationRepository.cs" /> <Compile Include="Persistence\MediaStreamQuery.cs" /> + <Compile Include="Providers\ICustomMetadataProvider.cs" /> <Compile Include="Providers\IDynamicInfoProvider.cs" /> <Compile Include="Providers\IHasMetadata.cs" /> <Compile Include="Providers\IImageProvider.cs" /> diff --git a/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs new file mode 100644 index 000000000..a53222b5a --- /dev/null +++ b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs @@ -0,0 +1,15 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public interface ICustomMetadataProvider : IMetadataProvider + { + } + + public interface ICustomMetadataProvider<TItemType> : IMetadataProvider<TItemType>, ICustomMetadataProvider + where TItemType : IHasMetadata + { + Task FetchAsync(TItemType item, CancellationToken cancellationToken); + } +} diff --git a/MediaBrowser.Controller/Providers/IHasMetadata.cs b/MediaBrowser.Controller/Providers/IHasMetadata.cs index 4ee54f69e..1e2a76b79 100644 --- a/MediaBrowser.Controller/Providers/IHasMetadata.cs +++ b/MediaBrowser.Controller/Providers/IHasMetadata.cs @@ -27,5 +27,11 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <value>The date last saved.</value> DateTime DateLastSaved { get; set; } + + /// <summary> + /// Determines whether [is save local metadata enabled]. + /// </summary> + /// <returns><c>true</c> if [is save local metadata enabled]; otherwise, <c>false</c>.</returns> + bool IsSaveLocalMetadataEnabled(); } } diff --git a/MediaBrowser.Controller/Providers/IMetadataService.cs b/MediaBrowser.Controller/Providers/IMetadataService.cs index e9ce320ab..c4314c15f 100644 --- a/MediaBrowser.Controller/Providers/IMetadataService.cs +++ b/MediaBrowser.Controller/Providers/IMetadataService.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.Threading; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Controller.Providers @@ -7,12 +6,6 @@ namespace MediaBrowser.Controller.Providers public interface IMetadataService { /// <summary> - /// Adds the parts. - /// </summary> - /// <param name="providers">The providers.</param> - void AddParts(IEnumerable<IMetadataProvider> providers); - - /// <summary> /// Determines whether this instance can refresh the specified item. /// </summary> /// <param name="item">The item.</param> @@ -23,10 +16,10 @@ namespace MediaBrowser.Controller.Providers /// Refreshes the metadata. /// </summary> /// <param name="item">The item.</param> - /// <param name="options">The options.</param> + /// <param name="refreshOptions">The options.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken); + Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken); /// <summary> /// Gets the order. diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 0159f778f..0e4f70c06 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -1,5 +1,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; using System.Collections.Generic; @@ -64,7 +65,9 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageProviders">The image providers.</param> /// <param name="metadataServices">The metadata services.</param> /// <param name="metadataProviders">The metadata providers.</param> - void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders); + /// <param name="savers">The savers.</param> + void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, + IEnumerable<IMetadataSaver> savers); /// <summary> /// Gets the available remote images. @@ -82,5 +85,19 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <returns>IEnumerable{ImageProviderInfo}.</returns> IEnumerable<ImageProviderInfo> GetImageProviderInfo(IHasImages item); + + /// <summary> + /// Gets all metadata plugins. + /// </summary> + /// <returns>IEnumerable{MetadataPlugin}.</returns> + IEnumerable<MetadataPluginSummary> GetAllMetadataPlugins(); + + /// <summary> + /// Saves the metadata. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="updateType">Type of the update.</param> + /// <returns>Task.</returns> + Task SaveMetadata(IHasMetadata item, ItemUpdateType updateType); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemId.cs b/MediaBrowser.Controller/Providers/ItemId.cs index 3abb64bfb..3dbaa78fa 100644 --- a/MediaBrowser.Controller/Providers/ItemId.cs +++ b/MediaBrowser.Controller/Providers/ItemId.cs @@ -51,4 +51,22 @@ namespace MediaBrowser.Controller.Providers /// <value>The artist music brainz identifier.</value> public string ArtistMusicBrainzId { get; set; } } + + public class GameId : ItemId + { + /// <summary> + /// Gets or sets the game system. + /// </summary> + /// <value>The game system.</value> + public string GameSystem { get; set; } + } + + public class GameSystemId : ItemId + { + /// <summary> + /// Gets or sets the path. + /// </summary> + /// <value>The path.</value> + public string Path { get; set; } + } } diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 04f95c4ff..d95c27efd 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -74,15 +74,21 @@ <Compile Include="..\MediaBrowser.Model\ApiClient\ServerEventArgs.cs"> <Link>ApiClient\ServerEventArgs.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\AutoOrganize.cs"> + <Link>Configuration\AutoOrganize.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\BaseApplicationConfiguration.cs"> <Link>Configuration\BaseApplicationConfiguration.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Configuration\ImageDownloadOptions.cs"> - <Link>Configuration\ImageDownloadOptions.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\ManualLoginCategory.cs"> <Link>Configuration\ManualLoginCategory.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\MetadataOptions.cs"> + <Link>Configuration\MetadataOptions.cs</Link> + </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\MetadataPlugin.cs"> + <Link>Configuration\MetadataPlugin.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\ServerConfiguration.cs"> <Link>Configuration\ServerConfiguration.cs</Link> </Compile> diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index bd411cce1..93d52e9c0 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -61,15 +61,21 @@ <Compile Include="..\MediaBrowser.Model\ApiClient\ServerEventArgs.cs"> <Link>ApiClient\ServerEventArgs.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\AutoOrganize.cs"> + <Link>Configuration\AutoOrganize.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\BaseApplicationConfiguration.cs"> <Link>Configuration\BaseApplicationConfiguration.cs</Link> </Compile> - <Compile Include="..\MediaBrowser.Model\Configuration\ImageDownloadOptions.cs"> - <Link>Configuration\ImageDownloadOptions.cs</Link> - </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\ManualLoginCategory.cs"> <Link>Configuration\ManualLoginCategory.cs</Link> </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\MetadataOptions.cs"> + <Link>Configuration\MetadataOptions.cs</Link> + </Compile> + <Compile Include="..\MediaBrowser.Model\Configuration\MetadataPlugin.cs"> + <Link>Configuration\MetadataPlugin.cs</Link> + </Compile> <Compile Include="..\MediaBrowser.Model\Configuration\ServerConfiguration.cs"> <Link>Configuration\ServerConfiguration.cs</Link> </Compile> diff --git a/MediaBrowser.Model/Configuration/AutoOrganize.cs b/MediaBrowser.Model/Configuration/AutoOrganize.cs new file mode 100644 index 000000000..a30aa36d8 --- /dev/null +++ b/MediaBrowser.Model/Configuration/AutoOrganize.cs @@ -0,0 +1,36 @@ + +namespace MediaBrowser.Model.Configuration +{ + public class TvFileOrganizationOptions + { + public bool IsEnabled { get; set; } + public int MinFileSizeMb { get; set; } + public string[] LeftOverFileExtensionsToDelete { get; set; } + public string[] WatchLocations { get; set; } + + public string SeasonFolderPattern { get; set; } + + public string SeasonZeroFolderName { get; set; } + + public string EpisodeNamePattern { get; set; } + public string MultiEpisodeNamePattern { get; set; } + + public bool OverwriteExistingEpisodes { get; set; } + + public bool DeleteEmptyFolders { get; set; } + + public TvFileOrganizationOptions() + { + MinFileSizeMb = 50; + + LeftOverFileExtensionsToDelete = new string[] { }; + + WatchLocations = new string[] { }; + + EpisodeNamePattern = "%sn - %sx%0e - %en.%ext"; + MultiEpisodeNamePattern = "%sn - %sx%0e-x%0ed - %en.%ext"; + SeasonFolderPattern = "Season %s"; + SeasonZeroFolderName = "Season 0"; + } + } +} diff --git a/MediaBrowser.Model/Configuration/ImageDownloadOptions.cs b/MediaBrowser.Model/Configuration/ImageDownloadOptions.cs deleted file mode 100644 index 603112110..000000000 --- a/MediaBrowser.Model/Configuration/ImageDownloadOptions.cs +++ /dev/null @@ -1,81 +0,0 @@ - -namespace MediaBrowser.Model.Configuration -{ - /// <summary> - /// Class ImageDownloadOptions - /// </summary> - public class ImageDownloadOptions - { - /// <summary> - /// Download Art Image - /// </summary> - /// <value><c>true</c> if art; otherwise, <c>false</c>.</value> - public bool Art { get; set; } - - /// <summary> - /// Download Logo Image - /// </summary> - /// <value><c>true</c> if logo; otherwise, <c>false</c>.</value> - public bool Logo { get; set; } - - /// <summary> - /// Download Primary Image - /// </summary> - /// <value><c>true</c> if primary; otherwise, <c>false</c>.</value> - public bool Primary { get; set; } - - /// <summary> - /// Download Backdrop Images - /// </summary> - /// <value><c>true</c> if backdrops; otherwise, <c>false</c>.</value> - public bool Backdrops { get; set; } - - /// <summary> - /// Download Disc Image - /// </summary> - /// <value><c>true</c> if disc; otherwise, <c>false</c>.</value> - public bool Disc { get; set; } - - /// <summary> - /// Download Thumb Image - /// </summary> - /// <value><c>true</c> if thumb; otherwise, <c>false</c>.</value> - public bool Thumb { get; set; } - - /// <summary> - /// Download Banner Image - /// </summary> - /// <value><c>true</c> if banner; otherwise, <c>false</c>.</value> - public bool Banner { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="ImageDownloadOptions"/> class. - /// </summary> - public ImageDownloadOptions() - { - Art = true; - Logo = true; - Primary = true; - Backdrops = true; - Disc = true; - Thumb = true; - Banner = true; - } - } - - /// <summary> - /// Class MetadataOptions. - /// </summary> - public class MetadataOptions - { - public int MaxBackdrops { get; set; } - - public int MinBackdropWidth { get; set; } - - public MetadataOptions() - { - MaxBackdrops = 3; - MinBackdropWidth = 1280; - } - } -} diff --git a/MediaBrowser.Model/Configuration/MetadataOptions.cs b/MediaBrowser.Model/Configuration/MetadataOptions.cs new file mode 100644 index 000000000..f914a2d21 --- /dev/null +++ b/MediaBrowser.Model/Configuration/MetadataOptions.cs @@ -0,0 +1,89 @@ +using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Model.Configuration +{ + /// <summary> + /// Class MetadataOptions. + /// </summary> + public class MetadataOptions + { + public string ItemType { get; set; } + + public ImageOption[] ImageOptions { get; set; } + + public string[] DisabledMetadataSavers { get; set; } + + public MetadataOptions() + : this(3, 1280) + { + } + + public MetadataOptions(int backdropLimit, int minBackdropWidth) + { + var imageOptions = new List<ImageOption> + { + new ImageOption + { + Limit = backdropLimit, + MinWidth = minBackdropWidth, + Type = ImageType.Backdrop + } + }; + + ImageOptions = imageOptions.ToArray(); + DisabledMetadataSavers = new string[] { }; + } + + public int GetLimit(ImageType type) + { + var option = ImageOptions.FirstOrDefault(i => i.Type == type); + + return option == null ? 1 : option.Limit; + } + + public int GetMinWidth(ImageType type) + { + var option = ImageOptions.FirstOrDefault(i => i.Type == type); + + return option == null ? 0 : option.MinWidth; + } + + public bool IsEnabled(ImageType type) + { + return GetLimit(type) > 0; + } + + public bool IsMetadataSaverEnabled(string name) + { + return !DisabledMetadataSavers.Contains(name, StringComparer.OrdinalIgnoreCase); + } + } + + public class ImageOption + { + /// <summary> + /// Gets or sets the type. + /// </summary> + /// <value>The type.</value> + public ImageType Type { get; set; } + /// <summary> + /// Gets or sets the limit. + /// </summary> + /// <value>The limit.</value> + public int Limit { get; set; } + + /// <summary> + /// Gets or sets the minimum width. + /// </summary> + /// <value>The minimum width.</value> + public int MinWidth { get; set; } + + public ImageOption() + { + Limit = 1; + } + } +} diff --git a/MediaBrowser.Model/Configuration/MetadataPlugin.cs b/MediaBrowser.Model/Configuration/MetadataPlugin.cs new file mode 100644 index 000000000..b019cf71a --- /dev/null +++ b/MediaBrowser.Model/Configuration/MetadataPlugin.cs @@ -0,0 +1,60 @@ +using MediaBrowser.Model.Entities; +using System.Collections.Generic; + +namespace MediaBrowser.Model.Configuration +{ + public class MetadataPlugin + { + /// <summary> + /// Gets or sets the name. + /// </summary> + /// <value>The name.</value> + public string Name { get; set; } + + /// <summary> + /// Gets or sets the type. + /// </summary> + /// <value>The type.</value> + public MetadataPluginType Type { get; set; } + } + + public class MetadataPluginSummary + { + /// <summary> + /// Gets or sets the type of the item. + /// </summary> + /// <value>The type of the item.</value> + public string ItemType { get; set; } + + /// <summary> + /// Gets or sets the plugins. + /// </summary> + /// <value>The plugins.</value> + public List<MetadataPlugin> Plugins { get; set; } + + /// <summary> + /// Gets or sets the supported image types. + /// </summary> + /// <value>The supported image types.</value> + public List<ImageType> SupportedImageTypes { get; set; } + + public MetadataPluginSummary() + { + SupportedImageTypes = new List<ImageType>(); + Plugins = new List<MetadataPlugin>(); + } + } + + /// <summary> + /// Enum MetadataPluginType + /// </summary> + public enum MetadataPluginType + { + LocalImageProvider, + ImageFetcher, + ImageSaver, + LocalMetadataProvider, + MetadataFetcher, + MetadataSaver + } +} diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 716be54d2..f874bdbb2 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using MediaBrowser.Model.Weather; using System; @@ -88,31 +89,6 @@ namespace MediaBrowser.Model.Configuration public string MetadataCountryCode { get; set; } /// <summary> - /// Options for specific art to download for movies. - /// </summary> - public ImageDownloadOptions DownloadMovieImages { get; set; } - - /// <summary> - /// Options for specific art to download for Series. - /// </summary> - public ImageDownloadOptions DownloadSeriesImages { get; set; } - - /// <summary> - /// Options for specific art to download for Seasons. - /// </summary> - public ImageDownloadOptions DownloadSeasonImages { get; set; } - - /// <summary> - /// Options for specific art to download for MusicArtists. - /// </summary> - public ImageDownloadOptions DownloadMusicArtistImages { get; set; } - - /// <summary> - /// Options for specific art to download for MusicAlbums. - /// </summary> - public ImageDownloadOptions DownloadMusicAlbumImages { get; set; } - - /// <summary> /// Characters to be replaced with a ' ' in strings to create a sort name /// </summary> /// <value>The sort replace characters.</value> @@ -215,11 +191,7 @@ namespace MediaBrowser.Model.Configuration public bool EnableEpisodeChapterImageExtraction { get; set; } public bool EnableOtherVideoChapterImageExtraction { get; set; } - public MetadataOptions MovieOptions { get; set; } - public MetadataOptions TvOptions { get; set; } - public MetadataOptions MusicOptions { get; set; } - public MetadataOptions GameOptions { get; set; } - public MetadataOptions BookOptions { get; set; } + public MetadataOptions[] MetadataOptions { get; set; } public bool EnableDebugEncodingLogging { get; set; } public string TranscodingTempPath { get; set; } @@ -267,14 +239,6 @@ namespace MediaBrowser.Model.Configuration MetadataRefreshDays = 30; PreferredMetadataLanguage = "en"; MetadataCountryCode = "US"; - DownloadMovieImages = new ImageDownloadOptions(); - DownloadSeriesImages = new ImageDownloadOptions(); - DownloadSeasonImages = new ImageDownloadOptions - { - Backdrops = false - }; - DownloadMusicArtistImages = new ImageDownloadOptions(); - DownloadMusicAlbumImages = new ImageDownloadOptions(); SortReplaceCharacters = new[] { ".", "+", "%" }; SortRemoveCharacters = new[] { ",", "&", "-", "{", "}", "'" }; @@ -282,26 +246,26 @@ namespace MediaBrowser.Model.Configuration SeasonZeroDisplayName = "Specials"; - MovieOptions = new MetadataOptions(); - TvOptions = new MetadataOptions(); + LiveTvOptions = new LiveTvOptions(); - MusicOptions = new MetadataOptions() - { - MaxBackdrops = 1 - }; + TvFileOrganizationOptions = new TvFileOrganizationOptions(); - GameOptions = new MetadataOptions(); + EnableRealtimeMonitor = true; - BookOptions = new MetadataOptions + var options = new List<MetadataOptions> { - MaxBackdrops = 1 + new MetadataOptions(1, 1280) {ItemType = "Book"}, + new MetadataOptions(1, 1280) {ItemType = "MusicAlbum"}, + new MetadataOptions(1, 1280) {ItemType = "MusicArtist"}, + new MetadataOptions(0, 1280) {ItemType = "Season"} }; - LiveTvOptions = new LiveTvOptions(); - - TvFileOrganizationOptions = new TvFileOrganizationOptions(); + MetadataOptions = options.ToArray(); + } - EnableRealtimeMonitor = true; + public MetadataOptions GetMetadataOptions(string type) + { + return MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase)); } } @@ -324,39 +288,6 @@ namespace MediaBrowser.Model.Configuration public int? GuideDays { get; set; } } - public class TvFileOrganizationOptions - { - public bool IsEnabled { get; set; } - public int MinFileSizeMb { get; set; } - public string[] LeftOverFileExtensionsToDelete { get; set; } - public string[] WatchLocations { get; set; } - - public string SeasonFolderPattern { get; set; } - - public string SeasonZeroFolderName { get; set; } - - public string EpisodeNamePattern { get; set; } - public string MultiEpisodeNamePattern { get; set; } - - public bool OverwriteExistingEpisodes { get; set; } - - public bool DeleteEmptyFolders { get; set; } - - public TvFileOrganizationOptions() - { - MinFileSizeMb = 50; - - LeftOverFileExtensionsToDelete = new string[] {}; - - WatchLocations = new string[] { }; - - EpisodeNamePattern = "%sn - %sx%0e - %en.%ext"; - MultiEpisodeNamePattern = "%sn - %sx%0e-x%0ed - %en.%ext"; - SeasonFolderPattern = "Season %s"; - SeasonZeroFolderName = "Season 0"; - } - } - public class PathSubstitution { public string From { get; set; } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 1e9b57971..136a78381 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -58,8 +58,11 @@ <Compile Include="ApiClient\ApiClientExtensions.cs" /> <Compile Include="ApiClient\IServerEvents.cs" /> <Compile Include="ApiClient\ServerEventArgs.cs" /> + <Compile Include="Configuration\AutoOrganize.cs" /> <Compile Include="Configuration\BaseApplicationConfiguration.cs" /> <Compile Include="Configuration\ManualLoginCategory.cs" /> + <Compile Include="Configuration\MetadataPlugin.cs" /> + <Compile Include="Configuration\MetadataOptions.cs" /> <Compile Include="Configuration\ServerConfiguration.cs" /> <Compile Include="Drawing\ImageOutputFormat.cs" /> <Compile Include="Dto\BaseItemPerson.cs" /> @@ -124,7 +127,6 @@ <Compile Include="Session\MessageCommand.cs" /> <Compile Include="Session\PlayRequest.cs" /> <Compile Include="Session\PlaystateCommand.cs" /> - <Compile Include="Configuration\ImageDownloadOptions.cs" /> <Compile Include="Logging\ILogManager.cs" /> <Compile Include="MediaInfo\BlurayDiscInfo.cs" /> <Compile Include="Entities\ChapterInfo.cs" /> diff --git a/MediaBrowser.Providers/BaseXmlProvider.cs b/MediaBrowser.Providers/BaseXmlProvider.cs index eab5bb574..68b003480 100644 --- a/MediaBrowser.Providers/BaseXmlProvider.cs +++ b/MediaBrowser.Providers/BaseXmlProvider.cs @@ -17,18 +17,18 @@ namespace MediaBrowser.Providers FileSystem = fileSystem; } - protected abstract string GetXmlPath(string path); + protected abstract FileInfo GetXmlFile(string path); public bool HasChanged(IHasMetadata item, DateTime date) { - var path = GetXmlPath(item.Path); + var file = GetXmlFile(item.Path); - return FileSystem.GetLastWriteTimeUtc(path) > date; + return FileSystem.GetLastWriteTimeUtc(file) > date; } public bool HasLocalMetadata(IHasMetadata item) { - return File.Exists(GetXmlPath(item.Path)); + return GetXmlFile(item.Path).Exists; } } } diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs index 53ab3614d..2d0fed02d 100644 --- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs +++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs @@ -1,9 +1,12 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -15,13 +18,13 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.BoxSets { - public class BoxSetMetadataService : ConcreteMetadataService<BoxSet, ItemId> + public class BoxSetMetadataService : MetadataService<BoxSet, ItemId> { private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _iLocalizationManager; - public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager, ILocalizationManager iLocalizationManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public BoxSetMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager, ILocalizationManager iLocalizationManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; _iLocalizationManager = iLocalizationManager; @@ -34,6 +37,7 @@ namespace MediaBrowser.Providers.BoxSets /// <param name="target">The target.</param> /// <param name="lockedFields">The locked fields.</param> /// <param name="replaceData">if set to <c>true</c> [replace data].</param> + /// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param> protected override void MergeData(BoxSet source, BoxSet target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) { ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); diff --git a/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs b/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs index 8b8c8bffd..391dd456e 100644 --- a/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs +++ b/MediaBrowser.Providers/BoxSets/BoxSetXmlProvider.cs @@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.BoxSets public async Task<MetadataResult<BoxSet>> GetMetadata(string path, CancellationToken cancellationToken) { - path = GetXmlPath(path); + path = GetXmlFile(path).FullName; var result = new MetadataResult<BoxSet>(); @@ -51,12 +51,12 @@ namespace MediaBrowser.Providers.BoxSets public string Name { - get { return "Media Browser Xml"; } + get { return "Media Browser xml"; } } - protected override string GetXmlPath(string path) + protected override FileInfo GetXmlFile(string path) { - return Path.Combine(path, "collection.xml"); + return new FileInfo(Path.Combine(path, "collection.xml")); } } } diff --git a/MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs b/MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs index 0dbf11450..85aa9f716 100644 --- a/MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs +++ b/MediaBrowser.Providers/GameGenres/GameGenreImageProvider.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.GameGenres public static string ProviderName { - get { return "Media Browser"; } + get { return "Media Browser Images"; } } public bool Supports(IHasImages item) diff --git a/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs b/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs index 1eefb0798..68602b159 100644 --- a/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs +++ b/MediaBrowser.Providers/GameGenres/GameGenreMetadataService.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +14,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.GameGenres { - public class GameGenreMetadataService : ConcreteMetadataService<GameGenre, ItemId> + public class GameGenreMetadataService : MetadataService<GameGenre, ItemId> { private readonly ILibraryManager _libraryManager; - public GameGenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public GameGenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/Games/GameMetadataService.cs b/MediaBrowser.Providers/Games/GameMetadataService.cs new file mode 100644 index 000000000..afa123bf7 --- /dev/null +++ b/MediaBrowser.Providers/Games/GameMetadataService.cs @@ -0,0 +1,59 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Providers.Manager; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Games +{ + public class GameMetadataService : MetadataService<Game, GameId> + { + private readonly ILibraryManager _libraryManager; + + public GameMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) + { + _libraryManager = libraryManager; + } + + /// <summary> + /// Merges the specified source. + /// </summary> + /// <param name="source">The source.</param> + /// <param name="target">The target.</param> + /// <param name="lockedFields">The locked fields.</param> + /// <param name="replaceData">if set to <c>true</c> [replace data].</param> + /// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param> + protected override void MergeData(Game source, Game target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) + { + ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + + if (replaceData || string.IsNullOrEmpty(target.GameSystem)) + { + target.GameSystem = source.GameSystem; + } + } + + protected override Task SaveItem(Game item, ItemUpdateType reason, CancellationToken cancellationToken) + { + return _libraryManager.UpdateItem(item, reason, cancellationToken); + } + + protected override GameId GetId(Game item) + { + var id = base.GetId(item); + + id.GameSystem = item.GameSystem; + + return id; + } + } +} diff --git a/MediaBrowser.Providers/Games/GameProviderFromXml.cs b/MediaBrowser.Providers/Games/GameProviderFromXml.cs deleted file mode 100644 index ab1f96a8e..000000000 --- a/MediaBrowser.Providers/Games/GameProviderFromXml.cs +++ /dev/null @@ -1,93 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; -using MediaBrowser.Providers.Savers; -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Games -{ - public class GameProviderFromXml : BaseMetadataProvider - { - private readonly IFileSystem _fileSystem; - - /// <summary> - /// - /// </summary> - /// <param name="logManager"></param> - /// <param name="configurationManager"></param> - public GameProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) - : base(logManager, configurationManager) - { - _fileSystem = fileSystem; - } - - /// <summary> - /// - /// </summary> - /// <param name="item"></param> - /// <returns></returns> - public override bool Supports(BaseItem item) - { - return item is Game; - } - - protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) - { - var savePath = GameXmlSaver.GetGameSavePath(item); - - var xml = item.ResolveArgs.GetMetaFileByPath(savePath) ?? new FileInfo(savePath); - - if (!xml.Exists) - { - return false; - } - - return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; - } - - /// <summary> - /// - /// </summary> - /// <param name="item"></param> - /// <param name="force"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) - { - var game = (Game)item; - cancellationToken.ThrowIfCancellationRequested(); - - var metaFile = GameXmlSaver.GetGameSavePath(game); - - if (File.Exists(metaFile)) - { - await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - new GameXmlParser(Logger).Fetch(game, metaFile, cancellationToken); - } - finally - { - XmlParsingResourcePool.Release(); - } - } - - SetLastRefreshed(game, DateTime.UtcNow, providerInfo); - return true; - } - - /// <summary> - /// - /// </summary> - public override MetadataProviderPriority Priority - { - get { return MetadataProviderPriority.Second; } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Providers/Games/GameSystemMetadataService.cs b/MediaBrowser.Providers/Games/GameSystemMetadataService.cs new file mode 100644 index 000000000..9e5532a27 --- /dev/null +++ b/MediaBrowser.Providers/Games/GameSystemMetadataService.cs @@ -0,0 +1,59 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using MediaBrowser.Providers.Manager; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Games +{ + public class GameSystemMetadataService : MetadataService<GameSystem, GameSystemId> + { + private readonly ILibraryManager _libraryManager; + + public GameSystemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) + { + _libraryManager = libraryManager; + } + + /// <summary> + /// Merges the specified source. + /// </summary> + /// <param name="source">The source.</param> + /// <param name="target">The target.</param> + /// <param name="lockedFields">The locked fields.</param> + /// <param name="replaceData">if set to <c>true</c> [replace data].</param> + /// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param> + protected override void MergeData(GameSystem source, GameSystem target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) + { + ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + + if (replaceData || string.IsNullOrEmpty(target.GameSystemName)) + { + target.GameSystemName = source.GameSystemName; + } + } + + protected override Task SaveItem(GameSystem item, ItemUpdateType reason, CancellationToken cancellationToken) + { + return _libraryManager.UpdateItem(item, reason, cancellationToken); + } + + protected override GameSystemId GetId(GameSystem item) + { + var id = base.GetId(item); + + id.Path = item.Path; + + return id; + } + } +} diff --git a/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs b/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs deleted file mode 100644 index 58143ce3d..000000000 --- a/MediaBrowser.Providers/Games/GameSystemProviderFromXml.cs +++ /dev/null @@ -1,92 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Providers.Games -{ - public class GameSystemProviderFromXml : BaseMetadataProvider - { - private readonly IFileSystem _fileSystem; - - public GameSystemProviderFromXml(ILogManager logManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem) - : base(logManager, configurationManager) - { - _fileSystem = fileSystem; - } - - /// <summary> - /// Supportses the specified item. - /// </summary> - /// <param name="item">The item.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - public override bool Supports(BaseItem item) - { - return item is GameSystem && item.LocationType == LocationType.FileSystem; - } - - /// <summary> - /// Gets the priority. - /// </summary> - /// <value>The priority.</value> - public override MetadataProviderPriority Priority - { - get { return MetadataProviderPriority.Second; } - } - - private const string XmlFileName = "gamesystem.xml"; - protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) - { - var xml = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, XmlFileName)); - - if (xml == null) - { - return false; - } - - return _fileSystem.GetLastWriteTimeUtc(xml) > item.DateLastSaved; - } - - /// <summary> - /// Fetches metadata and returns true or false indicating if any work that requires persistence was done - /// </summary> - /// <param name="item">The item.</param> - /// <param name="force">if set to <c>true</c> [force].</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{System.Boolean}.</returns> - public override async Task<bool> FetchAsync(BaseItem item, bool force, BaseProviderInfo providerInfo, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, XmlFileName)); - - if (metadataFile != null) - { - var path = metadataFile.FullName; - - await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - new BaseItemXmlParser<GameSystem>(Logger).Fetch((GameSystem)item, path, cancellationToken); - } - finally - { - XmlParsingResourcePool.Release(); - } - - SetLastRefreshed(item, DateTime.UtcNow, providerInfo); - - return true; - } - - return false; - } - } -} diff --git a/MediaBrowser.Providers/Games/GameSystemXmlParser.cs b/MediaBrowser.Providers/Games/GameSystemXmlParser.cs new file mode 100644 index 000000000..ba69c1fb2 --- /dev/null +++ b/MediaBrowser.Providers/Games/GameSystemXmlParser.cs @@ -0,0 +1,63 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; + +namespace MediaBrowser.Providers.Games +{ + public class GameSystemXmlParser : BaseItemXmlParser<GameSystem> + { + public GameSystemXmlParser(ILogger logger) + : base(logger) + { + } + + public Task FetchAsync(GameSystem item, string metadataFile, CancellationToken cancellationToken) + { + Fetch(item, metadataFile, cancellationToken); + + cancellationToken.ThrowIfCancellationRequested(); + + return Task.FromResult(true); + } + + /// <summary> + /// Fetches the data from XML node. + /// </summary> + /// <param name="reader">The reader.</param> + /// <param name="item">The item.</param> + protected override void FetchDataFromXmlNode(XmlReader reader, GameSystem item) + { + switch (reader.Name) + { + case "GameSystem": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.GameSystemName = val; + } + break; + } + + case "GamesDbId": + { + var val = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(val)) + { + item.SetProviderId(MetadataProviders.Gamesdb, val); + } + break; + } + + + default: + base.FetchDataFromXmlNode(reader, item); + break; + } + } + } +} diff --git a/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs b/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs new file mode 100644 index 000000000..f2001f586 --- /dev/null +++ b/MediaBrowser.Providers/Games/GameSystemXmlProvider.cs @@ -0,0 +1,59 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Games +{ + public class GameSystemXmlProvider : BaseXmlProvider, ILocalMetadataProvider<GameSystem> + { + private readonly ILogger _logger; + + public GameSystemXmlProvider(IFileSystem fileSystem, ILogger logger) + : base(fileSystem) + { + _logger = logger; + } + + public async Task<MetadataResult<GameSystem>> GetMetadata(string path, CancellationToken cancellationToken) + { + path = GetXmlFile(path).FullName; + + var result = new MetadataResult<GameSystem>(); + + await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + var item = new GameSystem(); + + new GameSystemXmlParser(_logger).Fetch(item, path, cancellationToken); + result.HasMetadata = true; + result.Item = item; + } + catch (FileNotFoundException) + { + result.HasMetadata = false; + } + finally + { + XmlParsingResourcePool.Release(); + } + + return result; + } + + public string Name + { + get { return "Media Browser xml"; } + } + + protected override FileInfo GetXmlFile(string path) + { + return new FileInfo(Path.Combine(path, "gamesystem.xml")); + } + } +} diff --git a/MediaBrowser.Providers/Games/GameXmlParser.cs b/MediaBrowser.Providers/Games/GameXmlParser.cs index 53cc12388..a5e6adbef 100644 --- a/MediaBrowser.Providers/Games/GameXmlParser.cs +++ b/MediaBrowser.Providers/Games/GameXmlParser.cs @@ -14,7 +14,6 @@ namespace MediaBrowser.Providers.Games /// </summary> public class GameXmlParser : BaseItemXmlParser<Game> { - private Task _chaptersTask = null; private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public GameXmlParser(ILogger logger) @@ -22,18 +21,13 @@ namespace MediaBrowser.Providers.Games { } - public async Task FetchAsync(Game item, string metadataFile, CancellationToken cancellationToken) + public Task FetchAsync(Game item, string metadataFile, CancellationToken cancellationToken) { - _chaptersTask = null; - Fetch(item, metadataFile, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); - if (_chaptersTask != null) - { - await _chaptersTask.ConfigureAwait(false); - } + return Task.FromResult(true); } /// <summary> diff --git a/MediaBrowser.Providers/Games/GameXmlProvider.cs b/MediaBrowser.Providers/Games/GameXmlProvider.cs new file mode 100644 index 000000000..fb64c2a61 --- /dev/null +++ b/MediaBrowser.Providers/Games/GameXmlProvider.cs @@ -0,0 +1,74 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Logging; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Providers.Games +{ + public class GameXmlProvider : BaseXmlProvider, ILocalMetadataProvider<Game> + { + private readonly ILogger _logger; + + public GameXmlProvider(IFileSystem fileSystem, ILogger logger) + : base(fileSystem) + { + _logger = logger; + } + + public async Task<MetadataResult<Game>> GetMetadata(string path, CancellationToken cancellationToken) + { + path = GetXmlFile(path).FullName; + + var result = new MetadataResult<Game>(); + + await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + var item = new Game(); + + new GameXmlParser(_logger).Fetch(item, path, cancellationToken); + result.HasMetadata = true; + result.Item = item; + } + catch (FileNotFoundException) + { + result.HasMetadata = false; + } + finally + { + XmlParsingResourcePool.Release(); + } + + return result; + } + + public string Name + { + get { return "Media Browser xml"; } + } + + protected override FileInfo GetXmlFile(string path) + { + var fileInfo = FileSystem.GetFileSystemInfo(path); + + var directoryInfo = fileInfo as DirectoryInfo; + + if (directoryInfo == null) + { + directoryInfo = new DirectoryInfo(Path.GetDirectoryName(path)); + } + + var directoryPath = directoryInfo.FullName; + + var specificFile = Path.Combine(directoryPath, Path.GetFileNameWithoutExtension(path) + ".xml"); + + var file = new FileInfo(specificFile); + + return file.Exists ? file : new FileInfo(Path.Combine(directoryPath, "game.xml")); + } + } +} diff --git a/MediaBrowser.Providers/Genres/GenreImageProvider.cs b/MediaBrowser.Providers/Genres/GenreImageProvider.cs index 189cc8cde..007eeab7b 100644 --- a/MediaBrowser.Providers/Genres/GenreImageProvider.cs +++ b/MediaBrowser.Providers/Genres/GenreImageProvider.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.Genres public static string ProviderName { - get { return "Media Browser"; } + get { return "Media Browser Images"; } } public bool Supports(IHasImages item) diff --git a/MediaBrowser.Providers/Genres/GenreMetadataService.cs b/MediaBrowser.Providers/Genres/GenreMetadataService.cs index fa4a4c955..e2437fed1 100644 --- a/MediaBrowser.Providers/Genres/GenreMetadataService.cs +++ b/MediaBrowser.Providers/Genres/GenreMetadataService.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +14,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Genres { - public class GenreMetadataService : ConcreteMetadataService<Genre, ItemId> + public class GenreMetadataService : MetadataService<Genre, ItemId> { private readonly ILibraryManager _libraryManager; - public GenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public GenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs b/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs index 5c476c89d..b0c916a61 100644 --- a/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs +++ b/MediaBrowser.Providers/LiveTv/ChannelMetadataService.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +14,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.LiveTv { - public class ChannelMetadataService : ConcreteMetadataService<LiveTvChannel, ItemId> + public class ChannelMetadataService : MetadataService<LiveTvChannel, ItemId> { private readonly ILibraryManager _libraryManager; - public ChannelMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public ChannelMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs b/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs index 544685f66..096e68a8a 100644 --- a/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs +++ b/MediaBrowser.Providers/LiveTv/ChannelXmlProvider.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.LiveTv public async Task<MetadataResult<LiveTvChannel>> GetMetadata(string path, CancellationToken cancellationToken) { - path = GetXmlPath(path); + path = GetXmlFile(path).FullName; var result = new MetadataResult<LiveTvChannel>(); @@ -48,12 +48,12 @@ namespace MediaBrowser.Providers.LiveTv public string Name { - get { return "Media Browser Xml"; } + get { return "Media Browser xml"; } } - protected override string GetXmlPath(string path) + protected override FileInfo GetXmlFile(string path) { - return Path.Combine(path, "channel.xml"); + return new FileInfo(Path.Combine(path, "channel.xml")); } } } diff --git a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs b/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs index 0a22daf2f..02d5c1a79 100644 --- a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs +++ b/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +14,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.LiveTv { - public class ProgramMetadataService : ConcreteMetadataService<LiveTvProgram, ItemId> + public class ProgramMetadataService : MetadataService<LiveTvProgram, ItemId> { private readonly ILibraryManager _libraryManager; - public ProgramMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public ProgramMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/Manager/ConcreteMetadataService.cs b/MediaBrowser.Providers/Manager/ConcreteMetadataService.cs deleted file mode 100644 index f3644581e..000000000 --- a/MediaBrowser.Providers/Manager/ConcreteMetadataService.cs +++ /dev/null @@ -1,21 +0,0 @@ -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Providers.Manager -{ - public abstract class ConcreteMetadataService<TItemType, TIdType> : MetadataService<TItemType, TIdType> - where TItemType : IHasMetadata, new() - where TIdType : ItemId, new() - { - protected ConcreteMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo) - : base(serverConfigurationManager, logger, providerManager, providerRepo) - { - } - - protected override TItemType CreateNew() - { - return new TItemType(); - } - } -} diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs index 2decba161..2e0bf9a05 100644 --- a/MediaBrowser.Providers/Manager/ImageSaver.cs +++ b/MediaBrowser.Providers/Manager/ImageSaver.cs @@ -309,15 +309,6 @@ namespace MediaBrowser.Providers.Manager { item.BackdropImagePaths.Add(path); } - - if (string.IsNullOrEmpty(sourceUrl)) - { - item.RemoveImageSourceForPath(path); - } - else - { - item.AddImageSource(path, sourceUrl); - } break; default: item.SetImagePath(type, path); diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 7f0dc8b89..ee6f7cf69 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -1,16 +1,17 @@ -using System.IO; -using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Threading; @@ -25,11 +26,12 @@ namespace MediaBrowser.Providers.Manager private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; - public ItemImageProvider(ILogger logger, IProviderManager providerManager, IServerConfigurationManager config) + public ItemImageProvider(ILogger logger, IProviderManager providerManager, IServerConfigurationManager config, IFileSystem fileSystem) { _logger = logger; _providerManager = providerManager; _config = config; + _fileSystem = fileSystem; } public bool ValidateImages(IHasImages item, IEnumerable<IImageProvider> providers) @@ -49,7 +51,7 @@ namespace MediaBrowser.Providers.Manager return hasChanges; } - public async Task<RefreshResult> RefreshImages(IHasImages item, IEnumerable<IImageProvider> imageProviders, ImageRefreshOptions options, CancellationToken cancellationToken) + public async Task<RefreshResult> RefreshImages(IHasImages item, IEnumerable<IImageProvider> imageProviders, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, CancellationToken cancellationToken) { var result = new RefreshResult { UpdateType = ItemUpdateType.Unspecified }; @@ -57,16 +59,20 @@ namespace MediaBrowser.Providers.Manager var providerIds = new List<Guid>(); + // In order to avoid duplicates, only download these if there are none already + var backdropLimit = item.HasImage(ImageType.Backdrop) ? 0 : savedOptions.GetLimit(ImageType.Backdrop); + var screenshotLimit = item.HasImage(ImageType.Screenshot) ? 0 : savedOptions.GetLimit(ImageType.Screenshot); + foreach (var provider in providers.OfType<IRemoteImageProvider>()) { - await RefreshFromProvider(item, provider, options, result, cancellationToken).ConfigureAwait(false); + await RefreshFromProvider(item, provider, refreshOptions, savedOptions, backdropLimit, screenshotLimit, result, cancellationToken).ConfigureAwait(false); providerIds.Add(provider.GetType().FullName.GetMD5()); } foreach (var provider in providers.OfType<IDynamicImageProvider>()) { - await RefreshFromProvider(item, provider, result, cancellationToken).ConfigureAwait(false); + await RefreshFromProvider(item, provider, savedOptions, result, cancellationToken).ConfigureAwait(false); providerIds.Add(provider.GetType().FullName.GetMD5()); } @@ -81,10 +87,11 @@ namespace MediaBrowser.Providers.Manager /// </summary> /// <param name="item">The item.</param> /// <param name="provider">The provider.</param> + /// <param name="savedOptions">The saved options.</param> /// <param name="result">The result.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - private async Task RefreshFromProvider(IHasImages item, IDynamicImageProvider provider, RefreshResult result, CancellationToken cancellationToken) + private async Task RefreshFromProvider(IHasImages item, IDynamicImageProvider provider, MetadataOptions savedOptions, RefreshResult result, CancellationToken cancellationToken) { _logger.Debug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name); @@ -94,7 +101,7 @@ namespace MediaBrowser.Providers.Manager foreach (var imageType in images) { - if (!item.HasImage(imageType)) + if (!item.HasImage(imageType) && savedOptions.IsEnabled(imageType)) { var response = await provider.GetImage(item, imageType, cancellationToken).ConfigureAwait(false); @@ -152,17 +159,20 @@ namespace MediaBrowser.Providers.Manager /// <summary> /// Determines if an item already contains the given images /// </summary> - /// <param name="item"></param> - /// <param name="images"></param> - /// <returns></returns> - private bool ContainsImages(IHasImages item, List<ImageType> images) + /// <param name="item">The item.</param> + /// <param name="images">The images.</param> + /// <param name="savedOptions">The saved options.</param> + /// <param name="backdropLimit">The backdrop limit.</param> + /// <param name="screenshotLimit">The screenshot limit.</param> + /// <returns><c>true</c> if the specified item contains images; otherwise, <c>false</c>.</returns> + private bool ContainsImages(IHasImages item, List<ImageType> images, MetadataOptions savedOptions, int backdropLimit, int screenshotLimit) { - if (_singularImages.Any(i => images.Contains(i) && !item.HasImage(i))) + if (_singularImages.Any(i => images.Contains(i) && !item.HasImage(i) && savedOptions.GetLimit(i) > 0)) { return false; } - if (images.Contains(ImageType.Backdrop) && item.BackdropImagePaths.Count < GetMaxBackdropCount(item)) + if (images.Contains(ImageType.Backdrop) && item.BackdropImagePaths.Count < backdropLimit) { return false; } @@ -172,7 +182,7 @@ namespace MediaBrowser.Providers.Manager var hasScreenshots = item as IHasScreenshots; if (hasScreenshots != null) { - if (hasScreenshots.ScreenshotImagePaths.Count < GetMaxBackdropCount(item)) + if (hasScreenshots.ScreenshotImagePaths.Count < screenshotLimit) { return false; } @@ -187,16 +197,18 @@ namespace MediaBrowser.Providers.Manager /// </summary> /// <param name="item">The item.</param> /// <param name="provider">The provider.</param> - /// <param name="options">The options.</param> + /// <param name="refreshOptions">The refresh options.</param> + /// <param name="savedOptions">The saved options.</param> + /// <param name="backdropLimit">The backdrop limit.</param> + /// <param name="screenshotLimit">The screenshot limit.</param> /// <param name="result">The result.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - private async Task RefreshFromProvider(IHasImages item, IRemoteImageProvider provider, ImageRefreshOptions options, RefreshResult result, CancellationToken cancellationToken) + private async Task RefreshFromProvider(IHasImages item, IRemoteImageProvider provider, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, int backdropLimit, int screenshotLimit, RefreshResult result, CancellationToken cancellationToken) { try { - // TODO: Also factor in IsConfiguredToDownloadImage - if (ContainsImages(item, provider.GetSupportedImages(item).ToList())) + if (ContainsImages(item, provider.GetSupportedImages(item).ToList(), savedOptions, backdropLimit, screenshotLimit)) { return; } @@ -208,18 +220,18 @@ namespace MediaBrowser.Providers.Manager foreach (var type in _singularImages) { - if (IsConfiguredToDownloadImage(item, type) && !item.HasImage(type)) + if (savedOptions.IsEnabled(type) && !item.HasImage(type)) { await DownloadImage(item, provider, result, list, type, cancellationToken).ConfigureAwait(false); } } - await DownloadBackdrops(item, provider, result, list, cancellationToken).ConfigureAwait(false); + await DownloadBackdrops(item, backdropLimit, provider, result, list, cancellationToken).ConfigureAwait(false); var hasScreenshots = item as IHasScreenshots; if (hasScreenshots != null) { - await DownloadScreenshots(hasScreenshots, provider, result, list, cancellationToken).ConfigureAwait(false); + await DownloadScreenshots(hasScreenshots, screenshotLimit, provider, result, list, cancellationToken).ConfigureAwait(false); } } catch (OperationCanceledException) @@ -342,25 +354,19 @@ namespace MediaBrowser.Providers.Manager } } - private async Task DownloadBackdrops(IHasImages item, IRemoteImageProvider provider, RefreshResult result, IEnumerable<RemoteImageInfo> images, CancellationToken cancellationToken) + private async Task DownloadBackdrops(IHasImages item, int limit, IRemoteImageProvider provider, RefreshResult result, IEnumerable<RemoteImageInfo> images, CancellationToken cancellationToken) { const ImageType imageType = ImageType.Backdrop; - var maxCount = GetMaxBackdropCount(item); foreach (var image in images.Where(i => i.Type == imageType)) { - if (item.BackdropImagePaths.Count >= maxCount) + if (item.BackdropImagePaths.Count >= limit) { break; } var url = image.Url; - if (item.ContainsImageWithSourceUrl(url)) - { - continue; - } - try { var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false); @@ -381,25 +387,19 @@ namespace MediaBrowser.Providers.Manager } } - private async Task DownloadScreenshots(IHasScreenshots item, IRemoteImageProvider provider, RefreshResult result, IEnumerable<RemoteImageInfo> images, CancellationToken cancellationToken) + private async Task DownloadScreenshots(IHasScreenshots item, int limit, IRemoteImageProvider provider, RefreshResult result, IEnumerable<RemoteImageInfo> images, CancellationToken cancellationToken) { const ImageType imageType = ImageType.Screenshot; - var maxCount = GetMaxScreenshotCount(item); foreach (var image in images.Where(i => i.Type == imageType)) { - if (item.ScreenshotImagePaths.Count >= maxCount) + if (item.ScreenshotImagePaths.Count >= limit) { break; } var url = image.Url; - if (item.ContainsImageWithSourceUrl(url)) - { - continue; - } - try { var response = await provider.GetImageResponse(url, cancellationToken).ConfigureAwait(false); @@ -419,20 +419,5 @@ namespace MediaBrowser.Providers.Manager } } } - - private bool IsConfiguredToDownloadImage(IHasImages item, ImageType type) - { - return true; - } - - private int GetMaxBackdropCount(IHasImages item) - { - return 1; - } - - private int GetMaxScreenshotCount(IHasScreenshots item) - { - return 1; - } } } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 69f970891..f6e27238e 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -1,7 +1,9 @@ using MediaBrowser.Common.Extensions; +using MediaBrowser.Common.IO; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using System; @@ -13,32 +15,22 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Manager { public abstract class MetadataService<TItemType, TIdType> : IMetadataService - where TItemType : IHasMetadata + where TItemType : IHasMetadata, new() where TIdType : ItemId, new() { protected readonly IServerConfigurationManager ServerConfigurationManager; protected readonly ILogger Logger; protected readonly IProviderManager ProviderManager; - private readonly IProviderRepository _providerRepo; + protected readonly IProviderRepository ProviderRepo; + protected readonly IFileSystem FileSystem; - private IMetadataProvider<TItemType>[] _providers = { }; - - protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo) + protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem) { ServerConfigurationManager = serverConfigurationManager; Logger = logger; ProviderManager = providerManager; - _providerRepo = providerRepo; - } - - /// <summary> - /// Adds the parts. - /// </summary> - /// <param name="providers">The providers.</param> - public void AddParts(IEnumerable<IMetadataProvider> providers) - { - _providers = providers.OfType<IMetadataProvider<TItemType>>() - .ToArray(); + ProviderRepo = providerRepo; + FileSystem = fileSystem; } /// <summary> @@ -48,7 +40,7 @@ namespace MediaBrowser.Providers.Manager /// <returns>Task.</returns> protected Task SaveProviderResult(MetadataStatus result) { - return _providerRepo.SaveMetadataStatus(result, CancellationToken.None); + return ProviderRepo.SaveMetadataStatus(result, CancellationToken.None); } /// <summary> @@ -58,20 +50,22 @@ namespace MediaBrowser.Providers.Manager /// <returns>ProviderResult.</returns> protected MetadataStatus GetLastResult(Guid itemId) { - return _providerRepo.GetMetadataStatus(itemId) ?? new MetadataStatus { ItemId = itemId }; + return ProviderRepo.GetMetadataStatus(itemId) ?? new MetadataStatus { ItemId = itemId }; } - public async Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken) + public async Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { var itemOfType = (TItemType)item; + var config = GetMetadataOptions(itemOfType); + var updateType = ItemUpdateType.Unspecified; var lastResult = GetLastResult(item.Id); var refreshResult = lastResult; refreshResult.LastErrorMessage = string.Empty; refreshResult.LastStatus = ProviderRefreshStatus.Success; - var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager); + var itemImageProvider = new ItemImageProvider(Logger, ProviderManager, ServerConfigurationManager, FileSystem); var localImagesFailed = false; var allImageProviders = ((ProviderManager)ProviderManager).GetImageProviders(item).ToList(); @@ -93,13 +87,13 @@ namespace MediaBrowser.Providers.Manager } // Next run metadata providers - if (options.MetadataRefreshMode != MetadataRefreshMode.None) + if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None) { - var providers = GetProviders(item, lastResult.DateLastMetadataRefresh.HasValue, options).ToList(); + var providers = GetProviders(item, lastResult.DateLastMetadataRefresh.HasValue, refreshOptions).ToList(); if (providers.Count > 0) { - var result = await RefreshWithProviders(itemOfType, options, providers, cancellationToken).ConfigureAwait(false); + var result = await RefreshWithProviders(itemOfType, refreshOptions, providers, cancellationToken).ConfigureAwait(false); updateType = updateType | result.UpdateType; refreshResult.AddStatus(result.Status, result.ErrorMessage); @@ -109,13 +103,13 @@ namespace MediaBrowser.Providers.Manager } // Next run remote image providers, but only if local image providers didn't throw an exception - if (!localImagesFailed && options.ImageRefreshMode != ImageRefreshMode.ValidationOnly) + if (!localImagesFailed && refreshOptions.ImageRefreshMode != ImageRefreshMode.ValidationOnly) { - var providers = GetNonLocalImageProviders(item, allImageProviders, lastResult.DateLastImagesRefresh.HasValue, options).ToList(); + var providers = GetNonLocalImageProviders(item, allImageProviders, lastResult.DateLastImagesRefresh.HasValue, refreshOptions).ToList(); if (providers.Count > 0) { - var result = await itemImageProvider.RefreshImages(itemOfType, providers, options, cancellationToken).ConfigureAwait(false); + var result = await itemImageProvider.RefreshImages(itemOfType, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false); updateType = updateType | result.UpdateType; refreshResult.AddStatus(result.Status, result.ErrorMessage); @@ -128,7 +122,7 @@ namespace MediaBrowser.Providers.Manager var providersHadChanges = updateType > ItemUpdateType.Unspecified; - if (options.ForceSave || providersHadChanges) + if (refreshOptions.ForceSave || providersHadChanges) { if (string.IsNullOrEmpty(item.Name)) { @@ -145,6 +139,15 @@ namespace MediaBrowser.Providers.Manager } } + private readonly MetadataOptions _defaultOptions = new MetadataOptions(); + protected MetadataOptions GetMetadataOptions(TItemType item) + { + var type = item.GetType().Name; + return ServerConfigurationManager.Configuration.MetadataOptions + .FirstOrDefault(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase)) ?? + _defaultOptions; + } + /// <summary> /// Afters the metadata refresh. /// </summary> @@ -292,10 +295,35 @@ namespace MediaBrowser.Providers.Manager MergeData(temp, item, item.LockedFields, true, true); } + foreach (var provider in providers.OfType<ICustomMetadataProvider<TItemType>>()) + { + Logger.Debug("Running {0} for {1}", provider.GetType().Name, item.Path ?? item.Name); + + try + { + await provider.FetchAsync(item, cancellationToken).ConfigureAwait(false); + + refreshResult.UpdateType = refreshResult.UpdateType | ItemUpdateType.MetadataDownload; + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + refreshResult.Status = ProviderRefreshStatus.CompletedWithErrors; + refreshResult.ErrorMessage = ex.Message; + Logger.ErrorException("Error in {0}", ex, provider.Name); + } + } + return refreshResult; } - protected abstract TItemType CreateNew(); + protected virtual TItemType CreateNew() + { + return new TItemType(); + } private async Task ExecuteRemoteProviders(TItemType item, TItemType temp, IEnumerable<IRemoteMetadataProvider<TItemType>> providers, RefreshResult refreshResult, CancellationToken cancellationToken) { diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 77a9298ee..b4f228a1d 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -2,14 +2,17 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Entities.Movies; +using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -58,6 +61,7 @@ namespace MediaBrowser.Providers.Manager private IMetadataService[] _metadataServices = { }; private IMetadataProvider[] _metadataProviders = { }; + private IEnumerable<IMetadataSaver> _savers; /// <summary> /// Initializes a new instance of the <see cref="ProviderManager" /> class. @@ -85,7 +89,8 @@ namespace MediaBrowser.Providers.Manager /// <param name="imageProviders">The image providers.</param> /// <param name="metadataServices">The metadata services.</param> /// <param name="metadataProviders">The metadata providers.</param> - public void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders) + /// <param name="metadataSavers">The metadata savers.</param> + public void AddParts(IEnumerable<BaseMetadataProvider> providers, IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders, IEnumerable<IMetadataSaver> metadataSavers) { MetadataProviders = providers.OrderBy(e => e.Priority).ToArray(); @@ -93,6 +98,7 @@ namespace MediaBrowser.Providers.Manager _metadataServices = metadataServices.OrderBy(i => i.Order).ToArray(); _metadataProviders = metadataProviders.ToArray(); + _savers = metadataSavers.ToArray(); } public Task RefreshMetadata(IHasMetadata item, MetadataRefreshOptions options, CancellationToken cancellationToken) @@ -480,8 +486,14 @@ namespace MediaBrowser.Providers.Manager public IEnumerable<IMetadataProvider<T>> GetMetadataProviders<T>(IHasMetadata item) where T : IHasMetadata { + return GetMetadataProvidersInternal<T>(item, false); + } + + private IEnumerable<IMetadataProvider<T>> GetMetadataProvidersInternal<T>(IHasMetadata item, bool includeDisabled) + where T : IHasMetadata + { return _metadataProviders.OfType<IMetadataProvider<T>>() - .Where(i => CanRefresh(i, item)) + .Where(i => CanRefresh(i, item, includeDisabled)) .OrderBy(i => GetOrder(item, i)); } @@ -495,10 +507,11 @@ namespace MediaBrowser.Providers.Manager /// </summary> /// <param name="provider">The provider.</param> /// <param name="item">The item.</param> + /// <param name="includeDisabled">if set to <c>true</c> [include disabled].</param> /// <returns><c>true</c> if this instance can refresh the specified provider; otherwise, <c>false</c>.</returns> - protected bool CanRefresh(IMetadataProvider provider, IHasMetadata item) + private bool CanRefresh(IMetadataProvider provider, IHasMetadata item, bool includeDisabled) { - if (!ConfigurationManager.Configuration.EnableInternetProviders && provider is IRemoteMetadataProvider) + if (!includeDisabled && !ConfigurationManager.Configuration.EnableInternetProviders && provider is IRemoteMetadataProvider) { return false; } @@ -546,5 +559,148 @@ namespace MediaBrowser.Providers.Manager return hasOrder.Order; } + + public IEnumerable<MetadataPluginSummary> GetAllMetadataPlugins() + { + var list = new List<MetadataPluginSummary>(); + + list.Add(GetPluginSummary<Game>()); + list.Add(GetPluginSummary<GameSystem>()); + list.Add(GetPluginSummary<Movie>()); + list.Add(GetPluginSummary<Trailer>()); + list.Add(GetPluginSummary<BoxSet>()); + list.Add(GetPluginSummary<Book>()); + list.Add(GetPluginSummary<Series>()); + list.Add(GetPluginSummary<Season>()); + list.Add(GetPluginSummary<Episode>()); + list.Add(GetPluginSummary<Person>()); + list.Add(GetPluginSummary<MusicAlbum>()); + list.Add(GetPluginSummary<MusicArtist>()); + list.Add(GetPluginSummary<Audio>()); + + list.Add(GetPluginSummary<Genre>()); + list.Add(GetPluginSummary<Studio>()); + list.Add(GetPluginSummary<GameGenre>()); + list.Add(GetPluginSummary<MusicGenre>()); + + return list; + } + + private MetadataPluginSummary GetPluginSummary<T>() + where T : BaseItem, new() + { + // Give it a dummy path just so that it looks like a file system item + var dummy = new T() + { + Path = "C:\\", + + // Dummy this up to fool the local trailer check + Parent = new Folder() + }; + + var summary = new MetadataPluginSummary + { + ItemType = typeof(T).Name + }; + + var imageProviders = GetImageProviders(dummy).ToList(); + + AddMetadataPlugins(summary.Plugins, dummy); + AddImagePlugins(summary.Plugins, dummy, imageProviders); + + summary.SupportedImageTypes = imageProviders.OfType<IRemoteImageProvider>() + .SelectMany(i => i.GetSupportedImages(dummy)) + .Distinct() + .ToList(); + + return summary; + } + + private void AddMetadataPlugins<T>(List<MetadataPlugin> list, T item) + where T : IHasMetadata + { + var providers = GetMetadataProvidersInternal<T>(item, true).ToList(); + + // Locals + list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin + { + Name = i.Name, + Type = MetadataPluginType.LocalMetadataProvider + })); + + // Fetchers + list.AddRange(providers.Where(i => !(i is ILocalMetadataProvider)).Select(i => new MetadataPlugin + { + Name = i.Name, + Type = MetadataPluginType.MetadataFetcher + })); + + // Savers + list.AddRange(_savers.Where(i => i.IsEnabledFor(item, ItemUpdateType.MetadataEdit)).OrderBy(i => i.Name).Select(i => new MetadataPlugin + { + Name = i.Name, + Type = MetadataPluginType.MetadataSaver + })); + } + + private void AddImagePlugins<T>(List<MetadataPlugin> list, T item, List<IImageProvider> imageProviders) + where T : IHasImages + { + + // Locals + list.AddRange(imageProviders.Where(i => (i is ILocalImageProvider)).Select(i => new MetadataPlugin + { + Name = i.Name, + Type = MetadataPluginType.LocalImageProvider + })); + + // Fetchers + list.AddRange(imageProviders.Where(i => !(i is ILocalImageProvider)).Select(i => new MetadataPlugin + { + Name = i.Name, + Type = MetadataPluginType.ImageFetcher + })); + } + + private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>(); + + /// <summary> + /// Saves the metadata. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="updateType">Type of the update.</param> + /// <returns>Task.</returns> + public async Task SaveMetadata(IHasMetadata item, ItemUpdateType updateType) + { + var locationType = item.LocationType; + if (locationType == LocationType.Remote || locationType == LocationType.Virtual) + { + throw new ArgumentException("Only file-system based items can save metadata."); + } + + foreach (var saver in _savers.Where(i => i.IsEnabledFor(item, updateType))) + { + var path = saver.GetSavePath(item); + + var semaphore = _fileLocks.GetOrAdd(path, key => new SemaphoreSlim(1, 1)); + + await semaphore.WaitAsync().ConfigureAwait(false); + + try + { + _libraryMonitor.ReportFileSystemChangeBeginning(path); + saver.Save(item, CancellationToken.None); + } + catch (Exception ex) + { + _logger.ErrorException("Error in metadata saver", ex); + } + finally + { + _libraryMonitor.ReportFileSystemChangeComplete(path, false); + semaphore.Release(); + } + } + } } } diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 512b11051..87029e557 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -69,11 +69,13 @@ <Compile Include="BoxSets\MovieDbBoxSetImageProvider.cs" /> <Compile Include="BoxSets\MovieDbBoxSetProvider.cs" /> <Compile Include="GameGenres\GameGenreMetadataService.cs" /> + <Compile Include="Games\GameMetadataService.cs" /> + <Compile Include="Games\GameSystemMetadataService.cs" /> + <Compile Include="Games\GameSystemXmlParser.cs" /> <Compile Include="Genres\GenreMetadataService.cs" /> <Compile Include="LiveTv\ChannelMetadataService.cs" /> <Compile Include="LiveTv\ChannelXmlProvider.cs" /> <Compile Include="LiveTv\ProgramMetadataService.cs" /> - <Compile Include="Manager\ConcreteMetadataService.cs" /> <Compile Include="Manager\ImageSaver.cs" /> <Compile Include="Manager\ItemImageProvider.cs" /> <Compile Include="Manager\ProviderManager.cs" /> @@ -82,8 +84,8 @@ <Compile Include="CollectionFolderImageProvider.cs" /> <Compile Include="FolderProviderFromXml.cs" /> <Compile Include="Games\GameXmlParser.cs" /> - <Compile Include="Games\GameProviderFromXml.cs" /> - <Compile Include="Games\GameSystemProviderFromXml.cs" /> + <Compile Include="Games\GameXmlProvider.cs" /> + <Compile Include="Games\GameSystemXmlProvider.cs" /> <Compile Include="ImageFromMediaLocationProvider.cs" /> <Compile Include="ImagesByNameProvider.cs" /> <Compile Include="Movies\MovieDbSearch.cs" /> diff --git a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs index f2cd2718a..8eebf595a 100644 --- a/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs +++ b/MediaBrowser.Providers/Movies/FanArtMovieProvider.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; @@ -271,50 +272,53 @@ namespace MediaBrowser.Providers.Movies { cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadMovieImages.Primary && !item.HasImage(ImageType.Primary)) + var options = ConfigurationManager.Configuration.GetMetadataOptions("Movie") ?? new MetadataOptions(); + + if (options.IsEnabled(ImageType.Primary) && !item.HasImage(ImageType.Primary)) { await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadMovieImages.Logo && !item.HasImage(ImageType.Logo)) + if (options.IsEnabled(ImageType.Logo) && !item.HasImage(ImageType.Logo)) { await SaveImage(item, images, ImageType.Logo, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadMovieImages.Art && !item.HasImage(ImageType.Art)) + if (options.IsEnabled(ImageType.Art) && !item.HasImage(ImageType.Art)) { await SaveImage(item, images, ImageType.Art, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadMovieImages.Disc && !item.HasImage(ImageType.Disc)) + if (options.IsEnabled(ImageType.Disc) && !item.HasImage(ImageType.Disc)) { await SaveImage(item, images, ImageType.Disc, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadMovieImages.Banner && !item.HasImage(ImageType.Banner)) + if (options.IsEnabled(ImageType.Banner) && !item.HasImage(ImageType.Banner)) { await SaveImage(item, images, ImageType.Banner, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadMovieImages.Thumb && !item.HasImage(ImageType.Thumb)) + if (options.IsEnabled(ImageType.Thumb) && !item.HasImage(ImageType.Thumb)) { await SaveImage(item, images, ImageType.Thumb, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - var backdropLimit = ConfigurationManager.Configuration.MovieOptions.MaxBackdrops; - if (ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && + var backdropLimit = options.GetLimit(ImageType.Backdrop); + + if (backdropLimit > 0 && item.BackdropImagePaths.Count < backdropLimit) { foreach (var image in images.Where(i => i.Type == ImageType.Backdrop)) diff --git a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs index 55d1b7588..e6c3a2035 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImagesProvider.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; @@ -126,9 +127,11 @@ namespace MediaBrowser.Providers.Movies return false; } + var options = ConfigurationManager.Configuration.GetMetadataOptions("Movie") ?? new MetadataOptions(); + // Don't refresh if we already have both poster and backdrop and we're not refreshing images if (item.HasImage(ImageType.Primary) && - item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.MovieOptions.MaxBackdrops && + item.BackdropImagePaths.Count >= options.GetLimit(ImageType.Backdrop) && !item.LockedFields.Contains(MetadataFields.Images)) { return false; @@ -205,15 +208,17 @@ namespace MediaBrowser.Providers.Movies cancellationToken.ThrowIfCancellationRequested(); + var options = ConfigurationManager.Configuration.GetMetadataOptions("Movie") ?? new MetadataOptions(); + var eligibleBackdrops = images - .Where(i => i.Type == ImageType.Backdrop && i.Width.HasValue && i.Width.Value >= ConfigurationManager.Configuration.MovieOptions.MinBackdropWidth) + .Where(i => i.Type == ImageType.Backdrop && i.Width.HasValue && i.Width.Value >= options.GetMinWidth(ImageType.Backdrop)) .ToList(); - var backdropLimit = ConfigurationManager.Configuration.MovieOptions.MaxBackdrops; + var backdropLimit = options.GetLimit(ImageType.Backdrop); // backdrops - only download if earlier providers didn't find any (fanart) if (eligibleBackdrops.Count > 0 && - ConfigurationManager.Configuration.DownloadMovieImages.Backdrops && + options.IsEnabled(ImageType.Backdrop) && item.BackdropImagePaths.Count < backdropLimit && !item.LockedFields.Contains(MetadataFields.Backdrops)) { @@ -221,18 +226,15 @@ namespace MediaBrowser.Providers.Movies { var url = eligibleBackdrops[i].Url; - if (!item.ContainsImageWithSourceUrl(url)) + var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions { - var img = await MovieDbProvider.Current.GetMovieDbResponse(new HttpRequestOptions - { - Url = url, - CancellationToken = cancellationToken + Url = url, + CancellationToken = cancellationToken - }).ConfigureAwait(false); + }).ConfigureAwait(false); - await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(url), ImageType.Backdrop, null, url, cancellationToken) - .ConfigureAwait(false); - } + await _providerManager.SaveImage(item, img, MimeTypes.GetMimeType(url), ImageType.Backdrop, null, url, cancellationToken) + .ConfigureAwait(false); if (item.BackdropImagePaths.Count >= backdropLimit) { diff --git a/MediaBrowser.Providers/Movies/MovieDbProvider.cs b/MediaBrowser.Providers/Movies/MovieDbProvider.cs index d1cc17e15..c6c47e198 100644 --- a/MediaBrowser.Providers/Movies/MovieDbProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbProvider.cs @@ -285,7 +285,7 @@ namespace MediaBrowser.Providers.Movies /// <returns><c>true</c> if [has alt meta] [the specified item]; otherwise, <c>false</c>.</returns> internal static bool HasAltMeta(BaseItem item) { - var path = MovieXmlSaver.GetMovieSavePath(item); + var path = MovieXmlSaver.GetMovieSavePath((Video)item); if (item.LocationType == LocationType.FileSystem) { diff --git a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs index 3ba777b37..67b62548e 100644 --- a/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs +++ b/MediaBrowser.Providers/Movies/MovieProviderFromXml.cs @@ -63,7 +63,7 @@ namespace MediaBrowser.Providers.Movies protected override bool NeedsRefreshBasedOnCompareDate(BaseItem item, BaseProviderInfo providerInfo) { - var savePath = MovieXmlSaver.GetMovieSavePath(item); + var savePath = MovieXmlSaver.GetMovieSavePath((Video)item); var xml = item.ResolveArgs.GetMetaFileByPath(savePath) ?? new FileInfo(savePath); @@ -86,7 +86,9 @@ namespace MediaBrowser.Providers.Movies { cancellationToken.ThrowIfCancellationRequested(); - var path = MovieXmlSaver.GetMovieSavePath(item); + var video = (Video)item; + + var path = MovieXmlSaver.GetMovieSavePath(video); if (File.Exists(path)) { @@ -94,8 +96,6 @@ namespace MediaBrowser.Providers.Movies try { - var video = (Video)item; - await new MovieXmlParser(Logger, _itemRepo).FetchAsync(video, path, cancellationToken).ConfigureAwait(false); } finally diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs index 511fa0547..8418c3898 100644 --- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs +++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs @@ -1,7 +1,9 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -13,12 +15,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Music { - public class AlbumMetadataService : ConcreteMetadataService<MusicAlbum, AlbumId> + public class AlbumMetadataService : MetadataService<MusicAlbum, AlbumId> { private readonly ILibraryManager _libraryManager; - public AlbumMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public AlbumMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/Music/AlbumXmlProvider.cs b/MediaBrowser.Providers/Music/AlbumXmlProvider.cs index 66095fb7f..e0d830369 100644 --- a/MediaBrowser.Providers/Music/AlbumXmlProvider.cs +++ b/MediaBrowser.Providers/Music/AlbumXmlProvider.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music public async Task<MetadataResult<MusicAlbum>> GetMetadata(string path, CancellationToken cancellationToken) { - path = GetXmlPath(path); + path = GetXmlFile(path).FullName; var result = new MetadataResult<MusicAlbum>(); @@ -48,12 +48,12 @@ namespace MediaBrowser.Providers.Music public string Name { - get { return "Media Browser Xml"; } + get { return "Media Browser xml"; } } - protected override string GetXmlPath(string path) + protected override FileInfo GetXmlFile(string path) { - return Path.Combine(path, "album.xml"); + return new FileInfo(Path.Combine(path, "album.xml")); } } } diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs index 1b598e596..6e4093faa 100644 --- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs +++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs @@ -1,7 +1,9 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -13,12 +15,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Music { - public class ArtistMetadataService : ConcreteMetadataService<MusicArtist, ItemId> + public class ArtistMetadataService : MetadataService<MusicArtist, ItemId> { private readonly ILibraryManager _libraryManager; - public ArtistMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public ArtistMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/Music/ArtistXmlProvider.cs b/MediaBrowser.Providers/Music/ArtistXmlProvider.cs index f29a6b861..3f073d512 100644 --- a/MediaBrowser.Providers/Music/ArtistXmlProvider.cs +++ b/MediaBrowser.Providers/Music/ArtistXmlProvider.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.Music public async Task<MetadataResult<MusicArtist>> GetMetadata(string path, CancellationToken cancellationToken) { - path = GetXmlPath(path); + path = GetXmlFile(path).FullName; var result = new MetadataResult<MusicArtist>(); @@ -48,12 +48,12 @@ namespace MediaBrowser.Providers.Music public string Name { - get { return "Media Browser Xml"; } + get { return "Media Browser xml"; } } - protected override string GetXmlPath(string path) + protected override FileInfo GetXmlFile(string path) { - return Path.Combine(path, "artist.xml"); + return new FileInfo(Path.Combine(path, "artist.xml")); } } } diff --git a/MediaBrowser.Providers/MusicGenres/MusicGenreImageProvider.cs b/MediaBrowser.Providers/MusicGenres/MusicGenreImageProvider.cs index 8ae217e0b..0867156e3 100644 --- a/MediaBrowser.Providers/MusicGenres/MusicGenreImageProvider.cs +++ b/MediaBrowser.Providers/MusicGenres/MusicGenreImageProvider.cs @@ -38,7 +38,7 @@ namespace MediaBrowser.Providers.MusicGenres public static string ProviderName { - get { return "Media Browser"; } + get { return "Media Browser Images"; } } public bool Supports(IHasImages item) diff --git a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs index b252970cb..c0a62fba2 100644 --- a/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs +++ b/MediaBrowser.Providers/MusicGenres/MusicGenreMetadataService.cs @@ -1,7 +1,9 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +13,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.MusicGenres { - public class MusicGenreMetadataService : ConcreteMetadataService<MusicGenre, ItemId> + public class MusicGenreMetadataService : MetadataService<MusicGenre, ItemId> { private readonly ILibraryManager _libraryManager; - public MusicGenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public MusicGenreMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/People/PersonMetadataService.cs b/MediaBrowser.Providers/People/PersonMetadataService.cs index f39ae68bd..ba7f3a738 100644 --- a/MediaBrowser.Providers/People/PersonMetadataService.cs +++ b/MediaBrowser.Providers/People/PersonMetadataService.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +14,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.People { - public class PersonMetadataService : ConcreteMetadataService<Person, ItemId> + public class PersonMetadataService : MetadataService<Person, ItemId> { private readonly ILibraryManager _libraryManager; - public PersonMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public PersonMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/People/PersonXmlProvider.cs b/MediaBrowser.Providers/People/PersonXmlProvider.cs index 900b7956c..72aef7a4c 100644 --- a/MediaBrowser.Providers/People/PersonXmlProvider.cs +++ b/MediaBrowser.Providers/People/PersonXmlProvider.cs @@ -20,7 +20,7 @@ namespace MediaBrowser.Providers.People public async Task<MetadataResult<Person>> GetMetadata(string path, CancellationToken cancellationToken) { - path = GetXmlPath(path); + path = GetXmlFile(path).FullName; var result = new MetadataResult<Person>(); @@ -48,12 +48,12 @@ namespace MediaBrowser.Providers.People public string Name { - get { return "Media Browser Xml"; } + get { return "Media Browser xml"; } } - protected override string GetXmlPath(string path) + protected override FileInfo GetXmlFile(string path) { - return Path.Combine(path, "person.xml"); + return new FileInfo(Path.Combine(path, "person.xml")); } } } diff --git a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs index 5e4401cff..7eb56e40b 100644 --- a/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/AlbumXmlSaver.cs @@ -1,9 +1,7 @@ using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; -using MediaBrowser.Providers.Music; -using System; +using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.IO; using System.Text; @@ -20,13 +18,21 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -46,13 +52,13 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes((MusicAlbum)item, builder); builder.Append("</Item>"); @@ -66,7 +72,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "album.xml"); } diff --git a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs index 6b801f1e2..efaa96751 100644 --- a/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/ArtistXmlSaver.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Providers.Music; using System; using System.Collections.Generic; @@ -20,13 +21,21 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -59,13 +68,13 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes((MusicArtist)item, builder); builder.Append("</Item>"); @@ -79,7 +88,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "artist.xml"); } diff --git a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs index 5d5624c55..078b1feba 100644 --- a/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/BoxSetXmlSaver.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; +using MediaBrowser.Controller.Providers; namespace MediaBrowser.Providers.Savers { @@ -18,13 +19,21 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -44,13 +53,13 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes((BoxSet)item, builder); builder.Append("</Item>"); @@ -64,7 +73,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "collection.xml"); } diff --git a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs b/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs index ad7f1287f..ed9a9bd6d 100644 --- a/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/ChannelXmlSaver.cs @@ -1,8 +1,6 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Providers.LiveTv; -using System; +using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.IO; using System.Text; @@ -21,7 +19,7 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -35,19 +33,27 @@ namespace MediaBrowser.Providers.Savers return false; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Saves the specified item. /// </summary> /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes((LiveTvChannel)item, builder); builder.Append("</Item>"); @@ -63,7 +69,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "channel.xml"); } diff --git a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs index b7cfe8aee..a0e309718 100644 --- a/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/EpisodeXmlSaver.cs @@ -1,8 +1,8 @@ using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -23,7 +23,7 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -37,6 +37,14 @@ namespace MediaBrowser.Providers.Savers return false; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + private readonly CultureInfo _usCulture = new CultureInfo("en-US"); public EpisodeXmlSaver(IServerConfigurationManager config, IItemRepository itemRepository) @@ -51,7 +59,7 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var episode = (Episode)item; @@ -112,7 +120,7 @@ namespace MediaBrowser.Providers.Savers builder.Append("<FirstAired>" + SecurityElement.Escape(episode.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>"); } - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes(episode, builder); XmlSaverHelpers.AddMediaInfo(episode, builder, _itemRepository); builder.Append("</Item>"); @@ -140,7 +148,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { var filename = Path.ChangeExtension(Path.GetFileName(item.Path), ".xml"); diff --git a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs index 7ad13905d..6d384e410 100644 --- a/MediaBrowser.Providers/Savers/FolderXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/FolderXmlSaver.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.IO; using System.Text; @@ -20,15 +21,25 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { - if (!item.IsFolder) + var folder = item as Folder; + + if (folder == null) { return false; } @@ -40,7 +51,8 @@ namespace MediaBrowser.Providers.Savers if (item.IsSaveLocalMetadataEnabled() && (wasMetadataEdited || wasMetadataDownloaded)) { if (!(item is Series) && !(item is BoxSet) && !(item is MusicArtist) && !(item is MusicAlbum) && - !(item is Season)) + !(item is Season) && + !(item is GameSystem)) { return true; } @@ -64,13 +76,13 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes((Folder)item, builder); builder.Append("</Item>"); @@ -84,7 +96,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "folder.xml"); } diff --git a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs index 7089b8e1b..d0d2ffcd0 100644 --- a/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/GameSystemXmlSaver.cs @@ -1,10 +1,10 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Providers.Games; -using System; +using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.IO; +using System.Security; using System.Text; using System.Threading; @@ -19,13 +19,21 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -45,13 +53,20 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { + var gameSystem = (GameSystem)item; + var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + if (!string.IsNullOrEmpty(gameSystem.GameSystemName)) + { + builder.Append("<GameSystem>" + SecurityElement.Escape(gameSystem.GameSystemName) + "</GameSystem>"); + } + + XmlSaverHelpers.AddCommonNodes(gameSystem, builder); builder.Append("</Item>"); @@ -65,7 +80,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "gamesystem.xml"); } diff --git a/MediaBrowser.Providers/Savers/GameXmlSaver.cs b/MediaBrowser.Providers/Savers/GameXmlSaver.cs index 5dd7617e0..4e3f948a3 100644 --- a/MediaBrowser.Providers/Savers/GameXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/GameXmlSaver.cs @@ -1,9 +1,8 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Providers.Movies; -using System; using System.Collections.Generic; using System.Globalization; using System.IO; @@ -25,13 +24,21 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -53,7 +60,7 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var builder = new StringBuilder(); @@ -85,7 +92,7 @@ namespace MediaBrowser.Providers.Savers builder.Append("<NesBoxRom>" + SecurityElement.Escape(val) + "</NesBoxRom>"); } - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes(game, builder); builder.Append("</Item>"); @@ -100,12 +107,12 @@ namespace MediaBrowser.Providers.Savers }); } - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { - return GetGameSavePath(item); + return GetGameSavePath((Game)item); } - public static string GetGameSavePath(BaseItem item) + public static string GetGameSavePath(Game item) { if (item.IsInMixedFolder) { diff --git a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs index 3fc4579e3..f65c8f5df 100644 --- a/MediaBrowser.Providers/Savers/MovieXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/MovieXmlSaver.cs @@ -10,6 +10,7 @@ using System.IO; using System.Security; using System.Text; using System.Threading; +using MediaBrowser.Controller.Providers; namespace MediaBrowser.Providers.Savers { @@ -27,13 +28,21 @@ namespace MediaBrowser.Providers.Savers _itemRepository = itemRepository; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -48,9 +57,9 @@ namespace MediaBrowser.Providers.Savers { return !trailer.IsLocalTrailer; } - + var video = item as Video; // Check parent for null to avoid running this against things like video backdrops - return item is Video && !(item is Episode) && item.Parent != null; + return video != null && !(item is Episode) && video.Parent != null; } return false; @@ -64,22 +73,24 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { + var video = (Video)item; + var builder = new StringBuilder(); builder.Append("<Title>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes(video, builder); - if (item.CommunityRating.HasValue) + if (video.CommunityRating.HasValue) { - builder.Append("<IMDBrating>" + SecurityElement.Escape(item.CommunityRating.Value.ToString(UsCulture)) + "</IMDBrating>"); + builder.Append("<IMDBrating>" + SecurityElement.Escape(video.CommunityRating.Value.ToString(UsCulture)) + "</IMDBrating>"); } - if (!string.IsNullOrEmpty(item.Overview)) + if (!string.IsNullOrEmpty(video.Overview)) { - builder.Append("<Description><![CDATA[" + item.Overview + "]]></Description>"); + builder.Append("<Description><![CDATA[" + video.Overview + "]]></Description>"); } var musicVideo = item as MusicVideo; @@ -106,8 +117,6 @@ namespace MediaBrowser.Providers.Savers } } - var video = (Video)item; - XmlSaverHelpers.AddMediaInfo(video, builder, _itemRepository); builder.Append("</Title>"); @@ -124,12 +133,12 @@ namespace MediaBrowser.Providers.Savers }); } - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { - return GetMovieSavePath(item); + return GetMovieSavePath((Video)item); } - public static string GetMovieSavePath(BaseItem item) + public static string GetMovieSavePath(Video item) { if (item.IsInMixedFolder) { diff --git a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs b/MediaBrowser.Providers/Savers/PersonXmlSaver.cs index a6d7575ea..676f2dae0 100644 --- a/MediaBrowser.Providers/Savers/PersonXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/PersonXmlSaver.cs @@ -1,7 +1,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Providers.Movies; -using System; +using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.IO; using System.Security; @@ -15,13 +14,21 @@ namespace MediaBrowser.Providers.Savers /// </summary> public class PersonXmlSaver : IMetadataSaver { + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -41,15 +48,15 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { + var person = (Person)item; + var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); - - var person = (Person)item; + XmlSaverHelpers.AddCommonNodes(person, builder); if (!string.IsNullOrEmpty(person.PlaceOfBirth)) { @@ -71,7 +78,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "person.xml"); } diff --git a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs index 0a9f2e4f6..52f310f0f 100644 --- a/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/SeasonXmlSaver.cs @@ -1,7 +1,7 @@ using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; using System.Collections.Generic; using System.IO; using System.Text; @@ -18,13 +18,21 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -44,13 +52,13 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var builder = new StringBuilder(); builder.Append("<Item>"); - XmlSaverHelpers.AddCommonNodes(item, builder); + XmlSaverHelpers.AddCommonNodes((Season)item, builder); builder.Append("</Item>"); @@ -64,7 +72,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "season.xml"); } diff --git a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs index 29ca12f7f..d472c2da2 100644 --- a/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs +++ b/MediaBrowser.Providers/Savers/SeriesXmlSaver.cs @@ -1,7 +1,7 @@ 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 System.Collections.Generic; using System.IO; @@ -20,13 +20,21 @@ namespace MediaBrowser.Providers.Savers _config = config; } + public string Name + { + get + { + return "Media Browser xml"; + } + } + /// <summary> /// Determines whether [is enabled for] [the specified item]. /// </summary> /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> - public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) + public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) { var wasMetadataEdited = (updateType & ItemUpdateType.MetadataEdit) == ItemUpdateType.MetadataEdit; var wasMetadataDownloaded = (updateType & ItemUpdateType.MetadataDownload) == ItemUpdateType.MetadataDownload; @@ -46,7 +54,7 @@ namespace MediaBrowser.Providers.Savers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - public void Save(BaseItem item, CancellationToken cancellationToken) + public void Save(IHasMetadata item, CancellationToken cancellationToken) { var series = (Series)item; @@ -73,7 +81,7 @@ namespace MediaBrowser.Providers.Savers if (series.Studios.Count > 0) { - builder.Append("<Network>" + SecurityElement.Escape(item.Studios[0]) + "</Network>"); + builder.Append("<Network>" + SecurityElement.Escape(series.Studios[0]) + "</Network>"); } if (!string.IsNullOrEmpty(series.AirTime)) @@ -97,8 +105,8 @@ namespace MediaBrowser.Providers.Savers { builder.Append("<FirstAired>" + SecurityElement.Escape(series.PremiereDate.Value.ToLocalTime().ToString("yyyy-MM-dd")) + "</FirstAired>"); } - - XmlSaverHelpers.AddCommonNodes(item, builder); + + XmlSaverHelpers.AddCommonNodes(series, builder); builder.Append("</Series>"); @@ -124,7 +132,7 @@ namespace MediaBrowser.Providers.Savers /// </summary> /// <param name="item">The item.</param> /// <returns>System.String.</returns> - public string GetSavePath(BaseItem item) + public string GetSavePath(IHasMetadata item) { return Path.Combine(item.Path, "series.xml"); } diff --git a/MediaBrowser.Providers/Studios/StudioMetadataService.cs b/MediaBrowser.Providers/Studios/StudioMetadataService.cs index 78ef1b51c..a42a882af 100644 --- a/MediaBrowser.Providers/Studios/StudioMetadataService.cs +++ b/MediaBrowser.Providers/Studios/StudioMetadataService.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +14,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Studios { - public class StudioMetadataService : ConcreteMetadataService<Studio, ItemId> + public class StudioMetadataService : MetadataService<Studio, ItemId> { private readonly ILibraryManager _libraryManager; - public StudioMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public StudioMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, ILibraryManager libraryManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _libraryManager = libraryManager; } diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs index eacec5b69..006ab827d 100644 --- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs +++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.Providers.Studios public static string ProviderName { - get { return "Media Browser"; } + get { return "Media Browser Images"; } } public bool Supports(IHasImages item) diff --git a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs index 6ab612784..50db33b3d 100644 --- a/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtSeasonProvider.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; @@ -121,7 +122,9 @@ namespace MediaBrowser.Providers.TV /// <returns>Task.</returns> private async Task FetchImages(Season season, List<RemoteImageInfo> images, CancellationToken cancellationToken) { - if (ConfigurationManager.Configuration.DownloadSeasonImages.Thumb && !season.HasImage(ImageType.Thumb) && !season.LockedFields.Contains(MetadataFields.Images)) + var options = ConfigurationManager.Configuration.GetMetadataOptions("Season") ?? new MetadataOptions(); + + if (options.IsEnabled(ImageType.Thumb) && !season.HasImage(ImageType.Thumb) && !season.LockedFields.Contains(MetadataFields.Images)) { await SaveImage(season, images, ImageType.Thumb, cancellationToken).ConfigureAwait(false); } diff --git a/MediaBrowser.Providers/TV/FanArtTVProvider.cs b/MediaBrowser.Providers/TV/FanArtTVProvider.cs index 1f7109c61..3f2199fc4 100644 --- a/MediaBrowser.Providers/TV/FanArtTVProvider.cs +++ b/MediaBrowser.Providers/TV/FanArtTVProvider.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; @@ -197,39 +198,41 @@ namespace MediaBrowser.Providers.TV /// <returns>Task.</returns> private async Task FetchFromXml(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken) { + var options = ConfigurationManager.Configuration.GetMetadataOptions("Series") ?? new MetadataOptions(); + if (!item.LockedFields.Contains(MetadataFields.Images)) { cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadSeriesImages.Primary && !item.HasImage(ImageType.Primary)) + if (options.IsEnabled(ImageType.Primary) && !item.HasImage(ImageType.Primary)) { await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadSeriesImages.Logo && !item.HasImage(ImageType.Logo)) + if (options.IsEnabled(ImageType.Logo) && !item.HasImage(ImageType.Logo)) { await SaveImage(item, images, ImageType.Logo, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadSeriesImages.Art && !item.HasImage(ImageType.Art)) + if (options.IsEnabled(ImageType.Art) && !item.HasImage(ImageType.Art)) { await SaveImage(item, images, ImageType.Art, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadSeriesImages.Thumb && !item.HasImage(ImageType.Thumb)) + if (options.IsEnabled(ImageType.Thumb) && !item.HasImage(ImageType.Thumb)) { await SaveImage(item, images, ImageType.Thumb, cancellationToken).ConfigureAwait(false); } cancellationToken.ThrowIfCancellationRequested(); - if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && !item.HasImage(ImageType.Banner)) + if (options.IsEnabled(ImageType.Banner) && !item.HasImage(ImageType.Banner)) { await SaveImage(item, images, ImageType.Banner, cancellationToken).ConfigureAwait(false); } @@ -239,8 +242,8 @@ namespace MediaBrowser.Providers.TV { cancellationToken.ThrowIfCancellationRequested(); - var backdropLimit = ConfigurationManager.Configuration.TvOptions.MaxBackdrops; - if (ConfigurationManager.Configuration.DownloadSeriesImages.Backdrops && + var backdropLimit = options.GetLimit(ImageType.Backdrop); + if (options.IsEnabled(ImageType.Backdrop) && item.BackdropImagePaths.Count < backdropLimit) { foreach (var image in images.Where(i => i.Type == ImageType.Backdrop)) diff --git a/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs index 17ed6b5a2..d7281ac21 100644 --- a/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeasonProvider.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; @@ -149,16 +150,17 @@ namespace MediaBrowser.Providers.TV var images = await _providerManager.GetAvailableRemoteImages(item, cancellationToken, ManualTvdbSeasonImageProvider.ProviderName).ConfigureAwait(false); - const int backdropLimit = 1; - - await DownloadImages(item, images.ToList(), backdropLimit, cancellationToken).ConfigureAwait(false); + await DownloadImages(item, images.ToList(), cancellationToken).ConfigureAwait(false); SetLastRefreshed(item, DateTime.UtcNow, providerInfo); return true; } - private async Task DownloadImages(BaseItem item, List<RemoteImageInfo> images, int backdropLimit, CancellationToken cancellationToken) + private async Task DownloadImages(BaseItem item, List<RemoteImageInfo> images, CancellationToken cancellationToken) { + var options = ConfigurationManager.Configuration.GetMetadataOptions("Season") ?? new MetadataOptions(); + var backdropLimit = options.GetLimit(ImageType.Backdrop); + if (!item.LockedFields.Contains(MetadataFields.Images)) { if (!item.HasImage(ImageType.Primary)) @@ -166,23 +168,18 @@ namespace MediaBrowser.Providers.TV await SaveImage(item, images, ImageType.Primary, cancellationToken).ConfigureAwait(false); } - if (ConfigurationManager.Configuration.DownloadSeasonImages.Banner && !item.HasImage(ImageType.Banner)) + if (options.IsEnabled(ImageType.Banner) && !item.HasImage(ImageType.Banner)) { await SaveImage(item, images, ImageType.Banner, cancellationToken).ConfigureAwait(false); } } - if (ConfigurationManager.Configuration.DownloadSeasonImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit && !item.LockedFields.Contains(MetadataFields.Backdrops)) + if (options.IsEnabled(ImageType.Backdrop) && item.BackdropImagePaths.Count < backdropLimit && !item.LockedFields.Contains(MetadataFields.Backdrops)) { foreach (var backdrop in images.Where(i => i.Type == ImageType.Backdrop)) { var url = backdrop.Url; - if (item.ContainsImageWithSourceUrl(url)) - { - continue; - } - await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, null, cancellationToken).ConfigureAwait(false); if (item.BackdropImagePaths.Count >= backdropLimit) break; diff --git a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs index 21a72dd57..73db2680e 100644 --- a/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs +++ b/MediaBrowser.Providers/TV/TvdbSeriesImageProvider.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Providers; @@ -137,7 +138,9 @@ namespace MediaBrowser.Providers.TV protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) { - if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Banner) && item.BackdropImagePaths.Count >= ConfigurationManager.Configuration.TvOptions.MaxBackdrops) + var options = ConfigurationManager.Configuration.GetMetadataOptions("Series") ?? new MetadataOptions(); + + if (item.HasImage(ImageType.Primary) && item.HasImage(ImageType.Banner) && item.BackdropImagePaths.Count >= options.GetLimit(ImageType.Backdrop)) { return false; } @@ -167,6 +170,8 @@ namespace MediaBrowser.Providers.TV private async Task DownloadImages(BaseItem item, List<RemoteImageInfo> images, int backdropLimit, CancellationToken cancellationToken) { + var options = ConfigurationManager.Configuration.GetMetadataOptions("Series") ?? new MetadataOptions(); + if (!item.LockedFields.Contains(MetadataFields.Images)) { if (!item.HasImage(ImageType.Primary)) @@ -180,7 +185,7 @@ namespace MediaBrowser.Providers.TV } } - if (ConfigurationManager.Configuration.DownloadSeriesImages.Banner && !item.HasImage(ImageType.Banner)) + if (options.IsEnabled(ImageType.Banner) && !item.HasImage(ImageType.Banner)) { var image = images.FirstOrDefault(i => i.Type == ImageType.Banner); @@ -192,19 +197,14 @@ namespace MediaBrowser.Providers.TV } } - if (ConfigurationManager.Configuration.DownloadSeriesImages.Backdrops && item.BackdropImagePaths.Count < backdropLimit && !item.LockedFields.Contains(MetadataFields.Backdrops)) + if (options.IsEnabled(ImageType.Backdrop) && item.BackdropImagePaths.Count < backdropLimit && !item.LockedFields.Contains(MetadataFields.Backdrops)) { foreach (var backdrop in images.Where(i => i.Type == ImageType.Backdrop && (!i.Width.HasValue || - i.Width.Value >= ConfigurationManager.Configuration.TvOptions.MinBackdropWidth))) + i.Width.Value >= options.GetMinWidth(ImageType.Backdrop)))) { var url = backdrop.Url; - if (item.ContainsImageWithSourceUrl(url)) - { - continue; - } - await _providerManager.SaveImage(item, url, TvdbSeriesProvider.Current.TvDbResourcePool, ImageType.Backdrop, null, cancellationToken).ConfigureAwait(false); if (item.BackdropImagePaths.Count >= backdropLimit) break; diff --git a/MediaBrowser.Providers/Users/UserMetadataService.cs b/MediaBrowser.Providers/Users/UserMetadataService.cs index 3a7abd79b..01c27c754 100644 --- a/MediaBrowser.Providers/Users/UserMetadataService.cs +++ b/MediaBrowser.Providers/Users/UserMetadataService.cs @@ -1,7 +1,10 @@ -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; @@ -11,12 +14,12 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.Users { - public class UserMetadataService : ConcreteMetadataService<User, ItemId> + public class UserMetadataService : MetadataService<User, ItemId> { private readonly IUserManager _userManager; - public UserMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, ILibraryManager libraryManager, IUserManager userManager) - : base(serverConfigurationManager, logger, providerManager, providerRepo) + public UserMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserManager userManager) + : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem) { _userManager = userManager; } @@ -28,6 +31,7 @@ namespace MediaBrowser.Providers.Users /// <param name="target">The target.</param> /// <param name="lockedFields">The locked fields.</param> /// <param name="replaceData">if set to <c>true</c> [replace data].</param> + /// <param name="mergeMetadataSettings">if set to <c>true</c> [merge metadata settings].</param> protected override void MergeData(User source, User target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) { ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 17b5ea424..789cc1100 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -9,6 +9,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; +using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Configuration; @@ -135,9 +136,8 @@ namespace MediaBrowser.Server.Implementations.Library /// <value>The by reference items.</value> private ConcurrentDictionary<Guid, BaseItem> ByReferenceItems { get; set; } - private IEnumerable<IMetadataSaver> _savers; - private readonly Func<ILibraryMonitor> _libraryMonitorFactory; + private readonly Func<IProviderManager> _providerManagerFactory; /// <summary> /// The _library items cache @@ -180,7 +180,7 @@ namespace MediaBrowser.Server.Implementations.Library /// <param name="userManager">The user manager.</param> /// <param name="configurationManager">The configuration manager.</param> /// <param name="userDataRepository">The user data repository.</param> - public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func<ILibraryMonitor> libraryMonitorFactory, IFileSystem fileSystem) + public LibraryManager(ILogger logger, ITaskManager taskManager, IUserManager userManager, IServerConfigurationManager configurationManager, IUserDataManager userDataRepository, Func<ILibraryMonitor> libraryMonitorFactory, IFileSystem fileSystem, Func<IProviderManager> providerManagerFactory) { _logger = logger; _taskManager = taskManager; @@ -189,6 +189,7 @@ namespace MediaBrowser.Server.Implementations.Library _userDataRepository = userDataRepository; _libraryMonitorFactory = libraryMonitorFactory; _fileSystem = fileSystem; + _providerManagerFactory = providerManagerFactory; ByReferenceItems = new ConcurrentDictionary<Guid, BaseItem>(); ConfigurationManager.ConfigurationUpdated += ConfigurationUpdated; @@ -215,8 +216,7 @@ namespace MediaBrowser.Server.Implementations.Library IEnumerable<IBaseItemComparer> itemComparers, IEnumerable<ILibraryPrescanTask> prescanTasks, IEnumerable<ILibraryPostScanTask> postscanTasks, - IEnumerable<IPeoplePrescanTask> peoplePrescanTasks, - IEnumerable<IMetadataSaver> savers) + IEnumerable<IPeoplePrescanTask> peoplePrescanTasks) { EntityResolutionIgnoreRules = rules.ToArray(); PluginFolderCreators = pluginFolders.ToArray(); @@ -226,7 +226,6 @@ namespace MediaBrowser.Server.Implementations.Library PrescanTasks = prescanTasks; PostscanTasks = postscanTasks; PeoplePrescanTasks = peoplePrescanTasks; - _savers = savers; } /// <summary> @@ -1375,9 +1374,9 @@ namespace MediaBrowser.Server.Implementations.Library { if (item.LocationType == LocationType.FileSystem) { - await SaveMetadata(item, updateReason).ConfigureAwait(false); + await _providerManagerFactory().SaveMetadata(item, updateReason).ConfigureAwait(false); } - + item.DateLastSaved = DateTime.UtcNow; await ItemRepository.SaveItem(item, cancellationToken).ConfigureAwait(false); @@ -1440,49 +1439,6 @@ namespace MediaBrowser.Server.Implementations.Library return ItemRepository.RetrieveItem(id); } - private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>(); - - /// <summary> - /// Saves the metadata. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="updateType">Type of the update.</param> - /// <returns>Task.</returns> - public async Task SaveMetadata(BaseItem item, ItemUpdateType updateType) - { - var locationType = item.LocationType; - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) - { - throw new ArgumentException("Only file-system based items can save metadata."); - } - - foreach (var saver in _savers.Where(i => i.IsEnabledFor(item, updateType))) - { - var path = saver.GetSavePath(item); - - var semaphore = _fileLocks.GetOrAdd(path, key => new SemaphoreSlim(1, 1)); - - var libraryMonitor = _libraryMonitorFactory(); - - await semaphore.WaitAsync().ConfigureAwait(false); - - try - { - libraryMonitor.ReportFileSystemChangeBeginning(path); - saver.Save(item, CancellationToken.None); - } - catch (Exception ex) - { - _logger.ErrorException("Error in metadata saver", ex); - } - finally - { - libraryMonitor.ReportFileSystemChangeComplete(path, false); - semaphore.Release(); - } - } - } - /// <summary> /// Finds the type of the collection. /// </summary> diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 4fa345829..88a928795 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -282,7 +282,7 @@ namespace MediaBrowser.ServerApplication UserManager = new UserManager(Logger, ServerConfigurationManager, UserRepository); RegisterSingleInstance(UserManager); - LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager); + LibraryManager = new LibraryManager(Logger, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager); RegisterSingleInstance(LibraryManager); LibraryMonitor = new LibraryMonitor(LogManager, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager); @@ -499,10 +499,10 @@ namespace MediaBrowser.ServerApplication GetExports<IBaseItemComparer>(), GetExports<ILibraryPrescanTask>(), GetExports<ILibraryPostScanTask>(), - GetExports<IPeoplePrescanTask>(), - GetExports<IMetadataSaver>()); + GetExports<IPeoplePrescanTask>()); - ProviderManager.AddParts(GetExports<BaseMetadataProvider>(), GetExports<IImageProvider>(), GetExports<IMetadataService>(), GetExports<IMetadataProvider>()); + ProviderManager.AddParts(GetExports<BaseMetadataProvider>(), GetExports<IImageProvider>(), GetExports<IMetadataService>(), GetExports<IMetadataProvider>(), + GetExports<IMetadataSaver>()); ImageProcessor.AddParts(GetExports<IImageEnhancer>()); diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index 607b286ed..daf905a8a 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common.Internal</id> - <version>3.0.310</version> + <version>3.0.317</version> <title>MediaBrowser.Common.Internal</title> <authors>Luke</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.310" /> + <dependency id="MediaBrowser.Common" version="3.0.317" /> <dependency id="NLog" version="2.1.0" /> <dependency id="SimpleInjector" version="2.4.1" /> <dependency id="sharpcompress" version="0.10.2" /> diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 3222e429b..4a3c25880 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd"> <metadata> <id>MediaBrowser.Common</id> - <version>3.0.310</version> + <version>3.0.317</version> <title>MediaBrowser.Common</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index abfd72ff3..08f0a1188 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ <package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> <metadata> <id>MediaBrowser.Server.Core</id> - <version>3.0.310</version> + <version>3.0.317</version> <title>Media Browser.Server.Core</title> <authors>Media Browser Team</authors> <owners>ebr,Luke,scottisafool</owners> @@ -12,7 +12,7 @@ <description>Contains core components required to build plugins for Media Browser Server.</description> <copyright>Copyright © Media Browser 2013</copyright> <dependencies> - <dependency id="MediaBrowser.Common" version="3.0.310" /> + <dependency id="MediaBrowser.Common" version="3.0.317" /> </dependencies> </metadata> <files> |
