# Linux / Proton : ATC vocal et radio cockpit

## Essayer le prototype

1. Extraire **CopiloteVR-Linux-x64.zip** intégralement. Ouvrir un terminal dans le dossier extrait et lancer `bash Lancer-Linux.sh --demo`. Ce n'est pas l'ancienne page web.
2. La démo s'ouvre dans l'application native. Cliquer **Batterie**, attendre une seconde, **Avionique**, attendre, puis **COM tour ↔ autre**. La station fictive devient joignable sur **118.005** ; cette fréquence de test n'est pas une fréquence réelle de Bordeaux.
3. Choisir son IA texte : fournisseur + modèle + clé API personnelle, ou un serveur Ollama/LM Studio déjà démarré avec un modèle chargé. Aucun modèle conversationnel ni clé n'est fourni. Le champ modèle est modifiable ; les noms proposés sont des exemples, leur disponibilité dépend du compte.
4. Saisir un appel dans le champ pilote et cliquer **Émettre**. L'application envoie un texte JSON compact, pas du son, puis prononce la réponse avec Piper. Aucun appel n'est émis quand on règle une fréquence ou affiche l'aide.
5. Cliquer **Tester la voix**, puis **Activer le micro**. En mode vocal, dire **« radio, [ton appel] »** ; par exemple « radio, tour, Fox Golf Juliette Papa Papa, bonjour, demandons les paramètres ». Le préfixe local empêche d'envoyer toute conversation ambiante à l'IA. Les transcriptions sont visibles dans le journal écran.
6. Dire **phrase** pour afficher la suggestion du dernier échange. Dire **fréquence** ou **tour** pour les stations proches. Autres commandes : checklist, plan de vol, afficher, masquer, silence, reprendre, valider, point suivant, nouvelle session. Lire exactement le call-out d'un item reste possible. Les commandes système restent locales.
7. Cliquer **Panneau en jeu** pour un panneau sombre déplaçable, au-dessus des fenêtres. Tester MSFS en mode fenêtré/sans bordure ; un plein écran exclusif ou le compositeur peut empêcher le recouvrement.
8. Pour le casque, lancer SteamVR puis cliquer **Panneau SteamVR**. Le panneau est une texture OpenVR positionnée par rapport au casque, devant et légèrement à droite. Il ne dépend pas du navigateur. Il n'est pas interactif à la manette dans cette alpha ; utiliser les commandes vocales. Bouton désactivé = overlay détruit.

## Ce qui se passe quand on règle une fréquence

```text
Position avion → aéroports du cache MSFS → leurs fréquences → tour proche affichée
Radio cockpit : COM active + choix émission/réception + alimentation
              ↓
Recherche de la station correspondante à proximité
              ↓
État « prêt pour ton appel » → ton appel vocal → réponse du bon service ATC
```

- La tour proche est une **suggestion**, pas un changement automatique de station. La COM réellement sélectionnée pour l'émission décide du service ; COM2 est aussi prise en compte. Régler seulement la veille ne suffit pas : il faut basculer la fréquence en actif dans le cockpit.
- L'application ne règle jamais la radio à ta place. SimConnect est utilisé en lecture seule.
- « Prêt pour ton appel » ne fait pas parler automatiquement le contrôleur. Tu prends contact, puis l'IA joue le rôle de cette station. Au sol, tu peux ainsi joindre le sol plutôt que la tour la plus proche.
- La radio doit être alimentée, disponible et en réception. Aucun service connu, mauvais canal, panne ou télémétrie périmée : pas d'appel IA. Les radios spécifiques d'add-ons peuvent exiger des profils particuliers.
- Comparaison au kHz du **canal affiché**, sans arrondi à 25 kHz : 118.000 et 118.005 restent distincts. La lecture des canaux 8,33 kHz doit encore être vérifiée sur les avions réels du simulateur.
- Changer de station remet à zéro la mémoire de dialogue de cette alpha. Une réponse encore en préparation est ignorée ; une lecture en cours est interrompue. Ce n'est pas encore un transfert inter-contrôleurs avec mémoire partagée.
- Aéroports demandés toutes les 30 secondes, détails des 32 plus proches dans 80 NM, huit requêtes simultanées maximum, cache de cinq minutes. La « tour proche » est donc la plus proche **parmi les installations connues et chargées**, pas une recherche mondiale garantie.
- Distance géographique et seuil 80 NM sont une approximation de jeu. Relief, propagation radio, secteurs, horaires et portée de chaque installation ne sont pas modélisés. Une fréquence partagée est attribuée au service connu le plus proche.
- Les fréquences viennent des scènes et de la base du simulateur via `RequestFacilitiesList` / `RequestFacilityData`, jamais du modèle de langage. Si l'API n'est pas disponible, aucune fréquence réelle de secours n'est inventée.

## Brancher MSFS 2020 / 2024 sous Proton

1. Lancer **un seul** MSFS depuis Steam et ouvrir un vol, idéalement avec un avion standard simple.
2. Lancer l'application Linux depuis ton bureau/terminal habituel, sélectionner la version et **Connecter**. Elle lit les bibliothèques Steam, le manifeste du jeu et `CompatToolMapping` ; elle lance le pont dans le préfixe existant, avec le Proton configuré pour ce jeu. Elle ne modifie ni la configuration Steam, ni les options du simulateur, ni les réglages radio.
3. Pour MSFS 2020, la DLL `SimConnect.dll` présente à côté du jeu est découverte. Si elle manque, fournir la DLL cliente native x64 du SDK avec la variable ci-dessous.
4. **Sur ce PC, MSFS 2024 est installé mais sa DLL cliente SDK n'a pas été trouvée.** `SimConnect_internal.dll` n'est pas chargée automatiquement : ses exports ne constituent pas une validation du fonctionnement client. Fournir une DLL cliente SimConnect x64 adaptée au SDK utilisé.
5. Le statut **Connecté via SimConnect** et une altitude qui réagit constituent la première validation ; détecter le jeu ou lancer le pont ne suffit pas. Les erreurs sont dans le panneau et `sessions/<identifiant>/bridge-output.log`.
6. Attendre les fréquences proches, régler la fréquence affichée dans le cockpit, sélectionner l'émission sur cette COM, puis appeler. Si tu gardes l'ATC intégré de MSFS, il peut parler en même temps : désactive sa voix/assistance radio dans les options du jeu pour tester ce contrôleur séparément.

Exemples de réglages facultatifs, chemins **Linux absolus** :

```bash
export COPILOTE_SIMCONNECT_DLL="/chemin/SDK/SimConnect.dll"
export COPILOTE_PROTON="/chemin/du/Proton-utilise-par-le-jeu/proton"
bash Lancer-Linux.sh
```

Ne choisis pas une autre version Proton pour « essayer » sur le même préfixe. Le lanceur refuse d'en deviner une si la configuration Steam n'est pas trouvée. Une installation Steam Flatpak peut avoir besoin de chemins/permissions adaptés ; elle n'est pas prise en charge automatiquement ici. Pour changer de simulateur, fermer puis rouvrir l'application.

## Dépendances voix et UI

Hôte x86-64, Python 3.10+, Qt5/PyQt5, `numpy`, `torch`, `openai-whisper`, `piper-tts`, `ffmpeg`, `parec` et `paplay` (PulseAudio ou compatibilité PipeWire). Le runtime .NET est inclus dans l'archive Linux, pas le SDK. Les dépendances Python ne sont pas embarquées.

Sur ce PC : PyQt5, Whisper, Torch, le module Python Piper, les utilitaires audio et les deux modèles ont été détectés. Le binaire isolé `piper` échoue avec une bibliothèque manquante ; l'application utilise **`python3 -m piper`**, testé ici.

Pour une nouvelle installation Ubuntu/Pop!_OS, à exécuter toi-même si nécessaire :

```bash
sudo apt install python3-pyqt5 python3-venv ffmpeg pulseaudio-utils
python3 -m venv --system-site-packages .venv
.venv/bin/pip install openai-whisper piper-tts
export COPILOTE_PYTHON="$PWD/.venv/bin/python"
```

Les modèles ne sont jamais téléchargés automatiquement au lancement. Par défaut, détection de `~/.cache/whisper/tiny.pt` et `~/.local/share/piper-voices/fr_FR-upmc-medium.onnx` avec son fichier `.onnx.json`. Pour utiliser d'autres modèles déjà téléchargés :

```bash
export COPILOTE_WHISPER_MODEL="/chemin/small.pt"
export COPILOTE_PIPER_MODEL="/chemin/voix-francaise.onnx"
```

**Limite mesurée :** Whisper tiny a mal reconnu un indicatif et le mot isolé « phrase » dans un essai audio synthétique. Un appel plus long avec vocabulaire contextuel a été transcrit correctement dans un autre essai, ce qui ne prouve pas la qualité au microphone. Une reconnaissance plus précise nécessite un modèle plus grand et des essais réels. Ne considère pas cette alpha comme un produit vocal fini ; saisie et boutons permettent de tester indépendamment la radio et l'IA.

Le micro par défaut du système est utilisé, capture locale 16 kHz, détection de parole heuristique puis transcription CPU (quatre threads). Pas de touche joystick push-to-talk dans cette version : bouton micro + mot « radio ». Pendant la réponse audio, la capture est ignorée pour limiter la boucle de réécoute. Un casque est préférable aux haut-parleurs. **Silence** suspend les échanges, mais garde « reprendre » actif ; **Couper le micro** arrête réellement la capture.

Le panneau desktop utilise XWayland par défaut (`QT_QPA_PLATFORM=xcb`). Le recouvrement dépend du compositeur. Le panneau VR demande la bibliothèque Linux `libopenvr_api.so` de SteamVR ; chemin automatique pour la bibliothèque Steam principale, sinon `COPILOTE_OPENVR_LIBRARY`. Interfaces OpenVR 027/028 implémentées. Monado/OpenComposite/OpenXR sans SteamVR ne sont pas pris en charge par cet overlay.

## IA, coût et confidentialité

- Aucun abonnement à une IA web ne vaut automatiquement droit à son API. Utiliser une clé API compatible avec le fournisseur choisi et vérifier ses quotas/modèles. Les valeurs du sélecteur sont modifiables et ne garantissent pas la gratuité.
- Appels seulement à la demande du pilote, sans flux de télémétrie continu vers l'IA. Contexte instantané compact, quatre messages d'historique maximum, résumé mémoire borné, réponse limitée à 400 tokens demandés. Certaines offres facturent aussi la requête ou des tokens de raisonnement ; le compteur reprend seulement l'usage communiqué par l'API.
- Ce prototype n'impose pas un plafond mensuel de dépense et ne promet pas 1–2 €/mois. Définir les quotas/plafonds chez le fournisseur. Erreur/quota atteint : message visible, pas de fournisseur de secours payant.
- Aucun son du micro envoyé au cloud. Seuls la transcription, position/altitude/vitesse, phase, plan d'exercice et service radio actif sont envoyés directement au fournisseur choisi. Les clés ne vont pas à un serveur du projet et ne sont pas enregistrées dans les fichiers ; elles restent en mémoire jusqu'à fermeture/changement de fournisseur.
- Journaux locaux sous `~/.local/share/CopiloteVR/linux` (ou `$XDG_DATA_HOME/CopiloteVR/linux`, ou `--data`). Positions et textes y figurent, pas les clés ; pas de fichier micro permanent. Les WAV de synthèse sont temporaires. Supprimer les journaux manuellement si souhaité.
- L'IA joue le contrôleur en contexte, mais l'analyse de collationnement est encore générative, non un moteur déterministe de circulation. Trafic proche et météo ne sont **pas encore collectés** : le contexte signale explicitement leur absence. Pas de secteurs IFR, séparation de trafic ou carte OACI intégrés.
- Aucun serveur SaaS, compte, facturation ou gestion d'abonnement n'est déployé. Cette version teste le client BYOK à coût serveur nul pour le développeur. La commercialisation nécessitera notamment packaging, licences des dépendances/voix, tests utilisateurs et gestion de produit.

## Architecture et build

```text
MSFS dans Proton ← SimConnect.dll ← CopiloteBridge.exe dans le même préfixe
                                         ↓ fichiers locaux atomiques
                         Python/Qt Linux + micro Whisper + voix Piper
                                         ↓ texte/contexte à la demande
                           IA au choix (locale ou API personnelle)
                                         ↓
                      texte écran + panneau desktop / SteamVR + journal
```

Le pont relit une commande locale datée, l'acquitte et publie un état toutes les 250 ms. Il s'arrête après 45 secondes sans heartbeat du client. Il n'ouvre aucun serveur réseau. La démo utilise le même pont .NET en natif Linux. `ISimulatorAdapter` permet un futur X-Plane natif sans toucher au dialogue, au micro ou aux panneaux.

Build des ponts avec un SDK .NET 10 :

```bash
dotnet publish src/Copilote.Bridge -c Release -r win-x64 --self-contained true -o artifacts/bridge-windows -m:1
dotnet publish src/Copilote.Bridge -c Release --no-self-contained -o artifacts/linux/bridge -m:1
dotnet build tests/Copilote.Tests -m:1
dotnet tests/Copilote.Tests/bin/Debug/net10.0/Copilote.Tests.dll
PYTHONPATH=linux QT_QPA_PLATFORM=offscreen python3 -m unittest discover -s tests -p test_linux.py -v
```

Pour la démo reconstruite sans runtime embarqué, `dotnet` doit être dans le PATH, ou défini par `COPILOTE_DOTNET`. Le runtime inclus dans le ZIP est copié depuis la distribution officielle .NET utilisée pour le build, avec ses notices. La restauration nécessite les packages/runtime packs ; ici les packages étaient déjà en cache. L'audit de vulnérabilités NuGet n'a pas pu joindre son service et a été désactivé uniquement pour la commande de build hors ligne, pas dans la configuration du projet.

Sources techniques : [SimVars radio Microsoft](https://docs.flightsimulator.com/html/Programming_Tools/SimVars/Aircraft_SimVars/Aircraft_RadioNavigation_Variables.htm), [fréquences des installations Microsoft](https://docs.flightsimulator.com/html/Programming_Tools/SimConnect/API_Reference/Facilities/SimConnect_AddToFacilityDefinition.htm), [OpenVR Valve](https://github.com/ValveSoftware/openvr), [Whisper](https://github.com/openai/whisper), [Piper](https://github.com/OHF-Voice/piper1-gpl).
