implemented error wrapper

This commit is contained in:
Rene Eichhorn
2016-05-06 19:31:04 +02:00
parent f085d27003
commit e89b43216b
7 changed files with 171 additions and 34 deletions

2
Cargo.lock generated
View File

@ -1,6 +1,6 @@
[root] [root]
name = "openvr" name = "openvr"
version = "0.2.0" version = "0.3.0"
dependencies = [ dependencies = [
"glium 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "glium 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"nalgebra 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "nalgebra 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "openvr" name = "openvr"
version = "0.2.0" version = "0.3.0"
authors = [ authors = [
"Colin Sherratt", "Colin Sherratt",
"Erick Tryzelaar", "Erick Tryzelaar",

123
src/error.rs Normal file
View File

@ -0,0 +1,123 @@
use openvr_sys;
use subsystems::*;
pub trait RawError {
fn is_err(&self) -> bool;
fn message(&self) -> String;
}
#[derive(Debug)]
pub struct Error<Err: RawError + Copy> {
raw: Err
}
impl<Err: RawError + Copy> Error<Err> {
/// Creates a new error object using the raw openvr_sys error
pub fn from_raw(raw: Err) -> Self {
Error {
raw: raw
}
}
/// Turns managed error into raw enum from binding
pub fn to_raw(&self) -> Err {
self.raw
}
/// Gets an human-readable error message (if available)
pub fn message(&self) -> String {
self.raw.message()
}
/// Returns true when current object is not an error
pub fn is_ok(&self) -> bool {
!self.raw.is_err()
}
/// Return true when current object is an error
pub fn is_err(&self) -> bool {
self.raw.is_err()
}
}
// OpenVR implement per error type a new function to get a error string
// for easier use, this macro will generate easily the RawError trait
macro_rules! impl_raw_error {
($subsystem:ident, $fntable: ident, $get:ident, $raw_name:ident, $none_name:ident) => {
impl RawError for $raw_name {
fn is_err(&self) -> bool {
match *self {
$none_name => {
true
},
_ => {
false
}
}
}
fn message(&self) -> String {
let sstr = unsafe {
let sub = * { $subsystem().unwrap().0 as *mut openvr_sys::$fntable};
CStr::from_ptr(sub.$get.unwrap()(*self)).to_str().unwrap()
};
String::from(sstr)
}
}
}
}
use std::ffi::CStr;
use openvr_sys::*;
use openvr_sys::Enum_ETrackedPropertyError::*;
use openvr_sys::Enum_EVRInitError::*;
use openvr_sys::Enum_EVRRenderModelError::*;
impl_raw_error!(
system,
Struct_VR_IVRSystem_FnTable,
GetPropErrorNameFromEnum,
ETrackedPropertyError,
ETrackedPropertyError_TrackedProp_Success);
// The init error has some special function to retrieve string
impl RawError for Enum_EVRInitError {
fn is_err(&self) -> bool {
match *self {
EVRInitError_VRInitError_None => {
true
},
_ => {
false
}
}
}
fn message(&self) -> String {
let sstr = unsafe {
CStr::from_ptr(openvr_sys::VR_GetVRInitErrorAsEnglishDescription(*self)).to_str().unwrap()
};
String::from(sstr)
}
}
// RenderModelError has no implementation in 0.1.19 unfortunately
impl RawError for Enum_EVRRenderModelError {
fn is_err(&self) -> bool {
match *self {
EVRRenderModelError_VRRenderModelError_None => {
true
},
_ => {
false
}
}
}
fn message(&self) -> String {
String::from(format!("{:?}", *self))
}
}

View File

@ -5,6 +5,7 @@ pub use openvr_sys::Enum_ETrackedDeviceProperty::*;
pub use openvr_sys::Enum_ETrackedDeviceClass::*; pub use openvr_sys::Enum_ETrackedDeviceClass::*;
pub mod common; pub mod common;
pub mod error;
pub mod tracking; pub mod tracking;
pub mod system; pub mod system;
pub mod extended_display; pub mod extended_display;
@ -18,11 +19,12 @@ pub use compositor::IVRCompositor;
pub use render_models::IVRRenderModels; pub use render_models::IVRRenderModels;
pub use subsystems::*; pub use subsystems::*;
pub use error::*;
pub use common::Eye; pub use common::Eye;
/// Inits the open vr interface and returns the system /// Inits the open vr interface and returns the system
pub fn init() -> Result<system::IVRSystem, openvr_sys::HmdError> { pub fn init() -> Result<system::IVRSystem, Error<openvr_sys::Enum_EVRInitError>> {
let mut err = EVRInitError_VRInitError_None; let mut err = EVRInitError_VRInitError_None;
let app_type = EVRApplicationType_VRApplication_Scene; let app_type = EVRApplicationType_VRApplication_Scene;
@ -46,7 +48,7 @@ pub fn init() -> Result<system::IVRSystem, openvr_sys::HmdError> {
} }
}, },
_ => { _ => {
return Err(err); return Err(Error::from_raw(err));
} }
}; };
} }

View File

@ -5,12 +5,31 @@ use std::string::String;
use std::ptr::null_mut; use std::ptr::null_mut;
use std::slice; use std::slice;
use subsystems::render_models; use subsystems::render_models;
use error::*;
pub struct IVRRenderModels(*const ()); pub struct IVRRenderModels(*const ());
pub struct RenderModel(*mut openvr_sys::RenderModel_t); pub struct RenderModel(*mut openvr_sys::RenderModel_t);
pub struct RenderModelTexture(*mut openvr_sys::RenderModel_TextureMap_t); pub struct RenderModelTexture(*mut openvr_sys::RenderModel_TextureMap_t);
trait AsyncError {
/// checks if result is currently loading
fn is_loading(&self) -> bool;
}
impl AsyncError for Error<openvr_sys::Enum_EVRRenderModelError> {
fn is_loading(&self) -> bool {
match self.to_raw() {
EVRRenderModelError_VRRenderModelError_Loading => {
true
},
_ => {
false
}
}
}
}
impl Drop for RenderModel { impl Drop for RenderModel {
/// will inform openvr that the memory for the render model is no longer required /// will inform openvr that the memory for the render model is no longer required
fn drop (&mut self) { fn drop (&mut self) {
@ -54,7 +73,7 @@ impl RenderModel {
/// asynchronosly loads the texture for the current render model /// asynchronosly loads the texture for the current render model
/// see IVRRenderModels::load_async for info how openvr async work /// see IVRRenderModels::load_async for info how openvr async work
pub fn load_texture_async(&self) -> Result<RenderModelTexture, openvr_sys::Enum_EVRRenderModelError> { pub fn load_texture_async(&self) -> Result<RenderModelTexture, Error<openvr_sys::Enum_EVRRenderModelError>> {
unsafe { unsafe {
let models = * { render_models().unwrap().0 as *mut openvr_sys::Struct_VR_IVRRenderModels_FnTable}; let models = * { render_models().unwrap().0 as *mut openvr_sys::Struct_VR_IVRRenderModels_FnTable};
let mut resp: *mut openvr_sys::RenderModel_TextureMap_t = null_mut(); let mut resp: *mut openvr_sys::RenderModel_TextureMap_t = null_mut();
@ -69,7 +88,7 @@ impl RenderModel {
Ok(RenderModelTexture (resp)) Ok(RenderModelTexture (resp))
}, },
_ => { _ => {
Err(err) Err(Error::from_raw(err))
} }
} }
@ -77,7 +96,7 @@ impl RenderModel {
} }
/// loads the texture for current model /// loads the texture for current model
pub fn load_texture(&self) -> Result<RenderModelTexture, openvr_sys::Enum_EVRRenderModelError> { pub fn load_texture(&self) -> Result<RenderModelTexture, Error<openvr_sys::Enum_EVRRenderModelError>> {
use std; use std;
loop { loop {
@ -87,13 +106,8 @@ impl RenderModel {
return Ok(texture); return Ok(texture);
}, },
Err(err) => { Err(err) => {
match err { if !err.is_loading() {
EVRRenderModelError_VRRenderModelError_Loading => { return Err(err);
// ask again later
},
_ => {
return Err(err);
}
} }
} }
} }
@ -158,7 +172,7 @@ impl IVRRenderModels {
/// Loads an render model into local memory /// Loads an render model into local memory
/// blocks the thread and waits until driver responds with model /// blocks the thread and waits until driver responds with model
pub fn load(&self, name: String) -> Result<RenderModel, openvr_sys::EVRRenderModelError> { pub fn load(&self, name: String) -> Result<RenderModel, Error<openvr_sys::EVRRenderModelError>> {
use std; use std;
loop { loop {
@ -168,13 +182,8 @@ impl IVRRenderModels {
return Ok(model); return Ok(model);
}, },
Err(err) => { Err(err) => {
match err { if !err.is_loading() {
EVRRenderModelError_VRRenderModelError_Loading => { return Err(err);
// ask again later
},
_ => {
return Err(err);
}
} }
} }
} }
@ -186,7 +195,7 @@ impl IVRRenderModels {
/// When called for the first time openvr will start to load the model into memory /// When called for the first time openvr will start to load the model into memory
/// In the mean time this call will respond with EVRRenderModelError_VRRenderModelError_Loading /// In the mean time this call will respond with EVRRenderModelError_VRRenderModelError_Loading
/// It is designed to be used wihtin the render loop as it won't block the user, for sync usage use load() /// It is designed to be used wihtin the render loop as it won't block the user, for sync usage use load()
pub fn load_async(&self, name: String) -> Result<RenderModel, openvr_sys::EVRRenderModelError> { pub fn load_async(&self, name: String) -> Result<RenderModel, Error<openvr_sys::EVRRenderModelError>> {
use std; use std;
unsafe { unsafe {
@ -207,7 +216,7 @@ impl IVRRenderModels {
Ok(RenderModel ( resp )) Ok(RenderModel ( resp ))
}, },
_ => { _ => {
Err(err) Err(Error::from_raw(err))
} }
} }

View File

@ -1,6 +1,7 @@
extern crate openvr_sys; extern crate openvr_sys;
use openvr_sys::Enum_EVRInitError::*; use openvr_sys::Enum_EVRInitError::*;
use error::*;
use system::IVRSystem; use system::IVRSystem;
use extended_display::IVRExtendedDisplay; use extended_display::IVRExtendedDisplay;
use compositor::IVRCompositor; use compositor::IVRCompositor;
@ -9,7 +10,7 @@ use render_models::IVRRenderModels;
use std; use std;
/// gets the current vr system interface (initialization is required beforehand) /// gets the current vr system interface (initialization is required beforehand)
pub fn system() -> Result<IVRSystem, openvr_sys::HmdError> { pub fn system() -> Result<IVRSystem, Error<openvr_sys::Enum_EVRInitError>> {
let mut err = EVRInitError_VRInitError_None; let mut err = EVRInitError_VRInitError_None;
let name = std::ffi::CString::new("FnTable:IVRSystem_012").unwrap(); let name = std::ffi::CString::new("FnTable:IVRSystem_012").unwrap();
let ptr = unsafe { let ptr = unsafe {
@ -23,13 +24,13 @@ pub fn system() -> Result<IVRSystem, openvr_sys::HmdError> {
} }
}, },
_ => { _ => {
return Err(err); return Err(Error::from_raw(err));
} }
} }
} }
/// gets the current vr extended display interface (initialization is required beforehand) /// gets the current vr extended display interface (initialization is required beforehand)
pub fn extended_display() -> Result<IVRExtendedDisplay, openvr_sys::HmdError> { pub fn extended_display() -> Result<IVRExtendedDisplay, Error<openvr_sys::Enum_EVRInitError>> {
let mut err = EVRInitError_VRInitError_None; let mut err = EVRInitError_VRInitError_None;
let name = std::ffi::CString::new("FnTable:IVRExtendedDisplay_001").unwrap(); let name = std::ffi::CString::new("FnTable:IVRExtendedDisplay_001").unwrap();
let ptr = unsafe { let ptr = unsafe {
@ -43,13 +44,13 @@ pub fn extended_display() -> Result<IVRExtendedDisplay, openvr_sys::HmdError> {
} }
}, },
_ => { _ => {
return Err(err); return Err(Error::from_raw(err));
} }
} }
} }
/// gets the current vr extended display interface (initialization is required beforehand) /// gets the current vr extended display interface (initialization is required beforehand)
pub fn compositor() -> Result<IVRCompositor, openvr_sys::HmdError> { pub fn compositor() -> Result<IVRCompositor, Error<openvr_sys::Enum_EVRInitError>> {
let mut err = EVRInitError_VRInitError_None; let mut err = EVRInitError_VRInitError_None;
let name = std::ffi::CString::new("FnTable:IVRCompositor_013").unwrap(); let name = std::ffi::CString::new("FnTable:IVRCompositor_013").unwrap();
let ptr = unsafe { let ptr = unsafe {
@ -63,13 +64,13 @@ pub fn compositor() -> Result<IVRCompositor, openvr_sys::HmdError> {
} }
}, },
_ => { _ => {
return Err(err); return Err(Error::from_raw(err));
} }
} }
} }
/// gets the current vr extended display interface (initialization is required beforehand) /// gets the current vr extended display interface (initialization is required beforehand)
pub fn render_models() -> Result<IVRRenderModels, openvr_sys::HmdError> { pub fn render_models() -> Result<IVRRenderModels, Error<openvr_sys::Enum_EVRInitError>> {
let mut err = EVRInitError_VRInitError_None; let mut err = EVRInitError_VRInitError_None;
let name = std::ffi::CString::new("FnTable:IVRRenderModels_005").unwrap(); let name = std::ffi::CString::new("FnTable:IVRRenderModels_005").unwrap();
let ptr = unsafe { let ptr = unsafe {
@ -83,7 +84,7 @@ pub fn render_models() -> Result<IVRRenderModels, openvr_sys::HmdError> {
} }
}, },
_ => { _ => {
return Err(err); return Err(Error::from_raw(err));
} }
} }
} }

View File

@ -1,6 +1,8 @@
use openvr_sys; use openvr_sys;
use openvr_sys::Enum_ETrackedPropertyError::*; use openvr_sys::Enum_ETrackedPropertyError::*;
use subsystems::*; use subsystems::*;
use error::*;
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct TrackedDevicePose { pub struct TrackedDevicePose {
@ -22,7 +24,7 @@ impl TrackedDevicePose {
} }
/// gets a propery as a string /// gets a propery as a string
pub fn get_property_string(&self, property: openvr_sys::Enum_ETrackedDeviceProperty) -> Result<String, openvr_sys::Enum_ETrackedPropertyError> { pub fn get_property_string(&self, property: openvr_sys::Enum_ETrackedDeviceProperty) -> Result<String, Error<openvr_sys::Enum_ETrackedPropertyError>> {
unsafe { unsafe {
let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable}; let system = * { system().unwrap().0 as *mut openvr_sys::Struct_VR_IVRSystem_FnTable};
@ -40,7 +42,7 @@ impl TrackedDevicePose {
if size > 0 { if size > 0 {
return Ok(String::from_raw_parts(val_out.as_ptr() as *mut _, (size - 1) as usize, (size - 1) as usize)); return Ok(String::from_raw_parts(val_out.as_ptr() as *mut _, (size - 1) as usize, (size - 1) as usize));
} else { } else {
return Err(err); return Err(Error::from_raw(err));
} }
} }
} }