Added config editor in front end
All checks were successful
CI / React UI Build (push) Successful in 11s
CI / Native Windows Build And Tests (push) Successful in 2m46s
CI / Windows Release Package (push) Has been skipped

This commit is contained in:
Aiden
2026-05-30 19:33:40 +10:00
parent f0f8b080ca
commit 8ffc011ca0
26 changed files with 1201 additions and 55 deletions

View File

@@ -71,7 +71,9 @@ add_video_shader_test(RenderCadenceCompositorSupportedShaderCatalogTests
add_video_shader_test(RenderCadenceCompositorRuntimeStateJsonTests
"${SRC_DIR}/app/AppConfig.cpp"
"${SRC_DIR}/app/AppRestart.cpp"
"${SRC_DIR}/app/AppConfigProvider.cpp"
"${SRC_DIR}/app/AppConfigJson.cpp"
${VIDEO_MODE_SOURCES}
${VIDEO_FORMAT_SOURCES}
"${SRC_DIR}/json/JsonWriter.cpp"
@@ -97,7 +99,9 @@ target_link_libraries(RenderCadenceCompositorHttpControlServerTests PRIVATE Ws2_
add_video_shader_test(RenderCadenceCompositorAppConfigProviderTests
"${SRC_DIR}/app/AppConfig.cpp"
"${SRC_DIR}/app/AppRestart.cpp"
"${SRC_DIR}/app/AppConfigProvider.cpp"
"${SRC_DIR}/app/AppConfigJson.cpp"
${VIDEO_MODE_SOURCES}
"${SRC_DIR}/video/decklink/DeckLinkDisplayMode.cpp"
${RUNTIME_JSON_SOURCES}

View File

@@ -1,4 +1,5 @@
#include "AppConfigProvider.h"
#include "AppConfigJson.h"
#include "DeckLinkDisplayMode.h"
#include <chrono>
@@ -51,7 +52,8 @@ std::filesystem::path WriteConfigFixture()
<< " \"autoReload\": false,\n"
<< " \"maxTemporalHistoryFrames\": 8,\n"
<< " \"previewEnabled\": true,\n"
<< " \"previewFps\": 24\n"
<< " \"previewFps\": 24,\n"
<< " \"runtimeShaderId\": \"solid-color\"\n"
<< "}\n";
return path;
}
@@ -87,6 +89,7 @@ void TestLoadsRuntimeHostConfig()
Expect(config.maxTemporalHistoryFrames == 8, "history length loads");
Expect(config.previewEnabled, "preview enabled toggle loads");
Expect(config.previewFps == 24.0, "preview fps loads");
Expect(config.runtimeShaderId == "solid-color", "runtime shader id loads");
Expect(config.output.externalKeyingEnabled, "external keying loads");
Expect(config.output.outputAlphaRequired, "output alpha requirement loads");
@@ -121,6 +124,31 @@ void TestPreviewDefaultsAreOptIn()
Expect(config.previewFps == 60.0, "preview fps default is 60");
}
void TestConfigJsonRoundTrip()
{
using namespace RenderCadenceCompositor;
AppConfig config = DefaultAppConfig();
config.shaderLibrary = "custom-shaders";
config.output.backend = "ndi";
config.output.device = "Program";
config.output.pixelFormat = "uyvy8";
config.previewEnabled = true;
config.runtimeShaderId = "solid-color";
const std::string json = AppConfigToJson(config);
AppConfig parsed;
std::string error;
Expect(ParseAppConfigJson(json, parsed, error), "serialized config parses");
Expect(error.empty(), "serialized config parse has no error");
Expect(parsed.shaderLibrary == "custom-shaders", "shader library round trips");
Expect(parsed.output.backend == "ndi", "output backend round trips");
Expect(parsed.output.device == "Program", "output device round trips");
Expect(parsed.output.pixelFormat == "uyvy8", "output pixel format round trips");
Expect(parsed.previewEnabled, "preview enabled round trips");
Expect(parsed.runtimeShaderId == "solid-color", "runtime shader id round trips");
}
void TestHelpers()
{
using namespace RenderCadenceCompositor;
@@ -149,6 +177,7 @@ int main()
TestLoadsRuntimeHostConfig();
TestCommandLineOverrides();
TestPreviewDefaultsAreOptIn();
TestConfigJsonRoundTrip();
TestHelpers();
if (gFailures != 0)

View File

@@ -64,6 +64,25 @@ void TestStateEndpointUsesCallback()
ExpectEquals(response.body, "{\"ok\":true}", "state endpoint returns callback JSON");
}
void TestConfigEndpointUsesCallback()
{
using namespace RenderCadenceCompositor;
HttpControlServer server;
HttpControlServerCallbacks callbacks;
callbacks.getConfigJson = []() { return std::string("{\"diskLoaded\":true}"); };
server.SetCallbacksForTest(callbacks);
HttpControlServer::HttpRequest request;
request.method = "GET";
request.path = "/api/config";
const HttpControlServer::HttpResponse response = server.RouteRequestForTest(request);
ExpectEquals(response.status, "200 OK", "config endpoint succeeds");
ExpectEquals(response.contentType, "application/json", "config endpoint is JSON");
ExpectEquals(response.body, "{\"diskLoaded\":true}", "config endpoint returns callback JSON");
}
void TestWebSocketAcceptKey()
{
using namespace RenderCadenceCompositor;
@@ -171,6 +190,29 @@ void TestGenericPostCallbackHandlesControlRoutes()
Expect(response.body.find("\"ok\":true") != std::string::npos, "generic control callback returns action success");
}
void TestGenericPostCallbackHandlesConfigRoutes()
{
using namespace RenderCadenceCompositor;
HttpControlServer server;
HttpControlServerCallbacks callbacks;
callbacks.executePost = [](const std::string& path, const std::string& body) {
ExpectEquals(path, "/api/config/save", "generic callback receives config route path");
Expect(body.find("runtimeShaderId") != std::string::npos, "generic callback receives config request body");
return ControlActionResult{ true, std::string() };
};
server.SetCallbacksForTest(callbacks);
HttpControlServer::HttpRequest request;
request.method = "POST";
request.path = "/api/config/save";
request.body = "{\"runtimeShaderId\":\"solid-color\"}";
const HttpControlServer::HttpResponse response = server.RouteRequestForTest(request);
ExpectEquals(response.status, "200 OK", "config save callback success returns 200");
Expect(response.body.find("\"ok\":true") != std::string::npos, "config save callback returns action success");
}
void TestReloadRouteParsesAsControlCommand()
{
using namespace RenderCadenceCompositor;
@@ -199,11 +241,13 @@ int main()
{
TestParsesHttpRequest();
TestStateEndpointUsesCallback();
TestConfigEndpointUsesCallback();
TestWebSocketAcceptKey();
TestRootServesUiIndex();
TestKnownPostEndpointReturnsActionError();
TestLayerPostEndpointsUseCallbacks();
TestGenericPostCallbackHandlesControlRoutes();
TestGenericPostCallbackHandlesConfigRoutes();
TestReloadRouteParsesAsControlCommand();
TestUnknownEndpointReturns404();