From 9c65d3c5e0008a5e88e221ceafc9b5e0a45149f3 Mon Sep 17 00:00:00 2001 From: cubee Date: Sun, 24 Nov 2024 22:44:47 +1100 Subject: [PATCH] fix osc timer and give battery parameters their own timer --- src/backend/openvr/mod.rs | 2 +- src/backend/osc.rs | 157 ++++++++++++++++++++------------------ 2 files changed, 83 insertions(+), 76 deletions(-) diff --git a/src/backend/openvr/mod.rs b/src/backend/openvr/mod.rs index 1c405cf..9d85ec4 100644 --- a/src/backend/openvr/mod.rs +++ b/src/backend/openvr/mod.rs @@ -324,7 +324,7 @@ pub fn openvr_run(running: Arc, show_by_default: bool) -> Result<(), #[cfg(feature = "osc")] if let Some(ref mut sender) = osc_sender { - let _ = sender.send_params(&overlays, &state); // i love inconsistent naming; in openxr.rs `state` is called `app_state` + let _ = sender.send_params(&overlays, &state); }; #[cfg(feature = "wayvr")] diff --git a/src/backend/osc.rs b/src/backend/osc.rs index b3b1a54..44e9ead 100644 --- a/src/backend/osc.rs +++ b/src/backend/osc.rs @@ -16,7 +16,8 @@ use crate::{ use super::common::OverlayContainer; pub struct OscSender { - last_sent: Instant, + last_sent_overlay: Instant, + last_sent_battery: Instant, upstream: UdpSocket, } @@ -34,7 +35,8 @@ impl OscSender { Ok(Self { upstream, - last_sent: Instant::now(), + last_sent_overlay: Instant::now(), + last_sent_battery: Instant::now(), }) } @@ -55,91 +57,96 @@ impl OscSender { where D: Default, { - if self.last_sent.elapsed().as_millis() < 100 { - return Ok(()); - } + // send overlay data every 0.1 seconds + if self.last_sent_overlay.elapsed().as_millis() >= 100 { + self.last_sent_overlay = Instant::now(); - let mut num_overlays = 0; - let mut has_keyboard = false; - let mut has_wrist = false; + let mut num_overlays = 0; + let mut has_keyboard = false; + let mut has_wrist = false; - for o in overlays.iter() { - if !o.state.want_visible { - continue; - } - match o.state.name.as_ref() { - WATCH_NAME => has_wrist = true, - KEYBOARD_NAME => has_keyboard = true, - _ => { - if o.state.interactable { - num_overlays += 1 + for o in overlays.iter() { + if !o.state.want_visible { + continue; + } + match o.state.name.as_ref() { + WATCH_NAME => has_wrist = true, + KEYBOARD_NAME => has_keyboard = true, + _ => { + if o.state.interactable { + num_overlays += 1 + } } } } + + self.send_message( + "/avatar/parameters/isOverlayOpen".into(), + vec![OscType::Bool(num_overlays > 0)], + )?; + self.send_message( + "/avatar/parameters/isKeyboardOpen".into(), + vec![OscType::Bool(has_keyboard)], + )?; + self.send_message( + "/avatar/parameters/isWristVisible".into(), + vec![OscType::Bool(has_wrist)], + )?; + self.send_message( + "/avatar/parameters/openOverlayCount".into(), + vec![OscType::Int(num_overlays)], + )?; + } - self.send_message( - "/avatar/parameters/isOverlayOpen".into(), - vec![OscType::Bool(num_overlays > 0)], - )?; - self.send_message( - "/avatar/parameters/isKeyboardOpen".into(), - vec![OscType::Bool(has_keyboard)], - )?; - self.send_message( - "/avatar/parameters/isWristVisible".into(), - vec![OscType::Bool(has_wrist)], - )?; - self.send_message( - "/avatar/parameters/openOverlayCount".into(), - vec![OscType::Int(num_overlays)], - )?; - - // battery levels - let mut tracker_idx = 0; - - for device in &app.input_state.devices { - - // soc is the battery level (set to device status.charge) - let level = device.soc.unwrap_or(-1.0); - let parameter; - - match device.role { - TrackedDeviceRole::None => {parameter = String::from("")} - TrackedDeviceRole::Hmd => { - // XSOverlay style (float) - // this parameter doesn't exist, but it's a stepping stone for 0-1 values (i presume XSOverlay would use the full name headset and not the abbreviation hmd) - parameter = String::from("headset"); - - // legacy OVR Toolkit style (int) - // according to their docs, OVR Toolkit is now supposed to use float 0-1. - // as of 20 Nov 2024 they still use int 0-100, but this may change in a future update. - //TODO: remove once their implementation matches the docs - self.send_message( - "/avatar/parameters/hmdBattery".into(), - vec![OscType::Int((level * 100.0f32).round() as i32)], - )?; + // send battery levels every 10 seconds + if self.last_sent_battery.elapsed().as_millis() >= 10000 { + self.last_sent_battery = Instant::now(); + + let mut tracker_idx = 0; + + for device in &app.input_state.devices { + + // soc is the battery level (set to device status.charge) + let level = device.soc.unwrap_or(-1.0); + let parameter; + match device.role { + TrackedDeviceRole::None => {parameter = String::from("")} + TrackedDeviceRole::Hmd => { + // XSOverlay style (float) + // this parameter doesn't exist, but it's a stepping stone for 0-1 values (i presume XSOverlay would use the full name headset and not the abbreviation hmd) + parameter = String::from("headset"); + + // legacy OVR Toolkit style (int) + // according to their docs, OVR Toolkit is now supposed to use float 0-1. + // as of 20 Nov 2024 they still use int 0-100, but this may change in a future update. + //TODO: remove once their implementation matches the docs + self.send_message( + "/avatar/parameters/hmdBattery".into(), + vec![OscType::Int((level * 100.0f32).round() as i32)], + )?; + + } + TrackedDeviceRole::LeftHand => {parameter = String::from("leftController")} + TrackedDeviceRole::RightHand => {parameter = String::from("rightController")} + TrackedDeviceRole::Tracker => {parameter = format!("tracker{tracker_idx}"); tracker_idx += 1;} } - TrackedDeviceRole::LeftHand => {parameter = String::from("leftController")} - TrackedDeviceRole::RightHand => {parameter = String::from("rightController")} - TrackedDeviceRole::Tracker => {parameter = format!("tracker{tracker_idx}"); tracker_idx += 1;} - } - // send battery parameters - if !parameter.is_empty() { - - self.send_message( - format!("/avatar/parameters/{parameter}Battery").into(), - vec![OscType::Float(level)], - )?; - self.send_message( - format!("/avatar/parameters/{parameter}Charging").into(), - vec![OscType::Bool(device.charging)], - )?; + // send battery parameters + if !parameter.is_empty() { + + self.send_message( + format!("/avatar/parameters/{parameter}Battery").into(), + vec![OscType::Float(level)], + )?; + self.send_message( + format!("/avatar/parameters/{parameter}Charging").into(), + vec![OscType::Bool(device.charging)], + )?; + } } } - Ok(()) }