libmapper_rs/
signal.rs

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