lesavka: refresh live eye detection
This commit is contained in:
parent
64f6ab3336
commit
fc38925f0d
@ -4,7 +4,7 @@ path = "src/main.rs"
|
||||
|
||||
[package]
|
||||
name = "lesavka_client"
|
||||
version = "0.11.20"
|
||||
version = "0.11.21"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
|
||||
@ -81,6 +81,7 @@ fn print_state(state: lesavka_common::lesavka::CapturePowerState) {
|
||||
println!("available={}", state.available);
|
||||
println!("enabled={}", state.enabled);
|
||||
println!("mode={}", state.mode);
|
||||
println!("detected_devices={}", state.detected_devices);
|
||||
println!("active_leases={}", state.active_leases);
|
||||
println!("unit={}", state.unit);
|
||||
println!("detail={}", state.detail);
|
||||
|
||||
@ -738,6 +738,8 @@ pub fn run_gui_launcher(server_addr: String) -> Result<()> {
|
||||
let caps_request_in_flight = Rc::new(Cell::new(false));
|
||||
let diagnostics_network = Rc::new(RefCell::new(NetworkTelemetry::default()));
|
||||
let diagnostics_process = Rc::new(RefCell::new(ProcessCpuSampler::new()));
|
||||
let next_power_probe =
|
||||
Rc::new(Cell::new(Instant::now() + Duration::from_millis(500)));
|
||||
let next_diagnostics_probe =
|
||||
Rc::new(Cell::new(Instant::now() + Duration::from_millis(250)));
|
||||
let next_diagnostics_sample =
|
||||
@ -1891,6 +1893,21 @@ pub fn run_gui_launcher(server_addr: String) -> Result<()> {
|
||||
}
|
||||
|
||||
let now = Instant::now();
|
||||
let child_running = child_proc.borrow().is_some();
|
||||
|
||||
if now >= next_power_probe.get()
|
||||
&& !power_request_in_flight.get()
|
||||
&& (child_running
|
||||
|| state.borrow().capture_power.enabled
|
||||
|| state.borrow().remote_active)
|
||||
{
|
||||
power_request_in_flight.set(true);
|
||||
let server_addr =
|
||||
selected_server_addr(&server_entry, server_addr_fallback.as_ref());
|
||||
request_capture_power_refresh(power_tx.clone(), server_addr, Duration::ZERO);
|
||||
next_power_probe.set(now + Duration::from_secs(2));
|
||||
}
|
||||
|
||||
if now >= next_diagnostics_probe.get() && !caps_request_in_flight.get() {
|
||||
caps_request_in_flight.set(true);
|
||||
let server_addr =
|
||||
@ -1915,7 +1932,6 @@ pub fn run_gui_launcher(server_addr: String) -> Result<()> {
|
||||
next_diagnostics_sample.set(now + Duration::from_secs(1));
|
||||
}
|
||||
|
||||
let child_running = child_proc.borrow().is_some();
|
||||
refresh_launcher_ui(&widgets, &state.borrow(), child_running);
|
||||
refresh_test_buttons(&widgets, &mut tests.borrow_mut());
|
||||
glib::ControlFlow::Continue
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "lesavka_common"
|
||||
version = "0.11.20"
|
||||
version = "0.11.21"
|
||||
edition = "2024"
|
||||
build = "build.rs"
|
||||
|
||||
|
||||
@ -17,6 +17,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn banner_includes_version() {
|
||||
assert_eq!(banner("0.11.20"), "lesavka-common CLI (v0.11.20)");
|
||||
assert_eq!(banner("0.11.21"), "lesavka-common CLI (v0.11.21)");
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ bench = false
|
||||
|
||||
[package]
|
||||
name = "lesavka_server"
|
||||
version = "0.11.20"
|
||||
version = "0.11.21"
|
||||
edition = "2024"
|
||||
autobins = false
|
||||
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
#[allow(clippy::useless_attribute)]
|
||||
#[forbid(unsafe_code)]
|
||||
use futures_util::{Stream, StreamExt};
|
||||
use std::collections::HashSet;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
@ -112,15 +113,59 @@ impl Handler {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn detected_capture_devices() -> u32 {
|
||||
fn detected_capture_devices_from_symlinks() -> u32 {
|
||||
["/dev/lesavka_l_eye", "/dev/lesavka_r_eye"]
|
||||
.into_iter()
|
||||
.filter(|path| Path::new(path).exists())
|
||||
.count() as u32
|
||||
}
|
||||
|
||||
fn with_detected_capture_devices(mut state: CapturePowerState) -> CapturePowerState {
|
||||
state.detected_devices = Self::detected_capture_devices();
|
||||
fn detected_capture_devices_from_udev() -> u32 {
|
||||
let Ok(mut enumerator) = udev::Enumerator::new() else {
|
||||
return 0;
|
||||
};
|
||||
let _ = enumerator.match_subsystem("video4linux");
|
||||
let Ok(devices) = enumerator.scan_devices() else {
|
||||
return 0;
|
||||
};
|
||||
devices
|
||||
.filter(|device| {
|
||||
device
|
||||
.attribute_value("index")
|
||||
.and_then(|value| value.to_str())
|
||||
== Some("0")
|
||||
&& device
|
||||
.property_value("ID_VENDOR_ID")
|
||||
.and_then(|value| value.to_str())
|
||||
== Some("07ca")
|
||||
&& device
|
||||
.property_value("ID_MODEL_ID")
|
||||
.and_then(|value| value.to_str())
|
||||
== Some("3311")
|
||||
})
|
||||
.count()
|
||||
.min(2) as u32
|
||||
}
|
||||
|
||||
async fn active_eye_source_count(&self) -> u32 {
|
||||
self.eye_hubs
|
||||
.lock()
|
||||
.await
|
||||
.iter()
|
||||
.filter_map(|(key, hub)| {
|
||||
hub.running
|
||||
.load(Ordering::Relaxed)
|
||||
.then_some(key.source_id)
|
||||
})
|
||||
.collect::<HashSet<_>>()
|
||||
.len()
|
||||
.min(2) as u32
|
||||
}
|
||||
|
||||
async fn with_detected_capture_devices(&self, mut state: CapturePowerState) -> CapturePowerState {
|
||||
state.detected_devices = Self::detected_capture_devices_from_udev()
|
||||
.max(Self::detected_capture_devices_from_symlinks())
|
||||
.max(self.active_eye_source_count().await);
|
||||
state
|
||||
}
|
||||
|
||||
@ -295,12 +340,12 @@ impl Handler {
|
||||
}
|
||||
|
||||
async fn get_capture_power_reply(&self) -> Result<Response<CapturePowerState>, Status> {
|
||||
self.capture_power
|
||||
let state = self
|
||||
.capture_power
|
||||
.snapshot()
|
||||
.await
|
||||
.map(Self::with_detected_capture_devices)
|
||||
.map(Response::new)
|
||||
.map_err(|e| Status::internal(format!("{e:#}")))
|
||||
.map_err(|e| Status::internal(format!("{e:#}")))?;
|
||||
Ok(Response::new(self.with_detected_capture_devices(state).await))
|
||||
}
|
||||
|
||||
async fn set_capture_power_reply(
|
||||
@ -316,10 +361,8 @@ impl Handler {
|
||||
CapturePowerCommand::ForceOff => self.capture_power.set_manual(false).await,
|
||||
CapturePowerCommand::Unspecified => self.capture_power.set_manual(req.enabled).await,
|
||||
};
|
||||
result
|
||||
.map(Self::with_detected_capture_devices)
|
||||
.map(Response::new)
|
||||
.map_err(|e| Status::internal(format!("{e:#}")))
|
||||
let state = result.map_err(|e| Status::internal(format!("{e:#}")))?;
|
||||
Ok(Response::new(self.with_detected_capture_devices(state).await))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user