diff options
| -rw-r--r-- | MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs | 300 |
1 files changed, 164 insertions, 136 deletions
diff --git a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs index 4eb75b82f..51a3ba0c7 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs @@ -1,7 +1,5 @@ #nullable disable -#pragma warning disable CS1591 - using System; using System.Collections.Generic; using System.IO; @@ -18,182 +16,212 @@ using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; using PlaylistsNET.Content; -namespace MediaBrowser.Providers.Playlists +namespace MediaBrowser.Providers.Playlists; + +/// <summary> +/// Local playlist provider. +/// </summary> +public class PlaylistItemsProvider : ILocalMetadataProvider<Playlist>, + IHasOrder, + IForcedProvider, + IHasItemChangeMonitor { - public class PlaylistItemsProvider : ICustomMetadataProvider<Playlist>, - IHasOrder, - IForcedProvider, - IPreRefreshProvider, - IHasItemChangeMonitor + private readonly IFileSystem _fileSystem; + private readonly ILibraryManager _libraryManager; + private readonly ILogger<PlaylistItemsProvider> _logger; + private readonly CollectionType[] _ignoredCollections = [CollectionType.livetv, CollectionType.boxsets, CollectionType.playlists]; + + /// <summary> + /// Initializes a new instance of the <see cref="PlaylistItemsProvider"/> class. + /// </summary> + /// <param name="logger">Instance of the <see cref="ILogger{PlaylistItemsProvider}"/> interface.</param> + /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> + /// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param> + public PlaylistItemsProvider(ILogger<PlaylistItemsProvider> logger, ILibraryManager libraryManager, IFileSystem fileSystem) { - private readonly IFileSystem _fileSystem; - private readonly ILibraryManager _libraryManager; - private readonly ILogger<PlaylistItemsProvider> _logger; - private readonly CollectionType[] _ignoredCollections = [CollectionType.livetv, CollectionType.boxsets, CollectionType.playlists]; + _logger = logger; + _libraryManager = libraryManager; + _fileSystem = fileSystem; + } + + /// <inheritdoc /> + public string Name => "Playlist Item Provider"; + + /// <inheritdoc /> + public int Order => 100; - public PlaylistItemsProvider(ILogger<PlaylistItemsProvider> logger, ILibraryManager libraryManager, IFileSystem fileSystem) + /// <inheritdoc /> + public Task<MetadataResult<Playlist>> GetMetadata( + ItemInfo info, + IDirectoryService directoryService, + CancellationToken cancellationToken) + { + var result = new MetadataResult<Playlist>() { - _logger = logger; - _libraryManager = libraryManager; - _fileSystem = fileSystem; + Item = new Playlist + { + Path = info.Path + } + }; + Fetch(result); + + return Task.FromResult(result); + } + + private void Fetch(MetadataResult<Playlist> result) + { + var item = result.Item; + var path = item.Path; + if (!Playlist.IsPlaylistFile(path)) + { + return; } - public string Name => "Playlist Reader"; + var extension = Path.GetExtension(path); + if (!Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparison.OrdinalIgnoreCase)) + { + return; + } + + var items = GetItems(path, extension).ToArray(); + if (items.Length > 0) + { + result.HasMetadata = true; + item.LinkedChildren = items; + } - // Run last - public int Order => 100; + return; + } - public Task<ItemUpdateType> FetchAsync(Playlist item, MetadataRefreshOptions options, CancellationToken cancellationToken) + private IEnumerable<LinkedChild> GetItems(string path, string extension) + { + var libraryRoots = _libraryManager.GetUserRootFolder().Children + .OfType<CollectionFolder>() + .Where(f => f.CollectionType.HasValue && !_ignoredCollections.Contains(f.CollectionType.Value)) + .SelectMany(f => f.PhysicalLocations) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToList(); + + using (var stream = File.OpenRead(path)) { - var path = item.Path; - if (!Playlist.IsPlaylistFile(path)) + if (string.Equals(".wpl", extension, StringComparison.OrdinalIgnoreCase)) { - return Task.FromResult(ItemUpdateType.None); + return GetWplItems(stream, path, libraryRoots); } - var extension = Path.GetExtension(path); - if (!Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparison.OrdinalIgnoreCase)) + if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase)) { - return Task.FromResult(ItemUpdateType.None); + return GetZplItems(stream, path, libraryRoots); } - var items = GetItems(path, extension).ToArray(); - - item.LinkedChildren = items; - - return Task.FromResult(ItemUpdateType.MetadataImport); - } + if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase)) + { + return GetM3uItems(stream, path, libraryRoots); + } - private IEnumerable<LinkedChild> GetItems(string path, string extension) - { - var libraryRoots = _libraryManager.GetUserRootFolder().Children - .OfType<CollectionFolder>() - .Where(f => f.CollectionType.HasValue && !_ignoredCollections.Contains(f.CollectionType.Value)) - .SelectMany(f => f.PhysicalLocations) - .Distinct(StringComparer.OrdinalIgnoreCase) - .ToList(); - - using (var stream = File.OpenRead(path)) + if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase)) { - if (string.Equals(".wpl", extension, StringComparison.OrdinalIgnoreCase)) - { - return GetWplItems(stream, path, libraryRoots); - } - - if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase)) - { - return GetZplItems(stream, path, libraryRoots); - } - - if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase)) - { - return GetM3uItems(stream, path, libraryRoots); - } - - if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase)) - { - return GetM3uItems(stream, path, libraryRoots); - } - - if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase)) - { - return GetPlsItems(stream, path, libraryRoots); - } + return GetM3uItems(stream, path, libraryRoots); } - return Enumerable.Empty<LinkedChild>(); + if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase)) + { + return GetPlsItems(stream, path, libraryRoots); + } } - private IEnumerable<LinkedChild> GetPlsItems(Stream stream, string playlistPath, List<string> libraryRoots) - { - var content = new PlsContent(); - var playlist = content.GetFromStream(stream); + return Enumerable.Empty<LinkedChild>(); + } - return playlist.PlaylistEntries - .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) - .Where(i => i is not null); - } + private IEnumerable<LinkedChild> GetPlsItems(Stream stream, string playlistPath, List<string> libraryRoots) + { + var content = new PlsContent(); + var playlist = content.GetFromStream(stream); - private IEnumerable<LinkedChild> GetM3uItems(Stream stream, string playlistPath, List<string> libraryRoots) - { - var content = new M3uContent(); - var playlist = content.GetFromStream(stream); + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); + } - return playlist.PlaylistEntries - .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) - .Where(i => i is not null); - } + private IEnumerable<LinkedChild> GetM3uItems(Stream stream, string playlistPath, List<string> libraryRoots) + { + var content = new M3uContent(); + var playlist = content.GetFromStream(stream); - private IEnumerable<LinkedChild> GetZplItems(Stream stream, string playlistPath, List<string> libraryRoots) - { - var content = new ZplContent(); - var playlist = content.GetFromStream(stream); + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); + } - return playlist.PlaylistEntries - .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) - .Where(i => i is not null); - } + private IEnumerable<LinkedChild> GetZplItems(Stream stream, string playlistPath, List<string> libraryRoots) + { + var content = new ZplContent(); + var playlist = content.GetFromStream(stream); - private IEnumerable<LinkedChild> GetWplItems(Stream stream, string playlistPath, List<string> libraryRoots) - { - var content = new WplContent(); - var playlist = content.GetFromStream(stream); + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); + } - return playlist.PlaylistEntries - .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) - .Where(i => i is not null); - } + private IEnumerable<LinkedChild> GetWplItems(Stream stream, string playlistPath, List<string> libraryRoots) + { + var content = new WplContent(); + var playlist = content.GetFromStream(stream); + + return playlist.PlaylistEntries + .Select(i => GetLinkedChild(i.Path, playlistPath, libraryRoots)) + .Where(i => i is not null); + } - private LinkedChild GetLinkedChild(string itemPath, string playlistPath, List<string> libraryRoots) + private LinkedChild GetLinkedChild(string itemPath, string playlistPath, List<string> libraryRoots) + { + if (TryGetPlaylistItemPath(itemPath, playlistPath, libraryRoots, out var parsedPath)) { - if (TryGetPlaylistItemPath(itemPath, playlistPath, libraryRoots, out var parsedPath)) + return new LinkedChild { - return new LinkedChild - { - Path = parsedPath, - Type = LinkedChildType.Manual - }; - } - - return null; + Path = parsedPath, + Type = LinkedChildType.Manual + }; } - private bool TryGetPlaylistItemPath(string itemPath, string playlistPath, List<string> libraryPaths, out string path) + return null; + } + + private bool TryGetPlaylistItemPath(string itemPath, string playlistPath, List<string> libraryPaths, out string path) + { + path = null; + string pathToCheck = _fileSystem.MakeAbsolutePath(Path.GetDirectoryName(playlistPath), itemPath); + if (!File.Exists(pathToCheck)) { - path = null; - string pathToCheck = _fileSystem.MakeAbsolutePath(Path.GetDirectoryName(playlistPath), itemPath); - if (!File.Exists(pathToCheck)) - { - return false; - } + return false; + } - foreach (var libraryPath in libraryPaths) + foreach (var libraryPath in libraryPaths) + { + if (pathToCheck.StartsWith(libraryPath, StringComparison.OrdinalIgnoreCase)) { - if (pathToCheck.StartsWith(libraryPath, StringComparison.OrdinalIgnoreCase)) - { - path = pathToCheck; - return true; - } + path = pathToCheck; + return true; } - - return false; } - public bool HasChanged(BaseItem item, IDirectoryService directoryService) - { - var path = item.Path; + return false; + } - if (!string.IsNullOrWhiteSpace(path) && item.IsFileProtocol) + /// <inheritdoc /> + public bool HasChanged(BaseItem item, IDirectoryService directoryService) + { + var path = item.Path; + if (!string.IsNullOrWhiteSpace(path) && item.IsFileProtocol) + { + var file = directoryService.GetFile(path); + if (file is not null && file.LastWriteTimeUtc != item.DateModified) { - var file = directoryService.GetFile(path); - if (file is not null && file.LastWriteTimeUtc != item.DateModified) - { - _logger.LogDebug("Refreshing {Path} due to date modified timestamp change.", path); - return true; - } + _logger.LogDebug("Refreshing {Path} due to date modified timestamp change.", path); + return true; } - - return false; } + + return false; } } |
