mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
Merge pull request #10141 from Bond-009/nullable3
This commit is contained in:
commit
9ae429b6f6
@ -1006,7 +1006,7 @@ namespace Emby.Server.Implementations
|
|||||||
if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest)
|
if (ConfigurationManager.GetNetworkConfiguration().EnablePublishedServerUriByRequest)
|
||||||
{
|
{
|
||||||
int? requestPort = request.Host.Port;
|
int? requestPort = request.Host.Port;
|
||||||
if (requestPort == null
|
if (requestPort is null
|
||||||
|| (requestPort == 80 && string.Equals(request.Scheme, "http", StringComparison.OrdinalIgnoreCase))
|
|| (requestPort == 80 && string.Equals(request.Scheme, "http", StringComparison.OrdinalIgnoreCase))
|
||||||
|| (requestPort == 443 && string.Equals(request.Scheme, "https", StringComparison.OrdinalIgnoreCase)))
|
|| (requestPort == 443 && string.Equals(request.Scheme, "https", StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
@ -1190,7 +1190,7 @@ namespace Emby.Server.Implementations
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_sessionManager != null)
|
if (_sessionManager is not null)
|
||||||
{
|
{
|
||||||
// used for closing websockets
|
// used for closing websockets
|
||||||
foreach (var session in _sessionManager.Sessions)
|
foreach (var session in _sessionManager.Sessions)
|
||||||
|
@ -1971,18 +1971,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
if (reader.TryGetString(2, out var imagePath))
|
if (reader.TryGetString(2, out var imagePath))
|
||||||
{
|
{
|
||||||
chapter.ImagePath = imagePath;
|
chapter.ImagePath = imagePath;
|
||||||
|
chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter);
|
||||||
if (!string.IsNullOrEmpty(chapter.ImagePath))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Logger.LogError(ex, "Failed to create image cache tag.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reader.TryReadDateTime(3, out var imageDateModified))
|
if (reader.TryReadDateTime(3, out var imageDateModified))
|
||||||
|
@ -693,7 +693,7 @@ public class DynamicHlsHelper
|
|||||||
// Currently we only transcode to 8 bits AV1
|
// Currently we only transcode to 8 bits AV1
|
||||||
int bitDepth = 8;
|
int bitDepth = 8;
|
||||||
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
|
if (EncodingHelper.IsCopyCodec(state.OutputVideoCodec)
|
||||||
&& state.VideoStream != null
|
&& state.VideoStream is not null
|
||||||
&& state.VideoStream.BitDepth.HasValue)
|
&& state.VideoStream.BitDepth.HasValue)
|
||||||
{
|
{
|
||||||
bitDepth = state.VideoStream.BitDepth.Value;
|
bitDepth = state.VideoStream.BitDepth.Value;
|
||||||
|
@ -77,7 +77,7 @@ public class CommaDelimitedArrayModelBinder : IModelBinder
|
|||||||
var typedValueIndex = 0;
|
var typedValueIndex = 0;
|
||||||
for (var i = 0; i < parsedValues.Length; i++)
|
for (var i = 0; i < parsedValues.Length; i++)
|
||||||
{
|
{
|
||||||
if (parsedValues[i] != null)
|
if (parsedValues[i] is not null)
|
||||||
{
|
{
|
||||||
typedValues.SetValue(parsedValues[i], typedValueIndex);
|
typedValues.SetValue(parsedValues[i], typedValueIndex);
|
||||||
typedValueIndex++;
|
typedValueIndex++;
|
||||||
|
@ -77,7 +77,7 @@ public class PipeDelimitedArrayModelBinder : IModelBinder
|
|||||||
var typedValueIndex = 0;
|
var typedValueIndex = 0;
|
||||||
for (var i = 0; i < parsedValues.Length; i++)
|
for (var i = 0; i < parsedValues.Length; i++)
|
||||||
{
|
{
|
||||||
if (parsedValues[i] != null)
|
if (parsedValues[i] is not null)
|
||||||
{
|
{
|
||||||
typedValues.SetValue(parsedValues[i], typedValueIndex);
|
typedValues.SetValue(parsedValues[i], typedValueIndex);
|
||||||
typedValueIndex++;
|
typedValueIndex++;
|
||||||
|
@ -276,7 +276,7 @@ namespace Jellyfin.Server.Extensions
|
|||||||
}
|
}
|
||||||
else if (NetworkExtensions.TryParseToSubnet(allowedProxies[i], out var subnet))
|
else if (NetworkExtensions.TryParseToSubnet(allowedProxies[i], out var subnet))
|
||||||
{
|
{
|
||||||
if (subnet != null)
|
if (subnet is not null)
|
||||||
{
|
{
|
||||||
AddIPAddress(config, options, subnet.Prefix, subnet.PrefixLength);
|
AddIPAddress(config, options, subnet.Prefix, subnet.PrefixLength);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ namespace MediaBrowser.Controller.Drawing
|
|||||||
/// <returns>Guid.</returns>
|
/// <returns>Guid.</returns>
|
||||||
string GetImageCacheTag(BaseItem item, ItemImageInfo image);
|
string GetImageCacheTag(BaseItem item, ItemImageInfo image);
|
||||||
|
|
||||||
string GetImageCacheTag(BaseItem item, ChapterInfo chapter);
|
string? GetImageCacheTag(BaseItem item, ChapterInfo chapter);
|
||||||
|
|
||||||
string? GetImageCacheTag(User user);
|
string? GetImageCacheTag(User user);
|
||||||
|
|
||||||
|
@ -1864,7 +1864,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// <exception cref="ArgumentException">Backdrops should be accessed using Item.Backdrops.</exception>
|
/// <exception cref="ArgumentException">Backdrops should be accessed using Item.Backdrops.</exception>
|
||||||
public bool HasImage(ImageType type, int imageIndex)
|
public bool HasImage(ImageType type, int imageIndex)
|
||||||
{
|
{
|
||||||
return GetImageInfo(type, imageIndex) != null;
|
return GetImageInfo(type, imageIndex) is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetImage(ItemImageInfo image, int index)
|
public void SetImage(ItemImageInfo image, int index)
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@ -14,7 +12,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the path.
|
/// Gets or sets the path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The path.</value>
|
/// <value>The path.</value>
|
||||||
public string Path { get; set; }
|
public required string Path { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the type.
|
/// Gets or sets the type.
|
||||||
@ -36,9 +34,9 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
/// Gets or sets the blurhash.
|
/// Gets or sets the blurhash.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The blurhash.</value>
|
/// <value>The blurhash.</value>
|
||||||
public string BlurHash { get; set; }
|
public string? BlurHash { get; set; }
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool IsLocalFile => Path is null || !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
|
public bool IsLocalFile => !Path.StartsWith("http", StringComparison.OrdinalIgnoreCase);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public bool IsInSeasonFolder => FindParent<Season>() != null;
|
public bool IsInSeasonFolder => FindParent<Season>() is not null;
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public string SeriesPresentationUniqueKey { get; set; }
|
public string SeriesPresentationUniqueKey { get; set; }
|
||||||
|
@ -333,7 +333,7 @@ namespace MediaBrowser.Controller.Entities
|
|||||||
|
|
||||||
protected override bool IsActiveRecording()
|
protected override bool IsActiveRecording()
|
||||||
{
|
{
|
||||||
return LiveTvManager.GetActiveRecordingInfo(Path) != null;
|
return LiveTvManager.GetActiveRecordingInfo(Path) is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool CanDelete()
|
public override bool CanDelete()
|
||||||
|
@ -217,7 +217,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <returns><c>true</c> if [contains file system entry by name] [the specified name]; otherwise, <c>false</c>.</returns>
|
/// <returns><c>true</c> if [contains file system entry by name] [the specified name]; otherwise, <c>false</c>.</returns>
|
||||||
public bool ContainsFileSystemEntryByName(string name)
|
public bool ContainsFileSystemEntryByName(string name)
|
||||||
{
|
{
|
||||||
return GetFileSystemEntryByName(name) != null;
|
return GetFileSystemEntryByName(name) is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCollectionType()
|
public string GetCollectionType()
|
||||||
|
@ -2692,7 +2692,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||||||
string args = string.Empty;
|
string args = string.Empty;
|
||||||
|
|
||||||
// http://ffmpeg.org/ffmpeg-all.html#toc-Complex-filtergraphs-1
|
// http://ffmpeg.org/ffmpeg-all.html#toc-Complex-filtergraphs-1
|
||||||
if (state.VideoStream != null && videoProcessFilters.Contains("-filter_complex", StringComparison.Ordinal))
|
if (state.VideoStream is not null && videoProcessFilters.Contains("-filter_complex", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
int videoStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.VideoStream);
|
int videoStreamIndex = FindIndex(state.MediaSource.MediaStreams, state.VideoStream);
|
||||||
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#nullable enable
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace MediaBrowser.Controller.Security
|
namespace MediaBrowser.Controller.Security
|
||||||
|
@ -135,7 +135,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transcodingProfile != null)
|
if (transcodingProfile is not null)
|
||||||
{
|
{
|
||||||
if (!item.SupportsTranscoding)
|
if (!item.SupportsTranscoding)
|
||||||
{
|
{
|
||||||
@ -759,7 +759,7 @@ namespace MediaBrowser.Model.Dlna
|
|||||||
{
|
{
|
||||||
// prefer direct copy profile
|
// prefer direct copy profile
|
||||||
float videoFramerate = videoStream?.AverageFrameRate ?? videoStream?.RealFrameRate ?? 0;
|
float videoFramerate = videoStream?.AverageFrameRate ?? videoStream?.RealFrameRate ?? 0;
|
||||||
TransportStreamTimestamp? timestamp = videoStream == null ? TransportStreamTimestamp.None : item.Timestamp;
|
TransportStreamTimestamp? timestamp = videoStream is null ? TransportStreamTimestamp.None : item.Timestamp;
|
||||||
int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio);
|
int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio);
|
||||||
int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video);
|
int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video);
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
#nullable disable
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@ -20,16 +19,16 @@ namespace MediaBrowser.Model.Entities
|
|||||||
/// Gets or sets the name.
|
/// Gets or sets the name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The name.</value>
|
/// <value>The name.</value>
|
||||||
public string Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the image path.
|
/// Gets or sets the image path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The image path.</value>
|
/// <value>The image path.</value>
|
||||||
public string ImagePath { get; set; }
|
public string? ImagePath { get; set; }
|
||||||
|
|
||||||
public DateTime ImageDateModified { get; set; }
|
public DateTime ImageDateModified { get; set; }
|
||||||
|
|
||||||
public string ImageTag { get; set; }
|
public string? ImageTag { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
#nullable disable
|
|
||||||
|
|
||||||
#pragma warning disable CA1068, CS1591
|
#pragma warning disable CA1068, CS1591
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -83,9 +80,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
where T : Video
|
where T : Video
|
||||||
{
|
{
|
||||||
BlurayDiscInfo blurayDiscInfo = null;
|
BlurayDiscInfo? blurayDiscInfo = null;
|
||||||
|
|
||||||
Model.MediaInfo.MediaInfo mediaInfoResult = null;
|
Model.MediaInfo.MediaInfo? mediaInfoResult = null;
|
||||||
|
|
||||||
if (!item.IsShortcut || options.EnableRemoteContentProbe)
|
if (!item.IsShortcut || options.EnableRemoteContentProbe)
|
||||||
{
|
{
|
||||||
@ -131,7 +128,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
var m2ts = _mediaEncoder.GetPrimaryPlaylistM2tsFiles(item.Path);
|
var m2ts = _mediaEncoder.GetPrimaryPlaylistM2tsFiles(item.Path);
|
||||||
|
|
||||||
// Return if no playable .m2ts files are found
|
// Return if no playable .m2ts files are found
|
||||||
if (blurayDiscInfo.Files.Length == 0 || m2ts.Count == 0)
|
if (blurayDiscInfo is null || blurayDiscInfo.Files.Length == 0 || m2ts.Count == 0)
|
||||||
{
|
{
|
||||||
_logger.LogError("No playable .m2ts files found in Blu-ray structure, skipping FFprobe.");
|
_logger.LogError("No playable .m2ts files found in Blu-ray structure, skipping FFprobe.");
|
||||||
return ItemUpdateType.MetadataImport;
|
return ItemUpdateType.MetadataImport;
|
||||||
@ -192,16 +189,14 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
protected async Task Fetch(
|
protected async Task Fetch(
|
||||||
Video video,
|
Video video,
|
||||||
CancellationToken cancellationToken,
|
CancellationToken cancellationToken,
|
||||||
Model.MediaInfo.MediaInfo mediaInfo,
|
Model.MediaInfo.MediaInfo? mediaInfo,
|
||||||
BlurayDiscInfo blurayInfo,
|
BlurayDiscInfo? blurayInfo,
|
||||||
MetadataRefreshOptions options)
|
MetadataRefreshOptions options)
|
||||||
{
|
{
|
||||||
List<MediaStream> mediaStreams;
|
List<MediaStream> mediaStreams = new List<MediaStream>();
|
||||||
IReadOnlyList<MediaAttachment> mediaAttachments;
|
IReadOnlyList<MediaAttachment> mediaAttachments;
|
||||||
ChapterInfo[] chapters;
|
ChapterInfo[] chapters;
|
||||||
|
|
||||||
mediaStreams = new List<MediaStream>();
|
|
||||||
|
|
||||||
// Add external streams before adding the streams from the file to preserve stream IDs on remote videos
|
// Add external streams before adding the streams from the file to preserve stream IDs on remote videos
|
||||||
await AddExternalSubtitlesAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
await AddExternalSubtitlesAsync(video, mediaStreams, options, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
@ -221,18 +216,6 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
video.TotalBitrate = mediaInfo.Bitrate;
|
video.TotalBitrate = mediaInfo.Bitrate;
|
||||||
video.RunTimeTicks = mediaInfo.RunTimeTicks;
|
video.RunTimeTicks = mediaInfo.RunTimeTicks;
|
||||||
video.Size = mediaInfo.Size;
|
video.Size = mediaInfo.Size;
|
||||||
|
|
||||||
if (video.VideoType == VideoType.VideoFile)
|
|
||||||
{
|
|
||||||
var extension = (Path.GetExtension(video.Path) ?? string.Empty).TrimStart('.');
|
|
||||||
|
|
||||||
video.Container = extension;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
video.Container = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
video.Container = mediaInfo.Container;
|
video.Container = mediaInfo.Container;
|
||||||
|
|
||||||
chapters = mediaInfo.Chapters ?? Array.Empty<ChapterInfo>();
|
chapters = mediaInfo.Chapters ?? Array.Empty<ChapterInfo>();
|
||||||
@ -243,8 +226,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var currentMediaStreams = video.GetMediaStreams();
|
foreach (var mediaStream in video.GetMediaStreams())
|
||||||
foreach (var mediaStream in currentMediaStreams)
|
|
||||||
{
|
{
|
||||||
if (!mediaStream.IsExternal)
|
if (!mediaStream.IsExternal)
|
||||||
{
|
{
|
||||||
@ -295,8 +277,8 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
_itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken);
|
_itemRepo.SaveMediaAttachments(video.Id, mediaAttachments, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh ||
|
if (options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh
|
||||||
options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
|| options.MetadataRefreshMode == MetadataRefreshMode.Default)
|
||||||
{
|
{
|
||||||
if (_config.Configuration.DummyChapterDuration > 0 && chapters.Length == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
|
if (_config.Configuration.DummyChapterDuration > 0 && chapters.Length == 0 && mediaStreams.Any(i => i.Type == MediaStreamType.Video))
|
||||||
{
|
{
|
||||||
@ -321,11 +303,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < chapters.Length; i++)
|
for (int i = 0; i < chapters.Length; i++)
|
||||||
{
|
{
|
||||||
string name = chapters[i].Name;
|
string? name = chapters[i].Name;
|
||||||
// Check if the name is empty and/or if the name is a time
|
// Check if the name is empty and/or if the name is a time
|
||||||
// Some ripping programs do that.
|
// Some ripping programs do that.
|
||||||
if (string.IsNullOrWhiteSpace(name) ||
|
if (string.IsNullOrWhiteSpace(name)
|
||||||
TimeSpan.TryParse(name, out _))
|
|| TimeSpan.TryParse(name, out _))
|
||||||
{
|
{
|
||||||
chapters[i].Name = string.Format(
|
chapters[i].Name = string.Format(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
@ -384,23 +366,18 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
// Use the ffprobe values if these are empty
|
// Use the ffprobe values if these are empty
|
||||||
if (videoStream is not null)
|
if (videoStream is not null)
|
||||||
{
|
{
|
||||||
videoStream.BitRate = IsEmpty(videoStream.BitRate) ? currentBitRate : videoStream.BitRate;
|
videoStream.BitRate = videoStream.BitRate.GetValueOrDefault() == 0 ? currentBitRate : videoStream.BitRate;
|
||||||
videoStream.Width = IsEmpty(videoStream.Width) ? currentWidth : videoStream.Width;
|
videoStream.Width = videoStream.Width.GetValueOrDefault() == 0 ? currentWidth : videoStream.Width;
|
||||||
videoStream.Height = IsEmpty(videoStream.Height) ? currentHeight : videoStream.Height;
|
videoStream.Height = videoStream.Height.GetValueOrDefault() == 0 ? currentHeight : videoStream.Height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsEmpty(int? num)
|
|
||||||
{
|
|
||||||
return !num.HasValue || num.Value == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets information about the longest playlist on a bdrom.
|
/// Gets information about the longest playlist on a bdrom.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path.</param>
|
/// <param name="path">The path.</param>
|
||||||
/// <returns>VideoStream.</returns>
|
/// <returns>VideoStream.</returns>
|
||||||
private BlurayDiscInfo GetBDInfo(string path)
|
private BlurayDiscInfo? GetBDInfo(string path)
|
||||||
{
|
{
|
||||||
ArgumentException.ThrowIfNullOrEmpty(path);
|
ArgumentException.ThrowIfNullOrEmpty(path);
|
||||||
|
|
||||||
@ -527,32 +504,29 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
|
|
||||||
private void FetchPeople(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
|
private void FetchPeople(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions options)
|
||||||
{
|
{
|
||||||
var replaceData = options.ReplaceAllMetadata;
|
if (video.IsLocked
|
||||||
|
|| video.LockedFields.Contains(MetadataField.Cast)
|
||||||
if (!video.IsLocked && !video.LockedFields.Contains(MetadataField.Cast))
|
|| data.People.Length == 0)
|
||||||
{
|
{
|
||||||
if (replaceData || _libraryManager.GetPeople(video).Count == 0)
|
return;
|
||||||
{
|
|
||||||
var people = new List<PersonInfo>();
|
|
||||||
|
|
||||||
foreach (var person in data.People)
|
|
||||||
{
|
|
||||||
PeopleHelper.AddPerson(people, new PersonInfo
|
|
||||||
{
|
|
||||||
Name = person.Name,
|
|
||||||
Type = person.Type,
|
|
||||||
Role = person.Role
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_libraryManager.UpdatePeople(video, people);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private SubtitleOptions GetOptions()
|
if (options.ReplaceAllMetadata || _libraryManager.GetPeople(video).Count == 0)
|
||||||
{
|
{
|
||||||
return _config.GetConfiguration<SubtitleOptions>("subtitles");
|
var people = new List<PersonInfo>();
|
||||||
|
|
||||||
|
foreach (var person in data.People)
|
||||||
|
{
|
||||||
|
PeopleHelper.AddPerson(people, new PersonInfo
|
||||||
|
{
|
||||||
|
Name = person.Name,
|
||||||
|
Type = person.Type,
|
||||||
|
Role = person.Role
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_libraryManager.UpdatePeople(video, people);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -575,7 +549,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
|
var enableSubtitleDownloading = options.MetadataRefreshMode == MetadataRefreshMode.Default ||
|
||||||
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
|
options.MetadataRefreshMode == MetadataRefreshMode.FullRefresh;
|
||||||
|
|
||||||
var subtitleOptions = GetOptions();
|
var subtitleOptions = _config.GetConfiguration<SubtitleOptions>("subtitles");
|
||||||
|
|
||||||
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
var libraryOptions = _libraryManager.GetLibraryOptions(video);
|
||||||
|
|
||||||
@ -659,9 +633,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="video">The video.</param>
|
/// <param name="video">The video.</param>
|
||||||
/// <returns>An array of dummy chapters.</returns>
|
/// <returns>An array of dummy chapters.</returns>
|
||||||
private ChapterInfo[] CreateDummyChapters(Video video)
|
internal ChapterInfo[] CreateDummyChapters(Video video)
|
||||||
{
|
{
|
||||||
var runtime = video.RunTimeTicks ?? 0;
|
var runtime = video.RunTimeTicks.GetValueOrDefault();
|
||||||
|
|
||||||
// Only process files with a runtime higher than 0 and lower than 12h. The latter are likely corrupted.
|
// Only process files with a runtime higher than 0 and lower than 12h. The latter are likely corrupted.
|
||||||
if (runtime < 0 || runtime > TimeSpan.FromHours(12).Ticks)
|
if (runtime < 0 || runtime > TimeSpan.FromHours(12).Ticks)
|
||||||
@ -671,30 +645,30 @@ namespace MediaBrowser.Providers.MediaInfo
|
|||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"{0} has an invalid runtime of {1} minutes",
|
"{0} has an invalid runtime of {1} minutes",
|
||||||
video.Name,
|
video.Name,
|
||||||
TimeSpan.FromTicks(runtime).Minutes));
|
TimeSpan.FromTicks(runtime).TotalMinutes));
|
||||||
}
|
}
|
||||||
|
|
||||||
long dummyChapterDuration = TimeSpan.FromSeconds(_config.Configuration.DummyChapterDuration).Ticks;
|
long dummyChapterDuration = TimeSpan.FromSeconds(_config.Configuration.DummyChapterDuration).Ticks;
|
||||||
if (runtime > dummyChapterDuration)
|
if (runtime <= dummyChapterDuration)
|
||||||
{
|
{
|
||||||
int chapterCount = (int)(runtime / dummyChapterDuration);
|
return Array.Empty<ChapterInfo>();
|
||||||
var chapters = new ChapterInfo[chapterCount];
|
|
||||||
|
|
||||||
long currentChapterTicks = 0;
|
|
||||||
for (int i = 0; i < chapterCount; i++)
|
|
||||||
{
|
|
||||||
chapters[i] = new ChapterInfo
|
|
||||||
{
|
|
||||||
StartPositionTicks = currentChapterTicks
|
|
||||||
};
|
|
||||||
|
|
||||||
currentChapterTicks += dummyChapterDuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
return chapters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.Empty<ChapterInfo>();
|
int chapterCount = (int)(runtime / dummyChapterDuration);
|
||||||
|
var chapters = new ChapterInfo[chapterCount];
|
||||||
|
|
||||||
|
long currentChapterTicks = 0;
|
||||||
|
for (int i = 0; i < chapterCount; i++)
|
||||||
|
{
|
||||||
|
chapters[i] = new ChapterInfo
|
||||||
|
{
|
||||||
|
StartPositionTicks = currentChapterTicks
|
||||||
|
};
|
||||||
|
|
||||||
|
currentChapterTicks += dummyChapterDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chapters;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ using MediaBrowser.Controller;
|
|||||||
using MediaBrowser.Controller.Configuration;
|
using MediaBrowser.Controller.Configuration;
|
||||||
using MediaBrowser.Controller.Drawing;
|
using MediaBrowser.Controller.Drawing;
|
||||||
using MediaBrowser.Controller.Entities;
|
using MediaBrowser.Controller.Entities;
|
||||||
using MediaBrowser.Controller.MediaEncoding;
|
|
||||||
using MediaBrowser.Model.Drawing;
|
using MediaBrowser.Model.Drawing;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
@ -437,8 +436,13 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
|
|||||||
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string GetImageCacheTag(BaseItem item, ChapterInfo chapter)
|
public string? GetImageCacheTag(BaseItem item, ChapterInfo chapter)
|
||||||
{
|
{
|
||||||
|
if (chapter.ImagePath is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return GetImageCacheTag(item, new ItemImageInfo
|
return GetImageCacheTag(item, new ItemImageInfo
|
||||||
{
|
{
|
||||||
Path = chapter.ImagePath,
|
Path = chapter.ImagePath,
|
||||||
|
@ -59,7 +59,7 @@ namespace Jellyfin.Extensions.Json.Converters
|
|||||||
var typedValueIndex = 0;
|
var typedValueIndex = 0;
|
||||||
for (var i = 0; i < stringEntries.Length; i++)
|
for (var i = 0; i < stringEntries.Length; i++)
|
||||||
{
|
{
|
||||||
if (parsedValues[i] != null)
|
if (parsedValues[i] is not null)
|
||||||
{
|
{
|
||||||
typedValues.SetValue(parsedValues[i], typedValueIndex);
|
typedValues.SetValue(parsedValues[i], typedValueIndex);
|
||||||
typedValueIndex++;
|
typedValueIndex++;
|
||||||
|
@ -40,7 +40,7 @@ namespace Jellyfin.Extensions
|
|||||||
public static IEnumerable<string> ReadAllLines(this TextReader reader)
|
public static IEnumerable<string> ReadAllLines(this TextReader reader)
|
||||||
{
|
{
|
||||||
string? line;
|
string? line;
|
||||||
while ((line = reader.ReadLine()) != null)
|
while ((line = reader.ReadLine()) is not null)
|
||||||
{
|
{
|
||||||
yield return line;
|
yield return line;
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ namespace Jellyfin.Extensions
|
|||||||
public static async IAsyncEnumerable<string> ReadAllLinesAsync(this TextReader reader)
|
public static async IAsyncEnumerable<string> ReadAllLinesAsync(this TextReader reader)
|
||||||
{
|
{
|
||||||
string? line;
|
string? line;
|
||||||
while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) != null)
|
while ((line = await reader.ReadLineAsync().ConfigureAwait(false)) is not null)
|
||||||
{
|
{
|
||||||
yield return line;
|
yield return line;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="AutoFixture" />
|
||||||
|
<PackageReference Include="AutoFixture.AutoMoq" />
|
||||||
|
<PackageReference Include="AutoFixture.Xunit2" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||||
<PackageReference Include="Moq" />
|
<PackageReference Include="Moq" />
|
||||||
<PackageReference Include="xunit" />
|
<PackageReference Include="xunit" />
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using AutoFixture;
|
||||||
|
using AutoFixture.AutoMoq;
|
||||||
|
using MediaBrowser.Controller.Configuration;
|
||||||
|
using MediaBrowser.Controller.Entities;
|
||||||
|
using MediaBrowser.Model.Configuration;
|
||||||
|
using MediaBrowser.Providers.MediaInfo;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Jellyfin.Providers.Tests.MediaInfo;
|
||||||
|
|
||||||
|
public class FFProbeVideoInfoTests
|
||||||
|
{
|
||||||
|
private readonly FFProbeVideoInfo _fFProbeVideoInfo;
|
||||||
|
|
||||||
|
public FFProbeVideoInfoTests()
|
||||||
|
{
|
||||||
|
var serverConfiguration = new ServerConfiguration()
|
||||||
|
{
|
||||||
|
DummyChapterDuration = (int)TimeSpan.FromMinutes(5).TotalSeconds
|
||||||
|
};
|
||||||
|
var serverConfig = new Mock<IServerConfigurationManager>();
|
||||||
|
serverConfig.Setup(c => c.Configuration)
|
||||||
|
.Returns(serverConfiguration);
|
||||||
|
|
||||||
|
IFixture fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true });
|
||||||
|
fixture.Inject(serverConfig);
|
||||||
|
_fFProbeVideoInfo = fixture.Create<FFProbeVideoInfo>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(-1L)]
|
||||||
|
[InlineData(long.MinValue)]
|
||||||
|
[InlineData(long.MaxValue)]
|
||||||
|
public void CreateDummyChapters_InvalidRuntime_ThrowsArgumentException(long? runtime)
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentException>(
|
||||||
|
() => _fFProbeVideoInfo.CreateDummyChapters(new Video()
|
||||||
|
{
|
||||||
|
RunTimeTicks = runtime
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(null, 0)]
|
||||||
|
[InlineData(0L, 0)]
|
||||||
|
[InlineData(1L, 0)]
|
||||||
|
[InlineData(TimeSpan.TicksPerMinute * 5, 0)]
|
||||||
|
[InlineData((TimeSpan.TicksPerMinute * 5) + 1, 1)]
|
||||||
|
[InlineData(TimeSpan.TicksPerMinute * 50, 10)]
|
||||||
|
public void CreateDummyChapters_ValidRuntime_CorrectChaptersCount(long? runtime, int chaptersCount)
|
||||||
|
{
|
||||||
|
var chapters = _fFProbeVideoInfo.CreateDummyChapters(new Video()
|
||||||
|
{
|
||||||
|
RunTimeTicks = runtime
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal(chaptersCount, chapters.Length);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user