From 74c298fd933a296d5251fa96d9bf9d1ed45e3c57 Mon Sep 17 00:00:00 2001 From: Craig Raw Date: Thu, 29 May 2025 13:58:46 +0200 Subject: [PATCH] iterate and remove faulty capture devices on opening qr scan dialog --- .../sparrow/control/QRScanDialog.java | 15 ++++---- .../sparrow/control/WebcamService.java | 34 ++++++++++++++----- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java b/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java index d6c39809..608468c7 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/QRScanDialog.java @@ -122,19 +122,21 @@ public class QRScanDialog extends Dialog { if(percentComplete.get() <= 0.0) { Platform.runLater(() -> percentComplete.set(opening ? 0.0 : -1.0)); } + }); - if(opening) { + webcamService.openedProperty().addListener((_, _, opened) -> { + if(opened) { Platform.runLater(() -> { try { postOpenUpdate = true; - List newDevices = new ArrayList<>(webcamService.getDevices()); + List newDevices = new ArrayList<>(webcamService.getAvailableDevices()); newDevices.removeAll(foundDevices); foundDevices.addAll(newDevices); foundDevices.removeIf(device -> !webcamService.getDevices().contains(device)); - if(Config.get().getWebcamDevice() != null && webcamDeviceProperty.get() == null) { + if(webcamService.getDevice() != null) { for(CaptureDevice device : foundDevices) { - if(device.getName().equals(Config.get().getWebcamDevice())) { + if(device.equals(webcamService.getDevice())) { webcamDeviceProperty.set(device); } } @@ -146,10 +148,7 @@ public class QRScanDialog extends Dialog { postOpenUpdate = false; } }); - } - }); - webcamService.closedProperty().addListener((_, _, closed) -> { - if(closed && webcamResolutionProperty.get() != null) { + } else if(webcamResolutionProperty.get() != null) { webcamService.setResolution(webcamResolutionProperty.get()); webcamService.setDevice(webcamDeviceProperty.get()); Platform.runLater(() -> { diff --git a/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java b/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java index e7f97973..bffa0532 100644 --- a/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java +++ b/src/main/java/com/sparrowwallet/sparrow/control/WebcamService.java @@ -35,12 +35,13 @@ public class WebcamService extends ScheduledService { private static final Logger log = LoggerFactory.getLogger(WebcamService.class); private List devices; + private List availableDevices; private Set resolutions; private WebcamResolution resolution; private CaptureDevice device; private final BooleanProperty opening = new SimpleBooleanProperty(false); - private final BooleanProperty closed = new SimpleBooleanProperty(false); + private final BooleanProperty opened = new SimpleBooleanProperty(false); private final ObjectProperty resultProperty = new SimpleObjectProperty<>(null); @@ -106,23 +107,26 @@ public class WebcamService extends ScheduledService { @Override protected Image call() throws Exception { try { - if(stream == null) { + if(devices == null) { devices = capture.getDevices(); + availableDevices = new ArrayList<>(devices); if(devices.isEmpty()) { throw new UnsupportedOperationException("No cameras available"); } + } - CaptureDevice selectedDevice = devices.stream().filter(d -> !d.getFormats().isEmpty()).findFirst().orElse(devices.getFirst()); + while(stream == null && !availableDevices.isEmpty()) { + CaptureDevice selectedDevice = availableDevices.stream().filter(d -> !d.getFormats().isEmpty()).findFirst().orElse(availableDevices.getFirst()); if(device != null) { - for(CaptureDevice webcam : devices) { + for(CaptureDevice webcam : availableDevices) { if(webcam.getName().equals(device.getName())) { selectedDevice = webcam; } } } else if(Config.get().getWebcamDevice() != null) { - for(CaptureDevice webcam : devices) { + for(CaptureDevice webcam : availableDevices) { if(webcam.getName().equals(Config.get().getWebcamDevice())) { selectedDevice = webcam; } @@ -170,15 +174,23 @@ public class WebcamService extends ScheduledService { opening.set(true); stream = device.openStream(format); opening.set(false); - closed.set(false); try { zoomLimits = stream.getPropertyLimits(CaptureProperty.Zoom); } catch(Throwable e) { log.debug("Error getting zoom limits on " + device + ", assuming no zoom function"); } + + if(stream == null) { + availableDevices.remove(device); + } } + if(stream == null) { + throw new UnsupportedOperationException("No usable cameras available, tried " + devices); + } + + opened.set(true); BufferedImage originalImage = stream.capture(); CroppedDimension cropped = getCroppedDimension(originalImage); BufferedImage croppedImage = originalImage.getSubimage(cropped.x, cropped.y, cropped.length, cropped.length); @@ -211,7 +223,7 @@ public class WebcamService extends ScheduledService { public boolean cancel() { if(stream != null) { stream.close(); - closed.set(true); + opened.set(false); } return super.cancel(); @@ -336,6 +348,10 @@ public class WebcamService extends ScheduledService { return devices; } + public List getAvailableDevices() { + return availableDevices; + } + public Set getResolutions() { return resolutions; } @@ -376,8 +392,8 @@ public class WebcamService extends ScheduledService { return opening; } - public BooleanProperty closedProperty() { - return closed; + public BooleanProperty openedProperty() { + return opened; } public static > T getNearestEnum(T target) {