Skip to content

Commit 67edea9

Browse files
committed
Terminate the event loop when the audio context is closing
Fixes #421
1 parent e4a0a51 commit 67edea9

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

src/context/concrete_base.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,14 @@ impl ConcreteBaseAudioContext {
356356

357357
/// Updates state of current context
358358
pub(super) fn set_state(&self, state: AudioContextState) {
359+
// Only to be used from OfflineAudioContext, the online one should emit the state changes
360+
// from the render thread
361+
debug_assert!(self.offline());
362+
359363
let current_state = self.state();
360364
if current_state != state {
361365
self.inner.state.store(state as u8, Ordering::Release);
362-
let _ = self.send_event(EventDispatch::state_change());
366+
let _ = self.send_event(EventDispatch::state_change(state));
363367
}
364368
}
365369

src/events.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::context::AudioNodeId;
1+
use crate::context::{AudioContextState, AudioNodeId};
22
use crate::{AudioBuffer, AudioRenderCapacityEvent};
33

44
use std::any::Any;
@@ -55,6 +55,7 @@ pub(crate) enum EventPayload {
5555
ProcessorError(ErrorEvent),
5656
Diagnostics(Vec<u8>),
5757
Message(Box<dyn Any + Send + 'static>),
58+
AudioContextState(AudioContextState),
5859
}
5960

6061
#[derive(Debug)]
@@ -78,10 +79,10 @@ impl EventDispatch {
7879
}
7980
}
8081

81-
pub fn state_change() -> Self {
82+
pub fn state_change(state: AudioContextState) -> Self {
8283
EventDispatch {
8384
type_: EventType::StateChange,
84-
payload: EventPayload::None,
85+
payload: EventPayload::AudioContextState(state),
8586
}
8687
}
8788

@@ -130,11 +131,22 @@ impl EventLoop {
130131
}
131132

132133
pub fn run(&self, event_channel: Receiver<EventDispatch>) {
134+
log::debug!("Entering event loop");
133135
let self_clone = self.clone();
134136

135-
std::thread::spawn(move || loop {
136-
// this thread is dedicated to event handling so we can block
137-
for event in event_channel.iter() {
137+
std::thread::spawn(move || {
138+
// This thread is dedicated to event handling so we can block
139+
for mut event in event_channel.iter() {
140+
// Terminate the event loop when the audio context is closing
141+
let mut terminate = false;
142+
if matches!(
143+
event.payload,
144+
EventPayload::AudioContextState(AudioContextState::Closed)
145+
) {
146+
event.payload = EventPayload::None; // the statechange handler takes no argument
147+
terminate = true;
148+
}
149+
138150
let mut event_handler_lock = self_clone.event_handlers.lock().unwrap();
139151
let callback_option = event_handler_lock.remove(&event.type_);
140152
drop(event_handler_lock); // release Mutex while running callback
@@ -152,7 +164,13 @@ impl EventLoop {
152164
}
153165
};
154166
}
167+
168+
if terminate {
169+
break;
170+
}
155171
}
172+
173+
log::debug!("Event loop has terminated");
156174
});
157175
}
158176

src/render/thread.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ impl RenderThread {
461461
fn set_state(&self, state: AudioContextState) {
462462
self.state.store(state as u8, Ordering::Relaxed);
463463
if let Some(sender) = self.event_sender.as_ref() {
464-
sender.try_send(EventDispatch::state_change()).ok();
464+
sender.try_send(EventDispatch::state_change(state)).ok();
465465
}
466466
}
467467
}

0 commit comments

Comments
 (0)