This commit is contained in:
2026-01-26 00:24:17 +01:00
parent 016d050678
commit 87fd59549d
12 changed files with 862 additions and 614 deletions

View File

@@ -9,7 +9,7 @@ use crate::commands::AppCommand;
use crate::engine::{AudioCommand, LinkState, SequencerSnapshot};
use crate::model::PatternSpeed;
use crate::page::Page;
use crate::state::{AudioFocus, Modal, PanelFocus, PatternField, SampleBrowserState, SidePanel};
use crate::state::{DeviceKind, EngineSection, Modal, OptionsFocus, PanelFocus, PatternField, SampleBrowserState, SettingKind, SidePanel};
pub enum InputResult {
Continue,
@@ -453,7 +453,8 @@ fn handle_normal_input(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
match ctx.app.page {
Page::Main => handle_main_page(ctx, key, ctrl),
Page::Patterns => handle_patterns_page(ctx, key),
Page::Audio => handle_audio_page(ctx, key),
Page::Engine => handle_engine_page(ctx, key),
Page::Options => handle_options_page(ctx, key),
Page::Help => handle_help_page(ctx, key),
Page::Dict => handle_dict_page(ctx, key),
}
@@ -719,132 +720,113 @@ fn handle_patterns_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
InputResult::Continue
}
fn handle_audio_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
fn handle_engine_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
match key.code {
KeyCode::Char('q') => {
ctx.dispatch(AppCommand::OpenModal(Modal::ConfirmQuit {
selected: false,
}));
}
KeyCode::Tab => ctx.app.audio.next_focus(),
KeyCode::BackTab => ctx.app.audio.prev_focus(),
KeyCode::Up => match ctx.app.audio.focus {
AudioFocus::OutputDevice => ctx.app.audio.output_list.move_up(),
AudioFocus::InputDevice => ctx.app.audio.input_list.move_up(),
_ => {}
KeyCode::Tab => ctx.app.audio.next_section(),
KeyCode::BackTab => ctx.app.audio.prev_section(),
KeyCode::Up => match ctx.app.audio.section {
EngineSection::Devices => match ctx.app.audio.device_kind {
DeviceKind::Output => ctx.app.audio.output_list.move_up(),
DeviceKind::Input => ctx.app.audio.input_list.move_up(),
},
EngineSection::Settings => {
ctx.app.audio.setting_kind = ctx.app.audio.setting_kind.prev();
}
EngineSection::Samples => {}
},
KeyCode::Down => match ctx.app.audio.focus {
AudioFocus::OutputDevice => {
let count = ctx.app.audio.output_devices.len();
ctx.app.audio.output_list.move_down(count);
KeyCode::Down => match ctx.app.audio.section {
EngineSection::Devices => match ctx.app.audio.device_kind {
DeviceKind::Output => {
let count = ctx.app.audio.output_devices.len();
ctx.app.audio.output_list.move_down(count);
}
DeviceKind::Input => {
let count = ctx.app.audio.input_devices.len();
ctx.app.audio.input_list.move_down(count);
}
},
EngineSection::Settings => {
ctx.app.audio.setting_kind = ctx.app.audio.setting_kind.next();
}
AudioFocus::InputDevice => {
let count = ctx.app.audio.input_devices.len();
ctx.app.audio.input_list.move_down(count);
}
_ => {}
EngineSection::Samples => {}
},
KeyCode::PageUp => match ctx.app.audio.focus {
AudioFocus::OutputDevice => ctx.app.audio.output_list.page_up(),
AudioFocus::InputDevice => ctx.app.audio.input_list.page_up(),
_ => {}
},
KeyCode::PageDown => match ctx.app.audio.focus {
AudioFocus::OutputDevice => {
let count = ctx.app.audio.output_devices.len();
ctx.app.audio.output_list.page_down(count);
}
AudioFocus::InputDevice => {
let count = ctx.app.audio.input_devices.len();
ctx.app.audio.input_list.page_down(count);
}
_ => {}
},
KeyCode::Enter => match ctx.app.audio.focus {
AudioFocus::OutputDevice => {
let cursor = ctx.app.audio.output_list.cursor;
if cursor < ctx.app.audio.output_devices.len() {
ctx.app.audio.config.output_device =
Some(ctx.app.audio.output_devices[cursor].name.clone());
ctx.app.save_settings(ctx.link);
KeyCode::PageUp => {
if ctx.app.audio.section == EngineSection::Devices {
match ctx.app.audio.device_kind {
DeviceKind::Output => ctx.app.audio.output_list.page_up(),
DeviceKind::Input => ctx.app.audio.input_list.page_up(),
}
}
AudioFocus::InputDevice => {
let cursor = ctx.app.audio.input_list.cursor;
if cursor < ctx.app.audio.input_devices.len() {
ctx.app.audio.config.input_device =
Some(ctx.app.audio.input_devices[cursor].name.clone());
ctx.app.save_settings(ctx.link);
}
}
_ => {}
},
KeyCode::Left => {
match ctx.app.audio.focus {
AudioFocus::OutputDevice | AudioFocus::InputDevice => {}
AudioFocus::Channels => ctx.app.audio.adjust_channels(-1),
AudioFocus::BufferSize => ctx.app.audio.adjust_buffer_size(-64),
AudioFocus::Polyphony => ctx.app.audio.adjust_max_voices(-1),
AudioFocus::RefreshRate => ctx.app.audio.toggle_refresh_rate(),
AudioFocus::RuntimeHighlight => {
ctx.app.ui.runtime_highlight = !ctx.app.ui.runtime_highlight
}
AudioFocus::ShowScope => {
ctx.app.audio.config.show_scope = !ctx.app.audio.config.show_scope;
}
AudioFocus::ShowSpectrum => {
ctx.app.audio.config.show_spectrum = !ctx.app.audio.config.show_spectrum;
}
AudioFocus::ShowCompletion => {
ctx.app.ui.show_completion = !ctx.app.ui.show_completion;
}
AudioFocus::SamplePaths => ctx.app.audio.remove_last_sample_path(),
AudioFocus::LinkEnabled => ctx.link.set_enabled(!ctx.link.is_enabled()),
AudioFocus::StartStopSync => ctx
.link
.set_start_stop_sync_enabled(!ctx.link.is_start_stop_sync_enabled()),
AudioFocus::Quantum => ctx.link.set_quantum(ctx.link.quantum() - 1.0),
}
if !matches!(
ctx.app.audio.focus,
AudioFocus::SamplePaths | AudioFocus::OutputDevice | AudioFocus::InputDevice
) {
ctx.app.save_settings(ctx.link);
}
}
KeyCode::Right => {
match ctx.app.audio.focus {
AudioFocus::OutputDevice | AudioFocus::InputDevice => {}
AudioFocus::Channels => ctx.app.audio.adjust_channels(1),
AudioFocus::BufferSize => ctx.app.audio.adjust_buffer_size(64),
AudioFocus::Polyphony => ctx.app.audio.adjust_max_voices(1),
AudioFocus::RefreshRate => ctx.app.audio.toggle_refresh_rate(),
AudioFocus::RuntimeHighlight => {
ctx.app.ui.runtime_highlight = !ctx.app.ui.runtime_highlight
KeyCode::PageDown => {
if ctx.app.audio.section == EngineSection::Devices {
match ctx.app.audio.device_kind {
DeviceKind::Output => {
let count = ctx.app.audio.output_devices.len();
ctx.app.audio.output_list.page_down(count);
}
DeviceKind::Input => {
let count = ctx.app.audio.input_devices.len();
ctx.app.audio.input_list.page_down(count);
}
}
AudioFocus::ShowScope => {
ctx.app.audio.config.show_scope = !ctx.app.audio.config.show_scope;
}
AudioFocus::ShowSpectrum => {
ctx.app.audio.config.show_spectrum = !ctx.app.audio.config.show_spectrum;
}
AudioFocus::ShowCompletion => {
ctx.app.ui.show_completion = !ctx.app.ui.show_completion;
}
AudioFocus::SamplePaths => {}
AudioFocus::LinkEnabled => ctx.link.set_enabled(!ctx.link.is_enabled()),
AudioFocus::StartStopSync => ctx
.link
.set_start_stop_sync_enabled(!ctx.link.is_start_stop_sync_enabled()),
AudioFocus::Quantum => ctx.link.set_quantum(ctx.link.quantum() + 1.0),
}
if !matches!(
ctx.app.audio.focus,
AudioFocus::SamplePaths | AudioFocus::OutputDevice | AudioFocus::InputDevice
) {
ctx.app.save_settings(ctx.link);
}
}
KeyCode::Enter => {
if ctx.app.audio.section == EngineSection::Devices {
match ctx.app.audio.device_kind {
DeviceKind::Output => {
let cursor = ctx.app.audio.output_list.cursor;
if cursor < ctx.app.audio.output_devices.len() {
ctx.app.audio.config.output_device =
Some(ctx.app.audio.output_devices[cursor].name.clone());
ctx.app.save_settings(ctx.link);
}
}
DeviceKind::Input => {
let cursor = ctx.app.audio.input_list.cursor;
if cursor < ctx.app.audio.input_devices.len() {
ctx.app.audio.config.input_device =
Some(ctx.app.audio.input_devices[cursor].name.clone());
ctx.app.save_settings(ctx.link);
}
}
}
}
}
KeyCode::Left => match ctx.app.audio.section {
EngineSection::Devices => {
ctx.app.audio.device_kind = DeviceKind::Output;
}
EngineSection::Settings => {
match ctx.app.audio.setting_kind {
SettingKind::Channels => ctx.app.audio.adjust_channels(-1),
SettingKind::BufferSize => ctx.app.audio.adjust_buffer_size(-64),
SettingKind::Polyphony => ctx.app.audio.adjust_max_voices(-1),
}
ctx.app.save_settings(ctx.link);
}
EngineSection::Samples => {}
},
KeyCode::Right => match ctx.app.audio.section {
EngineSection::Devices => {
ctx.app.audio.device_kind = DeviceKind::Input;
}
EngineSection::Settings => {
match ctx.app.audio.setting_kind {
SettingKind::Channels => ctx.app.audio.adjust_channels(1),
SettingKind::BufferSize => ctx.app.audio.adjust_buffer_size(64),
SettingKind::Polyphony => ctx.app.audio.adjust_max_voices(1),
}
ctx.app.save_settings(ctx.link);
}
EngineSection::Samples => {}
},
KeyCode::Char('R') => ctx.app.audio.trigger_restart(),
KeyCode::Char('A') => {
use crate::state::file_browser::FileBrowserState;
@@ -852,12 +834,16 @@ fn handle_audio_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
ctx.dispatch(AppCommand::OpenModal(Modal::AddSamplePath(state)));
}
KeyCode::Char('D') => {
ctx.app.audio.refresh_devices();
let out_count = ctx.app.audio.output_devices.len();
let in_count = ctx.app.audio.input_devices.len();
ctx.dispatch(AppCommand::SetStatus(format!(
"Found {out_count} output, {in_count} input devices"
)));
if ctx.app.audio.section == EngineSection::Samples {
ctx.app.audio.remove_last_sample_path();
} else {
ctx.app.audio.refresh_devices();
let out_count = ctx.app.audio.output_devices.len();
let in_count = ctx.app.audio.input_devices.len();
ctx.dispatch(AppCommand::SetStatus(format!(
"Found {out_count} output, {in_count} input devices"
)));
}
}
KeyCode::Char('h') => {
let _ = ctx.audio_tx.send(AudioCommand::Hush);
@@ -871,6 +857,46 @@ fn handle_audio_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
.audio_tx
.send(AudioCommand::Evaluate("/sound/sine/dur/0.5/decay/0.2".into()));
}
_ => {}
}
InputResult::Continue
}
fn handle_options_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
match key.code {
KeyCode::Char('q') => {
ctx.dispatch(AppCommand::OpenModal(Modal::ConfirmQuit {
selected: false,
}));
}
KeyCode::Down | KeyCode::Tab => ctx.app.options.next_focus(),
KeyCode::Up | KeyCode::BackTab => ctx.app.options.prev_focus(),
KeyCode::Left | KeyCode::Right => {
match ctx.app.options.focus {
OptionsFocus::RefreshRate => ctx.app.audio.toggle_refresh_rate(),
OptionsFocus::RuntimeHighlight => {
ctx.app.ui.runtime_highlight = !ctx.app.ui.runtime_highlight
}
OptionsFocus::ShowScope => {
ctx.app.audio.config.show_scope = !ctx.app.audio.config.show_scope
}
OptionsFocus::ShowSpectrum => {
ctx.app.audio.config.show_spectrum = !ctx.app.audio.config.show_spectrum
}
OptionsFocus::ShowCompletion => {
ctx.app.ui.show_completion = !ctx.app.ui.show_completion
}
OptionsFocus::LinkEnabled => ctx.link.set_enabled(!ctx.link.is_enabled()),
OptionsFocus::StartStopSync => ctx
.link
.set_start_stop_sync_enabled(!ctx.link.is_start_stop_sync_enabled()),
OptionsFocus::Quantum => {
let delta = if key.code == KeyCode::Left { -1.0 } else { 1.0 };
ctx.link.set_quantum(ctx.link.quantum() + delta);
}
}
ctx.app.save_settings(ctx.link);
}
KeyCode::Char(' ') => {
ctx.dispatch(AppCommand::TogglePlaying);
ctx.playing