#include "RuntimeLayerController.h" #include "RuntimeJson.h" #include "../logging/Logger.h" namespace RenderCadenceCompositor { ControlActionResult RuntimeLayerController::HandleAddLayer(const std::string& body) { CleanupRetiredShaderBuilds(); std::string shaderId; std::string error; if (!ExtractStringField(body, "shaderId", shaderId, error)) return { false, error }; std::string layerId; { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.AddLayer(mShaderCatalog, shaderId, layerId, error)) return { false, error }; } Log("runtime-shader", "Layer added: " + layerId + " shader=" + shaderId); StartLayerShaderBuild(layerId, shaderId); return { true, std::string() }; } ControlActionResult RuntimeLayerController::HandleRemoveLayer(const std::string& body) { CleanupRetiredShaderBuilds(); std::string layerId; std::string error; if (!ExtractStringField(body, "layerId", layerId, error)) return { false, error }; { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.RemoveLayer(layerId, error)) return { false, error }; } Log("runtime-shader", "Layer removed: " + layerId); RetireLayerShaderBuild(layerId); PublishRuntimeRenderLayers(); return { true, std::string() }; } ControlActionResult RuntimeLayerController::HandleControlCommand(const RuntimeControlCommand& command) { CleanupRetiredShaderBuilds(); std::string error; switch (command.type) { case RuntimeControlCommandType::AddLayer: { std::string layerId; { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.AddLayer(mShaderCatalog, command.shaderId, layerId, error)) return { false, error }; } Log("runtime-shader", "Layer added: " + layerId + " shader=" + command.shaderId); StartLayerShaderBuild(layerId, command.shaderId); return { true, std::string() }; } case RuntimeControlCommandType::RemoveLayer: { { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.RemoveLayer(command.layerId, error)) return { false, error }; } Log("runtime-shader", "Layer removed: " + command.layerId); RetireLayerShaderBuild(command.layerId); PublishRuntimeRenderLayers(); return { true, std::string() }; } case RuntimeControlCommandType::ReorderLayer: { { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.ReorderLayer(command.layerId, command.targetIndex, error)) return { false, error }; } PublishRuntimeRenderLayers(); return { true, std::string() }; } case RuntimeControlCommandType::SetLayerBypass: { { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.SetLayerBypass(command.layerId, command.bypass, error)) return { false, error }; } PublishRuntimeRenderLayers(); return { true, std::string() }; } case RuntimeControlCommandType::SetLayerShader: { { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.SetLayerShader(mShaderCatalog, command.layerId, command.shaderId, error)) return { false, error }; } Log("runtime-shader", "Layer shader changed: " + command.layerId + " shader=" + command.shaderId); StartLayerShaderBuild(command.layerId, command.shaderId); return { true, std::string() }; } case RuntimeControlCommandType::UpdateLayerParameter: { { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.UpdateParameter(command.layerId, command.parameterId, command.value, error)) return { false, error }; } PublishRuntimeRenderLayers(); return { true, std::string() }; } case RuntimeControlCommandType::ResetLayerParameters: { { std::lock_guard lock(mRuntimeLayerMutex); if (!mRuntimeLayerModel.ResetParameters(command.layerId, error)) return { false, error }; } PublishRuntimeRenderLayers(); return { true, std::string() }; } case RuntimeControlCommandType::Unsupported: break; } return { false, "Unsupported runtime control command." }; } bool RuntimeLayerController::ExtractStringField(const std::string& body, const char* fieldName, std::string& value, std::string& error) { JsonValue root; std::string parseError; if (!ParseJson(body.empty() ? "{}" : body, root, parseError) || !root.isObject()) { error = parseError.empty() ? "Request body must be a JSON object." : parseError; return false; } const JsonValue* field = root.find(fieldName); if (!field || !field->isString() || field->asString().empty()) { error = std::string("Request field '") + fieldName + "' must be a non-empty string."; return false; } value = field->asString(); error.clear(); return true; } }