libmapper_rs/
object.rs

1use std::{ffi::c_void, ptr};
2
3use crate::{bindings::{mpr_obj, mpr_obj_get_prop_by_idx, mpr_obj_get_type, mpr_obj_set_prop, mpr_prop, mpr_type}, device::{Device, MappableType}, graph::Map, signal::Signal};
4
5pub trait AsMprObject {
6  fn as_mpr_object(&self) -> *mut c_void;
7}
8
9impl AsMprObject for Signal {
10  fn as_mpr_object(&self) -> *mut c_void {
11    self.handle as *mut c_void
12  }
13}
14impl AsMprObject for Device<'_> {
15  fn as_mpr_object(&self) -> *mut c_void {
16    self.handle as *mut c_void
17  }
18}
19
20impl AsMprObject for Map {
21  fn as_mpr_object(&self) -> *mut c_void {
22    self.handle as *mut c_void
23  }
24}
25
26impl AsMprObject for mpr_obj {
27  fn as_mpr_object(&self) -> *mut c_void {
28      *self as *mut c_void
29  }
30}
31
32pub trait MapperObject {
33  /// Get the `mpr_type` representing this object
34  fn get_type(&self) -> mpr_type;
35  /// Set a property on this object to a numerical value
36  fn set_property<T: MappableType>(&self, property: mpr_prop, value: T);
37  /// Set a property on this object to a string value
38  fn set_property_str(&self, property: mpr_prop, value: &str);
39
40  /// Get the value of a property by it's key from this object.
41  /// If the property does not exist, or if the type is not matched, this function will return an error.
42  fn get_property<T: MappableType + Copy>(&self, property: mpr_prop) -> Result<T, PropertyError>;
43
44  /// Get the value of a string property by it's key from this object.
45  /// If the property does not exist, or if the type is not matched, this function will return an error.
46  fn get_property_str(&self, property: mpr_prop) -> Result<String, PropertyError>;
47
48  /// Set a user-defined property to the specified value.
49  /// The property is identified by a unique, case-sensitive string key.
50  /// 
51  /// If `publish` is true, the property will be published to other peers. Set to false if this property is only for local use.
52  fn set_custom_property<T: MappableType>(&self, property: &str, value: T, publish: bool);
53}
54
55impl<A> MapperObject for A where A: AsMprObject {
56  fn get_type(&self) -> mpr_type {
57    unsafe {
58      mpr_obj_get_type(self.as_mpr_object())
59    }
60  }
61
62  fn set_property<T: MappableType>(&self, property: mpr_prop, value: T) {
63    unsafe {
64      mpr_obj_set_prop(self.as_mpr_object(), property, ptr::null(), 1, T::get_mpr_type(), &value as *const T as *const c_void, 1);
65    }
66  }
67
68  fn set_property_str(&self, property: mpr_prop, value: &str) {
69    let value_ptr = std::ffi::CString::new(value).expect("CString::new failed");
70    unsafe {
71      mpr_obj_set_prop(self.as_mpr_object(), property, ptr::null(), 1, mpr_type::MPR_STR, value_ptr.as_ptr() as *const c_void, 1);
72    }
73  }
74
75  fn get_property<T: MappableType + Copy>(&self, property: mpr_prop) -> Result<T, PropertyError> {
76    unsafe {
77      let mut actual_type: mpr_type = mpr_type::MPR_NULL;
78      let mut value: *const c_void  = ptr::null();
79      mpr_obj_get_prop_by_idx(self.as_mpr_object(), property as i32,  ptr::null_mut(), ptr::null_mut(), 
80      &mut actual_type, &mut value, ptr::null_mut());
81      if value.is_null() {
82        return Err(PropertyError::PropertyNotFound)
83      }
84      if actual_type != T::get_mpr_type() {
85        return Err(PropertyError::TypeMismatch)
86      }
87      let value = value as *const T;
88      Ok(*value)
89    }
90  }
91
92  fn get_property_str(&self, property: mpr_prop) -> Result<String, PropertyError> {
93    unsafe {
94      let mut actual_type: mpr_type = mpr_type::MPR_NULL;
95      let mut value: *const c_void  = ptr::null();
96      mpr_obj_get_prop_by_idx(self.as_mpr_object(), property as i32,  ptr::null_mut(), ptr::null_mut(), 
97      &mut actual_type, &mut value, ptr::null_mut());
98      if value.is_null() {
99        return Err(PropertyError::PropertyNotFound)
100      }
101      if actual_type != mpr_type::MPR_STR {
102        return Err(PropertyError::TypeMismatch)
103      }
104      let value = value as *const std::os::raw::c_char;
105      let value = std::ffi::CStr::from_ptr(value).to_str().unwrap().to_string();
106      Ok(value)
107    }
108  }
109  
110  fn set_custom_property<T: MappableType>(&self, property: &str, value: T, publish: bool) {
111      let property = std::ffi::CString::new(property).expect("CString::new failed");
112      unsafe {
113        mpr_obj_set_prop(self.as_mpr_object(), mpr_prop::MPR_PROP_EXTRA, property.as_ptr() as *const i8, 
114           1, T::get_mpr_type(), &value as *const T as *const c_void, publish.into());
115      }
116  }
117}
118
119/// Errors that can occur when working with properties
120#[derive(Debug, PartialEq)]
121pub enum PropertyError {
122  /// The property was not found on the object
123  PropertyNotFound,
124  /// The property was found, but the type did not match the expected type
125  TypeMismatch
126}