mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Workaround resume issues
This commit is contained in:
parent
cdd7995d34
commit
1c2d872e33
3 changed files with 27 additions and 20 deletions
|
@ -46,11 +46,8 @@ impl AudioContext {
|
||||||
// servo-media takes care of setting the default sample rate of the output device
|
// servo-media takes care of setting the default sample rate of the output device
|
||||||
// and of resampling the audio output if needed.
|
// and of resampling the audio output if needed.
|
||||||
|
|
||||||
// Step 5.
|
// Steps 5 and 6 of the construction algorithm will happen in `resume`,
|
||||||
if context.is_allowed_to_start() {
|
// after reflecting dom object.
|
||||||
// Step 6.
|
|
||||||
context.resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioContext {
|
AudioContext {
|
||||||
context,
|
context,
|
||||||
|
@ -64,7 +61,9 @@ impl AudioContext {
|
||||||
pub fn new(global: &GlobalScope,
|
pub fn new(global: &GlobalScope,
|
||||||
options: &AudioContextOptions) -> DomRoot<AudioContext> {
|
options: &AudioContextOptions) -> DomRoot<AudioContext> {
|
||||||
let context = AudioContext::new_inherited(global, options);
|
let context = AudioContext::new_inherited(global, options);
|
||||||
reflect_dom_object(Box::new(context), global, AudioContextBinding::Wrap)
|
let context = reflect_dom_object(Box::new(context), global, AudioContextBinding::Wrap);
|
||||||
|
context.resume();
|
||||||
|
context
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
||||||
|
@ -73,6 +72,14 @@ impl AudioContext {
|
||||||
let global = window.upcast::<GlobalScope>();
|
let global = window.upcast::<GlobalScope>();
|
||||||
Ok(AudioContext::new(global, options))
|
Ok(AudioContext::new(global, options))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn resume(&self) {
|
||||||
|
// Step 5.
|
||||||
|
if self.context.is_allowed_to_start() {
|
||||||
|
// Step 6.
|
||||||
|
self.context.resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioContextMethods for AudioContext {
|
impl AudioContextMethods for AudioContext {
|
||||||
|
|
|
@ -65,8 +65,8 @@ impl AudioNodeMethods for AudioNode {
|
||||||
destination: &AudioNode,
|
destination: &AudioNode,
|
||||||
output: u32,
|
output: u32,
|
||||||
input: u32) -> Fallible<DomRoot<AudioNode>> {
|
input: u32) -> Fallible<DomRoot<AudioNode>> {
|
||||||
if self.context != destination.Context() {
|
if *(self.context) != *(destination.Context()) {
|
||||||
return Err(Error::InvalidAccess);
|
//XXX return Err(Error::InvalidAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
if output >= self.NumberOfOutputs() ||
|
if output >= self.NumberOfOutputs() ||
|
||||||
|
@ -74,6 +74,8 @@ impl AudioNodeMethods for AudioNode {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX Check previous connections.
|
||||||
|
|
||||||
self.context.audio_context_impl().connect_ports(
|
self.context.audio_context_impl().connect_ports(
|
||||||
self.node().output(output), destination.node().input(input)
|
self.node().output(output), destination.node().input(input)
|
||||||
);
|
);
|
||||||
|
|
|
@ -15,6 +15,7 @@ use dom::bindings::num::Finite;
|
||||||
use dom::bindings::refcounted::Trusted;
|
use dom::bindings::refcounted::Trusted;
|
||||||
use dom::bindings::reflector::{DomObject, Reflector};
|
use dom::bindings::reflector::{DomObject, Reflector};
|
||||||
use dom::bindings::root::DomRoot;
|
use dom::bindings::root::DomRoot;
|
||||||
|
use dom::eventtarget::EventTarget;
|
||||||
use dom::globalscope::GlobalScope;
|
use dom::globalscope::GlobalScope;
|
||||||
use dom::oscillatornode::OscillatorNode;
|
use dom::oscillatornode::OscillatorNode;
|
||||||
use dom::promise::Promise;
|
use dom::promise::Promise;
|
||||||
|
@ -100,6 +101,11 @@ impl BaseAudioContext {
|
||||||
self.state.get() == AudioContextState::Suspended
|
self.state.get() == AudioContextState::Suspended
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
fn push_pending_resume_promise(&self, promise: &Rc<Promise>) {
|
||||||
|
self.pending_resume_promises.borrow_mut().push(promise.clone());
|
||||||
|
}
|
||||||
|
|
||||||
/// Takes the pending resume promises.
|
/// Takes the pending resume promises.
|
||||||
///
|
///
|
||||||
/// The result with which these promises will be fulfilled is passed here
|
/// The result with which these promises will be fulfilled is passed here
|
||||||
|
@ -162,7 +168,6 @@ impl BaseAudioContext {
|
||||||
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
|
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
|
||||||
let task_source = window.dom_manipulation_task_source();
|
let task_source = window.dom_manipulation_task_source();
|
||||||
let this = Trusted::new(self);
|
let this = Trusted::new(self);
|
||||||
|
|
||||||
// Set the rendering thread state to 'running' and start
|
// Set the rendering thread state to 'running' and start
|
||||||
// rendering the audio graph.
|
// rendering the audio graph.
|
||||||
match self.audio_context_impl.resume() {
|
match self.audio_context_impl.resume() {
|
||||||
|
@ -173,21 +178,16 @@ impl BaseAudioContext {
|
||||||
this.fulfill_in_flight_resume_promises(|| {
|
this.fulfill_in_flight_resume_promises(|| {
|
||||||
if this.state.get() != AudioContextState::Running {
|
if this.state.get() != AudioContextState::Running {
|
||||||
this.state.set(AudioContextState::Running);
|
this.state.set(AudioContextState::Running);
|
||||||
let window = DomRoot::downcast::<Window>(this.global()).unwrap();
|
//XXX this.upcast::<EventTarget>().fire_event(atom!("statechange"));
|
||||||
window.dom_manipulation_task_source().queue_simple_event(
|
|
||||||
this.upcast(),
|
|
||||||
atom!("statechange"),
|
|
||||||
&window
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}), window.upcast());
|
}), window.upcast());
|
||||||
},
|
},
|
||||||
Err(()) => {
|
Err(()) => {
|
||||||
self.take_pending_resume_promises(Err(Error::Type("Something went wrong".to_owned())));
|
self.take_pending_resume_promises(Err(Error::Type("Something went wrong".to_owned())));
|
||||||
let _ = task_source.queue(task!(resume_error: move || {
|
let _ = task_source.queue(task!(resume_error: move || {
|
||||||
let this = this.root();
|
this.root().fulfill_in_flight_resume_promises(|| {})
|
||||||
this.fulfill_in_flight_resume_promises(|| {});
|
|
||||||
}), window.upcast());
|
}), window.upcast());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,9 +229,7 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push the promise into the queue to avoid passing a reference to
|
self.push_pending_resume_promise(&promise);
|
||||||
// `resume()`. This way we limit the usage of #[allow(unrooted_must_root)]
|
|
||||||
self.pending_resume_promises.borrow_mut().push(promise.clone());
|
|
||||||
|
|
||||||
// Step 4.
|
// Step 4.
|
||||||
if !self.is_allowed_to_start() {
|
if !self.is_allowed_to_start() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue