purezen/message/send/controller.rs
1//
2// Copyright © 2019 NeoBirth Developers
3//
4// This file is part of PureZen (a fork of ZenGarden)
5//
6// PureZen is free software: you can redistribute it and/or modify
7// it under the terms of the GNU Lesser General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// PureZen is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU Lesser General Public License for more details.
15//
16// You should have received a copy of the GNU Lesser General Public License
17// along with PureZen. If not, see <http://www.gnu.org/licenses/>.
18//
19
20//! Message send controller
21
22use crate::{message::object::connection, pd, Error, ErrorKind};
23use heapless::{self, consts::*, ArrayLength};
24
25/// Special index for referencing the system "pd" receiver
26// TODO(tarcieri): use an enum for this?
27const SYSTEM_NAME_INDEX: usize = 0x7FFF_FFFF;
28
29/// Size of the send stack
30// TODO(tarcieri): chosen completely arbitrarily. Fine tune this
31#[allow(non_camel_case_types)]
32type SEND_STACK_SIZE = U64;
33
34/// Set type used in the internal implementation of `Controller`
35// TODO(tarcieri): find better data structures for this?
36#[derive(Clone, Debug)]
37struct Set<T> {
38 members: heapless::Vec<T, U32>,
39}
40
41impl<T> Set<T> {
42 /// Create a new set
43 pub fn new() -> Self {
44 Set {
45 members: heapless::Vec::new(),
46 }
47 }
48
49 /// Insert an element into this set
50 pub fn insert(&mut self, element: T) {
51 assert!(self.members.push(element).is_ok())
52 }
53
54 /// Erase a value from this set
55 pub fn erase(&mut self, _element: T) {
56 panic!("unimplemented!")
57 }
58}
59
60/// Placeholder for `RemoteMessageReceiver`
61// TODO(tarcieri): translate C++ type
62#[derive(Clone, Debug)]
63pub struct RemoteMessageReceiver {}
64
65impl RemoteMessageReceiver {
66 /// TODO(tarcieri): actually implement this type
67 pub fn receive_message<'pd, N>(
68 &mut self,
69 _index: connection::Index,
70 _message: &pd::Message<'pd, N>,
71 ) where
72 N: ArrayLength<pd::message::Atom<'pd>>,
73 {
74 panic!("unimplemented!")
75 }
76
77 /// TODO(tarcieri): actually implement this type
78 pub fn get_name(&self) -> &str {
79 panic!("unimplemented!")
80 }
81}
82
83/// Message send controller object.
84///
85/// Because of features such as external message injection and implicit
86/// message sending from message boxes, it must be possible to `send` a
87/// message to associated `receive`ers without explicitly requiring a `send`
88/// object to exist in the graph. The `message::send::Controller` is intended
89/// as a central dispatcher for all sent messages, delivering a message to all
90/// associated `receive`ers without requiring the existence of a `send` object.
91///
92/// It can deliver messages via the usual `receive_message()` function, where
93/// the inlet index identifies a receiver name. The index for a receiver name
94/// can be determined with `get_name_index()`. This is useful for messages that
95/// must be scheduled in the global message queue and must then be dispatched
96/// via the `receive_message()` function.
97///
98/// Alternatively, a message can be sent to receivers using `receive_message()`
99/// with name and message arguments (instead of inlet index and message).
100/// Messages sent using this alternative will be sent right away (avoiding the
101/// message queue).
102// TODO(tarcieri): handle previous `MessageObject` superclass behaviors
103#[derive(Clone, Debug)]
104pub struct Controller {
105 // : public MessageObject
106 /// Stack of senders
107 // TODO(zg): explore using a hash table with receiver name keys and `List` values
108 send_stack: heapless::Vec<(heapless::String<U32>, Set<RemoteMessageReceiver>), SEND_STACK_SIZE>,
109
110 /// Set of external receivers
111 external_receiver_set: Set<heapless::String<U32>>,
112}
113
114impl Controller {
115 /// Create a new `message::send::Controller`
116 pub fn new() -> Self {
117 // message::Object(0, 0, NULL) {
118 let send_stack = heapless::Vec::new();
119 let external_receiver_set = Set::new();
120 Controller {
121 send_stack,
122 external_receiver_set,
123 }
124 }
125
126 /// Returns `true` if a receiver by that name is already registered, or
127 /// `false` otherwise.
128 pub fn receiver_exists(&self, receiver_name: &str) -> bool {
129 self.get_name_index(receiver_name).is_some()
130 }
131
132 /// Returns the index to which the given receiver name is referenced.
133 /// Used with `receive_message(usize, &pd::Message<_>)`.
134 pub fn get_name_index(&self, receiver_name: &str) -> Option<connection::Index> {
135 if receiver_name == "pd" {
136 // a special case for sending messages to the system
137 return Some(connection::Index(SYSTEM_NAME_INDEX));
138 }
139
140 for i in 0..self.send_stack.len() {
141 if self.send_stack[i].0 == receiver_name {
142 return Some(connection::Index(i));
143 }
144 }
145
146 None
147 }
148
149 /// Sends the message on to all receivers with the given name
150 pub fn receive_message<'pd, N>(
151 &mut self,
152 context: &mut pd::Context<'pd>,
153 name: &str,
154 message: &pd::Message<'pd, N>,
155 ) where
156 N: ArrayLength<pd::message::Atom<'pd>>,
157 {
158 if let Some(index) = self.get_name_index(name) {
159 // if the receiver name is not registered, nothing to do
160 self.send_message(context, index, message);
161 }
162
163 // check to see if the receiver name has been registered as an external receiver
164 if self
165 .external_receiver_set
166 .members
167 .iter()
168 .any(|member| member.as_str() == name)
169 {
170 // TODO(tarcieri): callback function support
171 // context.callback_function(ZG_RECEIVER_MESSAGE, context.callback_user_data, &(name, message));
172 }
173 }
174
175 /// Send a message to the given outlet index
176 pub fn send_message<'pd, N>(
177 &mut self,
178 context: &mut pd::Context<'pd>,
179 outlet_index: connection::Index,
180 message: &pd::Message<'pd, N>,
181 ) where
182 N: ArrayLength<pd::message::Atom<'pd>>,
183 {
184 if outlet_index == connection::Index(SYSTEM_NAME_INDEX) {
185 context.receive_system_message(message);
186 } else {
187 for receiver in self.send_stack[outlet_index.0].1.members.iter_mut() {
188 receiver.receive_message(connection::Index(0), message);
189 }
190 }
191 }
192
193 /// Add a receiver to this send controller
194 pub fn add_receiver(&mut self, receiver: RemoteMessageReceiver) -> Result<(), Error> {
195 let name_index = match self.get_name_index(receiver.get_name()) {
196 Some(i) => i.0,
197 None => {
198 let mut remote_set = Set::new();
199 remote_set.insert(receiver.clone());
200
201 if self
202 .send_stack
203 .push((receiver.get_name().into(), remote_set))
204 .is_err()
205 {
206 // TODO(tarcieri) is this really the only error case?
207 Err(ErrorKind::BufferOverflow)?;
208 }
209 self.send_stack.len() - 1
210 }
211 };
212
213 self.send_stack[name_index].1.insert(receiver.clone());
214 Ok(())
215 }
216
217 /// Remove a receiver from this send controller
218 // NOTE(mhroth): once the receiver set has been created, it should not
219 // be erased anymore from the send_stack.
220 //
221 // `pd::Context` depends on the `name_index` to be constant for all
222 // receiver names once they are defined, as a message destined for
223 // that receiver may already be in the message queue with the given
224 // index. If the indicies change, then message will be sent to the
225 // wrong receiver set.
226 // TODO(mhroth): This is a stupid constraint. Fix it.
227 pub fn remove_receiver(&mut self, receiver: RemoteMessageReceiver) {
228 if let Some(name_index) = self.get_name_index(receiver.get_name()) {
229 self.send_stack[name_index.0].1.erase(receiver);
230 }
231 }
232
233 /// Register an external message receiver with this send controller
234 pub fn register_external_receiver(&mut self, receiver_name: &str) {
235 // sets only contain unique items
236 self.external_receiver_set.insert(receiver_name.into());
237 }
238
239 /// Unregister an external message receiver from this send controller
240 pub fn unregister_external_receiver(&mut self, _receiver_name: &str) {
241 // TODO(tarcieri): implement this
242 panic!("unimplemented");
243 // self.external_receiver_set.erase(receiver_name);
244 }
245}
246
247impl Default for Controller {
248 fn default() -> Self {
249 Self::new()
250 }
251}