mod listener;
pub mod image;
mod managed;
mod timestamp;
use image::ImageList;
pub use managed::ManagedController;
pub use timestamp::Timestamp;
use std::{mem::MaybeUninit, ops::Deref};
use leapcpp_sys as sys;
use listener::BoxedListener;
pub use listener::Listener;
pub struct Controller {
sys: Box<sys::Leap_Controller>,
listeners: Vec<Box<BoxedListener>>,
}
impl Controller {
pub fn new() -> Self {
unsafe {
let mut controller = Box::new(MaybeUninit::uninit());
sys::Leap_Controller_Controller1(controller.as_mut_ptr());
Self {
sys: init_box(controller),
listeners: Vec::new(),
}
}
}
pub fn add_listener<L: Listener>(&mut self, listener: L) {
let mut listener = listener::create_rust_listener(listener);
let success = unsafe {
sys::Leap_Controller_addListener(&mut *self.sys, &mut listener.sys as *mut _ as _)
};
if success {
self.listeners.push(listener);
}
}
}
impl Drop for Controller {
fn drop(&mut self) {
unsafe {
sys::Leap_Controller_Controller_destructor(&mut *self.sys);
}
}
}
impl Deref for Controller {
type Target = ControllerRef;
fn deref(&self) -> &Self::Target {
unsafe { ControllerRef::from_raw(&*self.sys) }
}
}
#[repr(transparent)]
pub struct ControllerRef {
sys: sys::Leap_Controller,
}
impl ControllerRef {
unsafe fn from_raw<'a>(sys: *const sys::Leap_Controller) -> &'a Self {
&*(sys as *const _ as *const Self)
}
pub fn is_service_connected(&self) -> bool {
unsafe { sys::Leap_Controller_isServiceConnected(&self.sys) }
}
pub fn is_connected(&self) -> bool {
unsafe { sys::Leap_Controller_isConnected(&self.sys) }
}
pub fn has_focus(&self) -> bool {
unsafe { sys::Leap_Controller_hasFocus(&self.sys) }
}
pub fn set_policy(&self, policy: Policy) {
unsafe {
sys::Leap_Controller_setPolicy(&self.sys, policy as u32);
}
}
pub fn clear_policy(&self, policy: Policy) {
unsafe {
sys::Leap_Controller_clearPolicy(&self.sys, policy as u32);
}
}
pub fn is_policy_set(&self, policy: Policy) -> bool {
unsafe { sys::Leap_Controller_isPolicySet(&self.sys, policy as u32) }
}
pub fn now(&self) -> Timestamp {
let raw = unsafe { sys::Leap_Controller_now(&self.sys) };
Timestamp::from_raw(raw)
}
pub fn frame(&self) -> Frame {
self.frame_at(0)
}
pub fn frame_at(&self, history: u8) -> Frame {
unsafe {
let mut frame = Box::new(MaybeUninit::uninit());
sys::Leap_Controller_frame(frame.as_mut_ptr(), &self.sys, history.into());
Frame {
inner: init_box(frame),
}
}
}
pub fn images(&self) -> ImageList {
unsafe {
let mut images = Box::new(MaybeUninit::uninit());
sys::Leap_Controller_images(images.as_mut_ptr(), &self.sys);
ImageList::from_raw(init_box(images))
}
}
pub fn enable_gesture(&self, gesture: GestureType) {
unsafe {
sys::Leap_Controller_enableGesture(&self.sys, gesture as i32, true);
}
}
pub fn disable_gesture(&self, gesture: GestureType) {
unsafe {
sys::Leap_Controller_enableGesture(&self.sys, gesture as i32, false);
}
}
pub fn is_gesture_enabled(&self, gesture: GestureType) -> bool {
unsafe { sys::Leap_Controller_isGestureEnabled(&self.sys, gesture as i32) }
}
}
#[repr(u32)]
#[non_exhaustive]
pub enum Policy {
BackgroundFrames = sys::Leap_Controller_PolicyFlag_POLICY_BACKGROUND_FRAMES,
Images = sys::Leap_Controller_PolicyFlag_POLICY_IMAGES,
OptimizeHmd = sys::Leap_Controller_PolicyFlag_POLICY_OPTIMIZE_HMD,
}
pub struct Frame {
inner: Box<sys::Leap_Frame>,
}
impl Frame {
pub fn id(&self) -> i64 {
unsafe { sys::Leap_Frame_id(&*self.inner) }
}
pub fn timestamp(&self) -> Timestamp {
let raw = unsafe { sys::Leap_Frame_timestamp(&*self.inner) };
Timestamp::from_raw(raw)
}
pub fn frames_per_second(&self) -> f32 {
unsafe { sys::Leap_Frame_currentFramesPerSecond(&*self.inner) }
}
pub fn is_valid(&self) -> bool {
unsafe { sys::Leap_Frame_isValid(&*self.inner) }
}
}
impl Drop for Frame {
fn drop(&mut self) {
unsafe {
sys::Leap_Interface_Interface_destructor((&mut *self.inner) as *mut _ as _);
}
}
}
unsafe fn init_box<T>(bx: Box<MaybeUninit<T>>) -> Box<T> {
Box::from_raw(Box::into_raw(bx) as *mut T)
}
#[repr(i32)]
#[non_exhaustive]
pub enum GestureType {
Swipe = sys::Leap_Gesture_Type_TYPE_SWIPE,
Circle = sys::Leap_Gesture_Type_TYPE_CIRCLE,
ScreenTap = sys::Leap_Gesture_Type_TYPE_SCREEN_TAP,
KeyTap = sys::Leap_Gesture_Type_TYPE_KEY_TAP,
}
#[repr(i32)]
#[non_exhaustive]
pub enum GestureState {
Start = sys::Leap_Gesture_State_STATE_START,
Update = sys::Leap_Gesture_State_STATE_UPDATE,
Stop = sys::Leap_Gesture_State_STATE_STOP,
}