From df86aee35f7b21e339d8bf3614f073d68b7d2489 Mon Sep 17 00:00:00 2001 From: Eveldee Date: Thu, 17 Mar 2022 13:32:20 +0100 Subject: [PATCH] Update MkvInfoReader, Add MkvNode extensions --- MkvToolnixWrapper/MkvInfo/NodeUtils.cs | 21 ---- .../MkvInfo/{ => Reader}/MkvInfoReader.cs | 8 +- .../MkvInfo/{ => Reader}/MkvNode.cs | 2 +- .../MkvInfo/{ => Reader}/MkvNodeRoot.cs | 2 +- .../MkvInfo/{ => Reader}/MkvProperty.cs | 14 ++- .../MkvInfo/{ => Reader}/NodeType.cs | 2 +- MkvToolnixWrapper/MkvInfo/Reader/NodeUtils.cs | 107 ++++++++++++++++++ .../MkvInfo/{ => Reader}/PropertyType.cs | 4 +- MkvToolnixWrapper/Shared/TrackInfo.cs | 10 ++ 9 files changed, 142 insertions(+), 28 deletions(-) delete mode 100644 MkvToolnixWrapper/MkvInfo/NodeUtils.cs rename MkvToolnixWrapper/MkvInfo/{ => Reader}/MkvInfoReader.cs (91%) rename MkvToolnixWrapper/MkvInfo/{ => Reader}/MkvNode.cs (97%) rename MkvToolnixWrapper/MkvInfo/{ => Reader}/MkvNodeRoot.cs (87%) rename MkvToolnixWrapper/MkvInfo/{ => Reader}/MkvProperty.cs (76%) rename MkvToolnixWrapper/MkvInfo/{ => Reader}/NodeType.cs (74%) create mode 100644 MkvToolnixWrapper/MkvInfo/Reader/NodeUtils.cs rename MkvToolnixWrapper/MkvInfo/{ => Reader}/PropertyType.cs (52%) create mode 100644 MkvToolnixWrapper/Shared/TrackInfo.cs diff --git a/MkvToolnixWrapper/MkvInfo/NodeUtils.cs b/MkvToolnixWrapper/MkvInfo/NodeUtils.cs deleted file mode 100644 index 7acddab..0000000 --- a/MkvToolnixWrapper/MkvInfo/NodeUtils.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace MkvPropEditWrapper.MkvInfo; - -public static class NodeUtils -{ - public static IEnumerable Descendants(this MkvNode root) - { - var nodes = new Stack(new[] {root}); - - while (nodes.Any()) - { - var node = nodes.Pop(); - - yield return node; - - foreach (var newNode in node.Children) - { - nodes.Push(newNode); - } - } - } -} \ No newline at end of file diff --git a/MkvToolnixWrapper/MkvInfo/MkvInfoReader.cs b/MkvToolnixWrapper/MkvInfo/Reader/MkvInfoReader.cs similarity index 91% rename from MkvToolnixWrapper/MkvInfo/MkvInfoReader.cs rename to MkvToolnixWrapper/MkvInfo/Reader/MkvInfoReader.cs index da8c666..8db0b30 100644 --- a/MkvToolnixWrapper/MkvInfo/MkvInfoReader.cs +++ b/MkvToolnixWrapper/MkvInfo/Reader/MkvInfoReader.cs @@ -1,4 +1,6 @@ -namespace MkvPropEditWrapper.MkvInfo; +using System.Runtime.CompilerServices; + +namespace MkvPropEditWrapper.MkvInfo.Reader; public class MkvInfoReader { @@ -46,6 +48,7 @@ public class MkvInfoReader return _root; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ProcessLine(ReadOnlyMemory line) { var lineSpan = line.Span; @@ -71,7 +74,7 @@ public class MkvInfoReader if (propertyIndex != -1) { var name = content[..propertyIndex]; - var value = content[(propertyIndex + 1)..]; + var value = content[(propertyIndex + 2)..]; node = new MkvProperty(_currentNode, name, value); } @@ -90,6 +93,7 @@ public class MkvInfoReader /// Read in the span till next \n or EOF while incrementing _currentPosition /// /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] private ReadOnlyMemory ReadLine() { var remainingSpan = _remainingMemory.Span; diff --git a/MkvToolnixWrapper/MkvInfo/MkvNode.cs b/MkvToolnixWrapper/MkvInfo/Reader/MkvNode.cs similarity index 97% rename from MkvToolnixWrapper/MkvInfo/MkvNode.cs rename to MkvToolnixWrapper/MkvInfo/Reader/MkvNode.cs index 0a7603a..93a866a 100644 --- a/MkvToolnixWrapper/MkvInfo/MkvNode.cs +++ b/MkvToolnixWrapper/MkvInfo/Reader/MkvNode.cs @@ -1,7 +1,7 @@ using System.Collections; using System.Text; -namespace MkvPropEditWrapper.MkvInfo; +namespace MkvPropEditWrapper.MkvInfo.Reader; public class MkvNode : IEnumerable { diff --git a/MkvToolnixWrapper/MkvInfo/MkvNodeRoot.cs b/MkvToolnixWrapper/MkvInfo/Reader/MkvNodeRoot.cs similarity index 87% rename from MkvToolnixWrapper/MkvInfo/MkvNodeRoot.cs rename to MkvToolnixWrapper/MkvInfo/Reader/MkvNodeRoot.cs index 03470f4..37c0074 100644 --- a/MkvToolnixWrapper/MkvInfo/MkvNodeRoot.cs +++ b/MkvToolnixWrapper/MkvInfo/Reader/MkvNodeRoot.cs @@ -1,6 +1,6 @@ using System.Text; -namespace MkvPropEditWrapper.MkvInfo; +namespace MkvPropEditWrapper.MkvInfo.Reader; public class MkvNodeRoot : MkvNode { diff --git a/MkvToolnixWrapper/MkvInfo/MkvProperty.cs b/MkvToolnixWrapper/MkvInfo/Reader/MkvProperty.cs similarity index 76% rename from MkvToolnixWrapper/MkvInfo/MkvProperty.cs rename to MkvToolnixWrapper/MkvInfo/Reader/MkvProperty.cs index d69f721..5e7a255 100644 --- a/MkvToolnixWrapper/MkvInfo/MkvProperty.cs +++ b/MkvToolnixWrapper/MkvInfo/Reader/MkvProperty.cs @@ -1,11 +1,13 @@ using System.Text; -namespace MkvPropEditWrapper.MkvInfo; +namespace MkvPropEditWrapper.MkvInfo.Reader; public class MkvProperty : MkvNode { private static class KnownProperties { + public const string TrackType = "Track type"; + public const string TrackNumber = "Track number"; public const string FlagDefault = "\"Default track\" flag"; public const string FlagForced = "\"Forced display\" flag"; public const string Language = "Language"; @@ -26,6 +28,16 @@ public class MkvProperty : MkvNode private static PropertyType FindPropertyType(ReadOnlyMemory name) { var span = name.Span; + + if (span.SequenceEqual(KnownProperties.TrackType)) + { + return PropertyType.TrackType; + } + + if (span.SequenceEqual(KnownProperties.TrackNumber)) + { + return PropertyType.TrackNumber; + } if (span.SequenceEqual(KnownProperties.FlagDefault)) { diff --git a/MkvToolnixWrapper/MkvInfo/NodeType.cs b/MkvToolnixWrapper/MkvInfo/Reader/NodeType.cs similarity index 74% rename from MkvToolnixWrapper/MkvInfo/NodeType.cs rename to MkvToolnixWrapper/MkvInfo/Reader/NodeType.cs index 839d2db..4bf775a 100644 --- a/MkvToolnixWrapper/MkvInfo/NodeType.cs +++ b/MkvToolnixWrapper/MkvInfo/Reader/NodeType.cs @@ -1,4 +1,4 @@ -namespace MkvPropEditWrapper.MkvInfo; +namespace MkvPropEditWrapper.MkvInfo.Reader; public enum NodeType { diff --git a/MkvToolnixWrapper/MkvInfo/Reader/NodeUtils.cs b/MkvToolnixWrapper/MkvInfo/Reader/NodeUtils.cs new file mode 100644 index 0000000..5ec5c01 --- /dev/null +++ b/MkvToolnixWrapper/MkvInfo/Reader/NodeUtils.cs @@ -0,0 +1,107 @@ +using MkvPropEditWrapper.Shared; + +namespace MkvPropEditWrapper.MkvInfo.Reader; + +public static class NodeUtils +{ + public static IEnumerable Descendants(this MkvNode root) + { + var nodes = new Stack(new[] {root}); + + while (nodes.Any()) + { + var node = nodes.Pop(); + + yield return node; + + foreach (var newNode in node.Children) + { + nodes.Push(newNode); + } + } + } + + /// + /// Generate track info from parsed output, only works on the first root node as it uses absolute depth + /// + /// Node root + /// All parseable + public static IEnumerable GetTrackInfos(this MkvNodeRoot root) + { + TrackInfo? ParseTrackInfo(MkvNode track) + { + ReadOnlySpan audioType = "audio"; + ReadOnlySpan subtitleType = "subtitles"; + + int number = -1; + var trackType = TrackType.Unknown; + string language = "Unknown"; + bool defaultFlag = default; + bool forcedFlag = default; + + foreach (var child in track.Children) + { + if (child is MkvProperty property) + { + ReadOnlySpan span; + + switch (property.PropertyType) + { + case PropertyType.TrackType: + span = property.Value.Span; + + if (span.SequenceEqual(audioType)) + { + trackType = TrackType.Audio; + } + else if (span.SequenceEqual(subtitleType)) + { + trackType = TrackType.Subtitles; + } + else + { + return null; + } + + break; + case PropertyType.TrackNumber: + span = property.Value.Span; + + number = int.Parse(span[..span.IndexOf(' ')]); + break; + case PropertyType.Language: + language = property.Value.ToString(); + break; + case PropertyType.FlagDefault: + defaultFlag = property.Value.Span[0] == '1'; + break; + case PropertyType.FlagForced: + forcedFlag = property.Value.Span[0] == '1'; + break; + } + } + } + + return number == -1 ? null : new TrackInfo(number, trackType, language, defaultFlag, forcedFlag); + } + + var tracks = root.Descendants().Where(n => n is { Depth: 2, NodeType: NodeType.Track }); + + foreach (var track in tracks) + { + var trackInfo = ParseTrackInfo(track); + + if (trackInfo is not null) + { + yield return trackInfo; + } + } + } + + public static (IEnumerable audio, IEnumerable subtitles) SplitByType(this IEnumerable trackInfos) + { + var lookup = trackInfos.OrderBy(t => t.Number).ToLookup(t => t.TrackType); + + return (lookup[TrackType.Audio], lookup[TrackType.Subtitles]); + } +} \ No newline at end of file diff --git a/MkvToolnixWrapper/MkvInfo/PropertyType.cs b/MkvToolnixWrapper/MkvInfo/Reader/PropertyType.cs similarity index 52% rename from MkvToolnixWrapper/MkvInfo/PropertyType.cs rename to MkvToolnixWrapper/MkvInfo/Reader/PropertyType.cs index ee436ad..a8ce9de 100644 --- a/MkvToolnixWrapper/MkvInfo/PropertyType.cs +++ b/MkvToolnixWrapper/MkvInfo/Reader/PropertyType.cs @@ -1,7 +1,9 @@ -namespace MkvPropEditWrapper.MkvInfo; +namespace MkvPropEditWrapper.MkvInfo.Reader; public enum PropertyType { + TrackType, + TrackNumber, Unknown, FlagDefault, FlagForced, diff --git a/MkvToolnixWrapper/Shared/TrackInfo.cs b/MkvToolnixWrapper/Shared/TrackInfo.cs new file mode 100644 index 0000000..c4d14ae --- /dev/null +++ b/MkvToolnixWrapper/Shared/TrackInfo.cs @@ -0,0 +1,10 @@ +namespace MkvPropEditWrapper.Shared; + +public record TrackInfo(int Number, TrackType TrackType, string Language, bool IsDefault, bool IsForced); + +public enum TrackType +{ + Unknown, + Audio, + Subtitles +} \ No newline at end of file