Use stack of modes instead of just one
[kaka/cakelight.git] / src / kaka / cakelight / mode / VideoMode.java
1 package kaka.cakelight.mode;
2
3 import kaka.cakelight.Configuration;
4 import kaka.cakelight.FrameGrabber;
5 import kaka.cakelight.VideoDeviceListener;
6 import kaka.cakelight.VideoFrame;
7
8 import java.io.File;
9 import java.io.IOException;
10 import java.util.Optional;
11 import java.util.function.Consumer;
12
13 public class VideoMode extends Mode {
14     private Configuration config;
15     private Thread grabberThread;
16     private Consumer<VideoFrame> frameConsumer;
17     private VideoDeviceListener deviceListener;
18
19     public VideoMode() {
20         deviceListener = new VideoDeviceListener();
21         deviceListener.onVideoDeviceChange(this::onVideoDeviceChange);
22     }
23
24     @Override
25     public void enter(Configuration config) {
26         this.config = config;
27         deviceListener.startListening();
28     }
29
30     @Override
31     public void exit() {
32         grabberThread.interrupt();
33         deviceListener.stopListening();
34     }
35
36     private void startGrabberThread(File videoDevice) {
37         assert frameConsumer != null;
38         grabberThread = new Thread() {
39             public void run() {
40                 try (FrameGrabber grabber = FrameGrabber.from(videoDevice, config)) {
41                     while (!isInterrupted()) {
42                         Optional<VideoFrame> frame = grabber.grabFrame();
43                         if (frameConsumer != null) frame.ifPresent(frameConsumer);
44                         frame.ifPresent(VideoMode.this::onVideoFrame);
45 //                        timeIt("frame", grabber::grabFrame);
46                     }
47                 } catch (IOException e) {
48                     e.printStackTrace();
49                 }
50             }
51         };
52         grabberThread.start();
53     }
54
55     public void onVideoFrame(Consumer<VideoFrame> consumer) {
56         frameConsumer = consumer;
57     }
58
59     private void onVideoFrame(VideoFrame frame) {
60         updateWithFrame(frame.getLedFrame());
61     }
62
63     public void onVideoDeviceChange(Optional<File> videoDevice) {
64         // Should only happen when this mode is active!
65         if (grabberThread != null) {
66             grabberThread.interrupt();
67         }
68         videoDevice.ifPresent(this::startGrabberThread);
69     }
70 }