Fix strip (K60 coupe auto), diagnostic preview, nettoyage
Strip 10x15 : - Envoie la strip simple avec format 10x15-2up (w288h432-div2) le K60 duplique et coupe automatiquement → plus de papier non coupé - Supprime creer_impression_strip et le 2-up manuel avec marges blanches - api/imprimer accepte format_papier depuis le frontend - Frontend stocke formatImpression et le passe à l'impression Diagnostic preview : - GET /api/camera/debug : teste capture_preview(), liste les widgets config gphoto2, état du thread → permet de voir l'erreur exacte Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ except ImportError:
|
|||||||
gp = None
|
gp = None
|
||||||
from backend.gallery import lister_photos, compter_photos, supprimer_photo, vider_galerie
|
from backend.gallery import lister_photos, compter_photos, supprimer_photo, vider_galerie
|
||||||
from backend.effects import appliquer_filtre, appliquer_overlay, chroma_key, lister_overlays, lister_fonds, lister_cadres, FILTRES
|
from backend.effects import appliquer_filtre, appliquer_overlay, chroma_key, lister_overlays, lister_fonds, lister_cadres, FILTRES
|
||||||
from backend.collage import creer_strip, creer_collage, creer_impression_strip
|
from backend.collage import creer_strip, creer_collage
|
||||||
from backend.destinations import distribuer_photo, detecter_usb, compteur_restant, reset_compteur, recuperer_booth_password
|
from backend.destinations import distribuer_photo, detecter_usb, compteur_restant, reset_compteur, recuperer_booth_password
|
||||||
from backend.printer import lister_imprimantes, imprimer
|
from backend.printer import lister_imprimantes, imprimer
|
||||||
from backend.mailer import envoyer_photo
|
from backend.mailer import envoyer_photo
|
||||||
@@ -396,6 +396,38 @@ async def api_camera_statut():
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/api/camera/debug")
|
||||||
|
async def api_camera_debug():
|
||||||
|
"""Diagnostic complet de la caméra (preview, viewfinder, erreurs gphoto2)."""
|
||||||
|
info = {
|
||||||
|
"mode": camera.mode,
|
||||||
|
"connectee": camera.connectee,
|
||||||
|
"preview_actif": _preview_actif,
|
||||||
|
"derniere_frame_ok": _derniere_frame_preview is not None,
|
||||||
|
"preview_none_count": _preview_none_count,
|
||||||
|
"capture_en_cours": capture_en_cours,
|
||||||
|
}
|
||||||
|
if camera.mode == "gphoto2" and camera.connectee:
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
try:
|
||||||
|
frame = await loop.run_in_executor(None, camera._preview_gphoto2)
|
||||||
|
info["test_preview"] = "ok" if frame else "retourne None"
|
||||||
|
info["test_preview_taille"] = len(frame) if frame else 0
|
||||||
|
except Exception as e:
|
||||||
|
info["test_preview"] = f"ERREUR : {e}"
|
||||||
|
try:
|
||||||
|
cfg_names = []
|
||||||
|
with camera._gp_lock:
|
||||||
|
cfg = camera.camera.get_config()
|
||||||
|
for i in range(cfg.count_children()):
|
||||||
|
child = cfg.get_child(i)
|
||||||
|
cfg_names.append(child.get_name())
|
||||||
|
info["config_widgets_top"] = cfg_names
|
||||||
|
except Exception as e:
|
||||||
|
info["config_widgets_top"] = f"ERREUR : {e}"
|
||||||
|
return info
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/camera/reconnecter")
|
@app.post("/api/camera/reconnecter")
|
||||||
async def api_camera_reconnecter(body: dict = {}):
|
async def api_camera_reconnecter(body: dict = {}):
|
||||||
camera.deconnecter()
|
camera.deconnecter()
|
||||||
@@ -487,13 +519,13 @@ async def api_strip(donnees: dict):
|
|||||||
return JSONResponse({"erreur": f"Photo introuvable : {n}"}, status_code=404)
|
return JSONResponse({"erreur": f"Photo introuvable : {n}"}, status_code=404)
|
||||||
chemins.append(c)
|
chemins.append(c)
|
||||||
chemin_strip = creer_strip(chemins)
|
chemin_strip = creer_strip(chemins)
|
||||||
# Creer aussi la page d'impression (2 bandes sur 10x15 paysage)
|
|
||||||
chemin_print = creer_impression_strip(chemin_strip)
|
|
||||||
return {
|
return {
|
||||||
"nom": chemin_strip.name,
|
"nom": chemin_strip.name,
|
||||||
"chemin": f"/data/exports/{chemin_strip.name}",
|
"chemin": f"/data/exports/{chemin_strip.name}",
|
||||||
"impression": chemin_print.name,
|
# La strip elle-même est envoyée avec format 10x15-2up :
|
||||||
"chemin_impression": f"/data/exports/{chemin_print.name}",
|
# le K60 duplique et coupe automatiquement via -div2
|
||||||
|
"impression": chemin_strip.name,
|
||||||
|
"format_impression": "10x15-2up",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -652,8 +684,9 @@ async def api_imprimer(donnees: dict):
|
|||||||
chemin = DOSSIER_PHOTOS / nom
|
chemin = DOSSIER_PHOTOS / nom
|
||||||
if not chemin.exists():
|
if not chemin.exists():
|
||||||
return JSONResponse({"erreur": "Photo introuvable"}, status_code=404)
|
return JSONResponse({"erreur": "Photo introuvable"}, status_code=404)
|
||||||
cadre_override = donnees.get("cadre") # cadre choisi en session, prioritaire sur le config
|
cadre_override = donnees.get("cadre")
|
||||||
resultat = imprimer(chemin, copies=copies, cadre_override=cadre_override)
|
format_papier = donnees.get("format_papier") or None
|
||||||
|
resultat = imprimer(chemin, copies=copies, cadre_override=cadre_override, format_papier=format_papier)
|
||||||
if resultat.get("succes"):
|
if resultat.get("succes"):
|
||||||
distribuer_photo(chemin, imprimee=True)
|
distribuer_photo(chemin, imprimee=True)
|
||||||
return resultat
|
return resultat
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ wsOnMessage('camera_ok', () => {
|
|||||||
async function lancerCapture() {
|
async function lancerCapture() {
|
||||||
photosSession = [];
|
photosSession = [];
|
||||||
photoImpression = null;
|
photoImpression = null;
|
||||||
|
formatImpression = null;
|
||||||
|
|
||||||
document.getElementById('photo-resultat').src = '';
|
document.getElementById('photo-resultat').src = '';
|
||||||
document.getElementById('photo-partage').src = '';
|
document.getElementById('photo-partage').src = '';
|
||||||
@@ -249,7 +250,8 @@ function afficherFlash() {
|
|||||||
setTimeout(() => flash.classList.add('cache'), 400);
|
setTimeout(() => flash.classList.add('cache'), 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
let photoImpression = null; // Nom du fichier d'impression (2 bandes sur 10x15)
|
let photoImpression = null; // Fichier à imprimer (strip ou photo finale)
|
||||||
|
let formatImpression = null; // Format CUPS à utiliser (ex: "10x15-2up")
|
||||||
|
|
||||||
async function traiterCapture() {
|
async function traiterCapture() {
|
||||||
if (photosSession.length === 0) {
|
if (photosSession.length === 0) {
|
||||||
@@ -258,6 +260,7 @@ async function traiterCapture() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
photoImpression = null;
|
photoImpression = null;
|
||||||
|
formatImpression = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (modeActuel === 'multi') {
|
if (modeActuel === 'multi') {
|
||||||
@@ -270,6 +273,7 @@ async function traiterCapture() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (resultat.impression) photoImpression = resultat.impression;
|
if (resultat.impression) photoImpression = resultat.impression;
|
||||||
|
if (resultat.format_impression) formatImpression = resultat.format_impression;
|
||||||
} else {
|
} else {
|
||||||
resultat = await apiPost('/api/collage', { photos: photosSession });
|
resultat = await apiPost('/api/collage', { photos: photosSession });
|
||||||
if (resultat.erreur) {
|
if (resultat.erreur) {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ async function lancerImpression() {
|
|||||||
photo: fichierImpression,
|
photo: fichierImpression,
|
||||||
copies: nbExemplaires,
|
copies: nbExemplaires,
|
||||||
cadre: cadreChoisi || undefined,
|
cadre: cadreChoisi || undefined,
|
||||||
|
format_papier: formatImpression || undefined,
|
||||||
});
|
});
|
||||||
if (resultat.succes) {
|
if (resultat.succes) {
|
||||||
afficherStatut(`${nbExemplaires} exemplaire(s) envoye(s) a l'imprimante !`, 'succes');
|
afficherStatut(`${nbExemplaires} exemplaire(s) envoye(s) a l'imprimante !`, 'succes');
|
||||||
|
|||||||
Reference in New Issue
Block a user