< Summary - Jellyfin

Information
Class: MediaBrowser.Controller.Playlists.Playlist
Assembly: MediaBrowser.Controller
File(s): /srv/git/jellyfin/MediaBrowser.Controller/Playlists/Playlist.cs
Line coverage
12%
Covered lines: 12
Uncovered lines: 82
Coverable lines: 94
Total lines: 272
Line coverage: 12.7%
Branch coverage
0%
Covered branches: 0
Total branches: 30
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/Playlists/Playlist.cs

#LineLine coverage
 1#nullable disable
 2
 3#pragma warning disable CS1591
 4
 5using System;
 6using System.Collections.Generic;
 7using System.IO;
 8using System.Linq;
 9using System.Text.Json.Serialization;
 10using System.Threading;
 11using System.Threading.Tasks;
 12using Jellyfin.Data.Entities;
 13using Jellyfin.Data.Enums;
 14using MediaBrowser.Controller.Dto;
 15using MediaBrowser.Controller.Entities;
 16using MediaBrowser.Controller.Entities.Audio;
 17using MediaBrowser.Controller.Providers;
 18using MediaBrowser.Model.Entities;
 19
 20namespace MediaBrowser.Controller.Playlists
 21{
 22    public class Playlist : Folder, IHasShares
 23    {
 124        public static readonly IReadOnlyList<string> SupportedExtensions =
 125        [
 126            ".m3u",
 127            ".m3u8",
 128            ".pls",
 129            ".wpl",
 130            ".zpl"
 131        ];
 32
 133        public Playlist()
 34        {
 135            Shares = [];
 136            OpenAccess = false;
 137        }
 38
 39        public Guid OwnerUserId { get; set; }
 40
 41        public bool OpenAccess { get; set; }
 42
 43        public IReadOnlyList<PlaylistUserPermissions> Shares { get; set; }
 44
 45        [JsonIgnore]
 046        public bool IsFile => IsPlaylistFile(Path);
 47
 48        [JsonIgnore]
 49        public override string ContainingFolderPath
 50        {
 51            get
 52            {
 053                var path = Path;
 54
 055                if (IsPlaylistFile(path))
 56                {
 057                    return System.IO.Path.GetDirectoryName(path);
 58                }
 59
 060                return path;
 61            }
 62        }
 63
 64        [JsonIgnore]
 065        protected override bool FilterLinkedChildrenPerUser => true;
 66
 67        [JsonIgnore]
 068        public override bool SupportsInheritedParentImages => false;
 69
 70        [JsonIgnore]
 071        public override bool SupportsPlayedStatus => MediaType == Jellyfin.Data.Enums.MediaType.Video;
 72
 73        [JsonIgnore]
 074        public override bool AlwaysScanInternalMetadataPath => true;
 75
 76        [JsonIgnore]
 077        public override bool SupportsCumulativeRunTimeTicks => true;
 78
 79        [JsonIgnore]
 080        public override bool IsPreSorted => true;
 81
 82        public MediaType PlaylistMediaType { get; set; }
 83
 84        [JsonIgnore]
 085        public override MediaType MediaType => PlaylistMediaType;
 86
 87        [JsonIgnore]
 88        private bool IsSharedItem
 89        {
 90            get
 91            {
 092                var path = Path;
 93
 094                if (string.IsNullOrEmpty(path))
 95                {
 096                    return false;
 97                }
 98
 099                return FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, path);
 100            }
 101        }
 102
 103        public static bool IsPlaylistFile(string path)
 104        {
 105            // The path will sometimes be a directory and "Path.HasExtension" returns true if the name contains a '.' (d
 0106            return System.IO.Path.HasExtension(path) && !Directory.Exists(path);
 107        }
 108
 109        public void SetMediaType(MediaType? value)
 110        {
 0111            PlaylistMediaType = value ?? MediaType.Unknown;
 0112        }
 113
 114        public override double GetDefaultPrimaryImageAspectRatio()
 115        {
 0116            return 1;
 117        }
 118
 119        public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders)
 120        {
 0121            return true;
 122        }
 123
 124        public override bool IsSaveLocalMetadataEnabled()
 125        {
 0126            return true;
 127        }
 128
 129        protected override List<BaseItem> LoadChildren()
 130        {
 131            // Save a trip to the database
 0132            return [];
 133        }
 134
 135        protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMe
 136        {
 0137            return Task.CompletedTask;
 138        }
 139
 140        public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query)
 141        {
 0142            return GetPlayableItems(user, query);
 143        }
 144
 145        protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
 146        {
 0147            return [];
 148        }
 149
 150        public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
 151        {
 0152            return GetPlayableItems(user, query);
 153        }
 154
 155        public IEnumerable<Tuple<LinkedChild, BaseItem>> GetManageableItems()
 156        {
 0157            return GetLinkedChildrenInfos();
 158        }
 159
 160        private List<BaseItem> GetPlayableItems(User user, InternalItemsQuery query)
 161        {
 0162            query ??= new InternalItemsQuery(user);
 163
 0164            query.IsFolder = false;
 165
 0166            return base.GetChildren(user, true, query);
 167        }
 168
 169        public static IReadOnlyList<BaseItem> GetPlaylistItems(IEnumerable<BaseItem> inputItems, User user, DtoOptions o
 170        {
 0171            if (user is not null)
 172            {
 0173                inputItems = inputItems.Where(i => i.IsVisible(user));
 174            }
 175
 0176            var list = new List<BaseItem>();
 177
 0178            foreach (var item in inputItems)
 179            {
 0180                var playlistItems = GetPlaylistItems(item, user, options);
 0181                list.AddRange(playlistItems);
 182            }
 183
 0184            return list;
 185        }
 186
 187        private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem item, User user, DtoOptions options)
 188        {
 0189            if (item is MusicGenre musicGenre)
 190            {
 0191                return LibraryManager.GetItemList(new InternalItemsQuery(user)
 0192                {
 0193                    Recursive = true,
 0194                    IncludeItemTypes = [BaseItemKind.Audio],
 0195                    GenreIds = [musicGenre.Id],
 0196                    OrderBy = [(ItemSortBy.AlbumArtist, SortOrder.Ascending), (ItemSortBy.Album, SortOrder.Ascending), (
 0197                    DtoOptions = options
 0198                });
 199            }
 200
 0201            if (item is MusicArtist musicArtist)
 202            {
 0203                return LibraryManager.GetItemList(new InternalItemsQuery(user)
 0204                {
 0205                    Recursive = true,
 0206                    IncludeItemTypes = [BaseItemKind.Audio],
 0207                    ArtistIds = [musicArtist.Id],
 0208                    OrderBy = [(ItemSortBy.AlbumArtist, SortOrder.Ascending), (ItemSortBy.Album, SortOrder.Ascending), (
 0209                    DtoOptions = options
 0210                });
 211            }
 212
 0213            if (item is Folder folder)
 214            {
 0215                var query = new InternalItemsQuery(user)
 0216                {
 0217                    Recursive = true,
 0218                    IsFolder = false,
 0219                    MediaTypes = [MediaType.Audio, MediaType.Video],
 0220                    EnableTotalRecordCount = false,
 0221                    DtoOptions = options
 0222                };
 223
 0224                return folder.GetItemList(query);
 225            }
 226
 0227            return [item];
 228        }
 229
 230        public override bool IsVisible(User user)
 231        {
 0232            if (!IsSharedItem)
 233            {
 0234                return base.IsVisible(user);
 235            }
 236
 0237            if (OpenAccess)
 238            {
 0239                return true;
 240            }
 241
 0242            var userId = user.Id;
 0243            if (userId.Equals(OwnerUserId))
 244            {
 0245                return true;
 246            }
 247
 0248            var shares = Shares;
 0249            if (shares.Count == 0)
 250            {
 0251                return false;
 252            }
 253
 0254            return shares.Any(s => s.UserId.Equals(userId));
 255        }
 256
 257        public override bool CanDelete(User user)
 258        {
 0259            return user.HasPermission(PermissionKind.IsAdministrator) || user.Id.Equals(OwnerUserId);
 260        }
 261
 262        public override bool IsVisibleStandalone(User user)
 263        {
 0264            if (!IsSharedItem)
 265            {
 0266                return base.IsVisibleStandalone(user);
 267            }
 268
 0269            return IsVisible(user);
 270        }
 271    }
 272}

Methods/Properties

.cctor()
.ctor()
get_IsFile()
get_ContainingFolderPath()
get_FilterLinkedChildrenPerUser()
get_SupportsInheritedParentImages()
get_SupportsPlayedStatus()
get_AlwaysScanInternalMetadataPath()
get_SupportsCumulativeRunTimeTicks()
get_IsPreSorted()
get_MediaType()
get_IsSharedItem()
IsPlaylistFile(System.String)
SetMediaType(System.Nullable`1<Jellyfin.Data.Enums.MediaType>)
GetDefaultPrimaryImageAspectRatio()
IsAuthorizedToDelete(Jellyfin.Data.Entities.User,System.Collections.Generic.List`1<MediaBrowser.Controller.Entities.Folder>)
IsSaveLocalMetadataEnabled()
LoadChildren()
ValidateChildrenInternal(System.IProgress`1<System.Double>,System.Boolean,System.Boolean,System.Boolean,MediaBrowser.Controller.Providers.MetadataRefreshOptions,MediaBrowser.Controller.Providers.IDirectoryService,System.Threading.CancellationToken)
GetChildren(Jellyfin.Data.Entities.User,System.Boolean,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetNonCachedChildren(MediaBrowser.Controller.Providers.IDirectoryService)
GetRecursiveChildren(Jellyfin.Data.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetManageableItems()
GetPlayableItems(Jellyfin.Data.Entities.User,MediaBrowser.Controller.Entities.InternalItemsQuery)
GetPlaylistItems(System.Collections.Generic.IEnumerable`1<MediaBrowser.Controller.Entities.BaseItem>,Jellyfin.Data.Entities.User,MediaBrowser.Controller.Dto.DtoOptions)
GetPlaylistItems(MediaBrowser.Controller.Entities.BaseItem,Jellyfin.Data.Entities.User,MediaBrowser.Controller.Dto.DtoOptions)
IsVisible(Jellyfin.Data.Entities.User)
CanDelete(Jellyfin.Data.Entities.User)
IsVisibleStandalone(Jellyfin.Data.Entities.User)