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}