From 03670958a5eab132a4f1a6ae5ae58b88f55bfe2f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomas=20Wenstr=C3=B6m?= Date: Tue, 21 Mar 2017 22:59:29 +0100 Subject: [PATCH] Added a device listener --- config.properties | 1 - src/kaka/cakelight/Configuration.java | 2 -- src/kaka/cakelight/FrameGrabber.java | 4 +-- src/kaka/cakelight/VideoDeviceListener.java | 50 +++++++++++++++++++++++++++++ src/kaka/cakelight/VideoMode.java | 28 ++++++++++++---- 5 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 src/kaka/cakelight/VideoDeviceListener.java diff --git a/config.properties b/config.properties index cb1d685..ad972c2 100644 --- a/config.properties +++ b/config.properties @@ -1,6 +1,5 @@ # default settings -video.device=/dev/video2 video.width=720 video.height=576 video.bpp=2 diff --git a/src/kaka/cakelight/Configuration.java b/src/kaka/cakelight/Configuration.java index 30308e2..0d7bf5b 100644 --- a/src/kaka/cakelight/Configuration.java +++ b/src/kaka/cakelight/Configuration.java @@ -56,14 +56,12 @@ public class Configuration { } public class VideoConfiguration { - public String device; public int width; public int height; public int bpp; public CropConfiguration crop; private VideoConfiguration(Properties prop) { - device = get(prop, "video.device", "/dev/video0"); width = Integer.parseInt(get(prop, "video.width", "720")); height = Integer.parseInt(get(prop, "video.height", "576")); bpp = Integer.parseInt(get(prop, "video.bpp", "2")); diff --git a/src/kaka/cakelight/FrameGrabber.java b/src/kaka/cakelight/FrameGrabber.java index 8fbb16f..92fd50a 100644 --- a/src/kaka/cakelight/FrameGrabber.java +++ b/src/kaka/cakelight/FrameGrabber.java @@ -14,10 +14,10 @@ public class FrameGrabber implements Closeable { private FrameGrabber() { } - public static FrameGrabber from(Configuration config) { + public static FrameGrabber from(File videoDevice, Configuration config) { FrameGrabber fg = new FrameGrabber(); fg.config = config; - fg.file = new File(config.video.device); + fg.file = videoDevice; fg.bytesPerFrame = config.video.width * config.video.height * config.video.bpp; fg.prepare(); return fg; diff --git a/src/kaka/cakelight/VideoDeviceListener.java b/src/kaka/cakelight/VideoDeviceListener.java new file mode 100644 index 0000000..23c0b02 --- /dev/null +++ b/src/kaka/cakelight/VideoDeviceListener.java @@ -0,0 +1,50 @@ +package kaka.cakelight; + +import java.io.File; +import java.util.Optional; +import java.util.function.Consumer; + +import static kaka.cakelight.Main.log; + +public class VideoDeviceListener { + private Thread thread; + private Consumer> changeConsumer; + private File lastDevice = null; + + public void startListening() { + thread = new Thread() { + public void run() { + try { + while (!isInterrupted()) { + Optional device = findVideoDevice(); + if (!device.equals(Optional.ofNullable(lastDevice))) { + log("Video device change: %s", device.map(File::getAbsolutePath).orElse("none")); + changeConsumer.accept(device); + lastDevice = device.orElseGet(() -> null); + } + Thread.sleep(1000); + } + } catch (InterruptedException e) { + } + } + }; + thread.start(); + } + + public void stopListening() { + thread.interrupt(); + } + + private Optional findVideoDevice() { + File[] files = new File("/dev").listFiles((dir, name) -> name.matches("video[0-9]+")); + if (files == null || files.length == 0) { + return Optional.empty(); + } else { + return Optional.of(files[0]); + } + } + + public void onVideoDeviceChange(Consumer> consumer) { + changeConsumer = consumer; + } +} diff --git a/src/kaka/cakelight/VideoMode.java b/src/kaka/cakelight/VideoMode.java index 53cf09b..e0dc386 100644 --- a/src/kaka/cakelight/VideoMode.java +++ b/src/kaka/cakelight/VideoMode.java @@ -1,33 +1,38 @@ package kaka.cakelight; +import java.io.File; import java.io.IOException; import java.util.Optional; import java.util.function.Consumer; -import static kaka.cakelight.Main.log; -import static kaka.cakelight.Main.timeIt; - -public class VideoMode implements Mode { +public class VideoMode implements Mode, Consumer> { private Configuration config; private Thread thread; private Consumer frameConsumer; + private VideoDeviceListener deviceListener; + + public VideoMode() { + deviceListener = new VideoDeviceListener(); + deviceListener.onVideoDeviceChange(this); + } @Override public void enter(Configuration config) { this.config = config; - startGrabberThread(); + deviceListener.startListening(); } @Override public void exit() { thread.interrupt(); + deviceListener.stopListening(); } - private void startGrabberThread() { + private void startGrabberThread(File videoDevice) { assert frameConsumer != null; thread = new Thread() { public void run() { - try (FrameGrabber grabber = FrameGrabber.from(config)) { + try (FrameGrabber grabber = FrameGrabber.from(videoDevice, config)) { while (!isInterrupted()) { // Optional frame = grabber.grabFrame(); grabber.grabFrame().ifPresent(frameConsumer); @@ -46,4 +51,13 @@ public class VideoMode implements Mode { public void onFrame(Consumer consumer) { frameConsumer = consumer; } + + @Override + public void accept(Optional videoDevice) { + // Should only happen when this mode is active! + if (thread != null) { + thread.interrupt(); + } + videoDevice.ifPresent(this::startGrabberThread); + } } -- 2.11.0