Merge branch 'master' into segment-deletion

This commit is contained in:
Dominik
2023-06-15 19:38:42 +02:00
committed by GitHub
1007 changed files with 41859 additions and 38419 deletions

View File

@@ -22,7 +22,7 @@ public class BrandingOptions
/// <summary>
/// Gets or sets a value indicating whether to enable the splashscreen.
/// </summary>
public bool SplashscreenEnabled { get; set; } = true;
public bool SplashscreenEnabled { get; set; } = false;
/// <summary>
/// Gets or sets the splashscreen location on disk.

View File

@@ -1,134 +1,266 @@
#nullable disable
#pragma warning disable CS1591
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Configuration
namespace MediaBrowser.Model.Configuration;
/// <summary>
/// Class EncodingOptions.
/// </summary>
public class EncodingOptions
{
public class EncodingOptions
/// <summary>
/// Initializes a new instance of the <see cref="EncodingOptions" /> class.
/// </summary>
public EncodingOptions()
{
public EncodingOptions()
{
EnableFallbackFont = false;
DownMixAudioBoost = 2;
MaxMuxingQueueSize = 2048;
EnableThrottling = false;
EnableSegmentDeletion = false;
ThrottleDelaySeconds = 180;
SegmentKeepSeconds = 360;
EncodingThreadCount = -1;
// This is a DRM device that is almost guaranteed to be there on every intel platform,
// plus it's the default one in ffmpeg if you don't specify anything
VaapiDevice = "/dev/dri/renderD128";
EnableTonemapping = false;
EnableVppTonemapping = false;
TonemappingAlgorithm = "bt2390";
TonemappingRange = "auto";
TonemappingDesat = 0;
TonemappingThreshold = 0.8;
TonemappingPeak = 100;
TonemappingParam = 0;
VppTonemappingBrightness = 0;
VppTonemappingContrast = 1.2;
H264Crf = 23;
H265Crf = 28;
DeinterlaceDoubleRate = false;
DeinterlaceMethod = "yadif";
EnableDecodingColorDepth10Hevc = true;
EnableDecodingColorDepth10Vp9 = true;
EnableEnhancedNvdecDecoder = false;
PreferSystemNativeHwDecoder = true;
EnableIntelLowPowerH264HwEncoder = false;
EnableIntelLowPowerHevcHwEncoder = false;
EnableHardwareEncoding = true;
AllowHevcEncoding = false;
EnableSubtitleExtraction = true;
AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = new[] { "mkv" };
HardwareDecodingCodecs = new string[] { "h264", "vc1" };
}
public int EncodingThreadCount { get; set; }
public string TranscodingTempPath { get; set; }
public string FallbackFontPath { get; set; }
public bool EnableFallbackFont { get; set; }
public double DownMixAudioBoost { get; set; }
public int MaxMuxingQueueSize { get; set; }
public bool EnableThrottling { get; set; }
public bool EnableSegmentDeletion { get; set; }
public int ThrottleDelaySeconds { get; set; }
public int SegmentKeepSeconds { get; set; }
public string HardwareAccelerationType { get; set; }
/// <summary>
/// Gets or sets the FFmpeg path as set by the user via the UI.
/// </summary>
public string EncoderAppPath { get; set; }
/// <summary>
/// Gets or sets the current FFmpeg path being used by the system and displayed on the transcode page.
/// </summary>
public string EncoderAppPathDisplay { get; set; }
public string VaapiDevice { get; set; }
public bool EnableTonemapping { get; set; }
public bool EnableVppTonemapping { get; set; }
public string TonemappingAlgorithm { get; set; }
public string TonemappingRange { get; set; }
public double TonemappingDesat { get; set; }
public double TonemappingThreshold { get; set; }
public double TonemappingPeak { get; set; }
public double TonemappingParam { get; set; }
public double VppTonemappingBrightness { get; set; }
public double VppTonemappingContrast { get; set; }
public int H264Crf { get; set; }
public int H265Crf { get; set; }
public string EncoderPreset { get; set; }
public bool DeinterlaceDoubleRate { get; set; }
public string DeinterlaceMethod { get; set; }
public bool EnableDecodingColorDepth10Hevc { get; set; }
public bool EnableDecodingColorDepth10Vp9 { get; set; }
public bool EnableEnhancedNvdecDecoder { get; set; }
public bool PreferSystemNativeHwDecoder { get; set; }
public bool EnableIntelLowPowerH264HwEncoder { get; set; }
public bool EnableIntelLowPowerHevcHwEncoder { get; set; }
public bool EnableHardwareEncoding { get; set; }
public bool AllowHevcEncoding { get; set; }
public bool EnableSubtitleExtraction { get; set; }
public string[] HardwareDecodingCodecs { get; set; }
public string[] AllowOnDemandMetadataBasedKeyframeExtractionForExtensions { get; set; }
EnableFallbackFont = false;
EnableAudioVbr = false;
DownMixAudioBoost = 2;
DownMixStereoAlgorithm = DownMixStereoAlgorithms.None;
MaxMuxingQueueSize = 2048;
EnableThrottling = false;
ThrottleDelaySeconds = 180;
EnableSegmentDeletion = false;
SegmentKeepSeconds = 360;
EncodingThreadCount = -1;
// This is a DRM device that is almost guaranteed to be there on every intel platform,
// plus it's the default one in ffmpeg if you don't specify anything
VaapiDevice = "/dev/dri/renderD128";
EnableTonemapping = false;
EnableVppTonemapping = false;
TonemappingAlgorithm = "bt2390";
TonemappingMode = "auto";
TonemappingRange = "auto";
TonemappingDesat = 0;
TonemappingPeak = 100;
TonemappingParam = 0;
VppTonemappingBrightness = 16;
VppTonemappingContrast = 1;
H264Crf = 23;
H265Crf = 28;
DeinterlaceDoubleRate = false;
DeinterlaceMethod = "yadif";
EnableDecodingColorDepth10Hevc = true;
EnableDecodingColorDepth10Vp9 = true;
// Enhanced Nvdec or system native decoder is required for DoVi to SDR tone-mapping.
EnableEnhancedNvdecDecoder = true;
PreferSystemNativeHwDecoder = true;
EnableIntelLowPowerH264HwEncoder = false;
EnableIntelLowPowerHevcHwEncoder = false;
EnableHardwareEncoding = true;
AllowHevcEncoding = false;
EnableSubtitleExtraction = true;
AllowOnDemandMetadataBasedKeyframeExtractionForExtensions = new[] { "mkv" };
HardwareDecodingCodecs = new string[] { "h264", "vc1" };
}
/// <summary>
/// Gets or sets the thread count used for encoding.
/// </summary>
public int EncodingThreadCount { get; set; }
/// <summary>
/// Gets or sets the temporary transcoding path.
/// </summary>
public string TranscodingTempPath { get; set; }
/// <summary>
/// Gets or sets the path to the fallback font.
/// </summary>
public string FallbackFontPath { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to use the fallback font.
/// </summary>
public bool EnableFallbackFont { get; set; }
/// <summary>
/// Gets or sets a value indicating whether audio VBR is enabled.
/// </summary>
public bool EnableAudioVbr { get; set; }
/// <summary>
/// Gets or sets the audio boost applied when downmixing audio.
/// </summary>
public double DownMixAudioBoost { get; set; }
/// <summary>
/// Gets or sets the algorithm used for downmixing audio to stereo.
/// </summary>
public DownMixStereoAlgorithms DownMixStereoAlgorithm { get; set; }
/// <summary>
/// Gets or sets the maximum size of the muxing queue.
/// </summary>
public int MaxMuxingQueueSize { get; set; }
/// <summary>
/// Gets or sets a value indicating whether throttling is enabled.
/// </summary>
public bool EnableThrottling { get; set; }
/// <summary>
/// Gets or sets the delay after which throttling happens.
/// </summary>
public int ThrottleDelaySeconds { get; set; }
/// <summary>
/// Gets or sets a value indicating whether segment deletion is enabled.
/// </summary>
public bool EnableSegmentDeletion { get; set; }
/// <summary>
/// Gets or sets seconds for which segments should be kept before being deleted.
/// </summary>
public int SegmentKeepSeconds { get; set; }
/// <summary>
/// Gets or sets the hardware acceleration type.
/// </summary>
public string HardwareAccelerationType { get; set; }
/// <summary>
/// Gets or sets the FFmpeg path as set by the user via the UI.
/// </summary>
public string EncoderAppPath { get; set; }
/// <summary>
/// Gets or sets the current FFmpeg path being used by the system and displayed on the transcode page.
/// </summary>
public string EncoderAppPathDisplay { get; set; }
/// <summary>
/// Gets or sets the VA-API device.
/// </summary>
public string VaapiDevice { get; set; }
/// <summary>
/// Gets or sets a value indicating whether tonemapping is enabled.
/// </summary>
public bool EnableTonemapping { get; set; }
/// <summary>
/// Gets or sets a value indicating whether VPP tonemapping is enabled.
/// </summary>
public bool EnableVppTonemapping { get; set; }
/// <summary>
/// Gets or sets the tone-mapping algorithm.
/// </summary>
public string TonemappingAlgorithm { get; set; }
/// <summary>
/// Gets or sets the tone-mapping mode.
/// </summary>
public string TonemappingMode { get; set; }
/// <summary>
/// Gets or sets the tone-mapping range.
/// </summary>
public string TonemappingRange { get; set; }
/// <summary>
/// Gets or sets the tone-mapping desaturation.
/// </summary>
public double TonemappingDesat { get; set; }
/// <summary>
/// Gets or sets the tone-mapping peak.
/// </summary>
public double TonemappingPeak { get; set; }
/// <summary>
/// Gets or sets the tone-mapping parameters.
/// </summary>
public double TonemappingParam { get; set; }
/// <summary>
/// Gets or sets the VPP tone-mapping brightness.
/// </summary>
public double VppTonemappingBrightness { get; set; }
/// <summary>
/// Gets or sets the VPP tone-mapping contrast.
/// </summary>
public double VppTonemappingContrast { get; set; }
/// <summary>
/// Gets or sets the H264 CRF.
/// </summary>
public int H264Crf { get; set; }
/// <summary>
/// Gets or sets the H265 CRF.
/// </summary>
public int H265Crf { get; set; }
/// <summary>
/// Gets or sets the encoder preset.
/// </summary>
public string EncoderPreset { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the framerate is doubled when deinterlacing.
/// </summary>
public bool DeinterlaceDoubleRate { get; set; }
/// <summary>
/// Gets or sets the deinterlace method.
/// </summary>
public string DeinterlaceMethod { get; set; }
/// <summary>
/// Gets or sets a value indicating whether 10bit HEVC decoding is enabled.
/// </summary>
public bool EnableDecodingColorDepth10Hevc { get; set; }
/// <summary>
/// Gets or sets a value indicating whether 10bit VP9 decoding is enabled.
/// </summary>
public bool EnableDecodingColorDepth10Vp9 { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the enhanced NVDEC is enabled.
/// </summary>
public bool EnableEnhancedNvdecDecoder { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the system native hardware decoder should be used.
/// </summary>
public bool PreferSystemNativeHwDecoder { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the Intel H264 low-power hardware encoder should be used.
/// </summary>
public bool EnableIntelLowPowerH264HwEncoder { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the Intel HEVC low-power hardware encoder should be used.
/// </summary>
public bool EnableIntelLowPowerHevcHwEncoder { get; set; }
/// <summary>
/// Gets or sets a value indicating whether hardware encoding is enabled.
/// </summary>
public bool EnableHardwareEncoding { get; set; }
/// <summary>
/// Gets or sets a value indicating whether HEVC encoding is enabled.
/// </summary>
public bool AllowHevcEncoding { get; set; }
/// <summary>
/// Gets or sets a value indicating whether subtitle extraction is enabled.
/// </summary>
public bool EnableSubtitleExtraction { get; set; }
/// <summary>
/// Gets or sets the codecs hardware encoding is used for.
/// </summary>
public string[] HardwareDecodingCodecs { get; set; }
/// <summary>
/// Gets or sets the file extensions on-demand metadata based keyframe extraction is enabled for.
/// </summary>
public string[] AllowOnDemandMetadataBasedKeyframeExtractionForExtensions { get; set; }
}

View File

@@ -30,6 +30,8 @@ namespace MediaBrowser.Model.Configuration
public bool EnableRealtimeMonitor { get; set; }
public bool EnableLUFSScan { get; set; }
public bool EnableChapterImageExtraction { get; set; }
public bool ExtractChapterImagesDuringLibraryScan { get; set; }
@@ -45,6 +47,8 @@ namespace MediaBrowser.Model.Configuration
public bool EnableEmbeddedTitles { get; set; }
public bool EnableEmbeddedExtrasTitles { get; set; }
public bool EnableEmbeddedEpisodeInfos { get; set; }
public int AutomaticRefreshIntervalDays { get; set; }

View File

@@ -2,7 +2,7 @@
#pragma warning disable CA1819
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Updates;
@@ -193,7 +193,7 @@ namespace MediaBrowser.Model.Configuration
public string[] CodecsUsed { get; set; } = Array.Empty<string>();
public List<RepositoryInfo> PluginRepositories { get; set; } = new List<RepositoryInfo>();
public RepositoryInfo[] PluginRepositories { get; set; } = Array.Empty<RepositoryInfo>();
public bool EnableExternalContentInSuggestions { get; set; } = true;
@@ -240,5 +240,23 @@ namespace MediaBrowser.Model.Configuration
/// Gets or sets a value indicating whether clients should be allowed to upload logs.
/// </summary>
public bool AllowClientLogUpload { get; set; } = true;
/// <summary>
/// Gets or sets the dummy chapter duration in seconds, use 0 (zero) or less to disable generation alltogether.
/// </summary>
/// <value>The dummy chapters duration.</value>
public int DummyChapterDuration { get; set; } = 0;
/// <summary>
/// Gets or sets the chapter image resolution.
/// </summary>
/// <value>The chapter image resolution.</value>
public ImageResolution ChapterImageResolution { get; set; } = ImageResolution.MatchSource;
/// <summary>
/// Gets or sets the limit for parallel image encoding.
/// </summary>
/// <value>The limit for parallel image encoding.</value>
public int ParallelImageEncodingLimit { get; set; } = 0;
}
}

View File

@@ -29,12 +29,7 @@ namespace MediaBrowser.Model.Cryptography
public PasswordHash(string id, byte[] hash, byte[] salt, Dictionary<string, string> parameters)
{
ArgumentNullException.ThrowIfNull(id);
if (id.Length == 0)
{
throw new ArgumentException("String can't be empty", nameof(id));
}
ArgumentException.ThrowIfNullOrEmpty(id);
Id = id;
_hash = hash;
@@ -85,7 +80,8 @@ namespace MediaBrowser.Model.Cryptography
{
throw new FormatException("Hash string must contain a valid id");
}
else if (nextSegment == -1)
if (nextSegment == -1)
{
return new PasswordHash(hashString.ToString(), Array.Empty<byte>());
}

View File

@@ -136,12 +136,26 @@ namespace MediaBrowser.Model.Dlna
return !condition.IsRequired;
}
if (int.TryParse(condition.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var expected))
var conditionType = condition.Condition;
if (condition.Condition == ProfileConditionType.EqualsAny)
{
switch (condition.Condition)
foreach (var singleConditionString in condition.Value.AsSpan().Split('|'))
{
if (int.TryParse(singleConditionString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int conditionValue)
&& conditionValue.Equals(currentValue))
{
return true;
}
}
return false;
}
if (int.TryParse(condition.Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var expected))
{
switch (conditionType)
{
case ProfileConditionType.Equals:
case ProfileConditionType.EqualsAny:
return currentValue.Value.Equals(expected);
case ProfileConditionType.GreaterThanEqual:
return currentValue.Value >= expected;
@@ -212,9 +226,24 @@ namespace MediaBrowser.Model.Dlna
return !condition.IsRequired;
}
if (double.TryParse(condition.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var expected))
var conditionType = condition.Condition;
if (condition.Condition == ProfileConditionType.EqualsAny)
{
switch (condition.Condition)
foreach (var singleConditionString in condition.Value.AsSpan().Split('|'))
{
if (double.TryParse(singleConditionString, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out double conditionValue)
&& conditionValue.Equals(currentValue))
{
return true;
}
}
return false;
}
if (double.TryParse(condition.Value, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var expected))
{
switch (conditionType)
{
case ProfileConditionType.Equals:
return currentValue.Value.Equals(expected);

View File

@@ -11,7 +11,7 @@ namespace MediaBrowser.Model.Dlna
[XmlAttribute("type")]
public DlnaProfileType Type { get; set; }
public ProfileCondition[]? Conditions { get; set; } = Array.Empty<ProfileCondition>();
public ProfileCondition[] Conditions { get; set; } = Array.Empty<ProfileCondition>();
[XmlAttribute("container")]
public string Container { get; set; } = string.Empty;
@@ -36,7 +36,7 @@ namespace MediaBrowser.Model.Dlna
public static bool ContainsContainer(string? profileContainers, string? inputContainer)
{
var isNegativeList = false;
if (profileContainers != null && profileContainers.StartsWith('-'))
if (profileContainers is not null && profileContainers.StartsWith('-'))
{
isNegativeList = true;
profileContainers = profileContainers.Substring(1);
@@ -52,7 +52,7 @@ namespace MediaBrowser.Model.Dlna
public static bool ContainsContainer(string[]? profileContainers, bool isNegativeList, string? inputContainer)
{
if (profileContainers == null || profileContainers.Length == 0)
if (profileContainers is null || profileContainers.Length == 0)
{
// Empty profiles always support all containers/codecs
return true;

View File

@@ -192,7 +192,7 @@ namespace MediaBrowser.Model.Dlna
var orgPnValues = new List<string>();
if (mediaProfile != null && !string.IsNullOrEmpty(mediaProfile.OrgPn))
if (mediaProfile is not null && !string.IsNullOrEmpty(mediaProfile.OrgPn))
{
orgPnValues.AddRange(mediaProfile.OrgPn.Split(',', StringSplitOptions.RemoveEmptyEntries));
}

View File

@@ -18,17 +18,17 @@ namespace MediaBrowser.Model.Dlna
[XmlAttribute("type")]
public DlnaProfileType Type { get; set; }
public bool SupportsContainer(string container)
public bool SupportsContainer(string? container)
{
return ContainerProfile.ContainsContainer(Container, container);
}
public bool SupportsVideoCodec(string codec)
public bool SupportsVideoCodec(string? codec)
{
return Type == DlnaProfileType.Video && ContainerProfile.ContainsContainer(VideoCodec, codec);
}
public bool SupportsAudioCodec(string codec)
public bool SupportsAudioCodec(string? codec)
{
return (Type == DlnaProfileType.Audio || Type == DlnaProfileType.Video) && ContainerProfile.ContainsContainer(AudioCodec, codec);
}

View File

@@ -10,22 +10,4 @@ namespace MediaBrowser.Model.Dlna
bool CanExtractSubtitles(string codec);
}
public class FullTranscoderSupport : ITranscoderSupport
{
public bool CanEncodeToAudioCodec(string codec)
{
return true;
}
public bool CanEncodeToSubtitleCodec(string codec)
{
return true;
}
public bool CanExtractSubtitles(string codec)
{
return true;
}
}
}

View File

@@ -1,17 +1,17 @@
#nullable disable
#pragma warning disable CS1591
using System;
using MediaBrowser.Model.Dto;
namespace MediaBrowser.Model.Dlna
{
/// <summary>
/// Class AudioOptions.
/// Class MediaOptions.
/// </summary>
public class AudioOptions
public class MediaOptions
{
public AudioOptions()
/// <summary>
/// Initializes a new instance of the <see cref="MediaOptions"/> class.
/// </summary>
public MediaOptions()
{
Context = EncodingContext.Streaming;
@@ -19,28 +19,60 @@ namespace MediaBrowser.Model.Dlna
EnableDirectStream = true;
}
/// <summary>
/// Gets or sets a value indicating whether direct playback is allowed.
/// </summary>
public bool EnableDirectPlay { get; set; }
/// <summary>
/// Gets or sets a value indicating whether direct streaming is allowed.
/// </summary>
public bool EnableDirectStream { get; set; }
/// <summary>
/// Gets or sets a value indicating whether direct playback is forced.
/// </summary>
public bool ForceDirectPlay { get; set; }
/// <summary>
/// Gets or sets a value indicating whether direct streaming is forced.
/// </summary>
public bool ForceDirectStream { get; set; }
/// <summary>
/// Gets or sets a value indicating whether audio stream copy is allowed.
/// </summary>
public bool AllowAudioStreamCopy { get; set; }
/// <summary>
/// Gets or sets a value indicating whether video stream copy is allowed.
/// </summary>
public bool AllowVideoStreamCopy { get; set; }
/// <summary>
/// Gets or sets the item id.
/// </summary>
public Guid ItemId { get; set; }
public MediaSourceInfo[] MediaSources { get; set; }
/// <summary>
/// Gets or sets the media sources.
/// </summary>
public MediaSourceInfo[] MediaSources { get; set; } = Array.Empty<MediaSourceInfo>();
public DeviceProfile Profile { get; set; }
/// <summary>
/// Gets or sets the device profile.
/// </summary>
required public DeviceProfile Profile { get; set; }
/// <summary>
/// Gets or sets a media source id. Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested.
/// </summary>
public string MediaSourceId { get; set; }
public string? MediaSourceId { get; set; }
public string DeviceId { get; set; }
/// <summary>
/// Gets or sets the device id.
/// </summary>
public string? DeviceId { get; set; }
/// <summary>
/// Gets or sets an override of supported number of audio channels
@@ -49,7 +81,7 @@ namespace MediaBrowser.Model.Dlna
public int? MaxAudioChannels { get; set; }
/// <summary>
/// Gets or sets the application's configured quality setting.
/// Gets or sets the application's configured maximum bitrate.
/// </summary>
public int? MaxBitrate { get; set; }
@@ -65,6 +97,16 @@ namespace MediaBrowser.Model.Dlna
/// <value>The audio transcoding bitrate.</value>
public int? AudioTranscodingBitrate { get; set; }
/// <summary>
/// Gets or sets an override for the audio stream index.
/// </summary>
public int? AudioStreamIndex { get; set; }
/// <summary>
/// Gets or sets an override for the subtitle stream index.
/// </summary>
public int? SubtitleStreamIndex { get; set; }
/// <summary>
/// Gets the maximum bitrate.
/// </summary>
@@ -77,7 +119,7 @@ namespace MediaBrowser.Model.Dlna
return MaxBitrate;
}
if (Profile == null)
if (Profile is null)
{
return null;
}

View File

@@ -39,7 +39,7 @@ namespace MediaBrowser.Model.Dlna
}
var resolutionConfig = GetResolutionConfiguration(outputBitrate);
if (resolutionConfig != null)
if (resolutionConfig is not null)
{
var originvalValue = maxWidth;

View File

@@ -9,10 +9,7 @@ namespace MediaBrowser.Model.Dlna
{
public SearchCriteria(string search)
{
if (search.Length == 0)
{
throw new ArgumentException("String can't be empty.", nameof(search));
}
ArgumentException.ThrowIfNullOrEmpty(search);
SearchType = SearchType.Unknown;

View File

@@ -9,7 +9,7 @@ namespace MediaBrowser.Model.Dlna
{
public SortCriteria(string sortOrder)
{
if (!string.IsNullOrEmpty(sortOrder) && Enum.TryParse<SortOrder>(sortOrder, true, out var sortOrderValue))
if (Enum.TryParse<SortOrder>(sortOrder, true, out var sortOrderValue))
{
SortOrder = sortOrderValue;
}

File diff suppressed because it is too large Load Diff

View File

@@ -107,9 +107,8 @@ namespace MediaBrowser.Model.Dlna
public string MediaSourceId => MediaSource?.Id;
public bool IsDirectStream =>
PlayMethod == PlayMethod.DirectStream ||
PlayMethod == PlayMethod.DirectPlay;
public bool IsDirectStream => MediaSource?.VideoType is not (VideoType.Dvd or VideoType.BluRay)
&& PlayMethod is PlayMethod.DirectStream or PlayMethod.DirectPlay;
/// <summary>
/// Gets the audio stream that will be used.
@@ -215,7 +214,7 @@ namespace MediaBrowser.Model.Dlna
var stream = TargetVideoStream;
return MaxFramerate.HasValue && !IsDirectStream
? MaxFramerate
: stream == null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
: stream is null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
}
}
@@ -431,7 +430,7 @@ namespace MediaBrowser.Model.Dlna
return totalBitrate.HasValue ?
Convert.ToInt64(totalBitrate.Value * totalSeconds) :
(long?)null;
null;
}
return null;
@@ -460,7 +459,7 @@ namespace MediaBrowser.Model.Dlna
return !IsDirectStream
? defaultValue
: MediaSource == null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None;
: MediaSource is null ? defaultValue : MediaSource.Timestamp ?? TransportStreamTimestamp.None;
}
}
@@ -521,7 +520,7 @@ namespace MediaBrowser.Model.Dlna
{
var videoStream = TargetVideoStream;
if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
if (videoStream is not null && videoStream.Width.HasValue && videoStream.Height.HasValue)
{
ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value);
@@ -540,7 +539,7 @@ namespace MediaBrowser.Model.Dlna
{
var videoStream = TargetVideoStream;
if (videoStream != null && videoStream.Width.HasValue && videoStream.Height.HasValue)
if (videoStream is not null && videoStream.Width.HasValue && videoStream.Height.HasValue)
{
ImageDimensions size = new ImageDimensions(videoStream.Width.Value, videoStream.Height.Value);
@@ -620,10 +619,7 @@ namespace MediaBrowser.Model.Dlna
public string ToUrl(string baseUrl, string accessToken)
{
if (string.IsNullOrEmpty(baseUrl))
{
throw new ArgumentNullException(nameof(baseUrl));
}
ArgumentException.ThrowIfNullOrEmpty(baseUrl);
var list = new List<string>();
foreach (NameValuePair pair in BuildParams(this, accessToken))
@@ -664,10 +660,7 @@ namespace MediaBrowser.Model.Dlna
private string GetUrl(string baseUrl, string queryString)
{
if (string.IsNullOrEmpty(baseUrl))
{
throw new ArgumentNullException(nameof(baseUrl));
}
ArgumentException.ThrowIfNullOrEmpty(baseUrl);
string extension = string.IsNullOrEmpty(Container) ? string.Empty : "." + Container;
@@ -928,12 +921,8 @@ namespace MediaBrowser.Model.Dlna
public int? GetTargetVideoBitDepth(string codec)
{
var value = GetOption(codec, "videobitdepth");
if (string.IsNullOrEmpty(value))
{
return null;
}
if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
{
return result;
}
@@ -944,12 +933,8 @@ namespace MediaBrowser.Model.Dlna
public int? GetTargetAudioBitDepth(string codec)
{
var value = GetOption(codec, "audiobitdepth");
if (string.IsNullOrEmpty(value))
{
return null;
}
if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result))
if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
{
return result;
}
@@ -960,12 +945,8 @@ namespace MediaBrowser.Model.Dlna
public double? GetTargetVideoLevel(string codec)
{
var value = GetOption(codec, "level");
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
if (double.TryParse(value, CultureInfo.InvariantCulture, out var result))
{
return result;
}
@@ -976,12 +957,8 @@ namespace MediaBrowser.Model.Dlna
public int? GetTargetRefFrames(string codec)
{
var value = GetOption(codec, "maxrefframes");
if (string.IsNullOrEmpty(value))
{
return null;
}
if (int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var result))
if (int.TryParse(value, CultureInfo.InvariantCulture, out var result))
{
return result;
}

View File

@@ -1,16 +0,0 @@
#pragma warning disable CS1591
namespace MediaBrowser.Model.Dlna
{
/// <summary>
/// Class VideoOptions.
/// </summary>
public class VideoOptions : AudioOptions
{
public int? AudioStreamIndex { get; set; }
public int? SubtitleStreamIndex { get; set; }
public bool AllowVideoStreamCopy { get; set; }
}
}

View File

@@ -71,18 +71,18 @@ namespace MediaBrowser.Model.Drawing
int? fillHeight)
{
// Return original size if input is invalid.
if ((fillWidth == null || fillWidth == 0)
&& (fillHeight == null || fillHeight == 0))
if ((fillWidth is null || fillWidth == 0)
&& (fillHeight is null || fillHeight == 0))
{
return size;
}
if (fillWidth == null || fillWidth == 0)
if (fillWidth is null || fillWidth == 0)
{
fillWidth = 1;
}
if (fillHeight == null || fillHeight == 0)
if (fillHeight is null || fillHeight == 0)
{
fillHeight = 1;
}

View File

@@ -0,0 +1,52 @@
namespace MediaBrowser.Model.Drawing;
/// <summary>
/// Enum ImageResolution.
/// </summary>
public enum ImageResolution
{
/// <summary>
/// MatchSource.
/// </summary>
MatchSource = 0,
/// <summary>
/// 144p.
/// </summary>
P144 = 1,
/// <summary>
/// 240p.
/// </summary>
P240 = 2,
/// <summary>
/// 360p.
/// </summary>
P360 = 3,
/// <summary>
/// 480p.
/// </summary>
P480 = 4,
/// <summary>
/// 720p.
/// </summary>
P720 = 5,
/// <summary>
/// 1080p.
/// </summary>
P1080 = 6,
/// <summary>
/// 1440p.
/// </summary>
P1440 = 7,
/// <summary>
/// 2160p.
/// </summary>
P2160 = 8
}

View File

@@ -779,6 +779,12 @@ namespace MediaBrowser.Model.Dto
/// <value>The timer identifier.</value>
public string TimerId { get; set; }
/// <summary>
/// Gets or sets the LUFS value.
/// </summary>
/// <value>The LUFS Value.</value>
public float? LUFS { get; set; }
/// <summary>
/// Gets or sets the current program.
/// </summary>

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
using Jellyfin.Data.Enums;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Dto
@@ -33,7 +34,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets the type.
/// </summary>
/// <value>The type.</value>
public string Type { get; set; }
public PersonKind Type { get; set; }
/// <summary>
/// Gets or sets the primary image tag.
@@ -52,6 +53,6 @@ namespace MediaBrowser.Model.Dto
/// </summary>
/// <value><c>true</c> if this instance has primary image; otherwise, <c>false</c>.</value>
[JsonIgnore]
public bool HasPrimaryImage => PrimaryImageTag != null;
public bool HasPrimaryImage => PrimaryImageTag is not null;
}
}

View File

@@ -1,111 +0,0 @@
#nullable disable
using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Dto
{
/// <summary>
/// Class ImageOptions.
/// </summary>
public class ImageOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="ImageOptions" /> class.
/// </summary>
public ImageOptions()
{
EnableImageEnhancers = true;
}
/// <summary>
/// Gets or sets the type of the image.
/// </summary>
/// <value>The type of the image.</value>
public ImageType ImageType { get; set; }
/// <summary>
/// Gets or sets the index of the image.
/// </summary>
/// <value>The index of the image.</value>
public int? ImageIndex { get; set; }
/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>The width.</value>
public int? Width { get; set; }
/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>The height.</value>
public int? Height { get; set; }
/// <summary>
/// Gets or sets the width of the max.
/// </summary>
/// <value>The width of the max.</value>
public int? MaxWidth { get; set; }
/// <summary>
/// Gets or sets the height of the max.
/// </summary>
/// <value>The height of the max.</value>
public int? MaxHeight { get; set; }
/// <summary>
/// Gets or sets the quality.
/// </summary>
/// <value>The quality.</value>
public int? Quality { get; set; }
/// <summary>
/// Gets or sets the image tag.
/// If set this will result in strong, unconditional response caching.
/// </summary>
/// <value>The hash.</value>
public string Tag { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [crop whitespace].
/// </summary>
/// <value><c>null</c> if [crop whitespace] contains no value, <c>true</c> if [crop whitespace]; otherwise, <c>false</c>.</value>
public bool? CropWhitespace { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [enable image enhancers].
/// </summary>
/// <value><c>true</c> if [enable image enhancers]; otherwise, <c>false</c>.</value>
public bool EnableImageEnhancers { get; set; }
/// <summary>
/// Gets or sets the format.
/// </summary>
/// <value>The format.</value>
public ImageFormat? Format { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [add played indicator].
/// </summary>
/// <value><c>true</c> if [add played indicator]; otherwise, <c>false</c>.</value>
public bool AddPlayedIndicator { get; set; }
/// <summary>
/// Gets or sets the percent played.
/// </summary>
/// <value>The percent played.</value>
public int? PercentPlayed { get; set; }
/// <summary>
/// Gets or sets the un played count.
/// </summary>
/// <value>The un played count.</value>
public int? UnPlayedCount { get; set; }
/// <summary>
/// Gets or sets the color of the background.
/// </summary>
/// <value>The color of the background.</value>
public string BackgroundColor { get; set; }
}
}

View File

@@ -134,7 +134,7 @@ namespace MediaBrowser.Model.Dto
public void InferTotalBitrate(bool force = false)
{
if (MediaStreams == null)
if (MediaStreams is null)
{
return;
}

View File

@@ -66,6 +66,7 @@ namespace MediaBrowser.Model.Dto
/// Gets or sets a value indicating whether this instance has configured easy password.
/// </summary>
/// <value><c>true</c> if this instance has configured easy password; otherwise, <c>false</c>.</value>
[Obsolete("Easy Password has been replaced with Quick Connect")]
public bool HasConfiguredEasyPassword { get; set; }
/// <summary>

View File

@@ -0,0 +1,23 @@
namespace MediaBrowser.Model.Entities;
/// <summary>
/// An enum representing an algorithm to downmix 6ch+ to stereo.
/// Algorithms sourced from https://superuser.com/questions/852400/properly-downmix-5-1-to-stereo-using-ffmpeg/1410620#1410620.
/// </summary>
public enum DownMixStereoAlgorithms
{
/// <summary>
/// No special algorithm.
/// </summary>
None = 0,
/// <summary>
/// Algorithm by Dave_750.
/// </summary>
Dave750 = 1,
/// <summary>
/// Nightmode Dialogue algorithm.
/// </summary>
NightmodeDialogue = 2
}

View File

@@ -0,0 +1,12 @@
namespace MediaBrowser.Model.Entities;
/// <summary>
/// Interface for access to shares.
/// </summary>
public interface IHasShares
{
/// <summary>
/// Gets or sets the shares.
/// </summary>
Share[] Shares { get; set; }
}

View File

@@ -635,11 +635,12 @@ namespace MediaBrowser.Model.Entities
// sub = external .sub file
return !codec.Contains("pgs", StringComparison.OrdinalIgnoreCase) &&
!codec.Contains("dvd", StringComparison.OrdinalIgnoreCase) &&
!codec.Contains("dvbsub", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(codec, "sub", StringComparison.OrdinalIgnoreCase) &&
!string.Equals(codec, "dvb_subtitle", StringComparison.OrdinalIgnoreCase);
return !codec.Contains("pgs", StringComparison.OrdinalIgnoreCase)
&& !codec.Contains("dvd", StringComparison.OrdinalIgnoreCase)
&& !codec.Contains("dvbsub", StringComparison.OrdinalIgnoreCase)
&& !string.Equals(codec, "sub", StringComparison.OrdinalIgnoreCase)
&& !string.Equals(codec, "sup", StringComparison.OrdinalIgnoreCase)
&& !string.Equals(codec, "dvb_subtitle", StringComparison.OrdinalIgnoreCase);
}
public bool SupportsSubtitleConversionTo(string toCodec)

View File

@@ -1,5 +1,3 @@
#pragma warning disable CS1591
namespace MediaBrowser.Model.Entities
{
/// <summary>
@@ -14,38 +12,78 @@ namespace MediaBrowser.Model.Entities
Custom = 0,
/// <summary>
/// The imdb.
/// The IMDb provider.
/// </summary>
Imdb = 2,
/// <summary>
/// The TMDB.
/// The TMDb provider.
/// </summary>
Tmdb = 3,
/// <summary>
/// The TVDB.
/// The TVDb provider.
/// </summary>
Tvdb = 4,
/// <summary>
/// The tvcom.
/// The tvcom providerd.
/// </summary>
Tvcom = 5,
/// <summary>
/// Tmdb Collection Id.
/// TMDb collection provider.
/// </summary>
TmdbCollection = 7,
/// <summary>
/// The MusicBrainz album provider.
/// </summary>
MusicBrainzAlbum = 8,
/// <summary>
/// The MusicBrainz album artist provider.
/// </summary>
MusicBrainzAlbumArtist = 9,
/// <summary>
/// The MusicBrainz artist provider.
/// </summary>
MusicBrainzArtist = 10,
/// <summary>
/// The MusicBrainz release group provider.
/// </summary>
MusicBrainzReleaseGroup = 11,
/// <summary>
/// The Zap2It provider.
/// </summary>
Zap2It = 12,
/// <summary>
/// The TvRage provider.
/// </summary>
TvRage = 15,
/// <summary>
/// The AudioDb artist provider.
/// </summary>
AudioDbArtist = 16,
/// <summary>
/// The AudioDb collection provider.
/// </summary>
AudioDbAlbum = 17,
/// <summary>
/// The MusicBrainz track provider.
/// </summary>
MusicBrainzTrack = 18,
/// <summary>
/// The TvMaze provider.
/// </summary>
TvMaze = 19
}
}

View File

@@ -12,7 +12,7 @@ namespace MediaBrowser.Model.Entities
{
}
public ParentalRating(string name, int value)
public ParentalRating(string name, int? value)
{
Name = name;
Value = value;
@@ -28,6 +28,6 @@ namespace MediaBrowser.Model.Entities
/// Gets or sets the value.
/// </summary>
/// <value>The value.</value>
public int Value { get; set; }
public int? Value { get; set; }
}
}

View File

@@ -55,7 +55,7 @@ namespace MediaBrowser.Model.Entities
{
ArgumentNullException.ThrowIfNull(instance);
if (instance.ProviderIds == null)
if (instance.ProviderIds is null)
{
id = null;
return false;

View File

@@ -0,0 +1,17 @@
namespace MediaBrowser.Model.Entities;
/// <summary>
/// Class to hold data on sharing permissions.
/// </summary>
public class Share
{
/// <summary>
/// Gets or sets the user id.
/// </summary>
public string? UserId { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the user has edit permissions.
/// </summary>
public bool CanEdit { get; set; }
}

View File

@@ -24,24 +24,27 @@ namespace MediaBrowser.Model.Extensions
requestedLanguage = "en";
}
var isRequestedLanguageEn = string.Equals(requestedLanguage, "en", StringComparison.OrdinalIgnoreCase);
return remoteImageInfos.OrderByDescending(i =>
{
// Image priority ordering:
// - Images that match the requested language
// - Images with no language
// - TODO: Images that match the original language
// - Images in English
// - Images that don't match the requested language
if (string.Equals(requestedLanguage, i.Language, StringComparison.OrdinalIgnoreCase))
{
return 3;
return 4;
}
if (string.IsNullOrEmpty(i.Language))
{
// Assume empty image language is likely to be English.
return isRequestedLanguageEn ? 3 : 2;
return 3;
}
if (!isRequestedLanguageEn && string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase))
if (string.Equals(i.Language, "en", StringComparison.OrdinalIgnoreCase))
{
// Prioritize English over non-requested languages.
return 2;
}

View File

@@ -30,8 +30,9 @@ namespace MediaBrowser.Model.Globalization
/// Gets the rating level.
/// </summary>
/// <param name="rating">The rating.</param>
/// <param name="countryCode">The optional two letter ISO language string.</param>
/// <returns><see cref="int" /> or <c>null</c>.</returns>
int? GetRatingLevel(string rating);
int? GetRatingLevel(string rating, string? countryCode = null);
/// <summary>
/// Gets the localized string.

View File

@@ -40,5 +40,9 @@ namespace MediaBrowser.Model.LiveTv
public string RecordingPostProcessor { get; set; }
public string RecordingPostProcessorArguments { get; set; }
public bool SaveRecordingNFO { get; set; } = true;
public bool SaveRecordingImages { get; set; } = true;
}
}

View File

@@ -14,7 +14,7 @@
</PropertyGroup>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFramework>net7.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
@@ -24,7 +24,7 @@
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<CodeAnalysisTreatWarningsAsErrors>false</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Stability)'=='Unstable'">
@@ -33,14 +33,14 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.3" />
<PackageReference Include="MimeTypes" Version="2.4.0">
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="MimeTypes">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Globalization" Version="4.3.0" />
<PackageReference Include="System.Text.Json" Version="6.0.7" />
<PackageReference Include="System.Globalization" />
<PackageReference Include="System.Text.Json" />
</ItemGroup>
<ItemGroup>
@@ -49,13 +49,13 @@
<!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.3.3">
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
<PackageReference Include="SerilogAnalyzer" PrivateAssets="All" />
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="../Jellyfin.Data/Jellyfin.Data.csproj" />

View File

@@ -17,11 +17,13 @@ namespace MediaBrowser.Model.MediaInfo
{
return "Dolby Digital";
}
else if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase))
if (string.Equals(codec, "eac3", StringComparison.OrdinalIgnoreCase))
{
return "Dolby Digital+";
}
else if (string.Equals(codec, "dca", StringComparison.OrdinalIgnoreCase))
if (string.Equals(codec, "dca", StringComparison.OrdinalIgnoreCase))
{
return "DTS";
}

View File

@@ -1,39 +1,41 @@
#nullable disable
#pragma warning disable CS1591
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.MediaInfo
namespace MediaBrowser.Model.MediaInfo;
/// <summary>
/// Represents the result of BDInfo output.
/// </summary>
public class BlurayDiscInfo
{
/// <summary>
/// Represents the result of BDInfo output.
/// Gets or sets the media streams.
/// </summary>
public class BlurayDiscInfo
{
/// <summary>
/// Gets or sets the media streams.
/// </summary>
/// <value>The media streams.</value>
public MediaStream[] MediaStreams { get; set; }
/// <value>The media streams.</value>
public MediaStream[] MediaStreams { get; set; }
/// <summary>
/// Gets or sets the run time ticks.
/// </summary>
/// <value>The run time ticks.</value>
public long? RunTimeTicks { get; set; }
/// <summary>
/// Gets or sets the run time ticks.
/// </summary>
/// <value>The run time ticks.</value>
public long? RunTimeTicks { get; set; }
/// <summary>
/// Gets or sets the files.
/// </summary>
/// <value>The files.</value>
public string[] Files { get; set; }
/// <summary>
/// Gets or sets the files.
/// </summary>
/// <value>The files.</value>
public string[] Files { get; set; }
public string PlaylistName { get; set; }
/// <summary>
/// Gets or sets the playlist name.
/// </summary>
/// <value>The playlist name.</value>
public string PlaylistName { get; set; }
/// <summary>
/// Gets or sets the chapters.
/// </summary>
/// <value>The chapters.</value>
public double[] Chapters { get; set; }
}
/// <summary>
/// Gets or sets the chapters.
/// </summary>
/// <value>The chapters.</value>
public double[] Chapters { get; set; }
}

View File

@@ -1,15 +1,14 @@
namespace MediaBrowser.Model.MediaInfo
namespace MediaBrowser.Model.MediaInfo;
/// <summary>
/// Interface IBlurayExaminer.
/// </summary>
public interface IBlurayExaminer
{
/// <summary>
/// Interface IBlurayExaminer.
/// Gets the disc info.
/// </summary>
public interface IBlurayExaminer
{
/// <summary>
/// Gets the disc info.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>BlurayDiscInfo.</returns>
BlurayDiscInfo GetDiscInfo(string path);
}
/// <param name="path">The path.</param>
/// <returns>BlurayDiscInfo.</returns>
BlurayDiscInfo GetDiscInfo(string path);
}

View File

@@ -117,7 +117,9 @@ namespace MediaBrowser.Model.Net
// Type image
{ "image/jpeg", ".jpg" },
{ "image/tiff", ".tiff" },
{ "image/x-png", ".png" },
{ "image/x-icon", ".ico" },
// Type text
{ "text/plain", ".txt" },
@@ -140,10 +142,7 @@ namespace MediaBrowser.Model.Net
[return: NotNullIfNotNull("defaultValue")]
public static string? GetMimeType(string filename, string? defaultValue = null)
{
if (filename.Length == 0)
{
throw new ArgumentException("String can't be empty.", nameof(filename));
}
ArgumentException.ThrowIfNullOrEmpty(filename);
var ext = Path.GetExtension(filename);
@@ -168,10 +167,7 @@ namespace MediaBrowser.Model.Net
public static string? ToExtension(string mimeType)
{
if (mimeType.Length == 0)
{
throw new ArgumentException("String can't be empty.", nameof(mimeType));
}
ArgumentException.ThrowIfNullOrEmpty(mimeType);
// handle text/html; charset=UTF-8
mimeType = mimeType.AsSpan().LeftPart(';').ToString();
@@ -184,5 +180,8 @@ namespace MediaBrowser.Model.Net
var extension = Model.MimeTypes.GetMimeTypeExtensions(mimeType).FirstOrDefault();
return string.IsNullOrEmpty(extension) ? null : "." + extension;
}
public static bool IsImage(ReadOnlySpan<char> mimeType)
=> mimeType.StartsWith("image/", StringComparison.OrdinalIgnoreCase);
}
}

View File

@@ -1,31 +0,0 @@
#nullable disable
#pragma warning disable CS1591
using System;
using MediaBrowser.Model.Session;
namespace MediaBrowser.Model.Net
{
/// <summary>
/// Class WebSocketMessage.
/// </summary>
/// <typeparam name="T">The type of the data.</typeparam>
public class WebSocketMessage<T>
{
/// <summary>
/// Gets or sets the type of the message.
/// </summary>
/// <value>The type of the message.</value>
public SessionMessageType MessageType { get; set; }
public Guid MessageId { get; set; }
public string ServerId { get; set; }
/// <summary>
/// Gets or sets the data.
/// </summary>
/// <value>The data.</value>
public T Data { get; set; }
}
}

View File

@@ -1,11 +0,0 @@
#pragma warning disable CS1591
namespace MediaBrowser.Model.Notifications
{
public enum NotificationLevel
{
Normal = 0,
Warning = 1,
Error = 2
}
}

View File

@@ -1,55 +0,0 @@
#pragma warning disable CA1819 // Properties should not return arrays
#pragma warning disable CS1591
using System;
namespace MediaBrowser.Model.Notifications
{
public class NotificationOption
{
public NotificationOption(string type)
{
Type = type;
DisabledServices = Array.Empty<string>();
DisabledMonitorUsers = Array.Empty<string>();
SendToUsers = Array.Empty<string>();
}
public NotificationOption()
{
DisabledServices = Array.Empty<string>();
DisabledMonitorUsers = Array.Empty<string>();
SendToUsers = Array.Empty<string>();
}
public string? Type { get; set; }
/// <summary>
/// Gets or sets user Ids to not monitor (it's opt out).
/// </summary>
public string[] DisabledMonitorUsers { get; set; }
/// <summary>
/// Gets or sets user Ids to send to (if SendToUserMode == Custom).
/// </summary>
public string[] SendToUsers { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="NotificationOption"/> is enabled.
/// </summary>
/// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
public bool Enabled { get; set; }
/// <summary>
/// Gets or sets the disabled services.
/// </summary>
/// <value>The disabled services.</value>
public string[] DisabledServices { get; set; }
/// <summary>
/// Gets or sets the send to user mode.
/// </summary>
/// <value>The send to user mode.</value>
public SendToUserType SendToUserMode { get; set; }
}
}

View File

@@ -1,131 +0,0 @@
#nullable disable
#pragma warning disable CS1591
using System;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using Jellyfin.Extensions;
namespace MediaBrowser.Model.Notifications
{
public class NotificationOptions
{
public NotificationOptions()
{
Options = new[]
{
new NotificationOption(NotificationType.TaskFailed.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.ServerRestartRequired.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.ApplicationUpdateAvailable.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.ApplicationUpdateInstalled.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.PluginUpdateInstalled.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.PluginUninstalled.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.InstallationFailed.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.PluginInstalled.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.PluginError.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
},
new NotificationOption(NotificationType.UserLockedOut.ToString())
{
Enabled = true,
SendToUserMode = SendToUserType.Admins
}
};
}
public NotificationOption[] Options { get; set; }
public NotificationOption GetOptions(string type)
{
foreach (NotificationOption i in Options)
{
if (string.Equals(type, i.Type, StringComparison.OrdinalIgnoreCase))
{
return i;
}
}
return null;
}
public bool IsEnabled(string type)
{
NotificationOption opt = GetOptions(type);
return opt != null && opt.Enabled;
}
public bool IsServiceEnabled(string service, string notificationType)
{
NotificationOption opt = GetOptions(notificationType);
return opt == null
|| !opt.DisabledServices.Contains(service, StringComparison.OrdinalIgnoreCase);
}
public bool IsEnabledToMonitorUser(string type, Guid userId)
{
NotificationOption opt = GetOptions(type);
return opt != null
&& opt.Enabled
&& !opt.DisabledMonitorUsers.Contains(userId.ToString("N"), StringComparison.OrdinalIgnoreCase);
}
public bool IsEnabledToSendToUser(string type, string userId, User user)
{
NotificationOption opt = GetOptions(type);
if (opt != null && opt.Enabled)
{
if (opt.SendToUserMode == SendToUserType.All)
{
return true;
}
if (opt.SendToUserMode == SendToUserType.Admins && user.HasPermission(PermissionKind.IsAdministrator))
{
return true;
}
return opt.SendToUsers.Contains(userId, StringComparison.OrdinalIgnoreCase);
}
return false;
}
}
}

View File

@@ -1,35 +0,0 @@
#nullable disable
#pragma warning disable CS1591
using System;
namespace MediaBrowser.Model.Notifications
{
public class NotificationRequest
{
public NotificationRequest()
{
UserIds = Array.Empty<Guid>();
Date = DateTime.UtcNow;
}
public string Name { get; set; }
public string Description { get; set; }
public string Url { get; set; }
public NotificationLevel Level { get; set; }
public Guid[] UserIds { get; set; }
public DateTime Date { get; set; }
/// <summary>
/// Gets or sets the corresponding type name used in configuration. Not for display.
/// </summary>
public string NotificationType { get; set; }
public SendToUserType? SendToUserMode { get; set; }
}
}

View File

@@ -1,18 +0,0 @@
#nullable disable
#pragma warning disable CS1591
namespace MediaBrowser.Model.Notifications
{
public class NotificationTypeInfo
{
public string Type { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public string Category { get; set; }
public bool IsBasedOnUserEvent { get; set; }
}
}

View File

@@ -1,11 +0,0 @@
#pragma warning disable CS1591
namespace MediaBrowser.Model.Notifications
{
public enum SendToUserType
{
All = 0,
Admins = 1,
Custom = 2
}
}

View File

@@ -1,19 +1,36 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Generic;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Playlists
namespace MediaBrowser.Model.Playlists;
/// <summary>
/// A playlist creation request.
/// </summary>
public class PlaylistCreationRequest
{
public class PlaylistCreationRequest
{
public string Name { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
public string? Name { get; set; }
public IReadOnlyList<Guid> ItemIdList { get; set; } = Array.Empty<Guid>();
/// <summary>
/// Gets or sets the list of items.
/// </summary>
public IReadOnlyList<Guid> ItemIdList { get; set; } = Array.Empty<Guid>();
public string MediaType { get; set; }
/// <summary>
/// Gets or sets the media type.
/// </summary>
public string? MediaType { get; set; }
public Guid UserId { get; set; }
}
/// <summary>
/// Gets or sets the user id.
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// Gets or sets the shares.
/// </summary>
public Share[]? Shares { get; set; }
}

View File

@@ -126,7 +126,7 @@ namespace MediaBrowser.Model.Querying
ProductionLocations,
/// <summary>
/// Imdb, tmdb, etc.
/// The ids from IMDb, TMDb, etc.
/// </summary>
ProviderIds,

View File

@@ -154,5 +154,10 @@ namespace MediaBrowser.Model.Querying
/// The similarity score.
/// </summary>
public const string SimilarityScore = "SimilarityScore";
/// <summary>
/// The search score.
/// </summary>
public const string SearchScore = "SearchScore";
}
}

View File

@@ -1,42 +1,30 @@
using System;
namespace MediaBrowser.Model.SyncPlay
namespace MediaBrowser.Model.SyncPlay;
/// <summary>
/// Group update without data.
/// </summary>
public abstract class GroupUpdate
{
/// <summary>
/// Class GroupUpdate.
/// Initializes a new instance of the <see cref="GroupUpdate"/> class.
/// </summary>
/// <typeparam name="T">The type of the data of the message.</typeparam>
public class GroupUpdate<T>
/// <param name="groupId">The group identifier.</param>
protected GroupUpdate(Guid groupId)
{
/// <summary>
/// Initializes a new instance of the <see cref="GroupUpdate{T}"/> class.
/// </summary>
/// <param name="groupId">The group identifier.</param>
/// <param name="type">The update type.</param>
/// <param name="data">The update data.</param>
public GroupUpdate(Guid groupId, GroupUpdateType type, T data)
{
GroupId = groupId;
Type = type;
Data = data;
}
/// <summary>
/// Gets the group identifier.
/// </summary>
/// <value>The group identifier.</value>
public Guid GroupId { get; }
/// <summary>
/// Gets the update type.
/// </summary>
/// <value>The update type.</value>
public GroupUpdateType Type { get; }
/// <summary>
/// Gets the update data.
/// </summary>
/// <value>The update data.</value>
public T Data { get; }
GroupId = groupId;
}
/// <summary>
/// Gets the group identifier.
/// </summary>
/// <value>The group identifier.</value>
public Guid GroupId { get; }
/// <summary>
/// Gets the update type.
/// </summary>
/// <value>The update type.</value>
public GroupUpdateType Type { get; init; }
}

View File

@@ -0,0 +1,31 @@
#pragma warning disable SA1649
using System;
namespace MediaBrowser.Model.SyncPlay;
/// <summary>
/// Class GroupUpdate.
/// </summary>
/// <typeparam name="T">The type of the data of the message.</typeparam>
public class GroupUpdate<T> : GroupUpdate
{
/// <summary>
/// Initializes a new instance of the <see cref="GroupUpdate{T}"/> class.
/// </summary>
/// <param name="groupId">The group identifier.</param>
/// <param name="type">The update type.</param>
/// <param name="data">The update data.</param>
public GroupUpdate(Guid groupId, GroupUpdateType type, T data)
: base(groupId)
{
Data = data;
Type = type;
}
/// <summary>
/// Gets the update data.
/// </summary>
/// <value>The update data.</value>
public T Data { get; }
}

View File

@@ -19,7 +19,7 @@ namespace MediaBrowser.Model.SyncPlay
/// <param name="isPlaying">The playing item status.</param>
/// <param name="shuffleMode">The shuffle mode.</param>
/// <param name="repeatMode">The repeat mode.</param>
public PlayQueueUpdate(PlayQueueUpdateReason reason, DateTime lastUpdate, IReadOnlyList<QueueItem> playlist, int playingItemIndex, long startPositionTicks, bool isPlaying, GroupShuffleMode shuffleMode, GroupRepeatMode repeatMode)
public PlayQueueUpdate(PlayQueueUpdateReason reason, DateTime lastUpdate, IReadOnlyList<SyncPlayQueueItem> playlist, int playingItemIndex, long startPositionTicks, bool isPlaying, GroupShuffleMode shuffleMode, GroupRepeatMode repeatMode)
{
Reason = reason;
LastUpdate = lastUpdate;
@@ -47,7 +47,7 @@ namespace MediaBrowser.Model.SyncPlay
/// Gets the playlist.
/// </summary>
/// <value>The playlist.</value>
public IReadOnlyList<QueueItem> Playlist { get; }
public IReadOnlyList<SyncPlayQueueItem> Playlist { get; }
/// <summary>
/// Gets the playing item index in the playlist.

View File

@@ -5,13 +5,13 @@ namespace MediaBrowser.Model.SyncPlay
/// <summary>
/// Class QueueItem.
/// </summary>
public class QueueItem
public class SyncPlayQueueItem
{
/// <summary>
/// Initializes a new instance of the <see cref="QueueItem"/> class.
/// Initializes a new instance of the <see cref="SyncPlayQueueItem"/> class.
/// </summary>
/// <param name="itemId">The item identifier.</param>
public QueueItem(Guid itemId)
public SyncPlayQueueItem(Guid itemId)
{
ItemId = itemId;
}

View File

@@ -1,12 +0,0 @@
#pragma warning disable CS1591
namespace MediaBrowser.Model.System
{
public enum OperatingSystemId
{
Windows,
Linux,
Darwin,
BSD
}
}

View File

@@ -1,6 +1,8 @@
#nullable disable
#pragma warning disable CS1591
using System;
namespace MediaBrowser.Model.System
{
public class PublicSystemInfo
@@ -32,7 +34,8 @@ namespace MediaBrowser.Model.System
/// Gets or sets the operating system.
/// </summary>
/// <value>The operating system.</value>
public string OperatingSystem { get; set; }
[Obsolete("This is no longer set")]
public string OperatingSystem { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the id.

View File

@@ -42,7 +42,8 @@ namespace MediaBrowser.Model.System
/// Gets or sets the display name of the operating system.
/// </summary>
/// <value>The display name of the operating system.</value>
public string OperatingSystemDisplayName { get; set; }
[Obsolete("This is no longer set")]
public string OperatingSystemDisplayName { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the package name.
@@ -79,8 +80,9 @@ namespace MediaBrowser.Model.System
/// <summary>
/// Gets or sets a value indicating whether this instance can self restart.
/// </summary>
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value>
public bool CanSelfRestart { get; set; }
/// <value><c>true</c>.</value>
[Obsolete("This is always true")]
public bool CanSelfRestart { get; set; } = true;
public bool CanLaunchWebBrowser { get; set; }
@@ -136,6 +138,7 @@ namespace MediaBrowser.Model.System
[Obsolete("This isn't set correctly anymore")]
public FFmpegLocation EncoderLocation { get; set; }
public Architecture SystemArchitecture { get; set; }
[Obsolete("This is no longer set")]
public Architecture SystemArchitecture { get; set; } = Architecture.X64;
}
}

View File

@@ -9,9 +9,9 @@ namespace MediaBrowser.Model.Tasks
{
public interface ITaskManager : IDisposable
{
event EventHandler<GenericEventArgs<IScheduledTaskWorker>> TaskExecuting;
event EventHandler<GenericEventArgs<IScheduledTaskWorker>>? TaskExecuting;
event EventHandler<TaskCompletionEventArgs> TaskCompleted;
event EventHandler<TaskCompletionEventArgs>? TaskCompleted;
/// <summary>
/// Gets the list of Scheduled Tasks.

View File

@@ -17,7 +17,7 @@ namespace MediaBrowser.Model.Updates
[JsonPropertyName("version")]
public string Version
{
get => _version == null ? string.Empty : _version.ToString();
get => _version is null ? string.Empty : _version.ToString();
set => _version = SysVersion.Parse(value);
}

View File

@@ -13,6 +13,7 @@ namespace MediaBrowser.Model.Users
public UserPolicy()
{
IsHidden = true;
EnableCollectionManagement = false;
EnableContentDeletion = false;
EnableContentDeletionFromFolders = Array.Empty<string>();
@@ -35,6 +36,7 @@ namespace MediaBrowser.Model.Users
EnableSharedDeviceControl = true;
BlockedTags = Array.Empty<string>();
AllowedTags = Array.Empty<string>();
BlockUnratedItems = Array.Empty<UnratedItem>();
EnableUserPreferenceAccess = true;
@@ -44,6 +46,7 @@ namespace MediaBrowser.Model.Users
LoginAttemptsBeforeLockout = -1;
MaxActiveSessions = 0;
MaxParentalRating = null;
EnableAllChannels = true;
EnabledChannels = Array.Empty<Guid>();
@@ -72,6 +75,12 @@ namespace MediaBrowser.Model.Users
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
public bool IsHidden { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance can manage collections.
/// </summary>
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
public bool EnableCollectionManagement { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is disabled.
/// </summary>
@@ -86,6 +95,8 @@ namespace MediaBrowser.Model.Users
public string[] BlockedTags { get; set; }
public string[] AllowedTags { get; set; }
public bool EnableUserPreferenceAccess { get; set; }
public AccessSchedule[] AccessSchedules { get; set; }