From 12757d094b4998be8b56fc51e5199358d819d0da Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 7 Feb 2014 17:40:03 -0500 Subject: [PATCH] use music brainz values from audio files with bottom up refresh --- MediaBrowser.Api/Images/ImageService.cs | 7 +- MediaBrowser.Api/Images/RemoteImageService.cs | 8 +- .../Entities/Audio/MusicAlbum.cs | 11 ++- .../Entities/Audio/MusicArtist.cs | 27 +++++- .../Entities/Audio/MusicGenre.cs | 25 ++++++ MediaBrowser.Controller/Entities/BaseItem.cs | 11 ++- MediaBrowser.Controller/Entities/GameGenre.cs | 26 +++++- MediaBrowser.Controller/Entities/Genre.cs | 25 ++++++ MediaBrowser.Controller/Entities/Person.cs | 31 ++++++- MediaBrowser.Controller/Entities/Studio.cs | 25 ++++++ MediaBrowser.Controller/Entities/User.cs | 30 +++++++ MediaBrowser.Controller/Entities/Year.cs | 25 ++++++ .../LiveTv/LiveTvAudioRecording.cs | 25 ++++++ .../LiveTv/LiveTvChannel.cs | 25 ++++++ .../LiveTv/LiveTvProgram.cs | 25 ++++++ .../LiveTv/LiveTvVideoRecording.cs | 25 ++++++ .../Providers/BaseItemXmlParser.cs | 22 ++++- .../Providers/ILocalImageProvider.cs | 2 +- .../Entities/MetadataProviders.cs | 7 +- .../All/LocalImageProvider.cs | 85 ++++++++----------- .../Manager/ItemImageProvider.cs | 8 +- .../Manager/MetadataService.cs | 5 -- .../MediaBrowser.Providers.csproj | 1 + .../MediaInfo/FFProbeAudioInfo.cs | 5 ++ MediaBrowser.Providers/Music/Extensions.cs | 67 +++++++++++++++ .../Music/FanArtAlbumProvider.cs | 22 +++-- .../Music/FanArtArtistProvider.cs | 4 +- .../Music/LastFmImageProvider.cs | 4 +- .../Music/LastfmAlbumProvider.cs | 17 ++-- .../Music/LastfmArtistProvider.cs | 4 +- .../Music/MusicBrainzAlbumProvider.cs | 32 ++++--- .../Music/MusicBrainzArtistProvider.cs | 4 +- .../Savers/XmlSaverHelpers.cs | 18 +++- .../TV/EpisodeLocalImageProvider.cs | 8 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 37 files changed, 544 insertions(+), 132 deletions(-) create mode 100644 MediaBrowser.Providers/Music/Extensions.cs diff --git a/MediaBrowser.Api/Images/ImageService.cs b/MediaBrowser.Api/Images/ImageService.cs index 8cc1eabd0..8dfecceec 100644 --- a/MediaBrowser.Api/Images/ImageService.cs +++ b/MediaBrowser.Api/Images/ImageService.cs @@ -789,12 +789,7 @@ namespace MediaBrowser.Api.Images await _providerManager.SaveImage(entity, memoryStream, mimeType, imageType, null, CancellationToken.None).ConfigureAwait(false); - await entity.RefreshMetadata(new MetadataRefreshOptions - { - ImageRefreshMode = ImageRefreshMode.ValidationOnly, - ForceSave = true - - }, CancellationToken.None).ConfigureAwait(false); + await entity.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); } } } diff --git a/MediaBrowser.Api/Images/RemoteImageService.cs b/MediaBrowser.Api/Images/RemoteImageService.cs index deba146e8..dfa245c0e 100644 --- a/MediaBrowser.Api/Images/RemoteImageService.cs +++ b/MediaBrowser.Api/Images/RemoteImageService.cs @@ -281,13 +281,7 @@ namespace MediaBrowser.Api.Images { await _providerManager.SaveImage(item, request.ImageUrl, null, request.Type, null, CancellationToken.None).ConfigureAwait(false); - await item.RefreshMetadata(new MetadataRefreshOptions - { - ForceSave = true, - ImageRefreshMode = ImageRefreshMode.ValidationOnly, - MetadataRefreshMode = MetadataRefreshMode.None - - }, CancellationToken.None).ConfigureAwait(false); + await item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); } /// diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 6dda902c9..8b8c1a6ff 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -22,6 +22,15 @@ namespace MediaBrowser.Controller.Entities.Audio Tags = new List(); } + [IgnoreDataMember] + public MusicArtist MusicArtist + { + get + { + return Parents.OfType().FirstOrDefault(); + } + } + /// /// Gets or sets the tags. /// @@ -99,7 +108,7 @@ namespace MediaBrowser.Controller.Entities.Audio return "MusicAlbum-MusicBrainzReleaseGroup-" + id; } - id = this.GetProviderId(MetadataProviders.Musicbrainz); + id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); if (!string.IsNullOrEmpty(id)) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 570a011c2..e80aaa69a 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -89,6 +89,31 @@ namespace MediaBrowser.Controller.Entities.Audio return GetUserDataKey(this); } + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } + /// /// Gets the user data key. /// @@ -96,7 +121,7 @@ namespace MediaBrowser.Controller.Entities.Audio /// System.String. private static string GetUserDataKey(MusicArtist item) { - var id = item.GetProviderId(MetadataProviders.Musicbrainz); + var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!string.IsNullOrEmpty(id)) { diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index b54e14f2d..5e1d4c3c9 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities.Audio [IgnoreDataMember] public List UserItemCountList { get; set; } + + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 35691a080..01e8741af 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -124,7 +124,7 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public bool IsOwnedItem + public virtual bool IsOwnedItem { get { @@ -1215,7 +1215,12 @@ namespace MediaBrowser.Controller.Entities currentFile.Delete(); } - return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, CancellationToken.None); + return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + } + + public virtual Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) + { + return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, cancellationToken); } /// @@ -1370,7 +1375,7 @@ namespace MediaBrowser.Controller.Entities info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path); info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path); - return LibraryManager.UpdateItem(this, ItemUpdateType.ImageUpdate, CancellationToken.None); + return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); } public virtual bool IsPlayed(User user) diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index ffe62ba03..3a3c575cd 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Dto; -using System; using System.Collections.Generic; using System.Runtime.Serialization; @@ -23,5 +22,30 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public List UserItemCountList { get; set; } + + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } } } diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 53bc64194..c15ca0aa2 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -25,5 +25,30 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public List UserItemCountList { get; set; } + + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } } } diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index acf750870..c1dc81136 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -8,7 +8,7 @@ namespace MediaBrowser.Controller.Entities /// /// This is the full Person object that can be retrieved with all of it's data. /// - public class Person : BaseItem, IItemByName, IHasLookupInfo + public class Person : BaseItem, IItemByName, IHasLookupInfo { public Person() { @@ -33,9 +33,34 @@ namespace MediaBrowser.Controller.Entities return "Person-" + Name; } - public Providers.PersonLookupInfo GetLookupInfo() + public PersonLookupInfo GetLookupInfo() { - return GetItemLookupInfo(); + return GetItemLookupInfo(); + } + + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } } } diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 7bc17549f..5c3946f9b 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public List UserItemCountList { get; set; } + + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } } } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index ddaa0eb26..66ef8c7dc 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -72,6 +72,31 @@ namespace MediaBrowser.Controller.Entities } } + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } + /// /// The _root folder /// @@ -222,6 +247,11 @@ namespace MediaBrowser.Controller.Entities }, CancellationToken.None); } + public override Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) + { + return UserManager.UpdateUser(this); + } + /// /// Gets the path to the user's configuration directory /// diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index cd50a1c60..c6ca028ae 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -26,5 +26,30 @@ namespace MediaBrowser.Controller.Entities { return "Year-" + Name; } + + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 93de9d5c3..f093ef7cb 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -25,6 +25,31 @@ namespace MediaBrowser.Controller.LiveTv public string ServiceName { get; set; } + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } + public override string MediaType { get diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index f37e94714..583b90fd4 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -25,6 +25,31 @@ namespace MediaBrowser.Controller.LiveTv [IgnoreDataMember] public List UserItemCountList { get; set; } + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } + /// /// Gets or sets the number. /// diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 6a00607e4..497cfad67 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -127,6 +127,31 @@ namespace MediaBrowser.Controller.LiveTv /// true if this instance is premiere; otherwise, false. public bool IsPremiere { get; set; } + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } + public override string MediaType { get diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index bc4ed5493..aad760cc9 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -46,6 +46,31 @@ namespace MediaBrowser.Controller.LiveTv } } + /// + /// Returns the folder containing the item. + /// If the item is a folder, it returns the folder itself + /// + /// The containing folder path. + public override string ContainingFolderPath + { + get + { + return Path; + } + } + + /// + /// Gets a value indicating whether this instance is owned item. + /// + /// true if this instance is owned item; otherwise, false. + public override bool IsOwnedItem + { + get + { + return false; + } + } + public override string GetClientTypeName() { return "Recording"; diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs index 76530d7dd..dbb8c1edf 100644 --- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs @@ -680,12 +680,30 @@ namespace MediaBrowser.Controller.Providers } break; } - case "MusicbrainzId": + case "MusicBrainzAlbumId": { var mbz = reader.ReadElementContentAsString(); if (!string.IsNullOrWhiteSpace(mbz)) { - item.SetProviderId(MetadataProviders.Musicbrainz, mbz); + item.SetProviderId(MetadataProviders.MusicBrainzAlbum, mbz); + } + break; + } + case "MusicBrainzAlbumArtistId": + { + var mbz = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(mbz)) + { + item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, mbz); + } + break; + } + case "MusicBrainzArtistId": + { + var mbz = reader.ReadElementContentAsString(); + if (!string.IsNullOrWhiteSpace(mbz)) + { + item.SetProviderId(MetadataProviders.MusicBrainzArtist, mbz); } break; } diff --git a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs index 69242d1e2..d1ef68ce2 100644 --- a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs +++ b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs @@ -22,7 +22,7 @@ namespace MediaBrowser.Controller.Providers public class LocalImageInfo { - public string Path { get; set; } + public FileInfo FileInfo { get; set; } public ImageType Type { get; set; } } diff --git a/MediaBrowser.Model/Entities/MetadataProviders.cs b/MediaBrowser.Model/Entities/MetadataProviders.cs index 5ef449317..5f55e1287 100644 --- a/MediaBrowser.Model/Entities/MetadataProviders.cs +++ b/MediaBrowser.Model/Entities/MetadataProviders.cs @@ -24,10 +24,6 @@ namespace MediaBrowser.Model.Entities /// Tvcom, /// - /// MusicBrainz - /// - Musicbrainz, - /// /// The rotten tomatoes /// RottenTomatoes, @@ -35,6 +31,9 @@ namespace MediaBrowser.Model.Entities /// Tmdb Collection Id /// TmdbCollection, + MusicBrainzAlbum, + MusicBrainzAlbumArtist, + MusicBrainzArtist, MusicBrainzReleaseGroup, Zap2It, NesBox, diff --git a/MediaBrowser.Providers/All/LocalImageProvider.cs b/MediaBrowser.Providers/All/LocalImageProvider.cs index 5883781f9..0d078499d 100644 --- a/MediaBrowser.Providers/All/LocalImageProvider.cs +++ b/MediaBrowser.Providers/All/LocalImageProvider.cs @@ -65,25 +65,29 @@ namespace MediaBrowser.Providers.All return false; } - private IEnumerable GetFiles(IHasImages item, bool includeDirectories) + private IEnumerable GetFiles(IHasImages item, bool includeDirectories) { if (item.LocationType != LocationType.FileSystem) { - return new List(); + return new List(); } var path = item.ContainingFolderPath; if (includeDirectories) { - return Directory.EnumerateFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly); + return new DirectoryInfo(path).EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly) + .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase) || + (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory); } - return Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly); + + return new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly) + .Where(i => BaseItem.SupportedImageExtensions.Contains(i.Extension, StringComparer.OrdinalIgnoreCase)); } public List GetImages(IHasImages item) { - var files = GetFileDictionary(GetFiles(item, true)); + var files = GetFiles(item, true).ToList(); var list = new List(); @@ -92,7 +96,7 @@ namespace MediaBrowser.Providers.All return list; } - private void PopulateImages(IHasImages item, List images, Dictionary files) + private void PopulateImages(IHasImages item, List images, List files) { var imagePrefix = string.Empty; @@ -130,7 +134,7 @@ namespace MediaBrowser.Providers.All } } - private void PopulatePrimaryImages(IHasImages item, List images, Dictionary files, string imagePrefix) + private void PopulatePrimaryImages(IHasImages item, List images, List files, string imagePrefix) { AddImage(files, images, imagePrefix + "folder", ImageType.Primary); AddImage(files, images, imagePrefix + "cover", ImageType.Primary); @@ -161,7 +165,7 @@ namespace MediaBrowser.Providers.All } } - private void PopulateBackdrops(IHasImages item, List images, Dictionary files, string imagePrefix) + private void PopulateBackdrops(IHasImages item, List images, List files, string imagePrefix) { PopulateBackdrops(images, files, imagePrefix, "backdrop", "backdrop", ImageType.Backdrop); @@ -179,19 +183,21 @@ namespace MediaBrowser.Providers.All PopulateBackdrops(images, files, imagePrefix, "background", "background-", ImageType.Backdrop); PopulateBackdrops(images, files, imagePrefix, "art", "art-", ImageType.Backdrop); - string extraFanartFolder; - if (files.TryGetValue("extrafanart", out extraFanartFolder)) + var extraFanartFolder = files.OfType() + .FirstOrDefault(i => string.Equals(i.Name, "extrafanart", StringComparison.OrdinalIgnoreCase)); + + if (extraFanartFolder != null) { - PopulateBackdropsFromExtraFanart(extraFanartFolder, images); + PopulateBackdropsFromExtraFanart(extraFanartFolder.FullName, images); } } private void PopulateBackdropsFromExtraFanart(string path, List images) { - var imageFiles = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly) + var imageFiles = new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly) .Where(i => { - var extension = Path.GetExtension(i); + var extension = i.Extension; if (string.IsNullOrEmpty(extension)) { @@ -203,17 +209,17 @@ namespace MediaBrowser.Providers.All images.AddRange(imageFiles.Select(i => new LocalImageInfo { - Path = i, + FileInfo = i, Type = ImageType.Backdrop })); } - private void PopulateScreenshots(List images, Dictionary files, string imagePrefix) + private void PopulateScreenshots(List images, List files, string imagePrefix) { PopulateBackdrops(images, files, imagePrefix, "screenshot", "screenshot", ImageType.Screenshot); } - private void PopulateBackdrops(List images, Dictionary files, string imagePrefix, string firstFileName, string subsequentFileNamePrefix, ImageType type) + private void PopulateBackdrops(List images, List files, string imagePrefix, string firstFileName, string subsequentFileNamePrefix, ImageType type) { AddImage(files, images, imagePrefix + firstFileName, type); @@ -246,7 +252,7 @@ namespace MediaBrowser.Providers.All return; } - var files = GetFileDictionary(GetFiles(series, false)); + var seriesFiles = GetFiles(series, false).ToList(); // Try using the season name var prefix = season.Name.ToLower().Replace(" ", string.Empty); @@ -265,39 +271,22 @@ namespace MediaBrowser.Providers.All foreach (var filename in filenamePrefixes) { - AddImage(files, images, filename + "-poster", ImageType.Primary); - AddImage(files, images, filename + "-fanart", ImageType.Backdrop); - AddImage(files, images, filename + "-banner", ImageType.Banner); - AddImage(files, images, filename + "-landscape", ImageType.Thumb); + AddImage(seriesFiles, images, filename + "-poster", ImageType.Primary); + AddImage(seriesFiles, images, filename + "-fanart", ImageType.Backdrop); + AddImage(seriesFiles, images, filename + "-banner", ImageType.Banner); + AddImage(seriesFiles, images, filename + "-landscape", ImageType.Thumb); } } - private Dictionary GetFileDictionary(IEnumerable paths) + private bool AddImage(List files, List images, string name, ImageType type) { - var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (var path in paths) - { - var filename = Path.GetFileName(path); - - if (!string.IsNullOrEmpty(filename)) - { - dict[filename] = path; - } - } - - return dict; - } - - private bool AddImage(Dictionary dict, List images, string name, ImageType type) - { - var image = GetImage(dict, name); + var image = GetImage(files, name) as FileInfo; if (image != null) { images.Add(new LocalImageInfo { - Path = image, + FileInfo = image, Type = type }); @@ -307,16 +296,14 @@ namespace MediaBrowser.Providers.All return false; } - private string GetImage(Dictionary dict, string name) + private FileSystemInfo GetImage(IEnumerable files, string name) { - return BaseItem.SupportedImageExtensions - .Select(i => - { - var filename = name + i; - string path; + var candidates = files + .Where(i => string.Equals(name, Path.GetFileNameWithoutExtension(i.Name), StringComparison.OrdinalIgnoreCase)) + .ToList(); - return dict.TryGetValue(filename, out path) ? path : null; - }) + return BaseItem.SupportedImageExtensions + .Select(i => candidates.FirstOrDefault(c => string.Equals(c.Extension, i, StringComparison.OrdinalIgnoreCase))) .FirstOrDefault(i => i != null); } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 74c73821c..4ba959d14 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -275,9 +275,9 @@ namespace MediaBrowser.Providers.Manager { var currentImage = item.GetImageInfo(type, 0); - if (currentImage == null || !string.Equals(currentImage.Path, image.Path, StringComparison.OrdinalIgnoreCase)) + if (currentImage == null || !string.Equals(currentImage.Path, image.FileInfo.FullName, StringComparison.OrdinalIgnoreCase)) { - item.SetImagePath(type, new FileInfo(image.Path)); + item.SetImagePath(type, image.FileInfo); changed = true; } } @@ -287,7 +287,7 @@ namespace MediaBrowser.Providers.Manager if (backdrops.Count > 0) { var foundImages = images.Where(i => i.Type == ImageType.Backdrop) - .Select(i => new FileInfo(i.Path)) + .Select(i => i.FileInfo) .ToList(); if (foundImages.Count > 0) @@ -303,7 +303,7 @@ namespace MediaBrowser.Providers.Manager if (hasScreenshots != null) { var foundImages = images.Where(i => i.Type == ImageType.Screenshot) - .Select(i => new FileInfo(i.Path)) + .Select(i => i.FileInfo) .ToList(); if (foundImages.Count > 0) diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index bf186acc1..21173aebc 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -197,11 +197,6 @@ namespace MediaBrowser.Providers.Manager .Where(i => i.HasChanged(currentItem, currentItem.DateLastSaved)) .ToList(); - if (providersWithChanges.Count > 0) - { - var b = true; - } - // If local providers are the only ones with changes, then just run those if (providersWithChanges.All(i => i is ILocalMetadataProvider)) { diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 54da3471c..da9ea2947 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -117,6 +117,7 @@ + diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 4fc92ddeb..48e76e3b4 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -178,6 +178,11 @@ namespace MediaBrowser.Providers.MediaInfo FetchStudios(audio, tags, "ensemble"); FetchStudios(audio, tags, "publisher"); } + + audio.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Artist Id")); + audio.SetProviderId(MetadataProviders.MusicBrainzArtist, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Artist Id")); + audio.SetProviderId(MetadataProviders.MusicBrainzAlbum, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Album Id")); + audio.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, FFProbeHelpers.GetDictionaryValue(tags, "MusicBrainz Release Group Id")); } private readonly char[] _nameDelimiters = new[] { '/', '|', ';', '\\' }; diff --git a/MediaBrowser.Providers/Music/Extensions.cs b/MediaBrowser.Providers/Music/Extensions.cs new file mode 100644 index 000000000..0ba02cbec --- /dev/null +++ b/MediaBrowser.Providers/Music/Extensions.cs @@ -0,0 +1,67 @@ +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using System.Linq; + +namespace MediaBrowser.Providers.Music +{ + public static class Extensions + { + public static string GetAlbumArtist(this AlbumInfo info) + { + var id = info.AlbumArtist; + + if (string.IsNullOrEmpty(id)) + { + return info.SongInfos.Select(i => i.AlbumArtist) + .FirstOrDefault(i => !string.IsNullOrEmpty(i)); + } + + return id; + } + + public static string GetReleaseGroupId(this AlbumInfo info) + { + var id = info.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); + + if (string.IsNullOrEmpty(id)) + { + return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup)) + .FirstOrDefault(i => !string.IsNullOrEmpty(i)); + } + + return id; + } + + public static string GetReleaseId(this AlbumInfo info) + { + var id = info.GetProviderId(MetadataProviders.MusicBrainzAlbum); + + if (string.IsNullOrEmpty(id)) + { + return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzAlbum)) + .FirstOrDefault(i => !string.IsNullOrEmpty(i)); + } + + return id; + } + + public static string GetArtistId(this AlbumInfo info) + { + string id; + info.ProviderIds.TryGetValue(MetadataProviders.MusicBrainzAlbumArtist.ToString(), out id); + + if (string.IsNullOrEmpty(id)) + { + info.ArtistProviderIds.TryGetValue(MetadataProviders.MusicBrainzArtist.ToString(), out id); + } + + if (string.IsNullOrEmpty(id)) + { + return info.SongInfos.Select(i => i.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist)) + .FirstOrDefault(i => !string.IsNullOrEmpty(i)); + } + + return id; + } + } +} diff --git a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs index 343097639..f268cc910 100644 --- a/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtAlbumProvider.cs @@ -70,7 +70,7 @@ namespace MediaBrowser.Providers.Music var list = new List(); - var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz); + var artistMusicBrainzId = album.MusicArtist.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!string.IsNullOrEmpty(artistMusicBrainzId)) { @@ -80,7 +80,7 @@ namespace MediaBrowser.Providers.Music var musicBrainzReleaseGroupId = album.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); - var musicBrainzId = album.GetProviderId(MetadataProviders.Musicbrainz); + var musicBrainzId = album.GetProviderId(MetadataProviders.MusicBrainzAlbum); try { @@ -365,17 +365,21 @@ namespace MediaBrowser.Providers.Music } var album = (MusicAlbum)item; + var artist = album.MusicArtist; - var artistMusicBrainzId = album.Parent.GetProviderId(MetadataProviders.Musicbrainz); - - if (!String.IsNullOrEmpty(artistMusicBrainzId)) + if (artist != null) { - // Process images - var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId); + var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.MusicBrainzArtist); - var fileInfo = new FileInfo(artistXmlPath); + if (!String.IsNullOrEmpty(artistMusicBrainzId)) + { + // Process images + var artistXmlPath = FanartArtistProvider.GetArtistXmlPath(_config.CommonApplicationPaths, artistMusicBrainzId); - return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + var fileInfo = new FileInfo(artistXmlPath); + + return !fileInfo.Exists || _fileSystem.GetLastWriteTimeUtc(fileInfo) > date; + } } return false; diff --git a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs index c8f3ccfa3..8e27d6891 100644 --- a/MediaBrowser.Providers/Music/FanArtArtistProvider.cs +++ b/MediaBrowser.Providers/Music/FanArtArtistProvider.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Providers.Music var list = new List(); - var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz); + var artistMusicBrainzId = artist.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!String.IsNullOrEmpty(artistMusicBrainzId)) { @@ -381,7 +381,7 @@ namespace MediaBrowser.Providers.Music return false; } - var id = item.GetProviderId(MetadataProviders.Musicbrainz); + var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!String.IsNullOrEmpty(id)) { diff --git a/MediaBrowser.Providers/Music/LastFmImageProvider.cs b/MediaBrowser.Providers/Music/LastFmImageProvider.cs index 659ae5bef..26a89fa95 100644 --- a/MediaBrowser.Providers/Music/LastFmImageProvider.cs +++ b/MediaBrowser.Providers/Music/LastFmImageProvider.cs @@ -61,7 +61,9 @@ namespace MediaBrowser.Providers.Music RemoteImageInfo info = null; - var musicBrainzId = item.GetProviderId(MetadataProviders.Musicbrainz); + var musicBrainzId = item is MusicAlbum ? + item.GetProviderId(MetadataProviders.MusicBrainzAlbum) : + item.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!string.IsNullOrEmpty(musicBrainzId)) { diff --git a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs index 88be04a7e..0affbf909 100644 --- a/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs +++ b/MediaBrowser.Providers/Music/LastfmAlbumProvider.cs @@ -48,9 +48,10 @@ namespace MediaBrowser.Providers.Music private async Task GetAlbumResult(AlbumInfo item, CancellationToken cancellationToken) { // Try album release Id - if (!string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Musicbrainz))) + var id = item.GetReleaseId(); + if (!string.IsNullOrEmpty(id)) { - var result = await GetAlbumResult(item.GetProviderId(MetadataProviders.Musicbrainz), cancellationToken).ConfigureAwait(false); + var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false); if (result != null && result.album != null) { @@ -59,9 +60,10 @@ namespace MediaBrowser.Providers.Music } // Try album release group Id - if (!string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup))) + id = item.GetReleaseGroupId(); + if (!string.IsNullOrEmpty(id)) { - var result = await GetAlbumResult(item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup), cancellationToken).ConfigureAwait(false); + var result = await GetAlbumResult(id, cancellationToken).ConfigureAwait(false); if (result != null && result.album != null) { @@ -69,6 +71,7 @@ namespace MediaBrowser.Providers.Music } } + var albumArtist = item.GetAlbumArtist(); //// Get each song, distinct by the combination of AlbumArtist and Album //var songs = item.RecursiveChildren.OfType