broken
This commit is contained in:
@@ -33,3 +33,10 @@ minimad = "0.13"
|
|||||||
crossbeam-channel = "0.5"
|
crossbeam-channel = "0.5"
|
||||||
confy = "2"
|
confy = "2"
|
||||||
rustfft = "6"
|
rustfft = "6"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
opt-level = 3
|
||||||
|
lto = "fat"
|
||||||
|
codegen-units = 1
|
||||||
|
panic = "abort"
|
||||||
|
strip = true
|
||||||
|
|||||||
31
src/app.rs
31
src/app.rs
@@ -5,7 +5,6 @@ use std::path::PathBuf;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use ratatui::style::Color;
|
|
||||||
|
|
||||||
use crate::commands::AppCommand;
|
use crate::commands::AppCommand;
|
||||||
use crate::engine::{
|
use crate::engine::{
|
||||||
@@ -16,8 +15,8 @@ use crate::page::Page;
|
|||||||
use crate::services::pattern_editor;
|
use crate::services::pattern_editor;
|
||||||
use crate::settings::Settings;
|
use crate::settings::Settings;
|
||||||
use crate::state::{
|
use crate::state::{
|
||||||
AudioSettings, EditorContext, Focus, LiveKeyState, Metrics, Modal, PanelState, PatternField,
|
AudioSettings, EditorContext, FlashKind, Focus, LiveKeyState, Metrics, Modal, PanelState,
|
||||||
PatternsNav, PlaybackState, ProjectState, UiState,
|
PatternField, PatternsNav, PlaybackState, ProjectState, UiState,
|
||||||
};
|
};
|
||||||
use crate::views::{dict_view, help_view};
|
use crate::views::{dict_view, help_view};
|
||||||
|
|
||||||
@@ -320,7 +319,7 @@ impl App {
|
|||||||
Some(cmds.join("\n"))
|
Some(cmds.join("\n"))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.ui.flash("Script compiled", 150, Color::White);
|
self.ui.flash("Script compiled", 150, FlashKind::Info);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if let Some(step) = self
|
if let Some(step) = self
|
||||||
@@ -331,7 +330,7 @@ impl App {
|
|||||||
{
|
{
|
||||||
step.command = None;
|
step.command = None;
|
||||||
}
|
}
|
||||||
self.ui.flash(&format!("Script error: {e}"), 300, Color::Red);
|
self.ui.flash(&format!("Script error: {e}"), 300, FlashKind::Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -540,7 +539,7 @@ impl App {
|
|||||||
{
|
{
|
||||||
self.load_step_to_editor();
|
self.load_step_to_editor();
|
||||||
}
|
}
|
||||||
self.ui.flash("Step deleted", 150, Color::Green);
|
self.ui.flash("Step deleted", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_pattern(&mut self, bank: usize, pattern: usize) {
|
pub fn reset_pattern(&mut self, bank: usize, pattern: usize) {
|
||||||
@@ -549,7 +548,7 @@ impl App {
|
|||||||
if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern {
|
if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern {
|
||||||
self.load_step_to_editor();
|
self.load_step_to_editor();
|
||||||
}
|
}
|
||||||
self.ui.flash("Pattern reset", 150, Color::Green);
|
self.ui.flash("Pattern reset", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset_bank(&mut self, bank: usize) {
|
pub fn reset_bank(&mut self, bank: usize) {
|
||||||
@@ -560,13 +559,13 @@ impl App {
|
|||||||
if self.editor_ctx.bank == bank {
|
if self.editor_ctx.bank == bank {
|
||||||
self.load_step_to_editor();
|
self.load_step_to_editor();
|
||||||
}
|
}
|
||||||
self.ui.flash("Bank reset", 150, Color::Green);
|
self.ui.flash("Bank reset", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_pattern(&mut self, bank: usize, pattern: usize) {
|
pub fn copy_pattern(&mut self, bank: usize, pattern: usize) {
|
||||||
let pat = self.project_state.project.banks[bank].patterns[pattern].clone();
|
let pat = self.project_state.project.banks[bank].patterns[pattern].clone();
|
||||||
self.copied_pattern = Some(pat);
|
self.copied_pattern = Some(pat);
|
||||||
self.ui.flash("Pattern copied", 150, Color::Green);
|
self.ui.flash("Pattern copied", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paste_pattern(&mut self, bank: usize, pattern: usize) {
|
pub fn paste_pattern(&mut self, bank: usize, pattern: usize) {
|
||||||
@@ -582,14 +581,14 @@ impl App {
|
|||||||
if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern {
|
if self.editor_ctx.bank == bank && self.editor_ctx.pattern == pattern {
|
||||||
self.load_step_to_editor();
|
self.load_step_to_editor();
|
||||||
}
|
}
|
||||||
self.ui.flash("Pattern pasted", 150, Color::Green);
|
self.ui.flash("Pattern pasted", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy_bank(&mut self, bank: usize) {
|
pub fn copy_bank(&mut self, bank: usize) {
|
||||||
let b = self.project_state.project.banks[bank].clone();
|
let b = self.project_state.project.banks[bank].clone();
|
||||||
self.copied_bank = Some(b);
|
self.copied_bank = Some(b);
|
||||||
self.ui.flash("Bank copied", 150, Color::Green);
|
self.ui.flash("Bank copied", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paste_bank(&mut self, bank: usize) {
|
pub fn paste_bank(&mut self, bank: usize) {
|
||||||
@@ -607,7 +606,7 @@ impl App {
|
|||||||
if self.editor_ctx.bank == bank {
|
if self.editor_ctx.bank == bank {
|
||||||
self.load_step_to_editor();
|
self.load_step_to_editor();
|
||||||
}
|
}
|
||||||
self.ui.flash("Bank pasted", 150, Color::Green);
|
self.ui.flash("Bank pasted", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -676,7 +675,7 @@ impl App {
|
|||||||
self.project_state.mark_dirty(bank, pattern);
|
self.project_state.mark_dirty(bank, pattern);
|
||||||
self.load_step_to_editor();
|
self.load_step_to_editor();
|
||||||
self.ui
|
self.ui
|
||||||
.flash(&format!("Linked to step {:02}", copied.step + 1), 150, Color::Green);
|
.flash(&format!("Linked to step {:02}", copied.step + 1), 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn harden_step(&mut self) {
|
pub fn harden_step(&mut self) {
|
||||||
@@ -709,7 +708,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
self.project_state.mark_dirty(bank, pattern);
|
self.project_state.mark_dirty(bank, pattern);
|
||||||
self.load_step_to_editor();
|
self.load_step_to_editor();
|
||||||
self.ui.flash("Step hardened", 150, Color::Green);
|
self.ui.flash("Step hardened", 150, FlashKind::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_pattern_modal(&mut self, field: PatternField) {
|
pub fn open_pattern_modal(&mut self, field: PatternField) {
|
||||||
@@ -842,8 +841,8 @@ impl App {
|
|||||||
AppCommand::Flash {
|
AppCommand::Flash {
|
||||||
message,
|
message,
|
||||||
duration_ms,
|
duration_ms,
|
||||||
color,
|
kind,
|
||||||
} => self.ui.flash(&message, duration_ms, color),
|
} => self.ui.flash(&message, duration_ms, kind),
|
||||||
AppCommand::OpenModal(modal) => {
|
AppCommand::OpenModal(modal) => {
|
||||||
if matches!(modal, Modal::Editor) {
|
if matches!(modal, Modal::Editor) {
|
||||||
// If current step is a shallow copy, navigate to source step
|
// If current step is a shallow copy, navigate to source step
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use ratatui::style::Color;
|
|
||||||
|
|
||||||
use crate::engine::PatternChange;
|
use crate::engine::PatternChange;
|
||||||
use crate::model::PatternSpeed;
|
use crate::model::PatternSpeed;
|
||||||
use crate::state::{Modal, PatternField};
|
use crate::state::{FlashKind, Modal, PatternField};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub enum AppCommand {
|
pub enum AppCommand {
|
||||||
@@ -102,7 +100,7 @@ pub enum AppCommand {
|
|||||||
Flash {
|
Flash {
|
||||||
message: String,
|
message: String,
|
||||||
duration_ms: u64,
|
duration_ms: u64,
|
||||||
color: Color,
|
kind: FlashKind,
|
||||||
},
|
},
|
||||||
OpenModal(Modal),
|
OpenModal(Modal),
|
||||||
CloseModal,
|
CloseModal,
|
||||||
|
|||||||
@@ -193,10 +193,9 @@ pub fn build_stream(
|
|||||||
|
|
||||||
let sr = sample_rate;
|
let sr = sample_rate;
|
||||||
let channels = config.channels as usize;
|
let channels = config.channels as usize;
|
||||||
let max_voices = config.max_voices;
|
|
||||||
let metrics_clone = Arc::clone(&metrics);
|
let metrics_clone = Arc::clone(&metrics);
|
||||||
|
|
||||||
let mut engine = Engine::new_with_metrics(sample_rate, channels, max_voices, Arc::clone(&metrics));
|
let mut engine = Engine::new_with_metrics(sample_rate, channels, Arc::clone(&metrics));
|
||||||
engine.sample_index = initial_samples;
|
engine.sample_index = initial_samples;
|
||||||
|
|
||||||
let mut analyzer = SpectrumAnalyzer::new(sample_rate);
|
let mut analyzer = SpectrumAnalyzer::new(sample_rate);
|
||||||
@@ -225,7 +224,7 @@ pub fn build_stream(
|
|||||||
AudioCommand::ResetEngine => {
|
AudioCommand::ResetEngine => {
|
||||||
let old_samples = std::mem::take(&mut engine.sample_index);
|
let old_samples = std::mem::take(&mut engine.sample_index);
|
||||||
engine =
|
engine =
|
||||||
Engine::new_with_metrics(sr, channels, max_voices, Arc::clone(&metrics_clone));
|
Engine::new_with_metrics(sr, channels, Arc::clone(&metrics_clone));
|
||||||
engine.sample_index = old_samples;
|
engine.sample_index = old_samples;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,4 +19,4 @@ pub use patterns_nav::{PatternsColumn, PatternsNav};
|
|||||||
pub use playback::PlaybackState;
|
pub use playback::PlaybackState;
|
||||||
pub use project::ProjectState;
|
pub use project::ProjectState;
|
||||||
pub use sample_browser::SampleBrowserState;
|
pub use sample_browser::SampleBrowserState;
|
||||||
pub use ui::{DictFocus, UiState};
|
pub use ui::{DictFocus, FlashKind, UiState};
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use ratatui::style::Color;
|
|
||||||
|
|
||||||
use crate::state::Modal;
|
use crate::state::Modal;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||||
|
pub enum FlashKind {
|
||||||
|
#[default]
|
||||||
|
Success,
|
||||||
|
Error,
|
||||||
|
Info,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Sparkle {
|
pub struct Sparkle {
|
||||||
pub x: u16,
|
pub x: u16,
|
||||||
pub y: u16,
|
pub y: u16,
|
||||||
@@ -22,7 +28,7 @@ pub struct UiState {
|
|||||||
pub sparkles: Vec<Sparkle>,
|
pub sparkles: Vec<Sparkle>,
|
||||||
pub status_message: Option<String>,
|
pub status_message: Option<String>,
|
||||||
pub flash_until: Option<Instant>,
|
pub flash_until: Option<Instant>,
|
||||||
pub flash_color: Color,
|
pub flash_kind: FlashKind,
|
||||||
pub modal: Modal,
|
pub modal: Modal,
|
||||||
pub help_topic: usize,
|
pub help_topic: usize,
|
||||||
pub help_scroll: usize,
|
pub help_scroll: usize,
|
||||||
@@ -41,7 +47,7 @@ impl Default for UiState {
|
|||||||
sparkles: Vec::new(),
|
sparkles: Vec::new(),
|
||||||
status_message: None,
|
status_message: None,
|
||||||
flash_until: None,
|
flash_until: None,
|
||||||
flash_color: Color::Green,
|
flash_kind: FlashKind::Success,
|
||||||
modal: Modal::None,
|
modal: Modal::None,
|
||||||
help_topic: 0,
|
help_topic: 0,
|
||||||
help_scroll: 0,
|
help_scroll: 0,
|
||||||
@@ -57,14 +63,14 @@ impl Default for UiState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UiState {
|
impl UiState {
|
||||||
pub fn flash(&mut self, msg: &str, duration_ms: u64, color: Color) {
|
pub fn flash(&mut self, msg: &str, duration_ms: u64, kind: FlashKind) {
|
||||||
self.status_message = Some(msg.to_string());
|
self.status_message = Some(msg.to_string());
|
||||||
self.flash_until = Some(Instant::now() + Duration::from_millis(duration_ms));
|
self.flash_until = Some(Instant::now() + Duration::from_millis(duration_ms));
|
||||||
self.flash_color = color;
|
self.flash_kind = kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn flash_color(&self) -> Option<Color> {
|
pub fn flash_kind(&self) -> Option<FlashKind> {
|
||||||
if self.is_flashing() { Some(self.flash_color) } else { None }
|
if self.is_flashing() { Some(self.flash_kind) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_status(&mut self, msg: String) {
|
pub fn set_status(&mut self, msg: String) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use crate::app::App;
|
|||||||
use crate::engine::{LinkState, SequencerSnapshot};
|
use crate::engine::{LinkState, SequencerSnapshot};
|
||||||
use crate::model::SourceSpan;
|
use crate::model::SourceSpan;
|
||||||
use crate::page::Page;
|
use crate::page::Page;
|
||||||
use crate::state::{Modal, PanelFocus, PatternField, SidePanel};
|
use crate::state::{FlashKind, Modal, PanelFocus, PatternField, SidePanel};
|
||||||
use crate::views::highlight::{self, highlight_line, highlight_line_with_runtime};
|
use crate::views::highlight::{self, highlight_line, highlight_line_with_runtime};
|
||||||
use crate::widgets::{ConfirmModal, ModalFrame, NavMinimap, NavTile, SampleBrowser, TextInputModal};
|
use crate::widgets::{ConfirmModal, ModalFrame, NavMinimap, NavTile, SampleBrowser, TextInputModal};
|
||||||
|
|
||||||
@@ -524,9 +524,11 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
|
|||||||
let height = (term.height * 60 / 100).max(10);
|
let height = (term.height * 60 / 100).max(10);
|
||||||
let step_num = app.editor_ctx.step + 1;
|
let step_num = app.editor_ctx.step + 1;
|
||||||
|
|
||||||
let flash_color = app.ui.flash_color();
|
let flash_kind = app.ui.flash_kind();
|
||||||
let border_color = match flash_color {
|
let border_color = match flash_kind {
|
||||||
Some(c) => c,
|
Some(FlashKind::Error) => Color::Red,
|
||||||
|
Some(FlashKind::Info) => Color::White,
|
||||||
|
Some(FlashKind::Success) => Color::Green,
|
||||||
None => Color::Rgb(100, 160, 180),
|
None => Color::Rgb(100, 160, 180),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -566,11 +568,11 @@ fn render_modal(frame: &mut Frame, app: &App, snapshot: &SequencerSnapshot, term
|
|||||||
let editor_area = Rect::new(inner.x, inner.y, inner.width, inner.height.saturating_sub(1));
|
let editor_area = Rect::new(inner.x, inner.y, inner.width, inner.height.saturating_sub(1));
|
||||||
let hint_area = Rect::new(inner.x, inner.y + editor_area.height, inner.width, 1);
|
let hint_area = Rect::new(inner.x, inner.y + editor_area.height, inner.width, 1);
|
||||||
|
|
||||||
if let Some(c) = flash_color {
|
if let Some(kind) = flash_kind {
|
||||||
let bg = match c {
|
let bg = match kind {
|
||||||
Color::Red => Color::Rgb(60, 10, 10),
|
FlashKind::Error => Color::Rgb(60, 10, 10),
|
||||||
Color::White => Color::Rgb(30, 30, 40),
|
FlashKind::Info => Color::Rgb(30, 30, 40),
|
||||||
_ => Color::Rgb(10, 30, 10),
|
FlashKind::Success => Color::Rgb(10, 30, 10),
|
||||||
};
|
};
|
||||||
let flash_block = Block::default().style(Style::default().bg(bg));
|
let flash_block = Block::default().style(Style::default().bg(bg));
|
||||||
frame.render_widget(flash_block, editor_area);
|
frame.render_widget(flash_block, editor_area);
|
||||||
|
|||||||
Reference in New Issue
Block a user