MIDI Documentation and optional mouse event support
This commit is contained in:
@@ -19,9 +19,10 @@ use soft_ratatui::{EmbeddedGraphics, SoftBackend};
|
||||
|
||||
use cagire::app::App;
|
||||
use cagire::engine::{
|
||||
build_stream, spawn_sequencer, AnalysisHandle, AudioStreamConfig, LinkState, ScopeBuffer,
|
||||
SequencerConfig, SequencerHandle, SpectrumBuffer,
|
||||
build_stream, spawn_sequencer, AnalysisHandle, AudioStreamConfig, LinkState, MidiCommand,
|
||||
ScopeBuffer, SequencerConfig, SequencerHandle, SpectrumBuffer,
|
||||
};
|
||||
use crossbeam_channel::Receiver;
|
||||
use cagire::input::{handle_key, InputContext, InputResult};
|
||||
use cagire::input_egui::convert_egui_events;
|
||||
use cagire::settings::Settings;
|
||||
@@ -144,7 +145,11 @@ struct CagireDesktop {
|
||||
sample_rate_shared: Arc<AtomicU32>,
|
||||
_stream: Option<cpal::Stream>,
|
||||
_analysis_handle: Option<AnalysisHandle>,
|
||||
midi_rx: Receiver<MidiCommand>,
|
||||
current_font: FontChoice,
|
||||
mouse_x: Arc<AtomicU32>,
|
||||
mouse_y: Arc<AtomicU32>,
|
||||
mouse_down: Arc<AtomicU32>,
|
||||
}
|
||||
|
||||
impl CagireDesktop {
|
||||
@@ -201,13 +206,21 @@ impl CagireDesktop {
|
||||
initial_samples.extend(index);
|
||||
}
|
||||
|
||||
let mouse_x = Arc::new(AtomicU32::new(0.5_f32.to_bits()));
|
||||
let mouse_y = Arc::new(AtomicU32::new(0.5_f32.to_bits()));
|
||||
let mouse_down = Arc::new(AtomicU32::new(0.0_f32.to_bits()));
|
||||
|
||||
let seq_config = SequencerConfig {
|
||||
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)),
|
||||
mouse_x: Arc::clone(&mouse_x),
|
||||
mouse_y: Arc::clone(&mouse_y),
|
||||
mouse_down: Arc::clone(&mouse_down),
|
||||
};
|
||||
|
||||
let (sequencer, initial_audio_rx) = spawn_sequencer(
|
||||
let (sequencer, initial_audio_rx, midi_rx) = spawn_sequencer(
|
||||
Arc::clone(&link),
|
||||
Arc::clone(&playing),
|
||||
Arc::clone(&app.variables),
|
||||
@@ -268,7 +281,11 @@ impl CagireDesktop {
|
||||
sample_rate_shared,
|
||||
_stream: stream,
|
||||
_analysis_handle: analysis_handle,
|
||||
midi_rx,
|
||||
current_font,
|
||||
mouse_x,
|
||||
mouse_y,
|
||||
mouse_down,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,6 +302,7 @@ impl CagireDesktop {
|
||||
return;
|
||||
};
|
||||
let new_audio_rx = sequencer.swap_audio_channel();
|
||||
self.midi_rx = sequencer.swap_midi_channel();
|
||||
|
||||
let new_config = AudioStreamConfig {
|
||||
output_device: self.app.audio.config.output_device.clone(),
|
||||
@@ -373,6 +391,18 @@ impl eframe::App for CagireDesktop {
|
||||
self.handle_audio_restart();
|
||||
self.update_metrics();
|
||||
|
||||
ctx.input(|i| {
|
||||
if let Some(pos) = i.pointer.latest_pos() {
|
||||
let screen = i.viewport_rect();
|
||||
let nx = (pos.x / screen.width()).clamp(0.0, 1.0);
|
||||
let ny = (pos.y / screen.height()).clamp(0.0, 1.0);
|
||||
self.mouse_x.store(nx.to_bits(), Ordering::Relaxed);
|
||||
self.mouse_y.store(ny.to_bits(), Ordering::Relaxed);
|
||||
}
|
||||
let down = if i.pointer.primary_down() { 1.0_f32 } else { 0.0_f32 };
|
||||
self.mouse_down.store(down.to_bits(), Ordering::Relaxed);
|
||||
});
|
||||
|
||||
let Some(ref sequencer) = self.sequencer else {
|
||||
return;
|
||||
};
|
||||
@@ -395,6 +425,33 @@ impl eframe::App for CagireDesktop {
|
||||
self.app.flush_queued_changes(&sequencer.cmd_tx);
|
||||
self.app.flush_dirty_patterns(&sequencer.cmd_tx);
|
||||
|
||||
while let Ok(midi_cmd) = self.midi_rx.try_recv() {
|
||||
match midi_cmd {
|
||||
MidiCommand::NoteOn { device, channel, note, velocity } => {
|
||||
self.app.midi.send_note_on(device, channel, note, velocity);
|
||||
}
|
||||
MidiCommand::NoteOff { device, channel, note } => {
|
||||
self.app.midi.send_note_off(device, channel, note);
|
||||
}
|
||||
MidiCommand::CC { device, channel, cc, value } => {
|
||||
self.app.midi.send_cc(device, channel, cc, value);
|
||||
}
|
||||
MidiCommand::PitchBend { device, channel, value } => {
|
||||
self.app.midi.send_pitch_bend(device, channel, value);
|
||||
}
|
||||
MidiCommand::Pressure { device, channel, value } => {
|
||||
self.app.midi.send_pressure(device, channel, value);
|
||||
}
|
||||
MidiCommand::ProgramChange { device, channel, program } => {
|
||||
self.app.midi.send_program_change(device, channel, program);
|
||||
}
|
||||
MidiCommand::Clock { device } => self.app.midi.send_realtime(device, 0xF8),
|
||||
MidiCommand::Start { device } => self.app.midi.send_realtime(device, 0xFA),
|
||||
MidiCommand::Stop { device } => self.app.midi.send_realtime(device, 0xFC),
|
||||
MidiCommand::Continue { device } => self.app.midi.send_realtime(device, 0xFB),
|
||||
}
|
||||
}
|
||||
|
||||
let should_quit = self.handle_input(ctx);
|
||||
if should_quit {
|
||||
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
|
||||
|
||||
Reference in New Issue
Block a user