feat(fx-gui): đưa audio vào process GUI — meter VST nhảy theo âm thật qua SHM peek

- GUI process peek ring SHM đầu vào (không consume, không tranh chấp RealtimeFxLoop)
- gọi fx->processAudio() trên instance GUI để meter/UI plugin chuyển động theo âm thật
- performEdit forward sang controller -> meter điều khiển bởi param cũng cập nhật
- bridge /shm: frontend đẩy tên session live vào mỗi GUI đang mở (start/stop/open)
- tests: 127 passed
This commit is contained in:
2026-08-22 17:06:37 +07:00
parent 6ba38286ad
commit 6dfe390bda
7 changed files with 219 additions and 24 deletions
+16
View File
@@ -46,6 +46,9 @@
// anonymous namespace so both TUs see the same symbol.
extern void fxGuiRequestResize(HWND hwnd, int w, int h);
extern void fxGuiRequestCapture(void* hwnd, std::string& outB64, int timeoutMs);
// Tell RenderFxJob's SHM audio feeder which realtime session is live (the
// frontend pushes the session name; "" = session stopped/restarted).
extern void fxGuiSetShm(const std::string& name);
namespace {
@@ -582,6 +585,19 @@ void runHttpServer(HWND hwnd, std::atomic<bool>& stop) {
fxGuiRequestCapture(hwnd, b64, 1500);
const std::string body = "{\"preset_b64\":\"" + b64 + "\"}";
sendResponse(c, 200, "application/json", body.data(), (int)body.size());
} else if (req.path == "/shm") {
json_parse_result_s spres = {};
json_value_s* sroot = json_parse_ex(req.body.data(), req.body.size(),
json_parse_flags_default, nullptr, nullptr, &spres);
if (sroot && sroot->type == json_type_object) {
const json_object_s* so = static_cast<const json_object_s*>(sroot->payload);
fxGuiSetShm(memberString(so, "shm", ""));
std::free(sroot);
sendResponse(c, 200, "application/json", "{\"ok\":true}", 11);
} else {
if (sroot) std::free(sroot);
sendResponse(c, 400, "application/json", "{\"error\":\"bad json\"}", 20);
}
} else if (req.path == "/close") {
sendResponse(c, 200, "application/json", "{\"ok\":true}", 11);
stop.store(true);