consolidate Artist & MusicArtist

This commit is contained in:
Luke Pulverenti 2013-11-21 15:48:26 -05:00
parent ee1a746031
commit 17bacee089
35 changed files with 248 additions and 502 deletions

View File

@ -92,7 +92,7 @@ namespace MediaBrowser.Api
private readonly char[] _dashReplaceChars = new[] { '?', '/' }; private readonly char[] _dashReplaceChars = new[] { '?', '/' };
private const char SlugChar = '-'; private const char SlugChar = '-';
protected Artist GetArtist(string name, ILibraryManager libraryManager) protected MusicArtist GetArtist(string name, ILibraryManager libraryManager)
{ {
return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager)); return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager));
} }
@ -147,21 +147,7 @@ namespace MediaBrowser.Api
return name; return name;
} }
return libraryManager.RootFolder.GetRecursiveChildren() return libraryManager.GetAllArtists()
.OfType<Audio>()
.SelectMany(i =>
{
var list = new List<string>();
if (!string.IsNullOrEmpty(i.AlbumArtist))
{
list.Add(i.AlbumArtist);
}
list.AddRange(i.Artists);
return list;
})
.Distinct(StringComparer.OrdinalIgnoreCase)
.FirstOrDefault(i => .FirstOrDefault(i =>
{ {
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar)); i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));

View File

@ -194,20 +194,7 @@ namespace MediaBrowser.Api.DefaultTheme
.Select(i => _dtoService.GetBaseItemDto(i, fields, user)) .Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToList(); .ToList();
var artists = allItems.OfType<Audio>() var artists = _libraryManager.GetAllArtists(allItems)
.SelectMany(i =>
{
var list = new List<string>();
if (!string.IsNullOrEmpty(i.AlbumArtist))
{
list.Add(i.AlbumArtist);
}
list.AddRange(i.Artists);
return list;
})
.Distinct(StringComparer.OrdinalIgnoreCase)
.Randomize() .Randomize()
.Select(i => .Select(i =>
{ {

View File

@ -264,16 +264,14 @@ namespace MediaBrowser.Api
{ {
var item = _dtoService.GetItemByDtoId(request.Id); var item = _dtoService.GetItemByDtoId(request.Id);
var folder = item as Folder;
try try
{ {
await item.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false); await item.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false);
if (folder != null) if (item.IsFolder)
{ {
// Collection folders don't validate their children so we'll have to simulate that here // Collection folders don't validate their children so we'll have to simulate that here
var collectionFolder = folder as CollectionFolder; var collectionFolder = item as CollectionFolder;
if (collectionFolder != null) if (collectionFolder != null)
{ {
@ -281,6 +279,8 @@ namespace MediaBrowser.Api
} }
else else
{ {
var folder = (Folder)item;
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false); await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
} }
} }
@ -303,10 +303,10 @@ namespace MediaBrowser.Api
{ {
await child.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false); await child.RefreshMetadata(CancellationToken.None, forceRefresh: request.Forced).ConfigureAwait(false);
var folder = child as Folder; if (child.IsFolder)
if (folder != null)
{ {
var folder = (Folder)child;
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false); await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
} }
} }

View File

@ -126,15 +126,6 @@ namespace MediaBrowser.Api
UpdateItem(request, item); UpdateItem(request, item);
await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); await _libraryManager.UpdateItem(item, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
var musicArtist = Artist.FindMusicArtist(item, _libraryManager);
if (musicArtist != null)
{
UpdateItem(request, musicArtist);
await _libraryManager.UpdateItem(musicArtist, ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false);
}
} }
public void Post(UpdateStudio request) public void Post(UpdateStudio request)

View File

@ -367,7 +367,7 @@ namespace MediaBrowser.Api
BoxSetCount = boxsets.Count, BoxSetCount = boxsets.Count,
BookCount = books.Count, BookCount = books.Count,
UniqueTypes = items.Select(i => i.GetType().Name).Distinct().ToList() UniqueTypes = items.Select(i => i.GetClientTypeName()).Distinct().ToList()
}; };
var people = items.SelectMany(i => i.People) var people = items.SelectMany(i => i.People)
@ -390,19 +390,7 @@ namespace MediaBrowser.Api
people = request.UserId.HasValue ? FilterItems(people, request, request.UserId.Value).ToList() : people; people = request.UserId.HasValue ? FilterItems(people, request, request.UserId.Value).ToList() : people;
counts.PersonCount = people.Count; counts.PersonCount = people.Count;
var artists = items.OfType<Audio>().SelectMany(i => var artists = _libraryManager.GetAllArtists(items)
{
var list = new List<string>();
if (!string.IsNullOrEmpty(i.AlbumArtist))
{
list.Add(i.AlbumArtist);
}
list.AddRange(i.Artists);
return list;
})
.Distinct(StringComparer.OrdinalIgnoreCase)
.Select(i => .Select(i =>
{ {
try try

View File

@ -144,7 +144,7 @@ namespace MediaBrowser.Api
IndexNumber = item.IndexNumber, IndexNumber = item.IndexNumber,
ParentIndexNumber = item.ParentIndexNumber, ParentIndexNumber = item.ParentIndexNumber,
ItemId = _dtoService.GetDtoId(item), ItemId = _dtoService.GetDtoId(item),
Type = item.GetType().Name, Type = item.GetClientTypeName(),
MediaType = item.MediaType, MediaType = item.MediaType,
MatchedTerm = hintInfo.MatchedTerm, MatchedTerm = hintInfo.MatchedTerm,
DisplayMediaType = item.DisplayMediaType, DisplayMediaType = item.DisplayMediaType,
@ -187,9 +187,7 @@ namespace MediaBrowser.Api
result.SongCount = songs.Count; result.SongCount = songs.Count;
result.Artists = songs result.Artists = _libraryManager.GetAllArtists(songs)
.SelectMany(i => i.Artists)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToArray(); .ToArray();
result.AlbumArtist = songs.Select(i => i.AlbumArtist).FirstOrDefault(i => !string.IsNullOrEmpty(i)); result.AlbumArtist = songs.Select(i => i.AlbumArtist).FirstOrDefault(i => !string.IsNullOrEmpty(i));

View File

@ -43,7 +43,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary> /// <summary>
/// Class ArtistsService /// Class ArtistsService
/// </summary> /// </summary>
public class ArtistsService : BaseItemsByNameService<Artist> public class ArtistsService : BaseItemsByNameService<MusicArtist>
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ArtistsService" /> class. /// Initializes a new instance of the <see cref="ArtistsService" /> class.
@ -109,24 +109,9 @@ namespace MediaBrowser.Api.UserLibrary
/// <param name="request">The request.</param> /// <param name="request">The request.</param>
/// <param name="items">The items.</param> /// <param name="items">The items.</param>
/// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns> /// <returns>IEnumerable{Tuple{System.StringFunc{System.Int32}}}.</returns>
protected override IEnumerable<Artist> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items) protected override IEnumerable<MusicArtist> GetAllItems(GetItemsByName request, IEnumerable<BaseItem> items)
{ {
var itemsList = items.OfType<Audio>().ToList(); return LibraryManager.GetAllArtists(items)
return itemsList
.SelectMany(i =>
{
var list = new List<string>();
if (!string.IsNullOrEmpty(i.AlbumArtist))
{
list.Add(i.AlbumArtist);
}
list.AddRange(i.Artists);
return list;
})
.Distinct(StringComparer.OrdinalIgnoreCase)
.Select(name => LibraryManager.GetArtist(name)); .Select(name => LibraryManager.GetArtist(name));
} }
} }

View File

@ -1,86 +0,0 @@
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities.Audio
{
/// <summary>
/// Class Artist
/// </summary>
public class Artist : BaseItem, IItemByName, IHasMusicGenres
{
public Artist()
{
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
}
public string LastFmImageUrl { get; set; }
public string LastFmImageSize { get; set; }
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
public override string GetUserDataKey()
{
return GetUserDataKey(this);
}
[IgnoreDataMember]
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
/// <summary>
/// Finds the music artist.
/// </summary>
/// <param name="artist">The artist.</param>
/// <param name="libraryManager">The library manager.</param>
/// <returns>MusicArtist.</returns>
public static MusicArtist FindMusicArtist(Artist artist, ILibraryManager libraryManager)
{
return FindMusicArtist(artist, libraryManager.RootFolder.RecursiveChildren.OfType<MusicArtist>());
}
/// <summary>
/// Finds the music artist.
/// </summary>
/// <param name="artist">The artist.</param>
/// <param name="allMusicArtists">All music artists.</param>
/// <returns>MusicArtist.</returns>
public static MusicArtist FindMusicArtist(Artist artist, IEnumerable<MusicArtist> allMusicArtists)
{
var musicBrainzId = artist.GetProviderId(MetadataProviders.Musicbrainz);
return allMusicArtists.FirstOrDefault(i =>
{
if (!string.IsNullOrWhiteSpace(musicBrainzId) && string.Equals(musicBrainzId, i.GetProviderId(MetadataProviders.Musicbrainz), StringComparison.OrdinalIgnoreCase))
{
return true;
}
return string.Compare(i.Name, artist.Name, CultureInfo.CurrentCulture, CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols) == 0;
});
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public static string GetUserDataKey(BaseItem item)
{
var id = item.GetProviderId(MetadataProviders.Musicbrainz);
if (!string.IsNullOrEmpty(id))
{
return "Artist-Musicbrainz-" + id;
}
return "Artist-" + item.Name;
}
}
}

View File

@ -1,11 +1,52 @@
 using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities.Audio namespace MediaBrowser.Controller.Entities.Audio
{ {
/// <summary> /// <summary>
/// Class MusicArtist /// Class MusicArtist
/// </summary> /// </summary>
public class MusicArtist : Folder public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess
{ {
[IgnoreDataMember]
public Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
public bool IsAccessedByName { get; set; }
public override bool IsFolder
{
get
{
return !IsAccessedByName;
}
}
protected override IEnumerable<BaseItem> ActualChildren
{
get
{
if (IsAccessedByName)
{
throw new InvalidOperationException("Artists accessed by name do not have children.");
}
return base.ActualChildren;
}
}
public override string GetClientTypeName()
{
if (IsAccessedByName)
{
//return "Artist";
}
return base.GetClientTypeName();
}
/// <summary> /// <summary>
/// Gets or sets the last fm image URL. /// Gets or sets the last fm image URL.
/// </summary> /// </summary>
@ -13,13 +54,35 @@ namespace MediaBrowser.Controller.Entities.Audio
public string LastFmImageUrl { get; set; } public string LastFmImageUrl { get; set; }
public string LastFmImageSize { get; set; } public string LastFmImageSize { get; set; }
public MusicArtist()
{
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
}
/// <summary> /// <summary>
/// Gets the user data key. /// Gets the user data key.
/// </summary> /// </summary>
/// <returns>System.String.</returns> /// <returns>System.String.</returns>
public override string GetUserDataKey() public override string GetUserDataKey()
{ {
return Artist.GetUserDataKey(this); return GetUserDataKey(this);
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
public static string GetUserDataKey(BaseItem item)
{
var id = item.GetProviderId(MetadataProviders.Musicbrainz);
if (!string.IsNullOrEmpty(id))
{
return "Artist-Musicbrainz-" + id;
}
return "Artist-" + item.Name;
} }
} }
} }

View File

@ -1145,6 +1145,11 @@ namespace MediaBrowser.Controller.Entities
return changed; return changed;
} }
public virtual string GetClientTypeName()
{
return GetType().Name;
}
/// <summary> /// <summary>
/// Determines if the item is considered new based on user settings /// Determines if the item is considered new based on user settings
/// </summary> /// </summary>

View File

@ -1038,19 +1038,16 @@ namespace MediaBrowser.Controller.Entities
} }
} }
if (recursive) if (recursive && child.IsFolder)
{ {
var folder = child as Folder; var folder = (Folder)child;
if (folder != null)
{
if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter)) if (folder.AddChildrenToList(user, includeLinkedChildren, list, true, filter))
{ {
hasLinkedChildren = true; hasLinkedChildren = true;
} }
} }
} }
}
if (includeLinkedChildren) if (includeLinkedChildren)
{ {
@ -1150,17 +1147,14 @@ namespace MediaBrowser.Controller.Entities
list.Add(child); list.Add(child);
} }
if (recursive) if (recursive && child.IsFolder)
{ {
var folder = child as Folder; var folder = (Folder)child;
if (folder != null)
{
folder.AddChildrenToList(list, true, filter); folder.AddChildrenToList(list, true, filter);
} }
} }
} }
}
/// <summary> /// <summary>

View File

@ -12,6 +12,11 @@ namespace MediaBrowser.Controller.Entities
Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; } Dictionary<Guid, ItemByNameCounts> UserItemCounts { get; set; }
} }
public interface IHasDualAccess : IItemByName
{
bool IsAccessedByName { get; }
}
public static class IItemByNameExtensions public static class IItemByNameExtensions
{ {
public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, User user) public static ItemByNameCounts GetItemByNameCounts(this IItemByName item, User user)

View File

@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Library
/// </summary> /// </summary>
/// <param name="name">The name.</param> /// <param name="name">The name.</param>
/// <returns>Task{Artist}.</returns> /// <returns>Task{Artist}.</returns>
Artist GetArtist(string name); MusicArtist GetArtist(string name);
/// <summary> /// <summary>
/// Gets a Studio /// Gets a Studio
@ -302,5 +302,18 @@ namespace MediaBrowser.Controller.Library
/// <param name="updateType">Type of the update.</param> /// <param name="updateType">Type of the update.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task SaveMetadata(BaseItem item, ItemUpdateType updateType); Task SaveMetadata(BaseItem item, ItemUpdateType updateType);
/// <summary>
/// Gets all artists.
/// </summary>
/// <returns>IEnumerable{System.String}.</returns>
IEnumerable<string> GetAllArtists();
/// <summary>
/// Gets all artists.
/// </summary>
/// <param name="items">The items.</param>
/// <returns>IEnumerable{System.String}.</returns>
IEnumerable<string> GetAllArtists(IEnumerable<BaseItem> items);
} }
} }

View File

@ -115,7 +115,6 @@
<Compile Include="Session\ISessionManager.cs" /> <Compile Include="Session\ISessionManager.cs" />
<Compile Include="Drawing\ImageExtensions.cs" /> <Compile Include="Drawing\ImageExtensions.cs" />
<Compile Include="Entities\AggregateFolder.cs" /> <Compile Include="Entities\AggregateFolder.cs" />
<Compile Include="Entities\Audio\Artist.cs" />
<Compile Include="Entities\Audio\Audio.cs" /> <Compile Include="Entities\Audio\Audio.cs" />
<Compile Include="Entities\Audio\MusicAlbum.cs" /> <Compile Include="Entities\Audio\MusicAlbum.cs" />
<Compile Include="Entities\Audio\MusicArtist.cs" /> <Compile Include="Entities\Audio\MusicArtist.cs" />

View File

@ -34,7 +34,7 @@ namespace MediaBrowser.Providers
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item) public override bool Supports(BaseItem item)
{ {
return item is Folder && item.LocationType == LocationType.FileSystem; return item.IsFolder && item.LocationType == LocationType.FileSystem;
} }
/// <summary> /// <summary>

View File

@ -81,11 +81,9 @@
<Compile Include="Music\ArtistInfoFromSongProvider.cs" /> <Compile Include="Music\ArtistInfoFromSongProvider.cs" />
<Compile Include="Music\ArtistProviderFromXml.cs" /> <Compile Include="Music\ArtistProviderFromXml.cs" />
<Compile Include="Music\FanArtAlbumProvider.cs" /> <Compile Include="Music\FanArtAlbumProvider.cs" />
<Compile Include="Music\FanArtArtistByNameProvider.cs" />
<Compile Include="Music\FanArtArtistProvider.cs" /> <Compile Include="Music\FanArtArtistProvider.cs" />
<Compile Include="Music\FanArtUpdatesPrescanTask.cs" /> <Compile Include="Music\FanArtUpdatesPrescanTask.cs" />
<Compile Include="Music\LastfmAlbumProvider.cs" /> <Compile Include="Music\LastfmAlbumProvider.cs" />
<Compile Include="Music\LastfmArtistByNameProvider.cs" />
<Compile Include="Music\LastFmImageProvider.cs" /> <Compile Include="Music\LastFmImageProvider.cs" />
<Compile Include="Music\LastfmArtistProvider.cs" /> <Compile Include="Music\LastfmArtistProvider.cs" />
<Compile Include="Music\LastfmBaseProvider.cs" /> <Compile Include="Music\LastfmBaseProvider.cs" />

View File

@ -1,5 +1,4 @@
using System.Linq; using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Common.MediaInfo;
using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.MediaInfo; using MediaBrowser.Controller.MediaInfo;
@ -11,6 +10,7 @@ using MediaBrowser.Model.Serialization;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;

View File

@ -26,12 +26,17 @@ namespace MediaBrowser.Providers.Music
} }
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo) protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
var artist = (MusicArtist)item;
if (!artist.IsAccessedByName)
{ {
// If song metadata has changed // If song metadata has changed
if (GetComparisonData((MusicArtist)item) != providerInfo.FileStamp) if (GetComparisonData(artist) != providerInfo.FileStamp)
{ {
return true; return true;
} }
}
return base.NeedsRefreshInternal(item, providerInfo); return base.NeedsRefreshInternal(item, providerInfo);
} }
@ -47,7 +52,7 @@ namespace MediaBrowser.Providers.Music
return GetComparisonData(songs); return GetComparisonData(songs);
} }
private Guid GetComparisonData(List<Audio> songs) private Guid GetComparisonData(IEnumerable<Audio> songs)
{ {
var genres = songs.SelectMany(i => i.Genres) var genres = songs.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase) .Distinct(StringComparer.OrdinalIgnoreCase)
@ -60,6 +65,8 @@ namespace MediaBrowser.Providers.Music
{ {
var artist = (MusicArtist)item; var artist = (MusicArtist)item;
if (!artist.IsAccessedByName)
{
BaseProviderInfo data; BaseProviderInfo data;
if (!item.ProviderData.TryGetValue(Id, out data)) if (!item.ProviderData.TryGetValue(Id, out data))
{ {
@ -77,6 +84,7 @@ namespace MediaBrowser.Providers.Music
} }
data.FileStamp = GetComparisonData(songs); data.FileStamp = GetComparisonData(songs);
}
SetLastRefreshed(item, DateTime.UtcNow); SetLastRefreshed(item, DateTime.UtcNow);
return TrueTaskResult; return TrueTaskResult;

View File

@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Music
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item) public override bool Supports(BaseItem item)
{ {
return (item is Artist || item is MusicArtist) && item.LocationType == LocationType.FileSystem; return (item is MusicArtist) && item.LocationType == LocationType.FileSystem;
} }
/// <summary> /// <summary>
@ -87,18 +87,9 @@ namespace MediaBrowser.Providers.Music
await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
try try
{
var artist = item as Artist;
if (artist != null)
{
new BaseItemXmlParser<Artist>(Logger).Fetch(artist, path, cancellationToken);
}
else
{ {
new BaseItemXmlParser<MusicArtist>(Logger).Fetch((MusicArtist)item, path, cancellationToken); new BaseItemXmlParser<MusicArtist>(Logger).Fetch((MusicArtist)item, path, cancellationToken);
} }
}
finally finally
{ {
XmlParsingResourcePool.Release(); XmlParsingResourcePool.Release();

View File

@ -1,47 +0,0 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Providers.Music
{
/// <summary>
/// Class FanArtArtistByNameProvider
/// </summary>
public class FanArtArtistByNameProvider : FanArtArtistProvider
{
/// <summary>
/// Initializes a new instance of the <see cref="FanArtArtistByNameProvider" /> class.
/// </summary>
public FanArtArtistByNameProvider(IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, IProviderManager providerManager, IFileSystem fileSystem)
: base(httpClient, logManager, configurationManager, providerManager, 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 Artist;
}
/// <summary>
/// Gets a value indicating whether [save local meta].
/// </summary>
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
protected override bool SaveLocalMeta
{
get
{
return true;
}
}
}
}

View File

@ -42,7 +42,7 @@ namespace MediaBrowser.Providers.Music
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
public override bool Supports(BaseItem item) public override bool Supports(BaseItem item)
{ {
return item is Artist || item is MusicArtist || item is MusicAlbum; return item is MusicArtist || item is MusicAlbum;
} }
/// <summary> /// <summary>

View File

@ -1,89 +0,0 @@
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Serialization;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
/// <summary>
/// Class LastfmArtistByNameProvider
/// </summary>
public class LastfmArtistByNameProvider : LastfmArtistProvider
{
/// <summary>
/// Initializes a new instance of the <see cref="LastfmArtistByNameProvider" /> class.
/// </summary>
/// <param name="jsonSerializer">The json serializer.</param>
/// <param name="httpClient">The HTTP client.</param>
/// <param name="logManager">The log manager.</param>
/// <param name="configurationManager">The configuration manager.</param>
/// <param name="libraryManager">The library manager.</param>
public LastfmArtistByNameProvider(IJsonSerializer jsonSerializer, IHttpClient httpClient, ILogManager logManager, IServerConfigurationManager configurationManager, ILibraryManager libraryManager)
: base(jsonSerializer, httpClient, logManager, configurationManager, libraryManager)
{
}
/// <summary>
/// Gets a value indicating whether [save local meta].
/// </summary>
/// <value><c>true</c> if [save local meta]; otherwise, <c>false</c>.</value>
protected override bool SaveLocalMeta
{
get
{
return true;
}
}
/// <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 Artist;
}
/// <summary>
/// Gets the provider version.
/// </summary>
/// <value>The provider version.</value>
protected override string ProviderVersion
{
get
{
return "7";
}
}
/// <summary>
/// Fetches the lastfm data.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="musicBrainzId">The music brainz id.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
protected override async Task FetchLastfmData(BaseItem item, string musicBrainzId, bool force, CancellationToken cancellationToken)
{
var artist = (Artist)item;
// See if we can avoid an http request by finding the matching MusicArtist entity
var musicArtist = Artist.FindMusicArtist(artist, LibraryManager);
if (musicArtist != null && !force)
{
LastfmHelper.ProcessArtistData(musicArtist, artist);
}
else
{
await base.FetchLastfmData(item, musicBrainzId, force, cancellationToken).ConfigureAwait(false);
}
}
}
}

View File

@ -84,17 +84,6 @@ namespace MediaBrowser.Providers.Music
/// <returns>Task{System.String}.</returns> /// <returns>Task{System.String}.</returns>
private async Task<string> FindId(BaseItem item, CancellationToken cancellationToken) private async Task<string> FindId(BaseItem item, CancellationToken cancellationToken)
{ {
if (item is Artist)
{
// Since MusicArtists are refreshed first, try to find it from one of them
var id = FindIdFromMusicArtistEntity(item);
if (!string.IsNullOrEmpty(id))
{
return id;
}
}
try try
{ {
// If we don't get anything, go directly to music brainz // If we don't get anything, go directly to music brainz

View File

@ -39,21 +39,12 @@ namespace MediaBrowser.Providers.Music
var musicArtist = artist as MusicArtist; var musicArtist = artist as MusicArtist;
string imageSize;
if (musicArtist != null) if (musicArtist != null)
{ {
string imageSize;
musicArtist.LastFmImageUrl = GetImageUrl(data, out imageSize); musicArtist.LastFmImageUrl = GetImageUrl(data, out imageSize);
musicArtist.LastFmImageSize = imageSize; musicArtist.LastFmImageSize = imageSize;
} }
var artistByName = artist as Artist;
if (artistByName != null)
{
artistByName.LastFmImageUrl = GetImageUrl(data, out imageSize);
artistByName.LastFmImageSize = imageSize;
}
} }
private static string GetImageUrl(IHasLastFmImages data, out string size) private static string GetImageUrl(IHasLastFmImages data, out string size)
@ -85,15 +76,6 @@ namespace MediaBrowser.Providers.Music
return null; return null;
} }
public static void ProcessArtistData(MusicArtist source, Artist target)
{
target.PremiereDate = source.PremiereDate;
target.ProductionYear = source.ProductionYear;
target.Tags = source.Tags.ToList();
target.Overview = source.Overview;
target.ProductionLocations = source.ProductionLocations.ToList();
}
public static void ProcessAlbumData(BaseItem item, LastfmAlbum data) public static void ProcessAlbumData(BaseItem item, LastfmAlbum data)
{ {
var overview = data.wiki != null ? data.wiki.content : null; var overview = data.wiki != null ? data.wiki.content : null;

View File

@ -39,7 +39,7 @@ namespace MediaBrowser.Providers.Music
public bool Supports(BaseItem item) public bool Supports(BaseItem item)
{ {
return item is MusicArtist || item is Artist; return item is MusicArtist;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken)

View File

@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Music
public bool Supports(BaseItem item) public bool Supports(BaseItem item)
{ {
return item is MusicAlbum || item is MusicArtist || item is Artist; return item is MusicAlbum || item is MusicArtist;
} }
public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetImages(BaseItem item, ImageType imageType, CancellationToken cancellationToken)
@ -41,13 +41,6 @@ namespace MediaBrowser.Providers.Music
RemoteImageInfo info = null; RemoteImageInfo info = null;
var artist = item as Artist;
if (artist != null)
{
info = GetInfo(artist.LastFmImageUrl, artist.LastFmImageSize);
}
var album = item as MusicAlbum; var album = item as MusicAlbum;
if (album != null) if (album != null)
{ {

View File

@ -43,7 +43,8 @@ namespace MediaBrowser.Providers.Savers
// If new metadata has been downloaded or metadata was manually edited, proceed // If new metadata has been downloaded or metadata was manually edited, proceed
if (wasMetadataDownloaded || wasMetadataEdited) if (wasMetadataDownloaded || wasMetadataEdited)
{ {
if (item is Artist) var artist = item as MusicArtist;
if (artist != null && artist.IsAccessedByName)
{ {
return true; return true;
} }

View File

@ -29,7 +29,7 @@ namespace MediaBrowser.Providers.Savers
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> /// <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(BaseItem item, ItemUpdateType updateType)
{ {
if (!(item is Folder)) if (!item.IsFolder)
{ {
return false; return false;
} }

View File

@ -277,7 +277,7 @@ namespace MediaBrowser.Server.Implementations.Dto
Id = GetDtoId(item), Id = GetDtoId(item),
Name = item.Name, Name = item.Name,
MediaType = item.MediaType, MediaType = item.MediaType,
Type = item.GetType().Name, Type = item.GetClientTypeName(),
RunTimeTicks = item.RunTimeTicks RunTimeTicks = item.RunTimeTicks
}; };
@ -932,7 +932,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.RemoteTrailers = item.RemoteTrailers; dto.RemoteTrailers = item.RemoteTrailers;
} }
dto.Type = item.GetType().Name; dto.Type = item.GetClientTypeName();
dto.CommunityRating = item.CommunityRating; dto.CommunityRating = item.CommunityRating;
dto.VoteCount = item.VoteCount; dto.VoteCount = item.VoteCount;

View File

@ -391,11 +391,24 @@ namespace MediaBrowser.Server.Implementations.Library
/// <param name="item">The item.</param> /// <param name="item">The item.</param>
private void UpdateItemInLibraryCache(BaseItem item) private void UpdateItemInLibraryCache(BaseItem item)
{ {
if (!(item is IItemByName)) if (item is IItemByName)
{ {
LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; }); var hasDualAccess = item as IHasDualAccess;
if (hasDualAccess != null)
{
if (hasDualAccess.IsAccessedByName)
{
return;
} }
} }
else
{
return;
}
}
LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; });
}
/// <summary> /// <summary>
/// Resolves the item. /// Resolves the item.
@ -656,16 +669,6 @@ namespace MediaBrowser.Server.Implementations.Library
return GetItemByName<GameGenre>(ConfigurationManager.ApplicationPaths.GameGenrePath, name); return GetItemByName<GameGenre>(ConfigurationManager.ApplicationPaths.GameGenrePath, name);
} }
/// <summary>
/// Gets a Genre
/// </summary>
/// <param name="name">The name.</param>
/// <returns>Task{Genre}.</returns>
public Artist GetArtist(string name)
{
return GetItemByName<Artist>(ConfigurationManager.ApplicationPaths.ArtistsPath, name);
}
/// <summary> /// <summary>
/// The us culture /// The us culture
/// </summary> /// </summary>
@ -687,6 +690,16 @@ namespace MediaBrowser.Server.Implementations.Library
return GetItemByName<Year>(ConfigurationManager.ApplicationPaths.YearPath, value.ToString(UsCulture)); return GetItemByName<Year>(ConfigurationManager.ApplicationPaths.YearPath, value.ToString(UsCulture));
} }
/// <summary>
/// Gets a Genre
/// </summary>
/// <param name="name">The name.</param>
/// <returns>Task{Genre}.</returns>
public MusicArtist GetArtist(string name)
{
return GetItemByName<MusicArtist>(ConfigurationManager.ApplicationPaths.ArtistsPath, name);
}
/// <summary> /// <summary>
/// The images by name item cache /// The images by name item cache
/// </summary> /// </summary>
@ -697,12 +710,12 @@ namespace MediaBrowser.Server.Implementations.Library
{ {
if (string.IsNullOrEmpty(path)) if (string.IsNullOrEmpty(path))
{ {
throw new ArgumentNullException(); throw new ArgumentNullException("path");
} }
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
{ {
throw new ArgumentNullException(); throw new ArgumentNullException("name");
} }
var validFilename = _fileSystem.GetValidFilename(name).Trim(); var validFilename = _fileSystem.GetValidFilename(name).Trim();
@ -743,6 +756,20 @@ namespace MediaBrowser.Server.Implementations.Library
private Tuple<bool, T> CreateItemByName<T>(string path, string name) private Tuple<bool, T> CreateItemByName<T>(string path, string name)
where T : BaseItem, new() where T : BaseItem, new()
{ {
var isArtist = typeof(T) == typeof(MusicArtist);
if (isArtist)
{
var existing = RootFolder.RecursiveChildren
.OfType<T>()
.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));
if (existing != null)
{
return new Tuple<bool, T>(false, existing);
}
}
var fileInfo = new DirectoryInfo(path); var fileInfo = new DirectoryInfo(path);
var isNew = false; var isNew = false;
@ -779,6 +806,11 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true; isNew = true;
} }
if (isArtist)
{
(item as MusicArtist).IsAccessedByName = true;
}
// Set this now so we don't cause additional file system access during provider executions // Set this now so we don't cause additional file system access during provider executions
item.ResetResolveArgs(fileInfo); item.ResetResolveArgs(fileInfo);
@ -1363,16 +1395,19 @@ namespace MediaBrowser.Server.Implementations.Library
{ {
var item = ItemRepository.RetrieveItem(id); var item = ItemRepository.RetrieveItem(id);
var folder = item as Folder; if (item != null && item.IsFolder)
if (folder != null)
{ {
folder.LoadSavedChildren(); LoadSavedChildren(item as Folder);
} }
return item; return item;
} }
private void LoadSavedChildren(Folder item)
{
item.LoadSavedChildren();
}
private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>(); private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
/// <summary> /// <summary>
@ -1470,5 +1505,30 @@ namespace MediaBrowser.Server.Implementations.Library
return collectionTypes.Count == 1 ? collectionTypes[0] : null; return collectionTypes.Count == 1 ? collectionTypes[0] : null;
} }
public IEnumerable<string> GetAllArtists()
{
return GetAllArtists(RootFolder.RecursiveChildren);
}
public IEnumerable<string> GetAllArtists(IEnumerable<BaseItem> items)
{
return items
.OfType<Audio>()
.SelectMany(i =>
{
var list = new List<string>();
if (!string.IsNullOrEmpty(i.AlbumArtist))
{
list.Add(i.AlbumArtist);
}
list.AddRange(i.Artists);
return list;
})
.Distinct(StringComparer.OrdinalIgnoreCase);
}
} }
} }

View File

@ -74,21 +74,7 @@ namespace MediaBrowser.Server.Implementations.Library
})); }));
// Find artists // Find artists
var artists = items.OfType<Audio>() var artists = _libraryManager.GetAllArtists(items)
.SelectMany(i =>
{
var list = new List<string>();
if (!string.IsNullOrEmpty(i.AlbumArtist))
{
list.Add(i.AlbumArtist);
}
list.AddRange(i.Artists);
return list;
})
.Where(i => !string.IsNullOrEmpty(i))
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList(); .ToList();
foreach (var item in artists) foreach (var item in artists)

View File

@ -57,7 +57,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{ {
var allItems = _libraryManager.RootFolder.GetRecursiveChildren(); var allItems = _libraryManager.RootFolder.GetRecursiveChildren();
var allMusicArtists = allItems.OfType<MusicArtist>().ToList();
var allSongs = allItems.OfType<Audio>().ToList(); var allSongs = allItems.OfType<Audio>().ToList();
var innerProgress = new ActionableProgress<double>(); var innerProgress = new ActionableProgress<double>();
@ -80,36 +79,8 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
artist.ValidateImages(); // Only do this for artists accessed by name. Folder-based artists use ArtistInfoFromSongsProvider
artist.ValidateBackdrops(); if (artist.IsAccessedByName && !artist.LockedFields.Contains(MetadataFields.Genres))
var musicArtist = Artist.FindMusicArtist(artist, allMusicArtists);
if (musicArtist != null)
{
MergeImages(musicArtist.Images, artist.Images);
// Merge backdrops
var additionalBackdrops = musicArtist
.BackdropImagePaths
.Except(artist.BackdropImagePaths)
.ToList();
var sources = additionalBackdrops
.Select(musicArtist.GetImageSourceInfo)
.Where(i => i != null)
.ToList();
foreach (var path in additionalBackdrops)
{
artist.RemoveImageSourceForPath(path);
}
artist.BackdropImagePaths.AddRange(additionalBackdrops);
artist.ImageSources.AddRange(sources);
}
if (!artist.LockedFields.Contains(MetadataFields.Genres))
{ {
// Avoid implicitly captured closure // Avoid implicitly captured closure
var artist1 = artist; var artist1 = artist;
@ -145,7 +116,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <param name="artist">The artist.</param> /// <param name="artist">The artist.</param>
/// <param name="userId">The user id.</param> /// <param name="userId">The user id.</param>
/// <param name="allItems">All items.</param> /// <param name="allItems">All items.</param>
private void SetItemCounts(Artist artist, Guid? userId, IEnumerable<IHasArtist> allItems) private void SetItemCounts(MusicArtist artist, Guid? userId, IEnumerable<IHasArtist> allItems)
{ {
var name = artist.Name; var name = artist.Name;
@ -170,25 +141,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
} }
} }
/// <summary>
/// Merges the images.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="target">The target.</param>
private void MergeImages(Dictionary<ImageType, string> source, Dictionary<ImageType, string> target)
{
foreach (var key in source.Keys
.Where(k => !target.ContainsKey(k)))
{
string path;
if (source.TryGetValue(key, out path))
{
target[key] = path;
}
}
}
/// <summary> /// <summary>
/// Gets all artists. /// Gets all artists.
/// </summary> /// </summary>
@ -196,25 +148,12 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <param name="cancellationToken">The cancellation token.</param> /// <param name="cancellationToken">The cancellation token.</param>
/// <param name="progress">The progress.</param> /// <param name="progress">The progress.</param>
/// <returns>Task{Artist[]}.</returns> /// <returns>Task{Artist[]}.</returns>
private async Task<List<Artist>> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress) private async Task<List<MusicArtist>> GetAllArtists(IEnumerable<Audio> allSongs, CancellationToken cancellationToken, IProgress<double> progress)
{ {
var allArtists = allSongs var allArtists = _libraryManager.GetAllArtists(allSongs)
.SelectMany(i =>
{
var list = new List<string>();
if (!string.IsNullOrEmpty(i.AlbumArtist))
{
list.Add(i.AlbumArtist);
}
list.AddRange(i.Artists);
return list;
})
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList(); .ToList();
var returnArtists = new List<Artist>(allArtists.Count); var returnArtists = new List<MusicArtist>(allArtists.Count);
var numComplete = 0; var numComplete = 0;
var numArtists = allArtists.Count; var numArtists = allArtists.Count;

View File

@ -508,7 +508,7 @@ namespace MediaBrowser.Server.Implementations.Providers
return new[] { GetSavePathForItemInMixedFolder(item, type, string.Empty, extension) }; return new[] { GetSavePathForItemInMixedFolder(item, type, string.Empty, extension) };
} }
if (item is MusicAlbum || item is Artist || item is MusicArtist) if (item is MusicAlbum || item is MusicArtist)
{ {
return new[] { Path.Combine(item.MetaLocation, "folder" + extension) }; return new[] { Path.Combine(item.MetaLocation, "folder" + extension) };
} }

View File

@ -495,6 +495,7 @@ namespace MediaBrowser.WebDashboard.Api
"moviestudios.js", "moviestudios.js",
"movietrailers.js", "movietrailers.js",
"musicalbums.js", "musicalbums.js",
"musicalbumartists.js",
"musicartists.js", "musicartists.js",
"musicgenres.js", "musicgenres.js",
"musicrecommended.js", "musicrecommended.js",

View File

@ -80,6 +80,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="ApiClient.js" /> <EmbeddedResource Include="ApiClient.js" />
<Content Include="dashboard-ui\musicalbumartists.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\allusersettings.html"> <Content Include="dashboard-ui\allusersettings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
@ -341,6 +344,9 @@
<Content Include="dashboard-ui\livetvrecordings.html"> <Content Include="dashboard-ui\livetvrecordings.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>
<Content Include="dashboard-ui\scripts\musicalbumartists.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="dashboard-ui\scripts\livetvchannels.js"> <Content Include="dashboard-ui\scripts\livetvchannels.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content> </Content>