Pellicule galerie + délai S_PREV + USB unbind/bind
- draw_galerie() : rendu pellicule (bande film avec perforations) quand le mode est actif - _load_gal() : charge les surfs à la taille des cadres pellicule si actif - S_PREV : 1.5s → 2.5s pour laisser le DSLR revenir en live view - _usb_reset_done() : utilise unbind/bind sysfs au lieu de usbreset (unbind/bind = seule méthode qui libère réellement le claim USB) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -93,7 +93,7 @@ THEMES = {
|
|||||||
|
|
||||||
# ── Utilitaire USB ───────────────────────────────────────────────────────────
|
# ── Utilitaire USB ───────────────────────────────────────────────────────────
|
||||||
def _usb_reset_done():
|
def _usb_reset_done():
|
||||||
"""Reset USB des DSLR Canon/Nikon/Sony pour libérer tout claim obsolète."""
|
"""Reset USB des DSLR via unbind/bind sysfs pour libérer tout claim obsolète."""
|
||||||
import glob, subprocess as _sp
|
import glob, subprocess as _sp
|
||||||
for dev_path in glob.glob('/sys/bus/usb/devices/[0-9]*-[0-9.]*'):
|
for dev_path in glob.glob('/sys/bus/usb/devices/[0-9]*-[0-9.]*'):
|
||||||
prod_file = f"{dev_path}/product"
|
prod_file = f"{dev_path}/product"
|
||||||
@@ -106,12 +106,14 @@ def _usb_reset_done():
|
|||||||
if not any(b in prod for b in ('Canon', 'Nikon', 'Sony', 'Digital Camera')):
|
if not any(b in prod for b in ('Canon', 'Nikon', 'Sony', 'Digital Camera')):
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
bus = int(open(f"{dev_path}/busnum").read().strip())
|
dev_name = os.path.basename(dev_path)
|
||||||
dev = int(open(f"{dev_path}/devnum").read().strip())
|
_sp.run(['sudo', 'sh', '-c', f'echo {dev_name} > /sys/bus/usb/drivers/usb/unbind'],
|
||||||
usb_path = f"/dev/bus/usb/{bus:03d}/{dev:03d}"
|
capture_output=True, timeout=5)
|
||||||
_sp.run(['sudo', 'usbreset', usb_path], capture_output=True, timeout=5)
|
time.sleep(0.8)
|
||||||
print(f"USB reset: {usb_path} ({prod})")
|
_sp.run(['sudo', 'sh', '-c', f'echo {dev_name} > /sys/bus/usb/drivers/usb/bind'],
|
||||||
time.sleep(1.2)
|
capture_output=True, timeout=5)
|
||||||
|
print(f"USB unbind/bind: {dev_name} ({prod})")
|
||||||
|
time.sleep(2.0)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"USB reset err: {e}")
|
print(f"USB reset err: {e}")
|
||||||
|
|
||||||
@@ -836,7 +838,7 @@ class PB:
|
|||||||
thumb_h = _PELL_FH if is_pell else 200 # haute résolution en mode pellicule
|
thumb_h = _PELL_FH if is_pell else 200 # haute résolution en mode pellicule
|
||||||
|
|
||||||
for i in range(nb):
|
for i in range(nb):
|
||||||
self.num_ph=i; self.etat=S_PREV; time.sleep(1.5)
|
self.num_ph=i; self.etat=S_PREV; time.sleep(2.5)
|
||||||
self.etat=S_COMPTE
|
self.etat=S_COMPTE
|
||||||
for c in range(delai,0,-1): self.chiffre=c; time.sleep(1)
|
for c in range(delai,0,-1): self.chiffre=c; time.sleep(1)
|
||||||
self.etat=S_CAP; ch=self._capturer()
|
self.etat=S_CAP; ch=self._capturer()
|
||||||
@@ -858,7 +860,16 @@ class PB:
|
|||||||
|
|
||||||
def _load_gal(self):
|
def _load_gal(self):
|
||||||
surfs = []
|
surfs = []
|
||||||
if self.format in ("bande3x2","bande4x2"):
|
is_pell = self.cfg.get("fonctionnalites",{}).get("pellicule_mode",False)
|
||||||
|
if is_pell and self.format in ("bande3x2","bande4x2"):
|
||||||
|
nb = 3 if self.format=="bande3x2" else 4
|
||||||
|
fw = (W - _PELL_GAP*(nb+1)) // nb
|
||||||
|
for ch in self.photos[:nb]:
|
||||||
|
try:
|
||||||
|
img=ImageOps.exif_transpose(Image.open(ch).convert("RGB")).resize((fw,_PELL_FH),Image.LANCZOS)
|
||||||
|
surfs.append(pygame.image.fromstring(img.tobytes(),img.size,"RGB"))
|
||||||
|
except: surfs.append(None)
|
||||||
|
elif self.format in ("bande3x2","bande4x2"):
|
||||||
nb = 3 if self.format=="bande3x2" else 4
|
nb = 3 if self.format=="bande3x2" else 4
|
||||||
pw = W // nb; sh = (H - 150) // 2
|
pw = W // nb; sh = (H - 150) // 2
|
||||||
for ch in self.photos[:nb]:
|
for ch in self.photos[:nb]:
|
||||||
@@ -1319,6 +1330,34 @@ class PB:
|
|||||||
for k in range(4):
|
for k in range(4):
|
||||||
a=int(128+127*math.sin(t*3+k*1.5))
|
a=int(128+127*math.sin(t*3+k*1.5))
|
||||||
pygame.draw.circle(self.scr,(*T["prim"],a),(W//2-60+k*40,H//2+30),12)
|
pygame.draw.circle(self.scr,(*T["prim"],a),(W//2-60+k*40,H//2+30),12)
|
||||||
|
elif self._is_pell():
|
||||||
|
# ── Galerie style pellicule ──
|
||||||
|
nb=3 if self.format=="bande3x2" else 4
|
||||||
|
gap=_PELL_GAP; fw=(W-gap*(nb+1))//nb; fh=_PELL_FH
|
||||||
|
film_y=(H-_FILM_H)//2; frame_y=film_y+_SPR_H+_SPR_GAP
|
||||||
|
self.scr.fill((8,8,8))
|
||||||
|
pygame.draw.rect(self.scr,(18,18,18),(0,film_y,W,_FILM_H))
|
||||||
|
pygame.draw.rect(self.scr,(35,35,35),(0,film_y,W,_FILM_H),1)
|
||||||
|
hole_w,hole_h=32,22
|
||||||
|
for hy in (film_y+_SPR_H//2-hole_h//2, film_y+_FILM_H-_SPR_H//2-hole_h//2):
|
||||||
|
x=18
|
||||||
|
while x+hole_w<W-10:
|
||||||
|
pygame.draw.rect(self.scr,(180,180,180),(x,hy,hole_w,hole_h),border_radius=5)
|
||||||
|
pygame.draw.rect(self.scr,(8,8,8),(x+3,hy+3,hole_w-6,hole_h-6),border_radius=3)
|
||||||
|
x+=62
|
||||||
|
for i in range(nb):
|
||||||
|
fx=gap+i*(fw+gap); fy=frame_y
|
||||||
|
surf=self.gal_surfs[i] if i<len(self.gal_surfs) else None
|
||||||
|
if surf:
|
||||||
|
ts=pygame.transform.scale(surf,(fw,fh))
|
||||||
|
self.scr.blit(ts,(fx,fy))
|
||||||
|
pygame.draw.rect(self.scr,T["prim"],(fx,fy,fw,fh),2)
|
||||||
|
else:
|
||||||
|
pygame.draw.rect(self.scr,(15,15,15),(fx,fy,fw,fh))
|
||||||
|
nf=self.F["xxs"].render(f"{i+1:02d}A",True,(90,90,90))
|
||||||
|
num_y=frame_y+fh+_SPR_GAP+4
|
||||||
|
if num_y+20<film_y+_FILM_H:
|
||||||
|
self.scr.blit(nf,(fx+fw//2-nf.get_width()//2,num_y))
|
||||||
elif self.format in ("bande3x2","bande4x2"):
|
elif self.format in ("bande3x2","bande4x2"):
|
||||||
nb=3 if self.format=="bande3x2" else 4
|
nb=3 if self.format=="bande3x2" else 4
|
||||||
pw=W//nb; sh=(H-150)//2
|
pw=W//nb; sh=(H-150)//2
|
||||||
|
|||||||
Reference in New Issue
Block a user