< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Entities.Audio.MusicAlbum
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
Line coverage
7%
Covered lines: 4
Uncovered lines: 47
Coverable lines: 51
Total lines: 224
Line coverage: 7.8%
Branch coverage
0%
Covered branches: 0
Total branches: 16
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Coverage history

Coverage history 0 25 50 75 100

Metrics

File(s)

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

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CA1721, CA1826, 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.Entities;
 12using Jellyfin.Data.Enums;
 13using MediaBrowser.Controller.Dto;
 14using MediaBrowser.Controller.Library;
 15using MediaBrowser.Controller.Providers;
 16using MediaBrowser.Model.Entities;
 17using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
 18
 19namespace MediaBrowser.Controller.Entities.Audio
 20{
 21    /// <summary>
 22    /// Class MusicAlbum.
 23    /// </summary>
 24    public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadata
 25    {
 326        public MusicAlbum()
 27        {
 328            Artists = Array.Empty<string>();
 329            AlbumArtists = Array.Empty<string>();
 330        }
 31
 32        /// <inheritdoc />
 33        public IReadOnlyList<string> AlbumArtists { get; set; }
 34
 35        /// <inheritdoc />
 36        public IReadOnlyList<string> Artists { get; set; }
 37
 38        [JsonIgnore]
 039        public override bool SupportsAddingToPlaylist => true;
 40
 41        [JsonIgnore]
 042        public override bool SupportsInheritedParentImages => true;
 43
 44        [JsonIgnore]
 045        public MusicArtist MusicArtist => GetMusicArtist(new DtoOptions(true));
 46
 47        [JsonIgnore]
 048        public override bool SupportsPlayedStatus => false;
 49
 50        [JsonIgnore]
 051        public override bool SupportsCumulativeRunTimeTicks => true;
 52
 53        [JsonIgnore]
 054        public string AlbumArtist => AlbumArtists.FirstOrDefault();
 55
 56        [JsonIgnore]
 057        public override bool SupportsPeople => true;
 58
 59        /// <summary>
 60        /// Gets the tracks.
 61        /// </summary>
 62        /// <value>The tracks.</value>
 63        [JsonIgnore]
 064        public IEnumerable<Audio> Tracks => GetRecursiveChildren(i => i is Audio).Cast<Audio>();
 65
 66        public MusicArtist GetMusicArtist(DtoOptions options)
 67        {
 068            var parents = GetParents();
 069            foreach (var parent in parents)
 70            {
 071                if (parent is MusicArtist artist)
 72                {
 073                    return artist;
 74                }
 75            }
 76
 077            var name = AlbumArtist;
 078            if (!string.IsNullOrEmpty(name))
 79            {
 080                return LibraryManager.GetArtist(name, options);
 81            }
 82
 083            return null;
 084        }
 85
 86        protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
 87        {
 088            return Tracks;
 89        }
 90
 91        public override double GetDefaultPrimaryImageAspectRatio()
 92        {
 093            return 1;
 94        }
 95
 96        public override List<string> GetUserDataKeys()
 97        {
 098            var list = base.GetUserDataKeys();
 99
 0100            var albumArtist = AlbumArtist;
 0101            if (!string.IsNullOrEmpty(albumArtist))
 102            {
 0103                list.Insert(0, albumArtist + "-" + Name);
 104            }
 105
 0106            var id = this.GetProviderId(MetadataProvider.MusicBrainzAlbum);
 107
 0108            if (!string.IsNullOrEmpty(id))
 109            {
 0110                list.Insert(0, "MusicAlbum-Musicbrainz-" + id);
 111            }
 112
 0113            id = this.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup);
 114
 0115            if (!string.IsNullOrEmpty(id))
 116            {
 0117                list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id);
 118            }
 119
 0120            return list;
 121        }
 122
 123        protected override bool GetBlockUnratedValue(User user)
 124        {
 0125            return user.GetPreferenceValues<UnratedItem>(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Music);
 126        }
 127
 128        public override UnratedItem GetBlockUnratedType()
 129        {
 0130            return UnratedItem.Music;
 131        }
 132
 133        public AlbumInfo GetLookupInfo()
 134        {
 0135            var id = GetItemLookupInfo<AlbumInfo>();
 136
 0137            id.AlbumArtists = AlbumArtists;
 138
 0139            var artist = GetMusicArtist(new DtoOptions(false));
 140
 0141            if (artist is not null)
 142            {
 0143                id.ArtistProviderIds = artist.ProviderIds;
 144            }
 145
 0146            id.SongInfos = GetRecursiveChildren(i => i is Audio)
 0147                .Cast<Audio>()
 0148                .Select(i => i.GetLookupInfo())
 0149                .ToList();
 150
 0151            var album = id.SongInfos
 0152                .Select(i => i.Album)
 0153                .FirstOrDefault(i => !string.IsNullOrEmpty(i));
 154
 0155            if (!string.IsNullOrEmpty(album))
 156            {
 0157                id.Name = album;
 158            }
 159
 0160            return id;
 161        }
 162
 163        public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, Cancella
 164        {
 165            var items = GetRecursiveChildren();
 166
 167            var totalItems = items.Count;
 168            var numComplete = 0;
 169
 170            var childUpdateType = ItemUpdateType.None;
 171
 172            foreach (var item in items)
 173            {
 174                cancellationToken.ThrowIfCancellationRequested();
 175
 176                var updateType = await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
 177                childUpdateType = childUpdateType | updateType;
 178
 179                numComplete++;
 180                double percent = numComplete;
 181                percent /= totalItems;
 182                progress.Report(percent * 95);
 183            }
 184
 185            var parentRefreshOptions = refreshOptions;
 186            if (childUpdateType > ItemUpdateType.None)
 187            {
 188                parentRefreshOptions = new MetadataRefreshOptions(refreshOptions)
 189                {
 190                    MetadataRefreshMode = MetadataRefreshMode.FullRefresh
 191                };
 192            }
 193
 194            // Refresh current item
 195            await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
 196
 197            if (!refreshOptions.IsAutomated)
 198            {
 199                await RefreshArtists(refreshOptions, cancellationToken).ConfigureAwait(false);
 200            }
 201        }
 202
 203        private async Task RefreshArtists(MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
 204        {
 205            foreach (var i in this.GetAllArtists())
 206            {
 207                // This should not be necessary but we're seeing some cases of it
 208                if (string.IsNullOrEmpty(i))
 209                {
 210                    continue;
 211                }
 212
 213                var artist = LibraryManager.GetArtist(i);
 214
 215                if (!artist.IsAccessedByName)
 216                {
 217                    continue;
 218                }
 219
 220                await artist.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
 221            }
 222        }
 223    }
 224}