Update MkvInfoReader, Add MkvNode extensions
This commit is contained in:
107
MkvToolnixWrapper/MkvInfo/Reader/NodeUtils.cs
Normal file
107
MkvToolnixWrapper/MkvInfo/Reader/NodeUtils.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using MkvPropEditWrapper.Shared;
|
||||
|
||||
namespace MkvPropEditWrapper.MkvInfo.Reader;
|
||||
|
||||
public static class NodeUtils
|
||||
{
|
||||
public static IEnumerable<MkvNode> Descendants(this MkvNode root)
|
||||
{
|
||||
var nodes = new Stack<MkvNode>(new[] {root});
|
||||
|
||||
while (nodes.Any())
|
||||
{
|
||||
var node = nodes.Pop();
|
||||
|
||||
yield return node;
|
||||
|
||||
foreach (var newNode in node.Children)
|
||||
{
|
||||
nodes.Push(newNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate track info from parsed output, only works on the first root node as it uses absolute depth
|
||||
/// </summary>
|
||||
/// <param name="root">Node root</param>
|
||||
/// <returns>All parseable <see cref="TrackInfo"/></returns>
|
||||
public static IEnumerable<TrackInfo> GetTrackInfos(this MkvNodeRoot root)
|
||||
{
|
||||
TrackInfo? ParseTrackInfo(MkvNode track)
|
||||
{
|
||||
ReadOnlySpan<char> audioType = "audio";
|
||||
ReadOnlySpan<char> 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<char> 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<TrackInfo> audio, IEnumerable<TrackInfo> subtitles) SplitByType(this IEnumerable<TrackInfo> trackInfos)
|
||||
{
|
||||
var lookup = trackInfos.OrderBy(t => t.Number).ToLookup(t => t.TrackType);
|
||||
|
||||
return (lookup[TrackType.Audio], lookup[TrackType.Subtitles]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user