Merge branch 'master' into syncplay-enhanced

This commit is contained in:
Joshua M. Boniface
2020-11-27 09:46:18 -05:00
committed by GitHub
510 changed files with 15504 additions and 8822 deletions

View File

@@ -0,0 +1,86 @@
using System;
using System.Linq;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.BaseItemManager
{
/// <inheritdoc />
public class BaseItemManager : IBaseItemManager
{
private readonly IServerConfigurationManager _serverConfigurationManager;
/// <summary>
/// Initializes a new instance of the <see cref="BaseItemManager"/> class.
/// </summary>
/// <param name="serverConfigurationManager">Instance of the <see cref="IServerConfigurationManager"/> interface.</param>
public BaseItemManager(IServerConfigurationManager serverConfigurationManager)
{
_serverConfigurationManager = serverConfigurationManager;
}
/// <inheritdoc />
public bool IsMetadataFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name)
{
if (baseItem is Channel)
{
// Hack alert.
return true;
}
if (baseItem.SourceType == SourceType.Channel)
{
// Hack alert.
return !baseItem.EnableMediaSourceDisplay;
}
var typeOptions = libraryOptions.GetTypeOptions(GetType().Name);
if (typeOptions != null)
{
return typeOptions.ImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
if (!libraryOptions.EnableInternetProviders)
{
return false;
}
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, GetType().Name, StringComparison.OrdinalIgnoreCase));
return itemConfig == null || !itemConfig.DisabledImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
/// <inheritdoc />
public bool IsImageFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name)
{
if (baseItem is Channel)
{
// Hack alert.
return true;
}
if (baseItem.SourceType == SourceType.Channel)
{
// Hack alert.
return !baseItem.EnableMediaSourceDisplay;
}
var typeOptions = libraryOptions.GetTypeOptions(GetType().Name);
if (typeOptions != null)
{
return typeOptions.ImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
if (!libraryOptions.EnableInternetProviders)
{
return false;
}
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, GetType().Name, StringComparison.OrdinalIgnoreCase));
return itemConfig == null || !itemConfig.DisabledImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
}
}

View File

@@ -0,0 +1,29 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.BaseItemManager
{
/// <summary>
/// The <c>BaseItem</c> manager.
/// </summary>
public interface IBaseItemManager
{
/// <summary>
/// Is metadata fetcher enabled.
/// </summary>
/// <param name="baseItem">The base item.</param>
/// <param name="libraryOptions">The library options.</param>
/// <param name="name">The metadata fetcher name.</param>
/// <returns><c>true</c> if metadata fetcher is enabled, else false.</returns>
bool IsMetadataFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name);
/// <summary>
/// Is image fetcher enabled.
/// </summary>
/// <param name="baseItem">The base item.</param>
/// <param name="libraryOptions">The library options.</param>
/// <param name="name">The image fetcher name.</param>
/// <returns><c>true</c> if image fetcher is enabled, else false.</returns>
bool IsImageFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name);
}
}

View File

@@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
@@ -15,9 +16,9 @@ namespace MediaBrowser.Controller.Dto
ItemFields.RefreshState
};
public ItemFields[] Fields { get; set; }
public IReadOnlyList<ItemFields> Fields { get; set; }
public ImageType[] ImageTypes { get; set; }
public IReadOnlyList<ImageType> ImageTypes { get; set; }
public int ImageTypeLimit { get; set; }

View File

@@ -56,7 +56,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
if (query.IncludeItemTypes.Length == 0)
{
query.IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name };
query.IncludeItemTypes = new[] { nameof(Audio), nameof(MusicVideo), nameof(MusicAlbum) };
query.ArtistIds = new[] { Id };
}

View File

@@ -64,7 +64,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
{
query.GenreIds = new[] { Id };
query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
query.IncludeItemTypes = new[] { nameof(MusicVideo), nameof(Audio), nameof(MusicAlbum), nameof(MusicArtist) };
return LibraryManager.GetItemList(query);
}

View File

@@ -87,6 +87,8 @@ namespace MediaBrowser.Controller.Entities
public const string InterviewFolderName = "interviews";
public const string SceneFolderName = "scenes";
public const string SampleFolderName = "samples";
public const string ShortsFolderName = "shorts";
public const string FeaturettesFolderName = "featurettes";
public static readonly string[] AllExtrasTypesFolderNames = {
ExtrasFolderName,
@@ -94,7 +96,9 @@ namespace MediaBrowser.Controller.Entities
DeletedScenesFolderName,
InterviewFolderName,
SceneFolderName,
SampleFolderName
SampleFolderName,
ShortsFolderName,
FeaturettesFolderName
};
[JsonIgnore]
@@ -459,60 +463,6 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public string PrimaryImagePath => this.GetImagePath(ImageType.Primary);
public bool IsMetadataFetcherEnabled(LibraryOptions libraryOptions, string name)
{
if (SourceType == SourceType.Channel)
{
// hack alert
return !EnableMediaSourceDisplay;
}
var typeOptions = libraryOptions.GetTypeOptions(GetType().Name);
if (typeOptions != null)
{
return typeOptions.MetadataFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
if (!libraryOptions.EnableInternetProviders)
{
return false;
}
var itemConfig = ConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, GetType().Name, StringComparison.OrdinalIgnoreCase));
return itemConfig == null || !itemConfig.DisabledMetadataFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
public bool IsImageFetcherEnabled(LibraryOptions libraryOptions, string name)
{
if (this is Channel)
{
// hack alert
return true;
}
if (SourceType == SourceType.Channel)
{
// hack alert
return !EnableMediaSourceDisplay;
}
var typeOptions = libraryOptions.GetTypeOptions(GetType().Name);
if (typeOptions != null)
{
return typeOptions.ImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
if (!libraryOptions.EnableInternetProviders)
{
return false;
}
var itemConfig = ConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, GetType().Name, StringComparison.OrdinalIgnoreCase));
return itemConfig == null || !itemConfig.DisabledImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
}
public virtual bool CanDelete()
{
if (SourceType == SourceType.Channel)
@@ -1435,7 +1385,6 @@ namespace MediaBrowser.Controller.Entities
new List<FileSystemMetadata>();
var ownedItemsChanged = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false);
await LibraryManager.UpdateImagesAsync(this).ConfigureAwait(false); // ensure all image properties in DB are fresh
if (ownedItemsChanged)
{
@@ -2607,7 +2556,7 @@ namespace MediaBrowser.Controller.Entities
{
if (!AllowsMultipleImages(type))
{
throw new ArgumentException("The change index operation is only applicable to backdrops and screenshots");
throw new ArgumentException("The change index operation is only applicable to backdrops and screen shots");
}
var info1 = GetImageInfo(type, index1);

View File

@@ -212,7 +212,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Loads our children. Validation will occur externally.
/// We want this sychronous.
/// We want this synchronous.
/// </summary>
protected virtual List<BaseItem> LoadChildren()
{
@@ -353,11 +353,6 @@ namespace MediaBrowser.Controller.Entities
{
await currentChild.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false);
}
else
{
// metadata is up-to-date; make sure DB has correct images dimensions and hash
await LibraryManager.UpdateImagesAsync(currentChild).ConfigureAwait(false);
}
continue;
}
@@ -723,7 +718,7 @@ namespace MediaBrowser.Controller.Entities
private bool RequiresPostFiltering2(InternalItemsQuery query)
{
if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], typeof(BoxSet).Name, StringComparison.OrdinalIgnoreCase))
if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], nameof(BoxSet), StringComparison.OrdinalIgnoreCase))
{
Logger.LogDebug("Query requires post-filtering due to BoxSet query");
return true;
@@ -813,7 +808,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsPlayed.HasValue)
{
if (query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes.Contains(typeof(Series).Name))
if (query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes.Contains(nameof(Series)))
{
Logger.LogDebug("Query requires post-filtering due to IsPlayed");
return true;
@@ -1067,12 +1062,12 @@ namespace MediaBrowser.Controller.Entities
return false;
}
if (request.Genres.Length > 0)
if (request.Genres.Count > 0)
{
return false;
}
if (request.GenreIds.Length > 0)
if (request.GenreIds.Count > 0)
{
return false;
}
@@ -1177,7 +1172,7 @@ namespace MediaBrowser.Controller.Entities
return false;
}
if (request.GenreIds.Length > 0)
if (request.GenreIds.Count > 0)
{
return false;
}

View File

@@ -59,7 +59,13 @@ namespace MediaBrowser.Controller.Entities
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
{
query.GenreIds = new[] { Id };
query.ExcludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
query.ExcludeItemTypes = new[]
{
nameof(MusicVideo),
nameof(Entities.Audio.Audio),
nameof(MusicAlbum),
nameof(MusicArtist)
};
return LibraryManager.GetItemList(query);
}

View File

@@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.Entities
public string[] ExcludeInheritedTags { get; set; }
public string[] Genres { get; set; }
public IReadOnlyList<string> Genres { get; set; }
public bool? IsSpecialSeason { get; set; }
@@ -116,7 +116,7 @@ namespace MediaBrowser.Controller.Entities
public Guid[] StudioIds { get; set; }
public Guid[] GenreIds { get; set; }
public IReadOnlyList<Guid> GenreIds { get; set; }
public ImageType[] ImageTypes { get; set; }
@@ -162,7 +162,7 @@ namespace MediaBrowser.Controller.Entities
public double? MinCommunityRating { get; set; }
public Guid[] ChannelIds { get; set; }
public IReadOnlyList<Guid> ChannelIds { get; set; }
public int? ParentIndexNumber { get; set; }

View File

@@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System;
using Jellyfin.Data.Entities;
namespace MediaBrowser.Controller.Entities
{
@@ -23,6 +24,10 @@ namespace MediaBrowser.Controller.Entities
public string NameContains { get; set; }
public User User { get; set; }
public bool? IsFavorite { get; set; }
public InternalPeopleQuery()
{
PersonTypes = Array.Empty<string>();

View File

@@ -151,7 +151,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (query.IncludeItemTypes.Length == 0)
{
query.IncludeItemTypes = new[] { typeof(Episode).Name };
query.IncludeItemTypes = new[] { nameof(Episode) };
}
query.IsVirtualItem = false;
@@ -207,7 +207,7 @@ namespace MediaBrowser.Controller.Entities.TV
query.AncestorWithPresentationUniqueKey = null;
query.SeriesPresentationUniqueKey = seriesKey;
query.IncludeItemTypes = new[] { typeof(Season).Name };
query.IncludeItemTypes = new[] { nameof(Season) };
query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray();
if (user != null && !user.DisplayMissingEpisodes)
@@ -233,7 +233,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (query.IncludeItemTypes.Length == 0)
{
query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name };
query.IncludeItemTypes = new[] { nameof(Episode), nameof(Season) };
}
query.IsVirtualItem = false;
@@ -253,7 +253,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
AncestorWithPresentationUniqueKey = null,
SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
IncludeItemTypes = new[] { nameof(Episode), nameof(Season) },
OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
DtoOptions = options
};
@@ -364,7 +364,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
AncestorWithPresentationUniqueKey = queryFromSeries ? null : seriesKey,
SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null,
IncludeItemTypes = new[] { typeof(Episode).Name },
IncludeItemTypes = new[] { nameof(Episode) },
OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
DtoOptions = options
};

View File

@@ -142,7 +142,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IncludeItemTypes.Length == 0)
{
query.IncludeItemTypes = new[] { typeof(Movie).Name };
query.IncludeItemTypes = new[] { nameof(Movie) };
}
return parent.QueryRecursive(query);
@@ -167,7 +167,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.IsFavorite = true;
query.IncludeItemTypes = new[] { typeof(Movie).Name };
query.IncludeItemTypes = new[] { nameof(Movie) };
return _libraryManager.GetItemsResult(query);
}
@@ -178,7 +178,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.IsFavorite = true;
query.IncludeItemTypes = new[] { typeof(Series).Name };
query.IncludeItemTypes = new[] { nameof(Series) };
return _libraryManager.GetItemsResult(query);
}
@@ -189,7 +189,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.IsFavorite = true;
query.IncludeItemTypes = new[] { typeof(Episode).Name };
query.IncludeItemTypes = new[] { nameof(Episode) };
return _libraryManager.GetItemsResult(query);
}
@@ -200,7 +200,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Movie).Name };
query.IncludeItemTypes = new[] { nameof(Movie) };
return _libraryManager.GetItemsResult(query);
}
@@ -208,7 +208,7 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query)
{
query.Parent = null;
query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
query.IncludeItemTypes = new[] { nameof(BoxSet) };
query.SetUser(user);
query.Recursive = true;
@@ -223,7 +223,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.Limit = GetSpecialItemsLimit();
query.IncludeItemTypes = new[] { typeof(Movie).Name };
query.IncludeItemTypes = new[] { nameof(Movie) };
return ConvertToResult(_libraryManager.GetItemList(query));
}
@@ -236,7 +236,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.Limit = GetSpecialItemsLimit();
query.IncludeItemTypes = new[] { typeof(Movie).Name };
query.IncludeItemTypes = new[] { nameof(Movie) };
return ConvertToResult(_libraryManager.GetItemList(query));
}
@@ -255,7 +255,7 @@ namespace MediaBrowser.Controller.Entities
{
var genres = parent.QueryRecursive(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Movie).Name },
IncludeItemTypes = new[] { nameof(Movie) },
Recursive = true,
EnableTotalRecordCount = false
}).Items
@@ -286,7 +286,7 @@ namespace MediaBrowser.Controller.Entities
query.GenreIds = new[] { displayParent.Id };
query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Movie).Name };
query.IncludeItemTypes = new[] { nameof(Movie) };
return _libraryManager.GetItemsResult(query);
}
@@ -333,7 +333,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.Limit = GetSpecialItemsLimit();
query.IncludeItemTypes = new[] { typeof(Episode).Name };
query.IncludeItemTypes = new[] { nameof(Episode) };
query.IsVirtualItem = false;
return ConvertToResult(_libraryManager.GetItemList(query));
@@ -362,7 +362,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.Limit = GetSpecialItemsLimit();
query.IncludeItemTypes = new[] { typeof(Episode).Name };
query.IncludeItemTypes = new[] { nameof(Episode) };
return ConvertToResult(_libraryManager.GetItemList(query));
}
@@ -373,7 +373,7 @@ namespace MediaBrowser.Controller.Entities
query.Parent = parent;
query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Series).Name };
query.IncludeItemTypes = new[] { nameof(Series) };
return _libraryManager.GetItemsResult(query);
}
@@ -382,7 +382,7 @@ namespace MediaBrowser.Controller.Entities
{
var genres = parent.QueryRecursive(new InternalItemsQuery(user)
{
IncludeItemTypes = new[] { typeof(Series).Name },
IncludeItemTypes = new[] { nameof(Series) },
Recursive = true,
EnableTotalRecordCount = false
}).Items
@@ -413,7 +413,7 @@ namespace MediaBrowser.Controller.Entities
query.GenreIds = new[] { displayParent.Id };
query.SetUser(user);
query.IncludeItemTypes = new[] { typeof(Series).Name };
query.IncludeItemTypes = new[] { nameof(Series) };
return _libraryManager.GetItemsResult(query);
}
@@ -791,7 +791,7 @@ namespace MediaBrowser.Controller.Entities
}
// Apply genre filter
if (query.Genres.Length > 0 && !query.Genres.Any(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)))
if (query.Genres.Count > 0 && !query.Genres.Any(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase)))
{
return false;
}
@@ -822,7 +822,7 @@ namespace MediaBrowser.Controller.Entities
}
// Apply genre filter
if (query.GenreIds.Length > 0 && !query.GenreIds.Any(id =>
if (query.GenreIds.Count > 0 && !query.GenreIds.Any(id =>
{
var genreItem = libraryManager.GetItemById(id);
return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase);

View File

@@ -12,6 +12,9 @@ namespace MediaBrowser.Controller
/// <summary>
/// Gets the display preferences for the user and client.
/// </summary>
/// <remarks>
/// This will create the display preferences if it does not exist, but it will not save automatically.
/// </remarks>
/// <param name="userId">The user's id.</param>
/// <param name="client">The client string.</param>
/// <returns>The associated display preferences.</returns>
@@ -20,6 +23,9 @@ namespace MediaBrowser.Controller
/// <summary>
/// Gets the default item display preferences for the user and client.
/// </summary>
/// <remarks>
/// This will create the item display preferences if it does not exist, but it will not save automatically.
/// </remarks>
/// <param name="userId">The user id.</param>
/// <param name="itemId">The item id.</param>
/// <param name="client">The client string.</param>

View File

@@ -1,9 +0,0 @@
#pragma warning disable CS1591
namespace MediaBrowser.Controller
{
public interface IResourceFileManager
{
string GetResourcePath(string basePath, string virtualPath);
}
}

View File

@@ -6,6 +6,7 @@ using System.Net;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.System;
using Microsoft.AspNetCore.Http;
@@ -56,41 +57,43 @@ namespace MediaBrowser.Controller
/// <summary>
/// Gets the system info.
/// </summary>
/// <param name="source">The originator of the request.</param>
/// <returns>SystemInfo.</returns>
Task<SystemInfo> GetSystemInfo(CancellationToken cancellationToken);
SystemInfo GetSystemInfo(IPAddress source);
Task<PublicSystemInfo> GetPublicSystemInfo(CancellationToken cancellationToken);
PublicSystemInfo GetPublicSystemInfo(IPAddress address);
/// <summary>
/// Gets all the local IP addresses of this API instance. Each address is validated by sending a 'ping' request
/// to the API that should exist at the address.
/// Gets a URL specific for the request.
/// </summary>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the task.</param>
/// <returns>A list containing all the local IP addresses of the server.</returns>
Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken);
/// <param name="request">The <see cref="HttpRequest"/> instance.</param>
/// <param name="port">Optional port number.</param>
/// <returns>An accessible URL.</returns>
string GetSmartApiUrl(HttpRequest request, int? port = null);
/// <summary>
/// Gets a local (LAN) URL that can be used to access the API. The hostname used is the first valid configured
/// IP address that can be found via <see cref="GetLocalIpAddresses"/>. HTTPS will be preferred when available.
/// Gets a URL specific for the request.
/// </summary>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the task.</param>
/// <returns>The server URL.</returns>
Task<string> GetLocalApiUrl(CancellationToken cancellationToken);
/// <param name="remoteAddr">The remote <see cref="IPAddress"/> of the connection.</param>
/// <param name="port">Optional port number.</param>
/// <returns>An accessible URL.</returns>
string GetSmartApiUrl(IPAddress remoteAddr, int? port = null);
/// <summary>
/// Gets a localhost URL that can be used to access the API using the loop-back IP address (127.0.0.1)
/// Gets a URL specific for the request.
/// </summary>
/// <param name="hostname">The hostname used in the connection.</param>
/// <param name="port">Optional port number.</param>
/// <returns>An accessible URL.</returns>
string GetSmartApiUrl(string hostname, int? port = null);
/// <summary>
/// Gets a localhost URL that can be used to access the API using the loop-back IP address.
/// over HTTP (not HTTPS).
/// </summary>
/// <returns>The API URL.</returns>
string GetLoopbackHttpApiUrl();
/// <summary>
/// Gets a local (LAN) URL that can be used to access the API. HTTPS will be preferred when available.
/// </summary>
/// <param name="address">The IP address to use as the hostname in the URL.</param>
/// <returns>The API URL.</returns>
string GetLocalApiUrl(IPAddress address);
/// <summary>
/// Gets a local (LAN) URL that can be used to access the API.
/// Note: if passing non-null scheme or port it is up to the caller to ensure they form the correct pair.
@@ -105,7 +108,7 @@ namespace MediaBrowser.Controller
/// preferring the HTTPS port, if available.
/// </param>
/// <returns>The API URL.</returns>
string GetLocalApiUrl(ReadOnlySpan<char> hostname, string scheme = null, int? port = null);
string GetLocalApiUrl(string hostname, string scheme = null, int? port = null);
/// <summary>
/// Open a URL in an external browser window.
@@ -119,5 +122,13 @@ namespace MediaBrowser.Controller
string ExpandVirtualPath(string path);
string ReverseVirtualPath(string path);
/// <summary>
/// Gets the list of local plugins.
/// </summary>
/// <param name="path">Plugin base directory.</param>
/// <param name="cleanup">Cleanup old plugins.</param>
/// <returns>Enumerable of local plugins.</returns>
IEnumerable<LocalPlugin> GetLocalPlugins(string path, bool cleanup = true);
}
}

View File

@@ -570,5 +570,9 @@ namespace MediaBrowser.Controller.Library
List<MediaStream> streams,
string videoPath,
string[] files);
void RunMetadataSavers(IReadOnlyList<BaseItem> items, ItemUpdateType updateReason);
BaseItem GetParentItem(string parentId, Guid? userId);
}
}

View File

@@ -115,5 +115,7 @@ namespace MediaBrowser.Controller.Library
public interface IDirectStreamProvider
{
Task CopyToAsync(Stream stream, CancellationToken cancellationToken);
string GetFilePath();
}
}

View File

@@ -158,7 +158,8 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="userId">The user's Id.</param>
/// <param name="config">The request containing the new user configuration.</param>
void UpdateConfiguration(Guid userId, UserConfiguration config);
/// <returns>A task representing the update.</returns>
Task UpdateConfigurationAsync(Guid userId, UserConfiguration config);
/// <summary>
/// This method updates the user's policy.
@@ -167,12 +168,14 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="userId">The user's Id.</param>
/// <param name="policy">The request containing the new user policy.</param>
void UpdatePolicy(Guid userId, UserPolicy policy);
/// <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>
void ClearProfileImage(User user);
/// <returns>A task representing the clearing of the profile image.</returns>
Task ClearProfileImageAsync(User user);
}
}

View File

@@ -225,7 +225,7 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="fields">The fields.</param>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, ItemFields[] fields, User user = null);
Task AddInfoToProgramDto(IReadOnlyCollection<(BaseItem, BaseItemDto)> programs, IReadOnlyList<ItemFields> fields, User user = null);
/// <summary>
/// Saves the tuner host.

View File

@@ -14,8 +14,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.9" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.9" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="5.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
</ItemGroup>
@@ -29,7 +29,7 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors Condition=" '$(Configuration)' == 'Release' ">true</TreatWarningsAsErrors>

File diff suppressed because it is too large Load Diff

View File

@@ -287,6 +287,11 @@ namespace MediaBrowser.Controller.MediaEncoding
return BaseRequest.AudioChannels;
}
if (BaseRequest.TranscodingMaxAudioChannels.HasValue)
{
return BaseRequest.TranscodingMaxAudioChannels;
}
if (!string.IsNullOrEmpty(codec))
{
var value = BaseRequest.GetOption(codec, "audiochannels");
@@ -404,7 +409,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
// Don't exceed what the encoder supports
// Seeing issues of attempting to encode to 88200
return Math.Min(44100, BaseRequest.AudioSampleRate.Value);
return BaseRequest.AudioSampleRate.Value;
}
return null;
@@ -588,6 +593,11 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
if (VideoStream == null)
{
return null;
}
if (EncodingHelper.IsCopyCodec(OutputVideoCodec))
{
return VideoStream?.Codec;
@@ -601,6 +611,11 @@ namespace MediaBrowser.Controller.MediaEncoding
{
get
{
if (AudioStream == null)
{
return null;
}
if (EncodingHelper.IsCopyCodec(OutputAudioCodec))
{
return AudioStream?.Codec;

View File

@@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else if (part.StartsWith("fps=", StringComparison.OrdinalIgnoreCase))
{
var rate = part.Split(new[] { '=' }, 2)[^1];
var rate = part.Split('=', 2)[^1];
if (float.TryParse(rate, NumberStyles.Any, _usCulture, out var val))
{
@@ -103,7 +103,7 @@ namespace MediaBrowser.Controller.MediaEncoding
else if (state.RunTimeTicks.HasValue &&
part.StartsWith("time=", StringComparison.OrdinalIgnoreCase))
{
var time = part.Split(new[] { '=' }, 2).Last();
var time = part.Split('=', 2)[^1];
if (TimeSpan.TryParse(time, _usCulture, out var val))
{
@@ -116,7 +116,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else if (part.StartsWith("size=", StringComparison.OrdinalIgnoreCase))
{
var size = part.Split(new[] { '=' }, 2).Last();
var size = part.Split('=', 2)[^1];
int? scale = null;
if (size.IndexOf("kb", StringComparison.OrdinalIgnoreCase) != -1)
@@ -135,7 +135,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
else if (part.StartsWith("bitrate=", StringComparison.OrdinalIgnoreCase))
{
var rate = part.Split(new[] { '=' }, 2).Last();
var rate = part.Split('=', 2)[^1];
int? scale = null;
if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1)

View File

@@ -1,10 +1,11 @@
#pragma warning disable CS1591
using System;
using Jellyfin.Data.Entities;
namespace MediaBrowser.Controller.Net
{
/// <summary>
/// The request authorization info.
/// </summary>
public class AuthorizationInfo
{
/// <summary>
@@ -43,6 +44,19 @@ namespace MediaBrowser.Controller.Net
/// <value>The token.</value>
public string Token { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the authorization is from an api key.
/// </summary>
public bool IsApiKey { get; set; }
/// <summary>
/// Gets or sets the user making the request.
/// </summary>
public User User { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the token is authenticated.
/// </summary>
public bool IsAuthenticated { get; set; }
}
}

View File

@@ -16,12 +16,6 @@ namespace MediaBrowser.Controller.Net
/// </summary>
event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
/// <summary>
/// Inits this instance.
/// </summary>
/// <param name="listeners">The websocket listeners.</param>
void Init(IEnumerable<IWebSocketListener> listeners);
/// <summary>
/// The HTTP request handler.
/// </summary>

View File

@@ -31,7 +31,7 @@ namespace MediaBrowser.Controller.Playlists
/// <param name="itemIds">The item ids.</param>
/// <param name="userId">The user identifier.</param>
/// <returns>Task.</returns>
Task AddToPlaylistAsync(Guid playlistId, ICollection<Guid> itemIds, Guid userId);
Task AddToPlaylistAsync(Guid playlistId, IReadOnlyCollection<Guid> itemIds, Guid userId);
/// <summary>
/// Removes from playlist.

View File

@@ -160,7 +160,7 @@ namespace MediaBrowser.Controller.Playlists
return LibraryManager.GetItemList(new InternalItemsQuery(user)
{
Recursive = true,
IncludeItemTypes = new[] { typeof(Audio).Name },
IncludeItemTypes = new[] { nameof(Audio) },
GenreIds = new[] { musicGenre.Id },
OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
DtoOptions = options
@@ -172,7 +172,7 @@ namespace MediaBrowser.Controller.Playlists
return LibraryManager.GetItemList(new InternalItemsQuery(user)
{
Recursive = true,
IncludeItemTypes = new[] { typeof(Audio).Name },
IncludeItemTypes = new[] { nameof(Audio) },
ArtistIds = new[] { musicArtist.Id },
OrderBy = new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
DtoOptions = options

View File

@@ -1,6 +1,7 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
@@ -54,7 +55,7 @@ namespace MediaBrowser.Controller.Session
/// Gets or sets the playable media types.
/// </summary>
/// <value>The playable media types.</value>
public string[] PlayableMediaTypes
public IReadOnlyList<string> PlayableMediaTypes
{
get
{
@@ -230,7 +231,7 @@ namespace MediaBrowser.Controller.Session
/// Gets or sets the supported commands.
/// </summary>
/// <value>The supported commands.</value>
public GeneralCommandType[] SupportedCommands
public IReadOnlyList<GeneralCommandType> SupportedCommands
=> Capabilities == null ? Array.Empty<GeneralCommandType>() : Capabilities.SupportedCommands;
public Tuple<ISessionController, bool> EnsureController<T>(Func<SessionInfo, ISessionController> factory)

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
@@ -52,6 +53,14 @@ namespace MediaBrowser.Controller.Subtitles
/// </summary>
Task DownloadSubtitles(Video video, LibraryOptions libraryOptions, string subtitleId, CancellationToken cancellationToken);
/// <summary>
/// Upload new subtitle.
/// </summary>
/// <param name="video">The video the subtitle belongs to.</param>
/// <param name="response">The subtitle response.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
Task UploadSubtitle(Video video, SubtitleResponse response);
/// <summary>
/// Gets the remote subtitles.
/// </summary>