paired with anya, thank youuuu

This commit is contained in:
Nicole Tietz-Sokolskaya 2025-01-01 16:17:49 -05:00
parent bfbf0e62c0
commit 6f6b0721fe
2 changed files with 61 additions and 40 deletions

View file

@ -4,7 +4,7 @@ use std::{
};
use anyhow::{anyhow, Result};
use midi_keys::{log::load_raw_log, parser::parse_message};
use midi_keys::{log::load_raw_log, midi::daemon::Category, parser::parse_message};
//use enigo::{Direction, Enigo, Key, Keyboard, Settings};
use midir::{MidiInput, MidiInputPort};
@ -13,14 +13,24 @@ fn main() {
//enigo.text("echo \"hello world\"").unwrap();
//enigo.key(Key::Return, Direction::Press).unwrap();
midi_keys::midi::daemon::run_daemon();
midi_keys::ui::run();
let (send, receive) = crossbeam::channel::unbounded();
let all = Category::All;
std::thread::spawn(move || {
midi_keys::midi::daemon::run_daemon(vec![(all, send)]);
});
std::thread::spawn(move || loop {
match receive.recv() {
Ok(m) => println!("got: {m:?}"),
Err(err) => println!("err: {err:?}"),
}
});
midi_keys::ui::run();
}
pub fn run() -> Result<()> {
midi_keys::midi::daemon::run_daemon();
let midi_in = MidiInput::new("keyboard")?;
let midi_device = match find_first_midi_device(&midi_in) {

View file

@ -1,15 +1,17 @@
use std::{
collections::HashMap,
sync::mpsc::{self, Receiver, Sender},
};
use std::{collections::HashMap, time::Duration};
use crossbeam::{
channel::{Receiver, Sender},
select,
};
use midir::{MidiInput, MidiInputConnection, MidiInputPort};
use crate::parser::parse_message;
use super::Message;
enum Category {
pub enum Category {
All,
Drums,
WindSynth,
Piano,
@ -35,31 +37,54 @@ enum Category {
type ConnectionId = String;
type Timestamp = u64;
type TimestampedMessage = (Timestamp, Message);
type CTM = (ConnectionId, Timestamp, Message);
pub fn run_daemon() {
type MidiSend = crossbeam::channel::Sender<CTM>;
type MidiRecv = crossbeam::channel::Receiver<CTM>;
pub fn run_daemon(routes: Vec<(Category, MidiSend)>) {
let mut state = State::new();
let messages = state.message_queue();
let ticker = crossbeam::channel::tick(Duration::from_millis(250));
loop {
state.refresh_ports();
std::thread::sleep_ms(250);
select! {
recv(ticker) -> m => match m {
Ok(ts) => {
println!("refreshing ports at {ts:?}");
state.refresh_ports();
}
Err(e) => {
println!("borken {e:?}");
}
},
recv(messages) -> m => match m {
Ok(ctm) => {
for (_cat, q) in routes.iter() {
q.send(ctm.clone());
}
}
Err(e) => {
println!("borken2 {e:?}");
}
},
}
}
}
pub struct State {
midi: MidiInput,
ports: Vec<MidiInputPort>,
connections: HashMap<
String,
MidiInputConnection<(ConnectionId, Sender<(ConnectionId, TimestampedMessage)>)>,
>,
connections: HashMap<String, MidiInputConnection<(ConnectionId, Sender<CTM>)>>,
message_receive: Receiver<(ConnectionId, TimestampedMessage)>,
message_send: Sender<(ConnectionId, TimestampedMessage)>,
message_receive: Receiver<CTM>,
message_send: Sender<CTM>,
}
impl State {
pub fn new() -> State {
let (tx, rx) = mpsc::channel();
let (tx, rx) = crossbeam::channel::unbounded();
State {
midi: MidiInput::new("midi-keys daemon").expect("could not connect to system MIDI"),
@ -70,24 +95,21 @@ impl State {
}
}
pub fn refresh_ports(&mut self) {
let start = std::time::Instant::now();
pub fn message_queue(&self) -> Receiver<CTM> {
self.message_receive.clone()
}
pub fn refresh_ports(&mut self) {
let ports = self.midi.ports();
for port in ports.iter() {
self.refresh_port(port);
}
self.ports = ports;
let duration = std::time::Instant::now().duration_since(start).as_micros();
println!("refreshing ports took {} microseconds", duration);
}
pub fn refresh_port(&mut self, port: &MidiInputPort) {
let start = std::time::Instant::now();
let connected = self.connections.contains_key(&port.id());
println!("checking conn took {} microseconds", std::time::Instant::now().duration_since(start).as_micros());
let name = match self.midi.port_name(port) {
Ok(s) => s,
Err(_) => {
@ -99,16 +121,12 @@ impl State {
}
};
println!("getting name took {} microseconds", std::time::Instant::now().duration_since(start).as_micros());
if connected {
return;
}
let midi = MidiInput::new("midi-keys").expect("could not connect to system MIDI");
println!("midi input init took {} microseconds", std::time::Instant::now().duration_since(start).as_micros());
let send_queue = self.message_send.clone();
println!("cloning queue took {} microseconds", std::time::Instant::now().duration_since(start).as_micros());
if let Ok(conn) = midi.connect(
&port,
@ -120,19 +138,12 @@ impl State {
) {
self.connections.insert(port.id(), conn);
}
println!("midi conn took {} microseconds", std::time::Instant::now().duration_since(start).as_micros());
}
}
fn handle_message(
ts: Timestamp,
bytes: &[u8],
conn_id: &ConnectionId,
tx: &Sender<(ConnectionId, TimestampedMessage)>,
) {
fn handle_message(ts: Timestamp, bytes: &[u8], conn_id: &ConnectionId, tx: &Sender<CTM>) {
if let Ok((_rem, msg)) = parse_message(bytes) {
let _ = tx.send((conn_id.clone(), (ts, msg)));
let _ = tx.send((conn_id.clone(), ts, msg));
}
}
// TODO: chain of handlers? -> handle event as keypress, send to UI