1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
use std::ffi::c_void;
use crate::{bindings::{mpr_sig, mpr_sig_free, mpr_sig_get_inst_status, mpr_sig_get_value, mpr_status, mpr_sig_set_value, mpr_type}, device::MappableType};
pub struct Signal {
pub(crate) handle: mpr_sig,
pub(crate) owned: bool,
pub(crate) data_type: mpr_type,
pub(crate) vector_length: u32
}
unsafe impl Send for Signal {}
unsafe impl Sync for Signal {}
impl Drop for Signal {
fn drop(&mut self) {
if self.owned {
unsafe {
mpr_sig_free(self.handle);
}
}
}
}
/// An error that can occur when getting or setting the value of a signal.
#[derive(Debug)]
pub enum SignalError {
#[doc = "The data type of the signal does not match the type of the passed generic type."]
WrongType,
#[doc = "The signal does not have a value set yet."]
NoValue,
#[doc = "The length of the passed slice does not match the vector length of the signal."]
WrongLengthArg
}
impl Signal {
/// Get the status of the signal instance.
/// Calling this function will reset the flags `was_set_remote` and `was_set_local` and return their pre-reset values.
///
/// # Examples
/// Use this function to check if you should push or read data from the signal:
/// ```
/// use libmapper_rs::device::Device;
/// use libmapper_rs::signal::Signal;
/// use std::time::Duration;
/// fn main_loop(dev: &Device, sig: &mut Signal, value: &mut f64) {
/// loop {
/// dev.poll_and_block(Duration::from_millis(10));
///
/// if sig.get_status().was_set_remote() { // check if there's a new value waiting for us
/// let (new_value, _) = sig.get_value_single::<f64>().unwrap();
/// *value = new_value;
/// } else {
/// sig.set_value_single(value);
/// }
/// }
/// }
/// ```
pub fn get_status(&self) -> SignalStatus {
SignalStatus(unsafe {
mpr_sig_get_inst_status(self.handle, 0)
})
}
/// Get the type of data this signal is storing.
pub fn get_data_type(&self) -> mpr_type {
self.data_type
}
/// Get the length of the vector this signal is storing.
/// This will be how long the slice returned from Signal::get_value is.
///
/// If this is 1, you should use Signal::get_value_single instead.
pub fn get_vector_length(&self) -> u32 {
self.vector_length
}
}
/// A struct that represents the status of a signal instance.
/// When this struct is created by Signal::get_status(), the flags `was_set_remote` and `was_set_local` will be reset.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct SignalStatus(i32);
impl SignalStatus {
/// Returns true if the signal was set remotely since the last time the status was queried.
pub fn was_set_remote(&self) -> bool {
self.0 & mpr_status::MPR_STATUS_UPDATE_REM as i32 != 0
}
/// Returns true if the signal was set locally since the last time the status was queried.
pub fn was_set_local(&self) -> bool {
self.0 & mpr_status::MPR_STATUS_UPDATE_LOC as i32 != 0
}
/// Returns true if the signal has a value (i.e. Signal::get_value* will return Some).
pub fn has_value(&self) -> bool {
self.0 & mpr_status::MPR_STATUS_HAS_VALUE as i32 != 0
}
/// If the signal is active
pub fn is_active(&self) -> bool {
self.0 & mpr_status::MPR_STATUS_ACTIVE as i32 != 0
}
/// If the actual numerical value of the signal has changed since the last time the status was queried.
pub fn value_updated(&self) -> bool {
self.0 & mpr_status::MPR_STATUS_NEW_VALUE as i32 != 0
}
}
impl Signal {
/// Set the value of the signal.
/// This function will return [`SignalError::WrongType`](SignalError:WrongType) if the passed generic type doesn't match the signal's type.
///
/// If this signal is a vector, only the first element of the vector will be set.
pub fn set_value_single<T: MappableType + Copy>(&mut self, value: &T) -> Result<(), SignalError> {
if T::get_mpr_type() != self.data_type {
return Err(SignalError::WrongType);
}
unsafe {
mpr_sig_set_value(self.handle, 0, 1, self.data_type, value as *const T as *const c_void);
}
Ok(())
}
/// Get the value of the signal.
/// This function will return [`SignalError::WrongType`](SignalError:WrongType) if the passed generic type doesn't match the signal's type.
///
/// If this signal is a vector, only the first element of the vector will be returned.
pub fn get_value_single<T: MappableType + Copy>(&self) -> Result<(T, u64), SignalError> {
let mut time = 0;
if T::get_mpr_type() != self.data_type {
return Err(SignalError::WrongType);
}
unsafe {
let ptr = mpr_sig_get_value(self.handle, 0, &mut time);
if ptr.is_null() {
return Err(SignalError::NoValue);
}
let value = *(ptr as *const T);
Ok((value, time))
}
}
/// Get the value of the signal.
/// This function will return [`SignalError::WrongType`](SignalError:WrongType) if the passed generic type doesn't match the signal's type.
///
/// The length of the returned slice will be equal to the value returned by [get_vector_length](Signal::get_vector_length).
pub fn get_value<T: MappableType + Copy>(&self) -> Result<(Vec<T>, u64), SignalError> {
let mut time = 0;
if T::get_mpr_type() != self.data_type {
return Err(SignalError::WrongType);
}
unsafe {
let ptr = mpr_sig_get_value(self.handle, 0, &mut time);
if ptr.is_null() {
return Err(SignalError::NoValue);
}
let slice = std::slice::from_raw_parts(ptr as *const T, self.vector_length as usize);
Ok((slice.to_vec(), time))
}
}
/// Set the value of the signal.
/// This function will return [`SignalError::WrongType`](SignalError:WrongType) if the passed generic type doesn't match the signal's type.
///
/// The length of the slice must be equal to the value returned by [get_vector_length](Signal::get_vector_length).
/// If the lengths are not equal this function return an `Err` of `SignalError::WrongLengthArg`.
pub fn set_value<T: MappableType + Copy>(&mut self, values: &[T]) -> Result<(), SignalError> {
if T::get_mpr_type() != self.data_type {
return Err(SignalError::WrongType);
}
if values.len() != self.vector_length as usize {
return Err(SignalError::WrongLengthArg);
}
unsafe {
mpr_sig_set_value(self.handle, 0, self.vector_length as i32, self.data_type, values.as_ptr() as *const c_void);
}
Ok(())
}
}