41b599a3058a008aef3694cbd18ff546830e54d0
[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     private boolean isPaused = false;
19
20     public VideoMode() {
21         deviceListener = new VideoDeviceListener();
22         deviceListener.onVideoDeviceChange(this::onVideoDeviceChange);
23     }
24
25     @Override
26     public void enter(Configuration config) {
27         this.config = config;
28         deviceListener.startListening();
29     }
30
31     @Override
32     public void pause() {
33         isPaused = true;
34     }
35
36     @Override
37     public void resume() {
38         isPaused = false;
39         synchronized (grabberThread) {
40             grabberThread.notify();
41         }
42     }
43
44     @Override
45     public void exit() {
46         grabberThread.interrupt();
47         deviceListener.stopListening();
48     }
49
50     private void startGrabberThread(File videoDevice) {
51         assert frameConsumer != null;
52         grabberThread = new Thread() {
53             public void run() {
54                 try (FrameGrabber grabber = FrameGrabber.from(videoDevice, config)) {
55                     while (!isInterrupted()) {
56                         Optional<VideoFrame> frame = grabber.grabFrame();
57                         if (isPaused) {
58                             synchronized (grabberThread) {
59                                 wait();
60                             }
61                         }
62                         if (frameConsumer != null) frame.ifPresent(frameConsumer);
63                         frame.ifPresent(VideoMode.this::onVideoFrame);
64 //                        timeIt("frame", grabber::grabFrame);
65                     }
66                 } catch (IOException | InterruptedException e) {
67                     e.printStackTrace();
68                 }
69             }
70         };
71         grabberThread.start();
72     }
73
74     public void onVideoFrame(Consumer<VideoFrame> consumer) {
75         frameConsumer = consumer;
76     }
77
78     private void onVideoFrame(VideoFrame frame) {
79         updateWithFrame(frame.getLedFrame());
80     }
81
82     public void onVideoDeviceChange(Optional<File> videoDevice) {
83         // Should only happen when this mode is active!
84         if (grabberThread != null) {
85             grabberThread.interrupt();
86         }
87         videoDevice.ifPresent(this::startGrabberThread);
88     }
89 }