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