Move all modes to package kaka.cakelight.mode
[kaka/cakelight.git] / src / kaka / cakelight / mode / VideoMode.java
diff --git a/src/kaka/cakelight/mode/VideoMode.java b/src/kaka/cakelight/mode/VideoMode.java
new file mode 100644 (file)
index 0000000..91a9f04
--- /dev/null
@@ -0,0 +1,70 @@
+package kaka.cakelight.mode;
+
+import kaka.cakelight.Configuration;
+import kaka.cakelight.FrameGrabber;
+import kaka.cakelight.VideoDeviceListener;
+import kaka.cakelight.VideoFrame;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+public class VideoMode extends Mode {
+    private Configuration config;
+    private Thread grabberThread;
+    private Consumer<VideoFrame> frameConsumer;
+    private VideoDeviceListener deviceListener;
+
+    public VideoMode() {
+        deviceListener = new VideoDeviceListener();
+        deviceListener.onVideoDeviceChange(this::onVideoDeviceChange);
+    }
+
+    @Override
+    public void enter(Configuration config) {
+        this.config = config;
+        deviceListener.startListening();
+    }
+
+    @Override
+    public void exit() {
+        grabberThread.interrupt();
+        deviceListener.stopListening();
+    }
+
+    private void startGrabberThread(File videoDevice) {
+        assert frameConsumer != null;
+        grabberThread = new Thread() {
+            public void run() {
+                try (FrameGrabber grabber = FrameGrabber.from(videoDevice, config)) {
+                    while (!isInterrupted()) {
+                        Optional<VideoFrame> frame = grabber.grabFrame();
+                        if (frameConsumer != null) frame.ifPresent(frameConsumer);
+                        frame.ifPresent(VideoMode.this::onVideoFrame);
+//                        timeIt("frame", grabber::grabFrame);
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        };
+        grabberThread.start();
+    }
+
+    public void onVideoFrame(Consumer<VideoFrame> consumer) {
+        frameConsumer = consumer;
+    }
+
+    private void onVideoFrame(VideoFrame frame) {
+        updateWithFrame(frame.getLedFrame());
+    }
+
+    public void onVideoDeviceChange(Optional<File> videoDevice) {
+        // Should only happen when this mode is active!
+        if (grabberThread != null) {
+            grabberThread.interrupt();
+        }
+        videoDevice.ifPresent(this::startGrabberThread);
+    }
+}