diff --git a/libleap/Cargo.toml b/libleap/Cargo.toml index b4f28b1..b4abb17 100644 --- a/libleap/Cargo.toml +++ b/libleap/Cargo.toml @@ -7,4 +7,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -leap-sys = "0.1.1" \ No newline at end of file +leap-sys = "0.1.1" +num = "0.4" +num-derive = "0.3" +num-traits = "0.2" \ No newline at end of file diff --git a/libleap/src/error.rs b/libleap/src/error.rs new file mode 100644 index 0000000..8f33f9e --- /dev/null +++ b/libleap/src/error.rs @@ -0,0 +1,72 @@ +use leap_sys::eLeapRS; + +#[derive(FromPrimitive)] +pub enum LeapError { + /// The operation completed successfully. + Success = 0, + /// An undetermined error has occurred. + /// This is usually the result of an abnormal operating condition in LeapC, + /// the Leap Motion service, or the host computer itself. + UnknownError = -503250944, + /// An invalid argument was specified. + InvalidArgument = -503250943, + /// Insufficient resources existed to complete the request. + InsufficientResources = -503250942, + /// The specified buffer was not large enough to complete the request. + InsufficientBuffer = -503250941, + /// The requested operation has timed out. + Timeout = -503250940, + /// The operation is invalid because there is no current connection. + NotConnected = -503250939, + /// The operation is invalid because the connection is not complete. + HandshakeIncomplete = -503250938, + /// The specified buffer size is too large. + BufferSizeOverflow = -503250937, + /// A communications protocol error occurred. + ProtocolError = -503250936, + /// The server incorrectly specified zero as a client ID. + InvalidClientID = -503250935, + /// The connection to the service was unexpectedly closed while reading or writing a message. + /// The server may have terminated. + UnexpectedClosed = -503250934, + /// The specified request token does not appear to be valid + /// + /// Provided that the token value which identifies the request itself was, at one point, valid, this + /// error condition occurs when the request to which the token refers has already been satisfied or + /// is currently being satisfied. + UnknownImageFrameRequest = -503250933, + /// The specified frame ID is not valid or is no longer valid + /// + /// Provided that frame ID was, at one point, valid, this error condition occurs when the identifier + /// refers to a frame that occurred further in the past than is currently recorded in the rolling + /// frame window. + UnknownTrackingFrameID = -503250932, + /// The specified timestamp references a future point in time + /// + /// The related routine can only operate on time points having occurred in the past, and the + /// provided timestamp occurs in the future. + RoutineIsNotSeer = -503250931, + /// The specified timestamp references a point too far in the past + /// + /// The related routine can only operate on time points occurring within its immediate record of + /// the past. + TimestampTooEarly = -503250930, + /// LeapPollConnection is called concurrently. + ConcurrentPoll = -503250929, + /// A connection to the Leap Motion service could not be established. + NotAvailable = -419364862, + /// The requested operation can only be performed while the device is sending data. + NotStreaming = -419364860, + /// The specified device could not be opened. It is possible that the device identifier + /// is invalid, or that the device has been disconnected since being enumerated. + CannotOpenDevice = -419364859, +} + +impl From for LeapError { + fn from(error: eLeapRS) -> Self { + match num::FromPrimitive::from_i32(error) { + Some(e) => e, + None => Self::UnknownError, + } + } +} diff --git a/libleap/src/event.rs b/libleap/src/event.rs index a2b52d1..b68e8fb 100644 --- a/libleap/src/event.rs +++ b/libleap/src/event.rs @@ -1,3 +1,5 @@ +//! Wrappers for LeapMotion device events + use leap_sys::{ LEAP_CONFIG_CHANGE_EVENT, LEAP_CONFIG_RESPONSE_EVENT, LEAP_CONNECTION_EVENT, LEAP_CONNECTION_LOST_EVENT, LEAP_CONNECTION_MESSAGE, LEAP_DEVICE_EVENT, @@ -6,7 +8,7 @@ use leap_sys::{ }; #[derive(Debug)] -pub enum EventType { +pub enum Event { Invalid, Connection(*const LEAP_CONNECTION_EVENT), ConnectionLost(*const LEAP_CONNECTION_LOST_EVENT), @@ -26,7 +28,7 @@ pub enum EventType { HeadPose(*const LEAP_HEAD_POSE_EVENT), } -impl From for EventType { +impl From for Event { #[allow(non_snake_case)] fn from(message: LEAP_CONNECTION_MESSAGE) -> Self { unsafe { diff --git a/libleap/src/leap_compat.rs b/libleap/src/leap_compat.rs deleted file mode 100644 index 50e0821..0000000 --- a/libleap/src/leap_compat.rs +++ /dev/null @@ -1,71 +0,0 @@ -//! Some cleanup and tweaks to the LeapMotion bindings -//! -//! Since this library binds directly to `leap-sys`, some code -//! is not exactly fun to use. This file contains a few small shorthands -//! and typedefs and stuff - -pub mod types { - use std::ops::{Deref, DerefMut}; - - use leap_sys::LEAP_CONNECTION; - - /// A thin wrapper around `_LEAP_CONNECTION` - pub struct LeapConnection(LEAP_CONNECTION); - - impl Deref for LeapConnection { - type Target = LEAP_CONNECTION; - - fn deref(&self) -> &Self::Target { - &self.0 - } - } - - impl DerefMut for LeapConnection { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } - } - - impl From for LeapConnection { - fn from(c: LEAP_CONNECTION) -> Self { - Self { 0: c } - } - } -} - -pub mod errors { - use leap_sys::eLeapRS; - - /// A generic error, wrapping LeapMotion's `eLeapRS` - #[derive(Debug)] - pub struct GenericLeapError { - pub error: eLeapRS, - } - - impl From for GenericLeapError { - fn from(error: eLeapRS) -> Self { - Self { error } - } - } -} - -pub mod wrappers { - use leap_sys::{LeapCreateConnection, _eLeapRS_eLeapRS_Success}; - - use super::{errors::GenericLeapError, types::LeapConnection}; - - pub unsafe fn create_connection() -> Result { - // Create a handle for the connection - let connection_handle = std::ptr::null_mut(); - - // Call the leap driver - let result = LeapCreateConnection(std::ptr::null(), connection_handle); - - // Handle errors - if result != _eLeapRS_eLeapRS_Success { - return Err(result.into()); - } - - return Ok((*connection_handle).into()); - } -} diff --git a/libleap/src/lib.rs b/libleap/src/lib.rs index fadc4d0..37d0228 100644 --- a/libleap/src/lib.rs +++ b/libleap/src/lib.rs @@ -1,15 +1,97 @@ +#[macro_use] +extern crate num_derive; +use std::{ + sync::{ + mpsc::{self, Sender}, + Arc, + }, + thread::Thread, +}; -// pub mod leap_compat; +use error::LeapError; +use event::Event; +use leap_sys::{ + LeapCreateConnection, LeapOpenConnection, LeapPollConnection, _eLeapRS_eLeapRS_Success, + LEAP_CONNECTION, LEAP_CONNECTION_MESSAGE, +}; +pub mod error; pub mod event; +// Cheaty way to ensure only one LeapDevice is created +static mut LEAP_DEVICE_EXISTS: bool = false; +/// Wrapper around a LeapMotion device pub struct LeapDevice { + /// Device handle + handle: LEAP_CONNECTION, + + /// Storage for incoming messages + latest_message: *mut LEAP_CONNECTION_MESSAGE, } impl LeapDevice { + pub fn new() -> Result { + // Handle being called too many times + unsafe { + if LEAP_DEVICE_EXISTS { + panic!("Tried to call LeapDevice::new() more than once!"); + } + } + // Create a connection handle + let handle = std::ptr::null_mut(); + // Try to create a connection + let result; + unsafe { + result = LeapCreateConnection(std::ptr::null(), handle); + } + if result != _eLeapRS_eLeapRS_Success { + return Err(result.into()); + } + // Try to open a connection + let result; + unsafe { + result = LeapOpenConnection(*handle); + } + if result != _eLeapRS_eLeapRS_Success { + return Err(result.into()); + } + + // Set the device flag + unsafe { + LEAP_DEVICE_EXISTS = true; + } + + unsafe { + Ok(Self { + handle: *handle, + latest_message: std::ptr::null_mut(), + }) + } + } + + pub fn fetch_event(&mut self) -> Result { + // Poll for a new message + let result; + unsafe { + result = LeapPollConnection(self.handle, 1000, self.latest_message); + } + if result != _eLeapRS_eLeapRS_Success { + return Err(result.into()); + } + + unsafe{ + Ok((*self.latest_message).into()) + } + } +} + +impl Drop for LeapDevice { + fn drop(&mut self) { + todo!() + } }