Integrate libmonado and use it to pass battery status#229
Integrate libmonado and use it to pass battery status#229jvyden wants to merge 6 commits intoSupreeeme:mainfrom
libmonado and use it to pass battery status#229Conversation
| if let Some(err) = unsafe { err.as_mut() } { | ||
| *err = vr::ETrackedPropertyError::UnknownProperty; | ||
| } |
There was a problem hiding this comment.
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::UnknownProperty; | |
| } |
There was a problem hiding this comment.
i think what we actually want here is ValueNotProvidedByDevice?
There was a problem hiding this comment.
did so in 820fc0e but lmk if you want still want UnknownProperty by default
There was a problem hiding this comment.
it probably doesn't matter in practice, but I don't think returning an error when the battery isn't available makes sense for this property, unsure what SteamVR does
| let Some(d) = self.mnd_get_device_battery(device_index) else { | ||
| if let Some(err) = unsafe { err.as_mut() } { | ||
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | ||
| } | ||
| return 0.0; | ||
| }; | ||
|
|
||
| if !d.present { | ||
| if let Some(err) = unsafe { err.as_mut() } { | ||
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | ||
| } | ||
| return 0.0; | ||
| } | ||
|
|
||
| return d.charge; |
There was a problem hiding this comment.
| let Some(d) = self.mnd_get_device_battery(device_index) else { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return 0.0; | |
| }; | |
| if !d.present { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return 0.0; | |
| } | |
| return d.charge; | |
| let battery = self.mnd_get_device_battery(device_index); | |
| if let Some(charge) = battery.and_then(|b| b.present.then_some(b.charge)) { | |
| return charge; | |
| } else { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return 0.0; | |
| } |
| let Some(d) = self.mnd_get_device_battery(device_index) else { | ||
| if let Some(err) = unsafe { err.as_mut() } { | ||
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | ||
| } | ||
| return false; | ||
| }; | ||
|
|
||
| return d.present; |
There was a problem hiding this comment.
| let Some(d) = self.mnd_get_device_battery(device_index) else { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return false; | |
| }; | |
| return d.present; | |
| if let Some(d) = self.mnd_get_device_battery(device_index) { | |
| return d.present; | |
| } else { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return false; | |
| }; |
| let Some(d) = self.mnd_get_device_battery(device_index) else { | ||
| if let Some(err) = unsafe { err.as_mut() } { | ||
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | ||
| } | ||
| return false; | ||
| }; | ||
|
|
||
| if !d.present { | ||
| if let Some(err) = unsafe { err.as_mut() } { | ||
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| return d.charging; |
There was a problem hiding this comment.
| let Some(d) = self.mnd_get_device_battery(device_index) else { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return false; | |
| }; | |
| if !d.present { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return false; | |
| } | |
| return d.charging; | |
| let battery = self.mnd_get_device_battery(device_index); | |
| if let Some(charging) = battery.and_then(|b| b.present.then_some(b.charging)) { | |
| return charging; | |
| } else { | |
| if let Some(err) = unsafe { err.as_mut() } { | |
| *err = vr::ETrackedPropertyError::ValueNotProvidedByDevice; | |
| } | |
| return false; | |
| } |
| } | ||
|
|
||
| #[cfg(feature = "monado")] | ||
| pub fn mnd_get_device_battery(&self, device_index: u32) -> Option<BatteryStatus> { |
There was a problem hiding this comment.
| pub fn mnd_get_device_battery(&self, device_index: u32) -> Option<BatteryStatus> { | |
| fn mnd_get_device_battery(&self, device_index: u32) -> Option<BatteryStatus> { |
| unsafe impl Send for SafeMonado {} | ||
| unsafe impl Sync for SafeMonado {} |
There was a problem hiding this comment.
This needs a comment explaining why it's done
|
It's important to know that libmonado uses a separate IPC session to communicate with Monado, essentially the same as what libopenxr_monado does. There are 2 major issues with this:
There is an unpublished extension |
Maybe we should have this bumped upstream?
This should be fixed in https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2606 |
|
Monado IPC client increase: https://gitlab.freedesktop.org/monado/monado/-/merge_requests/2644 |
Now merged. |
|
Mind giving this a rebase? |
|
Sure, sorry, forgot about this branch. I should have this up to date tomorrow. |
Closes #26.
Summary
This PR integrates the
libmonadolibrary through thelibmonado-rscrate, the same cratewlx-overlay-sand others use. I've integrated it as an optional (but enabled by default) feature, with the ability for it to be either entirely compiled out or be silently unavailable on startup if we can't find Monado.As a demonstration of usage of the new library, I've also integrated the
DeviceIsCharging_Bool,DeviceProvidesBatteryStatus_Bool, andDeviceBatteryPercentage_Floattracked properties to allow games to observe device battery status.Testing
I've tested this on WiVRn and it seems to work well for headset battery. I do not have a headset that reports controller battery through OpenXR, so I had a friend test it on their Index and it also worked.
In both cases, I've tested in Resonite using the game's built-in scripting language to observe the values reported directly.
Additionally, on WiVRn you need to specify
LIBMONADO_PATHbefore xrizer can connect to Monado from within Proton's container. This seems to work fine on Monado for a reason I'm not sure why, but I've made an issue to track a workaround inlibmonado-rs: technobaboo/libmonado-rs#24Notes
libmonadoin the correct place. Guidance here and with code quality would be appreciated as I'm not familiar with Rust.libmonadois thread-safe, but over the past 3-4 days I've had no issues in release builds with wrapping the library context in aSend/Sync.