fix: add missing API endpoints for volume POST, bypass/toggle, block params, block toggle; fix JACK 1.9.22 cmd args; fix Scarlett 2i2 channel count

This commit is contained in:
2026-06-13 21:08:58 +00:00
parent cd2ed273e9
commit 9fade4a2d2
61 changed files with 13728 additions and 56 deletions
+98
View File
@@ -789,6 +789,104 @@ class WebServer:
pl._master_volume = vol
return {"ok": True, "volume": vol, "channel": channel}
# ── POST alias for volume (UI uses POST, server had PUT) ──
@app.post("/api/volume")
async def set_volume_post(data: dict, channel: str = "guitar"):
"""Set master volume — POST alias for PUT endpoint."""
_pm, pl, _nam, _ir = self._channel_deps(channel)
if not pl:
raise HTTPException(status_code=503)
vol = max(0.0, min(1.0, float(data.get("volume", 0.8))))
pl._master_volume = vol
return {"ok": True, "volume": vol, "channel": channel}
# ── Toggle bypass alias (UI calls /api/bypass/toggle) ─────
@app.post("/api/bypass/toggle")
async def toggle_bypass_alias(data: Optional[dict] = None, channel: str = "guitar"):
"""Toggle or set bypass state — alias for /api/bypass."""
_pm, pl, _nam, _ir = self._channel_deps(channel)
if not pl:
raise HTTPException(status_code=503)
if data and "bypass" in data:
pl._bypassed = bool(data["bypass"])
else:
pl._bypassed = not pl._bypassed
await self._manager.broadcast({
"type": "bypass_changed",
"channel": channel,
"bypass": pl._bypassed,
})
return {"ok": True, "bypass": pl._bypassed}
# ── Block toggle (UI: PATCH /api/blocks {id, enabled}) ──
@app.patch("/api/blocks")
async def toggle_block(data: dict, channel: str = "guitar"):
"""Enable/disable a block by its fx_type id."""
from ..presets.types import Channel
pm, pl, nam, ir = self._channel_deps(channel)
if not pm:
raise HTTPException(status_code=503)
block_id = data.get("id")
enabled = data.get("enabled")
if not block_id or enabled is None:
raise HTTPException(status_code=400, detail="Missing 'id' or 'enabled'")
try:
bank = pm.current_bank
program = pm.current_program
preset = pm.load(bank, program, channel=Channel(channel))
for b in preset.chain:
if b.fx_type.value == block_id:
b.enabled = bool(enabled)
pm.save(preset, channel=Channel(channel))
# Reload pipeline if needed
if pl:
pl.load_preset(preset)
return {"ok": True, "id": block_id, "enabled": b.enabled}
raise HTTPException(status_code=404, detail=f"Block '{block_id}' not found")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# ── Block param update (UI: PATCH /api/block {id, ...params}) ──
@app.patch("/api/block")
async def update_block_params(data: dict, channel: str = "guitar"):
"""Update parameters for a block by its fx_type id."""
from ..presets.types import Channel, FXBlock
pm, pl, nam, ir = self._channel_deps(channel)
if not pm:
raise HTTPException(status_code=503)
block_id = data.get("id")
if not block_id:
raise HTTPException(status_code=400, detail="Missing 'id'")
try:
bank = pm.current_bank
program = pm.current_program
preset = pm.load(bank, program, channel=Channel(channel))
for b in preset.chain:
if b.fx_type.value == block_id:
# Update params from request body (skip 'id' key)
for key, val in data.items():
if key == "id":
continue
if key in ("nam_model_path", "ir_file_path", "bypass", "enabled", "subtype"):
if key == "bypass":
b.bypass = bool(val)
elif key == "enabled":
b.enabled = bool(val)
elif key == "subtype":
b.subtype = str(val)
else:
setattr(b, key, str(val))
else:
# Try setting as param even if not in defaults
b.params[key] = float(val)
pm.save(preset, channel=Channel(channel))
if pl:
pl.load_preset(preset)
return {"ok": True, "id": block_id, "params": dict(b.params)}
raise HTTPException(status_code=404, detail=f"Block '{block_id}' not found")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
# ── 4CM routing endpoints ────────────────────────────────
@app.get("/api/routing")