tobii-sys 0.2.0

Bindings to the Tobii Stream Engine library for eye tracking.
Documentation
use super::*;
use std::os::raw;
use std::thread;
use std::time;
use std::ffi::CStr;
use std::ptr;

pub struct PtrWrapper<T> {
    ptr: *mut T,
    destroy_fn: unsafe extern "C" fn(ptr: *mut T) -> Status,
}

impl<T> PtrWrapper<T> {
    pub unsafe fn new(ptr: *mut T, destroy_fn: unsafe extern "C" fn(ptr: *mut T) -> Status) -> PtrWrapper<T> {
        PtrWrapper { ptr, destroy_fn }
    }

    pub fn ptr(&self) -> *mut T {
        self.ptr
    }
}

impl<T> Drop for PtrWrapper<T> {
    fn drop(&mut self) {
        let destroy_fn = self.destroy_fn;
        let status = unsafe { destroy_fn(self.ptr) };
        assert_eq!(status, TOBII_ERROR_NO_ERROR);
    }
}

#[derive(Debug,Clone,Copy)]
pub enum TobiiError {
    Internal,
    InsufficientLicense,
    NotSupported,
    NotAvailable,
    ConnectionFailed,
    TimedOut,
    AllocationFailed,
    InvalidParameter,
    CalibrationAlreadyStarted,
    CalibrationNotStarted,
    AlreadySubscribed,
    NotSubscribed,
    OperationFailed,
    ConflictingApiInstances,
    CalibrationBusy,
    CallbackInProgress,
    Unknown(Status),
}

pub fn status_to_result(status: Status) -> Result<(),TobiiError> {
    match status {
        TOBII_ERROR_NO_ERROR => Ok(()),
        TOBII_ERROR_INTERNAL => Err(TobiiError::Internal),
        TOBII_ERROR_INSUFFICIENT_LICENSE => Err(TobiiError::InsufficientLicense),
        TOBII_ERROR_NOT_SUPPORTED => Err(TobiiError::NotSupported),
        TOBII_ERROR_NOT_AVAILABLE => Err(TobiiError::NotAvailable),
        TOBII_ERROR_CONNECTION_FAILED => Err(TobiiError::ConnectionFailed),
        TOBII_ERROR_TIMED_OUT => Err(TobiiError::TimedOut),
        TOBII_ERROR_ALLOCATION_FAILED => Err(TobiiError::AllocationFailed),
        TOBII_ERROR_INVALID_PARAMETER => Err(TobiiError::InvalidParameter),
        TOBII_ERROR_CALIBRATION_ALREADY_STARTED => Err(TobiiError::CalibrationAlreadyStarted),
        TOBII_ERROR_CALIBRATION_NOT_STARTED => Err(TobiiError::CalibrationNotStarted),
        TOBII_ERROR_ALREADY_SUBSCRIBED => Err(TobiiError::AlreadySubscribed),
        TOBII_ERROR_NOT_SUBSCRIBED => Err(TobiiError::NotSubscribed),
        TOBII_ERROR_OPERATION_FAILED => Err(TobiiError::OperationFailed),
        TOBII_ERROR_CONFLICTING_API_INSTANCES => Err(TobiiError::ConflictingApiInstances),
        TOBII_ERROR_CALIBRATION_BUSY => Err(TobiiError::CalibrationBusy),
        TOBII_ERROR_CALLBACK_IN_PROGRESS => Err(TobiiError::CallbackInProgress),
        _ => Err(TobiiError::Unknown(status))
    }
}

pub unsafe fn list_devices(api: *mut Api) -> Result<Vec<String>, TobiiError> {
    unsafe extern "C" fn callback(url: *const raw::c_char, user_data: *mut raw::c_void) {
        let list = &mut *(user_data as *mut Vec<String>);
        let s = CStr::from_ptr(url);
        list.push(s.to_str().unwrap().to_string());
    }

    let mut list: Vec<String> = Vec::new();
    let list_ptr = &mut list as *mut Vec<String>;
    let status = tobii_enumerate_local_device_urls(api, Some(callback), list_ptr as *mut raw::c_void);
    status_to_result(status)?;
    Ok(list)
}

pub unsafe fn reconnect(device: *mut Device) -> Status {
    for _i in 0..40 {
        let status = tobii_device_reconnect(device);
        if status != TOBII_ERROR_CONNECTION_FAILED { return status; }
        thread::sleep(time::Duration::from_millis(250));
    }
    return TOBII_ERROR_CONNECTION_FAILED;
}

pub unsafe fn wait_for_device_callbacks(device: *mut Device) -> Status {
    let ptr_ptr_dev: *const *mut Device = (&device) as *const *mut Device;
    tobii_wait_for_callbacks(ptr::null_mut(), 1, ptr_ptr_dev)
}