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}