Added a LED controller that consumes LED frames from the modes
authorTomas Wenström <tomas.wenstrom@gmail.com>
Tue, 28 Mar 2017 20:14:58 +0000 (22:14 +0200)
committerTomas Wenström <tomas.wenstrom@gmail.com>
Tue, 28 Mar 2017 20:14:58 +0000 (22:14 +0200)
src/kaka/cakelight/CakeLight.java
src/kaka/cakelight/Frame.java
src/kaka/cakelight/GuiTest.java
src/kaka/cakelight/LedController.java [new file with mode: 0644]
src/kaka/cakelight/LedFrame.java [new file with mode: 0644]
src/kaka/cakelight/Main.java
src/kaka/cakelight/Mode.java
src/kaka/cakelight/VideoMode.java

index afc7b26..33e0035 100644 (file)
@@ -1,18 +1,19 @@
 package kaka.cakelight;
 
-import static kaka.cakelight.Main.timeIt;
-
 public class CakeLight {
     private Configuration config;
     private Mode mode;
+    private LedController ledController;
 
-    public CakeLight(Configuration config) {
+    public CakeLight(Configuration config, LedController ledController) {
         this.config = config;
+        this.ledController = ledController;
     }
 
     public void setMode(Mode mode) {
         cleanup();
         this.mode = mode;
+        mode.setFrameListener(ledController);
         mode.enter(config);
     }
 
index a1d6946..07a6ffd 100644 (file)
@@ -131,4 +131,17 @@ public class Frame {
     public Mat getConvertedImage() {
         return converted;
     }
+
+    /**
+     * Creates a LED frame going clockwise from the bottom-left corner, sans the corners.
+     */
+    public LedFrame getLedFrame() {
+        LedFrame frame = LedFrame.from(config);
+        int led = 0;
+        for (int i = config.leds.rows - 1; i >= 0; i--) frame.setLedColor(led++, getLedColor(ListPosition.LEFT, i));
+        for (int i = 0; i < config.leds.cols; i++)      frame.setLedColor(led++, getLedColor(ListPosition.TOP, i));
+        for (int i = 0; i < config.leds.rows; i++)      frame.setLedColor(led++, getLedColor(ListPosition.RIGHT, i));
+        for (int i = config.leds.cols - 1; i >= 0; i--) frame.setLedColor(led++, getLedColor(ListPosition.BOTTOM, i));
+        return frame;
+    }
 }
index 8feac32..a3cabf4 100644 (file)
@@ -56,11 +56,16 @@ public class GuiTest extends Application {
 
     private void setupCakeLight() {
         log("Running with config:\n" + config);
-        cakelight = new CakeLight(config);
+        cakelight = new CakeLight(config, new LedController() {
+            @Override
+            public void accept(LedFrame ledFrame) {
+                if (!paused) drawLEDs(canvas.getGraphicsContext2D(), ledFrame);
+            }
+        });
         VideoMode mode = new VideoMode();
         cakelight.setMode(mode);
         cakelight.startLoop();
-        mode.onFrame(frame -> drawFrame(canvas.getGraphicsContext2D(), frame));
+        mode.onVideoFrame(frame -> drawFrame(canvas.getGraphicsContext2D(), frame));
     }
 
     private void drawFrame(GraphicsContext gc, Frame frame) {
@@ -70,24 +75,23 @@ public class GuiTest extends Application {
         drawRows(gc, frame);
 //        drawVideo(gc, frame);
         drawBorderAndGrid(gc);
-        drawLEDs(gc, frame);
     }
 
-    private void drawLEDs(GraphicsContext gc, Frame frame) {
+    private void drawLEDs(GraphicsContext gc, LedFrame frame) {
         int ledLength = GUTTER;
         float colSize = 16f * BLOCK / config.leds.cols;
         float rowSize = 9f * BLOCK / config.leds.rows;
 //        DropShadow shadow = new DropShadow(BlurType.ONE_PASS_BOX, Color.RED, colSize * 2, colSize, 0, 0);
         for (int x = 0; x < config.leds.cols; x++) {
-            gc.setFill(frame.getLedColor(ListPosition.TOP, x));
+            gc.setFill(frame.getLedColor(x + config.leds.rows));
             gc.fillRect(GUTTER + x * colSize, GUTTER - ledLength, colSize, ledLength);
-            gc.setFill(frame.getLedColor(ListPosition.BOTTOM, x));
+            gc.setFill(frame.getLedColor(config.leds.rows * 2 + config.leds.cols * 2 - 1 - x));
             gc.fillRect(GUTTER + x * colSize, GUTTER + 9 * BLOCK, colSize, ledLength);
         }
         for (int y = 0; y < config.leds.rows; y++) {
-            gc.setFill(frame.getLedColor(ListPosition.LEFT, y));
+            gc.setFill(frame.getLedColor(config.leds.rows - 1 - y));
             gc.fillRect(GUTTER - ledLength, GUTTER + y * rowSize, ledLength, rowSize);
-            gc.setFill(frame.getLedColor(ListPosition.RIGHT, y));
+            gc.setFill(frame.getLedColor(y + config.leds.rows + config.leds.cols));
             gc.fillRect(GUTTER + 16 * BLOCK, GUTTER + y * rowSize, ledLength, rowSize);
         }
     }
diff --git a/src/kaka/cakelight/LedController.java b/src/kaka/cakelight/LedController.java
new file mode 100644 (file)
index 0000000..9749483
--- /dev/null
@@ -0,0 +1,10 @@
+package kaka.cakelight;
+
+import java.util.function.Consumer;
+
+public class LedController implements Consumer<LedFrame> {
+    @Override
+    public void accept(LedFrame ledFrame) {
+       // TODO
+    }
+}
diff --git a/src/kaka/cakelight/LedFrame.java b/src/kaka/cakelight/LedFrame.java
new file mode 100644 (file)
index 0000000..a4f6293
--- /dev/null
@@ -0,0 +1,21 @@
+package kaka.cakelight;
+
+import javafx.scene.paint.Color;
+
+public class LedFrame {
+    private Color[] leds;
+
+    public static LedFrame from(Configuration config) {
+        LedFrame frame = new LedFrame();
+        frame.leds = new Color[config.leds.cols * 2 + config.leds.rows * 2];
+        return frame;
+    }
+
+    public void setLedColor(int led, Color color) {
+        leds[led] = color;
+    }
+
+    public Color getLedColor(int led) {
+        return leds[led];
+    }
+}
index 9786aac..e071fec 100644 (file)
@@ -13,7 +13,7 @@ public class Main {
        Configuration config = Configuration.from("config.properties");
        log("Running with config:\n" + config);
 
-       CakeLight cakelight = new CakeLight(config);
+       CakeLight cakelight = new CakeLight(config, new LedController());
        cakelight.setMode(new VideoMode());
        cakelight.startLoop();
 //     try {
index 3a1f5d0..7b0227b 100644 (file)
@@ -1,6 +1,14 @@
 package kaka.cakelight;
 
-public interface Mode {
-    void enter(Configuration config);
-    void exit();
+import java.util.function.Consumer;
+
+public abstract class Mode {
+    protected Consumer<LedFrame> frameListener;
+
+    public abstract void enter(Configuration config);
+    public abstract void exit();
+
+    public void setFrameListener(Consumer<LedFrame> listener) {
+        frameListener = listener;
+    }
 }
index e0dc386..e4b9400 100644 (file)
@@ -5,7 +5,7 @@ import java.io.IOException;
 import java.util.Optional;
 import java.util.function.Consumer;
 
-public class VideoMode implements Mode, Consumer<Optional<File>> {
+public class VideoMode extends Mode implements Consumer<Optional<File>> {
     private Configuration config;
     private Thread thread;
     private Consumer<Frame> frameConsumer;
@@ -34,8 +34,9 @@ public class VideoMode implements Mode, Consumer<Optional<File>> {
             public void run() {
                 try (FrameGrabber grabber = FrameGrabber.from(videoDevice, config)) {
                     while (!isInterrupted()) {
-//                        Optional<Frame> frame = grabber.grabFrame();
-                        grabber.grabFrame().ifPresent(frameConsumer);
+                        Optional<Frame> frame = grabber.grabFrame();
+                        if (frameConsumer != null) frame.ifPresent(frameConsumer);
+                        frame.ifPresent(VideoMode.this::onFrame);
 //                        timeIt("frame", grabber::grabFrame);
                         // TODO: process frame
                         // TODO: save where the LedController can access it
@@ -48,10 +49,15 @@ public class VideoMode implements Mode, Consumer<Optional<File>> {
         thread.start();
     }
 
-    public void onFrame(Consumer<Frame> consumer) {
+    public void onVideoFrame(Consumer<Frame> consumer) {
         frameConsumer = consumer;
     }
 
+    private void onFrame(Frame frame) {
+        assert frameListener != null;
+        frameListener.accept(frame.getLedFrame());
+    }
+
     @Override
     public void accept(Optional<File> videoDevice) {
         // Should only happen when this mode is active!