1use crate::context::ConcreteBaseAudioContext;
2use crate::context::{AudioContextState, AudioNodeId};
3use crate::{AudioBuffer, AudioRenderCapacityEvent};
4
5use std::any::Any;
6use std::collections::HashMap;
7use std::hash::Hash;
8use std::ops::ControlFlow;
9use std::sync::{Arc, Mutex};
10
11use crossbeam_channel::Receiver;
12
13#[derive(Debug, Clone)]
15#[non_exhaustive]
16pub struct Event {
17 pub type_: &'static str,
18}
19
20#[derive(Hash, Eq, PartialEq, Debug)]
21pub(crate) enum EventType {
22 Ended(AudioNodeId),
23 SinkChange,
24 StateChange,
25 RenderCapacity,
26 ProcessorError(AudioNodeId),
27 Diagnostics,
28 Message(AudioNodeId),
29 Complete,
30 AudioProcessing(AudioNodeId),
31}
32
33#[non_exhaustive]
35#[derive(Debug)]
36pub struct ErrorEvent {
37 pub message: String,
39 pub error: Box<dyn Any + Send>,
41 pub event: Event,
43}
44
45#[non_exhaustive]
47#[derive(Debug)]
48pub struct AudioProcessingEvent {
49 pub input_buffer: AudioBuffer,
51 pub output_buffer: AudioBuffer,
53 pub playback_time: f64,
56 pub(crate) registration: Option<(ConcreteBaseAudioContext, AudioNodeId)>,
57}
58
59impl Drop for AudioProcessingEvent {
60 fn drop(&mut self) {
61 if let Some((context, id)) = self.registration.take() {
62 let wrapped = crate::message::ControlMessage::NodeMessage {
63 id,
64 msg: llq::Node::new(Box::new(self.output_buffer.clone())),
65 };
66 context.send_control_msg(wrapped);
67 }
68 }
69}
70
71#[non_exhaustive]
73#[derive(Debug)]
74pub struct OfflineAudioCompletionEvent {
75 pub rendered_buffer: AudioBuffer,
77 pub event: Event,
79}
80
81#[derive(Debug)]
82pub(crate) enum EventPayload {
83 None,
84 RenderCapacity(AudioRenderCapacityEvent),
85 ProcessorError(ErrorEvent),
86 Diagnostics(Vec<u8>),
87 Message(Box<dyn Any + Send + 'static>),
88 AudioContextState(AudioContextState),
89 Complete(AudioBuffer),
90 AudioProcessing(AudioProcessingEvent),
91}
92
93#[derive(Debug)]
94pub(crate) struct EventDispatch {
95 type_: EventType,
96 payload: EventPayload,
97}
98
99impl EventDispatch {
100 pub fn ended(id: AudioNodeId) -> Self {
101 EventDispatch {
102 type_: EventType::Ended(id),
103 payload: EventPayload::None,
104 }
105 }
106
107 pub fn sink_change() -> Self {
108 EventDispatch {
109 type_: EventType::SinkChange,
110 payload: EventPayload::None,
111 }
112 }
113
114 pub fn state_change(state: AudioContextState) -> Self {
115 EventDispatch {
116 type_: EventType::StateChange,
117 payload: EventPayload::AudioContextState(state),
118 }
119 }
120
121 pub fn render_capacity(value: AudioRenderCapacityEvent) -> Self {
122 EventDispatch {
123 type_: EventType::RenderCapacity,
124 payload: EventPayload::RenderCapacity(value),
125 }
126 }
127
128 pub fn processor_error(id: AudioNodeId, value: ErrorEvent) -> Self {
129 EventDispatch {
130 type_: EventType::ProcessorError(id),
131 payload: EventPayload::ProcessorError(value),
132 }
133 }
134
135 pub fn diagnostics(value: Vec<u8>) -> Self {
136 EventDispatch {
137 type_: EventType::Diagnostics,
138 payload: EventPayload::Diagnostics(value),
139 }
140 }
141
142 pub fn message(id: AudioNodeId, value: Box<dyn Any + Send + 'static>) -> Self {
143 EventDispatch {
144 type_: EventType::Message(id),
145 payload: EventPayload::Message(value),
146 }
147 }
148
149 pub fn complete(buffer: AudioBuffer) -> Self {
150 EventDispatch {
151 type_: EventType::Complete,
152 payload: EventPayload::Complete(buffer),
153 }
154 }
155
156 pub fn audio_processing(id: AudioNodeId, value: AudioProcessingEvent) -> Self {
157 EventDispatch {
158 type_: EventType::AudioProcessing(id),
159 payload: EventPayload::AudioProcessing(value),
160 }
161 }
162}
163
164pub(crate) enum EventHandler {
165 Once(Box<dyn FnOnce(EventPayload) + Send + 'static>),
166 Multiple(Box<dyn FnMut(EventPayload) + Send + 'static>),
167}
168
169#[derive(Clone)]
170pub(crate) struct EventLoop {
171 event_recv: Receiver<EventDispatch>,
172 event_handlers: Arc<Mutex<HashMap<EventType, EventHandler>>>,
173}
174
175impl EventLoop {
176 pub fn new(event_recv: Receiver<EventDispatch>) -> Self {
177 Self {
178 event_recv,
179 event_handlers: Default::default(),
180 }
181 }
182
183 fn handle_event(&self, mut event: EventDispatch) -> ControlFlow<()> {
184 let mut result = ControlFlow::Continue(());
186 if matches!(
187 event.payload,
188 EventPayload::AudioContextState(AudioContextState::Closed)
189 ) {
190 event.payload = EventPayload::None; result = ControlFlow::Break(());
192 }
193
194 #[cfg(test)]
197 if let EventPayload::ProcessorError(e) = event.payload {
198 panic!("Rethrowing exception during tests: {:?}", e);
199 }
200
201 let mut event_handler_lock = self.event_handlers.lock().unwrap();
202 let callback_option = event_handler_lock.remove(&event.type_);
203 drop(event_handler_lock); if let Some(callback) = callback_option {
206 match callback {
207 EventHandler::Once(f) => (f)(event.payload),
208 EventHandler::Multiple(mut f) => {
209 (f)(event.payload);
210 self.event_handlers
211 .lock()
212 .unwrap()
213 .insert(event.type_, EventHandler::Multiple(f));
214 }
215 };
216 }
217
218 result
219 }
220
221 #[inline(always)]
222 pub fn handle_pending_events(&self) -> bool {
223 let mut events_were_handled = false;
224 for event in self.event_recv.try_iter() {
226 self.handle_event(event);
227 events_were_handled = true;
228 }
229 events_were_handled
230 }
231
232 pub fn run_in_thread(&self) {
233 log::debug!("Entering event thread");
234
235 let self_clone = self.clone();
237
238 std::thread::spawn(move || {
239 for event in self_clone.event_recv.iter() {
241 let result = self_clone.handle_event(event);
242 if result.is_break() {
243 break;
244 }
245 }
246
247 log::debug!("Event loop has terminated");
248 });
249 }
250
251 pub fn set_handler(&self, event: EventType, callback: EventHandler) {
252 self.event_handlers.lock().unwrap().insert(event, callback);
253 }
254
255 pub fn clear_handler(&self, event: EventType) {
256 self.event_handlers.lock().unwrap().remove(&event);
257 }
258}