Add video device to config
[kaka/cakelight.git] / src / kaka / cakelight / mode / VideoMode.java
CommitLineData
67b0a758
TW
1package kaka.cakelight.mode;
2
3import kaka.cakelight.Configuration;
4import kaka.cakelight.FrameGrabber;
5import kaka.cakelight.VideoDeviceListener;
6import kaka.cakelight.VideoFrame;
4a2d6056 7
03670958 8import java.io.File;
4a2d6056
TW
9import java.io.IOException;
10import java.util.Optional;
100b82fe 11import java.util.function.Consumer;
4a2d6056 12
d182b8cc 13public class VideoMode extends Mode {
4a2d6056 14 private Configuration config;
8418fbda 15 private Thread grabberThread;
adc29b9a 16 private Consumer<VideoFrame> frameConsumer;
03670958 17 private VideoDeviceListener deviceListener;
fa9808cd 18 private boolean isPaused = false;
03670958
TW
19
20 public VideoMode() {
21 deviceListener = new VideoDeviceListener();
d182b8cc 22 deviceListener.onVideoDeviceChange(this::onVideoDeviceChange);
03670958 23 }
4a2d6056
TW
24
25 @Override
26 public void enter(Configuration config) {
27 this.config = config;
7434e71c
TW
28 if (config.video.deviceIsAutomatic) {
29 deviceListener.startListening();
30 } else {
31 File videoDevice = new File(config.video.device);
32 startGrabberThread(videoDevice);
33 }
4a2d6056
TW
34 }
35
36 @Override
d0afa6fb 37 public void pause() {
fa9808cd 38 isPaused = true;
d0afa6fb
TW
39 }
40
41 @Override
42 public void resume() {
fa9808cd 43 isPaused = false;
4c688086
TW
44 synchronized (grabberThread) {
45 grabberThread.notify();
46 }
d0afa6fb
TW
47 }
48
49 @Override
4a2d6056 50 public void exit() {
8418fbda 51 grabberThread.interrupt();
7434e71c
TW
52 if (config.video.deviceIsAutomatic) {
53 deviceListener.stopListening();
54 }
4a2d6056
TW
55 }
56
03670958 57 private void startGrabberThread(File videoDevice) {
100b82fe 58 assert frameConsumer != null;
8418fbda 59 grabberThread = new Thread() {
4a2d6056 60 public void run() {
03670958 61 try (FrameGrabber grabber = FrameGrabber.from(videoDevice, config)) {
4a2d6056 62 while (!isInterrupted()) {
adc29b9a 63 Optional<VideoFrame> frame = grabber.grabFrame();
fa9808cd 64 if (isPaused) {
4c688086
TW
65 synchronized (grabberThread) {
66 wait();
67 }
fa9808cd 68 }
03b67a73 69 if (frameConsumer != null) frame.ifPresent(frameConsumer);
adc29b9a 70 frame.ifPresent(VideoMode.this::onVideoFrame);
100b82fe 71// timeIt("frame", grabber::grabFrame);
4a2d6056 72 }
fa9808cd 73 } catch (IOException | InterruptedException e) {
4a2d6056
TW
74 e.printStackTrace();
75 }
76 }
77 };
8418fbda 78 grabberThread.start();
4a2d6056 79 }
100b82fe 80
adc29b9a 81 public void onVideoFrame(Consumer<VideoFrame> consumer) {
100b82fe
TW
82 frameConsumer = consumer;
83 }
03670958 84
adc29b9a 85 private void onVideoFrame(VideoFrame frame) {
6b569670 86 updateWithFrame(frame.getLedFrame());
03b67a73
TW
87 }
88
d182b8cc 89 public void onVideoDeviceChange(Optional<File> videoDevice) {
03670958 90 // Should only happen when this mode is active!
8418fbda
TW
91 if (grabberThread != null) {
92 grabberThread.interrupt();
03670958
TW
93 }
94 videoDevice.ifPresent(this::startGrabberThread);
95 }
4a2d6056 96}