Merge remote-tracking branch 'upstream/master' into client-logger

This commit is contained in:
Cody Robibero
2021-10-26 17:43:36 -06:00
1165 changed files with 24439 additions and 15715 deletions

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using MediaBrowser.Controller.Session;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System.Threading.Tasks;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;

View File

@@ -1,6 +1,8 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using Jellyfin.Extensions;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -13,7 +15,7 @@ namespace MediaBrowser.Controller.BaseItemManager
{
private readonly IServerConfigurationManager _serverConfigurationManager;
private int _metadataRefreshConcurrency = 0;
private int _metadataRefreshConcurrency;
/// <summary>
/// Initializes a new instance of the <see cref="BaseItemManager"/> class.
@@ -50,7 +52,7 @@ namespace MediaBrowser.Controller.BaseItemManager
var typeOptions = libraryOptions.GetTypeOptions(baseItem.GetType().Name);
if (typeOptions != null)
{
return typeOptions.MetadataFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
return typeOptions.MetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
}
if (!libraryOptions.EnableInternetProviders)
@@ -60,7 +62,7 @@ namespace MediaBrowser.Controller.BaseItemManager
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, GetType().Name, StringComparison.OrdinalIgnoreCase));
return itemConfig == null || !itemConfig.DisabledMetadataFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
return itemConfig == null || !itemConfig.DisabledMetadataFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
}
/// <inheritdoc />
@@ -81,7 +83,7 @@ namespace MediaBrowser.Controller.BaseItemManager
var typeOptions = libraryOptions.GetTypeOptions(baseItem.GetType().Name);
if (typeOptions != null)
{
return typeOptions.ImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
return typeOptions.ImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
}
if (!libraryOptions.EnableInternetProviders)
@@ -91,14 +93,14 @@ namespace MediaBrowser.Controller.BaseItemManager
var itemConfig = _serverConfigurationManager.Configuration.MetadataOptions.FirstOrDefault(i => string.Equals(i.ItemType, GetType().Name, StringComparison.OrdinalIgnoreCase));
return itemConfig == null || !itemConfig.DisabledImageFetchers.Contains(name, StringComparer.OrdinalIgnoreCase);
return itemConfig == null || !itemConfig.DisabledImageFetchers.Contains(name.AsSpan(), StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Called when the configuration is updated.
/// It will refresh the metadata throttler if the relevant config changed.
/// </summary>
private void OnConfigurationUpdated(object sender, EventArgs e)
private void OnConfigurationUpdated(object? sender, EventArgs e)
{
int newMetadataRefreshConcurrency = GetMetadataRefreshConcurrency();
if (_metadataRefreshConcurrency != newMetadataRefreshConcurrency)
@@ -111,6 +113,7 @@ namespace MediaBrowser.Controller.BaseItemManager
/// <summary>
/// Creates the metadata refresh throttler.
/// </summary>
[MemberNotNull(nameof(MetadataRefreshThrottler))]
private void SetupMetadataThrottler()
{
MetadataRefreshThrottler = new SemaphoreSlim(_metadataRefreshConcurrency);

View File

@@ -32,4 +32,4 @@ namespace MediaBrowser.Controller.BaseItemManager
/// <returns><c>true</c> if image fetcher is enabled, else false.</returns>
bool IsImageFetcherEnabled(BaseItem baseItem, LibraryOptions libraryOptions, string name);
}
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -15,6 +17,12 @@ namespace MediaBrowser.Controller.Channels
{
public class Channel : Folder
{
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
public override SourceType SourceType => SourceType.Channel;
public override bool IsVisible(User user)
{
var blockedChannelsPreference = user.GetPreferenceValues<Guid>(PreferenceKind.BlockedChannels);
@@ -37,12 +45,6 @@ namespace MediaBrowser.Controller.Channels
return base.IsVisible(user);
}
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
public override SourceType SourceType => SourceType.Channel;
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
{
try
@@ -82,7 +84,7 @@ namespace MediaBrowser.Controller.Channels
internal static bool IsChannelVisible(BaseItem channelItem, User user)
{
var channel = ChannelManager.GetChannel(channelItem.ChannelId.ToString(""));
var channel = ChannelManager.GetChannel(channelItem.ChannelId.ToString(string.Empty));
return channel.IsVisible(user);
}

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1002, CA2227, CS1591
using System;
using System.Collections.Generic;
@@ -11,6 +13,19 @@ namespace MediaBrowser.Controller.Channels
{
public class ChannelItemInfo : IHasProviderIds
{
public ChannelItemInfo()
{
MediaSources = new List<MediaSourceInfo>();
TrailerTypes = new List<TrailerType>();
Genres = new List<string>();
Studios = new List<string>();
People = new List<PersonInfo>();
Tags = new List<string>();
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
Artists = new List<string>();
AlbumArtists = new List<string>();
}
public string Name { get; set; }
public string SeriesName { get; set; }
@@ -78,18 +93,5 @@ namespace MediaBrowser.Controller.Channels
public bool IsLiveStream { get; set; }
public string Etag { get; set; }
public ChannelItemInfo()
{
MediaSources = new List<MediaSourceInfo>();
TrailerTypes = new List<TrailerType>();
Genres = new List<string>();
Studios = new List<string>();
People = new List<PersonInfo>();
Tags = new List<string>();
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
Artists = new List<string>();
AlbumArtists = new List<string>();
}
}
}

View File

@@ -1,18 +1,19 @@
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
namespace MediaBrowser.Controller.Channels
{
public class ChannelItemResult
{
public List<ChannelItemInfo> Items { get; set; }
public int? TotalRecordCount { get; set; }
public ChannelItemResult()
{
Items = new List<ChannelItemInfo>();
Items = Array.Empty<ChannelItemInfo>();
}
public IReadOnlyList<ChannelItemInfo> Items { get; set; }
public int? TotalRecordCount { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
#nullable disable
#pragma warning disable CS1591
namespace MediaBrowser.Controller.Channels
{
public class ChannelLatestMediaSearch
{
public string UserId { get; set; }
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
namespace MediaBrowser.Controller.Channels
@@ -8,9 +10,4 @@ namespace MediaBrowser.Controller.Channels
public string UserId { get; set; }
}
public class ChannelLatestMediaSearch
{
public string UserId { get; set; }
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System.Collections.Generic;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -49,32 +51,47 @@ namespace MediaBrowser.Controller.Channels
/// Gets the channels internal.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>The channels.</returns>
QueryResult<Channel> GetChannelsInternal(ChannelQuery query);
/// <summary>
/// Gets the channels.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>The channels.</returns>
QueryResult<BaseItemDto> GetChannels(ChannelQuery query);
/// <summary>
/// Gets the latest media.
/// Gets the latest channel items.
/// </summary>
/// <param name="query">The item query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The latest channels.</returns>
Task<QueryResult<BaseItemDto>> GetLatestChannelItems(InternalItemsQuery query, CancellationToken cancellationToken);
/// <summary>
/// Gets the latest media.
/// Gets the latest channel items.
/// </summary>
/// <param name="query">The item query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The latest channels.</returns>
Task<QueryResult<BaseItem>> GetLatestChannelItemsInternal(InternalItemsQuery query, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel items.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The channel items.</returns>
Task<QueryResult<BaseItemDto>> GetChannelItems(InternalItemsQuery query, CancellationToken cancellationToken);
/// <summary>
/// Gets the channel items internal.
/// Gets the channel items.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="progress">The progress to report to.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The channel items.</returns>
Task<QueryResult<BaseItem>> GetChannelItemsInternal(InternalItemsQuery query, IProgress<double> progress, CancellationToken cancellationToken);
/// <summary>
@@ -82,9 +99,14 @@ namespace MediaBrowser.Controller.Channels
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
/// <returns>The item media sources.</returns>
IEnumerable<MediaSourceInfo> GetStaticMediaSources(BaseItem item, CancellationToken cancellationToken);
/// <summary>
/// Whether the item supports media probe.
/// </summary>
/// <param name="item">The item.</param>
/// <returns>Whether media probe should be enabled.</returns>
bool EnableMediaProbe(BaseItem item);
}
}

View File

@@ -0,0 +1,12 @@
namespace MediaBrowser.Controller.Channels
{
/// <summary>
/// Disable media source display.
/// </summary>
/// <remarks>
/// <see cref="Channel"/> can inherit this interface to disable being displayed.
/// </remarks>
public interface IDisableMediaSourceDisplay
{
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
namespace MediaBrowser.Controller.Channels

View File

@@ -0,0 +1,9 @@
#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Channels
{
public interface IHasFolderAttributes
{
string[] Attributes { get; }
}
}

View File

@@ -1,5 +1,3 @@
#pragma warning disable CS1591
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -7,11 +5,17 @@ using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Channels
{
/// <summary>
/// The channel requires a media info callback.
/// </summary>
public interface IRequiresMediaInfoCallback
{
/// <summary>
/// Gets the channel item media information.
/// </summary>
/// <param name="id">The channel item id.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The enumerable of media source info.</returns>
Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaInfo(string id, CancellationToken cancellationToken);
}
}

View File

@@ -1,9 +1,10 @@
#nullable disable
#pragma warning disable CS1591
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Channels
{
@@ -17,35 +18,4 @@ namespace MediaBrowser.Controller.Channels
/// <returns>Task{IEnumerable{ChannelItemInfo}}.</returns>
Task<IEnumerable<ChannelItemInfo>> Search(ChannelSearchInfo searchInfo, CancellationToken cancellationToken);
}
public interface ISupportsLatestMedia
{
/// <summary>
/// Gets the latest media.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{ChannelItemInfo}}.</returns>
Task<IEnumerable<ChannelItemInfo>> GetLatestMedia(ChannelLatestMediaSearch request, CancellationToken cancellationToken);
}
public interface ISupportsDelete
{
bool CanDelete(BaseItem item);
Task DeleteItem(string id, CancellationToken cancellationToken);
}
public interface IDisableMediaSourceDisplay
{
}
public interface ISupportsMediaProbe
{
}
public interface IHasFolderAttributes
{
string[] Attributes { get; }
}
}

View File

@@ -0,0 +1,15 @@
#pragma warning disable CS1591
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Entities;
namespace MediaBrowser.Controller.Channels
{
public interface ISupportsDelete
{
bool CanDelete(BaseItem item);
Task DeleteItem(string id, CancellationToken cancellationToken);
}
}

View File

@@ -0,0 +1,21 @@
#nullable disable
#pragma warning disable CS1591
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Channels
{
public interface ISupportsLatestMedia
{
/// <summary>
/// Gets the latest media.
/// </summary>
/// <param name="request">The request.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The latest media.</returns>
Task<IEnumerable<ChannelItemInfo>> GetLatestMedia(ChannelLatestMediaSearch request, CancellationToken cancellationToken);
}
}

View File

@@ -0,0 +1,9 @@
namespace MediaBrowser.Controller.Channels
{
/// <summary>
/// Channel supports media probe.
/// </summary>
public interface ISupportsMediaProbe
{
}
}

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1002, CA2227, CS1591
using System.Collections.Generic;
using MediaBrowser.Model.Channels;
@@ -28,7 +30,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.
/// Gets or sets the maximum number of records the channel allows retrieving at a time.
/// </summary>
public int? MaxPageSize { get; set; }
@@ -39,7 +41,7 @@ namespace MediaBrowser.Controller.Channels
public List<ChannelItemSortField> DefaultSortFields { get; set; }
/// <summary>
/// Indicates if a sort ascending/descending toggle is supported or not.
/// Gets or sets a value indicating whether a sort ascending/descending toggle is supported or not.
/// </summary>
public bool SupportsSortOrderToggle { get; set; }

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;

View File

@@ -12,6 +12,8 @@ namespace MediaBrowser.Controller.Chapters
/// <summary>
/// Saves the chapters.
/// </summary>
/// <param name="itemId">The item.</param>
/// <param name="chapters">The set of chapters.</param>
void SaveChapters(Guid itemId, IReadOnlyList<ChapterInfo> chapters);
}
}

View File

@@ -0,0 +1,24 @@
#nullable disable
#pragma warning disable CS1591
using System;
using MediaBrowser.Controller.Entities.Movies;
namespace MediaBrowser.Controller.Collections
{
public class CollectionCreatedEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the collection.
/// </summary>
/// <value>The collection.</value>
public BoxSet Collection { get; set; }
/// <summary>
/// Gets or sets the options.
/// </summary>
/// <value>The options.</value>
public CollectionCreationOptions Options { get; set; }
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -23,8 +25,8 @@ namespace MediaBrowser.Controller.Collections
public Dictionary<string, string> ProviderIds { get; set; }
public string[] ItemIdList { get; set; }
public IReadOnlyList<string> ItemIdList { get; set; }
public Guid[] UserIds { get; set; }
public IReadOnlyList<Guid> UserIds { get; set; }
}
}

View File

@@ -7,23 +7,14 @@ using MediaBrowser.Controller.Entities.Movies;
namespace MediaBrowser.Controller.Collections
{
public class CollectionCreatedEventArgs : EventArgs
{
/// <summary>
/// Gets or sets the collection.
/// </summary>
/// <value>The collection.</value>
public BoxSet Collection { get; set; }
/// <summary>
/// Gets or sets the options.
/// </summary>
/// <value>The options.</value>
public CollectionCreationOptions Options { get; set; }
}
public class CollectionModifiedEventArgs : EventArgs
{
public CollectionModifiedEventArgs(BoxSet collection, IReadOnlyCollection<BaseItem> itemsChanged)
{
Collection = collection;
ItemsChanged = itemsChanged;
}
/// <summary>
/// Gets or sets the collection.
/// </summary>
@@ -34,6 +25,6 @@ namespace MediaBrowser.Controller.Collections
/// Gets or sets the items changed.
/// </summary>
/// <value>The items changed.</value>
public List<BaseItem> ItemsChanged { get; set; }
public IReadOnlyCollection<BaseItem> ItemsChanged { get; set; }
}
}

View File

@@ -14,22 +14,23 @@ namespace MediaBrowser.Controller.Collections
/// <summary>
/// Occurs when [collection created].
/// </summary>
event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
event EventHandler<CollectionCreatedEventArgs>? CollectionCreated;
/// <summary>
/// Occurs when [items added to collection].
/// </summary>
event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
event EventHandler<CollectionModifiedEventArgs>? ItemsAddedToCollection;
/// <summary>
/// Occurs when [items removed from collection].
/// </summary>
event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
event EventHandler<CollectionModifiedEventArgs>? ItemsRemovedFromCollection;
/// <summary>
/// Creates the collection.
/// </summary>
/// <param name="options">The options.</param>
/// <returns>BoxSet wrapped in an awaitable task.</returns>
Task<BoxSet> CreateCollectionAsync(CollectionCreationOptions options);
/// <summary>

View File

@@ -1,8 +1,13 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Entities.Security;
using Jellyfin.Data.Events;
using Jellyfin.Data.Queries;
using MediaBrowser.Model.Devices;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Session;
@@ -13,42 +18,63 @@ namespace MediaBrowser.Controller.Devices
{
event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
/// <summary>
/// Creates a new device.
/// </summary>
/// <param name="device">The device to create.</param>
/// <returns>A <see cref="Task{Device}"/> representing the creation of the device.</returns>
Task<Device> CreateDevice(Device device);
/// <summary>
/// Saves the capabilities.
/// </summary>
/// <param name="reportedId">The reported identifier.</param>
/// <param name="deviceId">The device id.</param>
/// <param name="capabilities">The capabilities.</param>
/// <returns>Task.</returns>
void SaveCapabilities(string reportedId, ClientCapabilities capabilities);
void SaveCapabilities(string deviceId, ClientCapabilities capabilities);
/// <summary>
/// Gets the capabilities.
/// </summary>
/// <param name="reportedId">The reported identifier.</param>
/// <param name="deviceId">The device id.</param>
/// <returns>ClientCapabilities.</returns>
ClientCapabilities GetCapabilities(string reportedId);
ClientCapabilities GetCapabilities(string deviceId);
/// <summary>
/// Gets the device information.
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>DeviceInfo.</returns>
DeviceInfo GetDevice(string id);
Task<DeviceInfo> GetDevice(string id);
/// <summary>
/// Gets devices based on the provided query.
/// </summary>
/// <param name="query">The device query.</param>
/// <returns>A <see cref="Task{QueryResult}"/> representing the retrieval of the devices.</returns>
Task<QueryResult<Device>> GetDevices(DeviceQuery query);
Task<QueryResult<DeviceInfo>> GetDeviceInfos(DeviceQuery query);
/// <summary>
/// Gets the devices.
/// </summary>
/// <param name="query">The query.</param>
/// <param name="userId">The user's id, or <c>null</c>.</param>
/// <param name="supportsSync">A value indicating whether the device supports sync, or <c>null</c>.</param>
/// <returns>IEnumerable&lt;DeviceInfo&gt;.</returns>
QueryResult<DeviceInfo> GetDevices(DeviceQuery query);
Task<QueryResult<DeviceInfo>> GetDevicesForUser(Guid? userId, bool? supportsSync);
Task DeleteDevice(Device device);
/// <summary>
/// Determines whether this instance [can access device] the specified user identifier.
/// </summary>
/// <param name="user">The user to test.</param>
/// <param name="deviceId">The device id to test.</param>
/// <returns>Whether the user can access the device.</returns>
bool CanAccessDevice(User user, string deviceId);
void UpdateDeviceOptions(string deviceId, DeviceOptions options);
Task UpdateDeviceOptions(string deviceId, string deviceName);
DeviceOptions GetDeviceOptions(string deviceId);
Task<DeviceOptions> GetDeviceOptions(string deviceId);
}
}

View File

@@ -20,7 +20,7 @@ namespace MediaBrowser.Controller.Dlna
/// </summary>
/// <param name="headers">The headers.</param>
/// <returns>DeviceProfile.</returns>
DeviceProfile GetProfile(IHeaderDictionary headers);
DeviceProfile? GetProfile(IHeaderDictionary headers);
/// <summary>
/// Gets the default profile.
@@ -51,14 +51,14 @@ namespace MediaBrowser.Controller.Dlna
/// </summary>
/// <param name="id">The identifier.</param>
/// <returns>DeviceProfile.</returns>
DeviceProfile GetProfile(string id);
DeviceProfile? GetProfile(string id);
/// <summary>
/// Gets the profile.
/// </summary>
/// <param name="deviceInfo">The device information.</param>
/// <returns>DeviceProfile.</returns>
DeviceProfile GetProfile(DeviceIdentification deviceInfo);
DeviceProfile? GetProfile(DeviceIdentification deviceInfo);
/// <summary>
/// Gets the server description XML.
@@ -74,6 +74,6 @@ namespace MediaBrowser.Controller.Dlna
/// </summary>
/// <param name="filename">The filename.</param>
/// <returns>DlnaIconResponse.</returns>
ImageStream GetIcon(string filename);
ImageStream? GetIcon(string filename);
}
}

View File

@@ -1,5 +1,4 @@
#pragma warning disable CS1591
#nullable enable
using System;
using System.Collections.Generic;
@@ -58,6 +57,15 @@ namespace MediaBrowser.Controller.Drawing
/// <summary>
/// Encode an image.
/// </summary>
/// <param name="inputPath">Input path of image.</param>
/// <param name="dateModified">Date modified.</param>
/// <param name="outputPath">Output path of image.</param>
/// <param name="autoOrient">Auto-orient image.</param>
/// <param name="orientation">Desired orientation of image.</param>
/// <param name="quality">Quality of encoded image.</param>
/// <param name="options">Image processing options.</param>
/// <param name="outputFormat">Image format of output.</param>
/// <returns>Path of encoded image.</returns>
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
/// <summary>

View File

@@ -1,5 +1,4 @@
#pragma warning disable CS1591
#nullable enable
using System;
using System.Collections.Generic;
@@ -59,7 +58,7 @@ namespace MediaBrowser.Controller.Drawing
/// <returns>Guid.</returns>
string GetImageCacheTag(BaseItem item, ItemImageInfo image);
string GetImageCacheTag(BaseItem item, ChapterInfo info);
string GetImageCacheTag(BaseItem item, ChapterInfo chapter);
string? GetImageCacheTag(User user);

View File

@@ -1,3 +1,7 @@
#nullable disable
using System.Collections.Generic;
#pragma warning disable CS1591
namespace MediaBrowser.Controller.Drawing
@@ -8,7 +12,7 @@ namespace MediaBrowser.Controller.Drawing
/// Gets or sets the input paths.
/// </summary>
/// <value>The input paths.</value>
public string[] InputPaths { get; set; }
public IReadOnlyList<string> InputPaths { get; set; }
/// <summary>
/// Gets or sets the output path.

View File

@@ -1,5 +1,4 @@
#pragma warning disable CS1591
#nullable enable
using MediaBrowser.Model.Drawing;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using MediaBrowser.Controller.Entities;

View File

@@ -1,4 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable CA1711, CS1591
using System;
using System.IO;
@@ -8,11 +8,16 @@ namespace MediaBrowser.Controller.Drawing
{
public class ImageStream : IDisposable
{
public ImageStream(Stream stream)
{
Stream = stream;
}
/// <summary>
/// Gets or sets the stream.
/// Gets the stream.
/// </summary>
/// <value>The stream.</value>
public Stream Stream { get; set; }
public Stream Stream { get; }
/// <summary>
/// Gets or sets the format.
@@ -22,9 +27,15 @@ namespace MediaBrowser.Controller.Drawing
public void Dispose()
{
if (Stream != null)
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
Stream.Dispose();
Stream?.Dispose();
}
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -16,6 +18,28 @@ namespace MediaBrowser.Controller.Dto
ItemFields.RefreshState
};
private static readonly ImageType[] AllImageTypes = Enum.GetValues<ImageType>();
private static readonly ItemFields[] AllItemFields = Enum.GetValues<ItemFields>()
.Except(DefaultExcludedFields)
.ToArray();
public DtoOptions()
: this(true)
{
}
public DtoOptions(bool allFields)
{
ImageTypeLimit = int.MaxValue;
EnableImages = true;
EnableUserData = true;
AddCurrentProgram = true;
Fields = allFields ? AllItemFields : Array.Empty<ItemFields>();
ImageTypes = AllImageTypes;
}
public IReadOnlyList<ItemFields> Fields { get; set; }
public IReadOnlyList<ImageType> ImageTypes { get; set; }
@@ -30,34 +54,9 @@ namespace MediaBrowser.Controller.Dto
public bool AddCurrentProgram { get; set; }
public DtoOptions()
: this(true)
{
}
private static readonly ImageType[] AllImageTypes = Enum.GetNames(typeof(ImageType))
.Select(i => (ImageType)Enum.Parse(typeof(ImageType), i, true))
.ToArray();
private static readonly ItemFields[] AllItemFields = Enum.GetNames(typeof(ItemFields))
.Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true))
.Except(DefaultExcludedFields)
.ToArray();
public bool ContainsField(ItemFields field)
=> Fields.Contains(field);
public DtoOptions(bool allFields)
{
ImageTypeLimit = int.MaxValue;
EnableImages = true;
EnableUserData = true;
AddCurrentProgram = true;
Fields = allFields ? AllItemFields : Array.Empty<ItemFields>();
ImageTypes = AllImageTypes;
}
public int GetImageLimit(ImageType type)
{
if (EnableImages && ImageTypes.Contains(type))

View File

@@ -1,3 +1,6 @@
#nullable disable
#pragma warning disable CA1002
using System.Collections.Generic;
using Jellyfin.Data.Entities;
using MediaBrowser.Controller.Entities;
@@ -34,11 +37,17 @@ namespace MediaBrowser.Controller.Dto
/// <param name="options">The options.</param>
/// <param name="user">The user.</param>
/// <param name="owner">The owner.</param>
/// <returns>The <see cref="IReadOnlyList{T}"/> of <see cref="BaseItemDto"/>.</returns>
IReadOnlyList<BaseItemDto> GetBaseItemDtos(IReadOnlyList<BaseItem> items, DtoOptions options, User user = null, BaseItem owner = null);
/// <summary>
/// Gets the item by name dto.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="options">The dto options.</param>
/// <param name="taggedItems">The list of tagged items.</param>
/// <param name="user">The user.</param>
/// <returns>The item dto.</returns>
BaseItemDto GetItemByNameDto(BaseItem item, DtoOptions options, List<BaseItem> taggedItems, User user = null);
}
}

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1819, CS1591
using System;
using System.Collections.Concurrent;
@@ -16,30 +18,23 @@ namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Specialized folder that can have items added to it's children by external entities.
/// Used for our RootFolder so plug-ins can add items.
/// Used for our RootFolder so plugins can add items.
/// </summary>
public class AggregateFolder : Folder
{
public AggregateFolder()
{
PhysicalLocationsList = Array.Empty<string>();
}
[JsonIgnore]
public override bool IsPhysicalRoot => true;
public override bool CanDelete()
{
return false;
}
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
private readonly object _childIdsLock = new object();
/// <summary>
/// The _virtual children.
/// </summary>
private readonly ConcurrentBag<BaseItem> _virtualChildren = new ConcurrentBag<BaseItem>();
private bool _requiresRefresh;
private Guid[] _childrenIds = null;
public AggregateFolder()
{
PhysicalLocationsList = Array.Empty<string>();
}
/// <summary>
/// Gets the virtual children.
@@ -47,19 +42,27 @@ namespace MediaBrowser.Controller.Entities
/// <value>The virtual children.</value>
public ConcurrentBag<BaseItem> VirtualChildren => _virtualChildren;
[JsonIgnore]
public override bool IsPhysicalRoot => true;
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
[JsonIgnore]
public override string[] PhysicalLocations => PhysicalLocationsList;
public string[] PhysicalLocationsList { get; set; }
public override bool CanDelete()
{
return false;
}
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
{
return CreateResolveArgs(directoryService, true).FileSystemChildren;
}
private Guid[] _childrenIds = null;
private readonly object _childIdsLock = new object();
protected override List<BaseItem> LoadChildren()
{
lock (_childIdsLock)
@@ -83,7 +86,6 @@ namespace MediaBrowser.Controller.Entities
}
}
private bool _requiresRefresh;
public override bool RequiresRefresh()
{
var changed = base.RequiresRefresh() || _requiresRefresh;
@@ -103,11 +105,11 @@ namespace MediaBrowser.Controller.Entities
return changed;
}
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
ClearCache();
var changed = base.BeforeMetadataRefresh(replaceAllMetdata) || _requiresRefresh;
var changed = base.BeforeMetadataRefresh(replaceAllMetadata) || _requiresRefresh;
_requiresRefresh = false;
return changed;
}
@@ -120,8 +122,7 @@ namespace MediaBrowser.Controller.Entities
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService)
{
FileInfo = FileSystem.GetDirectoryInfo(path),
Path = path
FileInfo = FileSystem.GetDirectoryInfo(path)
};
// Gather child folder and files
@@ -153,11 +154,11 @@ namespace MediaBrowser.Controller.Entities
return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren);
}
protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
ClearCache();
await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService)
await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken)
.ConfigureAwait(false);
ClearCache();
@@ -167,7 +168,7 @@ namespace MediaBrowser.Controller.Entities
/// Adds the virtual child.
/// </summary>
/// <param name="child">The child.</param>
/// <exception cref="ArgumentNullException"></exception>
/// <exception cref="ArgumentNullException">Throws if child is null.</exception>
public void AddVirtualChild(BaseItem child)
{
if (child == null)
@@ -183,7 +184,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <param name="id">The id.</param>
/// <returns>BaseItem.</returns>
/// <exception cref="ArgumentNullException">id</exception>
/// <exception cref="ArgumentNullException">The id is empty.</exception>
public BaseItem FindVirtualChild(Guid id)
{
if (id.Equals(Guid.Empty))

View File

@@ -1,7 +1,10 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1002, CA1724, CA1826, CS1591
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
@@ -22,6 +25,12 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasLookupInfo<SongInfo>,
IHasMediaSources
{
public Audio()
{
Artists = Array.Empty<string>();
AlbumArtists = Array.Empty<string>();
}
/// <inheritdoc />
[JsonIgnore]
public IReadOnlyList<string> Artists { get; set; }
@@ -30,22 +39,11 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public IReadOnlyList<string> AlbumArtists { get; set; }
public Audio()
{
Artists = Array.Empty<string>();
AlbumArtists = Array.Empty<string>();
}
public override double GetDefaultPrimaryImageAspectRatio()
{
return 1;
}
[JsonIgnore]
public override bool SupportsPlayedStatus => true;
[JsonIgnore]
public override bool SupportsPeople => false;
public override bool SupportsPeople => true;
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
@@ -59,11 +57,6 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override Folder LatestItemsIndexContainer => AlbumEntity;
public override bool CanDownload()
{
return IsFileProtocol;
}
[JsonIgnore]
public MusicAlbum AlbumEntity => FindParent<MusicAlbum>();
@@ -74,25 +67,35 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override string MediaType => Model.Entities.MediaType.Audio;
public override double GetDefaultPrimaryImageAspectRatio()
{
return 1;
}
public override bool CanDownload()
{
return IsFileProtocol;
}
/// <summary>
/// Creates the name of the sort.
/// </summary>
/// <returns>System.String.</returns>
protected override string CreateSortName()
{
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty)
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty) + Name;
}
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000", CultureInfo.InvariantCulture) : string.Empty;
if (ParentIndexNumber.HasValue)
{
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
songKey = ParentIndexNumber.Value.ToString("0000", CultureInfo.InvariantCulture) + "-" + songKey;
}
songKey += Name;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System.Collections.Generic;

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Entities.Audio
{

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1721, CA1826, CS1591
using System;
using System.Collections.Generic;
@@ -21,18 +23,18 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer
{
/// <inheritdoc />
public IReadOnlyList<string> AlbumArtists { get; set; }
/// <inheritdoc />
public IReadOnlyList<string> Artists { get; set; }
public MusicAlbum()
{
Artists = Array.Empty<string>();
AlbumArtists = Array.Empty<string>();
}
/// <inheritdoc />
public IReadOnlyList<string> AlbumArtists { get; set; }
/// <inheritdoc />
public IReadOnlyList<string> Artists { get; set; }
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
@@ -42,6 +44,25 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public MusicArtist MusicArtist => GetMusicArtist(new DtoOptions(true));
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
[JsonIgnore]
public override bool SupportsCumulativeRunTimeTicks => true;
[JsonIgnore]
public string AlbumArtist => AlbumArtists.FirstOrDefault();
[JsonIgnore]
public override bool SupportsPeople => false;
/// <summary>
/// Gets the tracks.
/// </summary>
/// <value>The tracks.</value>
[JsonIgnore]
public IEnumerable<Audio> Tracks => GetRecursiveChildren(i => i is Audio).Cast<Audio>();
public MusicArtist GetMusicArtist(DtoOptions options)
{
var parents = GetParents();
@@ -62,25 +83,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return null;
}
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
[JsonIgnore]
public override bool SupportsCumulativeRunTimeTicks => true;
[JsonIgnore]
public string AlbumArtist => AlbumArtists.FirstOrDefault();
[JsonIgnore]
public override bool SupportsPeople => false;
/// <summary>
/// Gets the tracks.
/// </summary>
/// <value>The tracks.</value>
[JsonIgnore]
public IEnumerable<Audio> Tracks => GetRecursiveChildren(i => i is Audio).Cast<Audio>();
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
{
return Tracks;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -6,9 +8,9 @@ using System.Linq;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using Diacritics.Extensions;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller.Extensions;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using Microsoft.Extensions.Logging;
@@ -42,6 +44,36 @@ namespace MediaBrowser.Controller.Entities.Audio
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
/// <summary>
/// Gets 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;
[JsonIgnore]
public override IEnumerable<BaseItem> Children
{
get
{
if (IsAccessedByName)
{
return new List<BaseItem>();
}
return base.Children;
}
}
[JsonIgnore]
public override bool SupportsPeople => false;
public static string GetPath(string name)
{
return GetPath(name, true);
}
public override double GetDefaultPrimaryImageAspectRatio()
{
return 1;
@@ -63,20 +95,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return LibraryManager.GetItemList(query);
}
[JsonIgnore]
public override IEnumerable<BaseItem> Children
{
get
{
if (IsAccessedByName)
{
return new List<BaseItem>();
}
return base.Children;
}
}
public override int GetChildCount(User user)
{
return IsAccessedByName ? 0 : base.GetChildCount(user);
@@ -92,7 +110,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return base.IsSaveLocalMetadataEnabled();
}
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
if (IsAccessedByName)
{
@@ -100,7 +118,7 @@ namespace MediaBrowser.Controller.Entities.Audio
return Task.CompletedTask;
}
return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService);
return base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken);
}
public override List<string> GetUserDataKeys()
@@ -111,14 +129,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return list;
}
/// <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 user data key.
/// </summary>
@@ -165,14 +175,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return info;
}
[JsonIgnore]
public override bool SupportsPeople => false;
public static string GetPath(string name)
{
return GetPath(name, true);
}
public static string GetPath(string name, bool normalizeName)
{
// Trim the period at the end because windows will have a hard time with that
@@ -206,9 +208,11 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
/// <param name="replaceAllMetadata">Option to replace metadata.</param>
/// <returns>True if metadata changed.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
if (IsAccessedByName)
{

View File

@@ -1,9 +1,11 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using MediaBrowser.Controller.Extensions;
using Diacritics.Extensions;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities.Audio
@@ -13,6 +15,26 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
public class MusicGenre : BaseItem, IItemByName
{
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
[JsonIgnore]
public override bool SupportsAncestors => false;
[JsonIgnore]
public override bool IsDisplayedAsFolder => true;
/// <summary>
/// Gets 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;
[JsonIgnore]
public override bool SupportsPeople => false;
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -26,23 +48,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return GetUserDataKeys()[0];
}
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
[JsonIgnore]
public override bool SupportsAncestors => false;
[JsonIgnore]
public override bool IsDisplayedAsFolder => true;
/// <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;
public override double GetDefaultPrimaryImageAspectRatio()
{
return 1;
@@ -58,9 +63,6 @@ namespace MediaBrowser.Controller.Entities.Audio
return true;
}
[JsonIgnore]
public override bool SupportsPeople => false;
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
{
query.GenreIds = new[] { Id };
@@ -104,9 +106,11 @@ namespace MediaBrowser.Controller.Entities.Audio
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
/// <param name="replaceAllMetadata">Option to replace metadata.</param>
/// <returns>True if metadata changed.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1724, CS1591
using System;
using System.Text.Json.Serialization;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,3 @@
#nullable enable
#pragma warning disable CS1591
using System;
@@ -45,7 +44,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="file">The file.</param>
public static void SetImagePath(this BaseItem item, ImageType imageType, string file)
{
if (file.StartsWith("http", System.StringComparison.OrdinalIgnoreCase))
if (file.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
item.SetImage(
new ItemImageInfo
@@ -65,6 +64,8 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <param name="source">The source object.</param>
/// <param name="dest">The destination object.</param>
/// <typeparam name="T">Source type.</typeparam>
/// <typeparam name="TU">Destination type.</typeparam>
public static void DeepCopy<T, TU>(this T source, TU dest)
where T : BaseItem
where TU : BaseItem
@@ -110,6 +111,9 @@ namespace MediaBrowser.Controller.Entities
/// Copies all properties on newly created object. Skips properties that do not exist.
/// </summary>
/// <param name="source">The source object.</param>
/// <typeparam name="T">Source type.</typeparam>
/// <typeparam name="TU">Destination type.</typeparam>
/// <returns>Destination object.</returns>
public static TU DeepCopy<T, TU>(this T source)
where T : BaseItem
where TU : BaseItem, new()

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System.Text.Json.Serialization;
@@ -13,6 +15,12 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public virtual string CollectionType => null;
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
public override bool SupportsPeople => false;
public override bool CanDelete()
{
return false;
@@ -22,11 +30,5 @@ namespace MediaBrowser.Controller.Entities
{
return true;
}
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
public override bool SupportsPeople => false;
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -10,6 +12,11 @@ namespace MediaBrowser.Controller.Entities
{
public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries
{
public Book()
{
this.RunTimeTicks = TimeSpan.TicksPerSecond;
}
[JsonIgnore]
public override string MediaType => Model.Entities.MediaType.Book;
@@ -26,11 +33,6 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public Guid SeriesId { get; set; }
public Book()
{
this.RunTimeTicks = TimeSpan.TicksPerSecond;
}
public string FindSeriesSortName()
{
return SeriesName;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -8,7 +10,7 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Json;
using Jellyfin.Extensions.Json;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
@@ -27,30 +29,65 @@ namespace MediaBrowser.Controller.Entities
public class CollectionFolder : Folder, ICollectionFolder
{
private static readonly JsonSerializerOptions _jsonOptions = JsonDefaults.Options;
public static IXmlSerializer XmlSerializer { get; set; }
public static IServerApplicationHost ApplicationHost { get; set; }
private static readonly Dictionary<string, LibraryOptions> _libraryOptions = new Dictionary<string, LibraryOptions>();
private bool _requiresRefresh;
/// <summary>
/// Initializes a new instance of the <see cref="CollectionFolder"/> class.
/// </summary>
public CollectionFolder()
{
PhysicalLocationsList = Array.Empty<string>();
PhysicalFolderIds = Array.Empty<Guid>();
}
/// <summary>
/// Gets the display preferences id.
/// </summary>
/// <remarks>
/// Allow different display preferences for each collection folder.
/// </remarks>
/// <value>The display prefs id.</value>
[JsonIgnore]
public override Guid DisplayPreferencesId => Id;
[JsonIgnore]
public override string[] PhysicalLocations => PhysicalLocationsList;
public string[] PhysicalLocationsList { get; set; }
public Guid[] PhysicalFolderIds { get; set; }
public static IXmlSerializer XmlSerializer { get; set; }
public static IServerApplicationHost ApplicationHost { get; set; }
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
public string CollectionType { get; set; }
/// <summary>
/// Gets the item's children.
/// </summary>
/// <remarks>
/// Our children are actually just references to the ones in the physical root...
/// </remarks>
/// <value>The actual children.</value>
[JsonIgnore]
public override IEnumerable<BaseItem> Children => GetActualChildren();
[JsonIgnore]
public override bool SupportsPeople => false;
public override bool CanDelete()
{
return false;
}
public string CollectionType { get; set; }
private static readonly Dictionary<string, LibraryOptions> LibraryOptions = new Dictionary<string, LibraryOptions>();
public LibraryOptions GetLibraryOptions()
{
return GetLibraryOptions(Path);
@@ -60,9 +97,7 @@ namespace MediaBrowser.Controller.Entities
{
try
{
var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions;
if (result == null)
if (XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) is not LibraryOptions result)
{
return new LibraryOptions();
}
@@ -105,12 +140,12 @@ namespace MediaBrowser.Controller.Entities
public static LibraryOptions GetLibraryOptions(string path)
{
lock (LibraryOptions)
lock (_libraryOptions)
{
if (!LibraryOptions.TryGetValue(path, out var options))
if (!_libraryOptions.TryGetValue(path, out var options))
{
options = LoadLibraryOptions(path);
LibraryOptions[path] = options;
_libraryOptions[path] = options;
}
return options;
@@ -119,9 +154,9 @@ namespace MediaBrowser.Controller.Entities
public static void SaveLibraryOptions(string path, LibraryOptions options)
{
lock (LibraryOptions)
lock (_libraryOptions)
{
LibraryOptions[path] = options;
_libraryOptions[path] = options;
var clone = JsonSerializer.Deserialize<LibraryOptions>(JsonSerializer.SerializeToUtf8Bytes(options, _jsonOptions), _jsonOptions);
foreach (var mediaPath in clone.PathInfos)
@@ -138,37 +173,22 @@ namespace MediaBrowser.Controller.Entities
public static void OnCollectionFolderChange()
{
lock (LibraryOptions)
lock (_libraryOptions)
{
LibraryOptions.Clear();
_libraryOptions.Clear();
}
}
/// <summary>
/// Allow different display preferences for each collection folder.
/// </summary>
/// <value>The display prefs id.</value>
[JsonIgnore]
public override Guid DisplayPreferencesId => Id;
[JsonIgnore]
public override string[] PhysicalLocations => PhysicalLocationsList;
public override bool IsSaveLocalMetadataEnabled()
{
return true;
}
public string[] PhysicalLocationsList { get; set; }
public Guid[] PhysicalFolderIds { get; set; }
protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService)
{
return CreateResolveArgs(directoryService, true).FileSystemChildren;
}
private bool _requiresRefresh;
public override bool RequiresRefresh()
{
var changed = base.RequiresRefresh() || _requiresRefresh;
@@ -200,9 +220,9 @@ namespace MediaBrowser.Controller.Entities
return changed;
}
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var changed = base.BeforeMetadataRefresh(replaceAllMetdata) || _requiresRefresh;
var changed = base.BeforeMetadataRefresh(replaceAllMetadata) || _requiresRefresh;
_requiresRefresh = false;
return changed;
}
@@ -271,7 +291,6 @@ namespace MediaBrowser.Controller.Entities
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService)
{
FileInfo = FileSystem.GetDirectoryInfo(path),
Path = path,
Parent = GetParent() as Folder,
CollectionType = CollectionType
};
@@ -298,27 +317,20 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes
/// ***Currently does not contain logic to maintain items that are unavailable in the file system***
/// ***Currently does not contain logic to maintain items that are unavailable in the file system***.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="refreshChildMetadata">if set to <c>true</c> [refresh child metadata].</param>
/// <param name="refreshOptions">The refresh options.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
/// <summary>
/// Our children are actually just references to the ones in the physical root...
/// </summary>
/// <value>The actual children.</value>
[JsonIgnore]
public override IEnumerable<BaseItem> Children => GetActualChildren();
public IEnumerable<BaseItem> GetActualChildren()
{
return GetPhysicalFolders(true).SelectMany(c => c.Children);
@@ -355,9 +367,7 @@ namespace MediaBrowser.Controller.Entities
if (result.Count == 0)
{
var folder = LibraryManager.FindByPath(path, true) as Folder;
if (folder != null)
if (LibraryManager.FindByPath(path, true) is Folder folder)
{
result.Add(folder);
}
@@ -365,8 +375,5 @@ namespace MediaBrowser.Controller.Entities
return result;
}
[JsonIgnore]
public override bool SupportsPeople => false;
}
}

View File

@@ -1,6 +1,8 @@
#nullable disable
using System;
using System.Linq;
using MediaBrowser.Common.Extensions;
using Jellyfin.Extensions;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
@@ -13,6 +15,8 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Adds the trailer URL.
/// </summary>
/// <param name="item">Media item.</param>
/// <param name="url">Trailer URL.</param>
public static void AddTrailerUrl(this BaseItem item, string url)
{
if (string.IsNullOrEmpty(url))

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1002, CA1721, CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -35,6 +37,11 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Folder : BaseItem
{
public Folder()
{
LinkedChildren = Array.Empty<LinkedChild>();
}
public static IUserViewManager UserViewManager { get; set; }
/// <summary>
@@ -48,11 +55,6 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public DateTime? DateLastMediaAdded { get; set; }
public Folder()
{
LinkedChildren = Array.Empty<LinkedChild>();
}
[JsonIgnore]
public override bool SupportsThemeMedia => true;
@@ -84,6 +86,87 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public virtual bool SupportsDateLastMediaAdded => false;
[JsonIgnore]
public override string FileNameWithoutExtension
{
get
{
if (IsFileProtocol)
{
return System.IO.Path.GetFileName(Path);
}
return null;
}
}
/// <summary>
/// Gets the actual children.
/// </summary>
/// <value>The actual children.</value>
[JsonIgnore]
public virtual IEnumerable<BaseItem> Children => LoadChildren();
/// <summary>
/// Gets thread-safe access to all recursive children of this folder - without regard to user.
/// </summary>
/// <value>The recursive children.</value>
[JsonIgnore]
public IEnumerable<BaseItem> RecursiveChildren => GetRecursiveChildren();
[JsonIgnore]
protected virtual bool SupportsShortcutChildren => false;
protected virtual bool FilterLinkedChildrenPerUser => false;
[JsonIgnore]
protected override bool SupportsOwnedItems => base.SupportsOwnedItems || SupportsShortcutChildren;
[JsonIgnore]
public virtual bool SupportsUserDataFromChildren
{
get
{
// These are just far too slow.
if (this is ICollectionFolder)
{
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;
}
if (this is IItemByName)
{
if (this is not IHasDualAccess hasDualAccess || hasDualAccess.IsAccessedByName)
{
return false;
}
}
return true;
}
}
public static ICollectionManager CollectionManager { get; set; }
public override bool CanDelete()
{
if (IsRoot)
@@ -106,20 +189,6 @@ namespace MediaBrowser.Controller.Entities
return baseResult;
}
[JsonIgnore]
public override string FileNameWithoutExtension
{
get
{
if (IsFileProtocol)
{
return System.IO.Path.GetFileName(Path);
}
return null;
}
}
protected override bool IsAllowTagFilterEnforced()
{
if (this is ICollectionFolder)
@@ -135,17 +204,12 @@ namespace MediaBrowser.Controller.Entities
return true;
}
[JsonIgnore]
protected virtual bool SupportsShortcutChildren => false;
/// <summary>
/// Adds the child.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
/// <exception cref="InvalidOperationException">Unable to add + item.Name</exception>
public void AddChild(BaseItem item, CancellationToken cancellationToken)
/// <exception cref="InvalidOperationException">Unable to add + item.Name.</exception>
public void AddChild(BaseItem item)
{
item.SetParent(this);
@@ -167,23 +231,9 @@ namespace MediaBrowser.Controller.Entities
LibraryManager.CreateItem(item, this);
}
/// <summary>
/// Gets the actual children.
/// </summary>
/// <value>The actual children.</value>
[JsonIgnore]
public virtual IEnumerable<BaseItem> Children => LoadChildren();
/// <summary>
/// thread-safe access to all recursive children of this folder - without regard to user.
/// </summary>
/// <value>The recursive children.</value>
[JsonIgnore]
public IEnumerable<BaseItem> RecursiveChildren => GetRecursiveChildren();
public override bool IsVisible(User user)
{
if (this is ICollectionFolder && !(this is BasePluginFolder))
if (this is ICollectionFolder && this is not BasePluginFolder)
{
var blockedMediaFolders = user.GetPreferenceValues<Guid>(PreferenceKind.BlockedMediaFolders);
if (blockedMediaFolders.Length > 0)
@@ -210,6 +260,7 @@ namespace MediaBrowser.Controller.Entities
/// Loads our children. Validation will occur externally.
/// We want this synchronous.
/// </summary>
/// <returns>Returns children.</returns>
protected virtual List<BaseItem> LoadChildren()
{
// logger.LogDebug("Loading children from {0} {1} {2}", GetType().Name, Id, Path);
@@ -224,20 +275,20 @@ namespace MediaBrowser.Controller.Entities
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken)
{
return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(FileSystem)));
return ValidateChildren(progress, new MetadataRefreshOptions(new DirectoryService(FileSystem)), cancellationToken: cancellationToken);
}
/// <summary>
/// Validates that the children of the folder still exist.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="metadataRefreshOptions">The metadata refresh options.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken, MetadataRefreshOptions metadataRefreshOptions, bool recursive = true)
public Task ValidateChildren(IProgress<double> progress, MetadataRefreshOptions metadataRefreshOptions, bool recursive = true, CancellationToken cancellationToken = default)
{
return ValidateChildrenInternal(progress, cancellationToken, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService);
return ValidateChildrenInternal(progress, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService, cancellationToken);
}
private Dictionary<Guid, BaseItem> GetActualChildrenDictionary()
@@ -277,13 +328,13 @@ namespace MediaBrowser.Controller.Entities
/// Validates the children internal.
/// </summary>
/// <param name="progress">The progress.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="recursive">if set to <c>true</c> [recursive].</param>
/// <param name="refreshChildMetadata">if set to <c>true</c> [refresh child metadata].</param>
/// <param name="refreshOptions">The refresh options.</param>
/// <param name="directoryService">The directory service.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
protected virtual async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
protected virtual async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
if (recursive)
{
@@ -292,7 +343,7 @@ namespace MediaBrowser.Controller.Entities
try
{
await ValidateChildrenInternal2(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService).ConfigureAwait(false);
await ValidateChildrenInternal2(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken).ConfigureAwait(false);
}
finally
{
@@ -303,7 +354,7 @@ namespace MediaBrowser.Controller.Entities
}
}
private async Task ValidateChildrenInternal2(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
private async Task ValidateChildrenInternal2(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -525,7 +576,7 @@ namespace MediaBrowser.Controller.Entities
private Task ValidateSubFolders(IList<Folder> children, IDirectoryService directoryService, IProgress<double> progress, CancellationToken cancellationToken)
{
return RunTasks(
(folder, innerProgress) => folder.ValidateChildrenInternal(innerProgress, cancellationToken, true, false, null, directoryService),
(folder, innerProgress) => folder.ValidateChildrenInternal(innerProgress, true, false, null, directoryService, cancellationToken),
children,
progress,
cancellationToken);
@@ -594,6 +645,8 @@ namespace MediaBrowser.Controller.Entities
/// Get the children of this folder from the actual file system.
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <param name="directoryService">The directory service to use for operation.</param>
/// <returns>Returns set of base items.</returns>
protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
{
var collectionType = LibraryManager.GetContentType(this);
@@ -620,7 +673,7 @@ namespace MediaBrowser.Controller.Entities
{
if (LinkedChildren.Length > 0)
{
if (!(this is ICollectionFolder))
if (this is not ICollectionFolder)
{
return GetChildren(user, true).Count;
}
@@ -677,7 +730,7 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(items, query, true);
}
if (!(this is UserRootFolder) && !(this is AggregateFolder) && query.ParentId == Guid.Empty)
if (this is not UserRootFolder && this is not AggregateFolder && query.ParentId == Guid.Empty)
{
query.Parent = this;
}
@@ -752,7 +805,7 @@ namespace MediaBrowser.Controller.Entities
{
if (LinkedChildren.Length > 0)
{
if (!(this is ICollectionFolder))
if (this is not ICollectionFolder)
{
Logger.LogDebug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name);
return true;
@@ -938,14 +991,18 @@ namespace MediaBrowser.Controller.Entities
}
else
{
items = GetChildren(user, true).Where(filter);
// need to pass this param to the children.
var childQuery = new InternalItemsQuery
{
DisplayAlbumFolders = query.DisplayAlbumFolders
};
items = GetChildren(user, true, childQuery).Where(filter);
}
return PostFilterAndSort(items, query, true);
}
public static ICollectionManager CollectionManager { get; set; }
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query, bool enableSorting)
{
var user = query.User;
@@ -958,17 +1015,17 @@ namespace MediaBrowser.Controller.Entities
if (!string.IsNullOrEmpty(query.NameStartsWithOrGreater))
{
items = items.Where(i => string.Compare(query.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1);
items = items.Where(i => string.Compare(query.NameStartsWithOrGreater, i.SortName, StringComparison.InvariantCultureIgnoreCase) < 1);
}
if (!string.IsNullOrEmpty(query.NameStartsWith))
{
items = items.Where(i => i.SortName.StartsWith(query.NameStartsWith, StringComparison.OrdinalIgnoreCase));
items = items.Where(i => i.SortName.StartsWith(query.NameStartsWith, StringComparison.InvariantCultureIgnoreCase));
}
if (!string.IsNullOrEmpty(query.NameLessThan))
{
items = items.Where(i => string.Compare(query.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1);
items = items.Where(i => string.Compare(query.NameLessThan, i.SortName, StringComparison.InvariantCultureIgnoreCase) == 1);
}
// This must be the last filter
@@ -1274,10 +1331,23 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Adds the children to list.
/// </summary>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query)
{
foreach (var child in GetEligibleChildrenForRecursiveChildren(user))
// If Query.AlbumFolders is set, then enforce the format as per the db in that it permits sub-folders in music albums.
IEnumerable<BaseItem> children = null;
if ((query?.DisplayAlbumFolders ?? false) && (this is MusicAlbum))
{
children = Children;
query = null;
}
// If there are not sub-folders, proceed as normal.
if (children == null)
{
children = GetEligibleChildrenForRecursiveChildren(user);
}
foreach (var child in children)
{
bool? isVisibleToUser = null;
@@ -1317,18 +1387,6 @@ namespace MediaBrowser.Controller.Entities
}
}
/// <summary>
/// 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>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="ArgumentNullException"></exception>
public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
{
return GetRecursiveChildren(user, null);
}
public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
{
if (user == null)
@@ -1426,8 +1484,6 @@ namespace MediaBrowser.Controller.Entities
return list;
}
protected virtual bool FilterLinkedChildrenPerUser => false;
public bool ContainsLinkedChildByItemId(Guid itemId)
{
var linkedChildren = LinkedChildren;
@@ -1489,7 +1545,7 @@ namespace MediaBrowser.Controller.Entities
var childOwner = child.GetOwner() ?? child;
if (childOwner != null && !(child is IItemByName))
if (child is not IItemByName)
{
var childProtocol = childOwner.PathProtocol;
if (!childProtocol.HasValue || childProtocol.Value != Model.MediaInfo.MediaProtocol.File)
@@ -1528,9 +1584,6 @@ namespace MediaBrowser.Controller.Entities
.Where(i => i.Item2 != null);
}
[JsonIgnore]
protected override bool SupportsOwnedItems => base.SupportsOwnedItems || SupportsShortcutChildren;
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var changesFound = false;
@@ -1551,7 +1604,8 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Refreshes the linked children.
/// </summary>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
/// <param name="fileSystemChildren">The enumerable of file system metadata.</param>
/// <returns><c>true</c> if the linked children were updated, <c>false</c> otherwise.</returns>
protected virtual bool RefreshLinkedChildren(IEnumerable<FileSystemMetadata> fileSystemChildren)
{
if (SupportsShortcutChildren)
@@ -1615,7 +1669,6 @@ namespace MediaBrowser.Controller.Entities
/// <param name="user">The user.</param>
/// <param name="datePlayed">The date played.</param>
/// <param name="resetPosition">if set to <c>true</c> [reset position].</param>
/// <returns>Task.</returns>
public override void MarkPlayed(
User user,
DateTime? datePlayed,
@@ -1657,7 +1710,6 @@ namespace MediaBrowser.Controller.Entities
/// Marks the unplayed.
/// </summary>
/// <param name="user">The user.</param>
/// <returns>Task.</returns>
public override void MarkUnplayed(User user)
{
var itemsResult = GetItemList(new InternalItemsQuery
@@ -1694,51 +1746,6 @@ namespace MediaBrowser.Controller.Entities
return !IsPlayed(user);
}
[JsonIgnore]
public virtual bool SupportsUserDataFromChildren
{
get
{
// These are just far too slow.
if (this is ICollectionFolder)
{
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)
{
var hasDualAccess = this as IHasDualAccess;
if (hasDualAccess == null || hasDualAccess.IsAccessedByName)
{
return false;
}
}
return true;
}
}
public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, DtoOptions fields)
{
if (!SupportsUserDataFromChildren)
@@ -1768,20 +1775,15 @@ namespace MediaBrowser.Controller.Entities
{
EnableImages = false
}
});
}).TotalRecordCount;
double unplayedCount = unplayedQueryResult.TotalRecordCount;
dto.UnplayedItemCount = unplayedQueryResult;
dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount;
if (itemDto != null && itemDto.RecursiveItemCount.HasValue)
if (itemDto?.RecursiveItemCount > 0)
{
if (itemDto.RecursiveItemCount.Value > 0)
{
var unplayedPercentage = (unplayedCount / itemDto.RecursiveItemCount.Value) * 100;
dto.PlayedPercentage = 100 - unplayedPercentage;
dto.Played = dto.PlayedPercentage.Value >= 100;
}
var unplayedPercentage = ((double)unplayedQueryResult / itemDto.RecursiveItemCount.Value) * 100;
dto.PlayedPercentage = 100 - unplayedPercentage;
dto.Played = dto.PlayedPercentage.Value >= 100;
}
else
{

View File

@@ -1,10 +1,12 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Diacritics.Extensions;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Extensions;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
@@ -14,6 +16,23 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Genre : BaseItem, IItemByName
{
/// <summary>
/// Gets 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;
[JsonIgnore]
public override bool IsDisplayedAsFolder => true;
[JsonIgnore]
public override bool SupportsAncestors => false;
[JsonIgnore]
public override bool SupportsPeople => false;
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -32,20 +51,6 @@ namespace MediaBrowser.Controller.Entities
return 1;
}
/// <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;
[JsonIgnore]
public override bool IsDisplayedAsFolder => true;
[JsonIgnore]
public override bool SupportsAncestors => false;
public override bool IsSaveLocalMetadataEnabled()
{
return true;
@@ -70,9 +75,6 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.GetItemList(query);
}
[JsonIgnore]
public override bool SupportsPeople => false;
public static string GetPath(string name)
{
return GetPath(name, true);
@@ -106,11 +108,13 @@ namespace MediaBrowser.Controller.Entities
}
/// <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 if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
/// <param name="replaceAllMetadata">Whether to replace all metadata.</param>
/// <returns>true if the item has change, else false.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1819, CS1591
using System;

View File

@@ -1,3 +1,5 @@
#nullable disable
namespace MediaBrowser.Controller.Entities
{
/// <summary>

View File

@@ -1,3 +1,5 @@
#nullable disable
namespace MediaBrowser.Controller.Entities
{
/// <summary>

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -18,6 +20,8 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Gets the media sources.
/// </summary>
/// <param name="enablePathSubstitution"><c>true</c> to enable path substitution, <c>false</c> to not.</param>
/// <returns>A list of media sources.</returns>
List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
List<MediaStream> GetMediaStreams();

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using MediaBrowser.Model.LiveTv;

View File

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

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -7,7 +9,7 @@ namespace MediaBrowser.Controller.Entities
public interface IHasSeries
{
/// <summary>
/// Gets the name of the series.
/// Gets or sets the name of the series.
/// </summary>
/// <value>The name of the series.</value>
string SeriesName { get; set; }

View File

@@ -0,0 +1,11 @@
#nullable disable
#pragma warning disable CA1819, CS1591
namespace MediaBrowser.Controller.Entities
{
public interface IHasShares
{
Share[] Shares { get; set; }
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -37,6 +39,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Gets the trailer count.
/// </summary>
/// <param name="item">Media item.</param>
/// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
public static int GetTrailerCount(this IHasTrailers item)
=> item.LocalTrailerIds.Count + item.RemoteTrailerIds.Count;
@@ -44,6 +47,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Gets the trailer ids.
/// </summary>
/// <param name="item">Media item.</param>
/// <returns><see cref="IReadOnlyList{Guid}" />.</returns>
public static IReadOnlyList<Guid> GetTrailerIds(this IHasTrailers item)
{
@@ -68,6 +72,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Gets the trailers.
/// </summary>
/// <param name="item">Media item.</param>
/// <returns><see cref="IReadOnlyList{BaseItem}" />.</returns>
public static IReadOnlyList<BaseItem> GetTrailers(this IHasTrailers item)
{

View File

@@ -1,4 +1,4 @@
#pragma warning disable CS1591
#pragma warning disable CA1044, CA1819, CA2227, CS1591
using System;
using System.Collections.Generic;
@@ -12,15 +12,64 @@ namespace MediaBrowser.Controller.Entities
{
public class InternalItemsQuery
{
public InternalItemsQuery()
{
AlbumArtistIds = Array.Empty<Guid>();
AlbumIds = Array.Empty<Guid>();
AncestorIds = Array.Empty<Guid>();
ArtistIds = Array.Empty<Guid>();
BlockUnratedItems = Array.Empty<UnratedItem>();
BoxSetLibraryFolders = Array.Empty<Guid>();
ChannelIds = Array.Empty<Guid>();
ContributingArtistIds = Array.Empty<Guid>();
DtoOptions = new DtoOptions();
EnableTotalRecordCount = true;
ExcludeArtistIds = Array.Empty<Guid>();
ExcludeInheritedTags = Array.Empty<string>();
ExcludeItemIds = Array.Empty<Guid>();
ExcludeItemTypes = Array.Empty<string>();
ExcludeTags = Array.Empty<string>();
GenreIds = Array.Empty<Guid>();
Genres = Array.Empty<string>();
GroupByPresentationUniqueKey = true;
ImageTypes = Array.Empty<ImageType>();
IncludeItemTypes = Array.Empty<string>();
ItemIds = Array.Empty<Guid>();
MediaTypes = Array.Empty<string>();
MinSimilarityScore = 20;
OfficialRatings = Array.Empty<string>();
OrderBy = Array.Empty<ValueTuple<string, SortOrder>>();
PersonIds = Array.Empty<Guid>();
PersonTypes = Array.Empty<string>();
PresetViews = Array.Empty<string>();
SeriesStatuses = Array.Empty<SeriesStatus>();
SourceTypes = Array.Empty<SourceType>();
StudioIds = Array.Empty<Guid>();
Tags = Array.Empty<string>();
TopParentIds = Array.Empty<Guid>();
TrailerTypes = Array.Empty<TrailerType>();
VideoTypes = Array.Empty<VideoType>();
Years = Array.Empty<int>();
}
public InternalItemsQuery(User? user)
: this()
{
if (user != null)
{
SetUser(user);
}
}
public bool Recursive { get; set; }
public int? StartIndex { get; set; }
public int? Limit { get; set; }
public User User { get; set; }
public User? User { get; set; }
public BaseItem SimilarTo { get; set; }
public BaseItem? SimilarTo { get; set; }
public bool? IsFolder { get; set; }
@@ -56,23 +105,23 @@ namespace MediaBrowser.Controller.Entities
public bool? CollapseBoxSetItems { get; set; }
public string NameStartsWithOrGreater { get; set; }
public string? NameStartsWithOrGreater { get; set; }
public string NameStartsWith { get; set; }
public string? NameStartsWith { get; set; }
public string NameLessThan { get; set; }
public string? NameLessThan { get; set; }
public string NameContains { get; set; }
public string? NameContains { get; set; }
public string MinSortName { get; set; }
public string? MinSortName { get; set; }
public string PresentationUniqueKey { get; set; }
public string? PresentationUniqueKey { get; set; }
public string Path { get; set; }
public string? Path { get; set; }
public string Name { get; set; }
public string? Name { get; set; }
public string Person { get; set; }
public string? Person { get; set; }
public Guid[] PersonIds { get; set; }
@@ -80,7 +129,7 @@ namespace MediaBrowser.Controller.Entities
public Guid[] ExcludeItemIds { get; set; }
public string AdjacentTo { get; set; }
public string? AdjacentTo { get; set; }
public string[] PersonTypes { get; set; }
@@ -180,29 +229,12 @@ namespace MediaBrowser.Controller.Entities
public Guid ParentId { get; set; }
public string ParentType { get; set; }
public string? ParentType { get; set; }
public Guid[] AncestorIds { get; set; }
public Guid[] TopParentIds { get; set; }
public BaseItem Parent
{
set
{
if (value == null)
{
ParentId = Guid.Empty;
ParentType = null;
}
else
{
ParentId = value.Id;
ParentType = value.GetType().Name;
}
}
}
public string[] PresetViews { get; set; }
public TrailerType[] TrailerTypes { get; set; }
@@ -211,9 +243,9 @@ namespace MediaBrowser.Controller.Entities
public SeriesStatus[] SeriesStatuses { get; set; }
public string ExternalSeriesId { get; set; }
public string? ExternalSeriesId { get; set; }
public string ExternalId { get; set; }
public string? ExternalId { get; set; }
public Guid[] AlbumIds { get; set; }
@@ -221,9 +253,9 @@ namespace MediaBrowser.Controller.Entities
public Guid[] ExcludeArtistIds { get; set; }
public string AncestorWithPresentationUniqueKey { get; set; }
public string? AncestorWithPresentationUniqueKey { get; set; }
public string SeriesPresentationUniqueKey { get; set; }
public string? SeriesPresentationUniqueKey { get; set; }
public bool GroupByPresentationUniqueKey { get; set; }
@@ -233,7 +265,7 @@ namespace MediaBrowser.Controller.Entities
public bool ForceDirect { get; set; }
public Dictionary<string, string> ExcludeProviderIds { get; set; }
public Dictionary<string, string>? ExcludeProviderIds { get; set; }
public bool EnableGroupByMetadataKey { get; set; }
@@ -251,13 +283,13 @@ namespace MediaBrowser.Controller.Entities
public int MinSimilarityScore { get; set; }
public string HasNoAudioTrackWithLanguage { get; set; }
public string? HasNoAudioTrackWithLanguage { get; set; }
public string HasNoInternalSubtitleTrackWithLanguage { get; set; }
public string? HasNoInternalSubtitleTrackWithLanguage { get; set; }
public string HasNoExternalSubtitleTrackWithLanguage { get; set; }
public string? HasNoExternalSubtitleTrackWithLanguage { get; set; }
public string HasNoSubtitleTrackWithLanguage { get; set; }
public string? HasNoSubtitleTrackWithLanguage { get; set; }
public bool? IsDeadArtist { get; set; }
@@ -265,74 +297,29 @@ namespace MediaBrowser.Controller.Entities
public bool? IsDeadPerson { get; set; }
public InternalItemsQuery()
{
AlbumArtistIds = Array.Empty<Guid>();
AlbumIds = Array.Empty<Guid>();
AncestorIds = Array.Empty<Guid>();
ArtistIds = Array.Empty<Guid>();
BlockUnratedItems = Array.Empty<UnratedItem>();
BoxSetLibraryFolders = Array.Empty<Guid>();
ChannelIds = Array.Empty<Guid>();
ContributingArtistIds = Array.Empty<Guid>();
DtoOptions = new DtoOptions();
EnableTotalRecordCount = true;
ExcludeArtistIds = Array.Empty<Guid>();
ExcludeInheritedTags = Array.Empty<string>();
ExcludeItemIds = Array.Empty<Guid>();
ExcludeItemTypes = Array.Empty<string>();
ExcludeProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
ExcludeTags = Array.Empty<string>();
GenreIds = Array.Empty<Guid>();
Genres = Array.Empty<string>();
GroupByPresentationUniqueKey = true;
HasAnyProviderId = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
ImageTypes = Array.Empty<ImageType>();
IncludeItemTypes = Array.Empty<string>();
ItemIds = Array.Empty<Guid>();
MediaTypes = Array.Empty<string>();
MinSimilarityScore = 20;
OfficialRatings = Array.Empty<string>();
OrderBy = Array.Empty<ValueTuple<string, SortOrder>>();
PersonIds = Array.Empty<Guid>();
PersonTypes = Array.Empty<string>();
PresetViews = Array.Empty<string>();
SeriesStatuses = Array.Empty<SeriesStatus>();
SourceTypes = Array.Empty<SourceType>();
StudioIds = Array.Empty<Guid>();
Tags = Array.Empty<string>();
TopParentIds = Array.Empty<Guid>();
TrailerTypes = Array.Empty<TrailerType>();
VideoTypes = Array.Empty<VideoType>();
Years = Array.Empty<int>();
}
/// <summary>
/// Gets or sets a value indicating whether album sub-folders should be returned if they exist.
/// </summary>
public bool? DisplayAlbumFolders { get; set; }
public InternalItemsQuery(User user)
: this()
public BaseItem? Parent
{
SetUser(user);
}
public void SetUser(User user)
{
if (user != null)
set
{
MaxParentalRating = user.MaxParentalAgeRating;
if (MaxParentalRating.HasValue)
if (value == null)
{
BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems)
.Where(i => i != UnratedItem.Other.ToString())
.Select(e => Enum.Parse<UnratedItem>(e, true)).ToArray();
ParentId = Guid.Empty;
ParentType = null;
}
else
{
ParentId = value.Id;
ParentType = value.GetType().Name;
}
ExcludeInheritedTags = user.GetPreference(PreferenceKind.BlockedTags);
User = user;
}
}
public Dictionary<string, string> HasAnyProviderId { get; set; }
public Dictionary<string, string>? HasAnyProviderId { get; set; }
public Guid[] AlbumArtistIds { get; set; }
@@ -354,8 +341,25 @@ namespace MediaBrowser.Controller.Entities
public int? MinWidth { get; set; }
public string SearchTerm { get; set; }
public string? SearchTerm { get; set; }
public string SeriesTimerId { get; set; }
public string? SeriesTimerId { get; set; }
public void SetUser(User user)
{
MaxParentalRating = user.MaxParentalAgeRating;
if (MaxParentalRating.HasValue)
{
string other = UnratedItem.Other.ToString();
BlockUnratedItems = user.GetPreference(PreferenceKind.BlockUnratedItems)
.Where(i => i != other)
.Select(e => Enum.Parse<UnratedItem>(e, true)).ToArray();
}
ExcludeInheritedTags = user.GetPreference(PreferenceKind.BlockedTags);
User = user;
}
}
}

View File

@@ -1,12 +1,26 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using Jellyfin.Data.Entities;
namespace MediaBrowser.Controller.Entities
{
public class InternalPeopleQuery
{
public InternalPeopleQuery()
: this(Array.Empty<string>(), Array.Empty<string>())
{
}
public InternalPeopleQuery(IReadOnlyList<string> personTypes, IReadOnlyList<string> excludePersonTypes)
{
PersonTypes = personTypes;
ExcludePersonTypes = excludePersonTypes;
}
/// <summary>
/// Gets or sets the maximum number of items the query should return.
/// </summary>
@@ -14,9 +28,9 @@ namespace MediaBrowser.Controller.Entities
public Guid ItemId { get; set; }
public string[] PersonTypes { get; set; }
public IReadOnlyList<string> PersonTypes { get; }
public string[] ExcludePersonTypes { get; set; }
public IReadOnlyList<string> ExcludePersonTypes { get; }
public int? MaxListOrder { get; set; }
@@ -27,11 +41,5 @@ namespace MediaBrowser.Controller.Entities
public User User { get; set; }
public bool? IsFavorite { get; set; }
public InternalPeopleQuery()
{
PersonTypes = Array.Empty<string>();
ExcludePersonTypes = Array.Empty<string>();
}
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;

View File

@@ -1,15 +1,20 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text.Json.Serialization;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Controller.Entities
{
public class LinkedChild
{
public LinkedChild()
{
Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
}
public string Path { get; set; }
public LinkedChildType Type { get; set; }
@@ -20,7 +25,7 @@ namespace MediaBrowser.Controller.Entities
public string Id { get; set; }
/// <summary>
/// Serves as a cache.
/// Gets or sets the linked item id.
/// </summary>
public Guid? ItemId { get; set; }
@@ -39,41 +44,5 @@ namespace MediaBrowser.Controller.Entities
return child;
}
public LinkedChild()
{
Id = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
}
}
public enum LinkedChildType
{
Manual = 0,
Shortcut = 1
}
public class LinkedChildComparer : IEqualityComparer<LinkedChild>
{
private readonly IFileSystem _fileSystem;
public LinkedChildComparer(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public bool Equals(LinkedChild x, LinkedChild y)
{
if (x.Type == y.Type)
{
return _fileSystem.AreEqual(x.Path, y.Path);
}
return false;
}
public int GetHashCode(LinkedChild obj)
{
return ((obj.Path ?? string.Empty) + (obj.LibraryItemId ?? string.Empty) + obj.Type).GetHashCode();
}
}
}

View File

@@ -0,0 +1,35 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using MediaBrowser.Model.IO;
namespace MediaBrowser.Controller.Entities
{
public class LinkedChildComparer : IEqualityComparer<LinkedChild>
{
private readonly IFileSystem _fileSystem;
public LinkedChildComparer(IFileSystem fileSystem)
{
_fileSystem = fileSystem;
}
public bool Equals(LinkedChild x, LinkedChild y)
{
if (x.Type == y.Type)
{
return _fileSystem.AreEqual(x.Path, y.Path);
}
return false;
}
public int GetHashCode(LinkedChild obj)
{
return ((obj.Path ?? string.Empty) + (obj.LibraryItemId ?? string.Empty) + obj.Type).GetHashCode(StringComparison.Ordinal);
}
}
}

View File

@@ -0,0 +1,18 @@
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// The linked child type.
/// </summary>
public enum LinkedChildType
{
/// <summary>
/// Manually linked child.
/// </summary>
Manual = 0,
/// <summary>
/// Shortcut linked child.
/// </summary>
Shortcut = 1
}
}

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1721, CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -47,6 +49,30 @@ namespace MediaBrowser.Controller.Entities.Movies
/// <value>The display order.</value>
public string DisplayOrder { get; set; }
[JsonIgnore]
private bool IsLegacyBoxSet
{
get
{
if (string.IsNullOrEmpty(Path))
{
return false;
}
if (LinkedChildren.Length > 0)
{
return false;
}
return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path);
}
}
[JsonIgnore]
public override bool IsPreSorted => true;
public Guid[] LibraryFolderIds { get; set; }
protected override bool GetBlockUnratedValue(User user)
{
return user.GetPreferenceValues<UnratedItem>(PreferenceKind.BlockUnratedItems).Contains(UnratedItem.Movie);
@@ -81,28 +107,6 @@ namespace MediaBrowser.Controller.Entities.Movies
return new List<BaseItem>();
}
[JsonIgnore]
private bool IsLegacyBoxSet
{
get
{
if (string.IsNullOrEmpty(Path))
{
return false;
}
if (LinkedChildren.Length > 0)
{
return false;
}
return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path);
}
}
[JsonIgnore]
public override bool IsPreSorted => true;
public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders)
{
return true;
@@ -189,8 +193,6 @@ namespace MediaBrowser.Controller.Entities.Movies
return IsVisible(user);
}
public Guid[] LibraryFolderIds { get; set; }
private Guid[] GetLibraryFolderIds(User user)
{
return LibraryManager.GetUserRootFolder().GetChildren(user, true)
@@ -217,8 +219,7 @@ namespace MediaBrowser.Controller.Entities.Movies
private IEnumerable<BaseItem> FlattenItems(BaseItem item, List<Guid> expandedFolders)
{
var boxset = item as BoxSet;
if (boxset != null)
if (item is BoxSet boxset)
{
if (!expandedFolders.Contains(item.Id))
{

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -142,9 +144,9 @@ namespace MediaBrowser.Controller.Entities.Movies
}
/// <inheritdoc />
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
if (!ProductionYear.HasValue)
{

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -11,15 +13,15 @@ namespace MediaBrowser.Controller.Entities
{
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasLookupInfo<MusicVideoInfo>
{
/// <inheritdoc />
[JsonIgnore]
public IReadOnlyList<string> Artists { get; set; }
public MusicVideo()
{
Artists = Array.Empty<string>();
}
/// <inheritdoc />
[JsonIgnore]
public IReadOnlyList<string> Artists { get; set; }
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
@@ -34,9 +36,9 @@ namespace MediaBrowser.Controller.Entities
return info;
}
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
if (!ProductionYear.HasValue)
{

View File

@@ -100,23 +100,5 @@ namespace MediaBrowser.Controller.Entities
existing.SetProviderId(id.Key, id.Value);
}
}
public static bool ContainsPerson(List<PersonInfo> people, string name)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException(nameof(name));
}
foreach (var i in people)
{
if (string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}
}

View File

@@ -1,9 +1,11 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using MediaBrowser.Controller.Extensions;
using Diacritics.Extensions;
using MediaBrowser.Controller.Providers;
using Microsoft.Extensions.Logging;
@@ -14,6 +16,26 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Person : BaseItem, IItemByName, IHasLookupInfo<PersonLookupInfo>
{
/// <summary>
/// Gets 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 a value indicating whether to enable alpha numeric sorting.
/// </summary>
[JsonIgnore]
public override bool EnableAlphaNumericSorting => false;
[JsonIgnore]
public override bool SupportsPeople => false;
[JsonIgnore]
public override bool SupportsAncestors => false;
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -47,14 +69,6 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.GetItemList(query);
}
/// <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;
public override bool CanDelete()
{
return false;
@@ -65,15 +79,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
[JsonIgnore]
public override bool EnableAlphaNumericSorting => false;
[JsonIgnore]
public override bool SupportsPeople => false;
[JsonIgnore]
public override bool SupportsAncestors => false;
public static string GetPath(string name)
{
return GetPath(name, true);
@@ -124,9 +129,11 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
/// <param name="replaceAllMetadata"><c>true</c> to replace all metadata, <c>false</c> to not.</param>
/// <returns><c>true</c> if changes were made, <c>false</c> if not.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA2227, CS1591
using System;
using System.Collections.Generic;

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System.Text.Json.Serialization;
@@ -24,8 +26,7 @@ namespace MediaBrowser.Controller.Entities
var parents = GetParents();
foreach (var parent in parents)
{
var photoAlbum = parent as PhotoAlbum;
if (photoAlbum != null)
if (parent is PhotoAlbum photoAlbum)
{
return photoAlbum;
}
@@ -35,6 +36,30 @@ 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; }
public override bool CanDownload()
{
return true;
@@ -68,29 +93,5 @@ namespace MediaBrowser.Controller.Entities
return base.GetDefaultPrimaryImageAspectRatio();
}
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

@@ -1,12 +1,9 @@
#nullable disable
#pragma warning disable CS1591
namespace MediaBrowser.Controller.Entities
{
public interface IHasShares
{
Share[] Shares { get; set; }
}
public class Share
{
public string UserId { get; set; }

View File

@@ -1,9 +1,11 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using MediaBrowser.Controller.Extensions;
using Diacritics.Extensions;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Controller.Entities
@@ -13,6 +15,23 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Studio : BaseItem, IItemByName
{
/// <summary>
/// Gets 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;
[JsonIgnore]
public override bool IsDisplayedAsFolder => true;
[JsonIgnore]
public override bool SupportsAncestors => false;
[JsonIgnore]
public override bool SupportsPeople => false;
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -26,20 +45,6 @@ namespace MediaBrowser.Controller.Entities
return GetUserDataKeys()[0];
}
/// <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;
[JsonIgnore]
public override bool IsDisplayedAsFolder => true;
[JsonIgnore]
public override bool SupportsAncestors => false;
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 16;
@@ -65,9 +70,6 @@ namespace MediaBrowser.Controller.Entities
return LibraryManager.GetItemList(query);
}
[JsonIgnore]
public override bool SupportsPeople => false;
public static string GetPath(string name)
{
return GetPath(name, true);
@@ -103,9 +105,11 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
/// <param name="replaceAllMetadata"><c>true</c> to replace all metadata, <c>false</c> to not.</param>
/// <returns><c>true</c> if changes were made, <c>false</c> if not.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -32,7 +34,7 @@ namespace MediaBrowser.Controller.Entities.TV
public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary>
/// Gets the season in which it aired.
/// Gets or sets the season in which it aired.
/// </summary>
/// <value>The aired season.</value>
public int? AirsBeforeSeasonNumber { get; set; }
@@ -42,17 +44,11 @@ namespace MediaBrowser.Controller.Entities.TV
public int? AirsBeforeEpisodeNumber { get; set; }
/// <summary>
/// This is the ending episode number for double episodes.
/// Gets or sets the ending episode number for double episodes.
/// </summary>
/// <value>The index number.</value>
public int? IndexNumberEnd { get; set; }
public string FindSeriesSortName()
{
var series = Series;
return series == null ? SeriesName : series.SortName;
}
[JsonIgnore]
protected override bool SupportsOwnedItems => IsStacked || MediaSourceCount > 1;
@@ -74,47 +70,8 @@ namespace MediaBrowser.Controller.Entities.TV
[JsonIgnore]
protected override bool EnableDefaultVideoUserDataKeys => false;
public override double GetDefaultPrimaryImageAspectRatio()
{
// hack for tv plugins
if (SourceType == SourceType.Channel)
{
return 0;
}
return 16.0 / 9;
}
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
var series = Series;
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
{
var seriesUserDataKeys = series.GetUserDataKeys();
var take = seriesUserDataKeys.Count;
if (seriesUserDataKeys.Count > 1)
{
take--;
}
var newList = seriesUserDataKeys.GetRange(0, take);
var suffix = ParentIndexNumber.Value.ToString("000", CultureInfo.InvariantCulture) + IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
for (int i = 0; i < take; i++)
{
newList[i] = newList[i] + suffix;
}
newList.AddRange(list);
list = newList;
}
return list;
}
/// <summary>
/// This Episode's Series Instance.
/// Gets the Episode's Series Instance.
/// </summary>
/// <value>The series.</value>
[JsonIgnore]
@@ -159,6 +116,74 @@ namespace MediaBrowser.Controller.Entities.TV
[JsonIgnore]
public string SeasonName { get; set; }
[JsonIgnore]
public override bool SupportsRemoteImageDownloading
{
get
{
if (IsMissingEpisode)
{
return false;
}
return true;
}
}
[JsonIgnore]
public bool IsMissingEpisode => LocationType == LocationType.Virtual;
[JsonIgnore]
public Guid SeasonId { get; set; }
[JsonIgnore]
public Guid SeriesId { get; set; }
public string FindSeriesSortName()
{
var series = Series;
return series == null ? SeriesName : series.SortName;
}
public override double GetDefaultPrimaryImageAspectRatio()
{
// hack for tv plugins
if (SourceType == SourceType.Channel)
{
return 0;
}
return 16.0 / 9;
}
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
var series = Series;
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
{
var seriesUserDataKeys = series.GetUserDataKeys();
var take = seriesUserDataKeys.Count;
if (seriesUserDataKeys.Count > 1)
{
take--;
}
var newList = seriesUserDataKeys.GetRange(0, take);
var suffix = ParentIndexNumber.Value.ToString("000", CultureInfo.InvariantCulture) + IndexNumber.Value.ToString("000", CultureInfo.InvariantCulture);
for (int i = 0; i < take; i++)
{
newList[i] = newList[i] + suffix;
}
newList.AddRange(list);
list = newList;
}
return list;
}
public string FindSeriesPresentationUniqueKey()
{
var series = Series;
@@ -216,8 +241,8 @@ namespace MediaBrowser.Controller.Entities.TV
/// <returns>System.String.</returns>
protected override string CreateSortName()
{
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "")
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ", CultureInfo.InvariantCulture) : string.Empty)
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ", CultureInfo.InvariantCulture) : string.Empty) + Name;
}
/// <summary>
@@ -240,28 +265,6 @@ namespace MediaBrowser.Controller.Entities.TV
return false;
}
[JsonIgnore]
public override bool SupportsRemoteImageDownloading
{
get
{
if (IsMissingEpisode)
{
return false;
}
return true;
}
}
[JsonIgnore]
public bool IsMissingEpisode => LocationType == LocationType.Virtual;
[JsonIgnore]
public Guid SeasonId { get; set; }
[JsonIgnore]
public Guid SeriesId { get; set; }
public Guid FindSeriesId()
{
var series = FindParent<Series>();
@@ -284,7 +287,8 @@ namespace MediaBrowser.Controller.Entities.TV
public override IEnumerable<FileSystemMetadata> GetDeletePaths()
{
return new[] {
return new[]
{
new FileSystemMetadata
{
FullName = Path,
@@ -316,9 +320,9 @@ namespace MediaBrowser.Controller.Entities.TV
return id;
}
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
if (!IsLocked)
{
@@ -326,7 +330,7 @@ namespace MediaBrowser.Controller.Entities.TV
{
try
{
if (LibraryManager.FillMissingEpisodeNumbersFromPath(this, replaceAllMetdata))
if (LibraryManager.FillMissingEpisodeNumbersFromPath(this, replaceAllMetadata))
{
hasChanges = true;
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -36,6 +38,50 @@ namespace MediaBrowser.Controller.Entities.TV
[JsonIgnore]
public override Guid DisplayParentId => SeriesId;
/// <summary>
/// Gets this Episode's Series Instance.
/// </summary>
/// <value>The series.</value>
[JsonIgnore]
public Series Series
{
get
{
var seriesId = SeriesId;
if (seriesId == Guid.Empty)
{
seriesId = FindSeriesId();
}
return seriesId == Guid.Empty ? null : (LibraryManager.GetItemById(seriesId) as Series);
}
}
[JsonIgnore]
public string SeriesPath
{
get
{
var series = Series;
if (series != null)
{
return series.Path;
}
return System.IO.Path.GetDirectoryName(Path);
}
}
[JsonIgnore]
public string SeriesPresentationUniqueKey { get; set; }
[JsonIgnore]
public string SeriesName { get; set; }
[JsonIgnore]
public Guid SeriesId { get; set; }
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 2;
@@ -78,41 +124,6 @@ namespace MediaBrowser.Controller.Entities.TV
return result;
}
/// <summary>
/// This Episode's Series Instance.
/// </summary>
/// <value>The series.</value>
[JsonIgnore]
public Series Series
{
get
{
var seriesId = SeriesId;
if (seriesId == Guid.Empty)
{
seriesId = FindSeriesId();
}
return seriesId == Guid.Empty ? null : (LibraryManager.GetItemById(seriesId) as Series);
}
}
[JsonIgnore]
public string SeriesPath
{
get
{
var series = Series;
if (series != null)
{
return series.Path;
}
return System.IO.Path.GetDirectoryName(Path);
}
}
public override string CreatePresentationUniqueKey()
{
if (IndexNumber.HasValue)
@@ -120,7 +131,7 @@ namespace MediaBrowser.Controller.Entities.TV
var series = Series;
if (series != null)
{
return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000");
return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000", CultureInfo.InvariantCulture);
}
}
@@ -133,7 +144,7 @@ namespace MediaBrowser.Controller.Entities.TV
/// <returns>System.String.</returns>
protected override string CreateSortName()
{
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
return IndexNumber != null ? IndexNumber.Value.ToString("0000", CultureInfo.InvariantCulture) : Name;
}
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
@@ -155,6 +166,9 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Gets the episodes.
/// </summary>
/// <param name="user">The user.</param>
/// <param name="options">The options to use.</param>
/// <returns>Set of episodes.</returns>
public List<BaseItem> GetEpisodes(User user, DtoOptions options)
{
return GetEpisodes(Series, user, options);
@@ -191,15 +205,6 @@ namespace MediaBrowser.Controller.Entities.TV
return UnratedItem.Series;
}
[JsonIgnore]
public string SeriesPresentationUniqueKey { get; set; }
[JsonIgnore]
public string SeriesName { get; set; }
[JsonIgnore]
public Guid SeriesId { get; set; }
public string FindSeriesPresentationUniqueKey()
{
var series = Series;
@@ -239,10 +244,11 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// This is called before any metadata refresh and returns true or false indicating if changes were made.
/// </summary>
/// <param name="replaceAllMetadata"><c>true</c> to replace metdata, <c>false</c> to not.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -57,8 +59,11 @@ namespace MediaBrowser.Controller.Entities.TV
public IReadOnlyList<Guid> RemoteTrailerIds { get; set; }
/// <summary>
/// airdate, dvd or absolute.
/// Gets or sets the display order.
/// </summary>
/// <remarks>
/// Valid options are airdate, dvd or absolute.
/// </remarks>
public string DisplayOrder { get; set; }
/// <summary>
@@ -67,6 +72,9 @@ namespace MediaBrowser.Controller.Entities.TV
/// <value>The status.</value>
public SeriesStatus? Status { get; set; }
[JsonIgnore]
public override bool StopRefreshIfLocalMetadataFound => false;
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 2;
@@ -288,7 +296,7 @@ namespace MediaBrowser.Controller.Entities.TV
// Refresh seasons
foreach (var item in items)
{
if (!(item is Season))
if (item is not Season)
{
continue;
}
@@ -316,20 +324,13 @@ namespace MediaBrowser.Controller.Entities.TV
cancellationToken.ThrowIfCancellationRequested();
var skipItem = false;
var episode = item as Episode;
if (episode != null
bool skipItem = item is Episode episode
&& refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh
&& !refreshOptions.ReplaceAllMetadata
&& episode.IsMissingEpisode
&& episode.LocationType == LocationType.Virtual
&& episode.PremiereDate.HasValue
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30)
{
skipItem = true;
}
&& (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30;
if (!skipItem)
{
@@ -396,6 +397,10 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Filters the episodes by season.
/// </summary>
/// <param name="episodes">The episodes.</param>
/// <param name="parentSeason">The season.</param>
/// <param name="includeSpecials"><c>true</c> to include special, <c>false</c> to not.</param>
/// <returns>The set of episodes.</returns>
public static IEnumerable<BaseItem> FilterEpisodesBySeason(IEnumerable<BaseItem> episodes, Season parentSeason, bool includeSpecials)
{
var seasonNumber = parentSeason.IndexNumber;
@@ -426,6 +431,10 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Filters the episodes by season.
/// </summary>
/// <param name="episodes">The episodes.</param>
/// <param name="seasonNumber">The season.</param>
/// <param name="includeSpecials"><c>true</c> to include special, <c>false</c> to not.</param>
/// <returns>The set of episodes.</returns>
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
{
if (!includeSpecials || seasonNumber < 1)
@@ -501,8 +510,5 @@ namespace MediaBrowser.Controller.Entities.TV
return list;
}
[JsonIgnore]
public override bool StopRefreshIfLocalMetadataFound => false;
}
}

View File

@@ -1,4 +1,6 @@
#pragma warning disable CS1591
#nullable disable
#pragma warning disable CA1819, CS1591
using System;
using System.Collections.Generic;
@@ -21,6 +23,9 @@ namespace MediaBrowser.Controller.Entities
TrailerTypes = Array.Empty<TrailerType>();
}
[JsonIgnore]
public override bool StopRefreshIfLocalMetadataFound => false;
public TrailerType[] TrailerTypes { get; set; }
public override double GetDefaultPrimaryImageAspectRatio()
@@ -43,9 +48,9 @@ namespace MediaBrowser.Controller.Entities
return info;
}
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
if (!ProductionYear.HasValue)
{
@@ -95,8 +100,5 @@ namespace MediaBrowser.Controller.Entities
return list;
}
[JsonIgnore]
public override bool StopRefreshIfLocalMetadataFound => false;
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -10,6 +12,13 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class UserItemData
{
public const double MinLikeValue = 6.5;
/// <summary>
/// The _rating.
/// </summary>
private double? _rating;
/// <summary>
/// Gets or sets the user id.
/// </summary>
@@ -22,11 +31,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The key.</value>
public string Key { get; set; }
/// <summary>
/// The _rating.
/// </summary>
private double? _rating;
/// <summary>
/// Gets or sets the users 0-10 rating.
/// </summary>
@@ -91,10 +95,8 @@ namespace MediaBrowser.Controller.Entities
/// <value>The index of the subtitle stream.</value>
public int? SubtitleStreamIndex { get; set; }
public const double MinLikeValue = 6.5;
/// <summary>
/// This is an interpreted property to indicate likes or dislikes
/// Gets or sets a value indicating whether the item is liked or not.
/// This should never be serialized.
/// </summary>
/// <value><c>null</c> if [likes] contains no value, <c>true</c> if [likes]; otherwise, <c>false</c>.</value>

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -19,8 +21,37 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class UserRootFolder : Folder
{
private List<Guid> _childrenIds = null;
private readonly object _childIdsLock = new object();
private List<Guid> _childrenIds = null;
/// <summary>
/// Initializes a new instance of the <see cref="UserRootFolder"/> class.
/// </summary>
public UserRootFolder()
{
IsRoot = true;
}
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
[JsonIgnore]
protected override bool SupportsShortcutChildren => true;
[JsonIgnore]
public override bool IsPreSorted => true;
private void ClearCache()
{
lock (_childIdsLock)
{
_childrenIds = null;
}
}
protected override List<BaseItem> LoadChildren()
{
lock (_childIdsLock)
@@ -36,20 +67,6 @@ namespace MediaBrowser.Controller.Entities
}
}
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
private void ClearCache()
{
lock (_childIdsLock)
{
_childrenIds = null;
}
}
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
{
if (query.Recursive)
@@ -71,12 +88,6 @@ namespace MediaBrowser.Controller.Entities
return GetChildren(user, true).Count;
}
[JsonIgnore]
protected override bool SupportsShortcutChildren => true;
[JsonIgnore]
public override bool IsPreSorted => true;
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
{
var list = base.GetEligibleChildrenForRecursiveChildren(user).ToList();
@@ -85,10 +96,10 @@ namespace MediaBrowser.Controller.Entities
return list;
}
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
ClearCache();
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
if (string.Equals("default", Name, StringComparison.OrdinalIgnoreCase))
{
@@ -106,11 +117,11 @@ namespace MediaBrowser.Controller.Entities
return base.GetNonCachedChildren(directoryService);
}
protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
protected override async Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
{
ClearCache();
await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService)
await base.ValidateChildrenInternal(progress, recursive, refreshChildMetadata, refreshOptions, directoryService, cancellationToken)
.ConfigureAwait(false);
ClearCache();

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -13,21 +15,56 @@ namespace MediaBrowser.Controller.Entities
{
public class UserView : Folder, IHasCollectionType
{
/// <inheritdoc />
private static readonly string[] _viewTypesEligibleForGrouping = new string[]
{
Model.Entities.CollectionType.Movies,
Model.Entities.CollectionType.TvShows,
string.Empty
};
private static readonly string[] _originalFolderViewTypes = new string[]
{
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 ITVSeriesManager TVSeriesManager { get; set; }
/// <summary>
/// Gets or sets the view type.
/// </summary>
public string ViewType { get; set; }
/// <inheritdoc />
/// <summary>
/// Gets or sets the display parent id.
/// </summary>
public new Guid DisplayParentId { get; set; }
/// <inheritdoc />
/// <summary>
/// Gets or sets the user id.
/// </summary>
public Guid? UserId { get; set; }
public static ITVSeriesManager TVSeriesManager;
/// <inheritdoc />
[JsonIgnore]
public string CollectionType => ViewType;
/// <inheritdoc />
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
/// <inheritdoc />
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
/// <inheritdoc />
[JsonIgnore]
public override bool SupportsPeople => false;
/// <inheritdoc />
public override IEnumerable<Guid> GetIdsForAncestorQuery()
{
@@ -45,17 +82,13 @@ namespace MediaBrowser.Controller.Entities
}
}
[JsonIgnore]
public override bool SupportsInheritedParentImages => false;
[JsonIgnore]
public override bool SupportsPlayedStatus => false;
/// <inheritdoc />
public override int GetChildCount(User user)
{
return GetChildren(user, true).Count;
}
/// <inheritdoc />
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
{
var parent = this as Folder;
@@ -73,12 +106,10 @@ namespace MediaBrowser.Controller.Entities
.GetUserItems(parent, this, CollectionType, query);
}
/// <inheritdoc />
public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query)
{
if (query == null)
{
query = new InternalItemsQuery(user);
}
query ??= new InternalItemsQuery(user);
query.EnableTotalRecordCount = false;
var result = GetItemList(query);
@@ -86,16 +117,19 @@ namespace MediaBrowser.Controller.Entities
return result.ToList();
}
/// <inheritdoc />
public override bool CanDelete()
{
return false;
}
/// <inheritdoc />
public override bool IsSaveLocalMetadataEnabled()
{
return true;
}
/// <inheritdoc />
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
{
query.SetUser(user);
@@ -106,32 +140,26 @@ namespace MediaBrowser.Controller.Entities
return GetItemList(query);
}
/// <inheritdoc />
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
{
return GetChildren(user, false);
}
private static string[] UserSpecificViewTypes = new string[]
{
Model.Entities.CollectionType.Playlists
};
public static bool IsUserSpecific(Folder folder)
{
var collectionFolder = folder as ICollectionFolder;
if (collectionFolder == null)
if (folder is not ICollectionFolder collectionFolder)
{
return false;
}
var supportsUserSpecific = folder as ISupportsUserSpecificView;
if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView)
if (folder is ISupportsUserSpecificView supportsUserSpecific
&& supportsUserSpecific.EnableUserSpecificView)
{
return true;
}
return UserSpecificViewTypes.Contains(collectionFolder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
return string.Equals(Model.Entities.CollectionType.Playlists, collectionFolder.CollectionType, StringComparison.OrdinalIgnoreCase);
}
public static bool IsEligibleForGrouping(Folder folder)
@@ -140,39 +168,19 @@ namespace MediaBrowser.Controller.Entities
&& IsEligibleForGrouping(collectionFolder.CollectionType);
}
private static string[] ViewTypesEligibleForGrouping = new string[]
{
Model.Entities.CollectionType.Movies,
Model.Entities.CollectionType.TvShows,
string.Empty
};
public static bool IsEligibleForGrouping(string viewType)
{
return ViewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
return _viewTypesEligibleForGrouping.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
private static string[] OriginalFolderViewTypes = new string[]
{
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)
{
return OriginalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
return _originalFolderViewTypes.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase);
}
protected override Task ValidateChildrenInternal(IProgress<double> progress, System.Threading.CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService)
protected override Task ValidateChildrenInternal(IProgress<double> progress, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService, System.Threading.CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
[JsonIgnore]
public override bool SupportsPeople => false;
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -53,17 +55,17 @@ namespace MediaBrowser.Controller.Entities
// if (query.IncludeItemTypes != null &&
// query.IncludeItemTypes.Length == 1 &&
// string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase))
//{
// {
// if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase))
// {
// return await FindPlaylists(queryParent, user, query).ConfigureAwait(false);
// }
//}
// }
switch (viewType)
{
case CollectionType.Folders:
return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), queryParent, query);
return GetResult(_libraryManager.GetUserRootFolder().GetChildren(user, true), query);
case CollectionType.TvShows:
return GetTvView(queryParent, user, query);
@@ -108,7 +110,7 @@ namespace MediaBrowser.Controller.Entities
return GetMovieMovies(queryParent, user, query);
case SpecialFolder.MovieCollections:
return GetMovieCollections(queryParent, user, query);
return GetMovieCollections(user, query);
case SpecialFolder.TvFavoriteEpisodes:
return GetFavoriteEpisodes(queryParent, user, query);
@@ -120,7 +122,7 @@ namespace MediaBrowser.Controller.Entities
{
if (queryParent is UserView)
{
return GetResult(GetMediaFolders(user).OfType<Folder>().SelectMany(i => i.GetChildren(user, true)), queryParent, query);
return GetResult(GetMediaFolders(user).OfType<Folder>().SelectMany(i => i.GetChildren(user, true)), query);
}
return queryParent.GetItems(query);
@@ -158,7 +160,7 @@ namespace MediaBrowser.Controller.Entities
GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent)
};
return GetResult(list, parent, query);
return GetResult(list, query);
}
private QueryResult<BaseItem> GetFavoriteMovies(Folder parent, User user, InternalItemsQuery query)
@@ -205,7 +207,7 @@ namespace MediaBrowser.Controller.Entities
return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query)
private QueryResult<BaseItem> GetMovieCollections(User user, InternalItemsQuery query)
{
query.Parent = null;
query.IncludeItemTypes = new[] { nameof(BoxSet) };
@@ -273,9 +275,9 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i != null)
.Select(i => GetUserViewWithName(i.Name, SpecialFolder.MovieGenre, i.SortName, parent));
.Select(i => GetUserViewWithName(SpecialFolder.MovieGenre, i.SortName, parent));
return GetResult(genres, parent, query);
return GetResult(genres, query);
}
private QueryResult<BaseItem> GetMovieGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
@@ -321,7 +323,7 @@ namespace MediaBrowser.Controller.Entities
GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent)
};
return GetResult(list, parent, query);
return GetResult(list, query);
}
private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query)
@@ -342,12 +344,14 @@ namespace MediaBrowser.Controller.Entities
var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows, string.Empty });
var result = _tvSeriesManager.GetNextUp(
new NextUpQuery
{
Limit = query.Limit,
StartIndex = query.StartIndex,
UserId = query.User.Id
}, parentFolders, query.DtoOptions);
new NextUpQuery
{
Limit = query.Limit,
StartIndex = query.StartIndex,
UserId = query.User.Id
},
parentFolders,
query.DtoOptions);
return result;
}
@@ -399,9 +403,9 @@ namespace MediaBrowser.Controller.Entities
}
})
.Where(i => i != null)
.Select(i => GetUserViewWithName(i.Name, SpecialFolder.TvGenre, i.SortName, parent));
.Select(i => GetUserViewWithName(SpecialFolder.TvGenre, i.SortName, parent));
return GetResult(genres, parent, query);
return GetResult(genres, query);
}
private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
@@ -428,13 +432,12 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetResult<T>(
IEnumerable<T> items,
BaseItem queryParent,
InternalItemsQuery query)
where T : BaseItem
{
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config);
return PostFilterAndSort(items, null, query, _libraryManager);
}
public static bool FilterItem(BaseItem item, InternalItemsQuery query)
@@ -444,11 +447,9 @@ namespace MediaBrowser.Controller.Entities
public static QueryResult<BaseItem> PostFilterAndSort(
IEnumerable<BaseItem> items,
BaseItem queryParent,
int? totalRecordLimit,
InternalItemsQuery query,
ILibraryManager libraryManager,
IServerConfigurationManager configurationManager)
ILibraryManager libraryManager)
{
var user = query.User;
@@ -997,7 +998,7 @@ namespace MediaBrowser.Controller.Entities
return new BaseItem[] { parent };
}
private UserView GetUserViewWithName(string name, string type, string sortName, BaseItem parent)
private UserView GetUserViewWithName(string type, string sortName, BaseItem parent)
{
return _userViewManager.GetUserSubView(parent.Id, parent.Id.ToString("N", CultureInfo.InvariantCulture), type, sortName);
}

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -26,6 +28,14 @@ namespace MediaBrowser.Controller.Entities
ISupportsPlaceHolders,
IHasMediaSources
{
public Video()
{
AdditionalParts = Array.Empty<string>();
LocalAlternateVersions = Array.Empty<string>();
SubtitleFiles = Array.Empty<string>();
LinkedAlternateVersions = Array.Empty<LinkedChild>();
}
[JsonIgnore]
public string PrimaryVersionId { get; set; }
@@ -72,30 +82,6 @@ namespace MediaBrowser.Controller.Entities
}
}
public void SetPrimaryVersionId(string id)
{
if (string.IsNullOrEmpty(id))
{
PrimaryVersionId = null;
}
else
{
PrimaryVersionId = id;
}
PresentationUniqueKey = CreatePresentationUniqueKey();
}
public override string CreatePresentationUniqueKey()
{
if (!string.IsNullOrEmpty(PrimaryVersionId))
{
return PrimaryVersionId;
}
return base.CreatePresentationUniqueKey();
}
[JsonIgnore]
public override bool SupportsThemeMedia => true;
@@ -149,24 +135,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The aspect ratio.</value>
public string AspectRatio { get; set; }
public Video()
{
AdditionalParts = Array.Empty<string>();
LocalAlternateVersions = Array.Empty<string>();
SubtitleFiles = Array.Empty<string>();
LinkedAlternateVersions = Array.Empty<LinkedChild>();
}
public override bool CanDownload()
{
if (VideoType == VideoType.Dvd || VideoType == VideoType.BluRay)
{
return false;
}
return IsFileProtocol;
}
[JsonIgnore]
public override bool SupportsAddingToPlaylist => true;
@@ -194,16 +162,6 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
public override bool HasLocalAlternateVersions => LocalAlternateVersions.Length > 0;
public IEnumerable<Guid> GetAdditionalPartIds()
{
return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
public IEnumerable<Guid> GetLocalAlternateVersionIds()
{
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
public static ILiveTvManager LiveTvManager { get; set; }
[JsonIgnore]
@@ -220,21 +178,6 @@ namespace MediaBrowser.Controller.Entities
}
}
protected override bool IsActiveRecording()
{
return LiveTvManager.GetActiveRecordingInfo(Path) != null;
}
public override bool CanDelete()
{
if (IsActiveRecording())
{
return false;
}
return base.CanDelete();
}
[JsonIgnore]
public bool IsCompleteMedia
{
@@ -252,80 +195,6 @@ namespace MediaBrowser.Controller.Entities
[JsonIgnore]
protected virtual bool EnableDefaultVideoUserDataKeys => true;
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
if (EnableDefaultVideoUserDataKeys)
{
if (ExtraType.HasValue)
{
var key = this.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, GetUserDataKey(key));
}
key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, GetUserDataKey(key));
}
}
else
{
var key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
}
key = this.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
}
}
}
return list;
}
private string GetUserDataKey(string providerId)
{
var key = providerId + "-" + ExtraType.ToString().ToLowerInvariant();
// Make sure different trailers have their own data.
if (RunTimeTicks.HasValue)
{
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
}
return key;
}
public IEnumerable<Video> GetLinkedAlternateVersions()
{
return LinkedAlternateVersions
.Select(GetLinkedChild)
.Where(i => i != null)
.OfType<Video>()
.OrderBy(i => i.SortName);
}
/// <summary>
/// Gets the additional parts.
/// </summary>
/// <returns>IEnumerable{Video}.</returns>
public IOrderedEnumerable<Video> GetAdditionalParts()
{
return GetAdditionalPartIds()
.Select(i => LibraryManager.GetItemById(i))
.Where(i => i != null)
.OfType<Video>()
.OrderBy(i => i.SortName);
}
[JsonIgnore]
public override string ContainingFolderPath
{
@@ -367,6 +236,153 @@ namespace MediaBrowser.Controller.Entities
}
}
/// <summary>
/// Gets a value indicating whether [is3 D].
/// </summary>
/// <value><c>true</c> if [is3 D]; otherwise, <c>false</c>.</value>
[JsonIgnore]
public bool Is3D => Video3DFormat.HasValue;
/// <summary>
/// Gets the type of the media.
/// </summary>
/// <value>The type of the media.</value>
[JsonIgnore]
public override string MediaType => Model.Entities.MediaType.Video;
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
if (EnableDefaultVideoUserDataKeys)
{
if (ExtraType.HasValue)
{
var key = this.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, GetUserDataKey(key));
}
key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, GetUserDataKey(key));
}
}
else
{
var key = this.GetProviderId(MetadataProvider.Imdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
}
key = this.GetProviderId(MetadataProvider.Tmdb);
if (!string.IsNullOrEmpty(key))
{
list.Insert(0, key);
}
}
}
return list;
}
public void SetPrimaryVersionId(string id)
{
if (string.IsNullOrEmpty(id))
{
PrimaryVersionId = null;
}
else
{
PrimaryVersionId = id;
}
PresentationUniqueKey = CreatePresentationUniqueKey();
}
public override string CreatePresentationUniqueKey()
{
if (!string.IsNullOrEmpty(PrimaryVersionId))
{
return PrimaryVersionId;
}
return base.CreatePresentationUniqueKey();
}
public override bool CanDownload()
{
if (VideoType == VideoType.Dvd || VideoType == VideoType.BluRay)
{
return false;
}
return IsFileProtocol;
}
protected override bool IsActiveRecording()
{
return LiveTvManager.GetActiveRecordingInfo(Path) != null;
}
public override bool CanDelete()
{
if (IsActiveRecording())
{
return false;
}
return base.CanDelete();
}
public IEnumerable<Guid> GetAdditionalPartIds()
{
return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
public IEnumerable<Guid> GetLocalAlternateVersionIds()
{
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
private string GetUserDataKey(string providerId)
{
var key = providerId + "-" + ExtraType.ToString().ToLowerInvariant();
// Make sure different trailers have their own data.
if (RunTimeTicks.HasValue)
{
key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
}
return key;
}
public IEnumerable<Video> GetLinkedAlternateVersions()
{
return LinkedAlternateVersions
.Select(GetLinkedChild)
.Where(i => i != null)
.OfType<Video>()
.OrderBy(i => i.SortName);
}
/// <summary>
/// Gets the additional parts.
/// </summary>
/// <returns>IEnumerable{Video}.</returns>
public IOrderedEnumerable<Video> GetAdditionalParts()
{
return GetAdditionalPartIds()
.Select(i => LibraryManager.GetItemById(i))
.Where(i => i != null)
.OfType<Video>()
.OrderBy(i => i.SortName);
}
internal override ItemUpdateType UpdateFromResolvedItem(BaseItem newItem)
{
var updateType = base.UpdateFromResolvedItem(newItem);
@@ -395,20 +411,6 @@ namespace MediaBrowser.Controller.Entities
return updateType;
}
/// <summary>
/// Gets a value indicating whether [is3 D].
/// </summary>
/// <value><c>true</c> if [is3 D]; otherwise, <c>false</c>.</value>
[JsonIgnore]
public bool Is3D => Video3DFormat.HasValue;
/// <summary>
/// Gets the type of the media.
/// </summary>
/// <value>The type of the media.</value>
[JsonIgnore]
public override string MediaType => Model.Entities.MediaType.Video;
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false);
@@ -480,7 +482,8 @@ namespace MediaBrowser.Controller.Entities
{
if (!IsInMixedFolder)
{
return new[] {
return new[]
{
new FileSystemMetadata
{
FullName = ContainingFolderPath,

View File

@@ -1,3 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
@@ -13,6 +15,25 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Year : BaseItem, IItemByName
{
[JsonIgnore]
public override bool SupportsAncestors => false;
[JsonIgnore]
public override bool SupportsPeople => false;
/// <summary>
/// Gets 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;
public override bool CanDelete()
{
return false;
}
public override List<string> GetUserDataKeys()
{
var list = base.GetUserDataKeys();
@@ -21,14 +42,6 @@ namespace MediaBrowser.Controller.Entities
return list;
}
/// <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;
public override double GetDefaultPrimaryImageAspectRatio()
{
double value = 2;
@@ -37,14 +50,6 @@ namespace MediaBrowser.Controller.Entities
return value;
}
[JsonIgnore]
public override bool SupportsAncestors => false;
public override bool CanDelete()
{
return false;
}
public override bool IsSaveLocalMetadataEnabled()
{
return true;
@@ -52,9 +57,7 @@ namespace MediaBrowser.Controller.Entities
public IList<BaseItem> GetTaggedItems(InternalItemsQuery query)
{
var usCulture = new CultureInfo("en-US");
if (!int.TryParse(Name, NumberStyles.Integer, usCulture, out var year))
if (!int.TryParse(Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out var year))
{
return new List<BaseItem>();
}
@@ -74,9 +77,6 @@ namespace MediaBrowser.Controller.Entities
return null;
}
[JsonIgnore]
public override bool SupportsPeople => false;
public static string GetPath(string name)
{
return GetPath(name, true);
@@ -110,11 +110,13 @@ namespace MediaBrowser.Controller.Entities
}
/// <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 if changes were made.
/// </summary>
public override bool BeforeMetadataRefresh(bool replaceAllMetdata)
/// <param name="replaceAllMetadata">Whether to replace all metadata.</param>
/// <returns>true if the item has change, else false.</returns>
public override bool BeforeMetadataRefresh(bool replaceAllMetadata)
{
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetdata);
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
var newPath = GetRebasedPath();
if (!string.Equals(Path, newPath, StringComparison.Ordinal))

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Events

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Events

View File

@@ -1,4 +1,4 @@
using Jellyfin.Data.Events;
using Jellyfin.Data.Events;
using MediaBrowser.Controller.Session;
namespace MediaBrowser.Controller.Events.Session

View File

@@ -1,4 +1,4 @@
using Jellyfin.Data.Events;
using Jellyfin.Data.Events;
using MediaBrowser.Controller.Session;
namespace MediaBrowser.Controller.Events.Session

View File

@@ -1,4 +1,4 @@
using Jellyfin.Data.Events;
using Jellyfin.Data.Events;
using MediaBrowser.Model.Updates;
namespace MediaBrowser.Controller.Events.Updates

View File

@@ -1,4 +1,4 @@
using Jellyfin.Data.Events;
using Jellyfin.Data.Events;
using MediaBrowser.Model.Updates;
namespace MediaBrowser.Controller.Events.Updates

View File

@@ -1,4 +1,4 @@
using Jellyfin.Data.Events;
using Jellyfin.Data.Events;
using MediaBrowser.Model.Updates;
namespace MediaBrowser.Controller.Events.Updates

View File

@@ -1,4 +1,4 @@
using Jellyfin.Data.Events;
using Jellyfin.Data.Events;
using MediaBrowser.Model.Updates;
namespace MediaBrowser.Controller.Events.Updates

View File

@@ -1,53 +0,0 @@
#nullable enable
#pragma warning disable CS1591
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace MediaBrowser.Controller.Extensions
{
/// <summary>
/// Class BaseExtensions.
/// </summary>
public static class StringExtensions
{
public static string RemoveDiacritics(this string text)
{
var chars = Normalize(text, NormalizationForm.FormD)
.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark);
return Normalize(string.Concat(chars), NormalizationForm.FormC);
}
private static string Normalize(string text, NormalizationForm form, bool stripStringOnFailure = true)
{
if (stripStringOnFailure)
{
try
{
return text.Normalize(form);
}
catch (ArgumentException)
{
// will throw if input contains invalid unicode chars
// https://mnaoumov.wordpress.com/2014/06/14/stripping-invalid-characters-from-utf-16-strings/
text = Regex.Replace(text, "([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])", "");
return Normalize(text, form, false);
}
}
try
{
return text.Normalize(form);
}
catch (ArgumentException)
{
// if it still fails, return the original text
return text;
}
}
}
}

View File

@@ -1,3 +1,5 @@
#nullable disable
using System;
using System.Collections.Generic;
using Jellyfin.Data.Entities;

View File

@@ -24,7 +24,7 @@ namespace MediaBrowser.Controller.IO
/// <param name="flattenFolderDepth">The flatten folder depth.</param>
/// <param name="resolveShortcuts">if set to <c>true</c> [resolve shortcuts].</param>
/// <returns>Dictionary{System.StringFileSystemInfo}.</returns>
/// <exception cref="ArgumentNullException">path</exception>
/// <exception cref="ArgumentNullException"><paramref name="path" /> is <c>null</c> or empty.</exception>
public static FileSystemMetadata[] GetFilteredFileSystemEntries(
IDirectoryService directoryService,
string path,

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