/* * Copyright 2013-2016 Cel Skeggs, 2013 Andrew Merrill. * * This file is part of the CCRE, the Common Chicken Runtime Engine. * * The CCRE is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * The CCRE is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with the CCRE. If not, see <http://www.gnu.org/licenses/>. */ package ccre.viewer; import java.awt.image.BufferedImage; import java.io.EOFException; import java.io.IOException; import java.net.ConnectException; import java.net.NoRouteToHostException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.util.function.Consumer; import ccre.concurrency.ReporterThread; import ccre.log.Logger; class WebcamThread { private volatile String address; private volatile boolean terminate = false; private final Consumer<BufferedImage> output; private final ReporterThread thread; private Consumer<String> error; public WebcamThread(Consumer<BufferedImage> output, Consumer<String> error) { this.output = output; this.error = error; this.thread = new ReporterThread("Webcam") { @Override protected void threadBody() throws Throwable { body(); } }; this.thread.start(); } public synchronized void setAddress(String address) { this.address = address; this.notifyAll(); } public String getAddress() { return address; } public void terminate() { Logger.finest("Terminating webcam connection to " + address + "."); terminate = true; this.thread.interrupt(); } private void body() throws InterruptedException { output.accept(null); while (!terminate) { synchronized (this) { if (address == null && !terminate) { error.accept("No address."); this.wait(); continue; } } boolean long_sleep = false; try { try { connectToWebcam(); error.accept("Stopped."); } catch (EOFException e) { error.accept("Ended."); } catch (NoRouteToHostException e) { error.accept("No route to host."); } catch (SocketTimeoutException e) { error.accept("Timed out."); } catch (UnknownHostException e) { error.accept("Could not resolve."); } catch (ConnectException e) { error.accept(e.getMessage()); } catch (Exception e) { // this is the case that actually logs anything, so it // should wait long enough to avoid log spam. other cases do // not log, and so only benefit from shorter waits. Logger.warning("Webcam connection to " + address + " failed.", e); long_sleep = true; } } finally { output.accept(null); } Thread.sleep(long_sleep ? 500 : 50); } } private void connectToWebcam() throws IOException, EOFException { String addr = address; if (addr == null) { return; } error.accept("Connecting..."); try (WebcamReader reader = new WebcamReader(addr, 500)) { error.accept("Beginning..."); while (!terminate && addr.equals(this.address)) { output.accept(reader.readNext()); error.accept(null); } } } }