mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-08-04 15:18:58 +00:00
feat!: use libmonado to enumerate devices; role to monado string fixes
This commit is contained in:
parent
6b567fac5b
commit
7266f0b2f0
5 changed files with 88 additions and 67 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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>>(),
|
||||||
);
|
);
|
||||||
|
|
|
@ -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()),
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue