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
+6
View File
@@ -620,6 +620,10 @@ class FxGuiRequest(BaseModel):
# embed=True → bridge --fx-gui (off-screen + HTTP frame/input server,
# PLAN_MASTERBUS_VST_GUI_EMBED.md); embed=False → cửa sổ rời cũ.
embed: bool = False
# shm: tên SHM session realtime (SonicForge_FXRT_*) — bridge fx-gui
# mở mapping này để PEEK input ring và chạy processAudio() trên instance
# GUI → meter trong plugin nhảy theo âm thật (GUI không consume ring).
shm: str = ""
class FxGuiCloseRequest(BaseModel):
@@ -832,6 +836,8 @@ async def open_fx_gui(req: FxGuiRequest, current_user: dict = Depends(get_curren
if proc is not None and proc.poll() is None and getattr(proc, "_sf_plugin_path", None) == plugin_path:
return {"success": True, "started": False, "already_running": True, "cmd": [], "embed_url": getattr(proc, "_sf_embed_url", None) or None}
job = {"path": plugin_path, "name": req.name or os.path.basename(plugin_path)}
if req.shm:
job["shm"] = req.shm
fd, job_path = tempfile.mkstemp(prefix="sf_fx_gui_", suffix=".json", dir=tempfile.gettempdir())
try:
with os.fdopen(fd, "w", encoding="utf-8") as f: