Synchronize on threads on wait/notify
[kaka/cakelight.git] / src / kaka / cakelight / mode / VideoMode.java
... / ...
CommitLineData
1package kaka.cakelight.mode;
2
3import kaka.cakelight.Configuration;
4import kaka.cakelight.FrameGrabber;
5import kaka.cakelight.VideoDeviceListener;
6import kaka.cakelight.VideoFrame;
7
8import java.io.File;
9import java.io.IOException;
10import java.util.Optional;
11import java.util.function.Consumer;
12
13public 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}