diff options
| author | historia <historiavg@proton.me> | 2026-08-23 23:48:25 -0400 |
|---|---|---|
| committer | historia <historiavg@proton.me> | 2026-08-23 23:48:25 -0400 |
| commit | 5bfbdcb5765fd4eb57d13c67169bb3c2706ead75 (patch) | |
| tree | a07a27976f56a449e8c33641161553aa0989f5c2 /backends/__init__.py | |
| parent | 07f7b351f2956b6c92761877c9a4314bcede3b6e (diff) | |
| download | tts-audiobook-generator-5bfbdcb5765fd4eb57d13c67169bb3c2706ead75.tar.gz | |
feat: audiobook.py tui: convert, modify, or install backends
Diffstat (limited to 'backends/__init__.py')
| -rw-r--r-- | backends/__init__.py | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/backends/__init__.py b/backends/__init__.py new file mode 100644 index 0000000..9203143 --- /dev/null +++ b/backends/__init__.py @@ -0,0 +1,114 @@ +"""Registry of the TTS backends the audiobook generator can talk to. + +Each backend (audio.cpp, qwen, faster) lives in its own module and owns +its setup wizard, its status detection, and the launch command it prints +once configured. This package aggregates them into a single registry so +``audiobook.py``'s TUI hub and future tools can iterate backends without +hardcoding their names: ``backends.detect_all()`` reports which are set +up, and ``backends.REGISTRY`` drives the hub's setup/modify menus. + +Adding a backend: create ``backends/<name>.py`` exposing +``detect() -> BackendStatus``, ``run_tui() -> int`` and +``modify_actions: list[ModifyAction]``, then append a ``BackendInfo`` in +``_build_registry`` below. ``audiobook.py`` and the hub pick it up +automatically. +""" + +from dataclasses import dataclass, field +from typing import Callable, List, Optional + + +@dataclass +class BackendStatus: + """How far a backend is set up, plus the command to start it. + + INSTALLED means the backend itself is present (a cloned + built + checkout, or a pip package). CONFIGURED means the supporting files are + in place (a server.json / voices.json and a converter/config.py that + points at the right port). DETAILS are short status lines for the hub. + LAUNCH_HINT is the exact command the user runs to start the server. + """ + key: str + label: str + installed: bool + configured: bool + details: List[str] = field(default_factory=list) + launch_hint: str = "" + + @property + def ready(self) -> bool: + """True when the backend is installed and configured for use.""" + return self.installed and self.configured + + +@dataclass +class ModifyAction: + """A per-backend "modify" menu entry (e.g. "New server.json").""" + label: str + run: Callable[[], int] + + +@dataclass +class BackendInfo: + """One registry entry: identity, detector, setup wizard, modify menu.""" + key: str + label: str + detect: Callable[[], BackendStatus] + setup_tui: Callable[[], int] + modify_actions: List[ModifyAction] = field(default_factory=list) + + +REGISTRY: List[BackendInfo] = [] +_BY_KEY: dict = {} + + +def _build_registry() -> None: + """Import the backend modules and wire up REGISTRY (once).""" + if REGISTRY: + return + from . import audiocpp, faster, qwen + + REGISTRY.append(BackendInfo( + key="audiocpp", + label="audio.cpp", + detect=audiocpp.detect, + setup_tui=audiocpp.run_tui, + modify_actions=audiocpp.modify_actions, + )) + REGISTRY.append(BackendInfo( + key="qwen", + label="Qwen3-TTS (demo server)", + detect=qwen.detect, + setup_tui=qwen.run_tui, + modify_actions=qwen.modify_actions, + )) + REGISTRY.append(BackendInfo( + key="faster", + label="faster-qwen3-tts", + detect=faster.detect, + setup_tui=faster.run_tui, + modify_actions=faster.modify_actions, + )) + for info in REGISTRY: + _BY_KEY[info.key] = info + + +def get(key: str) -> Optional[BackendInfo]: + """Return the registry entry for KEY, or None.""" + _build_registry() + return _BY_KEY.get(key) + + +def detect_all() -> List[BackendStatus]: + """Detect every registered backend's status, in registry order.""" + _build_registry() + return [info.detect() for info in REGISTRY] + + +def detect(key: str) -> Optional[BackendStatus]: + """Detect a single backend by key.""" + info = get(key) + return info.detect() if info is not None else None + + +_build_registry() |
