iterate and remove faulty capture devices on opening qr scan dialog

This commit is contained in:
Craig Raw 2025-05-29 13:58:46 +02:00
parent 4298bfb053
commit 74c298fd93
2 changed files with 32 additions and 17 deletions

View file

@ -122,19 +122,21 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> {
if(percentComplete.get() <= 0.0) { if(percentComplete.get() <= 0.0) {
Platform.runLater(() -> percentComplete.set(opening ? 0.0 : -1.0)); Platform.runLater(() -> percentComplete.set(opening ? 0.0 : -1.0));
} }
});
if(opening) { webcamService.openedProperty().addListener((_, _, opened) -> {
if(opened) {
Platform.runLater(() -> { Platform.runLater(() -> {
try { try {
postOpenUpdate = true; postOpenUpdate = true;
List<CaptureDevice> newDevices = new ArrayList<>(webcamService.getDevices()); List<CaptureDevice> newDevices = new ArrayList<>(webcamService.getAvailableDevices());
newDevices.removeAll(foundDevices); newDevices.removeAll(foundDevices);
foundDevices.addAll(newDevices); foundDevices.addAll(newDevices);
foundDevices.removeIf(device -> !webcamService.getDevices().contains(device)); foundDevices.removeIf(device -> !webcamService.getDevices().contains(device));
if(Config.get().getWebcamDevice() != null && webcamDeviceProperty.get() == null) { if(webcamService.getDevice() != null) {
for(CaptureDevice device : foundDevices) { for(CaptureDevice device : foundDevices) {
if(device.getName().equals(Config.get().getWebcamDevice())) { if(device.equals(webcamService.getDevice())) {
webcamDeviceProperty.set(device); webcamDeviceProperty.set(device);
} }
} }
@ -146,10 +148,7 @@ public class QRScanDialog extends Dialog<QRScanDialog.Result> {
postOpenUpdate = false; postOpenUpdate = false;
} }
}); });
} } else if(webcamResolutionProperty.get() != null) {
});
webcamService.closedProperty().addListener((_, _, closed) -> {
if(closed && webcamResolutionProperty.get() != null) {
webcamService.setResolution(webcamResolutionProperty.get()); webcamService.setResolution(webcamResolutionProperty.get());
webcamService.setDevice(webcamDeviceProperty.get()); webcamService.setDevice(webcamDeviceProperty.get());
Platform.runLater(() -> { Platform.runLater(() -> {

View file

@ -35,12 +35,13 @@ public class WebcamService extends ScheduledService<Image> {
private static final Logger log = LoggerFactory.getLogger(WebcamService.class); private static final Logger log = LoggerFactory.getLogger(WebcamService.class);
private List<CaptureDevice> devices; private List<CaptureDevice> devices;
private List<CaptureDevice> availableDevices;
private Set<WebcamResolution> resolutions; private Set<WebcamResolution> resolutions;
private WebcamResolution resolution; private WebcamResolution resolution;
private CaptureDevice device; private CaptureDevice device;
private final BooleanProperty opening = new SimpleBooleanProperty(false); private final BooleanProperty opening = new SimpleBooleanProperty(false);
private final BooleanProperty closed = new SimpleBooleanProperty(false); private final BooleanProperty opened = new SimpleBooleanProperty(false);
private final ObjectProperty<Result> resultProperty = new SimpleObjectProperty<>(null); private final ObjectProperty<Result> resultProperty = new SimpleObjectProperty<>(null);
@ -106,23 +107,26 @@ public class WebcamService extends ScheduledService<Image> {
@Override @Override
protected Image call() throws Exception { protected Image call() throws Exception {
try { try {
if(stream == null) { if(devices == null) {
devices = capture.getDevices(); devices = capture.getDevices();
availableDevices = new ArrayList<>(devices);
if(devices.isEmpty()) { if(devices.isEmpty()) {
throw new UnsupportedOperationException("No cameras available"); 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) { if(device != null) {
for(CaptureDevice webcam : devices) { for(CaptureDevice webcam : availableDevices) {
if(webcam.getName().equals(device.getName())) { if(webcam.getName().equals(device.getName())) {
selectedDevice = webcam; selectedDevice = webcam;
} }
} }
} else if(Config.get().getWebcamDevice() != null) { } else if(Config.get().getWebcamDevice() != null) {
for(CaptureDevice webcam : devices) { for(CaptureDevice webcam : availableDevices) {
if(webcam.getName().equals(Config.get().getWebcamDevice())) { if(webcam.getName().equals(Config.get().getWebcamDevice())) {
selectedDevice = webcam; selectedDevice = webcam;
} }
@ -170,15 +174,23 @@ public class WebcamService extends ScheduledService<Image> {
opening.set(true); opening.set(true);
stream = device.openStream(format); stream = device.openStream(format);
opening.set(false); opening.set(false);
closed.set(false);
try { try {
zoomLimits = stream.getPropertyLimits(CaptureProperty.Zoom); zoomLimits = stream.getPropertyLimits(CaptureProperty.Zoom);
} catch(Throwable e) { } catch(Throwable e) {
log.debug("Error getting zoom limits on " + device + ", assuming no zoom function"); 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(); BufferedImage originalImage = stream.capture();
CroppedDimension cropped = getCroppedDimension(originalImage); CroppedDimension cropped = getCroppedDimension(originalImage);
BufferedImage croppedImage = originalImage.getSubimage(cropped.x, cropped.y, cropped.length, cropped.length); BufferedImage croppedImage = originalImage.getSubimage(cropped.x, cropped.y, cropped.length, cropped.length);
@ -211,7 +223,7 @@ public class WebcamService extends ScheduledService<Image> {
public boolean cancel() { public boolean cancel() {
if(stream != null) { if(stream != null) {
stream.close(); stream.close();
closed.set(true); opened.set(false);
} }
return super.cancel(); return super.cancel();
@ -336,6 +348,10 @@ public class WebcamService extends ScheduledService<Image> {
return devices; return devices;
} }
public List<CaptureDevice> getAvailableDevices() {
return availableDevices;
}
public Set<WebcamResolution> getResolutions() { public Set<WebcamResolution> getResolutions() {
return resolutions; return resolutions;
} }
@ -376,8 +392,8 @@ public class WebcamService extends ScheduledService<Image> {
return opening; return opening;
} }
public BooleanProperty closedProperty() { public BooleanProperty openedProperty() {
return closed; return opened;
} }
public static <T extends Enum<T>> T getNearestEnum(T target) { public static <T extends Enum<T>> T getNearestEnum(T target) {