Add AquaSynth automation stream receipts
This commit is contained in:
parent
ee6501558c
commit
8c5f6d604a
7 changed files with 408 additions and 5 deletions
|
|
@ -35,6 +35,7 @@ internal static class AquaSynthDaemonCli
|
|||
return mode switch
|
||||
{
|
||||
"once" => await RunOnceAsync(service, options, output).ConfigureAwait(false),
|
||||
"stream" => await RunStreamOnceAsync(service, options, output).ConfigureAwait(false),
|
||||
"daemon" => await RunDaemonAsync(service, input, output, error).ConfigureAwait(false),
|
||||
_ => await UnknownModeAsync(mode, error).ConfigureAwait(false)
|
||||
};
|
||||
|
|
@ -64,6 +65,31 @@ internal static class AquaSynthDaemonCli
|
|||
return string.Equals(result.RenderReceipt.Status, "succeeded", StringComparison.Ordinal) ? 0 : 2;
|
||||
}
|
||||
|
||||
private static async Task<int> RunStreamOnceAsync(
|
||||
AquaSynthDaemonService service,
|
||||
IReadOnlyDictionary<string, string> options,
|
||||
TextWriter output)
|
||||
{
|
||||
var script = options.TryGetValue("--script", out var inlineScript)
|
||||
? inlineScript
|
||||
: await File.ReadAllTextAsync(Value(options, "--script-file", "")).ConfigureAwait(false);
|
||||
|
||||
var command = new AquaSynthAutomationStreamCommand(
|
||||
Value(options, "--command-id", $"stream-{DateTimeOffset.UtcNow:yyyyMMddHHmmssfff}"),
|
||||
Value(options, "--patch-id", "cli.stream.patch"),
|
||||
Value(options, "--faust-name", "aquasynth_cli_stream"),
|
||||
script,
|
||||
IntValue(options, "--block-size", 128),
|
||||
IntValue(options, "--blocks", 8),
|
||||
ParseControlFrames(Value(options, "--control-frame", "")),
|
||||
FloatValue(options, "--gain", 1.0f),
|
||||
IntValue(options, "--revision", 1));
|
||||
|
||||
var receipt = await service.StreamAutomationAsync(command).ConfigureAwait(false);
|
||||
await output.WriteLineAsync(JsonSerializer.Serialize(receipt, JsonOptions)).ConfigureAwait(false);
|
||||
return string.Equals(receipt.Status, "succeeded", StringComparison.Ordinal) ? 0 : 2;
|
||||
}
|
||||
|
||||
private static async Task<int> RunDaemonAsync(
|
||||
AquaSynthDaemonService service,
|
||||
TextReader input,
|
||||
|
|
@ -97,6 +123,13 @@ internal static class AquaSynthDaemonCli
|
|||
var receipt = await service.SampleAsync(command).ConfigureAwait(false);
|
||||
await output.WriteLineAsync(JsonSerializer.Serialize(receipt, JsonOptions)).ConfigureAwait(false);
|
||||
}
|
||||
else if (string.Equals(envelope.Command, "instrument.stream", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var command = envelope.Payload.Deserialize<AquaSynthAutomationStreamCommand>(JsonOptions)
|
||||
?? throw new InvalidOperationException("instrument.stream payload was empty.");
|
||||
var receipt = await service.StreamAutomationAsync(command).ConfigureAwait(false);
|
||||
await output.WriteLineAsync(JsonSerializer.Serialize(receipt, JsonOptions)).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidOperationException($"Unknown command '{envelope.Command}'.");
|
||||
|
|
@ -129,10 +162,12 @@ internal static class AquaSynthDaemonCli
|
|||
AquaSynthDaemon
|
||||
|
||||
once --script-file patch.aqua [--store .aquasynth] [--duration 0.25] [--gain 1]
|
||||
stream --script-file patch.aqua [--store .aquasynth] [--block-size 128] [--blocks 8]
|
||||
daemon [--store .aquasynth]
|
||||
|
||||
JSON-lines daemon commands:
|
||||
{"command":"instrument.sample","payload":{"commandId":"demo","patchId":"demo.patch","faustName":"demo","script":"voice wave=sine freq=440 gain=.2","durationSeconds":0.1}}
|
||||
{"command":"instrument.stream","payload":{"commandId":"demo-stream","patchId":"demo.patch","faustName":"demo","script":"param path=/macro/gain default=.2 min=0 max=1 step=.001; voice wave=sine freq=440 gain=@/macro/gain","blockSize":128,"blockCount":4,"controlFrames":[{"block":1,"controls":{"/macro/gain":0.05}}]}}
|
||||
""").ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
|
@ -184,5 +219,31 @@ internal static class AquaSynthDaemonCli
|
|||
return controls;
|
||||
}
|
||||
|
||||
private static AquaSynthAutomationControlFrame[]? ParseControlFrames(string value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var frames = new List<AquaSynthAutomationControlFrame>();
|
||||
foreach (var frameSpec in value.Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
||||
{
|
||||
var parts = frameSpec.Split(':', 2, StringSplitOptions.TrimEntries);
|
||||
if (parts.Length != 2 || !int.TryParse(parts[0], out var block))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var controls = ParseControls(parts[1]);
|
||||
if (controls is { Count: > 0 })
|
||||
{
|
||||
frames.Add(new AquaSynthAutomationControlFrame(block, controls));
|
||||
}
|
||||
}
|
||||
|
||||
return frames.Count == 0 ? null : [.. frames];
|
||||
}
|
||||
|
||||
private sealed record DaemonCommandEnvelope(string Command, JsonElement Payload);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue