Initial AmiReel application
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
|
||||
namespace AmigaDB.VideoRenderer.Services;
|
||||
|
||||
public sealed partial class ProcessRunner
|
||||
{
|
||||
public async Task<string> RunAsync(
|
||||
string executable,
|
||||
IEnumerable<string> arguments,
|
||||
Action<string>? log,
|
||||
Action<TimeSpan>? position,
|
||||
CancellationToken token,
|
||||
bool allowFailure = false)
|
||||
{
|
||||
ProcessStartInfo start = new()
|
||||
{
|
||||
FileName = executable,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true,
|
||||
RedirectStandardError = true,
|
||||
RedirectStandardOutput = true,
|
||||
StandardErrorEncoding = Encoding.UTF8,
|
||||
StandardOutputEncoding = Encoding.UTF8
|
||||
};
|
||||
foreach (string argument in arguments)
|
||||
start.ArgumentList.Add(argument);
|
||||
|
||||
using Process process = new() { StartInfo = start, EnableRaisingEvents = true };
|
||||
StringBuilder output = new();
|
||||
process.Start();
|
||||
|
||||
Task stdout = PumpAsync(process.StandardOutput, output, log, position, token);
|
||||
Task stderr = PumpAsync(process.StandardError, output, log, position, token);
|
||||
using CancellationTokenRegistration registration = token.Register(() =>
|
||||
{
|
||||
try { if (!process.HasExited) process.Kill(true); } catch { }
|
||||
});
|
||||
|
||||
await Task.WhenAll(stdout, stderr, process.WaitForExitAsync(token));
|
||||
if (process.ExitCode != 0 && !allowFailure)
|
||||
throw new InvalidOperationException($"Process exited with code {process.ExitCode}.\n{output}");
|
||||
return output.ToString();
|
||||
}
|
||||
|
||||
private static async Task PumpAsync(
|
||||
StreamReader reader, StringBuilder output, Action<string>? log,
|
||||
Action<TimeSpan>? position, CancellationToken token)
|
||||
{
|
||||
while (await reader.ReadLineAsync(token) is { } line)
|
||||
{
|
||||
output.AppendLine(line);
|
||||
log?.Invoke(line);
|
||||
Match match = TimeRegex().Match(line);
|
||||
if (match.Success && TimeSpan.TryParse(match.Groups[1].Value, CultureInfo.InvariantCulture, out TimeSpan time))
|
||||
position?.Invoke(time);
|
||||
}
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"time=(\d{2}:\d{2}:\d{2}(?:\.\d+)?)", RegexOptions.CultureInvariant)]
|
||||
private static partial Regex TimeRegex();
|
||||
}
|
||||
Reference in New Issue
Block a user