routes
This commit is contained in:
parent
6f6b0721fe
commit
3cae2d310c
3 changed files with 74 additions and 17 deletions
|
@ -13,19 +13,37 @@ fn main() {
|
||||||
//enigo.text("echo \"hello world\"").unwrap();
|
//enigo.text("echo \"hello world\"").unwrap();
|
||||||
//enigo.key(Key::Return, Direction::Press).unwrap();
|
//enigo.key(Key::Return, Direction::Press).unwrap();
|
||||||
|
|
||||||
let (send, receive) = crossbeam::channel::unbounded();
|
let (dbg_send, dbg_recv) = crossbeam::channel::unbounded();
|
||||||
|
let (ws_send, ws_recv) = crossbeam::channel::unbounded();
|
||||||
|
let (drum_send, drum_recv) = crossbeam::channel::unbounded();
|
||||||
let all = Category::All;
|
let all = Category::All;
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
midi_keys::midi::daemon::run_daemon(vec![(all, send)]);
|
midi_keys::midi::daemon::run_daemon(vec![
|
||||||
|
(all, dbg_send),
|
||||||
|
(Category::WindSynth, ws_send),
|
||||||
|
(Category::Drums, drum_send),
|
||||||
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
std::thread::spawn(move || loop {
|
std::thread::spawn(move || loop {
|
||||||
match receive.recv() {
|
match dbg_recv.recv() {
|
||||||
Ok(m) => println!("got: {m:?}"),
|
Ok(m) => println!("debug: {m:?}"),
|
||||||
Err(err) => println!("err: {err:?}"),
|
Err(err) => println!("err: {err:?}"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
std::thread::spawn(move || loop {
|
||||||
|
match ws_recv.recv() {
|
||||||
|
Ok(m) => println!("windsynth: {m:?}"),
|
||||||
|
Err(err) => println!("err(ws): {err:?}"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
std::thread::spawn(move || loop {
|
||||||
|
match drum_recv.recv() {
|
||||||
|
Ok(m) => println!("drum: {m:?}"),
|
||||||
|
Err(err) => println!("err(drum): {err:?}"),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
midi_keys::ui::run();
|
midi_keys::ui::run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::parser::parse_message;
|
||||||
|
|
||||||
use super::Message;
|
use super::Message;
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Debug)]
|
||||||
pub enum Category {
|
pub enum Category {
|
||||||
All,
|
All,
|
||||||
Drums,
|
Drums,
|
||||||
|
@ -36,7 +37,6 @@ pub enum Category {
|
||||||
|
|
||||||
type ConnectionId = String;
|
type ConnectionId = String;
|
||||||
type Timestamp = u64;
|
type Timestamp = u64;
|
||||||
type TimestampedMessage = (Timestamp, Message);
|
|
||||||
type CTM = (ConnectionId, Timestamp, Message);
|
type CTM = (ConnectionId, Timestamp, Message);
|
||||||
|
|
||||||
type MidiSend = crossbeam::channel::Sender<CTM>;
|
type MidiSend = crossbeam::channel::Sender<CTM>;
|
||||||
|
@ -44,25 +44,39 @@ type MidiRecv = crossbeam::channel::Receiver<CTM>;
|
||||||
|
|
||||||
pub fn run_daemon(routes: Vec<(Category, MidiSend)>) {
|
pub fn run_daemon(routes: Vec<(Category, MidiSend)>) {
|
||||||
let mut state = State::new();
|
let mut state = State::new();
|
||||||
let messages = state.message_queue();
|
|
||||||
|
|
||||||
|
let mut conn_mapping: HashMap<ConnectionId, Category> = HashMap::new();
|
||||||
|
|
||||||
|
let messages_q = state.message_queue();
|
||||||
|
let conn_mapping_q = state.connection_mapping_queue();
|
||||||
let ticker = crossbeam::channel::tick(Duration::from_millis(250));
|
let ticker = crossbeam::channel::tick(Duration::from_millis(250));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
select! {
|
select! {
|
||||||
recv(ticker) -> m => match m {
|
recv(ticker) -> m => match m {
|
||||||
Ok(ts) => {
|
Ok(_ts) => {
|
||||||
println!("refreshing ports at {ts:?}");
|
|
||||||
state.refresh_ports();
|
state.refresh_ports();
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("borken {e:?}");
|
println!("borken {e:?}");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
recv(messages) -> m => match m {
|
recv(conn_mapping_q) -> m => match m {
|
||||||
|
Ok((conn_id, category)) => {
|
||||||
|
conn_mapping.insert(conn_id, category);
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
println!("borken3 {e:?}");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
recv(messages_q) -> m => match m {
|
||||||
Ok(ctm) => {
|
Ok(ctm) => {
|
||||||
for (_cat, q) in routes.iter() {
|
let (cid, _ts, _msg) = &ctm;
|
||||||
q.send(ctm.clone());
|
let msg_cat = conn_mapping.get(cid).unwrap_or(&Category::Ignore);
|
||||||
|
for (route_cat, q) in routes.iter() {
|
||||||
|
if route_cat == msg_cat || *route_cat == Category::All {
|
||||||
|
let _ = q.send(ctm.clone());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -80,18 +94,24 @@ pub struct State {
|
||||||
|
|
||||||
message_receive: Receiver<CTM>,
|
message_receive: Receiver<CTM>,
|
||||||
message_send: Sender<CTM>,
|
message_send: Sender<CTM>,
|
||||||
|
|
||||||
|
conn_map_receive: Receiver<(ConnectionId, Category)>,
|
||||||
|
conn_map_send: Sender<(ConnectionId, Category)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
pub fn new() -> State {
|
pub fn new() -> State {
|
||||||
let (tx, rx) = crossbeam::channel::unbounded();
|
let (msg_tx, msg_rx) = crossbeam::channel::unbounded();
|
||||||
|
let (conn_tx, conn_rx) = crossbeam::channel::unbounded();
|
||||||
|
|
||||||
State {
|
State {
|
||||||
midi: MidiInput::new("midi-keys daemon").expect("could not connect to system MIDI"),
|
midi: MidiInput::new("midi-keys daemon").expect("could not connect to system MIDI"),
|
||||||
ports: vec![],
|
ports: vec![],
|
||||||
connections: HashMap::new(),
|
connections: HashMap::new(),
|
||||||
message_receive: rx,
|
message_receive: msg_rx,
|
||||||
message_send: tx,
|
message_send: msg_tx,
|
||||||
|
conn_map_receive: conn_rx,
|
||||||
|
conn_map_send: conn_tx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +119,10 @@ impl State {
|
||||||
self.message_receive.clone()
|
self.message_receive.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connection_mapping_queue(&self) -> Receiver<(ConnectionId, Category)> {
|
||||||
|
self.conn_map_receive.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn refresh_ports(&mut self) {
|
pub fn refresh_ports(&mut self) {
|
||||||
let ports = self.midi.ports();
|
let ports = self.midi.ports();
|
||||||
for port in ports.iter() {
|
for port in ports.iter() {
|
||||||
|
@ -136,11 +160,28 @@ impl State {
|
||||||
},
|
},
|
||||||
(port.id(), send_queue),
|
(port.id(), send_queue),
|
||||||
) {
|
) {
|
||||||
|
let category = guess_catgory(&name);
|
||||||
|
println!("guessing category:");
|
||||||
|
println!(" name> {name}");
|
||||||
|
println!(" id> {}", port.id());
|
||||||
|
println!(" cat> {category:?}");
|
||||||
|
|
||||||
|
let _ = self.conn_map_send.send((port.id(), category)); // TODO error handler
|
||||||
self.connections.insert(port.id(), conn);
|
self.connections.insert(port.id(), conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn guess_catgory(name: &str) -> Category {
|
||||||
|
if name.contains("TravelSax2") || name.contains("AE-20") {
|
||||||
|
Category::WindSynth
|
||||||
|
} else if name.contains("MultiPad") {
|
||||||
|
Category::Drums
|
||||||
|
} else {
|
||||||
|
Category::Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_message(ts: Timestamp, bytes: &[u8], conn_id: &ConnectionId, tx: &Sender<CTM>) {
|
fn handle_message(ts: Timestamp, bytes: &[u8], conn_id: &ConnectionId, tx: &Sender<CTM>) {
|
||||||
if let Ok((_rem, msg)) = parse_message(bytes) {
|
if let Ok((_rem, msg)) = parse_message(bytes) {
|
||||||
let _ = tx.send((conn_id.clone(), ts, msg));
|
let _ = tx.send((conn_id.clone(), ts, msg));
|
||||||
|
|
|
@ -156,9 +156,7 @@ impl eframe::App for MidiKeysApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MidiDaemon {
|
struct MidiDaemon {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn launch_midi_daemon(target_field: Arc<Mutex<Vec<MidiInputPort>>>) -> JoinHandle<()> {
|
pub fn launch_midi_daemon(target_field: Arc<Mutex<Vec<MidiInputPort>>>) -> JoinHandle<()> {
|
||||||
let daemon_handle = std::thread::spawn(move || midi_daemon(target_field));
|
let daemon_handle = std::thread::spawn(move || midi_daemon(target_field));
|
||||||
|
|
Loading…
Reference in a new issue