repo creation with initial code after cloning public repo

This commit is contained in:
2026-02-19 07:36:25 -05:00
commit 460884fea3
2860 changed files with 650825 additions and 0 deletions
@@ -0,0 +1,16 @@
#pragma warning disable CS1591
namespace MediaBrowser.Controller.Library
{
public class DeleteOptions
{
public DeleteOptions()
{
DeleteFromExternalProvider = true;
}
public bool DeleteFileLocation { get; set; }
public bool DeleteFromExternalProvider { get; set; }
}
}
@@ -0,0 +1,19 @@
using System.IO;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// The direct live TV stream provider.
/// </summary>
/// <remarks>
/// Deprecated.
/// </remarks>
public interface IDirectStreamProvider
{
/// <summary>
/// Gets the live stream, shared streams seek to the end of the file first.
/// </summary>
/// <returns>The stream.</returns>
Stream GetStream();
}
}
@@ -0,0 +1,29 @@
#nullable disable
using System.Collections.Generic;
using System.Threading.Tasks;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class BaseIntroProvider.
/// </summary>
public interface IIntroProvider
{
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
string Name { get; }
/// <summary>
/// Gets the intros.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="user">The user.</param>
/// <returns>IEnumerable{System.String}.</returns>
Task<IEnumerable<IntroInfo>> GetIntros(BaseItem item, User user);
}
}
@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.MediaEncoding.Keyframes;
namespace MediaBrowser.Controller.IO;
/// <summary>
/// Interface IKeyframeManager.
/// </summary>
public interface IKeyframeManager
{
/// <summary>
/// Gets the keyframe data.
/// </summary>
/// <param name="itemId">The item id.</param>
/// <returns>The keyframe data.</returns>
IReadOnlyList<KeyframeData> GetKeyframeData(Guid itemId);
/// <summary>
/// Saves the keyframe data.
/// </summary>
/// <param name="itemId">The item id.</param>
/// <param name="data">The keyframe data.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task SaveKeyframeDataAsync(Guid itemId, KeyframeData data, CancellationToken cancellationToken);
/// <summary>
/// Deletes the keyframe data.
/// </summary>
/// <param name="itemId">The item id.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task DeleteKeyframeDataAsync(Guid itemId, CancellationToken cancellationToken);
}
@@ -0,0 +1,671 @@
#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using Jellyfin.Database.Implementations.Entities;
using Jellyfin.Database.Implementations.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using Genre = MediaBrowser.Controller.Entities.Genre;
using Person = MediaBrowser.Controller.Entities.Person;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface ILibraryManager.
/// </summary>
public interface ILibraryManager
{
/// <summary>
/// Occurs when [item added].
/// </summary>
event EventHandler<ItemChangeEventArgs>? ItemAdded;
/// <summary>
/// Occurs when [item updated].
/// </summary>
event EventHandler<ItemChangeEventArgs>? ItemUpdated;
/// <summary>
/// Occurs when [item removed].
/// </summary>
event EventHandler<ItemChangeEventArgs>? ItemRemoved;
/// <summary>
/// Gets the root folder.
/// </summary>
/// <value>The root folder.</value>
AggregateFolder RootFolder { get; }
bool IsScanRunning { get; }
/// <summary>
/// Resolves the path.
/// </summary>
/// <param name="fileInfo">The file information.</param>
/// <param name="parent">The parent.</param>
/// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param>
/// <returns>BaseItem.</returns>
BaseItem? ResolvePath(
FileSystemMetadata fileInfo,
Folder? parent = null,
IDirectoryService? directoryService = null);
/// <summary>
/// Resolves a set of files into a list of BaseItem.
/// </summary>
/// <param name="files">The list of tiles.</param>
/// <param name="directoryService">Instance of the <see cref="IDirectoryService"/> interface.</param>
/// <param name="parent">The parent folder.</param>
/// <param name="libraryOptions">The library options.</param>
/// <param name="collectionType">The collection type.</param>
/// <returns>The items resolved from the paths.</returns>
IEnumerable<BaseItem> ResolvePaths(
IEnumerable<FileSystemMetadata> files,
IDirectoryService directoryService,
Folder parent,
LibraryOptions libraryOptions,
CollectionType? collectionType = null);
/// <summary>
/// Gets a Person.
/// </summary>
/// <param name="name">The name of the person.</param>
/// <returns>Task{Person}.</returns>
Person? GetPerson(string name);
/// <summary>
/// Finds the by path.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="isFolder"><c>true</c> is the path is a directory; otherwise <c>false</c>.</param>
/// <returns>BaseItem.</returns>
BaseItem? FindByPath(string path, bool? isFolder);
/// <summary>
/// Gets the artist.
/// </summary>
/// <param name="name">The name of the artist.</param>
/// <returns>Task{Artist}.</returns>
MusicArtist GetArtist(string name);
MusicArtist GetArtist(string name, DtoOptions options);
/// <summary>
/// Gets a Studio.
/// </summary>
/// <param name="name">The name of the studio.</param>
/// <returns>Task{Studio}.</returns>
Studio GetStudio(string name);
/// <summary>
/// Gets a Genre.
/// </summary>
/// <param name="name">The name of the genre.</param>
/// <returns>Task{Genre}.</returns>
Genre GetGenre(string name);
/// <summary>
/// Gets the genre.
/// </summary>
/// <param name="name">The name of the music genre.</param>
/// <returns>Task{MusicGenre}.</returns>
MusicGenre GetMusicGenre(string name);
/// <summary>
/// Gets a Year.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>Task{Year}.</returns>
/// <exception cref="ArgumentOutOfRangeException">Throws if year is invalid.</exception>
Year GetYear(int value);
/// <summary>
/// Validate and refresh the People sub-set of the IBN.
/// The items are stored in the db but not loaded into memory until actually requested by an operation.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task ValidatePeopleAsync(IProgress<double> progress, CancellationToken cancellationToken);
/// <summary>
/// Reloads the root media folder.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task ValidateMediaLibrary(IProgress<double> progress, CancellationToken cancellationToken);
/// <summary>
/// Reloads the root media folder.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="removeRoot">Is remove the library itself allowed.</param>
/// <returns>Task.</returns>
Task ValidateTopLibraryFolders(CancellationToken cancellationToken, bool removeRoot = false);
Task UpdateImagesAsync(BaseItem item, bool forceUpdate = false);
/// <summary>
/// Gets the default view.
/// </summary>
/// <returns>IEnumerable{VirtualFolderInfo}.</returns>
List<VirtualFolderInfo> GetVirtualFolders();
List<VirtualFolderInfo> GetVirtualFolders(bool includeRefreshState);
/// <summary>
/// Gets the item by id.
/// </summary>
/// <param name="id">The id.</param>
/// <returns>BaseItem.</returns>
/// <exception cref="ArgumentNullException"><paramref name="id"/> is <c>null</c>.</exception>
BaseItem? GetItemById(Guid id);
/// <summary>
/// Gets the item by id, as T.
/// </summary>
/// <param name="id">The item id.</param>
/// <typeparam name="T">The type of item.</typeparam>
/// <returns>The item.</returns>
T? GetItemById<T>(Guid id)
where T : BaseItem;
/// <summary>
/// Gets the item by id, as T, and validates user access.
/// </summary>
/// <param name="id">The item id.</param>
/// <param name="userId">The user id to validate against.</param>
/// <typeparam name="T">The type of item.</typeparam>
/// <returns>The item if found.</returns>
public T? GetItemById<T>(Guid id, Guid userId)
where T : BaseItem;
/// <summary>
/// Gets the item by id, as T, and validates user access.
/// </summary>
/// <param name="id">The item id.</param>
/// <param name="user">The user to validate against.</param>
/// <typeparam name="T">The type of item.</typeparam>
/// <returns>The item if found.</returns>
public T? GetItemById<T>(Guid id, User? user)
where T : BaseItem;
/// <summary>
/// Gets the intros.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="user">The user.</param>
/// <returns>IEnumerable{System.String}.</returns>
Task<IEnumerable<Video>> GetIntros(BaseItem item, User user);
/// <summary>
/// Adds the parts.
/// </summary>
/// <param name="rules">The rules.</param>
/// <param name="resolvers">The resolvers.</param>
/// <param name="introProviders">The intro providers.</param>
/// <param name="itemComparers">The item comparers.</param>
/// <param name="postScanTasks">The post scan tasks.</param>
void AddParts(
IEnumerable<IResolverIgnoreRule> rules,
IEnumerable<IItemResolver> resolvers,
IEnumerable<IIntroProvider> introProviders,
IEnumerable<IBaseItemComparer> itemComparers,
IEnumerable<ILibraryPostScanTask> postScanTasks);
/// <summary>
/// Sorts the specified items.
/// </summary>
/// <param name="items">The items.</param>
/// <param name="user">The user.</param>
/// <param name="sortBy">The sort by.</param>
/// <param name="sortOrder">The sort order.</param>
/// <returns>IEnumerable{BaseItem}.</returns>
IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User? user, IEnumerable<ItemSortBy> sortBy, SortOrder sortOrder);
IEnumerable<BaseItem> Sort(IEnumerable<BaseItem> items, User? user, IEnumerable<(ItemSortBy OrderBy, SortOrder SortOrder)> orderBy);
/// <summary>
/// Gets the user root folder.
/// </summary>
/// <returns>UserRootFolder.</returns>
Folder GetUserRootFolder();
/// <summary>
/// Creates the item.
/// </summary>
/// <param name="item">Item to create.</param>
/// <param name="parent">Parent of new item.</param>
void CreateItem(BaseItem item, BaseItem? parent);
/// <summary>
/// Creates the items.
/// </summary>
/// <param name="items">Items to create.</param>
/// <param name="parent">Parent of new items.</param>
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
void CreateItems(IReadOnlyList<BaseItem> items, BaseItem? parent, CancellationToken cancellationToken);
/// <summary>
/// Updates the item.
/// </summary>
/// <param name="items">Items to update.</param>
/// <param name="parent">Parent of updated items.</param>
/// <param name="updateReason">Reason for update.</param>
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
/// <returns>Returns a Task that can be awaited.</returns>
Task UpdateItemsAsync(IReadOnlyList<BaseItem> items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken);
/// <summary>
/// Updates the item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="parent">The parent item.</param>
/// <param name="updateReason">The update reason.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Returns a Task that can be awaited.</returns>
Task UpdateItemAsync(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken);
/// <summary>
/// Reattaches the user data to the item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task that represents the asynchronous reattachment operation.</returns>
Task ReattachUserDataAsync(BaseItem item, CancellationToken cancellationToken);
/// <summary>
/// Retrieves the item.
/// </summary>
/// <param name="id">The id.</param>
/// <returns>BaseItem.</returns>
BaseItem RetrieveItem(Guid id);
/// <summary>
/// Finds the type of the collection.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
CollectionType? GetContentType(BaseItem item);
/// <summary>
/// Gets the type of the inherited content.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
CollectionType? GetInheritedContentType(BaseItem item);
/// <summary>
/// Gets the type of the configured content.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
CollectionType? GetConfiguredContentType(BaseItem item);
/// <summary>
/// Gets the type of the configured content.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>System.String.</returns>
CollectionType? GetConfiguredContentType(string path);
/// <summary>
/// Normalizes the root path list.
/// </summary>
/// <param name="paths">The paths.</param>
/// <returns>IEnumerable{System.String}.</returns>
List<FileSystemMetadata> NormalizeRootPathList(IEnumerable<FileSystemMetadata> paths);
/// <summary>
/// Registers the item.
/// </summary>
/// <param name="item">The item.</param>
void RegisterItem(BaseItem item);
/// <summary>
/// Deletes the item.
/// </summary>
/// <param name="item">Item to delete.</param>
/// <param name="options">Options to use for deletion.</param>
void DeleteItem(BaseItem item, DeleteOptions options);
/// <summary>
/// Deletes items that are not having any children like Actors.
/// </summary>
/// <param name="items">Items to delete.</param>
/// <remarks>In comparison to <see cref="DeleteItem(BaseItem, DeleteOptions, BaseItem, bool)"/> this method skips a lot of steps assuming there are no children to recusively delete nor does it define the special handling for channels and alike.</remarks>
public void DeleteItemsUnsafeFast(IEnumerable<BaseItem> items);
/// <summary>
/// Deletes the item.
/// </summary>
/// <param name="item">Item to delete.</param>
/// <param name="options">Options to use for deletion.</param>
/// <param name="notifyParentItem">Notify parent of deletion.</param>
void DeleteItem(BaseItem item, DeleteOptions options, bool notifyParentItem);
/// <summary>
/// Deletes the item.
/// </summary>
/// <param name="item">Item to delete.</param>
/// <param name="options">Options to use for deletion.</param>
/// <param name="parent">Parent of item.</param>
/// <param name="notifyParentItem">Notify parent of deletion.</param>
void DeleteItem(BaseItem item, DeleteOptions options, BaseItem parent, bool notifyParentItem);
/// <summary>
/// Gets the named view.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="name">The name.</param>
/// <param name="parentId">The parent identifier.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
/// <returns>The named view.</returns>
UserView GetNamedView(
User user,
string name,
Guid parentId,
CollectionType? viewType,
string sortName);
/// <summary>
/// Gets the named view.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="name">The name.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
/// <returns>The named view.</returns>
UserView GetNamedView(
User user,
string name,
CollectionType? viewType,
string sortName);
/// <summary>
/// Gets the named view.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
/// <returns>The named view.</returns>
UserView GetNamedView(
string name,
CollectionType viewType,
string sortName);
/// <summary>
/// Gets the named view.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="parentId">The parent identifier.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
/// <param name="uniqueId">The unique identifier.</param>
/// <returns>The named view.</returns>
UserView GetNamedView(
string name,
Guid parentId,
CollectionType? viewType,
string sortName,
string uniqueId);
/// <summary>
/// Gets the shadow view.
/// </summary>
/// <param name="parent">The parent.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
/// <returns>The shadow view.</returns>
UserView GetShadowView(
BaseItem parent,
CollectionType? viewType,
string sortName);
/// <summary>
/// Gets the season number from path.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="parentId">The parent id.</param>
/// <returns>System.Nullable&lt;System.Int32&gt;.</returns>
int? GetSeasonNumberFromPath(string path, Guid? parentId);
/// <summary>
/// Fills the missing episode numbers from path.
/// </summary>
/// <param name="episode">Episode to use.</param>
/// <param name="forceRefresh">Option to force refresh of episode numbers.</param>
/// <returns>True if successful.</returns>
bool FillMissingEpisodeNumbersFromPath(Episode episode, bool forceRefresh);
/// <summary>
/// Parses the name.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>ItemInfo.</returns>
ItemLookupInfo ParseName(string name);
/// <summary>
/// Gets the new item identifier.
/// </summary>
/// <param name="key">The key.</param>
/// <param name="type">The type.</param>
/// <returns>Guid.</returns>
Guid GetNewItemId(string key, Type type);
/// <summary>
/// Finds the extras.
/// </summary>
/// <param name="owner">The owner.</param>
/// <param name="fileSystemChildren">The file system children.</param>
/// <param name="directoryService">An instance of <see cref="IDirectoryService"/>.</param>
/// <returns>IEnumerable&lt;BaseItem&gt;.</returns>
IEnumerable<BaseItem> FindExtras(BaseItem owner, IReadOnlyList<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService);
/// <summary>
/// Gets the collection folders.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>The folders that contain the item.</returns>
List<Folder> GetCollectionFolders(BaseItem item);
/// <summary>
/// Gets the collection folders.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="allUserRootChildren">The root folders to consider.</param>
/// <returns>The folders that contain the item.</returns>
List<Folder> GetCollectionFolders(BaseItem item, IEnumerable<Folder> allUserRootChildren);
LibraryOptions GetLibraryOptions(BaseItem item);
/// <summary>
/// Gets the people.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>List&lt;PersonInfo&gt;.</returns>
IReadOnlyList<PersonInfo> GetPeople(BaseItem item);
/// <summary>
/// Gets the people.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;PersonInfo&gt;.</returns>
IReadOnlyList<PersonInfo> GetPeople(InternalPeopleQuery query);
/// <summary>
/// Gets the people items.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;Person&gt;.</returns>
IReadOnlyList<Person> GetPeopleItems(InternalPeopleQuery query);
/// <summary>
/// Updates the people.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="people">The people.</param>
void UpdatePeople(BaseItem item, List<PersonInfo> people);
/// <summary>
/// Asynchronously updates the people.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="people">The people.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The async task.</returns>
Task UpdatePeopleAsync(BaseItem item, IReadOnlyList<PersonInfo> people, CancellationToken cancellationToken);
/// <summary>
/// Gets the item ids.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;Guid&gt;.</returns>
IReadOnlyList<Guid> GetItemIds(InternalItemsQuery query);
/// <summary>
/// Gets the people names.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;System.String&gt;.</returns>
IReadOnlyList<string> GetPeopleNames(InternalPeopleQuery query);
/// <summary>
/// Queries the items.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
QueryResult<BaseItem> QueryItems(InternalItemsQuery query);
string GetPathAfterNetworkSubstitution(string path, BaseItem? ownerItem = null);
/// <summary>
/// Converts the image to local.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="image">The image.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <param name="removeOnFailure">Whether to remove the image from the item on failure.</param>
/// <returns>Task.</returns>
Task<ItemImageInfo> ConvertImageToLocal(BaseItem item, ItemImageInfo image, int imageIndex, bool removeOnFailure = true);
/// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query);
IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent);
/// <summary>
/// Gets the items.
/// </summary>
/// <param name="query">The query to use.</param>
/// <param name="parents">Items to use for query.</param>
/// <returns>List of items.</returns>
IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents);
/// <summary>
/// Gets the TVShow/Album items for Latest api.
/// </summary>
/// <param name="query">The query to use.</param>
/// <param name="parents">Items to use for query.</param>
/// <param name="collectionType">Collection Type.</param>
/// <returns>List of items.</returns>
IReadOnlyList<BaseItem> GetLatestItemList(InternalItemsQuery query, IReadOnlyList<BaseItem> parents, CollectionType collectionType);
/// <summary>
/// Gets the list of series presentation keys for next up.
/// </summary>
/// <param name="query">The query to use.</param>
/// <param name="parents">Items to use for query.</param>
/// <param name="dateCutoff">The minimum date for a series to have been most recently watched.</param>
/// <returns>List of series presentation keys.</returns>
IReadOnlyList<string> GetNextUpSeriesKeys(InternalItemsQuery query, IReadOnlyCollection<BaseItem> parents, DateTime dateCutoff);
/// <summary>
/// Gets the items result.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
/// <summary>
/// Checks if the file is ignored.
/// </summary>
/// <param name="file">The file.</param>
/// <param name="parent">The parent.</param>
/// <returns><c>true</c> if ignored, <c>false</c> otherwise.</returns>
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
Guid GetStudioId(string name);
Guid GetGenreId(string name);
Guid GetMusicGenreId(string name);
Task AddVirtualFolder(string name, CollectionTypeOptions? collectionType, LibraryOptions options, bool refreshLibrary);
Task RemoveVirtualFolder(string name, bool refreshLibrary);
void AddMediaPath(string virtualFolderName, MediaPathInfo mediaPath);
void UpdateMediaPath(string virtualFolderName, MediaPathInfo mediaPath);
void RemoveMediaPath(string virtualFolderName, string mediaPath);
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetGenres(InternalItemsQuery query);
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetMusicGenres(InternalItemsQuery query);
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetStudios(InternalItemsQuery query);
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetArtists(InternalItemsQuery query);
IReadOnlyDictionary<string, MusicArtist[]> GetArtists(IReadOnlyList<string> names);
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAlbumArtists(InternalItemsQuery query);
QueryResult<(BaseItem Item, ItemCounts ItemCounts)> GetAllArtists(InternalItemsQuery query);
int GetCount(InternalItemsQuery query);
ItemCounts GetItemCounts(InternalItemsQuery query);
Task RunMetadataSavers(BaseItem item, ItemUpdateType updateReason);
BaseItem GetParentItem(Guid? parentId, Guid? userId);
/// <summary>
/// Queue a library scan.
/// </summary>
/// <remarks>
/// This exists so plugins can trigger a library scan.
/// </remarks>
void QueueLibraryScan();
/// <summary>
/// Add mblink file for a media path.
/// </summary>
/// <param name="virtualFolderPath">The path to the virtualfolder.</param>
/// <param name="pathInfo">The new virtualfolder.</param>
public void CreateShortcut(string virtualFolderPath, MediaPathInfo pathInfo);
}
}
@@ -0,0 +1,37 @@
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Service responsible for monitoring library filesystems for changes.
/// </summary>
public interface ILibraryMonitor
{
/// <summary>
/// Starts this instance.
/// </summary>
void Start();
/// <summary>
/// Stops this instance.
/// </summary>
void Stop();
/// <summary>
/// Reports the file system change beginning.
/// </summary>
/// <param name="path">The path.</param>
void ReportFileSystemChangeBeginning(string path);
/// <summary>
/// Reports the file system change complete.
/// </summary>
/// <param name="path">The path.</param>
/// <param name="refreshPath">if set to <c>true</c> [refresh path].</param>
void ReportFileSystemChangeComplete(string path, bool refreshPath);
/// <summary>
/// Reports the file system changed.
/// </summary>
/// <param name="path">The path.</param>
void ReportFileSystemChanged(string path);
}
}
@@ -0,0 +1,20 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// An interface for tasks that run after the media library scan.
/// </summary>
public interface ILibraryPostScanTask
{
/// <summary>
/// Runs the specified progress.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task Run(IProgress<double> progress, CancellationToken cancellationToken);
}
}
@@ -0,0 +1,33 @@
#nullable disable
#pragma warning disable CA1711, CS1591
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Library
{
public interface ILiveStream : IDisposable
{
int ConsumerCount { get; set; }
string OriginalStreamId { get; set; }
string TunerHostId { get; }
bool EnableStreamSharing { get; }
MediaSourceInfo MediaSource { get; set; }
string UniqueId { get; }
Task Open(CancellationToken openCancellationToken);
Task Close();
Stream GetStream();
}
}
@@ -0,0 +1,145 @@
#nullable disable
#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Controller.Library
{
public interface IMediaSourceManager
{
/// <summary>
/// Adds the parts.
/// </summary>
/// <param name="providers">The providers.</param>
void AddParts(IEnumerable<IMediaSourceProvider> providers);
/// <summary>
/// Gets the media streams.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <returns>IEnumerable&lt;MediaStream&gt;.</returns>
IReadOnlyList<MediaStream> GetMediaStreams(Guid itemId);
/// <summary>
/// Gets the media streams.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>IEnumerable&lt;MediaStream&gt;.</returns>
IReadOnlyList<MediaStream> GetMediaStreams(MediaStreamQuery query);
/// <summary>
/// Gets the media attachments.
/// </summary>
/// <param name="itemId">The item identifier.</param>
/// <returns>IEnumerable&lt;MediaAttachment&gt;.</returns>
IReadOnlyList<MediaAttachment> GetMediaAttachments(Guid itemId);
/// <summary>
/// Gets the media attachments.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>IEnumerable&lt;MediaAttachment&gt;.</returns>
IReadOnlyList<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query);
/// <summary>
/// Gets the playback media sources.
/// </summary>
/// <param name="item">Item to use.</param>
/// <param name="user">User to use for operation.</param>
/// <param name="allowMediaProbe">Option to allow media probe.</param>
/// <param name="enablePathSubstitution">Option to enable path substitution.</param>
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
/// <returns>List of media sources wrapped in an awaitable task.</returns>
Task<IReadOnlyList<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken);
/// <summary>
/// Gets the static media sources.
/// </summary>
/// <param name="item">Item to use.</param>
/// <param name="enablePathSubstitution">Option to enable path substitution.</param>
/// <param name="user">User to use for operation.</param>
/// <returns>List of media sources.</returns>
IReadOnlyList<MediaSourceInfo> GetStaticMediaSources(BaseItem item, bool enablePathSubstitution, User user = null);
/// <summary>
/// Gets the static media source.
/// </summary>
/// <param name="item">Item to use.</param>
/// <param name="mediaSourceId">Media source to get.</param>
/// <param name="liveStreamId">Live stream to use.</param>
/// <param name="enablePathSubstitution">Option to enable path substitution.</param>
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
/// <returns>The static media source wrapped in an awaitable task.</returns>
Task<MediaSourceInfo> GetMediaSource(BaseItem item, string mediaSourceId, string liveStreamId, bool enablePathSubstitution, CancellationToken cancellationToken);
/// <summary>
/// Opens the media source.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;MediaSourceInfo&gt;.</returns>
Task<LiveStreamResponse> OpenLiveStream(LiveStreamRequest request, CancellationToken cancellationToken);
Task<Tuple<LiveStreamResponse, IDirectStreamProvider>> OpenLiveStreamInternal(LiveStreamRequest request, CancellationToken cancellationToken);
/// <summary>
/// Gets the live stream.
/// </summary>
/// <param name="id">The identifier.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;MediaSourceInfo&gt;.</returns>
Task<MediaSourceInfo> GetLiveStream(string id, CancellationToken cancellationToken);
Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetLiveStreamWithDirectStreamProvider(string id, CancellationToken cancellationToken);
/// <summary>
/// Gets the live stream info.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>An instance of <see cref="ILiveStream"/>.</returns>
public ILiveStream GetLiveStreamInfo(string id);
/// <summary>
/// Gets the live stream info using the stream's unique id.
/// </summary>
/// <param name="uniqueId">The unique identifier.</param>
/// <returns>An instance of <see cref="ILiveStream"/>.</returns>
public ILiveStream GetLiveStreamInfoByUniqueId(string uniqueId);
/// <summary>
/// Gets the media sources for an active recording.
/// </summary>
/// <param name="info">The <see cref="ActiveRecordingInfo"/>.</param>
/// <param name="cancellationToken">The <see cref="CancellationToken"/>.</param>
/// <returns>A task containing the <see cref="MediaSourceInfo"/>'s for the recording.</returns>
Task<IReadOnlyList<MediaSourceInfo>> GetRecordingStreamMediaSources(ActiveRecordingInfo info, CancellationToken cancellationToken);
/// <summary>
/// Closes the media source.
/// </summary>
/// <param name="id">The live stream identifier.</param>
/// <returns>Task.</returns>
Task CloseLiveStream(string id);
Task<MediaSourceInfo> GetLiveStreamMediaInfo(string id, CancellationToken cancellationToken);
bool SupportsDirectStream(string path, MediaProtocol protocol);
MediaProtocol GetPathProtocol(string path);
void SetDefaultAudioAndSubtitleStreamIndices(BaseItem item, MediaSourceInfo source, User user);
Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, string cacheKey, bool addProbeDelay, bool isLiveStream, CancellationToken cancellationToken);
}
}
@@ -0,0 +1,30 @@
#pragma warning disable CA1002, CS1591
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Library
{
public interface IMediaSourceProvider
{
/// <summary>
/// Gets the media sources.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;IEnumerable&lt;MediaSourceInfo&gt;&gt;.</returns>
Task<IEnumerable<MediaSourceInfo>> GetMediaSources(BaseItem item, CancellationToken cancellationToken);
/// <summary>
/// Opens the media source.
/// </summary>
/// <param name="openToken">Token to use.</param>
/// <param name="currentLiveStreams">List of live streams.</param>
/// <param name="cancellationToken">CancellationToken to use for operation.</param>
/// <returns>The media source wrapped as an awaitable task.</returns>
Task<ILiveStream> OpenMediaSource(string openToken, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken);
}
}
@@ -0,0 +1,16 @@
#pragma warning disable CS1591
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
public interface IMetadataFileSaver : IMetadataSaver
{
/// <summary>
/// Gets the save path.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
string GetSavePath(BaseItem item);
}
}
@@ -0,0 +1,34 @@
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface IMetadataSaver.
/// </summary>
public interface IMetadataSaver
{
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
string Name { get; }
/// <summary>
/// Determines whether [is enabled for] [the specified item].
/// </summary>
/// <param name="item">The item.</param>
/// <param name="updateType">Type of the update.</param>
/// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns>
bool IsEnabledFor(BaseItem item, ItemUpdateType updateType);
/// <summary>
/// Saves the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The task object representing the asynchronous operation.</returns>
Task SaveAsync(BaseItem item, CancellationToken cancellationToken);
}
}
@@ -0,0 +1,40 @@
#pragma warning disable CA1002, CS1591
using System.Collections.Generic;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
namespace MediaBrowser.Controller.Library
{
public interface IMusicManager
{
/// <summary>
/// Gets the instant mix from song.
/// </summary>
/// <param name="item">The item to use.</param>
/// <param name="user">The user to use.</param>
/// <param name="dtoOptions">The options to use.</param>
/// <returns>List of items.</returns>
IReadOnlyList<BaseItem> GetInstantMixFromItem(BaseItem item, User? user, DtoOptions dtoOptions);
/// <summary>
/// Gets the instant mix from artist.
/// </summary>
/// <param name="artist">The artist to use.</param>
/// <param name="user">The user to use.</param>
/// <param name="dtoOptions">The options to use.</param>
/// <returns>List of items.</returns>
IReadOnlyList<BaseItem> GetInstantMixFromArtist(MusicArtist artist, User? user, DtoOptions dtoOptions);
/// <summary>
/// Gets the instant mix from genre.
/// </summary>
/// <param name="genres">The genres to use.</param>
/// <param name="user">The user to use.</param>
/// <param name="dtoOptions">The options to use.</param>
/// <returns>List of items.</returns>
IReadOnlyList<BaseItem> GetInstantMixFromGenres(IEnumerable<string> genres, User? user, DtoOptions dtoOptions);
}
}
@@ -0,0 +1,18 @@
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Search;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface ILibrarySearchEngine.
/// </summary>
public interface ISearchEngine
{
/// <summary>
/// Gets the search hints.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>Task{IEnumerable{SearchHintInfo}}.</returns>
QueryResult<SearchHintInfo> GetSearchHints(SearchQuery query);
}
}
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface IUserDataManager.
/// </summary>
public interface IUserDataManager
{
/// <summary>
/// Occurs when [user data saved].
/// </summary>
event EventHandler<UserDataSaveEventArgs>? UserDataSaved;
/// <summary>
/// Saves the user data.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="item">The item.</param>
/// <param name="userData">The user data.</param>
/// <param name="reason">The reason.</param>
/// <param name="cancellationToken">The cancellation token.</param>
void SaveUserData(User user, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
/// <summary>
/// Save the provided user data for the given user.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="item">The item.</param>
/// <param name="userDataDto">The reason for updating the user data.</param>
/// <param name="reason">The reason.</param>
void SaveUserData(User user, BaseItem item, UpdateUserItemDataDto userDataDto, UserDataSaveReason reason);
/// <summary>
/// Gets the user data.
/// </summary>
/// <param name="user">User to use.</param>
/// <param name="item">Item to use.</param>
/// <returns>User data.</returns>
UserItemData? GetUserData(User user, BaseItem item);
/// <summary>
/// Gets the user data dto.
/// </summary>
/// <param name="item">Item to use.</param>
/// <param name="user">User to use.</param>
/// <returns>User data dto.</returns>
UserItemDataDto? GetUserDataDto(BaseItem item, User user);
/// <summary>
/// Gets the user data dto.
/// </summary>
/// <param name="item">Item to use.</param>
/// <param name="itemDto">Item dto to use.</param>
/// <param name="user">User to use.</param>
/// <param name="options">Dto options to use.</param>
/// <returns>User data dto.</returns>
UserItemDataDto? GetUserDataDto(BaseItem item, BaseItemDto? itemDto, User user, DtoOptions options);
/// <summary>
/// Updates playstate for an item and returns true or false indicating if it was played to completion.
/// </summary>
/// <param name="item">Item to update.</param>
/// <param name="data">Data to update.</param>
/// <param name="reportedPositionTicks">New playstate.</param>
/// <returns>True if playstate was updated.</returns>
bool UpdatePlayState(BaseItem item, UserItemData data, long? reportedPositionTicks);
}
}
@@ -0,0 +1,171 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Jellyfin.Data.Events;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface IUserManager.
/// </summary>
public interface IUserManager
{
/// <summary>
/// Occurs when a user is updated.
/// </summary>
event EventHandler<GenericEventArgs<User>> OnUserUpdated;
/// <summary>
/// Gets the users.
/// </summary>
/// <value>The users.</value>
IEnumerable<User> Users { get; }
/// <summary>
/// Gets the user ids.
/// </summary>
/// <value>The users ids.</value>
IEnumerable<Guid> UsersIds { get; }
/// <summary>
/// Initializes the user manager and ensures that a user exists.
/// </summary>
/// <returns>Awaitable task.</returns>
Task InitializeAsync();
/// <summary>
/// Gets a user by Id.
/// </summary>
/// <param name="id">The id.</param>
/// <returns>The user with the specified Id, or <c>null</c> if the user doesn't exist.</returns>
/// <exception cref="ArgumentException"><c>id</c> is an empty Guid.</exception>
User? GetUserById(Guid id);
/// <summary>
/// Gets the name of the user by.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>User.</returns>
User? GetUserByName(string name);
/// <summary>
/// Renames the user.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="newName">The new name.</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException">If user is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If the provided user doesn't exist.</exception>
Task RenameUser(User user, string newName);
/// <summary>
/// Updates the user.
/// </summary>
/// <param name="user">The user.</param>
/// <exception cref="ArgumentNullException">If user is <c>null</c>.</exception>
/// <exception cref="ArgumentException">If the provided user doesn't exist.</exception>
/// <returns>A task representing the update of the user.</returns>
Task UpdateUserAsync(User user);
/// <summary>
/// Creates a user with the specified name.
/// </summary>
/// <param name="name">The name of the new user.</param>
/// <returns>The created user.</returns>
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c> or empty.</exception>
/// <exception cref="ArgumentException"><paramref name="name"/> already exists.</exception>
Task<User> CreateUserAsync(string name);
/// <summary>
/// Deletes the specified user.
/// </summary>
/// <param name="userId">The id of the user to be deleted.</param>
/// <returns>A task representing the deletion of the user.</returns>
Task DeleteUserAsync(Guid userId);
/// <summary>
/// Resets the password.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
Task ResetPassword(User user);
/// <summary>
/// Changes the password.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="newPassword">New password to use.</param>
/// <returns>Awaitable task.</returns>
Task ChangePassword(User user, string newPassword);
/// <summary>
/// Gets the user dto.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="remoteEndPoint">The remote end point.</param>
/// <returns>UserDto.</returns>
UserDto GetUserDto(User user, string? remoteEndPoint = null);
/// <summary>
/// Authenticates the user.
/// </summary>
/// <param name="username">The user.</param>
/// <param name="password">The password to use.</param>
/// <param name="remoteEndPoint">Remove endpoint to use.</param>
/// <param name="isUserSession">Specifies if a user session.</param>
/// <returns>User wrapped in awaitable task.</returns>
Task<User?> AuthenticateUser(string username, string password, string remoteEndPoint, bool isUserSession);
/// <summary>
/// Starts the forgot password process.
/// </summary>
/// <param name="enteredUsername">The entered username.</param>
/// <param name="isInNetwork">if set to <c>true</c> [is in network].</param>
/// <returns>ForgotPasswordResult.</returns>
Task<ForgotPasswordResult> StartForgotPasswordProcess(string enteredUsername, bool isInNetwork);
/// <summary>
/// Redeems the password reset pin.
/// </summary>
/// <param name="pin">The pin.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
Task<PinRedeemResult> RedeemPasswordResetPin(string pin);
NameIdPair[] GetAuthenticationProviders();
NameIdPair[] GetPasswordResetProviders();
/// <summary>
/// This method updates the user's configuration.
/// This is only included as a stopgap until the new API, using this internally is not recommended.
/// Instead, modify the user object directly, then call <see cref="UpdateUserAsync"/>.
/// </summary>
/// <param name="userId">The user's Id.</param>
/// <param name="config">The request containing the new user configuration.</param>
/// <returns>A task representing the update.</returns>
Task UpdateConfigurationAsync(Guid userId, UserConfiguration config);
/// <summary>
/// This method updates the user's policy.
/// This is only included as a stopgap until the new API, using this internally is not recommended.
/// Instead, modify the user object directly, then call <see cref="UpdateUserAsync"/>.
/// </summary>
/// <param name="userId">The user's Id.</param>
/// <param name="policy">The request containing the new user policy.</param>
/// <returns>A task representing the update.</returns>
Task UpdatePolicyAsync(Guid userId, UserPolicy policy);
/// <summary>
/// Clears the user's profile image.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>A task representing the clearing of the profile image.</returns>
Task ClearProfileImageAsync(User user);
}
}
@@ -0,0 +1,42 @@
#nullable disable
#pragma warning disable CA1002, CS1591
using System;
using System.Collections.Generic;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Controller.Library
{
public interface IUserViewManager
{
/// <summary>
/// Gets user views.
/// </summary>
/// <param name="query">Query to use.</param>
/// <returns>Set of folders.</returns>
Folder[] GetUserViews(UserViewQuery query);
/// <summary>
/// Gets user sub views.
/// </summary>
/// <param name="parentId">Parent to use.</param>
/// <param name="type">Type to use.</param>
/// <param name="localizationKey">Localization key to use.</param>
/// <param name="sortName">Sort to use.</param>
/// <returns>User view.</returns>
UserView GetUserSubView(Guid parentId, CollectionType? type, string localizationKey, string sortName);
/// <summary>
/// Gets latest items.
/// </summary>
/// <param name="request">Query to use.</param>
/// <param name="options">Options to use.</param>
/// <returns>Set of items.</returns>
List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request, DtoOptions options);
}
}
@@ -0,0 +1,23 @@
#nullable disable
#pragma warning disable CS1591
using System;
namespace MediaBrowser.Controller.Library
{
public class IntroInfo
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
public string Path { get; set; }
/// <summary>
/// Gets or sets the item id.
/// </summary>
/// <value>The item id.</value>
public Guid? ItemId { get; set; }
}
}
@@ -0,0 +1,28 @@
#nullable disable
#pragma warning disable CA1711, CS1591
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class ItemChangeEventArgs.
/// </summary>
public class ItemChangeEventArgs
{
/// <summary>
/// Gets or sets the item.
/// </summary>
/// <value>The item.</value>
public BaseItem Item { get; set; }
public BaseItem Parent { get; set; }
/// <summary>
/// Gets or sets the item.
/// </summary>
/// <value>The item.</value>
public ItemUpdateType UpdateReason { get; set; }
}
}
@@ -0,0 +1,286 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// These are arguments relating to the file system that are collected once and then referred to
/// whenever needed. Primarily for entity resolution.
/// </summary>
public class ItemResolveArgs
{
/// <summary>
/// The _app paths.
/// </summary>
private readonly IServerApplicationPaths _appPaths;
private readonly ILibraryManager _libraryManager;
private LibraryOptions _libraryOptions;
/// <summary>
/// Initializes a new instance of the <see cref="ItemResolveArgs" /> class.
/// </summary>
/// <param name="appPaths">The app paths.</param>
/// <param name="libraryManager">The library manager.</param>
public ItemResolveArgs(IServerApplicationPaths appPaths, ILibraryManager libraryManager)
{
_appPaths = appPaths;
_libraryManager = libraryManager;
}
/// <summary>
/// Gets or sets the file system children.
/// </summary>
/// <value>The file system children.</value>
public FileSystemMetadata[] FileSystemChildren { get; set; }
public LibraryOptions LibraryOptions
{
get => _libraryOptions ??= Parent is null ? new LibraryOptions() : _libraryManager.GetLibraryOptions(Parent);
set => _libraryOptions = value;
}
/// <summary>
/// Gets or sets the parent.
/// </summary>
/// <value>The parent.</value>
public Folder Parent { get; set; }
/// <summary>
/// Gets or sets the file info.
/// </summary>
/// <value>The file info.</value>
public FileSystemMetadata FileInfo { get; set; }
/// <summary>
/// Gets the path.
/// </summary>
/// <value>The path.</value>
public string Path => FileInfo.FullName;
/// <summary>
/// Gets a value indicating whether this instance is directory.
/// </summary>
/// <value><c>true</c> if this instance is directory; otherwise, <c>false</c>.</value>
public bool IsDirectory => FileInfo.IsDirectory;
/// <summary>
/// Gets a value indicating whether this instance is vf.
/// </summary>
/// <value><c>true</c> if this instance is vf; otherwise, <c>false</c>.</value>
public bool IsVf
{
// we should be considered a virtual folder if we are a child of one of the children of the system root folder.
// this is a bit of a trick to determine that... the directory name of a sub-child of the root will start with
// the root but not be equal to it
get
{
if (!IsDirectory)
{
return false;
}
var parentDir = System.IO.Path.GetDirectoryName(Path) ?? string.Empty;
return parentDir.Length > _appPaths.RootFolderPath.Length
&& parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
}
}
/// <summary>
/// Gets a value indicating whether this instance is physical root.
/// </summary>
/// <value><c>true</c> if this instance is physical root; otherwise, <c>false</c>.</value>
public bool IsPhysicalRoot => IsDirectory && BaseItem.FileSystem.AreEqual(Path, _appPaths.RootFolderPath);
/// <summary>
/// Gets or sets the additional locations.
/// </summary>
/// <value>The additional locations.</value>
private List<string> AdditionalLocations { get; set; }
/// <summary>
/// Gets the physical locations.
/// </summary>
/// <value>The physical locations.</value>
public string[] PhysicalLocations
{
get
{
var paths = string.IsNullOrEmpty(Path) ? Array.Empty<string>() : [Path];
return AdditionalLocations is null ? paths : [..paths, ..AdditionalLocations];
}
}
public CollectionType? CollectionType { get; set; }
public bool HasParent<T>()
where T : Folder
{
var parent = Parent;
if (parent is not null)
{
var item = parent as T;
// Just in case the user decided to nest episodes.
// Not officially supported but in some cases we can handle it.
if (item is null)
{
var parents = parent.GetParents();
foreach (var currentParent in parents)
{
if (currentParent is T)
{
return true;
}
}
}
return item is not null;
}
return false;
}
/// <summary>
/// Determines whether the specified <see cref="object" /> is equal to this instance.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>
/// <returns><c>true</c> if the specified <see cref="object" /> is equal to this instance; otherwise, <c>false</c>.</returns>
public override bool Equals(object obj)
{
return Equals(obj as ItemResolveArgs);
}
/// <summary>
/// Adds the additional location.
/// </summary>
/// <param name="path">The path.</param>
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <c>null</c> or empty.</exception>
public void AddAdditionalLocation(string path)
{
ArgumentException.ThrowIfNullOrEmpty(path);
AdditionalLocations ??= new List<string>();
AdditionalLocations.Add(path);
}
// REVIEW: @bond
/// <summary>
/// Gets the name of the file system entry by.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>FileSystemInfo.</returns>
/// <exception cref="ArgumentNullException"><paramref name="name"/> is <c>null</c> or empty.</exception>
public FileSystemMetadata GetFileSystemEntryByName(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);
return GetFileSystemEntryByPath(System.IO.Path.Combine(Path, name));
}
/// <summary>
/// Gets the file system entry by path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>FileSystemInfo.</returns>
/// <exception cref="ArgumentNullException">Throws if path is invalid.</exception>
public FileSystemMetadata GetFileSystemEntryByPath(string path)
{
ArgumentException.ThrowIfNullOrEmpty(path);
foreach (var file in FileSystemChildren)
{
if (string.Equals(file.FullName, path, StringComparison.Ordinal))
{
return file;
}
}
return null;
}
/// <summary>
/// Determines whether [contains file system entry by name] [the specified name].
/// </summary>
/// <param name="name">The name.</param>
/// <returns><c>true</c> if [contains file system entry by name] [the specified name]; otherwise, <c>false</c>.</returns>
public bool ContainsFileSystemEntryByName(string name)
{
return GetFileSystemEntryByName(name) is not null;
}
public CollectionType? GetCollectionType()
{
return CollectionType;
}
/// <summary>
/// Gets the configured content type for the path.
/// </summary>
/// <returns>The configured content type.</returns>
public CollectionType? GetConfiguredContentType()
{
return _libraryManager.GetConfiguredContentType(Path);
}
/// <summary>
/// Gets the file system children that do not hit the ignore file check.
/// </summary>
/// <returns>The file system children that are not ignored.</returns>
public IEnumerable<FileSystemMetadata> GetActualFileSystemChildren()
{
var numberOfChildren = FileSystemChildren.Length;
for (var i = 0; i < numberOfChildren; i++)
{
var child = FileSystemChildren[i];
if (_libraryManager.IgnoreFile(child, Parent))
{
continue;
}
yield return child;
}
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
public override int GetHashCode()
{
return Path.GetHashCode(StringComparison.Ordinal);
}
/// <summary>
/// Equals the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns><c>true</c> if the arguments are the same, <c>false</c> otherwise.</returns>
protected bool Equals(ItemResolveArgs args)
{
if (args is not null)
{
if (args.Path is null && Path is null)
{
return true;
}
return args.Path is not null && BaseItem.FileSystem.AreEqual(args.Path, Path);
}
return false;
}
}
}
@@ -0,0 +1,16 @@
#pragma warning disable CS1591
using System;
namespace MediaBrowser.Controller.Library
{
[Flags]
public enum ItemUpdateType
{
None = 1,
MetadataImport = 2,
ImageUpdate = 4,
MetadataDownload = 8,
MetadataEdit = 16
}
}
@@ -0,0 +1,15 @@
#pragma warning disable CS1591
using System;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
public static class LibraryManagerExtensions
{
public static BaseItem? GetItemById(this ILibraryManager manager, string id)
{
return manager.GetItemById(new Guid(id));
}
}
}
@@ -0,0 +1,24 @@
#pragma warning disable CS1591
using System;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Library
{
public static class MetadataConfigurationExtensions
{
public static MetadataConfiguration GetMetadataConfiguration(this IConfigurationManager config)
=> config.GetConfiguration<MetadataConfiguration>("metadata");
/// <summary>
/// Gets the <see cref="MetadataOptions" /> for the specified type.
/// </summary>
/// <param name="config">The <see cref="IServerConfigurationManager"/>.</param>
/// <param name="type">The type to get the <see cref="MetadataOptions" /> for.</param>
/// <returns>The <see cref="MetadataOptions" /> for the specified type or <c>null</c>.</returns>
public static MetadataOptions? GetMetadataOptionsForType(this IServerConfigurationManager config, string type)
=> Array.Find(config.Configuration.MetadataOptions, i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase));
}
}
@@ -0,0 +1,23 @@
#pragma warning disable CS1591
using System.Collections.Generic;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Library
{
public class MetadataConfigurationStore : IConfigurationFactory
{
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new ConfigurationStore[]
{
new ConfigurationStore
{
Key = "metadata",
ConfigurationType = typeof(MetadataConfiguration)
}
};
}
}
}
@@ -0,0 +1,25 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Extensions;
namespace MediaBrowser.Controller.Library
{
public static class NameExtensions
{
public static IEnumerable<string> DistinctNames(this IEnumerable<string> names)
=> names.DistinctBy(RemoveDiacritics, StringComparer.OrdinalIgnoreCase);
private static string RemoveDiacritics(string? name)
{
if (name is null)
{
return string.Empty;
}
return name.RemoveDiacritics();
}
}
}
@@ -0,0 +1,48 @@
#nullable disable
#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Holds information about a playback progress event.
/// </summary>
public class PlaybackProgressEventArgs : EventArgs
{
public PlaybackProgressEventArgs()
{
Users = new List<User>();
}
public List<User> Users { get; set; }
public long? PlaybackPositionTicks { get; set; }
public BaseItem Item { get; set; }
public BaseItemDto MediaInfo { get; set; }
public string MediaSourceId { get; set; }
public bool IsPaused { get; set; }
public bool IsAutomated { get; set; }
public string DeviceId { get; set; }
public string DeviceName { get; set; }
public string ClientName { get; set; }
public string PlaySessionId { get; set; }
public SessionInfo Session { get; set; }
}
}
@@ -0,0 +1,9 @@
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// An event that occurs when playback is started.
/// </summary>
public class PlaybackStartEventArgs : PlaybackProgressEventArgs
{
}
}
@@ -0,0 +1,13 @@
#pragma warning disable CS1591
namespace MediaBrowser.Controller.Library
{
public class PlaybackStopEventArgs : PlaybackProgressEventArgs
{
/// <summary>
/// Gets or sets a value indicating whether [played to completion].
/// </summary>
/// <value><c>true</c> if [played to completion]; otherwise, <c>false</c>.</value>
public bool PlayedToCompletion { get; set; }
}
}
@@ -0,0 +1,24 @@
#nullable disable
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class SearchHintInfo.
/// </summary>
public class SearchHintInfo
{
/// <summary>
/// Gets or sets the item.
/// </summary>
/// <value>The item.</value>
public BaseItem Item { get; set; }
/// <summary>
/// Gets or sets the matched term.
/// </summary>
/// <value>The matched term.</value>
public string MatchedTerm { get; set; }
}
}
@@ -0,0 +1,49 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class TVUtils.
/// </summary>
public static class TVUtils
{
/// <summary>
/// Gets the air days.
/// </summary>
/// <param name="day">The day.</param>
/// <returns>List{DayOfWeek}.</returns>
[return: NotNullIfNotNull("day")]
public static DayOfWeek[]? GetAirDays(string? day)
{
if (!string.IsNullOrEmpty(day))
{
if (string.Equals(day, "Daily", StringComparison.OrdinalIgnoreCase))
{
return new[]
{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
}
if (Enum.TryParse(day, true, out DayOfWeek value))
{
return new[]
{
value
};
}
return Array.Empty<DayOfWeek>();
}
return null;
}
}
}
@@ -0,0 +1,43 @@
#nullable disable
#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class UserDataSaveEventArgs.
/// </summary>
public class UserDataSaveEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the user id.
/// </summary>
/// <value>The user id.</value>
public Guid UserId { get; set; }
public List<string> Keys { get; set; }
/// <summary>
/// Gets or sets the save reason.
/// </summary>
/// <value>The save reason.</value>
public UserDataSaveReason SaveReason { get; set; }
/// <summary>
/// Gets or sets the user data.
/// </summary>
/// <value>The user data.</value>
public UserItemData UserData { get; set; }
/// <summary>
/// Gets or sets the item.
/// </summary>
/// <value>The item.</value>
public BaseItem Item { get; set; }
}
}