< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Entities.Audio.MusicArtist
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
Line coverage
5%
Covered lines: 3
Uncovered lines: 56
Coverable lines: 59
Total lines: 223
Line coverage: 5%
Branch coverage
0%
Covered branches: 0
Total branches: 26
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100 5/16/2026 - 12:15:55 AM Line coverage: 3.2% (2/61) Branch coverage: 0% (0/26) Total lines: 2267/27/2026 - 12:16:14 AM Line coverage: 4.9% (3/61) Branch coverage: 0% (0/26) Total lines: 22610/29/2026 - 12:17:11 AM Line coverage: 5% (3/59) Branch coverage: 0% (0/26) Total lines: 223 5/16/2026 - 12:15:55 AM Line coverage: 3.2% (2/61) Branch coverage: 0% (0/26) Total lines: 2267/27/2026 - 12:16:14 AM Line coverage: 4.9% (3/61) Branch coverage: 0% (0/26) Total lines: 22610/29/2026 - 12:17:11 AM Line coverage: 5% (3/59) Branch coverage: 0% (0/26) Total lines: 223

Coverage delta

Coverage delta 2 -2

Metrics

File(s)

/srv/git/jellyfin/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CS1591
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Linq;
 8using System.Text.Json.Serialization;
 9using System.Threading;
 10using System.Threading.Tasks;
 11using Jellyfin.Data;
 12using Jellyfin.Data.Enums;
 13using Jellyfin.Database.Implementations.Entities;
 14using Jellyfin.Database.Implementations.Enums;
 15using Jellyfin.Extensions;
 16using MediaBrowser.Controller.Providers;
 17using MediaBrowser.Model.Entities;
 18using Microsoft.Extensions.Logging;
 19using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
 20
 21namespace MediaBrowser.Controller.Entities.Audio
 22{
 23    /// <summary>
 24    /// Class MusicArtist.
 25    /// </summary>
 26    [Common.RequiresSourceSerialisation]
 27    public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo<ArtistInfo>
 28    {
 29        [JsonIgnore]
 730        public bool IsAccessedByName => ParentId.IsEmpty();
 31
 32        [JsonIgnore]
 133        public override bool IsFolder => !IsAccessedByName;
 34
 35        [JsonIgnore]
 236        public override bool SupportsInheritedParentImages => false;
 37
 38        [JsonIgnore]
 039        public override bool SupportsCumulativeRunTimeTicks => true;
 40
 41        [JsonIgnore]
 042        public override bool IsDisplayedAsFolder => true;
 43
 44        [JsonIgnore]
 045        public override bool SupportsAddingToPlaylist => true;
 46
 47        [JsonIgnore]
 048        public override bool SupportsPlayedStatus => false;
 49
 50        /// <summary>
 51        /// Gets the folder containing the item.
 52        /// If the item is a folder, it returns the folder itself.
 53        /// </summary>
 54        /// <value>The containing folder path.</value>
 55        [JsonIgnore]
 056        public override string ContainingFolderPath => Path;
 57
 58        [JsonIgnore]
 59        public override IEnumerable<BaseItem> Children
 60        {
 61            get
 62            {
 063                if (IsAccessedByName)
 64                {
 065                    return Enumerable.Empty<BaseItem>();
 66                }
 67
 068                return base.Children;
 69            }
 70        }
 71
 72        [JsonIgnore]
 073        public override bool SupportsPeople => false;
 74
 75        public static string GetPath(string name)
 76        {
 077            return GetPath(name, true);
 78        }
 79
 80        public override double GetDefaultPrimaryImageAspectRatio()
 81        {
 082            return 1;
 83        }
 84
 85        public override bool CanDelete()
 86        {
 087            return !IsAccessedByName;
 88        }
 89
 90        public IReadOnlyList<BaseItem> GetTaggedItems(InternalItemsQuery query)
 91        {
 092            if (query.IncludeItemTypes.Length == 0)
 93            {
 094                query.IncludeItemTypes = new[] { BaseItemKind.Audio, BaseItemKind.MusicVideo, BaseItemKind.MusicAlbum };
 095                query.ArtistIds = new[] { Id };
 96            }
 97
 098            return LibraryManager.GetItemList(query);
 99        }
 100
 101        public override int GetChildCount(User user)
 102        {
 0103            return IsAccessedByName ? 0 : base.GetChildCount(user);
 104        }
 105
 106        public override bool IsSaveLocalMetadataEnabled()
 107        {
 0108            if (IsAccessedByName)
 109            {
 0110                return true;
 111            }
 112
 0113            return base.IsSaveLocalMetadataEnabled();
 114        }
 115
 116        protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshC
 117        {
 0118            if (IsAccessedByName)
 119            {
 120                // Should never get in here anyway
 0121                return;
 122            }
 123
 0124            await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, false, refreshOptions, direct
 0125        }
 126
 127        public override List<string> GetUserDataKeys()
 128        {
 0129            var list = base.GetUserDataKeys();
 130
 0131            list.InsertRange(0, GetUserDataKeys(this));
 0132            return list;
 133        }
 134
 135        /// <summary>
 136        /// Gets the user data key.
 137        /// </summary>
 138        /// <param name="item">The item.</param>
 139        /// <returns>System.String.</returns>
 140        private static List<string> GetUserDataKeys(MusicArtist item)
 141        {
 0142            var list = new List<string>();
 0143            if (item.TryGetProviderId(MetadataProvider.MusicBrainzArtist, out var externalId))
 144            {
 0145                list.Add("Artist-Musicbrainz-" + externalId);
 146            }
 147
 0148            list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics());
 0149            return list;
 150        }
 151
 152        public override string CreatePresentationUniqueKey()
 153        {
 0154            return "Artist-" + (Name ?? string.Empty).RemoveDiacritics();
 155        }
 156
 157        public override UnratedItem GetBlockUnratedType()
 158        {
 0159            return UnratedItem.Music;
 160        }
 161
 162        public ArtistInfo GetLookupInfo()
 163        {
 0164            var info = GetItemLookupInfo<ArtistInfo>();
 165
 0166            info.SongInfos = GetRecursiveChildren(i => i is Audio)
 0167                .Cast<Audio>()
 0168                .Select(i => i.GetLookupInfo())
 0169                .ToList();
 170
 0171            return info;
 172        }
 173
 174        public static string GetPath(string name, bool normalizeName)
 175        {
 0176            var validName = normalizeName ? GetItemByNameFolderName(name) : name;
 177
 0178            return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName);
 179        }
 180
 181        private string GetRebasedPath()
 182        {
 0183            return GetPath(System.IO.Path.GetFileName(Path), false);
 184        }
 185
 186        public override bool RequiresRefresh()
 187        {
 0188            if (IsAccessedByName)
 189            {
 0190                var newPath = GetRebasedPath();
 0191                if (!string.Equals(Path, newPath, StringComparison.Ordinal))
 192                {
 0193                    Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
 0194                    return true;
 195                }
 196            }
 197
 0198            return base.RequiresRefresh();
 199        }
 200
 201        /// <summary>
 202        /// This is called before any metadata refresh and returns true or false indicating if changes were made.
 203        /// </summary>
 204        /// <param name="replaceAllMetadata">Option to replace metadata.</param>
 205        /// <returns>True if metadata changed.</returns>
 206        public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
 207        {
 0208            var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
 209
 0210            if (IsAccessedByName)
 211            {
 0212                var newPath = GetRebasedPath();
 0213                if (!string.Equals(Path, newPath, StringComparison.Ordinal))
 214                {
 0215                    Path = newPath;
 0216                    hasChanges = true;
 217                }
 218            }
 219
 0220            return hasChanges;
 221        }
 222    }
 223}