66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
"""Les trois frontières de Zonza.
|
|
|
|
Chaque contrat est délibérément minuscule : ce sont les seuls points par lesquels
|
|
le noyau parle au monde extérieur. Tout ce qui dépend d'un système d'exploitation,
|
|
d'une bibliothèque d'affichage ou d'un moteur de transcription vit DERRIÈRE l'un
|
|
d'eux — jamais dans `core.py`, `controller.py` ni `audio_level.py`.
|
|
"""
|
|
from typing import IO, Protocol
|
|
|
|
# numpy entre dans ce fichier volontairement minuscule car c'est déjà une
|
|
# dépendance dure du projet, et le type du signal audio fait partie du
|
|
# contrat : un `Any` implicite laisserait passer un mauvais type sans que
|
|
# rien ne bronche.
|
|
import numpy as np
|
|
|
|
|
|
class Transcripteur(Protocol):
|
|
"""Transforme un signal audio en texte."""
|
|
|
|
def warmup(self) -> None:
|
|
"""Charge le modèle une fois, pour que la première dictée ne traîne pas."""
|
|
|
|
def transcrire(self, audio: np.ndarray) -> str:
|
|
"""Rend le texte d'un tableau numpy float32 mono."""
|
|
|
|
|
|
class Overlay(Protocol):
|
|
"""La fenêtre flottante affichée pendant la dictée."""
|
|
|
|
def show(self) -> None:
|
|
"""Affiche la fenêtre et démarre l'animation. Thread principal."""
|
|
|
|
def hide(self) -> None:
|
|
"""Masque la fenêtre et arrête l'animation. Thread principal."""
|
|
|
|
def set_level(self, level: float) -> None:
|
|
"""Pousse un niveau audio dans [0, 1]. Appelable depuis un thread de fond."""
|
|
|
|
def set_status(self, text: str) -> None:
|
|
"""Texte affiché dans la bulle. Appelable depuis un thread de fond."""
|
|
|
|
def rearmer_garde(self, duree_s: float) -> None:
|
|
"""Remplace la durée de vie maximale de la fenêtre. Thread principal."""
|
|
|
|
|
|
class Systeme(Protocol):
|
|
"""Les appels qui diffèrent d'un système d'exploitation à l'autre."""
|
|
|
|
def jouer_son(self, nom: str) -> None:
|
|
"""Joue « start », « done » ou « error » sans bloquer."""
|
|
|
|
def modificateurs_enfonces(self) -> bool:
|
|
"""True si une touche modificatrice est physiquement enfoncée."""
|
|
|
|
def raccourci_defaut(self) -> str:
|
|
"""Raccourci global au format pynput, propre à la plateforme."""
|
|
|
|
def chemin_log(self) -> str:
|
|
"""Chemin absolu du journal."""
|
|
|
|
def dossier_donnees(self) -> str:
|
|
"""Dossier des données de l'application (verrou d'instance, réglages)."""
|
|
|
|
def acquerir_verrou_instance(self, chemin: str) -> IO | None:
|
|
"""Verrou exclusif non bloquant ; rend le fichier, ou None s'il est pris."""
|