rearchitechtured for multiple channels

This commit is contained in:
Brad Stein 2025-06-12 01:48:48 -05:00
parent 93991ee9db
commit 08c5230df3
4 changed files with 39 additions and 20 deletions

View File

@ -22,7 +22,8 @@ impl NavkaClientApp {
.nth(1) .nth(1)
.or_else(|| std::env::var("NAVKA_SERVER_ADDR").ok()) .or_else(|| std::env::var("NAVKA_SERVER_ADDR").ok())
.unwrap_or_else(|| "http://127.0.0.1:50051".to_owned()); .unwrap_or_else(|| "http://127.0.0.1:50051".to_owned());
let mut aggregator = InputAggregator::new(dev_mode); let (tx, _rx) = mpsc::channel::<HidReport>(64);
let mut aggregator = InputAggregator::new(dev_mode, tx);
aggregator.init()?; // discover & grab aggregator.init()?; // discover & grab
Ok(Self { Ok(Self {
@ -99,8 +100,8 @@ impl NavkaClientApp {
// fresh channel for aggregator => we do this with new (tx, rx) // fresh channel for aggregator => we do this with new (tx, rx)
let (tx, rx) = mpsc::channel::<HidReport>(64); let (tx, rx) = mpsc::channel::<HidReport>(64);
let mut aggregator = InputAggregator::new(dev_mode, tx.clone()); let _unused = InputAggregator::new(self.dev_mode, tx.clone()); // TODO: wire this up properly
let outbound = ReceiverStream::new(rx); let outbound = ReceiverStream::new(rx);
let response = match client.stream(Request::new(outbound)).await { let response = match client.stream(Request::new(outbound)).await {
Ok(r) => r, Ok(r) => r,
@ -116,7 +117,7 @@ impl NavkaClientApp {
while let Some(res) = inbound.message().await.transpose() { while let Some(res) = inbound.message().await.transpose() {
match res { match res {
Ok(report) => { Ok(report) => {
tracing::debug!(?report.data, "server inbound"); tracing::debug!(?report.kind, "server inbound");
}, },
Err(e) => { Err(e) => {
error!("Inbound error: {e}"); error!("Inbound error: {e}");

View File

@ -3,7 +3,7 @@
use anyhow::{bail, Context, Result}; use anyhow::{bail, Context, Result};
use evdev::{Device, EventType, KeyCode, RelativeAxisCode}; use evdev::{Device, EventType, KeyCode, RelativeAxisCode};
use tokio::time::{interval, Duration}; use tokio::time::{interval, Duration};
use tokio::sync::mpsc::{self, Sender}; use tokio::sync::mpsc::Sender;
use tracing::{debug, info}; use tracing::{debug, info};
use navka_common::navka::HidReport; use navka_common::navka::HidReport;
@ -18,7 +18,7 @@ use crate::input::microphone::MicrophoneCapture;
/// spawns specialized aggregator objects, and can also /// spawns specialized aggregator objects, and can also
/// create stubs for camera/microphone logic if needed. /// create stubs for camera/microphone logic if needed.
pub struct InputAggregator { pub struct InputAggregator {
tx: Sender<HidReport>, tx: Sender<HidReport>,
pub dev_mode: bool, pub dev_mode: bool,
keyboards: Vec<KeyboardAggregator>, keyboards: Vec<KeyboardAggregator>,
mice: Vec<MouseAggregator>, mice: Vec<MouseAggregator>,
@ -27,8 +27,9 @@ pub struct InputAggregator {
} }
impl InputAggregator { impl InputAggregator {
pub fn new(dev_mode: bool) -> Self { pub fn new(dev_mode: bool, tx: Sender<HidReport>) -> Self {
Self { Self {
tx,
dev_mode, dev_mode,
keyboards: Vec::new(), keyboards: Vec::new(),
mice: Vec::new(), mice: Vec::new(),
@ -73,7 +74,7 @@ impl InputAggregator {
// pass dev_mode to aggregator // pass dev_mode to aggregator
// let kbd_agg = KeyboardAggregator::new(dev, self.dev_mode); // let kbd_agg = KeyboardAggregator::new(dev, self.dev_mode);
let kbd_agg = KeyboardAggregator::new(dev.clone(), self.dev_mode, self.tx.clone()); let kbd_agg = KeyboardAggregator::new(dev, self.dev_mode, self.tx.clone());
self.keyboards.push(kbd_agg); self.keyboards.push(kbd_agg);
found_any = true; found_any = true;
continue; continue;
@ -83,7 +84,7 @@ impl InputAggregator {
info!("Grabbed mouse {:?}", dev.name().unwrap_or("UNKNOWN")); info!("Grabbed mouse {:?}", dev.name().unwrap_or("UNKNOWN"));
// let mouse_agg = MouseAggregator::new(dev);np // let mouse_agg = MouseAggregator::new(dev);np
let mouse_agg = MouseAggregator::new(dev.clone(), self.tx.clone()); let mouse_agg = MouseAggregator::new(dev, self.tx.clone());
self.mice.push(mouse_agg); self.mice.push(mouse_agg);
found_any = true; found_any = true;
continue; continue;
@ -124,10 +125,6 @@ impl InputAggregator {
} }
} }
pub fn new(dev_mode: bool, tx: Sender<HidReport>) -> Self {
Self { tx, dev_mode, keyboards: Vec::new(), mice: Vec::new(), camera: None, mic: None }
}
#[derive(Debug)] #[derive(Debug)]
struct Classification { struct Classification {
keyboard: Option<()>, keyboard: Option<()>,

View File

@ -2,7 +2,9 @@
use std::collections::HashSet; use std::collections::HashSet;
use evdev::{Device, InputEvent, KeyCode, EventType}; use evdev::{Device, InputEvent, KeyCode, EventType};
use tokio::sync::mpsc::Sender;
use tracing::{warn, error, info, debug}; use tracing::{warn, error, info, debug};
use navka_common::navka::HidReport;
use crate::input::keymap::{keycode_to_usage, is_modifier}; use crate::input::keymap::{keycode_to_usage, is_modifier};
@ -19,7 +21,7 @@ impl KeyboardAggregator {
let _ = dev.set_nonblocking(true); let _ = dev.set_nonblocking(true);
Self { Self {
dev, dev,
tx: Sender<HidReport>, tx,
dev_mode, dev_mode,
pressed_keys: HashSet::new(), pressed_keys: HashSet::new(),
} }
@ -74,6 +76,7 @@ impl KeyboardAggregator {
// TODO: send this somewhere (e.g. an mpsc::Sender) // TODO: send this somewhere (e.g. an mpsc::Sender)
// For now, just log: // For now, just log:
debug!(?report, "Keyboard HID report"); debug!(?report, "Keyboard HID report");
self.send_report(report);
// optional: magic chord // optional: magic chord
if self.is_magic_chord() { if self.is_magic_chord() {
warn!("Magic chord pressed => exit aggregator??"); warn!("Magic chord pressed => exit aggregator??");
@ -104,9 +107,13 @@ impl KeyboardAggregator {
bytes bytes
} }
let _ = self.tx.try_send(HidReport { fn send_report(&self, report: [u8; 8]) {
kind: Some(navka_common::navka::hid_report::Kind::KeyboardReport(report.to_vec())), let _ = self.tx.try_send(HidReport {
}); kind: Some(navka_common::navka::hid_report::Kind::KeyboardReport(
report.to_vec(),
)),
});
}
fn is_magic_chord(&self) -> bool { fn is_magic_chord(&self) -> bool {
self.pressed_keys.contains(&KeyCode::KEY_LEFTCTRL) self.pressed_keys.contains(&KeyCode::KEY_LEFTCTRL)

View File

@ -1,7 +1,9 @@
// client/src/input/mouse.rs // client/src/input/mouse.rs
use evdev::{Device, InputEvent, EventType, RelativeAxisCode}; use evdev::{Device, InputEvent, EventType, KeyCode, RelativeAxisCode};
use tracing::error; use tokio::sync::mpsc::Sender;
use tracing::{error, debug};
use navka_common::navka::HidReport;
/// Aggregator for a single mouse device /// Aggregator for a single mouse device
pub struct MouseAggregator { pub struct MouseAggregator {
@ -14,11 +16,23 @@ pub struct MouseAggregator {
} }
impl MouseAggregator { impl MouseAggregator {
pub fn new(dev: Device) -> Self { pub fn new(dev: Device, tx: Sender<HidReport>) -> Self {
Self { Self {
dev, dev,
tx,
buttons: 0,
dx: 0, dx: 0,
dy: 0, dy: 0,
wheel: 0,
}
}
/// helper to set or clear a mouse button bit
fn set_btn(&mut self, idx: usize, pressed: bool) {
if pressed {
self.buttons |= 1 << idx;
} else {
self.buttons &= !(1 << idx);
} }
} }