fix(midi): route MIDI live via masterBus, fix media explorer drag, add action logging

- TrackInstrument: gate native live path (SF/VSTi WASAPI bridge bypassed
  masterBus -> mastering FX + main out VU dead). Fallback to SonicSF WASM
  through masterBus.input; native kept for offline render only.
- MEDIA_LIBRARY_SAMPLES: rename MIDI_Loop_02_Bass/03_Lead/05_Bass to match
  actual /static/midi files (drag was 404 -> parse error).
- Add SonicAppLogger (console + POST /api/v1/logs) wired to: instrument load
  error, VSTi autosample fail, MIDI item -> mastering fx chain, play -> main
  out, drag MIDI errors (media explorer + window explorer).
- Add backend /api/v1/logs endpoint (server-side log, no DB).
This commit is contained in:
2026-08-11 21:48:06 +07:00
parent e3c9d6e4ab
commit 59cf77bcbc
7 changed files with 121 additions and 15 deletions
+39
View File
@@ -0,0 +1,39 @@
# SonicForge Client Logs API — client gửi log hành động (MIDI/mastering/drag
# errors) qua POST /api/v1/logs. Không lưu DB — in ra server log (uvicorn
# console). Public: log không chứa dữ liệu nhạy (client tự quyết định).
import logging
from typing import Any, Optional
from fastapi import APIRouter
from pydantic import BaseModel
router = APIRouter()
_logger = logging.getLogger("sonicforge.client_logs")
class ClientLogEntry(BaseModel):
category: str = "GENERAL"
level: str = "info"
message: str = ""
data: Optional[dict[str, Any]] = None
url: Optional[str] = None
ts: Optional[str] = None
@router.post("")
async def post_client_log(entry: ClientLogEntry):
"""Ghi log từ client vào server log (fire-and-forget, luôn 200)."""
tag = f"[ClientLog][{entry.category}][{entry.level}]"
line = f"{tag} {entry.message}"
if entry.data:
line += f" {entry.data}"
if entry.ts:
line += f" (ts={entry.ts})"
if entry.url:
line += f" url={entry.url}"
if entry.level == "error":
_logger.error(line)
elif entry.level == "warn":
_logger.warning(line)
else:
_logger.info(line)
return {"ok": True}