makepad_audio_graph/
audio_traits.rs1use {
2 std::collections::BTreeMap,
3 crate::{
4 makepad_platform::*,
5 }
6};
7
8
9pub enum AudioComponentAction{
14}
15
16pub trait AudioComponent: LiveApply {
17 fn ref_cast_type_id(&self) -> LiveType where Self: 'static {LiveType::of::<Self>()}
18 fn handle_event_with(&mut self, _cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, AudioComponentAction));
19 fn get_graph_node(&mut self, cx: &mut Cx) -> Box<dyn AudioGraphNode + Send>;
20 fn audio_query(&mut self, _query: &AudioQuery, _callback: &mut Option<AudioQueryCb>) -> AudioResult;
21}
22
23pub trait AudioGraphNode {
24 fn handle_midi_data(&mut self, data: MidiData);
25 fn all_notes_off(&mut self);
26 fn render_to_audio_buffer(
27 &mut self,
28 info: AudioInfo,
29 outputs: &mut [&mut AudioBuffer],
30 inputs: &[&AudioBuffer],
31 display: &mut DisplayAudioGraph
32 );
33}
34
35generate_any_trait_api!(AudioComponent);
36
37
38pub enum ToUIDisplayMsg{
42 DisplayAudio{voice: usize, buffer:AudioBuffer, active:bool},
43 VoiceOff{voice: usize},
44 OutOfBuffers
45}
46
47pub struct DisplayAudioGraph<'a> {
48 pub to_ui: &'a ToUISender<ToUIDisplayMsg>,
49 pub buffers: &'a mut Vec<AudioBuffer>,
50}
51
52impl<'a> DisplayAudioGraph<'a>{
54 pub fn pop_buffer_resize(&mut self, frame_count:usize, channels:usize)->Option<AudioBuffer>{
55 if let Some(mut buf) = self.buffers.pop(){
56 buf.resize(frame_count, channels);
57 return Some(buf)
58 }
59 else{
60 self.to_ui.send(ToUIDisplayMsg::OutOfBuffers).unwrap();
61 None
62 }
63 }
64 pub fn send_buffer(&self, active:bool, voice: usize, buffer:AudioBuffer){
65 self.to_ui.send(ToUIDisplayMsg::DisplayAudio{active, voice, buffer}).unwrap();
66 }
67
68 pub fn send_voice_off(&self, voice: usize){
69 self.to_ui.send(ToUIDisplayMsg::VoiceOff{voice}).unwrap();
70 }
71}
72
73
74#[derive(Default, LiveComponentRegistry)]
75pub struct AudioComponentRegistry {
76 pub map: BTreeMap<LiveType, (LiveComponentInfo, Box<dyn AudioComponentFactory>)>
77}
78
79pub trait AudioComponentFactory {
80 fn new(&self, cx: &mut Cx) -> Box<dyn AudioComponent>;
81}
82
83
84pub struct AudioQueryCb<'a> {
87 pub cb: &'a mut dyn FnMut(&mut Box<dyn AudioComponent >)
88}
89
90impl<'a> AudioQueryCb<'a> {
91 pub fn call(&mut self, args: &mut Box<dyn AudioComponent >) {
92 let cb = &mut self.cb;
93 cb(args)
94 }
95}
96
97pub struct AudioComponentRef(Option<Box<dyn AudioComponent >>);
98
99impl AudioComponentRef {
100 pub fn _as_ref(&mut self) -> Option<&Box<dyn AudioComponent >> {
101 self.0.as_ref()
102 }
103 pub fn as_mut(&mut self) -> Option<&mut Box<dyn AudioComponent >> {
104 self.0.as_mut()
105 }
106
107 pub fn audio_query(&mut self, query: &AudioQuery, callback: &mut Option<AudioQueryCb>) -> AudioResult {
108 if let Some(inner) = &mut self.0 {
109 match query {
110 AudioQuery::TypeId(id) => {
111 if inner.ref_cast_type_id() == *id {
112 if let Some(callback) = callback {
113 callback.call(inner)
114 }
115 else {
116 return AudioResult::found(inner)
117 }
118 }
119 },
120 }
121 inner.audio_query(query, callback)
122 }
123 else {
124 AudioResult::not_found()
125 }
126 }
127}
128
129impl LiveHook for AudioComponentRef {}
130impl LiveApply for AudioComponentRef {
131 fn apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
132 if let LiveValue::Class {live_type, ..} = nodes[index].value {
133 if let Some(component) = &mut self.0 {
134 if component.ref_cast_type_id() != live_type {
135 self.0 = None; }
137 else {
138 return component.apply(cx, apply, index, nodes)
139 }
140 }
141 if let Some(component) = cx.live_registry.clone().borrow()
142 .components.get::<AudioComponentRegistry>().new(cx, live_type) {
143 self.0 = Some(component);
144 return self.0.as_mut().unwrap().apply(cx, apply, index, nodes);
145 }
146 }
147 else if let Some(component) = &mut self.0 {
148 return component.apply(cx, apply, index, nodes);
149 }
150 nodes.skip_node(index)
151 }
152}
153
154impl LiveNew for AudioComponentRef {
155 fn new(_cx: &mut Cx) -> Self {
156 Self (None)
157 }
158
159 fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
160 LiveTypeInfo {
161 module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
162 live_type: LiveType::of::<dyn AudioComponent>(),
163 fields: Vec::new(),
164 live_ignore: true,
165 type_name: LiveId(0)
166 }
167 }
168}
169
170pub enum AudioQuery {
171 TypeId(std::any::TypeId),
172}
173
174pub type AudioResult<'a> = Result<(), &'a mut Box<dyn AudioComponent >>;
175
176pub trait AudioResultApi<'a> {
177 fn not_found() -> AudioResult<'a> {AudioResult::Ok(())}
178 fn found(arg: &'a mut Box<dyn AudioComponent>) -> AudioResult<'a> {AudioResult::Err(arg)}
179 fn is_not_found(&self) -> bool;
180 fn is_found(&self) -> bool;
181 fn into_found(self) -> Option<&'a mut Box<dyn AudioComponent >>;
182}
183impl<'a> AudioResultApi<'a> for AudioResult<'a> {
184
185 fn is_not_found(&self) -> bool {
186 match *self {
187 Result::Ok(_) => true,
188 Result::Err(_) => false
189 }
190 }
191 fn is_found(&self) -> bool {
192 match *self {
193 Result::Ok(_) => false,
194 Result::Err(_) => true
195 }
196 }
197 fn into_found(self) -> Option<&'a mut Box<dyn AudioComponent >> {
198 match self {
199 Result::Ok(_) => None,
200 Result::Err(arg) => Some(arg)
201 }
202 }
203}
204
205#[macro_export]
235macro_rules!register_audio_component {
236 ($cx:ident, $ ty: ident) => {
237 {
238 struct Factory();
239 impl AudioComponentFactory for Factory {
240 fn new(&self, cx: &mut Cx) -> Box<dyn AudioComponent> {
241 Box::new( $ ty::new(cx))
242 }
243 }
244 register_component_factory!($cx, AudioComponentRegistry, $ ty, Factory);
245 }
246 }
247}