diff options
| author | Marc Brooks <IDisposable@gmail.com> | 2025-03-12 10:33:27 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-12 10:33:27 -0500 |
| commit | a5f3d942f691b914b67b098f7a64406bea569aad (patch) | |
| tree | b4c73319032ef4b62d6f00e4bc9ff8971b504793 /src | |
| parent | 114591c1aacbdf4d07e95c536ea2e42af1c5ab0d (diff) | |
| parent | 237e7bd44b3c9a6f76892be1c6a925bcde64bdbf (diff) | |
Merge branch 'master' into sort-nfo-data
Diffstat (limited to 'src')
| -rw-r--r-- | src/Jellyfin.Drawing/ImageProcessor.cs | 2 | ||||
| -rw-r--r-- | src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedCollectionConverter.cs (renamed from src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs) | 8 | ||||
| -rw-r--r-- | src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedCollectionConverterFactory.cs (renamed from src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs) | 11 | ||||
| -rw-r--r-- | src/Jellyfin.Extensions/Json/Converters/JsonDelimitedCollectionConverter.cs (renamed from src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs) | 38 | ||||
| -rw-r--r-- | src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedCollectionConverter.cs (renamed from src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs) | 6 | ||||
| -rw-r--r-- | src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedCollectionConverterFactory.cs (renamed from src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs) | 11 | ||||
| -rw-r--r-- | src/Jellyfin.LiveTv/Guide/GuideManager.cs | 108 | ||||
| -rw-r--r-- | src/Jellyfin.Networking/Manager/NetworkManager.cs | 23 |
8 files changed, 80 insertions, 127 deletions
diff --git a/src/Jellyfin.Drawing/ImageProcessor.cs b/src/Jellyfin.Drawing/ImageProcessor.cs index 0bd3b8920..fcb315b3a 100644 --- a/src/Jellyfin.Drawing/ImageProcessor.cs +++ b/src/Jellyfin.Drawing/ImageProcessor.cs @@ -68,7 +68,7 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable var semaphoreCount = config.Configuration.ParallelImageEncodingLimit; if (semaphoreCount < 1) { - semaphoreCount = 2 * Environment.ProcessorCount; + semaphoreCount = Environment.ProcessorCount; } _parallelEncodingLimit = new(semaphoreCount); diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedCollectionConverter.cs index ccbc296fd..b1946143d 100644 --- a/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedCollectionConverter.cs @@ -1,15 +1,15 @@ namespace Jellyfin.Extensions.Json.Converters { /// <summary> - /// Convert comma delimited string to array of type. + /// Convert comma delimited string to collection of type. /// </summary> /// <typeparam name="T">Type to convert to.</typeparam> - public sealed class JsonCommaDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T> + public sealed class JsonCommaDelimitedCollectionConverter<T> : JsonDelimitedCollectionConverter<T> { /// <summary> - /// Initializes a new instance of the <see cref="JsonCommaDelimitedArrayConverter{T}"/> class. + /// Initializes a new instance of the <see cref="JsonCommaDelimitedCollectionConverter{T}"/> class. /// </summary> - public JsonCommaDelimitedArrayConverter() : base() + public JsonCommaDelimitedCollectionConverter() : base() { } diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedCollectionConverterFactory.cs index a95e493db..daa79b2b5 100644 --- a/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedArrayConverterFactory.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonCommaDelimitedCollectionConverterFactory.cs @@ -1,28 +1,31 @@ using System; +using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; namespace Jellyfin.Extensions.Json.Converters { /// <summary> - /// Json comma delimited array converter factory. + /// Json comma delimited collection converter factory. /// </summary> /// <remarks> /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. /// </remarks> - public class JsonCommaDelimitedArrayConverterFactory : JsonConverterFactory + public class JsonCommaDelimitedCollectionConverterFactory : JsonConverterFactory { /// <inheritdoc /> public override bool CanConvert(Type typeToConvert) { - return true; + return typeToConvert.IsArray + || (typeToConvert.IsGenericType + && (typeToConvert.GetGenericTypeDefinition().IsAssignableFrom(typeof(IReadOnlyCollection<>)) || typeToConvert.GetGenericTypeDefinition().IsAssignableFrom(typeof(IReadOnlyList<>)))); } /// <inheritdoc /> public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; - return (JsonConverter?)Activator.CreateInstance(typeof(JsonCommaDelimitedArrayConverter<>).MakeGenericType(structType)); + return (JsonConverter?)Activator.CreateInstance(typeof(JsonCommaDelimitedCollectionConverter<>).MakeGenericType(structType)); } } } diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedCollectionConverter.cs index 7472f9c66..fe85d7f73 100644 --- a/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedArrayConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonDelimitedCollectionConverter.cs @@ -10,14 +10,14 @@ namespace Jellyfin.Extensions.Json.Converters /// Convert delimited string to array of type. /// </summary> /// <typeparam name="T">Type to convert to.</typeparam> - public abstract class JsonDelimitedArrayConverter<T> : JsonConverter<T[]> + public abstract class JsonDelimitedCollectionConverter<T> : JsonConverter<IReadOnlyCollection<T>> { private readonly TypeConverter _typeConverter; /// <summary> - /// Initializes a new instance of the <see cref="JsonDelimitedArrayConverter{T}"/> class. + /// Initializes a new instance of the <see cref="JsonDelimitedCollectionConverter{T}"/> class. /// </summary> - protected JsonDelimitedArrayConverter() + protected JsonDelimitedCollectionConverter() { _typeConverter = TypeDescriptor.GetConverter(typeof(T)); } @@ -28,7 +28,7 @@ namespace Jellyfin.Extensions.Json.Converters protected virtual char Delimiter { get; } /// <inheritdoc /> - public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public override IReadOnlyCollection<T>? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { @@ -56,35 +56,21 @@ namespace Jellyfin.Extensions.Json.Converters } } - return typedValues.ToArray(); + if (typeToConvert.IsArray) + { + return typedValues.ToArray(); + } + + return typedValues; } return JsonSerializer.Deserialize<T[]>(ref reader, options); } /// <inheritdoc /> - public override void Write(Utf8JsonWriter writer, T[]? value, JsonSerializerOptions options) + public override void Write(Utf8JsonWriter writer, IReadOnlyCollection<T>? value, JsonSerializerOptions options) { - if (value is not null) - { - writer.WriteStartArray(); - if (value.Length > 0) - { - foreach (var it in value) - { - if (it is not null) - { - writer.WriteStringValue(it.ToString()); - } - } - } - - writer.WriteEndArray(); - } - else - { - writer.WriteNullValue(); - } + JsonSerializer.Serialize(writer, value, options); } } } diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedCollectionConverter.cs index 55720ee4f..57378a360 100644 --- a/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverter.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedCollectionConverter.cs @@ -4,12 +4,12 @@ namespace Jellyfin.Extensions.Json.Converters /// Convert Pipe delimited string to array of type. /// </summary> /// <typeparam name="T">Type to convert to.</typeparam> - public sealed class JsonPipeDelimitedArrayConverter<T> : JsonDelimitedArrayConverter<T> + public sealed class JsonPipeDelimitedCollectionConverter<T> : JsonDelimitedCollectionConverter<T> { /// <summary> - /// Initializes a new instance of the <see cref="JsonPipeDelimitedArrayConverter{T}"/> class. + /// Initializes a new instance of the <see cref="JsonPipeDelimitedCollectionConverter{T}"/> class. /// </summary> - public JsonPipeDelimitedArrayConverter() : base() + public JsonPipeDelimitedCollectionConverter() : base() { } diff --git a/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedCollectionConverterFactory.cs index ae9e1f67a..f487fcaca 100644 --- a/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedArrayConverterFactory.cs +++ b/src/Jellyfin.Extensions/Json/Converters/JsonPipeDelimitedCollectionConverterFactory.cs @@ -1,28 +1,31 @@ using System; +using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; namespace Jellyfin.Extensions.Json.Converters { /// <summary> - /// Json Pipe delimited array converter factory. + /// Json Pipe delimited collection converter factory. /// </summary> /// <remarks> /// This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. /// </remarks> - public class JsonPipeDelimitedArrayConverterFactory : JsonConverterFactory + public class JsonPipeDelimitedCollectionConverterFactory : JsonConverterFactory { /// <inheritdoc /> public override bool CanConvert(Type typeToConvert) { - return true; + return typeToConvert.IsArray + || (typeToConvert.IsGenericType + && (typeToConvert.GetGenericTypeDefinition().IsAssignableFrom(typeof(IReadOnlyCollection<>)) || typeToConvert.GetGenericTypeDefinition().IsAssignableFrom(typeof(IReadOnlyList<>)))); } /// <inheritdoc /> public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var structType = typeToConvert.GetElementType() ?? typeToConvert.GenericTypeArguments[0]; - return (JsonConverter?)Activator.CreateInstance(typeof(JsonPipeDelimitedArrayConverter<>).MakeGenericType(structType)); + return (JsonConverter?)Activator.CreateInstance(typeof(JsonPipeDelimitedCollectionConverter<>).MakeGenericType(structType)); } } } diff --git a/src/Jellyfin.LiveTv/Guide/GuideManager.cs b/src/Jellyfin.LiveTv/Guide/GuideManager.cs index b75cc0fb2..ac59a6d12 100644 --- a/src/Jellyfin.LiveTv/Guide/GuideManager.cs +++ b/src/Jellyfin.LiveTv/Guide/GuideManager.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; -using Jellyfin.Data.Entities.Libraries; using Jellyfin.Data.Enums; using Jellyfin.Extensions; using Jellyfin.LiveTv.Configuration; @@ -210,7 +209,7 @@ public class GuideManager : IGuideManager progress.Report(15); numComplete = 0; - var programs = new List<LiveTvProgram>(); + var programIds = new List<Guid>(); var channels = new List<Guid>(); var guideDays = GetGuideDays(); @@ -243,8 +242,8 @@ public class GuideManager : IGuideManager DtoOptions = new DtoOptions(true) }).Cast<LiveTvProgram>().ToDictionary(i => i.Id); - var newPrograms = new List<Guid>(); - var updatedPrograms = new List<Guid>(); + var newPrograms = new List<LiveTvProgram>(); + var updatedPrograms = new List<LiveTvProgram>(); foreach (var program in channelPrograms) { @@ -252,14 +251,14 @@ public class GuideManager : IGuideManager var id = programItem.Id; if (isNew) { - newPrograms.Add(id); + newPrograms.Add(programItem); } else if (isUpdated) { - updatedPrograms.Add(id); + updatedPrograms.Add(programItem); } - programs.Add(programItem); + programIds.Add(programItem.Id); isMovie |= program.IsMovie; isSeries |= program.IsSeries; @@ -276,21 +275,21 @@ public class GuideManager : IGuideManager if (newPrograms.Count > 0) { - var newProgramDtos = programs.Where(b => newPrograms.Contains(b.Id)).ToList(); - _libraryManager.CreateOrUpdateItems(newProgramDtos, null, cancellationToken); + _libraryManager.CreateItems(newPrograms, currentChannel, cancellationToken); + + await PreCacheImages(newPrograms, maxCacheDate).ConfigureAwait(false); } if (updatedPrograms.Count > 0) { - var updatedProgramDtos = programs.Where(b => updatedPrograms.Contains(b.Id)).ToList(); await _libraryManager.UpdateItemsAsync( - updatedProgramDtos, + updatedPrograms, currentChannel, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); - } - await PreCacheImages(programs, maxCacheDate).ConfigureAwait(false); + await PreCacheImages(updatedPrograms, maxCacheDate).ConfigureAwait(false); + } currentChannel.IsMovie = isMovie; currentChannel.IsNews = isNews; @@ -326,7 +325,6 @@ public class GuideManager : IGuideManager } progress.Report(100); - var programIds = programs.Select(p => p.Id).ToList(); return new Tuple<List<Guid>, List<Guid>>(channels, programIds); } @@ -502,35 +500,27 @@ public class GuideManager : IGuideManager forceUpdate = true; } - var seriesId = info.SeriesId; - - if (!item.ParentId.Equals(channel.Id)) + var channelId = channel.Id; + if (!item.ParentId.Equals(channelId)) { + item.ParentId = channel.Id; forceUpdate = true; } - item.ParentId = channel.Id; - item.Audio = info.Audio; - item.ChannelId = channel.Id; - item.CommunityRating ??= info.CommunityRating; - if ((item.CommunityRating ?? 0).Equals(0)) - { - item.CommunityRating = null; - } - + item.ChannelId = channelId; + item.CommunityRating = info.CommunityRating; item.EpisodeTitle = info.EpisodeTitle; item.ExternalId = info.Id; - if (!string.IsNullOrWhiteSpace(seriesId) && !string.Equals(item.ExternalSeriesId, seriesId, StringComparison.Ordinal)) + var seriesId = info.SeriesId; + if (!string.IsNullOrWhiteSpace(seriesId) && !string.Equals(item.ExternalSeriesId, seriesId, StringComparison.OrdinalIgnoreCase)) { + item.ExternalSeriesId = seriesId; forceUpdate = true; } - item.ExternalSeriesId = seriesId; - var isSeries = info.IsSeries || !string.IsNullOrEmpty(info.EpisodeTitle); - if (isSeries || !string.IsNullOrEmpty(info.EpisodeTitle)) { item.SeriesName = info.Name; @@ -578,7 +568,6 @@ public class GuideManager : IGuideManager } item.Tags = tags.ToArray(); - item.Genres = info.Genres.ToArray(); if (info.IsHD ?? false) @@ -589,41 +578,35 @@ public class GuideManager : IGuideManager item.IsMovie = info.IsMovie; item.IsRepeat = info.IsRepeat; - if (item.IsSeries != isSeries) { + item.IsSeries = isSeries; forceUpdate = true; } - item.IsSeries = isSeries; - item.Name = info.Name; - item.OfficialRating ??= info.OfficialRating; - item.Overview ??= info.Overview; + item.OfficialRating = info.OfficialRating; + item.Overview = info.Overview; item.RunTimeTicks = (info.EndDate - info.StartDate).Ticks; - item.ProviderIds = info.ProviderIds; - foreach (var providerId in info.SeriesProviderIds) { info.ProviderIds["Series" + providerId.Key] = providerId.Value; } + item.ProviderIds = info.ProviderIds; if (item.StartDate != info.StartDate) { + item.StartDate = info.StartDate; forceUpdate = true; } - item.StartDate = info.StartDate; - if (item.EndDate != info.EndDate) { + item.EndDate = info.EndDate; forceUpdate = true; } - item.EndDate = info.EndDate; - item.ProductionYear = info.ProductionYear; - if (!isSeries || info.IsRepeat) { item.PremiereDate = info.OriginalAirDate; @@ -632,37 +615,35 @@ public class GuideManager : IGuideManager item.IndexNumber = info.EpisodeNumber; item.ParentIndexNumber = info.SeasonNumber; - forceUpdate = forceUpdate || UpdateImages(item, info); + forceUpdate |= UpdateImages(item, info); if (isNew) { item.OnMetadataChanged(); - return (item, isNew, false); + return (item, true, false); } - var isUpdated = false; - if (forceUpdate || string.IsNullOrWhiteSpace(info.Etag)) + var isUpdated = forceUpdate; + var etag = info.Etag; + if (string.IsNullOrWhiteSpace(etag)) { isUpdated = true; } - else + else if (!string.Equals(etag, item.GetProviderId(EtagKey), StringComparison.OrdinalIgnoreCase)) { - var etag = info.Etag; - - if (!string.Equals(etag, item.GetProviderId(EtagKey), StringComparison.OrdinalIgnoreCase)) - { - item.SetProviderId(EtagKey, etag); - isUpdated = true; - } + item.SetProviderId(EtagKey, etag); + isUpdated = true; } if (isUpdated) { item.OnMetadataChanged(); + + return (item, false, true); } - return (item, isNew, isUpdated); + return (item, false, false); } private static bool UpdateImages(BaseItem item, ProgramInfo info) @@ -679,7 +660,9 @@ public class GuideManager : IGuideManager updated |= UpdateImage(ImageType.Logo, item, info); // Backdrop - return updated || UpdateImage(ImageType.Backdrop, item, info); + updated |= UpdateImage(ImageType.Backdrop, item, info); + + return updated; } private static bool UpdateImage(ImageType imageType, BaseItem item, ProgramInfo info) @@ -689,7 +672,7 @@ public class GuideManager : IGuideManager var newImagePath = imageType switch { ImageType.Primary => info.ImagePath, - _ => string.Empty + _ => null }; var newImageUrl = imageType switch { @@ -697,12 +680,12 @@ public class GuideManager : IGuideManager ImageType.Logo => info.LogoImageUrl, ImageType.Primary => info.ImageUrl, ImageType.Thumb => info.ThumbImageUrl, - _ => string.Empty + _ => null }; - var differentImage = newImageUrl?.Equals(currentImagePath, StringComparison.OrdinalIgnoreCase) == false - || newImagePath?.Equals(currentImagePath, StringComparison.OrdinalIgnoreCase) == false; - if (!differentImage) + var sameImage = (currentImagePath?.Equals(newImageUrl, StringComparison.OrdinalIgnoreCase) ?? false) + || (currentImagePath?.Equals(newImagePath, StringComparison.OrdinalIgnoreCase) ?? false); + if (sameImage) { return false; } @@ -757,6 +740,7 @@ public class GuideManager : IGuideManager var imageInfo = program.ImageInfos[i]; if (!imageInfo.IsLocalFile) { + _logger.LogDebug("Caching image locally: {Url}", imageInfo.Path); try { program.ImageInfos[i] = await _libraryManager.ConvertImageToLocal( diff --git a/src/Jellyfin.Networking/Manager/NetworkManager.cs b/src/Jellyfin.Networking/Manager/NetworkManager.cs index dd01e9533..2fbcbf79c 100644 --- a/src/Jellyfin.Networking/Manager/NetworkManager.cs +++ b/src/Jellyfin.Networking/Manager/NetworkManager.cs @@ -50,11 +50,6 @@ public class NetworkManager : INetworkManager, IDisposable private bool _eventfire; /// <summary> - /// List of all interface MAC addresses. - /// </summary> - private IReadOnlyList<PhysicalAddress> _macAddresses; - - /// <summary> /// Dictionary containing interface addresses and their subnets. /// </summary> private List<IPData> _interfaces; @@ -91,7 +86,6 @@ public class NetworkManager : INetworkManager, IDisposable _startupConfig = startupConfig; _initLock = new(); _interfaces = new List<IPData>(); - _macAddresses = new List<PhysicalAddress>(); _publishedServerUrls = new List<PublishedServerUriOverride>(); _networkEventLock = new(); _remoteAddressFilter = new List<IPNetwork>(); @@ -215,7 +209,6 @@ public class NetworkManager : INetworkManager, IDisposable /// <summary> /// Generate a list of all the interface ip addresses and submasks where that are in the active/unknown state. - /// Generate a list of all active mac addresses that aren't loopback addresses. /// </summary> private void InitializeInterfaces() { @@ -224,7 +217,6 @@ public class NetworkManager : INetworkManager, IDisposable _logger.LogDebug("Refreshing interfaces."); var interfaces = new List<IPData>(); - var macAddresses = new List<PhysicalAddress>(); try { @@ -236,13 +228,6 @@ public class NetworkManager : INetworkManager, IDisposable try { var ipProperties = adapter.GetIPProperties(); - var mac = adapter.GetPhysicalAddress(); - - // Populate MAC list - if (adapter.NetworkInterfaceType != NetworkInterfaceType.Loopback && !PhysicalAddress.None.Equals(mac)) - { - macAddresses.Add(mac); - } // Populate interface list foreach (var info in ipProperties.UnicastAddresses) @@ -302,7 +287,6 @@ public class NetworkManager : INetworkManager, IDisposable _logger.LogDebug("Discovered {NumberOfInterfaces} interfaces.", interfaces.Count); _logger.LogDebug("Interfaces addresses: {Addresses}", interfaces.OrderByDescending(s => s.AddressFamily == AddressFamily.InterNetwork).Select(s => s.Address.ToString())); - _macAddresses = macAddresses; _interfaces = interfaces; } } @@ -712,13 +696,6 @@ public class NetworkManager : INetworkManager, IDisposable } /// <inheritdoc/> - public IReadOnlyList<PhysicalAddress> GetMacAddresses() - { - // Populated in construction - so always has values. - return _macAddresses; - } - - /// <inheritdoc/> public IReadOnlyList<IPData> GetLoopbacks() { if (!IsIPv4Enabled && !IsIPv6Enabled) |
