muscriptor-studio-suite / studio_component.pyi
fffiloni's picture
Upload 8 files
88e1dfb verified
Raw
History Blame Contribute Delete
2.15 kB
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
import gradio as gr
ROOT = Path(__file__).resolve().parent
FRONTEND = ROOT / "frontend"
def _read_frontend(name: str) -> str:
return (FRONTEND / name).read_text(encoding="utf-8")
def initial_studio_value() -> dict[str, Any]:
return {
"state": "idle",
"status": "Upload a recording to begin.",
"progress": 0,
"audio_name": "",
"elapsed": 0,
"duration": 0,
"available_until": 0,
"original_audio": "",
"note_count": 0,
"tracks": [],
"full_midi": "",
"score_svg": "",
"score_pdf_url": "",
"score_parts": [],
"score_page_urls": [],
"score_pages": 0,
"notation": {},
}
from gradio.events import Dependency
class StudioViewer(gr.HTML):
"""MuScriptor result viewer implemented with Gradio's custom HTML API."""
def __init__(self, value: Any | None = None, **kwargs: Any) -> None:
synth_bundle = _read_frontend("spessasynth.bundle.js")
viewer_script = _read_frontend("studio.js")
super().__init__(
value=value or initial_studio_value(),
html_template=_read_frontend("studio.html"),
css_template=_read_frontend("studio.css"),
js_on_load=f"{synth_bundle}\n{viewer_script}",
apply_default_css=False,
container=False,
**kwargs,
)
def api_info(self) -> dict[str, Any]:
return {"type": "object"}
from typing import Callable, Literal, Sequence, Any, TYPE_CHECKING
from gradio.blocks import Block
if TYPE_CHECKING:
from gradio.components import Timer
from gradio.components.base import Component
def normalize_viewer_value(value: Any) -> dict[str, Any]:
if isinstance(value, dict):
return value
if isinstance(value, str):
try:
parsed = json.loads(value)
if isinstance(parsed, dict):
return parsed
except json.JSONDecodeError:
pass
return initial_studio_value()