Skip to content

Commit b3977f2

Browse files
committed
Properly emit events from the render thread for offline rendering
1 parent 78432fb commit b3977f2

File tree

7 files changed

+47
-45
lines changed

7 files changed

+47
-45
lines changed

src/context/offline.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ impl OfflineAudioContext {
102102

103103
// Communication channel for events from the render thread to the control thread.
104104
// Use an unbounded channel because we do not require real-time safety.
105-
let event_channel = crossbeam_channel::unbounded();
105+
let (event_send, event_recv) = crossbeam_channel::unbounded();
106106

107107
// setup the render 'thread', which will run inside the control thread
108108
let renderer = RenderThread::new(
@@ -111,6 +111,7 @@ impl OfflineAudioContext {
111111
receiver,
112112
state_clone,
113113
frames_played_clone,
114+
event_send.clone(),
114115
);
115116

116117
// first, setup the base audio context
@@ -120,7 +121,7 @@ impl OfflineAudioContext {
120121
state,
121122
frames_played,
122123
sender,
123-
event_channel,
124+
(event_send, event_recv),
124125
true,
125126
node_id_consumer,
126127
);

src/io/cpal.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,9 @@ impl AudioBackendManager for CpalBackend {
193193
ctrl_msg_recv.clone(),
194194
Arc::clone(&state),
195195
Arc::clone(&frames_played),
196+
event_send.clone(),
196197
);
197-
renderer.set_event_channels(load_value_send.clone(), event_send.clone());
198+
renderer.set_load_value_sender(load_value_send.clone());
198199
renderer.spawn_garbage_collector_thread();
199200

200201
log::debug!(
@@ -235,8 +236,9 @@ impl AudioBackendManager for CpalBackend {
235236
ctrl_msg_recv,
236237
state,
237238
frames_played,
239+
event_send,
238240
);
239-
renderer.set_event_channels(load_value_send, event_send);
241+
renderer.set_load_value_sender(load_value_send);
240242
renderer.spawn_garbage_collector_thread();
241243

242244
let spawned = spawn_output_stream(

src/io/cubeb.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,9 @@ impl AudioBackendManager for CubebBackend {
191191
ctrl_msg_recv,
192192
state,
193193
frames_played,
194+
event_send,
194195
);
195-
renderer.set_event_channels(load_value_send, event_send);
196+
renderer.set_load_value_sender(load_value_send);
196197
renderer.spawn_garbage_collector_thread();
197198

198199
let params = cubeb::StreamParamsBuilder::new()

src/io/none.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ impl AudioBackendManager for NoneBackend {
9494
ctrl_msg_recv,
9595
state,
9696
frames_played,
97+
event_send,
9798
);
98-
render_thread.set_event_channels(load_value_send, event_send);
99+
render_thread.set_load_value_sender(load_value_send);
99100
render_thread.spawn_garbage_collector_thread();
100101

101102
// Use a bounded channel for real-time safety. A maximum of 32 control messages (resume,

src/render/graph.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ mod tests {
750750
current_time: 0.,
751751
sample_rate: 48000.,
752752
node_id: std::cell::Cell::new(AudioNodeId(0)),
753-
event_sender: None,
753+
event_sender: crossbeam_channel::unbounded().0,
754754
};
755755
graph.render(&scope);
756756

@@ -807,7 +807,7 @@ mod tests {
807807
current_time: 0.,
808808
sample_rate: 48000.,
809809
node_id: std::cell::Cell::new(AudioNodeId(0)),
810-
event_sender: None,
810+
event_sender: crossbeam_channel::unbounded().0,
811811
};
812812

813813
// render twice
@@ -875,7 +875,7 @@ mod tests {
875875
current_time: 0.,
876876
sample_rate: 48000.,
877877
node_id: std::cell::Cell::new(AudioNodeId(0)),
878-
event_sender: None,
878+
event_sender: crossbeam_channel::unbounded().0,
879879
};
880880

881881
// render twice
@@ -924,7 +924,7 @@ mod tests {
924924
current_time: 0.,
925925
sample_rate: 48000.,
926926
node_id: std::cell::Cell::new(AudioNodeId(0)),
927-
event_sender: None,
927+
event_sender: crossbeam_channel::unbounded().0,
928928
};
929929
graph.render(&scope);
930930

src/render/processor.rs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub struct AudioWorkletGlobalScope {
2323
pub sample_rate: f32,
2424

2525
pub(crate) node_id: Cell<AudioNodeId>,
26-
pub(crate) event_sender: Option<Sender<EventDispatch>>,
26+
pub(crate) event_sender: Sender<EventDispatch>,
2727
}
2828

2929
impl std::fmt::Debug for AudioWorkletGlobalScope {
@@ -44,17 +44,17 @@ impl AudioWorkletGlobalScope {
4444
/// [`MessagePort`](https://webaudio.github.io/web-audio-api/#dom-audioworkletprocessor-port)
4545
/// `postMessage` functionality of the AudioWorkletProcessor.
4646
pub fn post_message(&self, msg: Box<dyn Any + Send + 'static>) {
47-
if let Some(sender) = self.event_sender.as_ref() {
48-
// sending could fail if the channel is saturated or the main thread is shutting down
49-
let _ = sender.try_send(EventDispatch::message(self.node_id.get(), msg));
50-
}
47+
// sending could fail if the channel is saturated or the main thread is shutting down
48+
let _ = self
49+
.event_sender
50+
.try_send(EventDispatch::message(self.node_id.get(), msg));
5151
}
5252

5353
pub(crate) fn send_ended_event(&self) {
54-
if let Some(sender) = self.event_sender.as_ref() {
55-
// sending could fail if the channel is saturated or the main thread is shutting down
56-
let _ = sender.try_send(EventDispatch::ended(self.node_id.get()));
57-
}
54+
// sending could fail if the channel is saturated or the main thread is shutting down
55+
let _ = self
56+
.event_sender
57+
.try_send(EventDispatch::ended(self.node_id.get()));
5858
}
5959

6060
pub(crate) fn report_error(&self, error: Box<dyn Any + Send>) {
@@ -73,16 +73,16 @@ impl AudioWorkletGlobalScope {
7373
&message
7474
);
7575

76-
if let Some(sender) = self.event_sender.as_ref() {
77-
let event = ErrorEvent {
78-
message,
79-
error,
80-
event: Event {
81-
type_: "ErrorEvent",
82-
},
83-
};
84-
let _ = sender.try_send(EventDispatch::processor_error(self.node_id.get(), event));
85-
}
76+
let event = ErrorEvent {
77+
message,
78+
error,
79+
event: Event {
80+
type_: "ErrorEvent",
81+
},
82+
};
83+
let _ = self
84+
.event_sender
85+
.try_send(EventDispatch::processor_error(self.node_id.get(), event));
8686
}
8787
}
8888

src/render/thread.rs

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub(crate) struct RenderThread {
3939
receiver: Option<Receiver<ControlMessage>>,
4040
buffer_offset: Option<(usize, AudioRenderQuantum)>,
4141
load_value_sender: Option<Sender<AudioRenderCapacityLoad>>,
42-
event_sender: Option<Sender<EventDispatch>>,
42+
event_sender: Sender<EventDispatch>,
4343
garbage_collector: Option<llq::Producer<Box<dyn Any + Send>>>,
4444
}
4545

@@ -72,6 +72,7 @@ impl RenderThread {
7272
receiver: Receiver<ControlMessage>,
7373
state: Arc<AtomicU8>,
7474
frames_played: Arc<AtomicU64>,
75+
event_sender: Sender<EventDispatch>,
7576
) -> Self {
7677
Self {
7778
graph: None,
@@ -84,18 +85,16 @@ impl RenderThread {
8485
receiver: Some(receiver),
8586
buffer_offset: None,
8687
load_value_sender: None,
87-
event_sender: None,
88+
event_sender,
8889
garbage_collector: None,
8990
}
9091
}
9192

92-
pub(crate) fn set_event_channels(
93+
pub(crate) fn set_load_value_sender(
9394
&mut self,
9495
load_value_sender: Sender<AudioRenderCapacityLoad>,
95-
event_sender: Sender<EventDispatch>,
9696
) {
9797
self.load_value_sender = Some(load_value_sender);
98-
self.event_sender = Some(event_sender);
9998
}
10099

101100
pub(crate) fn spawn_garbage_collector_thread(&mut self) {
@@ -174,14 +173,12 @@ impl RenderThread {
174173
}
175174
}
176175
RunDiagnostics { mut buffer } => {
177-
if let Some(sender) = self.event_sender.as_ref() {
178-
use std::io::Write;
179-
writeln!(&mut buffer, "{:#?}", &self).ok();
180-
writeln!(&mut buffer, "{:?}", &self.graph).ok();
181-
sender
182-
.try_send(EventDispatch::diagnostics(buffer))
183-
.expect("Unable to send diagnostics - channel is full");
184-
}
176+
use std::io::Write;
177+
writeln!(&mut buffer, "{:#?}", &self).ok();
178+
writeln!(&mut buffer, "{:?}", &self.graph).ok();
179+
self.event_sender
180+
.try_send(EventDispatch::diagnostics(buffer))
181+
.expect("Unable to send diagnostics - channel is full");
185182
}
186183
Suspend { notify } => {
187184
self.suspended = true;
@@ -460,9 +457,9 @@ impl RenderThread {
460457

461458
fn set_state(&self, state: AudioContextState) {
462459
self.state.store(state as u8, Ordering::Relaxed);
463-
if let Some(sender) = self.event_sender.as_ref() {
464-
sender.try_send(EventDispatch::state_change(state)).ok();
465-
}
460+
self.event_sender
461+
.try_send(EventDispatch::state_change(state))
462+
.ok();
466463
}
467464
}
468465

0 commit comments

Comments
 (0)