deckster/src/model/config.rs
2024-02-05 00:13:03 +01:00

135 lines
3.8 KiB
Rust

use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
use color_eyre::{eyre::eyre, Result};
use enum_map::EnumMap;
use rgb::RGB8;
use serde::{Deserialize, Serialize};
use deckster_shared::image_filter::ImageFilter;
use deckster_shared::rgb::RGB8Wrapper;
use crate::model;
use crate::model::position::ButtonPosition;
#[derive(Debug, Deserialize)]
pub struct File {
#[serde(default = "active_button_color_default")]
pub active_button_color: RGB8Wrapper,
#[serde(default = "inactive_button_color_default")]
pub inactive_button_color: RGB8Wrapper,
pub label_font_family: Option<String>,
pub icon_packs: Arc<HashMap<String, IconPack>>,
pub buttons: HashMap<ButtonPosition, ButtonConfig>, // EnumMap
pub initial: InitialConfig,
pub mqtt: Option<MqttConfig>,
}
#[derive(Debug)]
pub struct WithFallbackId<T> {
pub fallback_id: String,
pub inner: T,
}
#[derive(Debug)]
pub struct Config {
pub active_button_color: RGB8Wrapper,
pub inactive_button_color: RGB8Wrapper,
pub label_font_family: Option<String>,
pub key_pages_by_id: HashMap<String, model::key_page::Page>,
pub knob_pages_by_id: HashMap<String, model::knob_page::Page>,
pub icon_packs: Arc<HashMap<String, IconPack>>,
pub buttons: EnumMap<ButtonPosition, ButtonConfig>,
pub initial: InitialConfig,
pub mqtt: Option<MqttConfig>,
}
fn inactive_button_color_default() -> RGB8Wrapper {
RGB8::new(128, 128, 128).into()
}
fn active_button_color_default() -> RGB8Wrapper {
RGB8::new(0, 255, 0).into()
}
#[derive(Debug, Deserialize, Default)]
pub struct ButtonConfig {
pub key_page: Option<String>,
pub knob_page: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct InitialConfig {
pub key_page: String,
pub knob_page: String,
}
#[derive(Debug, Deserialize)]
pub struct MqttConfig {
pub client_id: String,
pub host: String,
pub port: u16,
pub credentials: Option<MqttConfigCredentials>,
pub topic_prefix: String,
}
#[derive(Debug, Deserialize)]
pub struct MqttConfigCredentials {
pub username: String,
pub password: String,
}
#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum IconFormat {
Png,
Svg,
}
#[derive(Debug, Deserialize)]
pub struct IconPack {
pub path: PathBuf,
pub format: IconFormat,
pub global_filter: Option<ImageFilter>,
}
impl Config {
pub fn validate(self) -> Result<Self> {
if !self.key_pages_by_id.contains_key(&self.initial.key_page) {
return Err(eyre!(format!(
"There is no key page with the ID specified at initial.key_page: {}",
&self.initial.key_page
)));
}
if !self.knob_pages_by_id.contains_key(&self.initial.knob_page) {
return Err(eyre!(format!(
"There is no knob page with the ID specified at initial.knob_page: {}",
&self.initial.knob_page
)));
}
for (position, button) in &self.buttons {
if let Some(key_page) = &button.key_page {
if !self.key_pages_by_id.contains_key(key_page) {
return Err(eyre!(format!(
"There is no key page with the ID specified at buttons.{}.key_page: {}",
position, &self.initial.key_page
)));
}
}
if let Some(knob_page) = &button.knob_page {
if !self.knob_pages_by_id.contains_key(knob_page) {
return Err(eyre!(format!(
"There is no knob page with the ID specified at buttons.{}.knob_page: {}",
position, &self.initial.knob_page
)));
}
}
}
Ok(self)
}
}