consolidate Artist & MusicArtist

pull/702/head
Luke Pulverenti 11 years ago
parent ee1a746031
commit 17bacee089

@ -92,7 +92,7 @@ namespace MediaBrowser.Api
private readonly char[] _dashReplaceChars = new[] { '?', '/' };
private const char SlugChar = '-';
protected Artist GetArtist(string name, ILibraryManager libraryManager)
protected MusicArtist GetArtist(string name, ILibraryManager libraryManager)
{
return libraryManager.GetArtist(DeSlugArtistName(name, libraryManager));
}
@ -147,21 +147,7 @@ namespace MediaBrowser.Api
return name;
}
return libraryManager.RootFolder.GetRecursiveChildren()
.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)
return libraryManager.GetAllArtists()
.FirstOrDefault(i =>
{
i = _dashReplaceChars.Aggregate(i, (current, c) => current.Replace(c, SlugChar));

@ -194,20 +194,7 @@ namespace MediaBrowser.Api.DefaultTheme
.Select(i => _dtoService.GetBaseItemDto(i, fields, user))
.ToList();
var artists = allItems.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)
var artists = _libraryManager.GetAllArtists(allItems)
.Randomize()
.Select(i =>
{

@ -264,16 +264,14 @@ namespace MediaBrowser.Api
{
var item = _dtoService.GetItemByDtoId(request.Id);
var folder = item as Folder;
try
{
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
var collectionFolder = folder as CollectionFolder;
var collectionFolder = item as CollectionFolder;
if (collectionFolder != null)
{
@ -281,6 +279,8 @@ namespace MediaBrowser.Api
}
else
{
var folder = (Folder)item;
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);
var folder = child as Folder;
if (folder != null)
if (child.IsFolder)
{
var folder = (Folder)child;
await folder.ValidateChildren(new Progress<double>(), CancellationToken.None, request.Recursive, request.Forced).ConfigureAwait(false);
}
}

@ -126,15 +126,6 @@ namespace MediaBrowser.Api
UpdateItem(request, item);
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)

@ -367,7 +367,7 @@ namespace MediaBrowser.Api
BoxSetCount = boxsets.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)
@ -390,19 +390,7 @@ namespace MediaBrowser.Api
people = request.UserId.HasValue ? FilterItems(people, request, request.UserId.Value).ToList() : people;
counts.PersonCount = people.Count;
var artists = 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)
var artists = _libraryManager.GetAllArtists(items)
.Select(i =>
{
try

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

@ -43,7 +43,7 @@ namespace MediaBrowser.Api.UserLibrary
/// <summary>
/// Class ArtistsService
/// </summary>
public class ArtistsService : BaseItemsByNameService<Artist>
public class ArtistsService : BaseItemsByNameService<MusicArtist>
{
/// <summary>
/// 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="items">The items.</param>
/// <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 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)
return LibraryManager.GetAllArtists(items)
.Select(name => LibraryManager.GetArtist(name));
}
}

@ -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;
}
}
}

@ -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
{
/// <summary>
/// Class MusicArtist
/// </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>
/// Gets or sets the last fm image URL.
/// </summary>
@ -13,13 +54,35 @@ namespace MediaBrowser.Controller.Entities.Audio
public string LastFmImageUrl { get; set; }
public string LastFmImageSize { get; set; }
public MusicArtist()
{
UserItemCounts = new Dictionary<Guid, ItemByNameCounts>();
}
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
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;
}
}
}

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

@ -1038,16 +1038,13 @@ 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;
}
}
}
@ -1150,14 +1147,11 @@ namespace MediaBrowser.Controller.Entities
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);
}
}
}

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

@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="name">The name.</param>
/// <returns>Task{Artist}.</returns>
Artist GetArtist(string name);
MusicArtist GetArtist(string name);
/// <summary>
/// Gets a Studio
@ -302,5 +302,18 @@ namespace MediaBrowser.Controller.Library
/// <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>
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);
}
}

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

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

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

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

@ -27,10 +27,15 @@ namespace MediaBrowser.Providers.Music
protected override bool NeedsRefreshInternal(BaseItem item, BaseProviderInfo providerInfo)
{
// If song metadata has changed
if (GetComparisonData((MusicArtist)item) != providerInfo.FileStamp)
var artist = (MusicArtist)item;
if (!artist.IsAccessedByName)
{
return true;
// If song metadata has changed
if (GetComparisonData(artist) != providerInfo.FileStamp)
{
return true;
}
}
return base.NeedsRefreshInternal(item, providerInfo);
@ -47,7 +52,7 @@ namespace MediaBrowser.Providers.Music
return GetComparisonData(songs);
}
private Guid GetComparisonData(List<Audio> songs)
private Guid GetComparisonData(IEnumerable<Audio> songs)
{
var genres = songs.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
@ -60,23 +65,26 @@ namespace MediaBrowser.Providers.Music
{
var artist = (MusicArtist)item;
BaseProviderInfo data;
if (!item.ProviderData.TryGetValue(Id, out data))
if (!artist.IsAccessedByName)
{
data = new BaseProviderInfo();
item.ProviderData[Id] = data;
}
BaseProviderInfo data;
if (!item.ProviderData.TryGetValue(Id, out data))
{
data = new BaseProviderInfo();
item.ProviderData[Id] = data;
}
var songs = artist.RecursiveChildren.OfType<Audio>().ToList();
var songs = artist.RecursiveChildren.OfType<Audio>().ToList();
if (!item.LockedFields.Contains(MetadataFields.Genres))
{
artist.Genres = songs.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
}
if (!item.LockedFields.Contains(MetadataFields.Genres))
{
artist.Genres = songs.SelectMany(i => i.Genres)
.Distinct(StringComparer.OrdinalIgnoreCase)
.ToList();
}
data.FileStamp = GetComparisonData(songs);
data.FileStamp = GetComparisonData(songs);
}
SetLastRefreshed(item, DateTime.UtcNow);
return TrueTaskResult;

@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Music
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
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>
@ -88,16 +88,7 @@ namespace MediaBrowser.Providers.Music
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
{

@ -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;
}
}
}
}

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

@ -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);
}
}
}
}

@ -84,17 +84,6 @@ namespace MediaBrowser.Providers.Music
/// <returns>Task{System.String}.</returns>
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
{
// If we don't get anything, go directly to music brainz

@ -39,21 +39,12 @@ namespace MediaBrowser.Providers.Music
var musicArtist = artist as MusicArtist;
string imageSize;
if (musicArtist != null)
{
string imageSize;
musicArtist.LastFmImageUrl = GetImageUrl(data, out 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)
@ -85,15 +76,6 @@ namespace MediaBrowser.Providers.Music
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)
{
var overview = data.wiki != null ? data.wiki.content : null;

@ -39,7 +39,7 @@ namespace MediaBrowser.Providers.Music
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)

@ -25,7 +25,7 @@ namespace MediaBrowser.Providers.Music
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)
@ -41,13 +41,6 @@ namespace MediaBrowser.Providers.Music
RemoteImageInfo info = null;
var artist = item as Artist;
if (artist != null)
{
info = GetInfo(artist.LastFmImageUrl, artist.LastFmImageSize);
}
var album = item as MusicAlbum;
if (album != null)
{

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

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

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

@ -391,10 +391,23 @@ namespace MediaBrowser.Server.Implementations.Library
/// <param name="item">The item.</param>
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>
@ -656,16 +669,6 @@ namespace MediaBrowser.Server.Implementations.Library
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>
/// The us culture
/// </summary>
@ -687,6 +690,16 @@ namespace MediaBrowser.Server.Implementations.Library
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>
/// The images by name item cache
/// </summary>
@ -697,12 +710,12 @@ namespace MediaBrowser.Server.Implementations.Library
{
if (string.IsNullOrEmpty(path))
{
throw new ArgumentNullException();
throw new ArgumentNullException("path");
}
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException();
throw new ArgumentNullException("name");
}
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)
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 isNew = false;
@ -779,6 +806,11 @@ namespace MediaBrowser.Server.Implementations.Library
isNew = true;
}
if (isArtist)
{
(item as MusicArtist).IsAccessedByName = true;
}
// Set this now so we don't cause additional file system access during provider executions
item.ResetResolveArgs(fileInfo);
@ -1363,16 +1395,19 @@ namespace MediaBrowser.Server.Implementations.Library
{
var item = ItemRepository.RetrieveItem(id);
var folder = item as Folder;
if (folder != null)
if (item != null && item.IsFolder)
{
folder.LoadSavedChildren();
LoadSavedChildren(item as Folder);
}
return item;
}
private void LoadSavedChildren(Folder item)
{
item.LoadSavedChildren();
}
private readonly ConcurrentDictionary<string, SemaphoreSlim> _fileLocks = new ConcurrentDictionary<string, SemaphoreSlim>();
/// <summary>
@ -1470,5 +1505,30 @@ namespace MediaBrowser.Server.Implementations.Library
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);
}
}
}

@ -74,21 +74,7 @@ namespace MediaBrowser.Server.Implementations.Library
}));
// Find artists
var artists = 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;
})
.Where(i => !string.IsNullOrEmpty(i))
.Distinct(StringComparer.OrdinalIgnoreCase)
var artists = _libraryManager.GetAllArtists(items)
.ToList();
foreach (var item in artists)

@ -57,7 +57,6 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{
var allItems = _libraryManager.RootFolder.GetRecursiveChildren();
var allMusicArtists = allItems.OfType<MusicArtist>().ToList();
var allSongs = allItems.OfType<Audio>().ToList();
var innerProgress = new ActionableProgress<double>();
@ -80,36 +79,8 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
{
cancellationToken.ThrowIfCancellationRequested();
artist.ValidateImages();
artist.ValidateBackdrops();
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))
// Only do this for artists accessed by name. Folder-based artists use ArtistInfoFromSongsProvider
if (artist.IsAccessedByName && !artist.LockedFields.Contains(MetadataFields.Genres))
{
// Avoid implicitly captured closure
var artist1 = artist;
@ -145,7 +116,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <param name="artist">The artist.</param>
/// <param name="userId">The user id.</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;
@ -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>
/// Gets all artists.
/// </summary>
@ -196,25 +148,12 @@ namespace MediaBrowser.Server.Implementations.Library.Validators
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="progress">The progress.</param>
/// <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
.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)
var allArtists = _libraryManager.GetAllArtists(allSongs)
.ToList();
var returnArtists = new List<Artist>(allArtists.Count);
var returnArtists = new List<MusicArtist>(allArtists.Count);
var numComplete = 0;
var numArtists = allArtists.Count;

@ -508,7 +508,7 @@ namespace MediaBrowser.Server.Implementations.Providers
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) };
}

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

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

Loading…
Cancel
Save