cog_task/server/task/
config.rs

1use crate::resource::{
2    AudioBackend, Color, Interpreter, LogFormat, StreamBackend, TimePrecision, UseTrigger, Volume,
3};
4use eyre::{eyre, Result};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Default, Clone, Deserialize, Serialize)]
8#[serde(deny_unknown_fields)]
9pub struct Config {
10    #[serde(default = "defaults::use_trigger")]
11    use_trigger: UseTrigger,
12    #[serde(default = "defaults::verify_sha2")]
13    #[serde(skip_serializing)]
14    verify_sha2: Option<String>,
15    #[serde(default = "defaults::blocks_per_row")]
16    blocks_per_row: i32,
17    #[serde(default = "defaults::volume")]
18    volume: Volume,
19    #[serde(default = "defaults::log_format")]
20    log_format: LogFormat,
21    #[serde(default = "defaults::time_precision")]
22    time_precision: TimePrecision,
23    #[serde(default = "defaults::interpreter")]
24    interpreter: Interpreter,
25    #[serde(default = "defaults::audio_backend")]
26    audio_backend: AudioBackend,
27    #[serde(default = "defaults::stream_backend")]
28    stream_backend: StreamBackend,
29    #[serde(default = "defaults::background")]
30    background: Color,
31}
32
33mod defaults {
34    use crate::resource::{
35        AudioBackend, Color, Interpreter, LogFormat, StreamBackend, TimePrecision, UseTrigger,
36        Volume,
37    };
38    use cfg_if::cfg_if;
39
40    #[inline(always)]
41    pub fn use_trigger() -> UseTrigger {
42        UseTrigger::Yes
43    }
44
45    #[inline(always)]
46    pub fn verify_sha2() -> Option<String> {
47        None
48    }
49
50    #[inline(always)]
51    pub fn blocks_per_row() -> i32 {
52        3
53    }
54
55    #[inline(always)]
56    pub fn volume() -> Volume {
57        Volume::Value(1.0)
58    }
59
60    #[inline(always)]
61    pub fn log_format() -> LogFormat {
62        LogFormat::RON
63    }
64
65    #[inline(always)]
66    pub fn time_precision() -> TimePrecision {
67        TimePrecision::RespectBoundaries
68    }
69
70    #[inline(always)]
71    pub fn interpreter() -> Interpreter {
72        Interpreter::Fasteval
73    }
74
75    #[inline(always)]
76    pub fn audio_backend() -> AudioBackend {
77        cfg_if! {
78            if #[cfg(feature = "rodio")] {
79                AudioBackend::Rodio
80            } else {
81                AudioBackend::None
82            }
83        }
84    }
85
86    #[inline(always)]
87    pub fn stream_backend() -> StreamBackend {
88        cfg_if! {
89            if #[cfg(feature = "gstreamer")] {
90                StreamBackend::Gst
91            } else if #[cfg(feature = "ffmpeg")] {
92                StreamBackend::Ffmpeg
93            } else {
94                StreamBackend::None
95            }
96        }
97    }
98
99    #[inline(always)]
100    pub fn background() -> Color {
101        Color::Transparent
102    }
103}
104
105impl Config {
106    pub fn init(&mut self) -> Result<()> {
107        self.volume = self.volume.or(&defaults::volume());
108        self.use_trigger = self.use_trigger.or(&defaults::use_trigger());
109        self.time_precision = self.time_precision.or(&defaults::time_precision());
110        self.log_format = self.log_format.or(&defaults::log_format());
111        self.interpreter = self.interpreter.or(&defaults::interpreter());
112        self.audio_backend = self.audio_backend.or(&defaults::audio_backend());
113        self.stream_backend = self.stream_backend.or(&defaults::stream_backend());
114        self.background = self.background.or(&defaults::background());
115        Ok(())
116    }
117
118    #[inline(always)]
119    pub fn volume(&self) -> Volume {
120        self.volume
121    }
122
123    #[inline(always)]
124    pub fn use_trigger(&self) -> UseTrigger {
125        self.use_trigger
126    }
127
128    pub fn verify_checksum(&self, task: String) -> Result<()> {
129        if let Some(checksum) = self.verify_sha2.as_ref() {
130            if checksum != &task {
131                return Err(eyre!(
132                    "Checksum of this task does not match the one on file.\n\
133                    Current: {task}\n\
134                    On file: {checksum}"
135                ));
136            }
137        }
138        Ok(())
139    }
140
141    #[inline(always)]
142    pub fn blocks_per_row(&self) -> i32 {
143        self.blocks_per_row
144    }
145
146    #[inline(always)]
147    pub fn log_format(&self) -> LogFormat {
148        self.log_format
149    }
150
151    #[inline(always)]
152    pub fn time_precision(&self) -> TimePrecision {
153        self.time_precision
154    }
155
156    #[inline(always)]
157    pub fn interpreter(&self) -> Interpreter {
158        self.interpreter
159    }
160
161    #[inline(always)]
162    pub fn audio_backend(&self) -> AudioBackend {
163        self.audio_backend
164    }
165
166    #[inline(always)]
167    pub fn stream_backend(&self) -> StreamBackend {
168        self.stream_backend
169    }
170
171    #[inline(always)]
172    pub fn background(&self) -> Color {
173        self.background
174    }
175}
176
177#[derive(Debug, Default, Clone, Copy, Deserialize, Serialize)]
178#[serde(deny_unknown_fields)]
179pub struct OptionalConfig {
180    #[serde(default)]
181    volume: Volume,
182    #[serde(default)]
183    use_trigger: UseTrigger,
184    #[serde(default)]
185    log_format: LogFormat,
186    #[serde(default)]
187    time_precision: TimePrecision,
188    #[serde(default)]
189    interpreter: Interpreter,
190    #[serde(default)]
191    audio_backend: AudioBackend,
192    #[serde(default)]
193    stream_backend: StreamBackend,
194    #[serde(default)]
195    background: Color,
196}
197
198impl OptionalConfig {
199    pub fn fill_blanks(&self, base_config: &Config) -> Config {
200        let mut config = base_config.clone();
201        config.volume = self.volume.or(&base_config.volume);
202        config.use_trigger = self.use_trigger.or(&base_config.use_trigger);
203        config.time_precision = self.time_precision.or(&config.time_precision);
204        config.log_format = self.log_format.or(&base_config.log_format);
205        config.interpreter = self.interpreter.or(&config.interpreter);
206        config.audio_backend = self.audio_backend.or(&config.audio_backend);
207        config.stream_backend = self.stream_backend.or(&config.stream_backend);
208        config.background = self.background.or(&config.background);
209        config
210    }
211}