From 2351eeba561905bafae48a948f3126797c284766 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Tue, 17 Sep 2024 20:29:43 +0200 Subject: Rework PR 6203 --- MediaBrowser.Model/Extensions/ContainerHelper.cs | 145 +++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 MediaBrowser.Model/Extensions/ContainerHelper.cs (limited to 'MediaBrowser.Model/Extensions/ContainerHelper.cs') diff --git a/MediaBrowser.Model/Extensions/ContainerHelper.cs b/MediaBrowser.Model/Extensions/ContainerHelper.cs new file mode 100644 index 000000000..4b75657ff --- /dev/null +++ b/MediaBrowser.Model/Extensions/ContainerHelper.cs @@ -0,0 +1,145 @@ +using System; +using System.Collections.Generic; +using Jellyfin.Extensions; + +namespace MediaBrowser.Model.Extensions; + +/// +/// Defines the class. +/// +public static class ContainerHelper +{ + /// + /// Compares two containers, returning true if an item in exists + /// in . + /// + /// The comma-delimited string being searched. + /// If the parameter begins with the - character, the operation is reversed. + /// The comma-delimited string being matched. + /// The result of the operation. + public static bool ContainsContainer(string? profileContainers, string? inputContainer) + { + var isNegativeList = false; + if (profileContainers != null && profileContainers.StartsWith('-')) + { + isNegativeList = true; + profileContainers = profileContainers[1..]; + } + + return ContainsContainer(profileContainers, isNegativeList, inputContainer); + } + + /// + /// Compares two containers, returning true if an item in exists + /// in . + /// + /// The comma-delimited string being searched. + /// If the parameter begins with the - character, the operation is reversed. + /// The comma-delimited string being matched. + /// The result of the operation. + public static bool ContainsContainer(string? profileContainers, ReadOnlySpan inputContainer) + { + var isNegativeList = false; + if (profileContainers != null && profileContainers.StartsWith('-')) + { + isNegativeList = true; + profileContainers = profileContainers[1..]; + } + + return ContainsContainer(profileContainers, isNegativeList, inputContainer); + } + + /// + /// Compares two containers, returning if an item in + /// does not exist in . + /// + /// The comma-delimited string being searched. + /// The boolean result to return if a match is not found. + /// The comma-delimited string being matched. + /// The result of the operation. + public static bool ContainsContainer(string? profileContainers, bool isNegativeList, string? inputContainer) + { + if (string.IsNullOrEmpty(inputContainer)) + { + return isNegativeList; + } + + return ContainsContainer(profileContainers, isNegativeList, inputContainer.AsSpan()); + } + + /// + /// Compares two containers, returning if an item in + /// does not exist in . + /// + /// The comma-delimited string being searched. + /// The boolean result to return if a match is not found. + /// The comma-delimited string being matched. + /// The result of the operation. + public static bool ContainsContainer(string? profileContainers, bool isNegativeList, ReadOnlySpan inputContainer) + { + if (string.IsNullOrEmpty(profileContainers)) + { + // Empty profiles always support all containers/codecs. + return true; + } + + var allInputContainers = inputContainer.Split(','); + var allProfileContainers = profileContainers.SpanSplit(','); + foreach (var container in allInputContainers) + { + if (!container.IsEmpty) + { + foreach (var profile in allProfileContainers) + { + if (container.Equals(profile, StringComparison.OrdinalIgnoreCase)) + { + return !isNegativeList; + } + } + } + } + + return isNegativeList; + } + + /// + /// Compares two containers, returning if an item in + /// does not exist in . + /// + /// The profile containers being matched searched. + /// The boolean result to return if a match is not found. + /// The comma-delimited string being matched. + /// The result of the operation. + public static bool ContainsContainer(IReadOnlyList? profileContainers, bool isNegativeList, string inputContainer) + { + if (profileContainers is null) + { + // Empty profiles always support all containers/codecs. + return true; + } + + var allInputContainers = inputContainer.Split(','); + foreach (var container in allInputContainers) + { + foreach (var profile in profileContainers) + { + if (string.Equals(profile, container, StringComparison.OrdinalIgnoreCase)) + { + return !isNegativeList; + } + } + } + + return isNegativeList; + } + + /// + /// Splits and input string. + /// + /// The input string. + /// The result of the operation. + public static string[] Split(string? input) + { + return input?.Split(',', StringSplitOptions.RemoveEmptyEntries) ?? []; + } +} -- cgit v1.2.3 From 5a5da33f44b933215c95947c479ded1cdbadbcd9 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Tue, 17 Sep 2024 23:34:12 +0200 Subject: Apply review suggestions --- MediaBrowser.Model/Dlna/StreamBuilder.cs | 7 +++--- MediaBrowser.Model/Extensions/ContainerHelper.cs | 4 +-- .../Dlna/ContainerHelperTests.cs | 29 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 6 deletions(-) (limited to 'MediaBrowser.Model/Extensions/ContainerHelper.cs') diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 6fc7f796d..bf122dcc7 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -407,10 +407,9 @@ namespace MediaBrowser.Model.Dlna continue; } - var formatStr = format.ToString(); - if (directPlayProfile.SupportsContainer(formatStr)) + if (directPlayProfile.SupportsContainer(format)) { - return formatStr; + return format; } } } @@ -1317,6 +1316,7 @@ namespace MediaBrowser.Model.Dlna } var containerSupported = false; + TranscodeReason[] rankings = [TranscodeReason.VideoCodecNotSupported, VideoCodecReasons, TranscodeReason.AudioCodecNotSupported, AudioCodecReasons, ContainerReasons]; // Check DirectPlay profiles to see if it can be direct played var analyzedProfiles = profile.DirectPlayProfiles @@ -1382,7 +1382,6 @@ namespace MediaBrowser.Model.Dlna playMethod = PlayMethod.DirectStream; } - TranscodeReason[] rankings = [TranscodeReason.VideoCodecNotSupported, VideoCodecReasons, TranscodeReason.AudioCodecNotSupported, AudioCodecReasons, ContainerReasons]; var ranked = GetRank(ref failureReasons, rankings); return (Result: (Profile: directPlayProfile, PlayMethod: playMethod, AudioStreamIndex: selectedAudioStream?.Index, TranscodeReason: failureReasons), Order: order, Rank: ranked); diff --git a/MediaBrowser.Model/Extensions/ContainerHelper.cs b/MediaBrowser.Model/Extensions/ContainerHelper.cs index 4b75657ff..c86328ba6 100644 --- a/MediaBrowser.Model/Extensions/ContainerHelper.cs +++ b/MediaBrowser.Model/Extensions/ContainerHelper.cs @@ -91,7 +91,7 @@ public static class ContainerHelper { foreach (var profile in allProfileContainers) { - if (container.Equals(profile, StringComparison.OrdinalIgnoreCase)) + if (!profile.IsEmpty && container.Equals(profile, StringComparison.OrdinalIgnoreCase)) { return !isNegativeList; } @@ -118,7 +118,7 @@ public static class ContainerHelper return true; } - var allInputContainers = inputContainer.Split(','); + var allInputContainers = Split(inputContainer); foreach (var container in allInputContainers) { foreach (var profile in profileContainers) diff --git a/tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs b/tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs index 68f8d94c7..1ad4bed56 100644 --- a/tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs +++ b/tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs @@ -40,6 +40,11 @@ public class ContainerHelperTests public void ContainsContainer_NotInList_ReturnsFalse(string container, string? extension) { Assert.False(ContainerHelper.ContainsContainer(container, extension)); + + if (extension is not null) + { + Assert.False(ContainerHelper.ContainsContainer(container, extension.AsSpan())); + } } [Theory] @@ -51,4 +56,28 @@ public class ContainerHelperTests { Assert.True(ContainerHelper.ContainsContainer(container, extension.AsSpan())); } + + [Theory] + [InlineData(new string[] { "mp3", "mpeg" }, false, "mpeg")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, false, "avi")] + [InlineData(new string[] { "mp3", "", "avi" }, false, "mp3")] + [InlineData(new string[] { "mp3", "mpeg" }, true, "avi")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, true, "mkv")] + [InlineData(new string[] { "mp3", "", "avi" }, true, "")] + public void ContainsContainer_ThreeArgs_InList_ReturnsTrue(string[] containers, bool isNegativeList, string inputContainer) + { + Assert.True(ContainerHelper.ContainsContainer(containers, isNegativeList, inputContainer)); + } + + [Theory] + [InlineData(new string[] { "mp3", "mpeg" }, false, "avi")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, false, "mkv")] + [InlineData(new string[] { "mp3", "", "avi" }, false, "")] + [InlineData(new string[] { "mp3", "mpeg" }, true, "mpeg")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, true, "mp3")] + [InlineData(new string[] { "mp3", "", "avi" }, true, "avi")] + public void ContainsContainer_ThreeArgs_InList_ReturnsFalse(string[] containers, bool isNegativeList, string inputContainer) + { + Assert.False(ContainerHelper.ContainsContainer(containers, isNegativeList, inputContainer)); + } } -- cgit v1.2.3