Add very special handling for the MJPG video format
[kaka/cakelight.git] / src / kaka / cakelight / Configuration.java
1 package kaka.cakelight;
2
3 import org.opencv.imgproc.Imgproc;
4
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.util.*;
9 import java.util.stream.Collectors;
10
11 public class Configuration {
12     private List<Map.Entry<String, String>> settings = new ArrayList<>();
13     public VideoConfiguration video;
14     public LedConfiguration leds;
15     public double gamma;
16
17     private Configuration(Properties prop) {
18         video = new VideoConfiguration(prop);
19         leds = new LedConfiguration(prop);
20         gamma = Double.parseDouble(get(prop,"gamma", "1"));
21     }
22
23     public static Configuration from(String propertiesFile) {
24         Properties prop = new Properties();
25         try (InputStream input = new FileInputStream(propertiesFile)) {
26             prop.load(input);
27         } catch (IOException ex) {
28             ex.printStackTrace();
29         }
30         return new Configuration(prop);
31     }
32
33     private String get(Properties prop, String name) {
34         return addSetting(name, prop.getProperty(name));
35     }
36
37     private String get(Properties prop, String name, String dflt) {
38         return addSetting(name, prop.getProperty(name, dflt));
39     }
40
41     private String addSetting(String name, String value) {
42         settings.add(new AbstractMap.SimpleEntry<>(name, value));
43         return value;
44     }
45
46     @Override
47     public String toString() {
48         return settings.stream().map(entry -> entry.getKey() + "=" + entry.getValue()).collect(Collectors.joining("\n"));
49     }
50
51     public class VideoConfiguration {
52         public int width;
53         public int height;
54         public int bpp;
55         public int format;
56         public boolean mjpg;
57         public double saturation;
58         public String device;
59         public boolean deviceIsAutomatic;
60         public CropConfiguration crop;
61         public ListConfiguration list;
62
63         private VideoConfiguration(Properties prop) {
64             width = Integer.parseInt(get(prop, "video.width", "720"));
65             height = Integer.parseInt(get(prop, "video.height", "576"));
66             bpp = Integer.parseInt(get(prop, "video.bpp", "2"));
67             device = get(prop, "video.device", "auto");
68             deviceIsAutomatic = "auto".equals(device);
69             switch (get(prop, "video.format", "").toUpperCase()) {
70                 case "YUYV":
71                     format = Imgproc.COLOR_YUV2BGR_YUYV;
72                     break;
73                 case "YVYU":
74                     format = Imgproc.COLOR_YUV2BGR_YVYU;
75                     break;
76                 case "MJPG":
77                     format = 0;
78                     mjpg = true;
79                 default:
80                     format = Imgproc.COLOR_YUV2BGR_UYVY;
81             }
82             saturation = inRange(Double.parseDouble(get(prop, "video.saturation", "0.5")), 0, 1);
83             crop = new CropConfiguration(prop);
84             list = new ListConfiguration(prop);
85         }
86
87         public class CropConfiguration {
88             public int left, right, top, bottom;
89
90             private CropConfiguration(Properties prop) {
91                 left = Integer.parseInt(get(prop, "video.crop.left", "0"));
92                 right = Integer.parseInt(get(prop, "video.crop.right", "0"));
93                 top = Integer.parseInt(get(prop, "video.crop.top", "0"));
94                 bottom = Integer.parseInt(get(prop, "video.crop.bottom", "0"));
95             }
96         }
97
98         public class ListConfiguration {
99             public boolean top, bottom, left, right;
100
101             private ListConfiguration(Properties prop) {
102                 top = get(prop, "video.list.top", "on").equals("on");
103                 bottom = get(prop, "video.list.bottom", "on").equals("on");
104                 left = get(prop, "video.list.left", "on").equals("on");
105                 right = get(prop, "video.list.right", "on").equals("on");
106             }
107         }
108     }
109
110     public class LedConfiguration {
111         public int cols;
112         public int rows;
113         public int brightness;
114         public LedType type;
115
116         private LedConfiguration(Properties prop) {
117             cols = Integer.parseInt(get(prop, "leds.cols"));
118             rows = Integer.parseInt(get(prop, "leds.rows"));
119             brightness = (int) inRange(Integer.parseInt(get(prop, "leds.brightness", "31")), 1, 31);
120             switch (get(prop, "leds.type", "").toUpperCase()) {
121                 case "WS2801":
122                     type = LedType.WS2801;
123                     break;
124                 case "APA102":
125                 default:
126                     type = LedType.APA102;
127             }
128         }
129
130         public int getCount() {
131             return cols * 2 + rows * 2;
132         }
133     }
134
135     public enum LedType {
136         WS2801, APA102
137     }
138
139     private double inRange(double value, double lower, double upper) {
140         return value < lower ? lower
141                 : value > upper ? upper
142                 : value;
143     }
144 }