feat!: use libmonado to enumerate devices; role to monado string fixes

This commit is contained in:
Gabriele Musco 2023-11-03 20:29:28 +01:00
commit 7266f0b2f0
No known key found for this signature in database
GPG key ID: 1068D795C80E51DE
5 changed files with 88 additions and 67 deletions

View file

@ -33,11 +33,13 @@ cd envision
./dist/appimage/build_appimage.sh ./dist/appimage/build_appimage.sh
``` ```
<!-- no feature flags for now :)
# Feature flags # Feature flags
|Env var|Values|Default| |Env var|Values|Default|
|---|---|---| |---|---|---|
|`ENVISION_FF_USE_LIBMONADO`|`1`: enabled; `0`: disabled|`0`| |`ENVISION_FF_USE_LIBMONADO`|`1`: enabled; `0`: disabled|`0`|
-->
# Common issues # Common issues

View file

@ -3,7 +3,6 @@ use super::alert::alert;
use super::build_window::{BuildStatus, BuildWindow}; use super::build_window::{BuildStatus, BuildWindow};
use super::debug_view::{DebugView, DebugViewMsg}; use super::debug_view::{DebugView, DebugViewMsg};
use super::fbt_config_editor::{FbtConfigEditor, FbtConfigEditorInit, FbtConfigEditorMsg}; use super::fbt_config_editor::{FbtConfigEditor, FbtConfigEditorInit, FbtConfigEditorMsg};
use super::feature_flags::FF_LIBMONADO_DEVICE_ENUMERATION_ENABLED;
use super::job_worker::internal_worker::JobWorkerOut; use super::job_worker::internal_worker::JobWorkerOut;
use super::job_worker::job::WorkerJob; use super::job_worker::job::WorkerJob;
use super::job_worker::JobWorker; use super::job_worker::JobWorker;
@ -343,26 +342,24 @@ impl SimpleComponent for App {
} }
Msg::ClockTicking => { Msg::ClockTicking => {
self.main_view.sender().emit(MainViewMsg::ClockTicking); self.main_view.sender().emit(MainViewMsg::ClockTicking);
if *FF_LIBMONADO_DEVICE_ENUMERATION_ENABLED { if let Some(w) = self.xrservice_worker.as_ref() {
if let Some(w) = self.xrservice_worker.as_ref() { if {
if { let state = w.state.lock().unwrap();
let state = w.state.lock().unwrap(); state.exit_status.is_none() && !state.stop_requested
state.exit_status.is_none() && !state.stop_requested } {
} { if let Some(monado) = self.libmonado.as_ref() {
if let Some(monado) = self.libmonado.as_ref() { self.xr_devices = XRDevice::merge(
self.xr_devices = XRDevice::merge( &self.xr_devices,
&self.xr_devices, &XRDevice::from_libmonado(monado),
&XRDevice::from_libmonado(monado), );
); self.main_view
self.main_view .sender()
.sender() .emit(MainViewMsg::UpdateDevices(self.xr_devices.clone()));
.emit(MainViewMsg::UpdateDevices(self.xr_devices.clone())); } else {
} else { if let Some(so) = self.get_selected_profile().libmonado_so() {
if let Some(so) = self.get_selected_profile().libmonado_so() { self.libmonado = libmonado_rs::Monado::create(so).ok();
self.libmonado = libmonado_rs::Monado::create(so).ok(); if self.libmonado.is_some() {
if self.libmonado.is_some() { sender.input(Msg::ClockTicking);
sender.input(Msg::ClockTicking);
}
} }
} }
} }
@ -374,15 +371,7 @@ impl SimpleComponent for App {
match MonadoLog::new_from_str(row.as_str()) { match MonadoLog::new_from_str(row.as_str()) {
None => {} None => {}
Some(parsed) => { Some(parsed) => {
if !*FF_LIBMONADO_DEVICE_ENUMERATION_ENABLED if let Some(tracker) =
&& parsed.func == "p_create_system"
{
let n_devs = XRDevice::from_log_message(parsed.message.as_str());
self.xr_devices = XRDevice::merge(&self.xr_devices, &n_devs);
self.main_view
.sender()
.emit(MainViewMsg::UpdateDevices(self.xr_devices.clone()));
} else if let Some(tracker) =
XRDevice::generic_tracker_from_log_row(parsed.message.as_str()) XRDevice::generic_tracker_from_log_row(parsed.message.as_str())
{ {
self.xr_devices.push(tracker); self.xr_devices.push(tracker);

View file

@ -4,7 +4,7 @@ use super::{
}; };
use crate::{ use crate::{
file_builders::monado_config_v0::dump_generic_trackers, file_builders::monado_config_v0::dump_generic_trackers,
xr_devices::{XRDevice, XRDeviceType}, xr_devices::{XRDevice, XRDeviceRole},
}; };
use adw::prelude::*; use adw::prelude::*;
use relm4::{factory::AsyncFactoryVecDeque, prelude::*, Sender}; use relm4::{factory::AsyncFactoryVecDeque, prelude::*, Sender};
@ -75,7 +75,7 @@ impl SimpleComponent for DevicesBox {
let mut generic: Vec<&XRDevice> = vec![]; let mut generic: Vec<&XRDevice> = vec![];
for dev in &self.devices { for dev in &self.devices {
match dev.dev_type { match dev.dev_type {
XRDeviceType::Head => { XRDeviceRole::Head => {
has_head = true; has_head = true;
let mut init = DeviceRowModelInit::from_xr_device(&dev); let mut init = DeviceRowModelInit::from_xr_device(&dev);
if dev.name == "Simulated HMD" { if dev.name == "Simulated HMD" {
@ -84,15 +84,15 @@ impl SimpleComponent for DevicesBox {
} }
models.push(init); models.push(init);
} }
XRDeviceType::Left => { XRDeviceRole::Left => {
has_left = true; has_left = true;
models.push(DeviceRowModelInit::from_xr_device(&dev)); models.push(DeviceRowModelInit::from_xr_device(&dev));
} }
XRDeviceType::Right => { XRDeviceRole::Right => {
has_right = true; has_right = true;
models.push(DeviceRowModelInit::from_xr_device(&dev)); models.push(DeviceRowModelInit::from_xr_device(&dev));
} }
XRDeviceType::GenericTracker => { XRDeviceRole::GenericTracker => {
generic.push(dev); generic.push(dev);
} }
_ => { _ => {
@ -102,7 +102,7 @@ impl SimpleComponent for DevicesBox {
} }
if !generic.is_empty() { if !generic.is_empty() {
models.push(DeviceRowModelInit { models.push(DeviceRowModelInit {
title: Some(XRDeviceType::GenericTracker.to_string()), title: Some(XRDeviceRole::GenericTracker.to_string()),
subtitle: Some( subtitle: Some(
generic generic
.iter() .iter()
@ -118,20 +118,20 @@ impl SimpleComponent for DevicesBox {
}); });
} }
if !has_right { if !has_right {
models.push(DeviceRowModelInit::new_missing(XRDeviceType::Right)); models.push(DeviceRowModelInit::new_missing(XRDeviceRole::Right));
} }
if !has_left { if !has_left {
models.push(DeviceRowModelInit::new_missing(XRDeviceType::Left)); models.push(DeviceRowModelInit::new_missing(XRDeviceRole::Left));
} }
if !has_head { if !has_head {
models.push(DeviceRowModelInit::new_missing(XRDeviceType::Head)); models.push(DeviceRowModelInit::new_missing(XRDeviceRole::Head));
} }
models.sort_by(|m1, m2| { models.sort_by(|m1, m2| {
let dt1 = XRDeviceType::from_display_str( let dt1 = XRDeviceRole::from_display_str(
m1.title.as_ref().unwrap_or(&String::new()), m1.title.as_ref().unwrap_or(&String::new()),
); );
let dt2 = XRDeviceType::from_display_str( let dt2 = XRDeviceRole::from_display_str(
m2.title.as_ref().unwrap_or(&String::new()), m2.title.as_ref().unwrap_or(&String::new()),
); );
dt1.cmp(&dt2) dt1.cmp(&dt2)
@ -147,7 +147,7 @@ impl SimpleComponent for DevicesBox {
&self &self
.devices .devices
.iter() .iter()
.filter(|d| d.dev_type == XRDeviceType::GenericTracker) .filter(|d| d.dev_type == XRDeviceRole::GenericTracker)
.map(|d| d.id.clone()) .map(|d| d.id.clone())
.collect::<Vec<String>>(), .collect::<Vec<String>>(),
); );

View file

@ -3,7 +3,7 @@ use relm4::{factory::AsyncFactoryComponent, prelude::*, AsyncFactorySender};
use crate::{ use crate::{
ui::devices_box::DevicesBoxMsg, ui::devices_box::DevicesBoxMsg,
xr_devices::{XRDevice, XRDeviceType}, xr_devices::{XRDevice, XRDeviceRole},
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -62,7 +62,7 @@ impl DeviceRowModelInit {
} }
} }
pub fn new_missing(t: XRDeviceType) -> Self { pub fn new_missing(t: XRDeviceRole) -> Self {
DeviceRowModelInit { DeviceRowModelInit {
title: Some(t.to_string()), title: Some(t.to_string()),
subtitle: Some("None".into()), subtitle: Some("None".into()),

View file

@ -3,7 +3,7 @@ use std::{fmt::Display, slice::Iter};
const GENERIC_TRACKER_PREFIX: &str = "Found generic tracker device: "; const GENERIC_TRACKER_PREFIX: &str = "Found generic tracker device: ";
#[derive(Debug, Clone, PartialEq, Eq, Copy)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum XRDeviceType { pub enum XRDeviceRole {
Head, Head,
Left, Left,
Right, Right,
@ -12,9 +12,19 @@ pub enum XRDeviceType {
HandTrackingLeft, HandTrackingLeft,
HandTrackingRight, HandTrackingRight,
GenericTracker, GenericTracker,
/**
* Devices with no role
*/
Other,
} }
impl Display for XRDeviceType { impl Default for XRDeviceRole {
fn default() -> Self {
Self::Other
}
}
impl Display for XRDeviceRole {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self { f.write_str(match self {
Self::Head => "Head", Self::Head => "Head",
@ -25,23 +35,24 @@ impl Display for XRDeviceType {
Self::HandTrackingLeft => "Hand tracking left", Self::HandTrackingLeft => "Hand tracking left",
Self::HandTrackingRight => "Hand tracking right", Self::HandTrackingRight => "Hand tracking right",
Self::GenericTracker => "Generic tracker", Self::GenericTracker => "Generic tracker",
Self::Other => "",
}) })
} }
} }
impl PartialOrd for XRDeviceType { impl PartialOrd for XRDeviceRole {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.as_number().cmp(&other.as_number())) Some(self.as_number().cmp(&other.as_number()))
} }
} }
impl Ord for XRDeviceType { impl Ord for XRDeviceRole {
fn cmp(&self, other: &Self) -> std::cmp::Ordering { fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap() self.partial_cmp(other).unwrap()
} }
} }
impl XRDeviceType { impl XRDeviceRole {
pub fn iter() -> Iter<'static, Self> { pub fn iter() -> Iter<'static, Self> {
[ [
Self::Head, Self::Head,
@ -63,9 +74,10 @@ impl XRDeviceType {
Self::Right => "right", Self::Right => "right",
Self::Gamepad => "gamepad", Self::Gamepad => "gamepad",
Self::Eyes => "eyes", Self::Eyes => "eyes",
Self::HandTrackingLeft => "hand_tracking.left", Self::HandTrackingLeft => "hand-tracking-left",
Self::HandTrackingRight => "hand_tracking.right", Self::HandTrackingRight => "hand-tracking-right",
Self::GenericTracker => "generic_tracker", Self::GenericTracker => "generic-tracker", // not actually in monado
Self::Other => "other", // not actually in monado
} }
} }
@ -79,6 +91,7 @@ impl XRDeviceType {
Self::HandTrackingLeft => 5, Self::HandTrackingLeft => 5,
Self::HandTrackingRight => 6, Self::HandTrackingRight => 6,
Self::GenericTracker => 7, Self::GenericTracker => 7,
Self::Other => 8,
} }
} }
@ -89,8 +102,8 @@ impl XRDeviceType {
"right" => Some(Self::Right), "right" => Some(Self::Right),
"gamepad" => Some(Self::Gamepad), "gamepad" => Some(Self::Gamepad),
"eyes" => Some(Self::Eyes), "eyes" => Some(Self::Eyes),
"hand_tracking.left" => Some(Self::HandTrackingLeft), "hand-tracking-left" => Some(Self::HandTrackingLeft),
"hand_tracking.right" => Some(Self::HandTrackingRight), "hand-tracking-right" => Some(Self::HandTrackingRight),
_ => None, _ => None,
} }
} }
@ -112,7 +125,7 @@ impl XRDeviceType {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct XRDevice { pub struct XRDevice {
pub dev_type: XRDeviceType, pub dev_type: XRDeviceRole,
pub name: String, pub name: String,
pub id: String, pub id: String,
pub battery: f32, // battery percentage, from 0 to 1 maybe pub battery: f32, // battery percentage, from 0 to 1 maybe
@ -122,7 +135,7 @@ pub struct XRDevice {
impl Default for XRDevice { impl Default for XRDevice {
fn default() -> Self { fn default() -> Self {
Self { Self {
dev_type: XRDeviceType::GenericTracker, dev_type: XRDeviceRole::GenericTracker,
name: String::default(), name: String::default(),
id: String::default(), id: String::default(),
battery: f32::default(), battery: f32::default(),
@ -135,7 +148,7 @@ impl XRDevice {
if s.starts_with(GENERIC_TRACKER_PREFIX) { if s.starts_with(GENERIC_TRACKER_PREFIX) {
let n_tracker = s.trim_start_matches(GENERIC_TRACKER_PREFIX); let n_tracker = s.trim_start_matches(GENERIC_TRACKER_PREFIX);
return Some(Self { return Some(Self {
dev_type: XRDeviceType::GenericTracker, dev_type: XRDeviceRole::GenericTracker,
id: n_tracker.into(), id: n_tracker.into(),
..Default::default() ..Default::default()
}); });
@ -143,14 +156,31 @@ impl XRDevice {
None None
} }
/* pub fn from_libmonado_devices(monado: &libmonado_rs::Monado) -> Vec<Self> {
if let Ok(devs) = monado.devices() {
return devs
.into_iter()
.map(|xrd| Self {
id: xrd.id.to_string(),
name: xrd.name,
..Default::default()
})
.collect();
}
vec![]
} */
pub fn from_libmonado(monado: &libmonado_rs::Monado) -> Vec<Self> { pub fn from_libmonado(monado: &libmonado_rs::Monado) -> Vec<Self> {
let mut res = vec![]; let mut res = vec![];
[ [
XRDeviceType::Head, XRDeviceRole::Head,
XRDeviceType::Left, XRDeviceRole::Left,
XRDeviceType::Right, XRDeviceRole::Right,
XRDeviceType::Gamepad, XRDeviceRole::HandTrackingLeft,
XRDeviceType::Eyes, XRDeviceRole::HandTrackingRight,
XRDeviceRole::Gamepad,
XRDeviceRole::Eyes,
] ]
.iter() .iter()
.for_each(|xrd| { .for_each(|xrd| {
@ -182,7 +212,7 @@ impl XRDevice {
match row.trim().split(": ").collect::<Vec<&str>>()[..] { match row.trim().split(": ").collect::<Vec<&str>>()[..] {
[_, "<none>"] => {} [_, "<none>"] => {}
[dev_type_s, name] => { [dev_type_s, name] => {
if let Some(xrdt) = XRDeviceType::from_monado_str(dev_type_s) { if let Some(xrdt) = XRDeviceRole::from_monado_str(dev_type_s) {
res.push(Self { res.push(Self {
dev_type: xrdt, dev_type: xrdt,
name: name.to_string(), name: name.to_string(),
@ -204,12 +234,12 @@ impl XRDevice {
let new_dev_types = new let new_dev_types = new
.iter() .iter()
.filter_map(|d| { .filter_map(|d| {
if d.dev_type == XRDeviceType::GenericTracker { if d.dev_type == XRDeviceRole::GenericTracker {
return None; return None;
} }
Some(d.dev_type) Some(d.dev_type)
}) })
.collect::<Vec<XRDeviceType>>(); .collect::<Vec<XRDeviceRole>>();
let mut res = old let mut res = old
.iter() .iter()
.filter(|d| !new_dev_types.contains(&d.dev_type)) .filter(|d| !new_dev_types.contains(&d.dev_type))
@ -218,14 +248,14 @@ impl XRDevice {
let old_tracker_ids = old let old_tracker_ids = old
.iter() .iter()
.filter_map(|d| { .filter_map(|d| {
if d.dev_type == XRDeviceType::GenericTracker { if d.dev_type == XRDeviceRole::GenericTracker {
return Some(d.id.clone()); return Some(d.id.clone());
} }
None None
}) })
.collect::<Vec<String>>(); .collect::<Vec<String>>();
for n_dev in new { for n_dev in new {
if n_dev.dev_type == XRDeviceType::GenericTracker { if n_dev.dev_type == XRDeviceRole::GenericTracker {
if !old_tracker_ids.contains(&n_dev.id) { if !old_tracker_ids.contains(&n_dev.id) {
res.push(n_dev.clone()); res.push(n_dev.clone());
} }