Files
SonicForgeStudio/app/main.py
T
3dtours d0def4bf1e feat: auto-scan soundfont for Synth instrument list
Background daemon (30s interval) tracks scanned files via
sf_scan_state.json (size+mtime). Only inspects new/changed SFs.
Catalog served from scanner cache, no full re-scan per request.
Upload/delete trigger immediate re-scan.
2026-07-28 07:06:37 +07:00

90 lines
3.6 KiB
Python

import os, threading
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from app.config import settings
from app.api.v1.audio import router as audio_router
from app.api.v1.tasks import router as tasks_router
from app.api.v1.multitrack import router as multitrack_router
from app.api.v1.auth import router as auth_router
from app.api.v1.admin import router as admin_router
from app.api.v1.projects import router as projects_router
from app.api.v1.user_config import router as user_config_router
from app.api.v1.ai_proxy import router as ai_proxy_router
from app.api.v1.plugins import router as plugins_router
from app.core.auth import seed_admin
from app.core.soundfont_converter import SoundFontConverter
from app.core.soundfont_scanner import SoundFontAutoScanner
# Ensure storage directories exist
os.makedirs(settings.UPLOADS_DIR, exist_ok=True)
os.makedirs(settings.PROCESSED_DIR, exist_ok=True)
app = FastAPI(title="SonicForge API Engine")
from fastapi.middleware.gzip import GZipMiddleware
app.add_middleware(GZipMiddleware, minimum_size=500)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Mount storage directory (must come before general /static mount)
app.mount("/static/audio", StaticFiles(directory=settings.STORAGE_DIR), name="audio")
# Mount app static files (js, css)
STATIC_DIR = os.path.join(os.path.dirname(__file__), "static")
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
# Include routers
app.include_router(audio_router, prefix="/api/v1/audio", tags=["audio"])
app.include_router(tasks_router, prefix="/api/v1/audio", tags=["tasks"])
app.include_router(multitrack_router, prefix="/api/v1/multitrack", tags=["multitrack"])
app.include_router(auth_router, prefix="/api/v1/auth", tags=["auth"])
app.include_router(admin_router, prefix="/api/v1/admin", tags=["admin"])
app.include_router(projects_router, prefix="/api/v1/projects", tags=["projects"])
app.include_router(user_config_router, prefix="/api/v1/user", tags=["user_config"])
app.include_router(ai_proxy_router, prefix="/api/v1/ai", tags=["ai"])
app.include_router(plugins_router, prefix="/api/v1/plugins", tags=["plugins"])
# Seed admin user on startup
@app.on_event("startup")
async def startup_seed_admin():
seed_admin()
@app.on_event("startup")
async def startup_convert_soundfonts():
def _run():
try:
SoundFontConverter().batch_convert_all()
except Exception as e:
print(f"[Startup] SoundFont conversion error: {e}")
threading.Thread(target=_run, daemon=True).start()
@app.on_event("startup")
async def startup_sf_scanner():
scanner = SoundFontAutoScanner()
scanner.start_background(interval=30)
@app.get("/", response_class=HTMLResponse)
async def get_index():
index_path = os.path.join(settings.TEMPLATES_DIR, "index.html")
if not os.path.exists(index_path):
return HTMLResponse(content=f"<h1>SonicForge Studio: index.html not found at {index_path}</h1>", status_code=404)
with open(index_path, "r", encoding="utf-8") as file:
return HTMLResponse(content=file.read(), status_code=200)
@app.get("/favicon.svg")
async def get_favicon():
import os
favicon_path = os.path.join(settings.TEMPLATES_DIR, "favicon.svg")
if os.path.exists(favicon_path):
from fastapi.responses import FileResponse
return FileResponse(favicon_path, media_type="image/svg+xml")
return HTMLResponse(content="", status_code=404)