From 7658cf9d511ac00a155e12b3bd437452062f3d04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Forment?= Date: Fri, 30 Jan 2026 20:27:08 +0100 Subject: [PATCH] Feat: add icon and reorganize desktop.rs --- Cargo.toml | 2 ++ README.md | 4 +++ cagire_pixel.png | Bin 0 -> 26749 bytes src/bin/desktop.rs | 74 ++++++++++------------------------------ src/engine/sequencer.rs | 6 ++-- src/settings.rs | 4 ++- 6 files changed, 31 insertions(+), 59 deletions(-) create mode 100644 cagire_pixel.png diff --git a/Cargo.toml b/Cargo.toml index 7cb086a..e407675 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ desktop = [ "eframe", "egui_ratatui", "soft_ratatui", + "image", ] [dependencies] @@ -56,6 +57,7 @@ egui = { version = "0.33", optional = true } eframe = { version = "0.33", optional = true } egui_ratatui = { version = "2.1", optional = true } soft_ratatui = { version = "0.1.3", features = ["unicodefonts"], optional = true } +image = { version = "0.25", default-features = false, features = ["png"], optional = true } [profile.release] opt-level = 3 diff --git a/README.md b/README.md index a7d9485..a3e4c1d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +

+ Cagire +

+ # Cagire A Forth Music Sequencer. diff --git a/cagire_pixel.png b/cagire_pixel.png new file mode 100644 index 0000000000000000000000000000000000000000..f7a4b2381694f8bcf68f3d7227f1b3cd4c9788c3 GIT binary patch literal 26749 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, _analysis_handle: Option, current_font: FontChoice, - pending_font: Option, } impl CagireDesktop { @@ -270,7 +269,6 @@ impl CagireDesktop { _stream: stream, _analysis_handle: analysis_handle, current_font, - pending_font: None, } } @@ -302,7 +300,7 @@ impl CagireDesktop { } self.app.audio.config.sample_count = restart_samples.len(); - self.audio_sample_pos.store(0, Ordering::Relaxed); + self.audio_sample_pos.store(0, Ordering::Release); match build_stream( &new_config, @@ -372,14 +370,6 @@ impl CagireDesktop { impl eframe::App for CagireDesktop { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - if let Some(font) = self.pending_font.take() { - self.terminal = create_terminal(font); - self.current_font = font; - let mut settings = Settings::load(); - settings.display.font = font.to_setting().to_string(); - settings.save(); - } - self.handle_audio_restart(); self.update_metrics(); @@ -412,7 +402,7 @@ impl eframe::App for CagireDesktop { } let current_font = self.current_font; - let mut pending_font = None; + let mut new_font = None; egui::CentralPanel::default() .frame(egui::Frame::NONE.fill(egui::Color32::BLACK)) @@ -429,7 +419,6 @@ impl eframe::App for CagireDesktop { ui.add(self.terminal.backend_mut()); - // Create a click-sensing overlay for context menu let response = ui.interact( ui.max_rect(), egui::Id::new("terminal_context"), @@ -440,7 +429,7 @@ impl eframe::App for CagireDesktop { for choice in FontChoice::ALL { let selected = current_font == choice; if ui.selectable_label(selected, choice.label()).clicked() { - pending_font = Some(choice); + new_font = Some(choice); ui.close(); } } @@ -448,8 +437,12 @@ impl eframe::App for CagireDesktop { }); }); - if pending_font.is_some() { - self.pending_font = pending_font; + if let Some(font) = new_font { + self.terminal = create_terminal(font); + self.current_font = font; + let mut settings = Settings::load(); + settings.display.font = font.to_setting().to_string(); + settings.save(); } ctx.request_repaint_after(Duration::from_millis( @@ -465,50 +458,19 @@ impl eframe::App for CagireDesktop { } fn load_icon() -> egui::IconData { - let size = 64u32; - let mut rgba = vec![0u8; (size * size * 4) as usize]; + const ICON_BYTES: &[u8] = include_bytes!("../../cagire_pixel.png"); - for y in 0..size { - for x in 0..size { - let idx = ((y * size + x) * 4) as usize; - let cx = x as f32 - size as f32 / 2.0; - let cy = y as f32 - size as f32 / 2.0; - let dist = (cx * cx + cy * cy).sqrt(); - let radius = size as f32 / 2.0 - 2.0; + let img = image::load_from_memory(ICON_BYTES) + .expect("Failed to load embedded icon") + .resize(64, 64, image::imageops::FilterType::Lanczos3) + .into_rgba8(); - if dist < radius { - let angle = cy.atan2(cx); - let normalized = (angle + std::f32::consts::PI) / (2.0 * std::f32::consts::PI); - - if normalized > 0.1 && normalized < 0.9 { - let inner_radius = radius * 0.5; - if dist > inner_radius { - rgba[idx] = 80; - rgba[idx + 1] = 160; - rgba[idx + 2] = 200; - rgba[idx + 3] = 255; - } else { - rgba[idx] = 30; - rgba[idx + 1] = 60; - rgba[idx + 2] = 80; - rgba[idx + 3] = 255; - } - } else { - rgba[idx] = 30; - rgba[idx + 1] = 30; - rgba[idx + 2] = 40; - rgba[idx + 3] = 255; - } - } else { - rgba[idx + 3] = 0; - } - } - } + let (width, height) = img.dimensions(); egui::IconData { - rgba, - width: size, - height: size, + rgba: img.into_raw(), + width, + height, } } diff --git a/src/engine/sequencer.rs b/src/engine/sequencer.rs index e3eb134..35be218 100644 --- a/src/engine/sequencer.rs +++ b/src/engine/sequencer.rs @@ -165,7 +165,9 @@ impl SequencerHandle { pub fn shutdown(self) { let _ = self.cmd_tx.send(SeqCommand::Shutdown); - let _ = self.thread.join(); + if let Err(e) = self.thread.join() { + eprintln!("Sequencer thread panicked: {e:?}"); + } } } @@ -873,7 +875,7 @@ fn sequencer_loop( let tempo = state.tempo(); let sr = sample_rate.load(Ordering::Relaxed) as f64; - let audio_samples = audio_sample_pos.load(Ordering::Relaxed); + let audio_samples = audio_sample_pos.load(Ordering::Acquire); let engine_time = if sr > 0.0 { audio_samples as f64 / sr } else { diff --git a/src/settings.rs b/src/settings.rs index 425bce4..f8daa38 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -101,7 +101,9 @@ impl Settings { } pub fn save(&self) { - let _ = confy::store(APP_NAME, None, self); + if let Err(e) = confy::store(APP_NAME, None, self) { + eprintln!("Failed to save settings: {e}"); + } } }