From d3a71a986692cff256b2b412dd46205f608b43d5 Mon Sep 17 00:00:00 2001 From: Jules Date: Mon, 8 Jun 2026 17:33:31 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20cam=C3=A9ra=20:=20gvfsd-gphoto2,=20race?= =?UTF-8?q?=20condition=20viewfinder,=20exif=5Ftranspose?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - kiosk-session.sh : tue gvfsd-gphoto2 au démarrage (démon GNOME qui monopolisait le DSLR sur USB et bloquait gphoto2) - camera.py : viewfinder activé AVANT mode="gphoto2" → le thread preview ne peut plus appeler capture_preview() avant que LiveView soit prêt - _activer_viewfinder_init() sans lock pour l'init (thread pas encore actif) - exif_transpose sur les captures DSLR → corrige l'orientation et les bandes blanches dues aux photos mal orientées Co-Authored-By: Claude Sonnet 4.6 --- backend/camera.py | 21 +++++++++++++++++---- scripts/kiosk-session.sh | 5 +++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/backend/camera.py b/backend/camera.py index 115aacc..b4d9b49 100644 --- a/backend/camera.py +++ b/backend/camera.py @@ -82,10 +82,11 @@ class Camera: try: self.camera = gp.Camera() self.camera.init() + # Viewfinder activé AVANT de rendre la caméra visible au thread preview + self._activer_viewfinder_init() self.connectee = True self.mode = "gphoto2" - log.info("Camera DSLR connectee") - self.activer_viewfinder() + log.info("Camera DSLR connectee (LiveView actif)") return True except gp.GPhoto2Error as e: log.warning(f"Pas de DSLR : {e}") @@ -159,7 +160,8 @@ class Camera: tmp_path = str(chemin_dest) + ".tmp" fichier_camera.save(tmp_path) self.activer_viewfinder() # Miroir relevé immédiatement après la prise - img = PILImage.open(tmp_path) + from PIL import ImageOps as PILImageOps + img = PILImageOps.exif_transpose(PILImage.open(tmp_path)) if img.width > 4000: ratio = 4000 / img.width img = img.resize((4000, int(img.height * ratio)), PILImage.LANCZOS) @@ -200,8 +202,19 @@ class Camera: else: return None # Pas de simulation ni webcam en dehors du mode dedie + def _activer_viewfinder_init(self): + """Active le LiveView pendant l'init (pas de lock, appelé avant que le thread démarre).""" + try: + cfg = self.camera.get_config() + vf = cfg.get_child_by_name("viewfinder") + vf.set_value(1) + self.camera.set_config(cfg) + log.info("Viewfinder activé (init)") + except Exception as e: + log.warning(f"Viewfinder non supporté : {e}") + def activer_viewfinder(self): - """Active le LiveView (miroir levé en permanence) sur les Canon.""" + """Active le LiveView (miroir levé) depuis le thread — thread-safe.""" if self.mode != "gphoto2" or not self.connectee: return try: diff --git a/scripts/kiosk-session.sh b/scripts/kiosk-session.sh index 70c969c..8e3e255 100755 --- a/scripts/kiosk-session.sh +++ b/scripts/kiosk-session.sh @@ -16,6 +16,11 @@ xset s noblank # Automount USB (pour la photostation) udiskie --no-notify --no-appindicator & +# Libérer le DSLR : gvfsd-gphoto2 (GNOME) le monopolise sinon +pkill -f gvfsd-gphoto2 2>/dev/null || true +pkill -f gvfs-gphoto2-volume-monitor 2>/dev/null || true +sleep 1 + # Backend en boucle : redémarre automatiquement s'il plante _backend_loop() { while true; do