Update MkvInfoReader, Add MkvNode extensions
This commit is contained in:
@@ -1,21 +0,0 @@
|
|||||||
namespace MkvPropEditWrapper.MkvInfo;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
namespace MkvPropEditWrapper.MkvInfo;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
namespace MkvPropEditWrapper.MkvInfo.Reader;
|
||||||
|
|
||||||
public class MkvInfoReader
|
public class MkvInfoReader
|
||||||
{
|
{
|
||||||
@@ -46,6 +48,7 @@ public class MkvInfoReader
|
|||||||
return _root;
|
return _root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void ProcessLine(ReadOnlyMemory<char> line)
|
private void ProcessLine(ReadOnlyMemory<char> line)
|
||||||
{
|
{
|
||||||
var lineSpan = line.Span;
|
var lineSpan = line.Span;
|
||||||
@@ -71,7 +74,7 @@ public class MkvInfoReader
|
|||||||
if (propertyIndex != -1)
|
if (propertyIndex != -1)
|
||||||
{
|
{
|
||||||
var name = content[..propertyIndex];
|
var name = content[..propertyIndex];
|
||||||
var value = content[(propertyIndex + 1)..];
|
var value = content[(propertyIndex + 2)..];
|
||||||
|
|
||||||
node = new MkvProperty(_currentNode, name, value);
|
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
|
/// Read in the span till next \n or EOF while incrementing _currentPosition
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private ReadOnlyMemory<char> ReadLine()
|
private ReadOnlyMemory<char> ReadLine()
|
||||||
{
|
{
|
||||||
var remainingSpan = _remainingMemory.Span;
|
var remainingSpan = _remainingMemory.Span;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace MkvPropEditWrapper.MkvInfo;
|
namespace MkvPropEditWrapper.MkvInfo.Reader;
|
||||||
|
|
||||||
public class MkvNode : IEnumerable<MkvNode>
|
public class MkvNode : IEnumerable<MkvNode>
|
||||||
{
|
{
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace MkvPropEditWrapper.MkvInfo;
|
namespace MkvPropEditWrapper.MkvInfo.Reader;
|
||||||
|
|
||||||
public class MkvNodeRoot : MkvNode
|
public class MkvNodeRoot : MkvNode
|
||||||
{
|
{
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace MkvPropEditWrapper.MkvInfo;
|
namespace MkvPropEditWrapper.MkvInfo.Reader;
|
||||||
|
|
||||||
public class MkvProperty : MkvNode
|
public class MkvProperty : MkvNode
|
||||||
{
|
{
|
||||||
private static class KnownProperties
|
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 FlagDefault = "\"Default track\" flag";
|
||||||
public const string FlagForced = "\"Forced display\" flag";
|
public const string FlagForced = "\"Forced display\" flag";
|
||||||
public const string Language = "Language";
|
public const string Language = "Language";
|
||||||
@@ -26,6 +28,16 @@ public class MkvProperty : MkvNode
|
|||||||
private static PropertyType FindPropertyType(ReadOnlyMemory<char> name)
|
private static PropertyType FindPropertyType(ReadOnlyMemory<char> name)
|
||||||
{
|
{
|
||||||
var span = name.Span;
|
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))
|
if (span.SequenceEqual(KnownProperties.FlagDefault))
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace MkvPropEditWrapper.MkvInfo;
|
namespace MkvPropEditWrapper.MkvInfo.Reader;
|
||||||
|
|
||||||
public enum NodeType
|
public enum NodeType
|
||||||
{
|
{
|
||||||
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
namespace MkvPropEditWrapper.MkvInfo;
|
namespace MkvPropEditWrapper.MkvInfo.Reader;
|
||||||
|
|
||||||
public enum PropertyType
|
public enum PropertyType
|
||||||
{
|
{
|
||||||
|
TrackType,
|
||||||
|
TrackNumber,
|
||||||
Unknown,
|
Unknown,
|
||||||
FlagDefault,
|
FlagDefault,
|
||||||
FlagForced,
|
FlagForced,
|
||||||
10
MkvToolnixWrapper/Shared/TrackInfo.cs
Normal file
10
MkvToolnixWrapper/Shared/TrackInfo.cs
Normal file
@@ -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
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user