diff options
Diffstat (limited to 'backends/__init__.py')
| -rw-r--r-- | backends/__init__.py | 146 |
1 files changed, 0 insertions, 146 deletions
diff --git a/backends/__init__.py b/backends/__init__.py deleted file mode 100644 index 6a23ab7..0000000 --- a/backends/__init__.py +++ /dev/null @@ -1,146 +0,0 @@ -"""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 whether their server is currently running), and the registry -drives the hub's setup/configure menus. - -The registry is built lazily on the first call to ``get``/``detect_all``/ -``detect`` (not at package import time), because the backend modules pull -in ``converter.tts`` and its third-party dependencies, which are only -available inside the managed venv that ``audiobook.py`` bootstraps before -importing them. ``backends.envs`` is imported during that bootstrap, so -importing this package must stay cheap and dependency-free. - -Adding a backend: create ``backends/<name>.py`` exposing -``detect() -> BackendStatus``, ``run_tui() -> int`` and -``configure_actions: list[ConfigureAction]``, then append a ``BackendInfo`` in -``_build_registry`` below. ``audiobook.py`` and the hub pick it up -automatically. -""" - -import shlex -from dataclasses import dataclass, field -from typing import Callable, List, Optional - - -@dataclass -class ServerSpec: - """One launchable server process for a backend. - - A backend may expose more than one server (qwen runs CustomVoice and Base - on separate ports). ARGV is the exact command line the hub spawns (using - the managed venv's absolute binaries, so no shell activation is needed); - URL is the endpoint ``common.server_running`` probes to decide readiness. - """ - name: str - url: str - argv: List[str] - - -@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). RUNNING means an external server is - currently accepting connections on the configured port (probed by - ``backends.common.server_running``). DETAILS are short status lines for - the hub. LAUNCH_HINT is the human-readable command(s) the user runs to - start the server, derived from SERVERS by ``format_launch_hint``. - SERVERS is the machine-usable list of server processes the hub can - start/stop (empty when the backend is not yet configured). - """ - key: str - label: str - installed: bool - configured: bool - running: bool = False - details: List[str] = field(default_factory=list) - launch_hint: str = "" - servers: List[ServerSpec] = field(default_factory=list) - - @property - def ready(self) -> bool: - """True when the backend is installed and configured for use.""" - return self.installed and self.configured - - -def format_launch_hint(servers: List[ServerSpec]) -> str: - """Join a backend's server argvs into a copy-pasteable launch hint.""" - return " ; ".join(shlex.join(s.argv) for s in servers) - - -@dataclass -class ConfigureAction: - """A per-backend "configure" menu entry (e.g. "New server.json").""" - label: str - run: Callable[[], int] - - -@dataclass -class BackendInfo: - """One registry entry: identity, detector, setup wizard, configure menu.""" - key: str - label: str - detect: Callable[[], BackendStatus] - setup_tui: Callable[[], int] - configure_actions: List[ConfigureAction] = 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, - configure_actions=audiocpp.configure_actions, - )) - REGISTRY.append(BackendInfo( - key="qwen", - label="qwen-tts", - detect=qwen.detect, - setup_tui=qwen.run_tui, - configure_actions=qwen.configure_actions, - )) - REGISTRY.append(BackendInfo( - key="faster", - label="faster-qwen3-tts", - detect=faster.detect, - setup_tui=faster.run_tui, - configure_actions=faster.configure_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 |
