use std::ffi::CString;
use std::os::raw::c_int;
use std::ptr;
use std::time::Duration;
use crate::bindings::{mpr_dev, mpr_dev_free, mpr_dev_get_is_ready, mpr_dev_get_sigs, mpr_dev_new, mpr_dev_poll, mpr_dir, mpr_obj, mpr_prop, mpr_sig_new, mpr_type};
use crate::graph::Graph;
use crate::object::MapperObject;
use crate::signal::Signal;
pub struct Device<'a> {
pub(crate) handle: mpr_dev,
pub(crate) owned: bool,
pub(crate) graph: Option<&'a Graph>
}
unsafe impl Send for Device<'_> {}
unsafe impl Sync for Device<'_> {}
impl Drop for Device<'_> {
fn drop(&mut self) {
if self.owned {
unsafe {
mpr_dev_free(self.handle);
}
}
}
}
impl Device<'_> {
pub fn create(name: &str) -> Device<'_> {
let name_ptr = CString::new(name).expect("CString::new failed");
unsafe {
Device {
owned: true,
handle: mpr_dev_new(name_ptr.as_ptr(), ptr::null_mut()),
graph: None
}
}
}
pub fn create_from_graph<'a>(name: &str, graph: &'a Graph) -> Device<'a> {
let name_ptr = CString::new(name).expect("CString::new failed");
unsafe {
Device {
owned: true,
handle: mpr_dev_new(name_ptr.as_ptr(), graph.handle),
graph: Some(graph)
}
}
}
}
impl Device<'_> {
pub fn poll(&self) {
unsafe {
mpr_dev_poll(self.handle, 0);
}
}
pub fn poll_all(&self) {
unsafe {
mpr_dev_poll(self.handle, -1);
}
}
pub fn poll_and_block(&self, time: Duration) {
unsafe {
mpr_dev_poll(self.handle, time.as_millis() as c_int);
}
}
}
impl Device<'_> {
pub fn is_ready(&self) -> bool {
unsafe {
mpr_dev_get_is_ready(self.handle) > 0
}
}
}
pub trait MappableType {
fn get_mpr_type() -> mpr_type;
}
impl MappableType for f64 {
fn get_mpr_type() -> mpr_type {
mpr_type::MPR_DBL
}
}
impl MappableType for mpr_type {
fn get_mpr_type() -> mpr_type {
mpr_type::MPR_TYPE
}
}
impl MappableType for f32 {
fn get_mpr_type() -> mpr_type {
mpr_type::MPR_FLT
}
}
impl MappableType for i32 {
fn get_mpr_type() -> mpr_type {
mpr_type::MPR_INT32
}
}
impl MappableType for i64 {
fn get_mpr_type() -> mpr_type {
mpr_type::MPR_INT64
}
}
impl<'a> Device<'a> {
pub fn get_graph(&self) -> Option<&'a Graph> {
self.graph
}
}
impl Device<'_> {
pub fn has_shared_graph(&self) -> bool {
self.graph.is_some()
}
pub fn create_signal<T: MappableType + Copy>(&self, name: &str, direction: mpr_dir) -> Signal {
self.create_vector_signal::<T>(name, direction, 1)
}
pub fn create_vector_signal<T: MappableType + Copy>(&self, name: &str, direction: mpr_dir, vector_length: u32) -> Signal {
let data_type: mpr_type = T::get_mpr_type();
let name_ptr = CString::new(name).expect("CString::new failed");
unsafe {
Signal {
handle: mpr_sig_new(self.handle, direction, name_ptr.as_ptr(), vector_length as i32,
data_type, ptr::null(), ptr::null(), ptr::null(), ptr::null_mut(), None, 0),
data_type,
owned: true,
vector_length
}
}
}
pub fn get_signals(&self, direction: mpr_dir) -> Vec<Signal> {
let list = unsafe {mpr_dev_get_sigs(self.handle, direction)};
crate::util::read_list(list, |ptr| {
let data_type = (ptr as mpr_obj).get_property::<mpr_type>(mpr_prop::MPR_PROP_TYPE).unwrap();
let vector_length = (ptr as mpr_obj).get_property::<i32>(mpr_prop::MPR_PROP_LEN).unwrap() as u32;
Signal {
handle: ptr,
data_type,
owned: false,
vector_length
}
})
}
}