1use std::num::NonZeroUsize;
2
3use serde_derive::{Deserialize, Serialize};
4use validator::Validate;
5
6use super::ServerConfig;
7
8#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
9#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
10pub struct FlatbuffersServer {
11 pub enable: bool,
12 #[validate(range(min = 1024))]
13 pub port: u16,
14 #[validate(range(min = 1))]
15 pub timeout: u32,
16}
17
18impl Default for FlatbuffersServer {
19 fn default() -> Self {
20 Self {
21 enable: true,
22 port: 19400,
23 timeout: 5,
24 }
25 }
26}
27
28impl ServerConfig for FlatbuffersServer {
29 fn port(&self) -> u16 {
30 self.port
31 }
32}
33
34#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
35#[serde(default, deny_unknown_fields)]
36pub struct Forwarder {
37 pub enable: bool,
38 pub json: Vec<String>,
39 pub flat: Vec<String>,
40}
41
42impl Default for Forwarder {
43 fn default() -> Self {
44 Self {
45 enable: false,
46 json: vec!["127.0.0.1:19446".to_owned()],
47 flat: vec!["127.0.0.1:19401".to_owned()],
48 }
49 }
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
53#[serde(rename_all = "lowercase", deny_unknown_fields)]
54#[derive(Default)]
55pub enum FramegrabberType {
56 #[default]
57 Auto,
58 AMLogic,
59 DispmanX,
60 DirectX9,
61 Framebuffer,
62 OSX,
63 QT,
64 X11,
65 XCB,
66}
67
68#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
69#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
70pub struct Framegrabber {
71 #[serde(rename = "type")]
72 pub ty: FramegrabberType,
73 #[validate(range(min = 10))]
74 pub width: u32,
75 #[validate(range(min = 10))]
76 pub height: u32,
77 #[serde(rename = "frequency_Hz")]
78 #[validate(range(min = 1))]
79 pub frequency_hz: u32,
80 pub crop_left: u32,
81 pub crop_right: u32,
82 pub crop_top: u32,
83 pub crop_bottom: u32,
84 #[validate(range(min = 1, max = 30))]
85 pub pixel_decimation: u32,
86 #[serde(default)]
87 pub display: u32,
88}
89
90impl Default for Framegrabber {
91 fn default() -> Self {
92 Self {
93 ty: Default::default(),
94 width: 80,
95 height: 45,
96 frequency_hz: 10,
97 crop_left: 0,
98 crop_right: 0,
99 crop_top: 0,
100 crop_bottom: 0,
101 pixel_decimation: 8,
102 display: 0,
103 }
104 }
105}
106
107#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
108pub enum WatchedVersionBranch {
109 Stable,
110 Beta,
111 Alpha,
112}
113
114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
115#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
116pub struct General {
117 #[validate(length(min = 4, max = 20))]
118 pub name: String,
119 pub watched_version_branch: WatchedVersionBranch,
120 pub show_opt_help: bool,
121}
122
123impl Default for General {
124 fn default() -> Self {
125 Self {
126 name: "My Hyperion Config".to_owned(),
127 watched_version_branch: WatchedVersionBranch::Stable,
128 show_opt_help: true,
129 }
130 }
131}
132
133#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
134#[serde(rename_all = "SCREAMING_SNAKE_CASE", deny_unknown_fields)]
135#[derive(Default)]
136pub enum V4L2Standard {
137 #[default]
138 NoChange,
139 Pal,
140 Ntsc,
141 Secam,
142}
143
144#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
145#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
146pub struct GrabberV4L2 {
147 pub device: String,
148 pub input: i32,
149 pub standard: V4L2Standard,
150 pub width: u32,
151 pub height: u32,
152 #[validate(range(min = 1))]
153 pub fps: u32,
154 #[validate(range(min = 1, max = 30))]
155 pub size_decimation: u32,
156 pub crop_left: u32,
157 pub crop_right: u32,
158 pub crop_top: u32,
159 pub crop_bottom: u32,
160 pub cec_detection: bool,
161 pub signal_detection: bool,
162 #[validate(range(min = 0, max = 100))]
163 pub red_signal_threshold: u32,
164 #[validate(range(min = 0, max = 100))]
165 pub green_signal_threshold: u32,
166 #[validate(range(min = 0, max = 100))]
167 pub blue_signal_threshold: u32,
168 #[serde(rename = "sDVOffsetMin")]
169 #[validate(range(min = 0., max = 1.))]
170 pub sdv_offset_min: f32,
171 #[serde(rename = "sDVOffsetMax")]
172 #[validate(range(min = 0., max = 1.))]
173 pub sdv_offset_max: f32,
174 #[serde(rename = "sDHOffsetMin")]
175 #[validate(range(min = 0., max = 1.))]
176 pub sdh_offset_min: f32,
177 #[serde(rename = "sDHOffsetMax")]
178 #[validate(range(min = 0., max = 1.))]
179 pub sdh_offset_max: f32,
180}
181
182impl Default for GrabberV4L2 {
183 fn default() -> Self {
184 Self {
185 device: "auto".to_owned(),
186 input: 0,
187 standard: Default::default(),
188 width: 0,
189 height: 0,
190 fps: 15,
191 size_decimation: 6,
192 crop_left: 0,
193 crop_right: 0,
194 crop_top: 0,
195 crop_bottom: 0,
196 cec_detection: false,
197 signal_detection: false,
198 red_signal_threshold: 5,
199 green_signal_threshold: 5,
200 blue_signal_threshold: 5,
201 sdv_offset_min: 0.25,
202 sdv_offset_max: 0.75,
203 sdh_offset_min: 0.25,
204 sdh_offset_max: 0.75,
205 }
206 }
207}
208
209#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Validate)]
210#[serde(default, deny_unknown_fields)]
211pub struct JsonServer {
212 #[validate(range(min = 1024))]
213 pub port: u16,
214}
215
216impl Default for JsonServer {
217 fn default() -> Self {
218 Self { port: 19444 }
219 }
220}
221
222impl ServerConfig for JsonServer {
223 fn port(&self) -> u16 {
224 self.port
225 }
226}
227
228#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
229#[serde(rename_all = "lowercase", deny_unknown_fields)]
230pub enum LoggerLevel {
231 Silent,
232 Warn,
233 Verbose,
234 Debug,
235}
236
237#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
238#[serde(default, deny_unknown_fields)]
239pub struct Logger {
240 pub level: LoggerLevel,
241}
242
243impl Default for Logger {
244 fn default() -> Self {
245 Self {
246 level: LoggerLevel::Warn,
247 }
248 }
249}
250
251#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
252#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
253pub struct Network {
254 pub api_auth: bool,
255 #[serde(default, rename = "internetAccessAPI")]
256 pub internet_access_api: bool,
257 #[serde(
258 default,
259 rename = "restrictedInternetAccessAPI",
260 alias = "restirctedInternetAccessAPI"
261 )]
262 pub restricted_internet_access_api: bool,
263 pub ip_whitelist: Vec<String>,
264 pub local_api_auth: bool,
265 pub local_admin_auth: bool,
266}
267
268impl Default for Network {
269 fn default() -> Self {
270 Self {
271 api_auth: true,
272 internet_access_api: false,
273 restricted_internet_access_api: false,
274 ip_whitelist: vec![],
275 local_api_auth: false,
276 local_admin_auth: true,
277 }
278 }
279}
280
281#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
282#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
283pub struct ProtoServer {
284 pub enable: bool,
285 #[validate(range(min = 1024))]
286 pub port: u16,
287 #[validate(range(min = 1))]
288 pub timeout: u32,
289}
290
291impl Default for ProtoServer {
292 fn default() -> Self {
293 Self {
294 enable: true,
295 port: 19445,
296 timeout: 5,
297 }
298 }
299}
300
301impl ServerConfig for ProtoServer {
302 fn port(&self) -> u16 {
303 self.port
304 }
305}
306
307#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
308#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
309pub struct WebConfig {
310 #[serde(rename = "document_root")]
311 pub document_root: String,
312 #[validate(range(min = 80))]
313 pub port: u16,
314 #[validate(range(min = 80))]
315 pub ssl_port: u16,
316 pub crt_path: String,
317 pub key_path: String,
318 pub key_pass_phrase: String,
319 pub max_sessions: NonZeroUsize,
320}
321
322impl WebConfig {
323 pub const SYSTEM_DOCUMENT_ROOT: &'static str = "$ROOT/webconfig";
324}
325
326impl Default for WebConfig {
327 fn default() -> Self {
328 Self {
329 document_root: String::new(),
330 port: 8090,
331 ssl_port: 8092,
332 crt_path: String::new(),
333 key_path: String::new(),
334 key_pass_phrase: String::new(),
335 max_sessions: NonZeroUsize::new(4).unwrap(),
336 }
337 }
338}
339
340#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
341#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
342pub struct Hooks {
343 pub instance_start: Vec<String>,
346 pub instance_stop: Vec<String>,
349 pub instance_activate: Vec<String>,
352 pub instance_deactivate: Vec<String>,
355 pub start: Vec<String>,
357 pub stop: Vec<String>,
359}
360
361#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize, Validate)]
362#[serde(default, rename_all = "camelCase", deny_unknown_fields)]
363pub struct GlobalConfig {
364 pub flatbuffers_server: FlatbuffersServer,
365 pub forwarder: Forwarder,
366 pub framegrabber: Framegrabber,
367 pub general: General,
368 #[serde(rename = "grabberV4L2")]
369 pub grabber_v4l2: GrabberV4L2,
370 pub json_server: JsonServer,
371 pub logger: Logger,
372 pub network: Network,
373 pub proto_server: ProtoServer,
374 pub web_config: WebConfig,
375 pub hooks: Hooks,
376}