Lots + MIDI implementation

This commit is contained in:
2026-01-31 23:13:51 +01:00
parent b5fe6a1437
commit 03c0baf5b5
34 changed files with 4323 additions and 191 deletions

View File

@@ -2,6 +2,7 @@ mod app;
mod commands;
mod engine;
mod input;
mod midi;
mod model;
mod page;
mod services;
@@ -101,6 +102,20 @@ fn main() -> io::Result<()> {
app.ui.color_scheme = settings.display.color_scheme;
theme::set(settings.display.color_scheme.to_theme());
// Load MIDI settings
if let Some(output_name) = &settings.midi.output_device {
let outputs = midi::list_midi_outputs();
if let Some(idx) = outputs.iter().position(|d| &d.name == output_name) {
let _ = app.midi.connect_output(idx);
}
}
if let Some(input_name) = &settings.midi.input_device {
let inputs = midi::list_midi_inputs();
if let Some(idx) = inputs.iter().position(|d| &d.name == input_name) {
let _ = app.midi.connect_input(idx);
}
}
let metrics = Arc::new(EngineMetrics::default());
let scope_buffer = Arc::new(ScopeBuffer::new());
let spectrum_buffer = Arc::new(SpectrumBuffer::new());
@@ -120,9 +135,10 @@ fn main() -> io::Result<()> {
audio_sample_pos: Arc::clone(&audio_sample_pos),
sample_rate: Arc::clone(&sample_rate_shared),
lookahead_ms: Arc::clone(&lookahead_ms),
cc_memory: Some(Arc::clone(&app.midi.cc_memory)),
};
let (sequencer, initial_audio_rx) = spawn_sequencer(
let (sequencer, initial_audio_rx, mut midi_rx) = spawn_sequencer(
Arc::clone(&link),
Arc::clone(&playing),
Arc::clone(&app.variables),
@@ -177,6 +193,7 @@ fn main() -> io::Result<()> {
_analysis_handle = None;
let new_audio_rx = sequencer.swap_audio_channel();
midi_rx = sequencer.swap_midi_channel();
let new_config = AudioStreamConfig {
output_device: app.audio.config.output_device.clone(),
@@ -220,6 +237,21 @@ fn main() -> io::Result<()> {
app.playback.playing = playing.load(Ordering::Relaxed);
// Process pending MIDI commands
while let Ok(midi_cmd) = midi_rx.try_recv() {
match midi_cmd {
engine::MidiCommand::NoteOn { channel, note, velocity } => {
app.midi.send_note_on(channel, note, velocity);
}
engine::MidiCommand::NoteOff { channel, note } => {
app.midi.send_note_off(channel, note);
}
engine::MidiCommand::CC { channel, cc, value } => {
app.midi.send_cc(channel, cc, value);
}
}
}
{
app.metrics.active_voices = metrics.active_voices.load(Ordering::Relaxed) as usize;
app.metrics.peak_voices = app.metrics.peak_voices.max(app.metrics.active_voices);