use serde::{Deserialize, Serialize}; use crate::state::ColorScheme; const APP_NAME: &str = "cagire"; #[derive(Debug, Default, Serialize, Deserialize)] pub struct Settings { pub audio: AudioSettings, pub display: DisplaySettings, pub link: LinkSettings, } #[derive(Debug, Serialize, Deserialize)] pub struct AudioSettings { pub output_device: Option, pub input_device: Option, pub channels: u16, pub buffer_size: u32, #[serde(default = "default_max_voices")] pub max_voices: usize, #[serde(default = "default_lookahead_ms")] pub lookahead_ms: u32, } fn default_max_voices() -> usize { 32 } fn default_lookahead_ms() -> u32 { 15 } #[derive(Debug, Serialize, Deserialize)] pub struct DisplaySettings { pub fps: u32, pub runtime_highlight: bool, pub show_scope: bool, pub show_spectrum: bool, #[serde(default = "default_true")] pub show_completion: bool, #[serde(default = "default_flash_brightness")] pub flash_brightness: f32, #[serde(default = "default_font")] pub font: String, #[serde(default)] pub color_scheme: ColorScheme, } fn default_font() -> String { "8x13".to_string() } fn default_flash_brightness() -> f32 { 1.0 } #[derive(Debug, Serialize, Deserialize)] pub struct LinkSettings { pub enabled: bool, pub tempo: f64, pub quantum: f64, } impl Default for AudioSettings { fn default() -> Self { Self { output_device: None, input_device: None, channels: 2, buffer_size: 512, max_voices: 32, lookahead_ms: 15, } } } fn default_true() -> bool { true } impl Default for DisplaySettings { fn default() -> Self { Self { fps: 60, runtime_highlight: false, show_scope: true, show_spectrum: true, show_completion: true, flash_brightness: 1.0, font: default_font(), color_scheme: ColorScheme::default(), } } } impl Default for LinkSettings { fn default() -> Self { Self { enabled: true, tempo: 120.0, quantum: 4.0, } } } impl Settings { pub fn load() -> Self { confy::load(APP_NAME, None).unwrap_or_default() } pub fn save(&self) { if let Err(e) = confy::store(APP_NAME, None, self) { eprintln!("Failed to save settings: {e}"); } } }