Merge remote-tracking branch 'upstream/master' into quickconnect

This commit is contained in:
ConfusedPolarBear
2020-06-19 23:33:43 -05:00
725 changed files with 8927 additions and 5743 deletions

View File

@@ -1,5 +1,5 @@
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
using Jellyfin.Data.Entities;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Authentication
@@ -7,7 +7,9 @@ namespace MediaBrowser.Controller.Authentication
public interface IAuthenticationProvider
{
string Name { get; }
bool IsEnabled { get; }
Task<ProviderAuthenticationResult> Authenticate(string username, string password);
bool HasPassword(User user);
Task ChangePassword(User user, string newPassword);
@@ -28,6 +30,7 @@ namespace MediaBrowser.Controller.Authentication
public class ProviderAuthenticationResult
{
public string Username { get; set; }
public string DisplayName { get; set; }
}
}

View File

@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
using Jellyfin.Data.Entities;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Authentication
@@ -8,7 +8,9 @@ namespace MediaBrowser.Controller.Authentication
public interface IPasswordResetProvider
{
string Name { get; }
bool IsEnabled { get; }
Task<ForgotPasswordResult> StartForgotPasswordProcess(User user, bool isInNetwork);
Task<PinRedeemResult> RedeemPasswordResetPin(string pin);
}
@@ -16,6 +18,7 @@ namespace MediaBrowser.Controller.Authentication
public class PasswordPinCreationResult
{
public string PinFile { get; set; }
public DateTime ExpirationDate { get; set; }
}
}

View File

@@ -3,6 +3,8 @@ using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Querying;
@@ -13,16 +15,18 @@ namespace MediaBrowser.Controller.Channels
{
public override bool IsVisible(User user)
{
if (user.Policy.BlockedChannels != null)
if (user.GetPreference(PreferenceKind.BlockedChannels) != null)
{
if (user.Policy.BlockedChannels.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
if (user.GetPreference(PreferenceKind.BlockedChannels).Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
else
{
if (!user.Policy.EnableAllChannels && !user.Policy.EnabledChannels.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
if (!user.HasPermission(PermissionKind.EnableAllChannels)
&& !user.GetPreference(PreferenceKind.EnabledChannels)
.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
{
return false;
}

View File

@@ -24,7 +24,9 @@ namespace MediaBrowser.Controller.Channels
public string Overview { get; set; }
public List<string> Genres { get; set; }
public List<string> Studios { get; set; }
public List<string> Tags { get; set; }
public List<PersonInfo> People { get; set; }
@@ -34,26 +36,33 @@ namespace MediaBrowser.Controller.Channels
public long? RunTimeTicks { get; set; }
public string ImageUrl { get; set; }
public string OriginalTitle { get; set; }
public ChannelMediaType MediaType { get; set; }
public ChannelFolderType FolderType { get; set; }
public ChannelMediaContentType ContentType { get; set; }
public ExtraType ExtraType { get; set; }
public List<TrailerType> TrailerTypes { get; set; }
public Dictionary<string, string> ProviderIds { get; set; }
public DateTime? PremiereDate { get; set; }
public int? ProductionYear { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public int? IndexNumber { get; set; }
public int? ParentIndexNumber { get; set; }
public List<MediaSourceInfo> MediaSources { get; set; }
@@ -63,7 +72,9 @@ namespace MediaBrowser.Controller.Channels
public List<string> Artists { get; set; }
public List<string> AlbumArtists { get; set; }
public bool IsLiveStream { get; set; }
public string Etag { get; set; }
public ChannelItemInfo()

View File

@@ -35,12 +35,10 @@ namespace MediaBrowser.Controller.Channels
public interface IDisableMediaSourceDisplay
{
}
public interface ISupportsMediaProbe
{
}
public interface IHasFolderAttributes

View File

@@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Channels
public List<ChannelMediaContentType> ContentTypes { get; set; }
/// <summary>
/// Represents the maximum number of records the channel allows retrieving at a time
/// Represents the maximum number of records the channel allows retrieving at a time.
/// </summary>
public int? MaxPageSize { get; set; }

View File

@@ -15,6 +15,7 @@ namespace MediaBrowser.Controller.Collections
public Dictionary<string, string> ProviderIds { get; set; }
public string[] ItemIdList { get; set; }
public Guid[] UserIds { get; set; }
public CollectionCreationOptions()

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;

View File

@@ -4,7 +4,7 @@ using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Configuration
{
/// <summary>
/// Interface IServerConfigurationManager
/// Interface IServerConfigurationManager.
/// </summary>
public interface IServerConfigurationManager : IConfigurationManager
{

View File

@@ -1,5 +1,5 @@
using System;
using MediaBrowser.Controller.Entities;
using Jellyfin.Data.Entities;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Querying;

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
@@ -9,7 +10,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Drawing
{
/// <summary>
/// Interface IImageProcessor
/// Interface IImageProcessor.
/// </summary>
public interface IImageProcessor
{
@@ -57,6 +58,8 @@ namespace MediaBrowser.Controller.Drawing
string GetImageCacheTag(BaseItem item, ChapterInfo info);
string GetImageCacheTag(User user);
/// <summary>
/// Processes the image.
/// </summary>

View File

@@ -16,6 +16,7 @@ namespace MediaBrowser.Controller.Drawing
return newSize;
}
return GetSizeEstimate(options);
}
@@ -57,6 +58,7 @@ namespace MediaBrowser.Controller.Drawing
case ImageType.BoxRear:
case ImageType.Disc:
case ImageType.Menu:
case ImageType.Profile:
return 1;
case ImageType.Logo:
return 2.58;

View File

@@ -15,6 +15,7 @@ namespace MediaBrowser.Controller.Drawing
}
public Guid ItemId { get; set; }
public BaseItem Item { get; set; }
public ItemImageInfo Image { get; set; }
@@ -38,12 +39,15 @@ namespace MediaBrowser.Controller.Drawing
public bool AddPlayedIndicator { get; set; }
public int? UnplayedCount { get; set; }
public int? Blur { get; set; }
public double PercentPlayed { get; set; }
public string BackgroundColor { get; set; }
public string ForegroundLayer { get; set; }
public bool RequiresAutoOrientation { get; set; }
private bool HasDefaultOptions(string originalImagePath)
@@ -73,14 +77,17 @@ namespace MediaBrowser.Controller.Drawing
{
return false;
}
if (Height.HasValue && !sizeValue.Height.Equals(Height.Value))
{
return false;
}
if (MaxWidth.HasValue && sizeValue.Width > MaxWidth.Value)
{
return false;
}
if (MaxHeight.HasValue && sizeValue.Height > MaxHeight.Value)
{
return false;

View File

@@ -14,11 +14,17 @@ namespace MediaBrowser.Controller.Dto
};
public ItemFields[] Fields { get; set; }
public ImageType[] ImageTypes { get; set; }
public int ImageTypeLimit { get; set; }
public bool EnableImages { get; set; }
public bool AddProgramRecordingInfo { get; set; }
public bool EnableUserData { get; set; }
public bool AddCurrentProgram { get; set; }
public DtoOptions()

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
@@ -6,7 +7,7 @@ using MediaBrowser.Model.Querying;
namespace MediaBrowser.Controller.Dto
{
/// <summary>
/// Interface IDtoService
/// Interface IDtoService.
/// </summary>
public interface IDtoService
{

View File

@@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.Entities
public override bool SupportsPlayedStatus => false;
/// <summary>
/// The _virtual children
/// The _virtual children.
/// </summary>
private readonly ConcurrentBag<BaseItem> _virtualChildren = new ConcurrentBag<BaseItem>();
@@ -195,6 +195,7 @@ namespace MediaBrowser.Controller.Entities
return child;
}
}
return null;
}
}

View File

@@ -2,16 +2,16 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities.Audio
{
/// <summary>
/// Class Audio
/// Class Audio.
/// </summary>
public class Audio : BaseItem,
IHasAlbumArtist,
@@ -93,6 +93,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
}
songKey += Name;
if (!string.IsNullOrEmpty(Album))
@@ -117,6 +118,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
return UnratedItem.Music;
}
return base.GetBlockUnratedType();
}

View File

@@ -4,17 +4,18 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
namespace MediaBrowser.Controller.Entities.Audio
{
/// <summary>
/// Class MusicAlbum
/// Class MusicAlbum.
/// </summary>
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer
{
@@ -55,6 +56,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
return LibraryManager.GetArtist(name, options);
}
return null;
}
@@ -97,14 +99,14 @@ namespace MediaBrowser.Controller.Entities.Audio
list.Insert(0, albumArtist + "-" + Name);
}
var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
var id = this.GetProviderId(MetadataProvider.MusicBrainzAlbum);
if (!string.IsNullOrEmpty(id))
{
list.Insert(0, "MusicAlbum-Musicbrainz-" + id);
}
id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
id = this.GetProviderId(MetadataProvider.MusicBrainzReleaseGroup);
if (!string.IsNullOrEmpty(id))
{
@@ -114,9 +116,9 @@ namespace MediaBrowser.Controller.Entities.Audio
return list;
}
protected override bool GetBlockUnratedValue(UserPolicy config)
protected override bool GetBlockUnratedValue(User user)
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
return user.GetPreference(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Music.ToString());
}
public override UnratedItem GetBlockUnratedType()

View File

@@ -4,17 +4,18 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Extensions;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Users;
using Microsoft.Extensions.Logging;
using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
namespace MediaBrowser.Controller.Entities.Audio
{
/// <summary>
/// Class MusicArtist
/// Class MusicArtist.
/// </summary>
public class MusicArtist : Folder, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo<ArtistInfo>
{
@@ -76,11 +77,7 @@ namespace MediaBrowser.Controller.Entities.Audio
public override int GetChildCount(User user)
{
if (IsAccessedByName)
{
return 0;
}
return base.GetChildCount(user);
return IsAccessedByName ? 0 : base.GetChildCount(user);
}
public override bool IsSaveLocalMetadataEnabled()
@@ -114,7 +111,7 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
@@ -128,7 +125,7 @@ namespace MediaBrowser.Controller.Entities.Audio
private static List<string> GetUserDataKeys(MusicArtist item)
{
var list = new List<string>();
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
var id = item.GetProviderId(MetadataProvider.MusicBrainzArtist);
if (!string.IsNullOrEmpty(id))
{
@@ -138,13 +135,15 @@ namespace MediaBrowser.Controller.Entities.Audio
list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics());
return list;
}
public override string CreatePresentationUniqueKey()
{
return "Artist-" + (Name ?? string.Empty).RemoveDiacritics();
}
protected override bool GetBlockUnratedValue(UserPolicy config)
protected override bool GetBlockUnratedValue(User user)
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
return user.GetPreference(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Music.ToString());
}
public override UnratedItem GetBlockUnratedType()
@@ -203,7 +202,7 @@ namespace MediaBrowser.Controller.Entities.Audio
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
{

View File

@@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities.Audio
{
/// <summary>
/// Class MusicGenre
/// Class MusicGenre.
/// </summary>
public class MusicGenre : BaseItem, IItemByName
{
@@ -18,6 +18,7 @@ namespace MediaBrowser.Controller.Entities.Audio
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
public override string CreatePresentationUniqueKey()
{
return GetUserDataKeys()[0];
@@ -34,7 +35,7 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
@@ -94,11 +95,12 @@ namespace MediaBrowser.Controller.Entities.Audio
Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities
{
@@ -24,10 +24,12 @@ namespace MediaBrowser.Controller.Entities
{
return SeriesName;
}
public string FindSeriesName()
{
return SeriesName;
}
public string FindSeriesPresentationUniqueKey()
{
return SeriesPresentationUniqueKey;

View File

@@ -7,6 +7,8 @@ using System.Text;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
@@ -24,18 +26,17 @@ using MediaBrowser.Model.Library;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Users;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class BaseItem
/// Class BaseItem.
/// </summary>
public abstract class BaseItem : IHasProviderIds, IHasLookupInfo<ItemLookupInfo>, IEquatable<BaseItem>
{
/// <summary>
/// The supported image extensions
/// The supported image extensions.
/// </summary>
public static readonly string[] SupportedImageExtensions
= new[] { ".png", ".jpg", ".jpeg", ".tbn", ".gif" };
@@ -63,7 +64,7 @@ namespace MediaBrowser.Controller.Entities
Genres = Array.Empty<string>();
Studios = Array.Empty<string>();
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
LockedFields = Array.Empty<MetadataFields>();
LockedFields = Array.Empty<MetadataField>();
ImageInfos = Array.Empty<ItemImageInfo>();
ProductionLocations = Array.Empty<string>();
RemoteTrailers = Array.Empty<MediaUrl>();
@@ -74,7 +75,7 @@ namespace MediaBrowser.Controller.Entities
public static char SlugChar = '-';
/// <summary>
/// The trailer folder name
/// The trailer folder name.
/// </summary>
public const string TrailerFolderName = "trailers";
public const string ThemeSongsFolderName = "theme-music";
@@ -107,6 +108,7 @@ namespace MediaBrowser.Controller.Entities
public string PreferredMetadataLanguage { get; set; }
public long? Size { get; set; }
public string Container { get; set; }
[JsonIgnore]
@@ -242,7 +244,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
[JsonIgnore]
public virtual string ContainingFolderPath
@@ -266,7 +268,7 @@ namespace MediaBrowser.Controller.Entities
public string ServiceName { get; set; }
/// <summary>
/// If this content came from an external service, the id of the content on that service
/// If this content came from an external service, the id of the content on that service.
/// </summary>
[JsonIgnore]
public string ExternalId { get; set; }
@@ -299,7 +301,7 @@ namespace MediaBrowser.Controller.Entities
{
get
{
//if (IsOffline)
// if (IsOffline)
//{
// return LocationType.Offline;
//}
@@ -410,7 +412,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// This is just a helper for convenience
/// This is just a helper for convenience.
/// </summary>
/// <value>The primary image path.</value>
[JsonIgnore]
@@ -447,6 +449,7 @@ namespace MediaBrowser.Controller.Entities
// hack alert
return true;
}
if (SourceType == SourceType.Channel)
{
// hack alert
@@ -481,12 +484,12 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders)
{
if (user.Policy.EnableContentDeletion)
if (user.HasPermission(PermissionKind.EnableContentDeletion))
{
return true;
}
var allowed = user.Policy.EnableContentDeletionFromFolders;
var allowed = user.GetPreference(PreferenceKind.EnableContentDeletionFromFolders);
if (SourceType == SourceType.Channel)
{
@@ -527,7 +530,7 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsAuthorizedToDownload(User user)
{
return user.Policy.EnableContentDownloading;
return user.HasPermission(PermissionKind.EnableContentDownloading);
}
public bool CanDownload(User user)
@@ -555,17 +558,28 @@ namespace MediaBrowser.Controller.Entities
public DateTime DateLastRefreshed { get; set; }
/// <summary>
/// The logger
/// The logger.
/// </summary>
public static ILogger Logger { get; set; }
public static ILoggerFactory LoggerFactory { get; set; }
public static ILogger<BaseItem> Logger { get; set; }
public static ILibraryManager LibraryManager { get; set; }
public static IServerConfigurationManager ConfigurationManager { get; set; }
public static IProviderManager ProviderManager { get; set; }
public static ILocalizationManager LocalizationManager { get; set; }
public static IItemRepository ItemRepository { get; set; }
public static IFileSystem FileSystem { get; set; }
public static IUserDataManager UserDataManager { get; set; }
public static IChannelManager ChannelManager { get; set; }
public static IMediaSourceManager MediaSourceManager { get; set; }
/// <summary>
@@ -585,7 +599,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The locked fields.</value>
[JsonIgnore]
public MetadataFields[] LockedFields { get; set; }
public MetadataField[] LockedFields { get; set; }
/// <summary>
/// Gets the type of the media.
@@ -642,8 +656,10 @@ namespace MediaBrowser.Controller.Entities
_sortName = CreateSortName();
}
}
return _sortName;
}
set => _sortName = value;
}
@@ -674,7 +690,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>System.String.</returns>
protected virtual string CreateSortName()
{
if (Name == null) return null; //some items may not have name filled in properly
if (Name == null) return null; // some items may not have name filled in properly
if (!EnableAlphaNumericSorting)
{
@@ -734,7 +750,7 @@ namespace MediaBrowser.Controller.Entities
builder.Append(chunkBuilder);
}
//logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString());
// logger.LogDebug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString());
return builder.ToString().RemoveDiacritics();
}
@@ -765,7 +781,6 @@ namespace MediaBrowser.Controller.Entities
get => GetParent() as Folder;
set
{
}
}
@@ -798,7 +813,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Finds a parent of a given type
/// Finds a parent of a given type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns>``0.</returns>
@@ -813,6 +828,7 @@ namespace MediaBrowser.Controller.Entities
return item;
}
}
return null;
}
@@ -836,6 +852,7 @@ namespace MediaBrowser.Controller.Entities
{
return null;
}
return LibraryManager.GetItemById(id);
}
}
@@ -1004,12 +1021,12 @@ namespace MediaBrowser.Controller.Entities
/// <returns>PlayAccess.</returns>
public PlayAccess GetPlayAccess(User user)
{
if (!user.Policy.EnableMediaPlayback)
if (!user.HasPermission(PermissionKind.EnableMediaPlayback))
{
return PlayAccess.None;
}
//if (!user.IsParentalScheduleAllowed())
// if (!user.IsParentalScheduleAllowed())
//{
// return PlayAccess.None;
//}
@@ -1062,7 +1079,6 @@ namespace MediaBrowser.Controller.Entities
}
return 1;
}).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
.ThenByDescending(i =>
{
@@ -1213,11 +1229,11 @@ namespace MediaBrowser.Controller.Entities
{
if (video.IsoType.HasValue)
{
if (video.IsoType.Value == Model.Entities.IsoType.BluRay)
if (video.IsoType.Value == IsoType.BluRay)
{
terms.Add("Bluray");
}
else if (video.IsoType.Value == Model.Entities.IsoType.Dvd)
else if (video.IsoType.Value == IsoType.Dvd)
{
terms.Add("DVD");
}
@@ -1245,8 +1261,7 @@ namespace MediaBrowser.Controller.Entities
// Support plex/xbmc convention
files.AddRange(fileSystemChildren
.Where(i => !i.IsDirectory && string.Equals(FileSystem.GetFileNameWithoutExtension(i), ThemeSongFilename, StringComparison.OrdinalIgnoreCase))
);
.Where(i => !i.IsDirectory && string.Equals(FileSystem.GetFileNameWithoutExtension(i), ThemeSongFilename, StringComparison.OrdinalIgnoreCase)));
return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions())
.OfType<Audio.Audio>()
@@ -1345,16 +1360,14 @@ namespace MediaBrowser.Controller.Entities
protected virtual void TriggerOnRefreshStart()
{
}
protected virtual void TriggerOnRefreshComplete()
{
}
/// <summary>
/// Overrides the base implementation to refresh metadata for local trailers
/// Overrides the base implementation to refresh metadata for local trailers.
/// </summary>
/// <param name="options">The options.</param>
/// <param name="cancellationToken">The cancellation token.</param>
@@ -1756,7 +1769,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Determines if a given user has access to this item
/// Determines if a given user has access to this item.
/// </summary>
/// <param name="user">The user.</param>
/// <returns><c>true</c> if [is parental allowed] [the specified user]; otherwise, <c>false</c>.</returns>
@@ -1773,7 +1786,7 @@ namespace MediaBrowser.Controller.Entities
return false;
}
var maxAllowedRating = user.Policy.MaxParentalRating;
var maxAllowedRating = user.MaxParentalAgeRating;
if (maxAllowedRating == null)
{
@@ -1789,7 +1802,7 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrEmpty(rating))
{
return !GetBlockUnratedValue(user.Policy);
return !GetBlockUnratedValue(user);
}
var value = LocalizationManager.GetRatingLevel(rating);
@@ -1797,7 +1810,7 @@ namespace MediaBrowser.Controller.Entities
// Could not determine the integer value
if (!value.HasValue)
{
var isAllowed = !GetBlockUnratedValue(user.Policy);
var isAllowed = !GetBlockUnratedValue(user);
if (!isAllowed)
{
@@ -1859,8 +1872,7 @@ namespace MediaBrowser.Controller.Entities
private bool IsVisibleViaTags(User user)
{
var policy = user.Policy;
if (policy.BlockedTags.Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
if (user.GetPreference(PreferenceKind.BlockedTags).Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
{
return false;
}
@@ -1886,22 +1898,18 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Gets the block unrated value.
/// </summary>
/// <param name="config">The configuration.</param>
/// <param name="user">The configuration.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
protected virtual bool GetBlockUnratedValue(UserPolicy config)
protected virtual bool GetBlockUnratedValue(User user)
{
// Don't block plain folders that are unrated. Let the media underneath get blocked
// Special folders like series and albums will override this method.
if (IsFolder)
{
return false;
}
if (this is IItemByName)
if (IsFolder || this is IItemByName)
{
return false;
}
return config.BlockUnratedItems.Contains(GetBlockUnratedType());
return user.GetPreference(PreferenceKind.BlockUnratedItems).Contains(GetBlockUnratedType().ToString());
}
/// <summary>
@@ -2067,7 +2075,7 @@ namespace MediaBrowser.Controller.Entities
public virtual bool EnableRememberingTrackSelections => true;
/// <summary>
/// Adds a studio to the item
/// Adds a studio to the item.
/// </summary>
/// <param name="name">The name.</param>
/// <exception cref="ArgumentNullException"></exception>
@@ -2103,7 +2111,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Adds a genre to the item
/// Adds a genre to the item.
/// </summary>
/// <param name="name">The name.</param>
/// <exception cref="ArgumentNullException"></exception>
@@ -2131,7 +2139,8 @@ namespace MediaBrowser.Controller.Entities
/// <param name="resetPosition">if set to <c>true</c> [reset position].</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException"></exception>
public virtual void MarkPlayed(User user,
public virtual void MarkPlayed(
User user,
DateTime? datePlayed,
bool resetPosition)
{
@@ -2177,7 +2186,7 @@ namespace MediaBrowser.Controller.Entities
var data = UserDataManager.GetUserData(user, this);
//I think it is okay to do this here.
// I think it is okay to do this here.
// if this is only called when a user is manually forcing something to un-played
// then it probably is what we want to do...
data.PlayCount = 0;
@@ -2197,7 +2206,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Gets an image
/// Gets an image.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="imageIndex">Index of the image.</param>
@@ -2513,7 +2522,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Gets the file system path to delete when the item is to be deleted
/// Gets the file system path to delete when the item is to be deleted.
/// </summary>
/// <returns></returns>
public virtual IEnumerable<FileSystemMetadata> GetDeletePaths()
@@ -2762,8 +2771,8 @@ namespace MediaBrowser.Controller.Entities
newOptions.ForceSave = true;
}
//var parentId = Id;
//if (!video.IsOwnedItem || video.ParentId != parentId)
// var parentId = Id;
// if (!video.IsOwnedItem || video.ParentId != parentId)
//{
// video.IsOwnedItem = true;
// video.ParentId = parentId;
@@ -2805,14 +2814,7 @@ namespace MediaBrowser.Controller.Entities
return this;
}
foreach (var parent in GetParents())
{
if (parent.IsTopParent)
{
return parent;
}
}
return null;
return GetParents().FirstOrDefault(parent => parent.IsTopParent);
}
[JsonIgnore]

View File

@@ -27,7 +27,7 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public override bool SupportsPeople => false;
//public override double? GetDefaultPrimaryImageAspectRatio()
// public override double? GetDefaultPrimaryImageAspectRatio()
//{
// double value = 16;
// value /= 9;

View File

@@ -1,8 +1,8 @@
using System;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities
{

View File

@@ -18,12 +18,14 @@ namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Specialized Folder class that points to a subset of the physical folders in the system.
/// It is created from the user-specific folders within the system root
/// It is created from the user-specific folders within the system root.
/// </summary>
public class CollectionFolder : Folder, ICollectionFolder
{
public static IXmlSerializer XmlSerializer { get; set; }
public static IJsonSerializer JsonSerializer { get; set; }
public static IServerApplicationHost ApplicationHost { get; set; }
public CollectionFolder()
@@ -140,7 +142,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Allow different display preferences for each collection folder
/// Allow different display preferences for each collection folder.
/// </summary>
/// <value>The display prefs id.</value>
[JsonIgnore]
@@ -155,6 +157,7 @@ namespace MediaBrowser.Controller.Entities
}
public string[] PhysicalLocationsList { get; set; }
public Guid[] PhysicalFolderIds { get; set; }
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)

View File

@@ -1,71 +0,0 @@
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities
{
public static class DayOfWeekHelper
{
public static List<DayOfWeek> GetDaysOfWeek(DynamicDayOfWeek day)
{
return GetDaysOfWeek(new List<DynamicDayOfWeek> { day });
}
public static List<DayOfWeek> GetDaysOfWeek(List<DynamicDayOfWeek> days)
{
var list = new List<DayOfWeek>();
if (days.Contains(DynamicDayOfWeek.Sunday) ||
days.Contains(DynamicDayOfWeek.Weekend) ||
days.Contains(DynamicDayOfWeek.Everyday))
{
list.Add(DayOfWeek.Sunday);
}
if (days.Contains(DynamicDayOfWeek.Saturday) ||
days.Contains(DynamicDayOfWeek.Weekend) ||
days.Contains(DynamicDayOfWeek.Everyday))
{
list.Add(DayOfWeek.Saturday);
}
if (days.Contains(DynamicDayOfWeek.Monday) ||
days.Contains(DynamicDayOfWeek.Weekday) ||
days.Contains(DynamicDayOfWeek.Everyday))
{
list.Add(DayOfWeek.Monday);
}
if (days.Contains(DynamicDayOfWeek.Tuesday) ||
days.Contains(DynamicDayOfWeek.Weekday) ||
days.Contains(DynamicDayOfWeek.Everyday))
{
list.Add(DayOfWeek.Tuesday
);
}
if (days.Contains(DynamicDayOfWeek.Wednesday) ||
days.Contains(DynamicDayOfWeek.Weekday) ||
days.Contains(DynamicDayOfWeek.Everyday))
{
list.Add(DayOfWeek.Wednesday);
}
if (days.Contains(DynamicDayOfWeek.Thursday) ||
days.Contains(DynamicDayOfWeek.Weekday) ||
days.Contains(DynamicDayOfWeek.Everyday))
{
list.Add(DayOfWeek.Thursday);
}
if (days.Contains(DynamicDayOfWeek.Friday) ||
days.Contains(DynamicDayOfWeek.Weekday) ||
days.Contains(DynamicDayOfWeek.Everyday))
{
list.Add(DayOfWeek.Friday);
}
return list;
}
}
}

View File

@@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Extensions
/// Class Extensions.
/// </summary>
public static class Extensions
{

View File

@@ -8,6 +8,8 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Collections;
@@ -15,18 +17,21 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using MusicAlbum = MediaBrowser.Controller.Entities.Audio.MusicAlbum;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Folder
/// Class Folder.
/// </summary>
public class Folder : BaseItem
{
@@ -121,10 +126,12 @@ namespace MediaBrowser.Controller.Entities
{
return false;
}
if (this is UserView)
{
return false;
}
return true;
}
@@ -151,6 +158,7 @@ namespace MediaBrowser.Controller.Entities
{
item.DateCreated = DateTime.UtcNow;
}
if (item.DateModified == DateTime.MinValue)
{
item.DateModified = DateTime.UtcNow;
@@ -167,7 +175,7 @@ namespace MediaBrowser.Controller.Entities
public virtual IEnumerable<BaseItem> Children => LoadChildren();
/// <summary>
/// thread-safe access to all recursive children of this folder - without regard to user
/// thread-safe access to all recursive children of this folder - without regard to user.
/// </summary>
/// <value>The recursive children.</value>
[JsonIgnore]
@@ -177,19 +185,22 @@ namespace MediaBrowser.Controller.Entities
{
if (this is ICollectionFolder && !(this is BasePluginFolder))
{
if (user.Policy.BlockedMediaFolders != null)
var blockedMediaFolders = user.GetPreference(PreferenceKind.BlockedMediaFolders);
if (blockedMediaFolders.Length > 0)
{
if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase) ||
if (blockedMediaFolders.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase) ||
// Backwards compatibility
user.Policy.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
blockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase))
{
return false;
}
}
else
{
if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
if (!user.HasPermission(PermissionKind.EnableAllFolders)
&& !user.GetPreference(PreferenceKind.EnabledFolders)
.Contains(Id.ToString("N", CultureInfo.InvariantCulture), StringComparer.OrdinalIgnoreCase))
{
return false;
}
@@ -205,8 +216,8 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
protected virtual List<BaseItem> LoadChildren()
{
//logger.LogDebug("Loading children from {0} {1} {2}", GetType().Name, Id, Path);
//just load our children from the repo - the library will be validated and maintained in other processes
// logger.LogDebug("Loading children from {0} {1} {2}", GetType().Name, Id, Path);
// just load our children from the repo - the library will be validated and maintained in other processes
return GetCachedChildren();
}
@@ -221,7 +232,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Validates that the children of the folder still exist
/// Validates that the children of the folder still exist.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
@@ -492,8 +503,8 @@ namespace MediaBrowser.Controller.Entities
if (series != null)
{
await series.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
}
await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false);
}
@@ -563,7 +574,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Get the children of this folder from the actual file system
/// Get the children of this folder from the actual file system.
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
@@ -575,7 +586,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Get our children from the repo - stubbed for now
/// Get our children from the repo - stubbed for now.
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
protected List<BaseItem> GetCachedChildren()
@@ -607,7 +618,6 @@ namespace MediaBrowser.Controller.Entities
{
EnableImages = false
}
});
return result.TotalRecordCount;
@@ -882,7 +892,7 @@ namespace MediaBrowser.Controller.Entities
try
{
query.Parent = this;
query.ChannelIds = new Guid[] { ChannelId };
query.ChannelIds = new[] { ChannelId };
// Don't blow up here because it could cause parent screens with other content to fail
return ChannelManager.GetChannelItemsInternal(query, new SimpleProgress<double>(), CancellationToken.None).Result;
@@ -933,6 +943,7 @@ namespace MediaBrowser.Controller.Entities
{
items = items.Where(i => string.Compare(query.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1);
}
if (!string.IsNullOrEmpty(query.NameStartsWith))
{
items = items.Where(i => i.SortName.StartsWith(query.NameStartsWith, StringComparison.OrdinalIgnoreCase));
@@ -952,11 +963,13 @@ namespace MediaBrowser.Controller.Entities
return UserViewBuilder.SortAndPage(items, null, query, LibraryManager, enableSorting);
}
private static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
private static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(
IEnumerable<BaseItem> items,
InternalItemsQuery query,
BaseItem queryParent,
User user,
IServerConfigurationManager configurationManager, ICollectionManager collectionManager)
IServerConfigurationManager configurationManager,
ICollectionManager collectionManager)
{
if (items == null)
{
@@ -981,18 +994,22 @@ namespace MediaBrowser.Controller.Entities
{
return false;
}
if (queryParent is Series)
{
return false;
}
if (queryParent is Season)
{
return false;
}
if (queryParent is MusicAlbum)
{
return false;
}
if (queryParent is MusicArtist)
{
return false;
@@ -1022,22 +1039,27 @@ namespace MediaBrowser.Controller.Entities
{
return false;
}
if (request.IsFavoriteOrLiked.HasValue)
{
return false;
}
if (request.IsLiked.HasValue)
{
return false;
}
if (request.IsPlayed.HasValue)
{
return false;
}
if (request.IsResumable.HasValue)
{
return false;
}
if (request.IsFolder.HasValue)
{
return false;
@@ -1213,7 +1235,7 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException(nameof(user));
}
//the true root should return our users root folder children
// the true root should return our users root folder children
if (IsPhysicalRoot)
{
return LibraryManager.GetUserRootFolder().GetChildren(user, includeLinkedChildren);
@@ -1278,7 +1300,7 @@ namespace MediaBrowser.Controller.Entities
}
/// <summary>
/// Gets allowed recursive children of an item
/// Gets allowed recursive children of an item.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
@@ -1383,6 +1405,7 @@ namespace MediaBrowser.Controller.Entities
list.Add(child);
}
}
return list;
}
@@ -1405,6 +1428,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
}
return false;
}
@@ -1582,7 +1606,7 @@ namespace MediaBrowser.Controller.Entities
EnableTotalRecordCount = false
};
if (!user.Configuration.DisplayMissingEpisodes)
if (!user.DisplayMissingEpisodes)
{
query.IsVirtualItem = false;
}
@@ -1619,7 +1643,6 @@ namespace MediaBrowser.Controller.Entities
Recursive = true,
IsFolder = false,
EnableTotalRecordCount = false
});
// Sweep through recursively and update status
@@ -1637,7 +1660,6 @@ namespace MediaBrowser.Controller.Entities
IsFolder = false,
IsVirtualItem = false,
EnableTotalRecordCount = false
});
return itemsResult
@@ -1659,22 +1681,27 @@ namespace MediaBrowser.Controller.Entities
{
return false;
}
if (this is UserView)
{
return false;
}
if (this is UserRootFolder)
{
return false;
}
if (this is Channel)
{
return false;
}
if (SourceType != SourceType.Library)
{
return false;
}
var iItemByName = this as IItemByName;
if (iItemByName != null)
{

View File

@@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Genre
/// Class Genre.
/// </summary>
public class Genre : BaseItem, IItemByName
{
@@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Entities
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
public override string CreatePresentationUniqueKey()
{
return GetUserDataKeys()[0];
@@ -31,7 +32,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
@@ -92,11 +93,12 @@ namespace MediaBrowser.Controller.Entities
Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
{

View File

@@ -3,7 +3,7 @@ using System;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// This is just a marker interface to denote top level folders
/// This is just a marker interface to denote top level folders.
/// </summary>
public interface ICollectionFolder : IHasCollectionType
{

View File

@@ -1,7 +1,7 @@
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Interface IHasAspectRatio
/// Interface IHasAspectRatio.
/// </summary>
public interface IHasAspectRatio
{

View File

@@ -1,7 +1,7 @@
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Interface IHasDisplayOrder
/// Interface IHasDisplayOrder.
/// </summary>
public interface IHasDisplayOrder
{

View File

@@ -13,7 +13,9 @@ namespace MediaBrowser.Controller.Entities
List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
List<MediaStream> GetMediaStreams();
Guid Id { get; set; }
long? RunTimeTicks { get; set; }
string Path { get; }
}
}

View File

@@ -5,13 +5,21 @@ namespace MediaBrowser.Controller.Entities
public interface IHasProgramAttributes
{
bool IsMovie { get; set; }
bool IsSports { get; }
bool IsNews { get; }
bool IsKids { get; }
bool IsRepeat { get; set; }
bool IsSeries { get; set; }
ProgramAudio? Audio { get; set; }
string EpisodeTitle { get; set; }
string ServiceName { get; set; }
}
}

View File

@@ -1,7 +1,7 @@
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Interface IHasScreenshots
/// Interface IHasScreenshots.
/// </summary>
public interface IHasScreenshots
{

View File

@@ -9,11 +9,14 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value>The name of the series.</value>
string SeriesName { get; set; }
string FindSeriesName();
string FindSeriesSortName();
Guid SeriesId { get; set; }
Guid FindSeriesId();
string SeriesPresentationUniqueKey { get; set; }
string FindSeriesPresentationUniqueKey();
}
}

View File

@@ -1,8 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
@@ -20,100 +21,167 @@ namespace MediaBrowser.Controller.Entities
public BaseItem SimilarTo { get; set; }
public bool? IsFolder { get; set; }
public bool? IsFavorite { get; set; }
public bool? IsFavoriteOrLiked { get; set; }
public bool? IsLiked { get; set; }
public bool? IsPlayed { get; set; }
public bool? IsResumable { get; set; }
public bool? IncludeItemsByName { get; set; }
public string[] MediaTypes { get; set; }
public string[] IncludeItemTypes { get; set; }
public string[] ExcludeItemTypes { get; set; }
public string[] ExcludeTags { get; set; }
public string[] ExcludeInheritedTags { get; set; }
public string[] Genres { get; set; }
public bool? IsSpecialSeason { get; set; }
public bool? IsMissing { get; set; }
public bool? IsUnaired { get; set; }
public bool? CollapseBoxSetItems { get; set; }
public string NameStartsWithOrGreater { get; set; }
public string NameStartsWith { get; set; }
public string NameLessThan { get; set; }
public string NameContains { get; set; }
public string MinSortName { get; set; }
public string PresentationUniqueKey { get; set; }
public string Path { get; set; }
public string Name { get; set; }
public string Person { get; set; }
public Guid[] PersonIds { get; set; }
public Guid[] ItemIds { get; set; }
public Guid[] ExcludeItemIds { get; set; }
public string AdjacentTo { get; set; }
public string[] PersonTypes { get; set; }
public bool? Is3D { get; set; }
public bool? IsHD { get; set; }
public bool? IsLocked { get; set; }
public bool? IsPlaceHolder { get; set; }
public bool? HasImdbId { get; set; }
public bool? HasOverview { get; set; }
public bool? HasTmdbId { get; set; }
public bool? HasOfficialRating { get; set; }
public bool? HasTvdbId { get; set; }
public bool? HasThemeSong { get; set; }
public bool? HasThemeVideo { get; set; }
public bool? HasSubtitles { get; set; }
public bool? HasSpecialFeature { get; set; }
public bool? HasTrailer { get; set; }
public bool? HasParentalRating { get; set; }
public Guid[] StudioIds { get; set; }
public Guid[] GenreIds { get; set; }
public ImageType[] ImageTypes { get; set; }
public VideoType[] VideoTypes { get; set; }
public UnratedItem[] BlockUnratedItems { get; set; }
public int[] Years { get; set; }
public string[] Tags { get; set; }
public string[] OfficialRatings { get; set; }
public DateTime? MinPremiereDate { get; set; }
public DateTime? MaxPremiereDate { get; set; }
public DateTime? MinStartDate { get; set; }
public DateTime? MaxStartDate { get; set; }
public DateTime? MinEndDate { get; set; }
public DateTime? MaxEndDate { get; set; }
public bool? IsAiring { get; set; }
public bool? IsMovie { get; set; }
public bool? IsSports { get; set; }
public bool? IsKids { get; set; }
public bool? IsNews { get; set; }
public bool? IsSeries { get; set; }
public int? MinIndexNumber { get; set; }
public int? AiredDuringSeason { get; set; }
public double? MinCriticRating { get; set; }
public double? MinCommunityRating { get; set; }
public Guid[] ChannelIds { get; set; }
public int? ParentIndexNumber { get; set; }
public int? ParentIndexNumberNotEquals { get; set; }
public int? IndexNumber { get; set; }
public int? MinParentalRating { get; set; }
public int? MaxParentalRating { get; set; }
public bool? HasDeadParentId { get; set; }
public bool? IsVirtualItem { get; set; }
public Guid ParentId { get; set; }
public string ParentType { get; set; }
public Guid[] AncestorIds { get; set; }
public Guid[] TopParentIds { get; set; }
public BaseItem Parent
@@ -134,41 +202,65 @@ namespace MediaBrowser.Controller.Entities
}
public string[] PresetViews { get; set; }
public TrailerType[] TrailerTypes { get; set; }
public SourceType[] SourceTypes { get; set; }
public SeriesStatus[] SeriesStatuses { get; set; }
public string ExternalSeriesId { get; set; }
public string ExternalId { get; set; }
public Guid[] AlbumIds { get; set; }
public Guid[] ArtistIds { get; set; }
public Guid[] ExcludeArtistIds { get; set; }
public string AncestorWithPresentationUniqueKey { get; set; }
public string SeriesPresentationUniqueKey { get; set; }
public bool GroupByPresentationUniqueKey { get; set; }
public bool GroupBySeriesPresentationUniqueKey { get; set; }
public bool EnableTotalRecordCount { get; set; }
public bool ForceDirect { get; set; }
public Dictionary<string, string> ExcludeProviderIds { get; set; }
public bool EnableGroupByMetadataKey { get; set; }
public bool? HasChapterImages { get; set; }
public IReadOnlyList<(string, SortOrder)> OrderBy { get; set; }
public DateTime? MinDateCreated { get; set; }
public DateTime? MinDateLastSaved { get; set; }
public DateTime? MinDateLastSavedForUser { get; set; }
public DtoOptions DtoOptions { get; set; }
public int MinSimilarityScore { get; set; }
public string HasNoAudioTrackWithLanguage { get; set; }
public string HasNoInternalSubtitleTrackWithLanguage { get; set; }
public string HasNoExternalSubtitleTrackWithLanguage { get; set; }
public string HasNoSubtitleTrackWithLanguage { get; set; }
public bool? IsDeadArtist { get; set; }
public bool? IsDeadStudio { get; set; }
public bool? IsDeadPerson { get; set; }
public InternalItemsQuery()
@@ -223,32 +315,45 @@ namespace MediaBrowser.Controller.Entities
{
if (user != null)
{
var policy = user.Policy;
MaxParentalRating = policy.MaxParentalRating;
MaxParentalRating = user.MaxParentalAgeRating;
if (policy.MaxParentalRating.HasValue)
if (MaxParentalRating.HasValue)
{
BlockUnratedItems = policy.BlockUnratedItems.Where(i => i != UnratedItem.Other).ToArray();
BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems)
.Where(i => i != UnratedItem.Other.ToString())
.Select(e => Enum.Parse<UnratedItem>(e, true)).ToArray();
}
ExcludeInheritedTags = policy.BlockedTags;
ExcludeInheritedTags = user.GetPreference(PreferenceKind.BlockedTags);
User = user;
}
}
public Dictionary<string, string> HasAnyProviderId { get; set; }
public Guid[] AlbumArtistIds { get; set; }
public Guid[] BoxSetLibraryFolders { get; set; }
public Guid[] ContributingArtistIds { get; set; }
public bool? HasAired { get; set; }
public bool? HasOwnerId { get; set; }
public bool? Is4K { get; set; }
public int? MaxHeight { get; set; }
public int? MaxWidth { get; set; }
public int? MinHeight { get; set; }
public int? MinWidth { get; set; }
public string SearchTerm { get; set; }
public string SeriesTimerId { get; set; }
}
}

View File

@@ -9,14 +9,16 @@ namespace MediaBrowser.Controller.Entities
public class LinkedChild
{
public string Path { get; set; }
public LinkedChildType Type { get; set; }
public string LibraryItemId { get; set; }
[JsonIgnore]
public string Id { get; set; }
/// <summary>
/// Serves as a cache
/// Serves as a cache.
/// </summary>
public Guid? ItemId { get; set; }
@@ -63,6 +65,7 @@ namespace MediaBrowser.Controller.Entities
{
return _fileSystem.AreEqual(x.Path, y.Path);
}
return false;
}

View File

@@ -2,16 +2,16 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.Movies
{
/// <summary>
/// Class BoxSet
/// Class BoxSet.
/// </summary>
public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>
{
@@ -45,9 +45,9 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <value>The display order.</value>
public string DisplayOrder { get; set; }
protected override bool GetBlockUnratedValue(UserPolicy config)
protected override bool GetBlockUnratedValue(User user)
{
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
return user.GetPreference(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Movie.ToString());
}
public override double GetDefaultPrimaryImageAspectRatio()

View File

@@ -4,8 +4,8 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
@@ -13,7 +13,7 @@ using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities.Movies
{
/// <summary>
/// Class Movie
/// Class Movie.
/// </summary>
public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping
{
@@ -173,7 +173,7 @@ namespace MediaBrowser.Controller.Entities.Movies
{
var list = base.GetRelatedUrls();
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
var imdbId = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(imdbId))
{
list.Add(new ExternalUrl

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
namespace MediaBrowser.Controller.Entities
{

View File

@@ -113,6 +113,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
}
return false;
}
}

View File

@@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Entities
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
public override string CreatePresentationUniqueKey()
{
return GetUserDataKeys()[0];
@@ -46,7 +47,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
@@ -114,11 +115,12 @@ namespace MediaBrowser.Controller.Entities
Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
{

View File

@@ -29,6 +29,7 @@ namespace MediaBrowser.Controller.Entities
return photoAlbum;
}
}
return null;
}
}
@@ -68,17 +69,27 @@ namespace MediaBrowser.Controller.Entities
}
public string CameraMake { get; set; }
public string CameraModel { get; set; }
public string Software { get; set; }
public double? ExposureTime { get; set; }
public double? FocalLength { get; set; }
public ImageOrientation? Orientation { get; set; }
public double? Aperture { get; set; }
public double? ShutterSpeed { get; set; }
public double? Latitude { get; set; }
public double? Longitude { get; set; }
public double? Altitude { get; set; }
public int? IsoSpeedRating { get; set; }
}
}

View File

@@ -8,6 +8,7 @@ namespace MediaBrowser.Controller.Entities
public class Share
{
public string UserId { get; set; }
public bool CanEdit { get; set; }
}
}

View File

@@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Studio
/// Class Studio.
/// </summary>
public class Studio : BaseItem, IItemByName
{
@@ -18,6 +18,7 @@ namespace MediaBrowser.Controller.Entities
list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
return list;
}
public override string CreatePresentationUniqueKey()
{
return GetUserDataKeys()[0];
@@ -25,7 +26,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
@@ -93,11 +94,12 @@ namespace MediaBrowser.Controller.Entities
Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
{

View File

@@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
@@ -12,7 +12,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities.TV
{
/// <summary>
/// Class Episode
/// Class Episode.
/// </summary>
public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries
{
@@ -34,7 +34,9 @@ namespace MediaBrowser.Controller.Entities.TV
/// </summary>
/// <value>The aired season.</value>
public int? AirsBeforeSeasonNumber { get; set; }
public int? AirsAfterSeasonNumber { get; set; }
public int? AirsBeforeEpisodeNumber { get; set; }
/// <summary>
@@ -94,6 +96,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
take--;
}
list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
}
@@ -101,7 +104,7 @@ namespace MediaBrowser.Controller.Entities.TV
}
/// <summary>
/// This Episode's Series Instance
/// This Episode's Series Instance.
/// </summary>
/// <value>The series.</value>
[JsonIgnore]
@@ -114,6 +117,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
seriesId = FindSeriesId();
}
return !seriesId.Equals(Guid.Empty) ? (LibraryManager.GetItemById(seriesId) as Series) : null;
}
}
@@ -128,6 +132,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
seasonId = FindSeasonId();
}
return !seasonId.Equals(Guid.Empty) ? (LibraryManager.GetItemById(seasonId) as Season) : null;
}
}
@@ -160,6 +165,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
return "Season " + ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture);
}
return "Season Unknown";
}

View File

@@ -2,16 +2,16 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities.TV
{
/// <summary>
/// Class Season
/// Class Season.
/// </summary>
public class Season : Folder, IHasSeries, IHasLookupInfo<SeasonInfo>
{
@@ -68,7 +68,7 @@ namespace MediaBrowser.Controller.Entities.TV
}
/// <summary>
/// This Episode's Series Instance
/// This Episode's Series Instance.
/// </summary>
/// <value>The series.</value>
[JsonIgnore]
@@ -81,6 +81,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
seriesId = FindSeriesId();
}
return seriesId == Guid.Empty ? null : (LibraryManager.GetItemById(seriesId) as Series);
}
}
@@ -168,7 +169,7 @@ namespace MediaBrowser.Controller.Entities.TV
return GetEpisodes(user, new DtoOptions(true));
}
protected override bool GetBlockUnratedValue(UserPolicy config)
protected override bool GetBlockUnratedValue(User user)
{
// Don't block. Let either the entire series rating or episode rating determine it
return false;
@@ -203,7 +204,7 @@ namespace MediaBrowser.Controller.Entities.TV
public Guid FindSeriesId()
{
var series = FindParent<Series>();
return series == null ? Guid.Empty : series.Id;
return series?.Id ?? Guid.Empty;
}
/// <summary>
@@ -225,7 +226,7 @@ namespace MediaBrowser.Controller.Entities.TV
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
@@ -234,7 +235,7 @@ namespace MediaBrowser.Controller.Entities.TV
if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{
IndexNumber = IndexNumber ?? LibraryManager.GetSeasonNumberFromPath(Path);
IndexNumber ??= LibraryManager.GetSeasonNumberFromPath(Path);
// If a change was made record it
if (IndexNumber.HasValue)

View File

@@ -5,18 +5,19 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Users;
using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
namespace MediaBrowser.Controller.Entities.TV
{
/// <summary>
/// Class Series
/// Class Series.
/// </summary>
public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IMetadataContainer
{
@@ -29,6 +30,7 @@ namespace MediaBrowser.Controller.Entities.TV
}
public DayOfWeek[] AirDays { get; set; }
public string AirTime { get; set; }
[JsonIgnore]
@@ -53,7 +55,7 @@ namespace MediaBrowser.Controller.Entities.TV
public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary>
/// airdate, dvd or absolute
/// airdate, dvd or absolute.
/// </summary>
public string DisplayOrder { get; set; }
@@ -119,7 +121,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
AncestorWithPresentationUniqueKey = null,
SeriesPresentationUniqueKey = seriesKey,
IncludeItemTypes = new[] { typeof(Season).Name },
IncludeItemTypes = new[] { nameof(Season) },
IsVirtualItem = false,
Limit = 0,
DtoOptions = new DtoOptions(false)
@@ -149,6 +151,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
query.IncludeItemTypes = new[] { typeof(Episode).Name };
}
query.IsVirtualItem = false;
query.Limit = 0;
var totalRecordCount = LibraryManager.GetCount(query);
@@ -164,13 +167,13 @@ namespace MediaBrowser.Controller.Entities.TV
{
var list = base.GetUserDataKeys();
var key = this.GetProviderId(MetadataProviders.Imdb);
var key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
}
key = this.GetProviderId(MetadataProviders.Tvdb);
key = this.GetProviderId(MetadataProvider.Tvdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
@@ -205,14 +208,9 @@ namespace MediaBrowser.Controller.Entities.TV
query.IncludeItemTypes = new[] { typeof(Season).Name };
query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray();
if (user != null)
if (user != null && !user.DisplayMissingEpisodes)
{
var config = user.Configuration;
if (!config.DisplayMissingEpisodes)
{
query.IsMissing = false;
}
query.IsMissing = false;
}
}
@@ -257,8 +255,8 @@ namespace MediaBrowser.Controller.Entities.TV
OrderBy = new[] { ItemSortBy.SortName }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(),
DtoOptions = options
};
var config = user.Configuration;
if (!config.DisplayMissingEpisodes)
if (!user.DisplayMissingEpisodes)
{
query.IsMissing = false;
}
@@ -311,7 +309,7 @@ namespace MediaBrowser.Controller.Entities.TV
// Refresh episodes and other children
foreach (var item in items)
{
if ((item is Season))
if (item is Season)
{
continue;
}
@@ -370,8 +368,7 @@ namespace MediaBrowser.Controller.Entities.TV
};
if (user != null)
{
var config = user.Configuration;
if (!config.DisplayMissingEpisodes)
if (!user.DisplayMissingEpisodes)
{
query.IsMissing = false;
}
@@ -452,9 +449,9 @@ namespace MediaBrowser.Controller.Entities.TV
}
protected override bool GetBlockUnratedValue(UserPolicy config)
protected override bool GetBlockUnratedValue(User user)
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);
return user.GetPreference(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Series.ToString());
}
public override UnratedItem GetBlockUnratedType()
@@ -493,7 +490,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
var list = base.GetRelatedUrls();
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
var imdbId = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(imdbId))
{
list.Add(new ExternalUrl

View File

@@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Trailer
/// Class Trailer.
/// </summary>
public class Trailer : Video, IHasLookupInfo<TrailerInfo>
{
@@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Entities
{
var list = base.GetRelatedUrls();
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
var imdbId = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(imdbId))
{
list.Add(new ExternalUrl

View File

@@ -1,262 +0,0 @@
using System;
using System.Globalization;
using System.IO;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class User
/// </summary>
public class User : BaseItem
{
public static IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the password.
/// </summary>
/// <value>The password.</value>
public string Password { get; set; }
public string EasyPassword { get; set; }
// Strictly to remove JsonIgnore
public override ItemImageInfo[] ImageInfos
{
get => base.ImageInfos;
set => base.ImageInfos = value;
}
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
[JsonIgnore]
public override string Path
{
get => ConfigurationDirectoryPath;
set => base.Path = value;
}
private string _name;
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public override string Name
{
get => _name;
set
{
_name = value;
// lazy load this again
SortName = null;
}
}
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
public override string ContainingFolderPath => Path;
/// <summary>
/// Gets the root folder.
/// </summary>
/// <value>The root folder.</value>
[JsonIgnore]
public Folder RootFolder => LibraryManager.GetUserRootFolder();
/// <summary>
/// Gets or sets the last login date.
/// </summary>
/// <value>The last login date.</value>
public DateTime? LastLoginDate { get; set; }
/// <summary>
/// Gets or sets the last activity date.
/// </summary>
/// <value>The last activity date.</value>
public DateTime? LastActivityDate { get; set; }
private volatile UserConfiguration _config;
private readonly object _configSyncLock = new object();
[JsonIgnore]
public UserConfiguration Configuration
{
get
{
if (_config == null)
{
lock (_configSyncLock)
{
if (_config == null)
{
_config = UserManager.GetUserConfiguration(this);
}
}
}
return _config;
}
set => _config = value;
}
private volatile UserPolicy _policy;
private readonly object _policySyncLock = new object();
[JsonIgnore]
public UserPolicy Policy
{
get
{
if (_policy == null)
{
lock (_policySyncLock)
{
if (_policy == null)
{
_policy = UserManager.GetUserPolicy(this);
}
}
}
return _policy;
}
set => _policy = value;
}
/// <summary>
/// Renames the user.
/// </summary>
/// <param name="newName">The new name.</param>
/// <returns>Task.</returns>
/// <exception cref="ArgumentNullException"></exception>
public Task Rename(string newName)
{
if (string.IsNullOrWhiteSpace(newName))
{
throw new ArgumentException("Username can't be empty", nameof(newName));
}
Name = newName;
return RefreshMetadata(
new MetadataRefreshOptions(new DirectoryService(FileSystem))
{
ReplaceAllMetadata = true,
ImageRefreshMode = MetadataRefreshMode.FullRefresh,
MetadataRefreshMode = MetadataRefreshMode.FullRefresh,
ForceSave = true
},
CancellationToken.None);
}
public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken)
{
UserManager.UpdateUser(this);
}
/// <summary>
/// Gets the path to the user's configuration directory
/// </summary>
/// <value>The configuration directory path.</value>
[JsonIgnore]
public string ConfigurationDirectoryPath => GetConfigurationDirectoryPath(Name);
public override double GetDefaultPrimaryImageAspectRatio()
{
return 1;
}
/// <summary>
/// Gets the configuration directory path.
/// </summary>
/// <param name="username">The username.</param>
/// <returns>System.String.</returns>
private string GetConfigurationDirectoryPath(string username)
{
var parentPath = ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath;
// TODO: Remove idPath and just use usernamePath for future releases
var usernamePath = System.IO.Path.Combine(parentPath, username);
var idPath = System.IO.Path.Combine(parentPath, Id.ToString("N", CultureInfo.InvariantCulture));
if (!Directory.Exists(usernamePath) && Directory.Exists(idPath))
{
Directory.Move(idPath, usernamePath);
}
return usernamePath;
}
public bool IsParentalScheduleAllowed()
{
return IsParentalScheduleAllowed(DateTime.UtcNow);
}
public bool IsParentalScheduleAllowed(DateTime date)
{
var schedules = Policy.AccessSchedules;
if (schedules.Length == 0)
{
return true;
}
foreach (var i in schedules)
{
if (IsParentalScheduleAllowed(i, date))
{
return true;
}
}
return false;
}
private bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date)
{
if (date.Kind != DateTimeKind.Utc)
{
throw new ArgumentException("Utc date expected");
}
var localTime = date.ToLocalTime();
return DayOfWeekHelper.GetDaysOfWeek(schedule.DayOfWeek).Contains(localTime.DayOfWeek) &&
IsWithinTime(schedule, localTime);
}
private bool IsWithinTime(AccessSchedule schedule, DateTime localTime)
{
var hour = localTime.TimeOfDay.TotalHours;
return hour >= schedule.StartHour && hour <= schedule.EndHour;
}
public bool IsFolderGrouped(Guid id)
{
foreach (var i in Configuration.GroupedFolders)
{
if (new Guid(i) == id)
{
return true;
}
}
return false;
}
[JsonIgnore]
public override bool SupportsPeople => false;
public long InternalId { get; set; }
}
}

View File

@@ -4,7 +4,7 @@ using System.Text.Json.Serialization;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class UserItemData
/// Class UserItemData.
/// </summary>
public class UserItemData
{
@@ -21,11 +21,11 @@ namespace MediaBrowser.Controller.Entities
public string Key { get; set; }
/// <summary>
/// The _rating
/// The _rating.
/// </summary>
private double? _rating;
/// <summary>
/// Gets or sets the users 0-10 rating
/// Gets or sets the users 0-10 rating.
/// </summary>
/// <value>The rating.</value>
/// <exception cref="ArgumentOutOfRangeException">Rating;A 0 to 10 rating is required for UserItemData.</exception>
@@ -105,6 +105,7 @@ namespace MediaBrowser.Controller.Entities
return null;
}
set
{
if (value.HasValue)

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;

View File

@@ -3,8 +3,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
{
@@ -66,7 +68,7 @@ namespace MediaBrowser.Controller.Entities
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
}
return new UserViewBuilder(UserViewManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager)
return new UserViewBuilder(UserViewManager, LibraryManager, LoggerFactory.CreateLogger<UserViewBuilder>(), UserDataManager, TVSeriesManager, ConfigurationManager)
.GetUserItems(parent, this, CollectionType, query);
}
@@ -110,7 +112,7 @@ namespace MediaBrowser.Controller.Entities
private static string[] UserSpecificViewTypes = new string[]
{
MediaBrowser.Model.Entities.CollectionType.Playlists
Model.Entities.CollectionType.Playlists
};
public static bool IsUserSpecific(Folder folder)
@@ -139,8 +141,8 @@ namespace MediaBrowser.Controller.Entities
private static string[] ViewTypesEligibleForGrouping = new string[]
{
MediaBrowser.Model.Entities.CollectionType.Movies,
MediaBrowser.Model.Entities.CollectionType.TvShows,
Model.Entities.CollectionType.Movies,
Model.Entities.CollectionType.TvShows,
string.Empty
};
@@ -151,12 +153,12 @@ namespace MediaBrowser.Controller.Entities
private static string[] OriginalFolderViewTypes = new string[]
{
MediaBrowser.Model.Entities.CollectionType.Books,
MediaBrowser.Model.Entities.CollectionType.MusicVideos,
MediaBrowser.Model.Entities.CollectionType.HomeVideos,
MediaBrowser.Model.Entities.CollectionType.Photos,
MediaBrowser.Model.Entities.CollectionType.Music,
MediaBrowser.Model.Entities.CollectionType.BoxSets
Model.Entities.CollectionType.Books,
Model.Entities.CollectionType.MusicVideos,
Model.Entities.CollectionType.HomeVideos,
Model.Entities.CollectionType.Photos,
Model.Entities.CollectionType.Music,
Model.Entities.CollectionType.BoxSets
};
public static bool EnableOriginalFolder(string viewType)

View File

@@ -2,14 +2,19 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.TV;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using Microsoft.Extensions.Logging;
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
using MetadataProvider = MediaBrowser.Model.Entities.MetadataProvider;
using Movie = MediaBrowser.Controller.Entities.Movies.Movie;
using Season = MediaBrowser.Controller.Entities.TV.Season;
using Series = MediaBrowser.Controller.Entities.TV.Series;
namespace MediaBrowser.Controller.Entities
{
@@ -17,7 +22,7 @@ namespace MediaBrowser.Controller.Entities
{
private readonly IUserViewManager _userViewManager;
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
private readonly ILogger<UserViewBuilder> _logger;
private readonly IUserDataManager _userDataManager;
private readonly ITVSeriesManager _tvSeriesManager;
private readonly IServerConfigurationManager _config;
@@ -25,7 +30,7 @@ namespace MediaBrowser.Controller.Entities
public UserViewBuilder(
IUserViewManager userViewManager,
ILibraryManager libraryManager,
ILogger logger,
ILogger<UserViewBuilder> logger,
IUserDataManager userDataManager,
ITVSeriesManager tvSeriesManager,
IServerConfigurationManager config)
@@ -42,7 +47,7 @@ namespace MediaBrowser.Controller.Entities
{
var user = query.User;
//if (query.IncludeItemTypes != null &&
// if (query.IncludeItemTypes != null &&
// query.IncludeItemTypes.Length == 1 &&
// string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
//{
@@ -140,14 +145,15 @@ namespace MediaBrowser.Controller.Entities
return parent.QueryRecursive(query);
}
var list = new List<BaseItem>();
list.Add(GetUserView(SpecialFolder.MovieResume, "HeaderContinueWatching", "0", parent));
list.Add(GetUserView(SpecialFolder.MovieLatest, "Latest", "1", parent));
list.Add(GetUserView(SpecialFolder.MovieMovies, "Movies", "2", parent));
list.Add(GetUserView(SpecialFolder.MovieCollections, "Collections", "3", parent));
list.Add(GetUserView(SpecialFolder.MovieFavorites, "Favorites", "4", parent));
list.Add(GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent));
var list = new List<BaseItem>
{
GetUserView(SpecialFolder.MovieResume, "HeaderContinueWatching", "0", parent),
GetUserView(SpecialFolder.MovieLatest, "Latest", "1", parent),
GetUserView(SpecialFolder.MovieMovies, "Movies", "2", parent),
GetUserView(SpecialFolder.MovieCollections, "Collections", "3", parent),
GetUserView(SpecialFolder.MovieFavorites, "Favorites", "4", parent),
GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent)
};
return GetResult(list, parent, query);
}
@@ -264,7 +270,6 @@ namespace MediaBrowser.Controller.Entities
_logger.LogError(ex, "Error getting genre");
return null;
}
})
.Where(i => i != null)
.Select(i => GetUserViewWithName(i.Name, SpecialFolder.MovieGenre, i.SortName, parent));
@@ -293,21 +298,27 @@ namespace MediaBrowser.Controller.Entities
if (query.IncludeItemTypes.Length == 0)
{
query.IncludeItemTypes = new[] { typeof(Series).Name, typeof(Season).Name, typeof(Episode).Name };
query.IncludeItemTypes = new[]
{
nameof(Series),
nameof(Season),
nameof(Episode)
};
}
return parent.QueryRecursive(query);
}
var list = new List<BaseItem>();
list.Add(GetUserView(SpecialFolder.TvResume, "HeaderContinueWatching", "0", parent));
list.Add(GetUserView(SpecialFolder.TvNextUp, "HeaderNextUp", "1", parent));
list.Add(GetUserView(SpecialFolder.TvLatest, "Latest", "2", parent));
list.Add(GetUserView(SpecialFolder.TvShowSeries, "Shows", "3", parent));
list.Add(GetUserView(SpecialFolder.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent));
list.Add(GetUserView(SpecialFolder.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent));
list.Add(GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent));
var list = new List<BaseItem>
{
GetUserView(SpecialFolder.TvResume, "HeaderContinueWatching", "0", parent),
GetUserView(SpecialFolder.TvNextUp, "HeaderNextUp", "1", parent),
GetUserView(SpecialFolder.TvLatest, "Latest", "2", parent),
GetUserView(SpecialFolder.TvShowSeries, "Shows", "3", parent),
GetUserView(SpecialFolder.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent),
GetUserView(SpecialFolder.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent),
GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent)
};
return GetResult(list, parent, query);
}
@@ -335,7 +346,6 @@ namespace MediaBrowser.Controller.Entities
Limit = query.Limit,
StartIndex = query.StartIndex,
UserId = query.User.Id
}, parentFolders, query.DtoOptions);
return result;
@@ -372,7 +382,6 @@ namespace MediaBrowser.Controller.Entities
IncludeItemTypes = new[] { typeof(Series).Name },
Recursive = true,
EnableTotalRecordCount = false
}).Items
.SelectMany(i => i.Genres)
.DistinctNames()
@@ -387,7 +396,6 @@ namespace MediaBrowser.Controller.Entities
_logger.LogError(ex, "Error getting genre");
return null;
}
})
.Where(i => i != null)
.Select(i => GetUserViewWithName(i.Name, SpecialFolder.TvGenre, i.SortName, parent));
@@ -412,12 +420,13 @@ namespace MediaBrowser.Controller.Entities
{
return new QueryResult<BaseItem>
{
Items = result.Items, //TODO Fix The co-variant conversion between T[] and BaseItem[], this can generate runtime issues if T is not BaseItem.
Items = result.Items, // TODO Fix The co-variant conversion between T[] and BaseItem[], this can generate runtime issues if T is not BaseItem.
TotalRecordCount = result.TotalRecordCount
};
}
private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items,
private QueryResult<BaseItem> GetResult<T>(
IEnumerable<T> items,
BaseItem queryParent,
InternalItemsQuery query)
where T : BaseItem
@@ -611,7 +620,7 @@ namespace MediaBrowser.Controller.Entities
{
var filterValue = query.HasImdbId.Value;
var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Imdb));
var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Imdb));
if (hasValue != filterValue)
{
@@ -623,7 +632,7 @@ namespace MediaBrowser.Controller.Entities
{
var filterValue = query.HasTmdbId.Value;
var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tmdb));
var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Tmdb));
if (hasValue != filterValue)
{
@@ -635,7 +644,7 @@ namespace MediaBrowser.Controller.Entities
{
var filterValue = query.HasTvdbId.Value;
var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tvdb));
var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProvider.Tvdb));
if (hasValue != filterValue)
{
@@ -951,6 +960,7 @@ namespace MediaBrowser.Controller.Entities
.OfType<Folder>()
.Where(UserView.IsEligibleForGrouping);
}
return _libraryManager.GetUserRootFolder()
.GetChildren(user, true)
.OfType<Folder>()
@@ -969,6 +979,7 @@ namespace MediaBrowser.Controller.Entities
return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}).ToArray();
}
return GetMediaFolders(user)
.Where(i =>
{

View File

@@ -17,7 +17,7 @@ using MediaBrowser.Model.MediaInfo;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Video
/// Class Video.
/// </summary>
public class Video : BaseItem,
IHasAspectRatio,
@@ -28,7 +28,9 @@ namespace MediaBrowser.Controller.Entities
public string PrimaryVersionId { get; set; }
public string[] AdditionalParts { get; set; }
public string[] LocalAlternateVersions { get; set; }
public LinkedChild[] LinkedAlternateVersions { get; set; }
[JsonIgnore]
@@ -52,15 +54,18 @@ namespace MediaBrowser.Controller.Entities
{
return false;
}
if (extraType.Value == Model.Entities.ExtraType.ThemeVideo)
{
return false;
}
if (extraType.Value == Model.Entities.ExtraType.Trailer)
{
return false;
}
}
return true;
}
}
@@ -196,6 +201,7 @@ namespace MediaBrowser.Controller.Entities
return video.MediaSourceCount;
}
}
return LinkedAlternateVersions.Length + LocalAlternateVersions.Length + 1;
}
}
@@ -272,13 +278,13 @@ namespace MediaBrowser.Controller.Entities
{
if (ExtraType.HasValue)
{
var key = this.GetProviderId(MetadataProviders.Tmdb);
var key = this.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, GetUserDataKey(key));
}
key = this.GetProviderId(MetadataProviders.Imdb);
key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, GetUserDataKey(key));
@@ -286,13 +292,13 @@ namespace MediaBrowser.Controller.Entities
}
else
{
var key = this.GetProviderId(MetadataProviders.Imdb);
var key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
}
key = this.GetProviderId(MetadataProviders.Tmdb);
key = this.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
@@ -390,11 +396,13 @@ namespace MediaBrowser.Controller.Entities
AdditionalParts = newVideo.AdditionalParts;
updateType |= ItemUpdateType.MetadataImport;
}
if (!LocalAlternateVersions.SequenceEqual(newVideo.LocalAlternateVersions, StringComparer.Ordinal))
{
LocalAlternateVersions = newVideo.LocalAlternateVersions;
updateType |= ItemUpdateType.MetadataImport;
}
if (VideoType != newVideo.VideoType)
{
VideoType = newVideo.VideoType;
@@ -416,6 +424,7 @@ namespace MediaBrowser.Controller.Entities
.Select(i => i.FullName)
.ToArray();
}
if (videoType == VideoType.BluRay)
{
return FileSystem.GetFiles(rootPath, new[] { ".m2ts" }, false, true)
@@ -425,6 +434,7 @@ namespace MediaBrowser.Controller.Entities
.Select(i => i.FullName)
.ToArray();
}
return Array.Empty<string>();
}
@@ -535,7 +545,6 @@ namespace MediaBrowser.Controller.Entities
{
ItemId = Id,
Index = DefaultVideoStreamIndex.Value
}).FirstOrDefault();
}

View File

@@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Year
/// Class Year.
/// </summary>
public class Year : BaseItem, IItemByName
{
@@ -21,7 +21,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
@@ -103,11 +103,12 @@ namespace MediaBrowser.Controller.Entities
Logger.LogDebug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath);
return true;
}
return base.RequiresRefresh();
}
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
{

View File

@@ -7,7 +7,7 @@ using System.Text.RegularExpressions;
namespace MediaBrowser.Controller.Extensions
{
/// <summary>
/// Class BaseExtensions
/// Class BaseExtensions.
/// </summary>
public static class StringExtensions
{

View File

@@ -20,6 +20,7 @@ namespace MediaBrowser.Controller.IO
{
dict[file.FullName] = file;
}
return dict;
}
@@ -35,7 +36,8 @@ namespace MediaBrowser.Controller.IO
/// <param name="resolveShortcuts">if set to <c>true</c> [resolve shortcuts].</param>
/// <returns>Dictionary{System.StringFileSystemInfo}.</returns>
/// <exception cref="ArgumentNullException">path</exception>
public static FileSystemMetadata[] GetFilteredFileSystemEntries(IDirectoryService directoryService,
public static FileSystemMetadata[] GetFilteredFileSystemEntries(
IDirectoryService directoryService,
string path,
IFileSystem fileSystem,
IServerApplicationHost appHost,
@@ -48,6 +50,7 @@ namespace MediaBrowser.Controller.IO
{
throw new ArgumentNullException(nameof(path));
}
if (args == null)
{
throw new ArgumentNullException(nameof(args));
@@ -76,7 +79,7 @@ namespace MediaBrowser.Controller.IO
if (string.IsNullOrEmpty(newPath))
{
//invalid shortcut - could be old or target could just be unavailable
// invalid shortcut - could be old or target could just be unavailable
logger.LogWarning("Encountered invalid shortcut: " + fullName);
continue;
}
@@ -115,9 +118,9 @@ namespace MediaBrowser.Controller.IO
returnResult[index] = value;
index++;
}
return returnResult;
}
}
}

View File

@@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Http;
namespace MediaBrowser.Controller
{
/// <summary>
/// Interface IServerApplicationHost
/// Interface IServerApplicationHost.
/// </summary>
public interface IServerApplicationHost : IApplicationHost
{

View File

@@ -5,7 +5,7 @@ namespace MediaBrowser.Controller
public interface IServerApplicationPaths : IApplicationPaths
{
/// <summary>
/// Gets the path to the base root media directory
/// Gets the path to the base root media directory.
/// </summary>
/// <value>The root folder path.</value>
string RootFolderPath { get; }
@@ -17,13 +17,13 @@ namespace MediaBrowser.Controller
string DefaultUserViewsPath { get; }
/// <summary>
/// Gets the path to the People directory
/// Gets the path to the People directory.
/// </summary>
/// <value>The people path.</value>
string PeoplePath { get; }
/// <summary>
/// Gets the path to the Genre directory
/// Gets the path to the Genre directory.
/// </summary>
/// <value>The genre path.</value>
string GenrePath { get; }
@@ -35,25 +35,25 @@ namespace MediaBrowser.Controller
string MusicGenrePath { get; }
/// <summary>
/// Gets the path to the Studio directory
/// Gets the path to the Studio directory.
/// </summary>
/// <value>The studio path.</value>
string StudioPath { get; }
/// <summary>
/// Gets the path to the Year directory
/// Gets the path to the Year directory.
/// </summary>
/// <value>The year path.</value>
string YearPath { get; }
/// <summary>
/// Gets the path to the General IBN directory
/// Gets the path to the General IBN directory.
/// </summary>
/// <value>The general path.</value>
string GeneralPath { get; }
/// <summary>
/// Gets the path to the Ratings IBN directory
/// Gets the path to the Ratings IBN directory.
/// </summary>
/// <value>The ratings path.</value>
string RatingsPath { get; }
@@ -65,7 +65,7 @@ namespace MediaBrowser.Controller
string MediaInfoImagesPath { get; }
/// <summary>
/// Gets the path to the user configuration directory
/// Gets the path to the user configuration directory.
/// </summary>
/// <value>The user configuration directory path.</value>
string UserConfigurationDirectoryPath { get; }

View File

@@ -3,6 +3,7 @@ namespace MediaBrowser.Controller.Library
public class DeleteOptions
{
public bool DeleteFileLocation { get; set; }
public bool DeleteFromExternalProvider { get; set; }
public DeleteOptions()

View File

@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class BaseIntroProvider
/// Class BaseIntroProvider.
/// </summary>
public interface IIntroProvider
{
@@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Library
/// <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);
Task<IEnumerable<IntroInfo>> GetIntros(BaseItem item, Jellyfin.Data.Entities.User user);
/// <summary>
/// Gets all intro files.

View File

@@ -2,10 +2,10 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Controller.Sorting;
@@ -14,11 +14,14 @@ 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
/// Interface ILibraryManager.
/// </summary>
public interface ILibraryManager
{
@@ -35,7 +38,7 @@ namespace MediaBrowser.Controller.Library
bool allowIgnorePath = true);
/// <summary>
/// Resolves a set of files into a list of BaseItem
/// Resolves a set of files into a list of BaseItem.
/// </summary>
IEnumerable<BaseItem> ResolvePaths(
IEnumerable<FileSystemMetadata> files,
@@ -51,7 +54,7 @@ namespace MediaBrowser.Controller.Library
AggregateFolder RootFolder { get; }
/// <summary>
/// Gets a Person
/// Gets a Person.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>Task{Person}.</returns>
@@ -72,14 +75,14 @@ namespace MediaBrowser.Controller.Library
MusicArtist GetArtist(string name);
MusicArtist GetArtist(string name, DtoOptions options);
/// <summary>
/// Gets a Studio
/// Gets a Studio.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>Task{Studio}.</returns>
Studio GetStudio(string name);
/// <summary>
/// Gets a Genre
/// Gets a Genre.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>Task{Genre}.</returns>
@@ -93,7 +96,7 @@ namespace MediaBrowser.Controller.Library
MusicGenre GetMusicGenre(string name);
/// <summary>
/// Gets a Year
/// Gets a Year.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>Task{Year}.</returns>
@@ -110,7 +113,7 @@ namespace MediaBrowser.Controller.Library
Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress);
/// <summary>
/// Reloads the root media folder
/// Reloads the root media folder.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
@@ -289,7 +292,8 @@ namespace MediaBrowser.Controller.Library
/// <param name="parentId">The parent identifier.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
UserView GetNamedView(User user,
UserView GetNamedView(
User user,
string name,
Guid parentId,
string viewType,
@@ -302,7 +306,8 @@ namespace MediaBrowser.Controller.Library
/// <param name="name">The name.</param>
/// <param name="viewType">Type of the view.</param>
/// <param name="sortName">Name of the sort.</param>
UserView GetNamedView(User user,
UserView GetNamedView(
User user,
string name,
string viewType,
string sortName);

View File

@@ -5,7 +5,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// An interface for tasks that run after the media library scan
/// An interface for tasks that run after the media library scan.
/// </summary>
public interface ILibraryPostScanTask
{

View File

@@ -9,10 +9,15 @@ namespace MediaBrowser.Controller.Library
Task Open(CancellationToken openCancellationToken);
Task Close();
int ConsumerCount { get; set; }
string OriginalStreamId { get; set; }
string TunerHostId { get; }
bool EnableStreamSharing { get; }
MediaSourceInfo MediaSource { get; set; }
string UniqueId { get; }
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Model.Dto;

View File

@@ -4,7 +4,7 @@ using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface IMetadataSaver
/// Interface IMetadataSaver.
/// </summary>
public interface IMetadataSaver
{

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;

View File

@@ -4,7 +4,7 @@ using MediaBrowser.Model.Search;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface ILibrarySearchEngine
/// Interface ILibrarySearchEngine.
/// </summary>
public interface ISearchEngine
{

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
@@ -27,7 +28,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="reason">The reason.</param>
/// <param name="cancellationToken">The cancellation token.</param>
void SaveUserData(Guid userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
void SaveUserData(User userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
void SaveUserData(User user, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
UserItemData GetUserData(User user, BaseItem item);
@@ -41,14 +42,14 @@ namespace MediaBrowser.Controller.Library
UserItemDataDto GetUserDataDto(BaseItem item, BaseItemDto itemDto, User user, DtoOptions dto_options);
/// <summary>
/// Get all user data for the given user
/// Get all user data for the given user.
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
List<UserItemData> GetAllUserData(Guid userId);
/// <summary>
/// Save the all provided user data for the given user
/// Save the all provided user data for the given user.
/// </summary>
/// <param name="userId"></param>
/// <param name="userData"></param>
@@ -57,7 +58,7 @@ namespace MediaBrowser.Controller.Library
void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken);
/// <summary>
/// Updates playstate for an item and returns true or false indicating if it was played to completion
/// Updates playstate for an item and returns true or false indicating if it was played to completion.
/// </summary>
bool UpdatePlayState(BaseItem item, UserItemData data, long? positionTicks);
}

View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Events;
@@ -12,10 +11,35 @@ using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Interface IUserManager
/// Interface IUserManager.
/// </summary>
public interface IUserManager
{
/// <summary>
/// Occurs when a user is updated.
/// </summary>
event EventHandler<GenericEventArgs<User>> OnUserUpdated;
/// <summary>
/// Occurs when a user is created.
/// </summary>
event EventHandler<GenericEventArgs<User>> OnUserCreated;
/// <summary>
/// Occurs when a user is deleted.
/// </summary>
event EventHandler<GenericEventArgs<User>> OnUserDeleted;
/// <summary>
/// Occurs when a user's password is changed.
/// </summary>
event EventHandler<GenericEventArgs<User>> OnUserPasswordChanged;
/// <summary>
/// Occurs when a user is locked out.
/// </summary>
event EventHandler<GenericEventArgs<User>> OnUserLockedOut;
/// <summary>
/// Gets the users.
/// </summary>
@@ -29,24 +53,9 @@ namespace MediaBrowser.Controller.Library
IEnumerable<Guid> UsersIds { get; }
/// <summary>
/// Occurs when [user updated].
/// Initializes the user manager and ensures that a user exists.
/// </summary>
event EventHandler<GenericEventArgs<User>> UserUpdated;
/// <summary>
/// Occurs when [user deleted].
/// </summary>
event EventHandler<GenericEventArgs<User>> UserDeleted;
event EventHandler<GenericEventArgs<User>> UserCreated;
event EventHandler<GenericEventArgs<User>> UserPolicyUpdated;
event EventHandler<GenericEventArgs<User>> UserConfigurationUpdated;
event EventHandler<GenericEventArgs<User>> UserPasswordChanged;
event EventHandler<GenericEventArgs<User>> UserLockedOut;
void Initialize();
/// <summary>
/// Gets a user by Id.
@@ -63,13 +72,6 @@ namespace MediaBrowser.Controller.Library
/// <returns>User.</returns>
User GetUserByName(string name);
/// <summary>
/// Refreshes metadata for each user
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task RefreshUsersMetadata(CancellationToken cancellationToken);
/// <summary>
/// Renames the user.
/// </summary>
@@ -89,19 +91,27 @@ namespace MediaBrowser.Controller.Library
void UpdateUser(User user);
/// <summary>
/// Creates the user.
/// Updates the user.
/// </summary>
/// <param name="name">The name.</param>
/// <returns>User.</returns>
/// <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">name</exception>
/// <exception cref="ArgumentException"></exception>
User CreateUser(string name);
/// <summary>
/// Deletes the user.
/// Deletes the specified user.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
/// <param name="user">The user to be deleted.</param>
void DeleteUser(User user);
/// <summary>
@@ -111,13 +121,6 @@ namespace MediaBrowser.Controller.Library
/// <returns>Task.</returns>
Task ResetPassword(User user);
/// <summary>
/// Gets the offline user dto.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>UserDto.</returns>
UserDto GetOfflineUserDto(User user);
/// <summary>
/// Resets the easy password.
/// </summary>
@@ -163,47 +166,34 @@ namespace MediaBrowser.Controller.Library
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
Task<PinRedeemResult> RedeemPasswordResetPin(string pin);
/// <summary>
/// Gets the user policy.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>UserPolicy.</returns>
UserPolicy GetUserPolicy(User user);
/// <summary>
/// Gets the user configuration.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>UserConfiguration.</returns>
UserConfiguration GetUserConfiguration(User user);
/// <summary>
/// Updates the configuration.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <param name="newConfiguration">The new configuration.</param>
/// <returns>Task.</returns>
void UpdateConfiguration(Guid userId, UserConfiguration newConfiguration);
void UpdateConfiguration(User user, UserConfiguration newConfiguration);
/// <summary>
/// Updates the user policy.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <param name="userPolicy">The user policy.</param>
void UpdateUserPolicy(Guid userId, UserPolicy userPolicy);
/// <summary>
/// Makes the valid username.
/// </summary>
/// <param name="username">The username.</param>
/// <returns>System.String.</returns>
string MakeValidUsername(string username);
void AddParts(IEnumerable<IAuthenticationProvider> authenticationProviders, IEnumerable<IPasswordResetProvider> passwordResetProviders);
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="UpdateUser"/>.
/// </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);
/// <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="UpdateUser"/>.
/// </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);
/// <summary>
/// Clears the user's profile image.
/// </summary>
/// <param name="user">The user.</param>
void ClearProfileImage(User user);
}
}

View File

@@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class ItemChangeEventArgs
/// Class ItemChangeEventArgs.
/// </summary>
public class ItemChangeEventArgs
{

View File

@@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Library
public class ItemResolveArgs : EventArgs
{
/// <summary>
/// The _app paths
/// The _app paths.
/// </summary>
private readonly IServerApplicationPaths _appPaths;
@@ -89,7 +89,6 @@ namespace MediaBrowser.Controller.Library
return parentDir.Length > _appPaths.RootFolderPath.Length
&& parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase);
}
}
@@ -129,8 +128,8 @@ namespace MediaBrowser.Controller.Library
}
return item != null;
}
return false;
}
@@ -258,6 +257,7 @@ namespace MediaBrowser.Controller.Library
if (args.Path == null && Path == null) return true;
return args.Path != null && BaseItem.FileSystem.AreEqual(args.Path, Path);
}
return false;
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Dto;
@@ -7,23 +8,32 @@ using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Holds information about a playback progress event
/// Holds information about a playback progress event.
/// </summary>
public class PlaybackProgressEventArgs : EventArgs
{
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; }
public PlaybackProgressEventArgs()

View File

@@ -5,23 +5,23 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class Profiler
/// Class Profiler.
/// </summary>
public class Profiler : IDisposable
{
/// <summary>
/// The name
/// The name.
/// </summary>
readonly string _name;
/// <summary>
/// The stopwatch
/// The stopwatch.
/// </summary>
readonly Stopwatch _stopwatch;
/// <summary>
/// The _logger
/// The _logger.
/// </summary>
private readonly ILogger _logger;
private readonly ILogger<Profiler> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="Profiler" /> class.
@@ -67,6 +67,7 @@ namespace MediaBrowser.Controller.Library
message = string.Format("{0} took {1} seconds.",
_name, ((float)_stopwatch.ElapsedMilliseconds / 1000).ToString("#0.000"));
}
_logger.LogInformation(message);
}
}

View File

@@ -3,7 +3,7 @@ using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class SearchHintInfo
/// Class SearchHintInfo.
/// </summary>
public class SearchHintInfo
{

View File

@@ -3,7 +3,7 @@ using System;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class TVUtils
/// Class TVUtils.
/// </summary>
public static class TVUtils
{
@@ -40,6 +40,7 @@ namespace MediaBrowser.Controller.Library
return new DayOfWeek[] { };
}
return null;
}
}

View File

@@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Library
{
/// <summary>
/// Class UserDataSaveEventArgs
/// Class UserDataSaveEventArgs.
/// </summary>
public class UserDataSaveEventArgs : EventArgs
{

View File

@@ -3,7 +3,7 @@ using MediaBrowser.Model.LiveTv;
namespace MediaBrowser.Controller.LiveTv
{
/// <summary>
/// Class ChannelInfo
/// Class ChannelInfo.
/// </summary>
public class ChannelInfo
{
@@ -44,13 +44,13 @@ namespace MediaBrowser.Controller.LiveTv
public ChannelType ChannelType { get; set; }
/// <summary>
/// Supply the image path if it can be accessed directly from the file system
/// Supply the image path if it can be accessed directly from the file system.
/// </summary>
/// <value>The image path.</value>
public string ImagePath { get; set; }
/// <summary>
/// Supply the image url if it can be downloaded
/// Supply the image url if it can be downloaded.
/// </summary>
/// <value>The image URL.</value>
public string ImageUrl { get; set; }
@@ -67,8 +67,11 @@ namespace MediaBrowser.Controller.LiveTv
public bool? IsFavorite { get; set; }
public bool? IsHD { get; set; }
public string AudioCodec { get; set; }
public string VideoCodec { get; set; }
public string[] Tags { get; set; }
}
}

View File

@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@@ -13,7 +14,7 @@ using MediaBrowser.Model.Querying;
namespace MediaBrowser.Controller.LiveTv
{
/// <summary>
/// Manages all live tv services installed on the server
/// Manages all live tv services installed on the server.
/// </summary>
public interface ILiveTvManager
{
@@ -285,8 +286,11 @@ namespace MediaBrowser.Controller.LiveTv
public class ActiveRecordingInfo
{
public string Id { get; set; }
public string Path { get; set; }
public TimerInfo Timer { get; set; }
public CancellationTokenSource CancellationTokenSource { get; set; }
}
}

View File

@@ -50,6 +50,7 @@ namespace MediaBrowser.Controller.LiveTv
get;
}
}
public interface IConfigurableTunerHost
{
/// <summary>

View File

@@ -3,8 +3,8 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;

View File

@@ -9,12 +9,11 @@ namespace MediaBrowser.Controller.LiveTv
{
public LiveTvConflictException()
{
}
public LiveTvConflictException(string message)
: base(message)
{
}
}
}

View File

@@ -3,10 +3,10 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Providers;
@@ -26,13 +26,13 @@ namespace MediaBrowser.Controller.LiveTv
if (!IsSeries)
{
var key = this.GetProviderId(MetadataProviders.Imdb);
var key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
}
key = this.GetProviderId(MetadataProviders.Tmdb);
key = this.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
@@ -140,14 +140,14 @@ namespace MediaBrowser.Controller.LiveTv
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
/// If the item is a folder, it returns the folder itself.
/// </summary>
/// <value>The containing folder path.</value>
[JsonIgnore]
public override string ContainingFolderPath => Path;
//[JsonIgnore]
//public override string MediaType
// public override string MediaType
//{
// get
// {
@@ -253,7 +253,7 @@ namespace MediaBrowser.Controller.LiveTv
{
var list = base.GetRelatedUrls();
var imdbId = this.GetProviderId(MetadataProviders.Imdb);
var imdbId = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(imdbId))
{
if (IsMovie)

View File

@@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.LiveTv
public string ChannelId { get; set; }
/// <summary>
/// Name of the program
/// Name of the program.
/// </summary>
public string Name { get; set; }
@@ -95,13 +95,13 @@ namespace MediaBrowser.Controller.LiveTv
public string EpisodeTitle { get; set; }
/// <summary>
/// Supply the image path if it can be accessed directly from the file system
/// Supply the image path if it can be accessed directly from the file system.
/// </summary>
/// <value>The image path.</value>
public string ImagePath { get; set; }
/// <summary>
/// Supply the image url if it can be downloaded
/// Supply the image url if it can be downloaded.
/// </summary>
/// <value>The image URL.</value>
public string ImageUrl { get; set; }
@@ -199,6 +199,7 @@ namespace MediaBrowser.Controller.LiveTv
public string Etag { get; set; }
public Dictionary<string, string> ProviderIds { get; set; }
public Dictionary<string, string> SeriesProviderIds { get; set; }
public ProgramInfo()

View File

@@ -169,13 +169,13 @@ namespace MediaBrowser.Controller.LiveTv
public float? CommunityRating { get; set; }
/// <summary>
/// Supply the image path if it can be accessed directly from the file system
/// Supply the image path if it can be accessed directly from the file system.
/// </summary>
/// <value>The image path.</value>
public string ImagePath { get; set; }
/// <summary>
/// Supply the image url if it can be downloaded
/// Supply the image url if it can be downloaded.
/// </summary>
/// <value>The image URL.</value>
public string ImageUrl { get; set; }

View File

@@ -57,6 +57,7 @@ namespace MediaBrowser.Controller.LiveTv
public bool RecordAnyChannel { get; set; }
public int KeepUpTo { get; set; }
public KeepUntil KeepUntil { get; set; }
public bool SkipEpisodesInLibrary { get; set; }

View File

@@ -18,7 +18,9 @@ namespace MediaBrowser.Controller.LiveTv
}
public Dictionary<string, string> ProviderIds { get; set; }
public Dictionary<string, string> SeriesProviderIds { get; set; }
public string[] Tags { get; set; }
/// <summary>
@@ -146,10 +148,15 @@ namespace MediaBrowser.Controller.LiveTv
public bool IsRepeat { get; set; }
public string HomePageUrl { get; set; }
public float? CommunityRating { get; set; }
public string OfficialRating { get; set; }
public string[] Genres { get; set; }
public string RecordingPath { get; set; }
public KeepUntil KeepUntil { get; set; }
}
}

View File

@@ -3,8 +3,11 @@ namespace MediaBrowser.Controller.LiveTv
public class TunerChannelMapping
{
public string Name { get; set; }
public string ProviderChannelName { get; set; }
public string ProviderChannelId { get; set; }
public string Id { get; set; }
}
}

View File

@@ -13,8 +13,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="3.1.5" />
</ItemGroup>
<ItemGroup>

View File

@@ -5,6 +5,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Extensions;
using MediaBrowser.Model.Configuration;
@@ -73,7 +74,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{"omx", hwEncoder + "_omx"},
{hwEncoder + "_v4l2m2m", hwEncoder + "_v4l2m2m"},
{"mediacodec", hwEncoder + "_mediacodec"},
{"vaapi", hwEncoder + "_vaapi"}
{"vaapi", hwEncoder + "_vaapi"},
{"videotoolbox", hwEncoder + "_videotoolbox"}
};
if (!string.IsNullOrEmpty(hwType)
@@ -103,11 +105,12 @@ namespace MediaBrowser.Controller.MediaEncoding
return false;
}
return true;
return _mediaEncoder.SupportsHwaccel("vaapi");
}
/// <summary>
/// Gets the name of the output video codec
/// Gets the name of the output video codec.
/// </summary>
public string GetVideoEncoder(EncodingJobInfo state, EncodingOptions encodingOptions)
{
@@ -284,7 +287,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Infers the audio codec based on the url
/// Infers the audio codec based on the url.
/// </summary>
public string InferAudioCodec(string container)
{
@@ -444,31 +447,41 @@ namespace MediaBrowser.Controller.MediaEncoding
public string GetInputArgument(EncodingJobInfo state, EncodingOptions encodingOptions)
{
var arg = new StringBuilder();
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions) ?? string.Empty;
var outputVideoCodec = GetVideoEncoder(state, encodingOptions) ?? string.Empty;
bool isVaapiDecoder = videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
bool isVaapiEncoder = outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1;
bool isQsvDecoder = videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
bool isQsvEncoder = outputVideoCodec.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1;
if (state.IsVideoRequest
&& string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
{
arg.Append("-hwaccel vaapi -hwaccel_output_format vaapi")
.Append(" -vaapi_device ")
.Append(encodingOptions.VaapiDevice)
.Append(' ');
if (isVaapiDecoder)
{
arg.Append("-hwaccel_output_format vaapi ")
.Append("-vaapi_device ")
.Append(encodingOptions.VaapiDevice)
.Append(" ");
}
else if (!isVaapiDecoder && isVaapiEncoder)
{
arg.Append("-vaapi_device ")
.Append(encodingOptions.VaapiDevice)
.Append(" ");
}
}
if (state.IsVideoRequest
&& string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions);
var outputVideoCodec = GetVideoEncoder(state, encodingOptions);
var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
if (!hasTextSubs)
{
// While using QSV encoder
if ((outputVideoCodec ?? string.Empty).IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1)
if (isQsvEncoder)
{
// While using QSV decoder
if ((videoDecoder ?? string.Empty).IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1)
if (isQsvDecoder)
{
arg.Append("-hwaccel qsv ");
}
@@ -526,6 +539,8 @@ namespace MediaBrowser.Controller.MediaEncoding
|| codec.IndexOf("hevc", StringComparison.OrdinalIgnoreCase) != -1;
}
// TODO This is auto inserted into the mpegts mux so it might not be needed
// https://www.ffmpeg.org/ffmpeg-bitstream-filters.html#h264_005fmp4toannexb
public string GetBitStreamArgs(MediaStream stream)
{
if (IsH264(stream))
@@ -550,8 +565,8 @@ namespace MediaBrowser.Controller.MediaEncoding
{
if (string.Equals(videoCodec, "libvpx", StringComparison.OrdinalIgnoreCase))
{
// With vpx when crf is used, b:v becomes a max rate
// https://trac.ffmpeg.org/wiki/vpxEncodingGuide.
// When crf is used with vpx, b:v becomes a max rate
// https://trac.ffmpeg.org/wiki/Encode/VP9
return string.Format(
CultureInfo.InvariantCulture,
" -maxrate:v {0} -bufsize:v {1} -b:v {0}",
@@ -702,7 +717,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Gets the video bitrate to specify on the command line
/// Gets the video bitrate to specify on the command line.
/// </summary>
public string GetVideoQualityParam(EncodingJobInfo state, string videoEncoder, EncodingOptions encodingOptions, string defaultPreset)
{
@@ -758,7 +773,6 @@ namespace MediaBrowser.Controller.MediaEncoding
}
param += " -look_ahead 0";
}
else if (string.Equals(videoEncoder, "h264_nvenc", StringComparison.OrdinalIgnoreCase) // h264 (h264_nvenc)
|| string.Equals(videoEncoder, "hevc_nvenc", StringComparison.OrdinalIgnoreCase))
@@ -767,7 +781,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
case "veryslow":
param += "-preset slow"; //lossless is only supported on maxwell and newer(2014+)
param += "-preset slow"; // lossless is only supported on maxwell and newer(2014+)
break;
case "slow":
@@ -998,7 +1012,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
if (string.IsNullOrEmpty(videoStream.Profile))
{
//return false;
// return false;
}
var requestedProfile = requestedProfiles[0];
@@ -1071,7 +1085,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
if (!videoStream.Level.HasValue)
{
//return false;
// return false;
}
if (videoStream.Level.HasValue && videoStream.Level.Value > requestLevel)
@@ -1300,7 +1314,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Gets the number of audio channels to specify on the command line
/// Gets the number of audio channels to specify on the command line.
/// </summary>
/// <param name="state">The state.</param>
/// <param name="audioStream">The audio stream.</param>
@@ -1326,7 +1340,6 @@ namespace MediaBrowser.Controller.MediaEncoding
// wmav2 currently only supports two channel output
transcoderChannelLimit = 2;
}
else if (codec.IndexOf("mp3", StringComparison.OrdinalIgnoreCase) != -1)
{
// libmp3lame currently only supports two channel output
@@ -1461,7 +1474,6 @@ namespace MediaBrowser.Controller.MediaEncoding
" -map 0:{0}",
state.AudioStream.Index);
}
else
{
args += " -map -0:a";
@@ -1488,7 +1500,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Determines which stream will be used for playback
/// Determines which stream will be used for playback.
/// </summary>
/// <param name="allStream">All stream.</param>
/// <param name="desiredIndex">Index of the desired.</param>
@@ -1527,8 +1539,9 @@ namespace MediaBrowser.Controller.MediaEncoding
EncodingOptions options,
string outputVideoCodec)
{
var outputSizeParam = string.Empty;
outputVideoCodec ??= string.Empty;
var outputSizeParam = string.Empty;
var request = state.BaseRequest;
// Add resolution params, if specified
@@ -1571,16 +1584,14 @@ namespace MediaBrowser.Controller.MediaEncoding
}
var videoSizeParam = string.Empty;
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options);
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty;
// Setup subtitle scaling
if (state.VideoStream != null && state.VideoStream.Width.HasValue && state.VideoStream.Height.HasValue)
{
// force_original_aspect_ratio=decrease
// Enable decreasing output video width or height if necessary to keep the original aspect ratio
videoSizeParam = string.Format(
CultureInfo.InvariantCulture,
"scale={0}:{1}:force_original_aspect_ratio=decrease",
"scale={0}:{1}",
state.VideoStream.Width.Value,
state.VideoStream.Height.Value);
@@ -1593,8 +1604,10 @@ namespace MediaBrowser.Controller.MediaEncoding
// For VAAPI and CUVID decoder
// these encoders cannot automatically adjust the size of graphical subtitles to fit the output video,
// thus needs to be manually adjusted.
if ((IsVaapiSupported(state) && string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
|| (videoDecoder ?? string.Empty).IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1)
if (videoDecoder.IndexOf("cuvid", StringComparison.OrdinalIgnoreCase) != -1
|| (IsVaapiSupported(state) && string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)
&& (videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1
|| outputVideoCodec.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1)))
{
var videoStream = state.VideoStream;
var inputWidth = videoStream?.Width;
@@ -1605,7 +1618,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
videoSizeParam = string.Format(
CultureInfo.InvariantCulture,
"scale={0}:{1}:force_original_aspect_ratio=decrease",
"scale={0}:{1}",
width.Value,
height.Value);
}
@@ -1636,7 +1649,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
else if (IsVaapiSupported(state) && string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)
else if (IsVaapiSupported(state) && videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1
&& string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
{
/*
@@ -1647,7 +1660,6 @@ namespace MediaBrowser.Controller.MediaEncoding
outputSizeParam = outputSizeParam.TrimStart(',');
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}]{3}[base];[base][sub]overlay\"";
}
else if (string.Equals(outputVideoCodec, "h264_qsv", StringComparison.OrdinalIgnoreCase))
{
/*
@@ -1655,7 +1667,7 @@ namespace MediaBrowser.Controller.MediaEncoding
For software decoding and hardware encoding option, frames must be hwuploaded into hardware
with fixed frame size.
*/
if (!string.IsNullOrEmpty(videoDecoder) && videoDecoder.Contains("qsv", StringComparison.OrdinalIgnoreCase))
if (videoDecoder.IndexOf("qsv", StringComparison.OrdinalIgnoreCase) != -1)
{
retStr = " -filter_complex \"[{0}:{1}]{4}[sub];[0:{2}][sub]overlay_qsv=x=(W-w)/2:y=(H-h)/2{3}\"";
}
@@ -1687,6 +1699,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return (null, null);
}
if (!videoHeight.HasValue && !requestedHeight.HasValue)
{
return (null, null);
@@ -1932,11 +1945,11 @@ namespace MediaBrowser.Controller.MediaEncoding
break;
case Video3DFormat.FullSideBySide:
filter = "crop=iw/2:ih:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
//fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to requestedWidth.
// fsbs crop width in half,set the display aspect,crop out any black bars we may have made the scale width to requestedWidth.
break;
case Video3DFormat.HalfTopAndBottom:
filter = "crop=iw:ih/2:0:0,scale=(iw*2):ih),setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
//htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth
// htab crop height in half,scale to correct size, set the display aspect,crop out any black bars we may have made the scale width to requestedWidth
break;
case Video3DFormat.FullTopAndBottom:
filter = "crop=iw:ih/2:0:0,setdar=dar=a,crop=min(iw\\,ih*dar):min(ih\\,iw/dar):(iw-min(iw\\,iw*sar))/2:(ih - min (ih\\,ih/sar))/2,setsar=sar=1,scale={0}:trunc({0}/dar/2)*2";
@@ -1964,7 +1977,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// If we're going to put a fixed size on the command line, this will calculate it
/// If we're going to put a fixed size on the command line, this will calculate it.
/// </summary>
public string GetOutputSizeParam(
EncodingJobInfo state,
@@ -1978,7 +1991,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var videoStream = state.VideoStream;
var filters = new List<string>();
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options);
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, options) ?? string.Empty;
var inputWidth = videoStream?.Width;
var inputHeight = videoStream?.Height;
var threeDFormat = state.MediaSource.Video3DFormat;
@@ -2003,7 +2016,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
// If we're hardware VAAPI decoding and software encoding, download frames from the decoder first
else if (IsVaapiSupported(state) && string.Equals(options.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase)
else if (videoDecoder.IndexOf("vaapi", StringComparison.OrdinalIgnoreCase) != -1
&& string.Equals(outputVideoCodec, "libx264", StringComparison.OrdinalIgnoreCase))
{
var codec = videoStream.Codec.ToLowerInvariant();
@@ -2148,7 +2161,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var user = state.User;
// If the user doesn't have access to transcoding, then force stream copy, regardless of whether it will be compatible or not
if (user != null && !user.Policy.EnableVideoPlaybackTranscoding)
if (user != null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding))
{
state.OutputVideoCodec = "copy";
}
@@ -2164,7 +2177,7 @@ namespace MediaBrowser.Controller.MediaEncoding
var user = state.User;
// If the user doesn't have access to transcoding, then force stream copy, regardless of whether it will be compatible or not
if (user != null && !user.Policy.EnableAudioPlaybackTranscoding)
if (user != null && !user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding))
{
state.OutputAudioCodec = "copy";
}
@@ -2508,20 +2521,21 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Gets the name of the output video codec
/// Gets the name of the output video codec.
/// </summary>
protected string GetHardwareAcceleratedVideoDecoder(EncodingJobInfo state, EncodingOptions encodingOptions)
{
var videoType = state.MediaSource.VideoType ?? VideoType.VideoFile;
var videoStream = state.VideoStream;
var isColorDepth10 = !string.IsNullOrEmpty(videoStream.Profile) && (videoStream.Profile.Contains("Main 10", StringComparison.OrdinalIgnoreCase)
|| videoStream.Profile.Contains("High 10", StringComparison.OrdinalIgnoreCase));
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec))
{
return null;
}
return GetHardwareAcceleratedVideoDecoder(state.MediaSource.VideoType ?? VideoType.VideoFile, state.VideoStream, encodingOptions);
}
public string GetHardwareAcceleratedVideoDecoder(VideoType videoType, MediaStream videoStream, EncodingOptions encodingOptions)
{
// Only use alternative encoders for video files.
// When using concat with folder rips, if the mfx session fails to initialize, ffmpeg will be stuck retrying and will not exit gracefully
// Since transcoding of folder rips is expiremental anyway, it's not worth adding additional variables such as this.
@@ -2534,6 +2548,14 @@ namespace MediaBrowser.Controller.MediaEncoding
&& !string.IsNullOrEmpty(videoStream.Codec)
&& !string.IsNullOrEmpty(encodingOptions.HardwareAccelerationType))
{
// Only hevc and vp9 formats have 10-bit hardware decoder support now.
if (isColorDepth10 && !(string.Equals(videoStream.Codec, "hevc", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.Codec, "h265", StringComparison.OrdinalIgnoreCase)
|| string.Equals(videoStream.Codec, "vp9", StringComparison.OrdinalIgnoreCase)))
{
return null;
}
if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase))
{
switch (videoStream.Codec.ToLowerInvariant())
@@ -2548,32 +2570,49 @@ namespace MediaBrowser.Controller.MediaEncoding
encodingOptions.HardwareDecodingCodecs = Array.Empty<string>();
return null;
}
return "-c:v h264_qsv";
}
break;
case "hevc":
case "h265":
if (_mediaEncoder.SupportsDecoder("hevc_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase))
{
//return "-c:v hevc_qsv -load_plugin hevc_hw ";
return "-c:v hevc_qsv";
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_qsv";
}
break;
case "mpeg2video":
if (_mediaEncoder.SupportsDecoder("mpeg2_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg2_qsv";
}
break;
case "vc1":
if (_mediaEncoder.SupportsDecoder("vc1_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vc1_qsv";
}
break;
case "vp8":
if (_mediaEncoder.SupportsDecoder("vp8_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vp8_qsv";
}
break;
case "vp9":
if (_mediaEncoder.SupportsDecoder("vp9_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase))
{
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_qsv";
}
break;
}
}
else if (string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase))
{
switch (videoStream.Codec.ToLowerInvariant())
@@ -2582,43 +2621,62 @@ namespace MediaBrowser.Controller.MediaEncoding
case "h264":
if (_mediaEncoder.SupportsDecoder("h264_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
{
// cuvid decoder does not support 10-bit input
// cuvid decoder does not support 10-bit input.
if ((videoStream.BitDepth ?? 8) > 8)
{
encodingOptions.HardwareDecodingCodecs = Array.Empty<string>();
return null;
}
return "-c:v h264_cuvid";
}
break;
case "hevc":
case "h265":
if (_mediaEncoder.SupportsDecoder("hevc_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase))
{
return "-c:v hevc_cuvid";
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_cuvid";
}
break;
case "mpeg2video":
if (_mediaEncoder.SupportsDecoder("mpeg2_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg2_cuvid";
}
break;
case "vc1":
if (_mediaEncoder.SupportsDecoder("vc1_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vc1_cuvid";
}
break;
case "mpeg4":
if (_mediaEncoder.SupportsDecoder("mpeg4_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg4_cuvid";
}
break;
case "vp8":
if (_mediaEncoder.SupportsDecoder("vp8_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vp8_cuvid";
}
break;
case "vp9":
if (_mediaEncoder.SupportsDecoder("vp9_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase))
{
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_cuvid";
}
break;
}
}
else if (string.Equals(encodingOptions.HardwareAccelerationType, "mediacodec", StringComparison.OrdinalIgnoreCase))
{
switch (videoStream.Codec.ToLowerInvariant())
@@ -2629,41 +2687,48 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return "-c:v h264_mediacodec";
}
break;
case "hevc":
case "h265":
if (_mediaEncoder.SupportsDecoder("hevc_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase))
{
return "-c:v hevc_mediacodec";
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_mediacodec";
}
break;
case "mpeg2video":
if (_mediaEncoder.SupportsDecoder("mpeg2_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg2_mediacodec";
}
break;
case "mpeg4":
if (_mediaEncoder.SupportsDecoder("mpeg4_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg4_mediacodec";
}
break;
case "vp8":
if (_mediaEncoder.SupportsDecoder("vp8_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("vp8", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vp8_mediacodec";
}
break;
case "vp9":
if (_mediaEncoder.SupportsDecoder("vp9_mediacodec") && encodingOptions.HardwareDecodingCodecs.Contains("vp9", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vp9_mediacodec";
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_mediacodec";
}
break;
}
}
else if (string.Equals(encodingOptions.HardwareAccelerationType, "omx", StringComparison.OrdinalIgnoreCase))
{
switch (videoStream.Codec.ToLowerInvariant())
@@ -2674,51 +2739,175 @@ namespace MediaBrowser.Controller.MediaEncoding
{
return "-c:v h264_mmal";
}
break;
case "mpeg2video":
if (_mediaEncoder.SupportsDecoder("mpeg2_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg2_mmal";
}
break;
case "mpeg4":
if (_mediaEncoder.SupportsDecoder("mpeg4_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg4_mmal";
}
break;
case "vc1":
if (_mediaEncoder.SupportsDecoder("vc1_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vc1_mmal";
}
break;
}
}
else if (string.Equals(encodingOptions.HardwareAccelerationType, "amf", StringComparison.OrdinalIgnoreCase))
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
switch (videoStream.Codec.ToLowerInvariant())
{
if (Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1))
return "-hwaccel d3d11va";
else
return "-hwaccel dxva2";
case "avc":
case "h264":
return GetHwaccelType(state, encodingOptions, "h264");
case "hevc":
case "h265":
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Hevc) ? null : GetHwaccelType(state, encodingOptions, "hevc");
case "mpeg2video":
return GetHwaccelType(state, encodingOptions, "mpeg2video");
case "vc1":
return GetHwaccelType(state, encodingOptions, "vc1");
case "mpeg4":
return GetHwaccelType(state, encodingOptions, "mpeg4");
case "vp9":
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Vp9) ? null : GetHwaccelType(state, encodingOptions, "vp9");
}
else
}
else if (string.Equals(encodingOptions.HardwareAccelerationType, "vaapi", StringComparison.OrdinalIgnoreCase))
{
switch (videoStream.Codec.ToLowerInvariant())
{
return "-hwaccel vaapi";
case "avc":
case "h264":
return GetHwaccelType(state, encodingOptions, "h264");
case "hevc":
case "h265":
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Hevc) ? null : GetHwaccelType(state, encodingOptions, "hevc");
case "mpeg2video":
return GetHwaccelType(state, encodingOptions, "mpeg2video");
case "vc1":
return GetHwaccelType(state, encodingOptions, "vc1");
case "vp8":
return GetHwaccelType(state, encodingOptions, "vp8");
case "vp9":
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Vp9) ? null : GetHwaccelType(state, encodingOptions, "vp9");
}
}
else if (string.Equals(encodingOptions.HardwareAccelerationType, "videotoolbox", StringComparison.OrdinalIgnoreCase))
{
switch (videoStream.Codec.ToLowerInvariant())
{
case "avc":
case "h264":
if (_mediaEncoder.SupportsDecoder("h264_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
{
return "-c:v h264_opencl";
}
break;
case "hevc":
case "h265":
if (_mediaEncoder.SupportsDecoder("hevc_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase))
{
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Hevc) ? null : "-c:v hevc_opencl";
}
break;
case "mpeg2video":
if (_mediaEncoder.SupportsDecoder("mpeg2_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg2_opencl";
}
break;
case "mpeg4":
if (_mediaEncoder.SupportsDecoder("mpeg4_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase))
{
return "-c:v mpeg4_opencl";
}
break;
case "vc1":
if (_mediaEncoder.SupportsDecoder("vc1_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vc1_opencl";
}
break;
case "vp8":
if (_mediaEncoder.SupportsDecoder("vp8_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase))
{
return "-c:v vp8_opencl";
}
break;
case "vp9":
if (_mediaEncoder.SupportsDecoder("vp9_opencl") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase))
{
return (isColorDepth10 &&
!encodingOptions.EnableDecodingColorDepth10Vp9) ? null : "-c:v vp9_opencl";
}
break;
}
}
}
var whichCodec = videoStream.Codec.ToLowerInvariant();
switch (whichCodec)
{
case "avc":
whichCodec = "h264";
break;
case "h265":
whichCodec = "hevc";
break;
}
// Avoid a second attempt if no hardware acceleration is being used
encodingOptions.HardwareDecodingCodecs = Array.Empty<string>();
encodingOptions.HardwareDecodingCodecs = encodingOptions.HardwareDecodingCodecs.Where(val => val != whichCodec).ToArray();
// leave blank so ffmpeg will decide
return null;
}
/// <summary>
/// Gets a hwaccel type to use as a hardware decoder(dxva/vaapi) depending on the system
/// </summary>
public string GetHwaccelType(EncodingJobInfo state, EncodingOptions options, string videoCodec)
{
var isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
var isWindows8orLater = Environment.OSVersion.Version.Major > 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor > 1);
var isDxvaSupported = _mediaEncoder.SupportsHwaccel("dxva2") || _mediaEncoder.SupportsHwaccel("d3d11va");
if ((isDxvaSupported || IsVaapiSupported(state)) && options.HardwareDecodingCodecs.Contains(videoCodec, StringComparer.OrdinalIgnoreCase))
{
if (!isWindows)
{
return "-hwaccel vaapi";
}
else if (isWindows8orLater)
{
return "-hwaccel d3d11va";
}
else
{
return "-hwaccel dxva2";
}
}
return null;
}
public string GetSubtitleEmbedArguments(EncodingJobInfo state)
{
if (state.SubtitleStream == null || state.SubtitleDeliveryMethod != SubtitleDeliveryMethod.Embed)

View File

@@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using MediaBrowser.Controller.Entities;
using Jellyfin.Data.Entities;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
@@ -18,22 +18,37 @@ namespace MediaBrowser.Controller.MediaEncoding
public class EncodingJobInfo
{
public MediaStream VideoStream { get; set; }
public VideoType VideoType { get; set; }
public Dictionary<string, string> RemoteHttpHeaders { get; set; }
public string OutputVideoCodec { get; set; }
public MediaProtocol InputProtocol { get; set; }
public string MediaPath { get; set; }
public bool IsInputVideo { get; set; }
public IIsoMount IsoMount { get; set; }
public string[] PlayableStreamFileNames { get; set; }
public string OutputAudioCodec { get; set; }
public int? OutputVideoBitrate { get; set; }
public MediaStream SubtitleStream { get; set; }
public SubtitleDeliveryMethod SubtitleDeliveryMethod { get; set; }
public string[] SupportedSubtitleCodecs { get; set; }
public int InternalSubtitleStreamOffset { get; set; }
public MediaSourceInfo MediaSource { get; set; }
public User User { get; set; }
public long? RunTimeTicks { get; set; }
@@ -112,13 +127,19 @@ namespace MediaBrowser.Controller.MediaEncoding
public string AlbumCoverPath { get; set; }
public string InputAudioSync { get; set; }
public string InputVideoSync { get; set; }
public TransportStreamTimestamp InputTimestamp { get; set; }
public MediaStream AudioStream { get; set; }
public string[] SupportedAudioCodecs { get; set; }
public string[] SupportedVideoCodecs { get; set; }
public string InputContainer { get; set; }
public IsoType? IsoType { get; set; }
public BaseEncodingJobOptions BaseRequest { get; set; }
@@ -278,6 +299,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
public bool IsVideoRequest { get; set; }
public TranscodingJobType TranscodingType { get; set; }
public EncodingJobInfo(TranscodingJobType jobType)
@@ -403,7 +425,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Predicts the audio sample rate that will be in the output stream
/// Predicts the audio sample rate that will be in the output stream.
/// </summary>
public double? TargetVideoLevel
{
@@ -426,7 +448,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Predicts the audio sample rate that will be in the output stream
/// Predicts the audio sample rate that will be in the output stream.
/// </summary>
public int? TargetVideoBitDepth
{
@@ -461,7 +483,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Predicts the audio sample rate that will be in the output stream
/// Predicts the audio sample rate that will be in the output stream.
/// </summary>
public float? TargetFramerate
{
@@ -493,7 +515,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Predicts the audio sample rate that will be in the output stream
/// Predicts the audio sample rate that will be in the output stream.
/// </summary>
public int? TargetPacketLength
{
@@ -509,7 +531,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Predicts the audio sample rate that will be in the output stream
/// Predicts the audio sample rate that will be in the output stream.
/// </summary>
public string TargetVideoProfile
{
@@ -657,6 +679,7 @@ namespace MediaBrowser.Controller.MediaEncoding
}
public IProgress<double> Progress { get; set; }
public virtual void ReportTranscodingProgress(TimeSpan? transcodingPosition, float? framerate, double? percentComplete, long? bytesTranscoded, int? bitRate)
{
Progress.Report(percentComplete.Value);
@@ -664,20 +687,20 @@ namespace MediaBrowser.Controller.MediaEncoding
}
/// <summary>
/// Enum TranscodingJobType
/// Enum TranscodingJobType.
/// </summary>
public enum TranscodingJobType
{
/// <summary>
/// The progressive
/// The progressive.
/// </summary>
Progressive,
/// <summary>
/// The HLS
/// The HLS.
/// </summary>
Hls,
/// <summary>
/// The dash
/// The dash.
/// </summary>
Dash
}

View File

@@ -9,9 +9,11 @@ namespace MediaBrowser.Controller.MediaEncoding
public class EncodingJobOptions : BaseEncodingJobOptions
{
public string OutputDirectory { get; set; }
public string ItemId { get; set; }
public string TempDirectory { get; set; }
public bool ReadInputAtNativeFramerate { get; set; }
/// <summary>
@@ -47,6 +49,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{
SubtitleStreamIndex = info.SubtitleStreamIndex;
}
StreamOptions = info.StreamOptions;
}
}
@@ -81,7 +84,9 @@ namespace MediaBrowser.Controller.MediaEncoding
public bool EnableAutoStreamCopy { get; set; }
public bool AllowVideoStreamCopy { get; set; }
public bool AllowAudioStreamCopy { get; set; }
public bool BreakOnNonKeyFrames { get; set; }
/// <summary>
@@ -197,10 +202,15 @@ namespace MediaBrowser.Controller.MediaEncoding
[ApiMember(Name = "MaxVideoBitDepth", Description = "Optional.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? MaxVideoBitDepth { get; set; }
public bool RequireAvc { get; set; }
public bool DeInterlace { get; set; }
public bool RequireNonAnamorphic { get; set; }
public int? TranscodingMaxAudioChannels { get; set; }
public int? CpuCoreLimit { get; set; }
public string LiveStreamId { get; set; }

View File

@@ -11,7 +11,7 @@ using MediaBrowser.Model.System;
namespace MediaBrowser.Controller.MediaEncoding
{
/// <summary>
/// Interface IMediaEncoder
/// Interface IMediaEncoder.
/// </summary>
public interface IMediaEncoder : ITranscoderSupport
{
@@ -27,12 +27,26 @@ namespace MediaBrowser.Controller.MediaEncoding
string EncoderPath { get; }
/// <summary>
/// Supportses the decoder.
/// Whether given encoder codec is supported.
/// </summary>
/// <param name="encoder">The encoder.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool SupportsEncoder(string encoder);
/// <summary>
/// Whether given decoder codec is supported.
/// </summary>
/// <param name="decoder">The decoder.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool SupportsDecoder(string decoder);
/// <summary>
/// Whether given hardware acceleration type is supported.
/// </summary>
/// <param name="hwaccel">The hwaccel.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool SupportsHwaccel(string hwaccel);
/// <summary>
/// Extracts the audio image.
/// </summary>
@@ -98,7 +112,6 @@ namespace MediaBrowser.Controller.MediaEncoding
void SetFFmpegPath();
void UpdateEncoderPath(string path, string pathType);
bool SupportsEncoder(string encoder);
IEnumerable<string> GetPrimaryPlaylistVobFiles(string path, IIsoMount isoMount, uint? titleNumber);
}

View File

@@ -7,7 +7,7 @@ using MediaBrowser.Model.IO;
namespace MediaBrowser.Controller.MediaEncoding
{
/// <summary>
/// Class MediaEncoderHelpers
/// Class MediaEncoderHelpers.
/// </summary>
public static class MediaEncoderHelpers
{

View File

@@ -8,9 +8,13 @@ namespace MediaBrowser.Controller.MediaEncoding
public class MediaInfoRequest
{
public MediaSourceInfo MediaSource { get; set; }
public bool ExtractChapters { get; set; }
public DlnaProfileType MediaType { get; set; }
public IIsoMount MountedIso { get; set; }
public string[] PlayableStreamFileNames { get; set; }
public MediaInfoRequest()

View File

@@ -58,8 +58,11 @@ namespace MediaBrowser.Controller.Net
public interface IAuthenticationAttributes
{
bool EscapeParentalControl { get; }
bool AllowBeforeStartupWizard { get; }
bool AllowLocal { get; }
bool AllowLocalOnly { get; }
string[] GetRoles();

View File

@@ -1,36 +1,40 @@
using System;
using MediaBrowser.Controller.Entities;
using Jellyfin.Data.Entities;
namespace MediaBrowser.Controller.Net
{
public class AuthorizationInfo
{
/// <summary>
/// Gets or sets the user identifier.
/// Gets the user identifier.
/// </summary>
/// <value>The user identifier.</value>
public Guid UserId => User == null ? Guid.Empty : User.Id;
public Guid UserId => User?.Id ?? Guid.Empty;
/// <summary>
/// Gets or sets the device identifier.
/// </summary>
/// <value>The device identifier.</value>
public string DeviceId { get; set; }
/// <summary>
/// Gets or sets the device.
/// </summary>
/// <value>The device.</value>
public string Device { get; set; }
/// <summary>
/// Gets or sets the client.
/// </summary>
/// <value>The client.</value>
public string Client { get; set; }
/// <summary>
/// Gets or sets the version.
/// </summary>
/// <value>The version.</value>
public string Version { get; set; }
/// <summary>
/// Gets or sets the token.
/// </summary>

View File

@@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Net
{
/// <summary>
/// Starts sending data over a web socket periodically when a message is received, and then stops when a corresponding stop message is received
/// Starts sending data over a web socket periodically when a message is received, and then stops when a corresponding stop message is received.
/// </summary>
/// <typeparam name="TReturnDataType">The type of the T return data type.</typeparam>
/// <typeparam name="TStateType">The type of the T state type.</typeparam>
@@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Net
where TReturnDataType : class
{
/// <summary>
/// The _active connections
/// The _active connections.
/// </summary>
private readonly List<Tuple<IWebSocketConnection, CancellationTokenSource, TStateType>> _activeConnections =
new List<Tuple<IWebSocketConnection, CancellationTokenSource, TStateType>>();
@@ -38,11 +38,11 @@ namespace MediaBrowser.Controller.Net
protected abstract Task<TReturnDataType> GetDataToSend();
/// <summary>
/// The logger
/// The logger.
/// </summary>
protected ILogger Logger;
protected ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> Logger;
protected BasePeriodicWebSocketListener(ILogger logger)
protected BasePeriodicWebSocketListener(ILogger<BasePeriodicWebSocketListener<TReturnDataType, TStateType>> logger)
{
if (logger == null)
{
@@ -78,7 +78,7 @@ namespace MediaBrowser.Controller.Net
}
/// <summary>
/// Starts sending messages over a web socket
/// Starts sending messages over a web socket.
/// </summary>
/// <param name="message">The message.</param>
private void Start(WebSocketMessageInfo message)
@@ -156,6 +156,7 @@ namespace MediaBrowser.Controller.Net
await connection.SendAsync(
new WebSocketMessage<TReturnDataType>
{
MessageId = Guid.NewGuid(),
MessageType = Name,
Data = data
},
@@ -179,7 +180,7 @@ namespace MediaBrowser.Controller.Net
}
/// <summary>
/// Stops sending messages over a web socket
/// Stops sending messages over a web socket.
/// </summary>
/// <param name="message">The message.</param>
private void Stop(WebSocketMessageInfo message)
@@ -213,7 +214,7 @@ namespace MediaBrowser.Controller.Net
}
catch (ObjectDisposedException)
{
//TODO Investigate and properly fix.
// TODO Investigate and properly fix.
}
lock (_activeConnections)
@@ -253,7 +254,9 @@ namespace MediaBrowser.Controller.Net
public class WebSocketListenerState
{
public DateTime DateLastSendUtc { get; set; }
public long InitialDelayMs { get; set; }
public long IntervalMs { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show More