Skip to content

gestes

gestes

Les gestes d'une seconde — volume, musique, presse-papiers, capture, vitaux.

Atlas, panier « Ensuite », 24 août 2026. « Monte le son » n'avait aucun outil : l'assistant passait par shell_exec — donc par la cloche, un clic et jusqu'à quarante-cinq secondes d'attente pour un geste qu'une main fait en une seconde. La jurisprudence est celle d'open_anything (desktop_tools.py) : un geste VISIBLE et RÉVERSIBLE ne se gate pas derrière une approbation.

Chaque outil constate au lieu de proclamer : après une commande de lecture, on redemande au lecteur son état réel ; la capture rend le chemin du fichier qui existe ; les vitaux disent « illisible » plutôt que d'inventer. Les fonctions de décision sont pures et testables sans matériel ; subprocess ne s'appelle que via _run, que les tests remplacent.

Classes

VolumeControlTool

Bases: BaseTool

Le volume de sortie du Mac — lire, régler, couper.

MediaControlTool

Bases: BaseTool

Pause, reprise, piste suivante/précédente — sur le lecteur en marche.

ClipboardReadTool

Bases: BaseTool

Ce que contient le presse-papiers, en texte.

ScreenSnapTool

Bases: BaseTool

Une capture d'écran, déposée sur le Bureau.

SystemVitalsTool

Bases: BaseTool

Batterie, Wi-Fi et disque en une phrase.

Functions:

interpreter_volume

interpreter_volume(
    sortie: str,
) -> tuple[Optional[int], bool]

(volume, coupé) depuis « 62, false » — (None, False) si illisible.

Source code in src/diapason/tools/gestes.py
def interpreter_volume(sortie: str) -> tuple[Optional[int], bool]:
    """(volume, coupé) depuis « 62, false » — (None, False) si illisible."""
    morceaux = [m.strip() for m in (sortie or "").strip().split(",")]
    try:
        volume = int(morceaux[0])
    except (ValueError, IndexError):
        return None, False
    coupe = len(morceaux) > 1 and morceaux[1].lower() == "true"
    return volume, coupe

lecteur_en_marche

lecteur_en_marche(runner=None) -> Optional[str]

Le premier lecteur dont le processus tourne — None sinon.

Source code in src/diapason/tools/gestes.py
def lecteur_en_marche(runner=None) -> Optional[str]:
    """Le premier lecteur dont le processus tourne — None sinon."""
    for lecteur in _LECTEURS:
        if (runner or _run)(["pgrep", "-x", lecteur]).returncode == 0:
            return lecteur
    return None

interpreter_etat_lecteur

interpreter_etat_lecteur(sortie: str) -> tuple[str, str]

(état, « Titre — Artiste ») — champs vides si le lecteur s'est tu.

Source code in src/diapason/tools/gestes.py
def interpreter_etat_lecteur(sortie: str) -> tuple[str, str]:
    """(état, « Titre — Artiste ») — champs vides si le lecteur s'est tu."""
    lignes = (sortie or "").strip().split("\n")
    etat = lignes[0].strip().lower() if lignes else ""
    piste = lignes[1].strip() if len(lignes) > 1 else ""
    return etat, piste

interpreter_wifi

interpreter_wifi(
    sortie_getsummary: str, sortie_getifaddr: str
) -> str

La phrase réseau : nom du Wi-Fi, « connecté », ou « pas de réseau ».

Source code in src/diapason/tools/gestes.py
def interpreter_wifi(sortie_getsummary: str, sortie_getifaddr: str) -> str:
    """La phrase réseau : nom du Wi-Fi, « connecté », ou « pas de réseau »."""
    m = _SSID_RE.search(sortie_getsummary or "")
    ssid = m.group(1).strip() if m else ""
    if ssid and ssid != "<redacted>":
        return f"Wi-Fi : {ssid}"
    if (sortie_getifaddr or "").strip():
        return "Réseau : connecté"
    return "pas de réseau"

formater_disque

formater_disque(libre: int, total: int) -> str

« 210 Go libres sur 494 » — en Go décimaux, comme le Finder.

Source code in src/diapason/tools/gestes.py
def formater_disque(libre: int, total: int) -> str:
    """« 210 Go libres sur 494 » — en Go décimaux, comme le Finder."""
    return f"{libre / 1e9:.0f} Go libres sur {total / 1e9:.0f}"