use serde::{Deserialize, Serialize}; use crate::state::{ColorScheme, MainLayout}; #[cfg(feature = "cli")] const APP_NAME: &str = "cagire"; #[derive(Debug, Default, Serialize, Deserialize)] pub struct MidiSettings { #[serde(default)] pub output_devices: Vec, #[serde(default)] pub input_devices: Vec, } #[derive(Debug, Default, Serialize, Deserialize)] pub struct Settings { pub audio: AudioSettings, pub display: DisplaySettings, pub link: LinkSettings, #[serde(default)] pub midi: MidiSettings, } #[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, } fn default_max_voices() -> usize { 32 } #[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_lissajous: bool, #[serde(default = "default_true")] pub show_preview: bool, #[serde(default = "default_true")] pub show_completion: bool, #[serde(default = "default_font")] pub font: String, #[serde(default = "default_zoom")] pub zoom_factor: f32, #[serde(default)] pub color_scheme: ColorScheme, #[serde(default)] pub layout: MainLayout, #[serde(default)] pub performance_mode: bool, #[serde(default)] pub hue_rotation: f32, #[serde(default)] pub onboarding_dismissed: Vec, #[serde(default = "default_true")] pub load_demo_on_startup: bool, #[serde(default)] pub demo_index: usize, } fn default_font() -> String { "8x13".to_string() } fn default_zoom() -> f32 { 1.5 } #[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, } } } 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_lissajous: true, show_preview: true, show_completion: true, font: default_font(), zoom_factor: default_zoom(), performance_mode: false, color_scheme: ColorScheme::default(), layout: MainLayout::default(), hue_rotation: 0.0, onboarding_dismissed: Vec::new(), load_demo_on_startup: true, demo_index: 0, } } } impl Default for LinkSettings { fn default() -> Self { Self { enabled: true, tempo: 120.0, quantum: 4.0, } } } impl Settings { #[cfg(feature = "cli")] pub fn load() -> Self { let mut settings: Self = confy::load(APP_NAME, None).unwrap_or_default(); if settings.audio.channels == 0 { settings.audio.channels = AudioSettings::default().channels; } if settings.audio.buffer_size == 0 { settings.audio.buffer_size = AudioSettings::default().buffer_size; } settings } #[cfg(not(feature = "cli"))] pub fn load() -> Self { Self::default() } #[cfg(feature = "cli")] pub fn save(&self) { if let Err(e) = confy::store(APP_NAME, None, self) { eprintln!("Failed to save settings: {e}"); } } #[cfg(not(feature = "cli"))] pub fn save(&self) {} }