mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
rustfmt
This commit is contained in:
parent
3fc9ecace0
commit
b26a3bd31b
10 changed files with 478 additions and 332 deletions
|
@ -35,18 +35,20 @@ pub struct AudioBuffer {
|
||||||
impl AudioBuffer {
|
impl AudioBuffer {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn new_inherited(global: &Window,
|
pub fn new_inherited(
|
||||||
number_of_channels: u32,
|
global: &Window,
|
||||||
length: u32,
|
number_of_channels: u32,
|
||||||
sample_rate: f32,
|
length: u32,
|
||||||
initial_data: Option<&[f32]>) -> AudioBuffer {
|
sample_rate: f32,
|
||||||
|
initial_data: Option<&[f32]>,
|
||||||
|
) -> AudioBuffer {
|
||||||
let initial_data = match initial_data {
|
let initial_data = match initial_data {
|
||||||
Some(initial_data) => {
|
Some(initial_data) => {
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
data.extend_from_slice(initial_data);
|
data.extend_from_slice(initial_data);
|
||||||
data
|
data
|
||||||
},
|
},
|
||||||
None => vec![0.; (length * number_of_channels) as usize]
|
None => vec![0.; (length * number_of_channels) as usize],
|
||||||
};
|
};
|
||||||
let cx = global.get_cx();
|
let cx = global.get_cx();
|
||||||
let mut js_channels: Vec<JSAudioChannel> = Vec::with_capacity(number_of_channels as usize);
|
let mut js_channels: Vec<JSAudioChannel> = Vec::with_capacity(number_of_channels as usize);
|
||||||
|
@ -57,7 +59,8 @@ impl AudioBuffer {
|
||||||
Float32Array::create(
|
Float32Array::create(
|
||||||
cx,
|
cx,
|
||||||
CreateWith::Slice(&initial_data.as_slice()[offset..offset + (length as usize)]),
|
CreateWith::Slice(&initial_data.as_slice()[offset..offset + (length as usize)]),
|
||||||
array.handle_mut())
|
array.handle_mut(),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
let js_channel = Heap::default();
|
let js_channel = Heap::default();
|
||||||
js_channel.set(array.get());
|
js_channel.set(array.get());
|
||||||
|
@ -66,7 +69,10 @@ impl AudioBuffer {
|
||||||
AudioBuffer {
|
AudioBuffer {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
js_channels: DomRefCell::new(js_channels),
|
js_channels: DomRefCell::new(js_channels),
|
||||||
shared_channels: DomRefCell::new(ServoMediaAudioBuffer::new(number_of_channels as u8, length as usize)),
|
shared_channels: DomRefCell::new(ServoMediaAudioBuffer::new(
|
||||||
|
number_of_channels as u8,
|
||||||
|
length as usize,
|
||||||
|
)),
|
||||||
sample_rate,
|
sample_rate,
|
||||||
length,
|
length,
|
||||||
duration: length as f64 / sample_rate as f64,
|
duration: length as f64 / sample_rate as f64,
|
||||||
|
@ -75,22 +81,38 @@ impl AudioBuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn new(global: &Window,
|
pub fn new(
|
||||||
number_of_channels: u32,
|
global: &Window,
|
||||||
length: u32,
|
number_of_channels: u32,
|
||||||
sample_rate: f32,
|
length: u32,
|
||||||
initial_data: Option<&[f32]>) -> DomRoot<AudioBuffer> {
|
sample_rate: f32,
|
||||||
let buffer = AudioBuffer::new_inherited(global, number_of_channels, length, sample_rate, initial_data);
|
initial_data: Option<&[f32]>,
|
||||||
|
) -> DomRoot<AudioBuffer> {
|
||||||
|
let buffer = AudioBuffer::new_inherited(
|
||||||
|
global,
|
||||||
|
number_of_channels,
|
||||||
|
length,
|
||||||
|
sample_rate,
|
||||||
|
initial_data,
|
||||||
|
);
|
||||||
reflect_dom_object(Box::new(buffer), global, AudioBufferBinding::Wrap)
|
reflect_dom_object(Box::new(buffer), global, AudioBufferBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-audiobuffer
|
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-audiobuffer
|
||||||
pub fn Constructor(window: &Window,
|
pub fn Constructor(
|
||||||
options: &AudioBufferOptions) -> Fallible<DomRoot<AudioBuffer>> {
|
window: &Window,
|
||||||
|
options: &AudioBufferOptions,
|
||||||
|
) -> Fallible<DomRoot<AudioBuffer>> {
|
||||||
if options.numberOfChannels > MAX_CHANNEL_COUNT {
|
if options.numberOfChannels > MAX_CHANNEL_COUNT {
|
||||||
return Err(Error::NotSupported);
|
return Err(Error::NotSupported);
|
||||||
}
|
}
|
||||||
Ok(AudioBuffer::new(window, options.numberOfChannels, options.length, *options.sampleRate, None))
|
Ok(AudioBuffer::new(
|
||||||
|
window,
|
||||||
|
options.numberOfChannels,
|
||||||
|
options.length,
|
||||||
|
*options.sampleRate,
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
|
@ -104,7 +126,9 @@ impl AudioBuffer {
|
||||||
// Move the channel data from shared_channels to js_channels.
|
// Move the channel data from shared_channels to js_channels.
|
||||||
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
|
rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
|
||||||
let shared_channel = (*self.shared_channels.borrow_mut()).buffers.remove(i);
|
let shared_channel = (*self.shared_channels.borrow_mut()).buffers.remove(i);
|
||||||
if Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut()).is_err() {
|
if Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut())
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
channel.set(array.get());
|
channel.set(array.get());
|
||||||
|
@ -175,7 +199,11 @@ impl AudioBufferMethods for AudioBuffer {
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-getchanneldata
|
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-getchanneldata
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
unsafe fn GetChannelData(&self, cx: *mut JSContext, channel: u32) -> Fallible<NonNull<JSObject>> {
|
unsafe fn GetChannelData(
|
||||||
|
&self,
|
||||||
|
cx: *mut JSContext,
|
||||||
|
channel: u32,
|
||||||
|
) -> Fallible<NonNull<JSObject>> {
|
||||||
if channel >= self.number_of_channels {
|
if channel >= self.number_of_channels {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
@ -184,15 +212,19 @@ impl AudioBufferMethods for AudioBuffer {
|
||||||
return Err(Error::JSFailed);
|
return Err(Error::JSFailed);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(NonNull::new_unchecked(self.js_channels.borrow()[channel as usize].get()))
|
Ok(NonNull::new_unchecked(
|
||||||
|
self.js_channels.borrow()[channel as usize].get(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copyfromchannel
|
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copyfromchannel
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn CopyFromChannel(&self,
|
fn CopyFromChannel(
|
||||||
mut destination: CustomAutoRooterGuard<Float32Array>,
|
&self,
|
||||||
channel_number: u32,
|
mut destination: CustomAutoRooterGuard<Float32Array>,
|
||||||
start_in_channel: u32) -> Fallible<()> {
|
channel_number: u32,
|
||||||
|
start_in_channel: u32,
|
||||||
|
) -> Fallible<()> {
|
||||||
if channel_number >= self.number_of_channels || start_in_channel > self.length {
|
if channel_number >= self.number_of_channels || start_in_channel > self.length {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
@ -220,17 +252,21 @@ impl AudioBufferMethods for AudioBuffer {
|
||||||
dest.extend_from_slice(&shared_channel.as_slice()[offset..offset + bytes_to_copy]);
|
dest.extend_from_slice(&shared_channel.as_slice()[offset..offset + bytes_to_copy]);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { destination.update(&dest); }
|
unsafe {
|
||||||
|
destination.update(&dest);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copytochannel
|
// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-copytochannel
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn CopyToChannel(&self,
|
fn CopyToChannel(
|
||||||
source: CustomAutoRooterGuard<Float32Array>,
|
&self,
|
||||||
channel_number: u32,
|
source: CustomAutoRooterGuard<Float32Array>,
|
||||||
start_in_channel: u32) -> Fallible<()> {
|
channel_number: u32,
|
||||||
|
start_in_channel: u32,
|
||||||
|
) -> Fallible<()> {
|
||||||
if channel_number >= self.number_of_channels || start_in_channel > (source.len() as u32) {
|
if channel_number >= self.number_of_channels || start_in_channel > (source.len() as u32) {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
@ -250,7 +286,9 @@ impl AudioBufferMethods for AudioBuffer {
|
||||||
if let Ok(mut array) = array {
|
if let Ok(mut array) = array {
|
||||||
let bytes_to_copy = min(self.length - start_in_channel, source.len() as u32) as usize;
|
let bytes_to_copy = min(self.length - start_in_channel, source.len() as u32) as usize;
|
||||||
let offset = start_in_channel as usize;
|
let offset = start_in_channel as usize;
|
||||||
unsafe { array.update(&source.as_slice()[offset..offset + bytes_to_copy]); }
|
unsafe {
|
||||||
|
array.update(&source.as_slice()[offset..offset + bytes_to_copy]);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::IndexSize);
|
return Err(Error::IndexSize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ use dom::bindings::codegen::Bindings::AudioParamBinding::AutomationRate;
|
||||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
|
||||||
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
|
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
|
||||||
use dom::bindings::codegen::Bindings::AudioScheduledSourceNodeBinding::
|
use dom::bindings::codegen::Bindings::AudioScheduledSourceNodeBinding::
|
||||||
AudioScheduledSourceNodeBinding::AudioScheduledSourceNodeMethods;
|
AudioScheduledSourceNodeBinding::AudioScheduledSourceNodeMethods;
|
||||||
use dom::bindings::error::{Error, Fallible};
|
use dom::bindings::error::{Error, Fallible};
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::num::Finite;
|
use dom::bindings::num::Finite;
|
||||||
|
@ -45,7 +45,7 @@ impl AudioBufferSourceNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
options: &AudioBufferSourceOptions,
|
options: &AudioBufferSourceOptions,
|
||||||
) -> AudioBufferSourceNode {
|
) -> AudioBufferSourceNode {
|
||||||
let mut node_options = AudioNodeOptions::empty();
|
let mut node_options = AudioNodeOptions::empty();
|
||||||
node_options.channelCount = Some(2);
|
node_options.channelCount = Some(2);
|
||||||
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
||||||
|
@ -54,24 +54,30 @@ impl AudioBufferSourceNode {
|
||||||
AudioNodeInit::AudioBufferSourceNode(options.into()),
|
AudioNodeInit::AudioBufferSourceNode(options.into()),
|
||||||
context,
|
context,
|
||||||
&node_options,
|
&node_options,
|
||||||
0 /* inputs */,
|
0, /* inputs */
|
||||||
1 /* outputs */,
|
1, /* outputs */
|
||||||
);
|
);
|
||||||
let node_id = source_node.node().node_id();
|
let node_id = source_node.node().node_id();
|
||||||
let playback_rate = AudioParam::new(&window,
|
let playback_rate = AudioParam::new(
|
||||||
context,
|
&window,
|
||||||
node_id,
|
context,
|
||||||
ParamType::PlaybackRate,
|
node_id,
|
||||||
AutomationRate::K_rate,
|
ParamType::PlaybackRate,
|
||||||
*options.playbackRate,
|
AutomationRate::K_rate,
|
||||||
f32::MIN, f32::MAX);
|
*options.playbackRate,
|
||||||
let detune = AudioParam::new(&window,
|
f32::MIN,
|
||||||
context,
|
f32::MAX,
|
||||||
node_id,
|
);
|
||||||
ParamType::Detune,
|
let detune = AudioParam::new(
|
||||||
AutomationRate::K_rate,
|
&window,
|
||||||
*options.detune,
|
context,
|
||||||
f32::MIN, f32::MAX);
|
node_id,
|
||||||
|
ParamType::Detune,
|
||||||
|
AutomationRate::K_rate,
|
||||||
|
*options.detune,
|
||||||
|
f32::MIN,
|
||||||
|
f32::MAX,
|
||||||
|
);
|
||||||
AudioBufferSourceNode {
|
AudioBufferSourceNode {
|
||||||
source_node,
|
source_node,
|
||||||
buffer: Default::default(),
|
buffer: Default::default(),
|
||||||
|
@ -88,7 +94,7 @@ impl AudioBufferSourceNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
options: &AudioBufferSourceOptions,
|
options: &AudioBufferSourceOptions,
|
||||||
) -> DomRoot<AudioBufferSourceNode> {
|
) -> DomRoot<AudioBufferSourceNode> {
|
||||||
let node = AudioBufferSourceNode::new_inherited(window, context, options);
|
let node = AudioBufferSourceNode::new_inherited(window, context, options);
|
||||||
reflect_dom_object(Box::new(node), window, AudioBufferSourceNodeBinding::Wrap)
|
reflect_dom_object(Box::new(node), window, AudioBufferSourceNodeBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
@ -97,7 +103,7 @@ impl AudioBufferSourceNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
options: &AudioBufferSourceOptions,
|
options: &AudioBufferSourceOptions,
|
||||||
) -> Fallible<DomRoot<AudioBufferSourceNode>> {
|
) -> Fallible<DomRoot<AudioBufferSourceNode>> {
|
||||||
Ok(AudioBufferSourceNode::new(window, context, options))
|
Ok(AudioBufferSourceNode::new(window, context, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,9 +125,11 @@ impl AudioBufferSourceNodeMethods for AudioBufferSourceNode {
|
||||||
if self.source_node.started() {
|
if self.source_node.started() {
|
||||||
if let Some(buffer) = self.buffer.get() {
|
if let Some(buffer) = self.buffer.get() {
|
||||||
let buffer = buffer.acquire_contents();
|
let buffer = buffer.acquire_contents();
|
||||||
self.source_node.node().message(
|
self.source_node
|
||||||
AudioNodeMessage::AudioBufferSourceNode(
|
.node()
|
||||||
AudioBufferSourceNodeMessage::SetBuffer(buffer)));
|
.message(AudioNodeMessage::AudioBufferSourceNode(
|
||||||
|
AudioBufferSourceNodeMessage::SetBuffer(buffer),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,17 +168,23 @@ impl AudioBufferSourceNodeMethods for AudioBufferSourceNode {
|
||||||
self.loop_end.set(*loop_end)
|
self.loop_end.set(*loop_end)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Start(&self,
|
fn Start(
|
||||||
when: Finite<f64>,
|
&self,
|
||||||
_offset: Option<Finite<f64>>,
|
when: Finite<f64>,
|
||||||
_duration: Option<Finite<f64>>) -> Fallible<()> {
|
_offset: Option<Finite<f64>>,
|
||||||
|
_duration: Option<Finite<f64>>,
|
||||||
|
) -> Fallible<()> {
|
||||||
if let Some(buffer) = self.buffer.get() {
|
if let Some(buffer) = self.buffer.get() {
|
||||||
let buffer = buffer.acquire_contents();
|
let buffer = buffer.acquire_contents();
|
||||||
self.source_node.node().message(
|
self.source_node
|
||||||
AudioNodeMessage::AudioBufferSourceNode(
|
.node()
|
||||||
AudioBufferSourceNodeMessage::SetBuffer(buffer)));
|
.message(AudioNodeMessage::AudioBufferSourceNode(
|
||||||
|
AudioBufferSourceNodeMessage::SetBuffer(buffer),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
self.source_node.upcast::<AudioScheduledSourceNode>().Start(when)
|
self.source_node
|
||||||
|
.upcast::<AudioScheduledSourceNode>()
|
||||||
|
.Start(when)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,10 @@ impl AudioContext {
|
||||||
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
||||||
fn new_inherited(global: &GlobalScope, options: &AudioContextOptions) -> AudioContext {
|
fn new_inherited(global: &GlobalScope, options: &AudioContextOptions) -> AudioContext {
|
||||||
// Steps 1-3.
|
// Steps 1-3.
|
||||||
let context = BaseAudioContext::new_inherited(global, BaseAudioContextOptions::AudioContext(options.into()));
|
let context = BaseAudioContext::new_inherited(
|
||||||
|
global,
|
||||||
|
BaseAudioContextOptions::AudioContext(options.into()),
|
||||||
|
);
|
||||||
|
|
||||||
// Step 4.1.
|
// Step 4.1.
|
||||||
let latency_hint = options.latencyHint;
|
let latency_hint = options.latencyHint;
|
||||||
|
@ -52,14 +55,13 @@ impl AudioContext {
|
||||||
AudioContext {
|
AudioContext {
|
||||||
context,
|
context,
|
||||||
latency_hint,
|
latency_hint,
|
||||||
base_latency: 0., // TODO
|
base_latency: 0., // TODO
|
||||||
output_latency: 0., // TODO
|
output_latency: 0., // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
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);
|
||||||
let context = reflect_dom_object(Box::new(context), global, AudioContextBinding::Wrap);
|
let context = reflect_dom_object(Box::new(context), global, AudioContextBinding::Wrap);
|
||||||
context.resume();
|
context.resume();
|
||||||
|
@ -67,8 +69,10 @@ impl AudioContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
|
||||||
pub fn Constructor(window: &Window,
|
pub fn Constructor(
|
||||||
options: &AudioContextOptions) -> Fallible<DomRoot<AudioContext>> {
|
window: &Window,
|
||||||
|
options: &AudioContextOptions,
|
||||||
|
) -> Fallible<DomRoot<AudioContext>> {
|
||||||
let global = window.upcast::<GlobalScope>();
|
let global = window.upcast::<GlobalScope>();
|
||||||
Ok(AudioContext::new(global, options))
|
Ok(AudioContext::new(global, options))
|
||||||
}
|
}
|
||||||
|
@ -125,7 +129,8 @@ impl AudioContextMethods for AudioContext {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let base_context = Trusted::new(&self.context);
|
let base_context = Trusted::new(&self.context);
|
||||||
let context = Trusted::new(self);
|
let context = Trusted::new(self);
|
||||||
let _ = task_source.queue(task!(suspend_ok: move || {
|
let _ = task_source.queue(
|
||||||
|
task!(suspend_ok: move || {
|
||||||
let base_context = base_context.root();
|
let base_context = base_context.root();
|
||||||
let context = context.root();
|
let context = context.root();
|
||||||
let promise = trusted_promise.root();
|
let promise = trusted_promise.root();
|
||||||
|
@ -139,15 +144,20 @@ impl AudioContextMethods for AudioContext {
|
||||||
&window
|
&window
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}), window.upcast());
|
}),
|
||||||
|
window.upcast(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// The spec does not define the error case and `suspend` should
|
// The spec does not define the error case and `suspend` should
|
||||||
// never fail, but we handle the case here for completion.
|
// never fail, but we handle the case here for completion.
|
||||||
let _ = task_source.queue(task!(suspend_error: move || {
|
let _ = task_source.queue(
|
||||||
|
task!(suspend_error: move || {
|
||||||
let promise = trusted_promise.root();
|
let promise = trusted_promise.root();
|
||||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||||
}), window.upcast());
|
}),
|
||||||
|
window.upcast(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -180,7 +190,8 @@ impl AudioContextMethods for AudioContext {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let base_context = Trusted::new(&self.context);
|
let base_context = Trusted::new(&self.context);
|
||||||
let context = Trusted::new(self);
|
let context = Trusted::new(self);
|
||||||
let _ = task_source.queue(task!(suspend_ok: move || {
|
let _ = task_source.queue(
|
||||||
|
task!(suspend_ok: move || {
|
||||||
let base_context = base_context.root();
|
let base_context = base_context.root();
|
||||||
let context = context.root();
|
let context = context.root();
|
||||||
let promise = trusted_promise.root();
|
let promise = trusted_promise.root();
|
||||||
|
@ -194,19 +205,23 @@ impl AudioContextMethods for AudioContext {
|
||||||
&window
|
&window
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}), window.upcast());
|
}),
|
||||||
|
window.upcast(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
// The spec does not define the error case and `suspend` should
|
// The spec does not define the error case and `suspend` should
|
||||||
// never fail, but we handle the case here for completion.
|
// never fail, but we handle the case here for completion.
|
||||||
let _ = task_source.queue(task!(suspend_error: move || {
|
let _ = task_source.queue(
|
||||||
|
task!(suspend_error: move || {
|
||||||
let promise = trusted_promise.root();
|
let promise = trusted_promise.root();
|
||||||
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
promise.reject_error(Error::Type("Something went wrong".to_owned()));
|
||||||
}), window.upcast());
|
}),
|
||||||
|
window.upcast(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
promise
|
promise
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,19 +18,28 @@ pub struct AudioDestinationNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioDestinationNode {
|
impl AudioDestinationNode {
|
||||||
fn new_inherited(context: &BaseAudioContext,
|
fn new_inherited(
|
||||||
options: &AudioNodeOptions) -> AudioDestinationNode {
|
context: &BaseAudioContext,
|
||||||
|
options: &AudioNodeOptions,
|
||||||
|
) -> AudioDestinationNode {
|
||||||
AudioDestinationNode {
|
AudioDestinationNode {
|
||||||
node: AudioNode::new_inherited(AudioNodeInit::DestinationNode,
|
node: AudioNode::new_inherited(
|
||||||
Some(context.destination_node()),
|
AudioNodeInit::DestinationNode,
|
||||||
context, options, 1, 1),
|
Some(context.destination_node()),
|
||||||
|
context,
|
||||||
|
options,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn new(global: &GlobalScope,
|
pub fn new(
|
||||||
context: &BaseAudioContext,
|
global: &GlobalScope,
|
||||||
options: &AudioNodeOptions) -> DomRoot<AudioDestinationNode> {
|
context: &BaseAudioContext,
|
||||||
|
options: &AudioNodeOptions,
|
||||||
|
) -> DomRoot<AudioDestinationNode> {
|
||||||
let node = AudioDestinationNode::new_inherited(context, options);
|
let node = AudioDestinationNode::new_inherited(context, options);
|
||||||
reflect_dom_object(Box::new(node), global, AudioDestinationNodeBinding::Wrap)
|
reflect_dom_object(Box::new(node), global, AudioDestinationNodeBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,15 +33,16 @@ pub struct AudioNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioNode {
|
impl AudioNode {
|
||||||
pub fn new_inherited(node_type: AudioNodeInit,
|
pub fn new_inherited(
|
||||||
node_id: Option<NodeId>,
|
node_type: AudioNodeInit,
|
||||||
context: &BaseAudioContext,
|
node_id: Option<NodeId>,
|
||||||
options: &AudioNodeOptions,
|
context: &BaseAudioContext,
|
||||||
number_of_inputs: u32,
|
options: &AudioNodeOptions,
|
||||||
number_of_outputs: u32) -> AudioNode {
|
number_of_inputs: u32,
|
||||||
let node_id = node_id.unwrap_or_else(|| {
|
number_of_outputs: u32,
|
||||||
context.audio_context_impl().create_node(node_type)
|
) -> AudioNode {
|
||||||
});
|
let node_id =
|
||||||
|
node_id.unwrap_or_else(|| context.audio_context_impl().create_node(node_type));
|
||||||
AudioNode {
|
AudioNode {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
node_id,
|
node_id,
|
||||||
|
@ -55,7 +56,9 @@ impl AudioNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn message(&self, message: AudioNodeMessage) {
|
pub fn message(&self, message: AudioNodeMessage) {
|
||||||
self.context.audio_context_impl().message_node(self.node_id, message);
|
self.context
|
||||||
|
.audio_context_impl()
|
||||||
|
.message_node(self.node_id, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_id(&self) -> NodeId {
|
pub fn node_id(&self) -> NodeId {
|
||||||
|
@ -65,65 +68,69 @@ impl AudioNode {
|
||||||
|
|
||||||
impl AudioNodeMethods for AudioNode {
|
impl AudioNodeMethods for AudioNode {
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-connect
|
// https://webaudio.github.io/web-audio-api/#dom-audionode-connect
|
||||||
fn Connect(&self,
|
fn Connect(
|
||||||
destination: &AudioNode,
|
&self,
|
||||||
output: u32,
|
destination: &AudioNode,
|
||||||
input: u32) -> Fallible<DomRoot<AudioNode>> {
|
output: u32,
|
||||||
|
input: u32,
|
||||||
|
) -> Fallible<DomRoot<AudioNode>> {
|
||||||
if self.context != destination.context {
|
if self.context != destination.context {
|
||||||
return Err(Error::InvalidAccess);
|
return Err(Error::InvalidAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
if output >= self.NumberOfOutputs() ||
|
if output >= self.NumberOfOutputs() || input >= destination.NumberOfInputs() {
|
||||||
input >= destination.NumberOfInputs() {
|
return Err(Error::IndexSize);
|
||||||
return Err(Error::IndexSize);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.context.audio_context_impl().connect_ports(
|
self.context.audio_context_impl().connect_ports(
|
||||||
self.node_id().output(output), destination.node_id().input(input)
|
self.node_id().output(output),
|
||||||
);
|
destination.node_id().input(input),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(DomRoot::from_ref(destination))
|
Ok(DomRoot::from_ref(destination))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Connect_(&self,
|
fn Connect_(&self, _: &AudioParam, _: u32) -> Fallible<()> {
|
||||||
_: &AudioParam,
|
|
||||||
_: u32) -> Fallible<()> {
|
|
||||||
// TODO
|
// TODO
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
|
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
|
||||||
fn Disconnect(&self) -> ErrorResult {
|
fn Disconnect(&self) -> ErrorResult {
|
||||||
self.context.audio_context_impl()
|
self.context
|
||||||
|
.audio_context_impl()
|
||||||
.disconnect_all_from(self.node_id());
|
.disconnect_all_from(self.node_id());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-output
|
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-output
|
||||||
fn Disconnect_(&self, out: u32) -> ErrorResult {
|
fn Disconnect_(&self, out: u32) -> ErrorResult {
|
||||||
self.context.audio_context_impl()
|
self.context
|
||||||
|
.audio_context_impl()
|
||||||
.disconnect_output(self.node_id().output(out));
|
.disconnect_output(self.node_id().output(out));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode
|
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode
|
||||||
fn Disconnect__(&self, to: &AudioNode) -> ErrorResult {
|
fn Disconnect__(&self, to: &AudioNode) -> ErrorResult {
|
||||||
self.context.audio_context_impl()
|
self.context
|
||||||
|
.audio_context_impl()
|
||||||
.disconnect_between(self.node_id(), to.node_id());
|
.disconnect_between(self.node_id(), to.node_id());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output
|
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output
|
||||||
fn Disconnect___(&self, to: &AudioNode, out: u32) -> ErrorResult{
|
fn Disconnect___(&self, to: &AudioNode, out: u32) -> ErrorResult {
|
||||||
self.context.audio_context_impl()
|
self.context
|
||||||
|
.audio_context_impl()
|
||||||
.disconnect_output_between(self.node_id().output(out), to.node_id());
|
.disconnect_output_between(self.node_id().output(out), to.node_id());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output-input
|
// https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output-input
|
||||||
fn Disconnect____(&self, to: &AudioNode, out: u32, inp: u32) -> ErrorResult {
|
fn Disconnect____(&self, to: &AudioNode, out: u32, inp: u32) -> ErrorResult {
|
||||||
self.context.audio_context_impl()
|
self.context
|
||||||
|
.audio_context_impl()
|
||||||
.disconnect_output_between_to(self.node_id().output(out), to.node_id().input(inp));
|
.disconnect_output_between_to(self.node_id().output(out), to.node_id().input(inp));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,13 +30,15 @@ pub struct AudioParam {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioParam {
|
impl AudioParam {
|
||||||
pub fn new_inherited(context: &BaseAudioContext,
|
pub fn new_inherited(
|
||||||
node: NodeId,
|
context: &BaseAudioContext,
|
||||||
param: ParamType,
|
node: NodeId,
|
||||||
automation_rate: AutomationRate,
|
param: ParamType,
|
||||||
default_value: f32,
|
automation_rate: AutomationRate,
|
||||||
min_value: f32,
|
default_value: f32,
|
||||||
max_value: f32) -> AudioParam {
|
min_value: f32,
|
||||||
|
max_value: f32,
|
||||||
|
) -> AudioParam {
|
||||||
AudioParam {
|
AudioParam {
|
||||||
reflector_: Reflector::new(),
|
reflector_: Reflector::new(),
|
||||||
context: Dom::from_ref(context),
|
context: Dom::from_ref(context),
|
||||||
|
@ -50,16 +52,25 @@ impl AudioParam {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn new(window: &Window,
|
pub fn new(
|
||||||
context: &BaseAudioContext,
|
window: &Window,
|
||||||
node: NodeId,
|
context: &BaseAudioContext,
|
||||||
param: ParamType,
|
node: NodeId,
|
||||||
automation_rate: AutomationRate,
|
param: ParamType,
|
||||||
default_value: f32,
|
automation_rate: AutomationRate,
|
||||||
min_value: f32,
|
default_value: f32,
|
||||||
max_value: f32) -> DomRoot<AudioParam> {
|
min_value: f32,
|
||||||
let audio_param = AudioParam::new_inherited(context, node, param, automation_rate,
|
max_value: f32,
|
||||||
default_value, min_value, max_value);
|
) -> DomRoot<AudioParam> {
|
||||||
|
let audio_param = AudioParam::new_inherited(
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
param,
|
||||||
|
automation_rate,
|
||||||
|
default_value,
|
||||||
|
min_value,
|
||||||
|
max_value,
|
||||||
|
);
|
||||||
reflect_dom_object(Box::new(audio_param), window, AudioParamBinding::Wrap)
|
reflect_dom_object(Box::new(audio_param), window, AudioParamBinding::Wrap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,14 +91,10 @@ impl AudioParamMethods for AudioParam {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetValue(&self, value: Finite<f32>) {
|
fn SetValue(&self, value: Finite<f32>) {
|
||||||
self.context.audio_context_impl()
|
self.context.audio_context_impl().message_node(
|
||||||
.message_node(self.node,
|
self.node,
|
||||||
AudioNodeMessage::SetParam(self.param,
|
AudioNodeMessage::SetParam(self.param, UserAutomationEvent::SetValue(*value)),
|
||||||
UserAutomationEvent::SetValue(
|
);
|
||||||
*value
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn DefaultValue(&self) -> Finite<f32> {
|
fn DefaultValue(&self) -> Finite<f32> {
|
||||||
|
@ -102,83 +109,82 @@ impl AudioParamMethods for AudioParam {
|
||||||
Finite::wrap(self.max_value)
|
Finite::wrap(self.max_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetValueAtTime(&self, value: Finite<f32>, start_time: Finite<f64>)
|
fn SetValueAtTime(&self, value: Finite<f32>, start_time: Finite<f64>) -> DomRoot<AudioParam> {
|
||||||
-> DomRoot<AudioParam>
|
self.context.audio_context_impl().message_node(
|
||||||
{
|
self.node,
|
||||||
self.context.audio_context_impl()
|
AudioNodeMessage::SetParam(
|
||||||
.message_node(self.node,
|
self.param,
|
||||||
AudioNodeMessage::SetParam(self.param,
|
UserAutomationEvent::SetValueAtTime(*value, *start_time),
|
||||||
UserAutomationEvent::SetValueAtTime(
|
),
|
||||||
*value, *start_time
|
);
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
DomRoot::from_ref(self)
|
DomRoot::from_ref(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn LinearRampToValueAtTime(&self, value: Finite<f32>, end_time: Finite<f64>)
|
fn LinearRampToValueAtTime(
|
||||||
-> DomRoot<AudioParam>
|
&self,
|
||||||
{
|
value: Finite<f32>,
|
||||||
self.context.audio_context_impl()
|
end_time: Finite<f64>,
|
||||||
.message_node(self.node,
|
) -> DomRoot<AudioParam> {
|
||||||
AudioNodeMessage::SetParam(self.param,
|
self.context.audio_context_impl().message_node(
|
||||||
UserAutomationEvent::RampToValueAtTime(
|
self.node,
|
||||||
RampKind::Linear, *value, *end_time
|
AudioNodeMessage::SetParam(
|
||||||
)
|
self.param,
|
||||||
)
|
UserAutomationEvent::RampToValueAtTime(RampKind::Linear, *value, *end_time),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
DomRoot::from_ref(self)
|
DomRoot::from_ref(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ExponentialRampToValueAtTime(&self, value: Finite<f32>, end_time: Finite<f64>)
|
fn ExponentialRampToValueAtTime(
|
||||||
-> DomRoot<AudioParam>
|
&self,
|
||||||
{
|
value: Finite<f32>,
|
||||||
self.context.audio_context_impl()
|
end_time: Finite<f64>,
|
||||||
.message_node(self.node,
|
) -> DomRoot<AudioParam> {
|
||||||
AudioNodeMessage::SetParam(self.param,
|
self.context.audio_context_impl().message_node(
|
||||||
UserAutomationEvent::RampToValueAtTime(
|
self.node,
|
||||||
RampKind::Exponential, *value, *end_time
|
AudioNodeMessage::SetParam(
|
||||||
)
|
self.param,
|
||||||
)
|
UserAutomationEvent::RampToValueAtTime(RampKind::Exponential, *value, *end_time),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
DomRoot::from_ref(self)
|
DomRoot::from_ref(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetTargetAtTime(&self, target: Finite<f32>, start_time: Finite<f64>, time_constant: Finite<f32>)
|
fn SetTargetAtTime(
|
||||||
-> DomRoot<AudioParam>
|
&self,
|
||||||
{
|
target: Finite<f32>,
|
||||||
self.context.audio_context_impl()
|
start_time: Finite<f64>,
|
||||||
.message_node(self.node,
|
time_constant: Finite<f32>,
|
||||||
AudioNodeMessage::SetParam(self.param,
|
) -> DomRoot<AudioParam> {
|
||||||
UserAutomationEvent::SetTargetAtTime(
|
self.context.audio_context_impl().message_node(
|
||||||
*target, *start_time, (*time_constant).into()
|
self.node,
|
||||||
)
|
AudioNodeMessage::SetParam(
|
||||||
)
|
self.param,
|
||||||
);
|
UserAutomationEvent::SetTargetAtTime(*target, *start_time, (*time_constant).into()),
|
||||||
|
),
|
||||||
|
);
|
||||||
DomRoot::from_ref(self)
|
DomRoot::from_ref(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CancelScheduledValues(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
|
fn CancelScheduledValues(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
|
||||||
self.context.audio_context_impl()
|
self.context.audio_context_impl().message_node(
|
||||||
.message_node(self.node,
|
self.node,
|
||||||
AudioNodeMessage::SetParam(self.param,
|
AudioNodeMessage::SetParam(
|
||||||
UserAutomationEvent::CancelScheduledValues(
|
self.param,
|
||||||
*cancel_time
|
UserAutomationEvent::CancelScheduledValues(*cancel_time),
|
||||||
)
|
),
|
||||||
)
|
);
|
||||||
);
|
|
||||||
DomRoot::from_ref(self)
|
DomRoot::from_ref(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CancelAndHoldAtTime(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
|
fn CancelAndHoldAtTime(&self, cancel_time: Finite<f64>) -> DomRoot<AudioParam> {
|
||||||
self.context.audio_context_impl()
|
self.context.audio_context_impl().message_node(
|
||||||
.message_node(self.node,
|
self.node,
|
||||||
AudioNodeMessage::SetParam(self.param,
|
AudioNodeMessage::SetParam(
|
||||||
UserAutomationEvent::CancelAndHoldAtTime(
|
self.param,
|
||||||
*cancel_time
|
UserAutomationEvent::CancelAndHoldAtTime(*cancel_time),
|
||||||
)
|
),
|
||||||
)
|
);
|
||||||
);
|
|
||||||
DomRoot::from_ref(self)
|
DomRoot::from_ref(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,16 +19,24 @@ pub struct AudioScheduledSourceNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AudioScheduledSourceNode {
|
impl AudioScheduledSourceNode {
|
||||||
pub fn new_inherited(node_type: AudioNodeInit,
|
pub fn new_inherited(
|
||||||
context: &BaseAudioContext,
|
node_type: AudioNodeInit,
|
||||||
options: &AudioNodeOptions,
|
context: &BaseAudioContext,
|
||||||
number_of_inputs: u32,
|
options: &AudioNodeOptions,
|
||||||
number_of_outputs: u32) -> AudioScheduledSourceNode {
|
number_of_inputs: u32,
|
||||||
|
number_of_outputs: u32,
|
||||||
|
) -> AudioScheduledSourceNode {
|
||||||
AudioScheduledSourceNode {
|
AudioScheduledSourceNode {
|
||||||
node: AudioNode::new_inherited(node_type, None /* node_id */,
|
node: AudioNode::new_inherited(
|
||||||
context, options, number_of_inputs, number_of_outputs),
|
node_type,
|
||||||
started: Cell::new(false),
|
None, /* node_id */
|
||||||
stopped: Cell::new(false),
|
context,
|
||||||
|
options,
|
||||||
|
number_of_inputs,
|
||||||
|
number_of_outputs,
|
||||||
|
),
|
||||||
|
started: Cell::new(false),
|
||||||
|
stopped: Cell::new(false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,9 +59,10 @@ impl AudioScheduledSourceNodeMethods for AudioScheduledSourceNode {
|
||||||
return Err(Error::InvalidState);
|
return Err(Error::InvalidState);
|
||||||
}
|
}
|
||||||
self.started.set(true);
|
self.started.set(true);
|
||||||
self.node.message(
|
self.node
|
||||||
AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(*when))
|
.message(AudioNodeMessage::AudioScheduledSourceNode(
|
||||||
);
|
AudioScheduledSourceNodeMessage::Start(*when),
|
||||||
|
));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +72,10 @@ impl AudioScheduledSourceNodeMethods for AudioScheduledSourceNode {
|
||||||
return Err(Error::InvalidState);
|
return Err(Error::InvalidState);
|
||||||
}
|
}
|
||||||
self.stopped.set(true);
|
self.stopped.set(true);
|
||||||
self.node.message(
|
self.node
|
||||||
AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Stop(*when))
|
.message(AudioNodeMessage::AudioScheduledSourceNode(
|
||||||
);
|
AudioScheduledSourceNodeMessage::Stop(*when),
|
||||||
|
));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,10 +86,7 @@ pub struct BaseAudioContext {
|
||||||
|
|
||||||
impl BaseAudioContext {
|
impl BaseAudioContext {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn new_inherited(
|
pub fn new_inherited(_: &GlobalScope, options: BaseAudioContextOptions) -> BaseAudioContext {
|
||||||
_: &GlobalScope,
|
|
||||||
options: BaseAudioContextOptions,
|
|
||||||
) -> BaseAudioContext {
|
|
||||||
let options = match options {
|
let options = match options {
|
||||||
BaseAudioContextOptions::AudioContext(options) => options,
|
BaseAudioContextOptions::AudioContext(options) => options,
|
||||||
BaseAudioContextOptions::OfflineAudioContext(_) => unimplemented!(),
|
BaseAudioContextOptions::OfflineAudioContext(_) => unimplemented!(),
|
||||||
|
@ -99,7 +96,11 @@ impl BaseAudioContext {
|
||||||
|
|
||||||
let context = BaseAudioContext {
|
let context = BaseAudioContext {
|
||||||
eventtarget: EventTarget::new_inherited(),
|
eventtarget: EventTarget::new_inherited(),
|
||||||
audio_context_impl: Rc::new(ServoMedia::get().unwrap().create_audio_context(options.into())),
|
audio_context_impl: Rc::new(
|
||||||
|
ServoMedia::get()
|
||||||
|
.unwrap()
|
||||||
|
.create_audio_context(options.into()),
|
||||||
|
),
|
||||||
destination: Default::default(),
|
destination: Default::default(),
|
||||||
in_flight_resume_promises_queue: Default::default(),
|
in_flight_resume_promises_queue: Default::default(),
|
||||||
pending_resume_promises: Default::default(),
|
pending_resume_promises: Default::default(),
|
||||||
|
@ -126,7 +127,9 @@ impl BaseAudioContext {
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
fn push_pending_resume_promise(&self, promise: &Rc<Promise>) {
|
fn push_pending_resume_promise(&self, promise: &Rc<Promise>) {
|
||||||
self.pending_resume_promises.borrow_mut().push(promise.clone());
|
self.pending_resume_promises
|
||||||
|
.borrow_mut()
|
||||||
|
.push(promise.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes the pending resume promises.
|
/// Takes the pending resume promises.
|
||||||
|
@ -141,14 +144,11 @@ impl BaseAudioContext {
|
||||||
/// which were taken and moved to the in-flight queue.
|
/// which were taken and moved to the in-flight queue.
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
fn take_pending_resume_promises(&self, result: ErrorResult) {
|
fn take_pending_resume_promises(&self, result: ErrorResult) {
|
||||||
let pending_resume_promises = mem::replace(
|
let pending_resume_promises =
|
||||||
&mut *self.pending_resume_promises.borrow_mut(),
|
mem::replace(&mut *self.pending_resume_promises.borrow_mut(), vec![]);
|
||||||
vec![],
|
self.in_flight_resume_promises_queue
|
||||||
);
|
.borrow_mut()
|
||||||
self.in_flight_resume_promises_queue.borrow_mut().push_back((
|
.push_back((pending_resume_promises.into(), result));
|
||||||
pending_resume_promises.into(),
|
|
||||||
result,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fulfills the next in-flight resume promises queue after running a closure.
|
/// Fulfills the next in-flight resume promises queue after running a closure.
|
||||||
|
@ -161,21 +161,22 @@ impl BaseAudioContext {
|
||||||
/// hiding actual safety bugs.
|
/// hiding actual safety bugs.
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
fn fulfill_in_flight_resume_promises<F>(&self, f: F)
|
fn fulfill_in_flight_resume_promises<F>(&self, f: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(),
|
F: FnOnce(),
|
||||||
{
|
{
|
||||||
let (promises, result) = self.in_flight_resume_promises_queue
|
let (promises, result) = self
|
||||||
.borrow_mut()
|
.in_flight_resume_promises_queue
|
||||||
.pop_front()
|
.borrow_mut()
|
||||||
.expect("there should be at least one list of in flight resume promises");
|
.pop_front()
|
||||||
f();
|
.expect("there should be at least one list of in flight resume promises");
|
||||||
for promise in &*promises {
|
f();
|
||||||
match result {
|
for promise in &*promises {
|
||||||
Ok(ref value) => promise.resolve_native(value),
|
match result {
|
||||||
Err(ref error) => promise.reject_error(error.clone()),
|
Ok(ref value) => promise.resolve_native(value),
|
||||||
}
|
Err(ref error) => promise.reject_error(error.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Control thread processing state
|
/// Control thread processing state
|
||||||
pub fn control_thread_state(&self) -> ProcessingState {
|
pub fn control_thread_state(&self) -> ProcessingState {
|
||||||
|
@ -197,7 +198,8 @@ impl BaseAudioContext {
|
||||||
match self.audio_context_impl.resume() {
|
match self.audio_context_impl.resume() {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
self.take_pending_resume_promises(Ok(()));
|
self.take_pending_resume_promises(Ok(()));
|
||||||
let _ = task_source.queue(task!(resume_success: move || {
|
let _ = task_source.queue(
|
||||||
|
task!(resume_success: move || {
|
||||||
let this = this.root();
|
let this = this.root();
|
||||||
this.fulfill_in_flight_resume_promises(|| {
|
this.fulfill_in_flight_resume_promises(|| {
|
||||||
if this.state.get() != AudioContextState::Running {
|
if this.state.get() != AudioContextState::Running {
|
||||||
|
@ -210,14 +212,21 @@ impl BaseAudioContext {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}), 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(
|
||||||
let _ = task_source.queue(task!(resume_error: move || {
|
"Something went wrong".to_owned(),
|
||||||
|
)));
|
||||||
|
let _ = task_source.queue(
|
||||||
|
task!(resume_error: move || {
|
||||||
this.root().fulfill_in_flight_resume_promises(|| {})
|
this.root().fulfill_in_flight_resume_promises(|| {})
|
||||||
}), window.upcast());
|
}),
|
||||||
}
|
window.upcast(),
|
||||||
|
);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,7 +297,11 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
|
|
||||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createoscillator
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createoscillator
|
||||||
fn CreateOscillator(&self) -> DomRoot<OscillatorNode> {
|
fn CreateOscillator(&self) -> DomRoot<OscillatorNode> {
|
||||||
OscillatorNode::new(&self.global().as_window(), &self, &OscillatorOptions::empty())
|
OscillatorNode::new(
|
||||||
|
&self.global().as_window(),
|
||||||
|
&self,
|
||||||
|
&OscillatorOptions::empty(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-creategain
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-creategain
|
||||||
|
@ -297,56 +310,74 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer
|
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-createbuffer
|
||||||
fn CreateBuffer(&self,
|
fn CreateBuffer(
|
||||||
number_of_channels: u32,
|
&self,
|
||||||
length: u32,
|
number_of_channels: u32,
|
||||||
sample_rate: Finite<f32>) -> Fallible<DomRoot<AudioBuffer>> {
|
length: u32,
|
||||||
|
sample_rate: Finite<f32>,
|
||||||
|
) -> Fallible<DomRoot<AudioBuffer>> {
|
||||||
if number_of_channels <= 0 ||
|
if number_of_channels <= 0 ||
|
||||||
number_of_channels > MAX_CHANNEL_COUNT ||
|
number_of_channels > MAX_CHANNEL_COUNT ||
|
||||||
length <= 0 ||
|
length <= 0 ||
|
||||||
*sample_rate <= 0. {
|
*sample_rate <= 0.
|
||||||
return Err(Error::NotSupported);
|
{
|
||||||
}
|
return Err(Error::NotSupported);
|
||||||
Ok(AudioBuffer::new(&self.global().as_window(), number_of_channels, length, *sample_rate, None))
|
}
|
||||||
|
Ok(AudioBuffer::new(
|
||||||
|
&self.global().as_window(),
|
||||||
|
number_of_channels,
|
||||||
|
length,
|
||||||
|
*sample_rate,
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn CreateBufferSource(&self) -> DomRoot<AudioBufferSourceNode> {
|
fn CreateBufferSource(&self) -> DomRoot<AudioBufferSourceNode> {
|
||||||
AudioBufferSourceNode::new(&self.global().as_window(), &self, &AudioBufferSourceOptions::empty())
|
AudioBufferSourceNode::new(
|
||||||
|
&self.global().as_window(),
|
||||||
|
&self,
|
||||||
|
&AudioBufferSourceOptions::empty(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
fn DecodeAudioData(&self,
|
fn DecodeAudioData(
|
||||||
audio_data: CustomAutoRooterGuard<ArrayBuffer>,
|
&self,
|
||||||
decode_success_callback: Option<Rc<DecodeSuccessCallback>>,
|
audio_data: CustomAutoRooterGuard<ArrayBuffer>,
|
||||||
decode_error_callback: Option<Rc<DecodeErrorCallback>>)
|
decode_success_callback: Option<Rc<DecodeSuccessCallback>>,
|
||||||
-> Rc<Promise> {
|
decode_error_callback: Option<Rc<DecodeErrorCallback>>,
|
||||||
// Step 1.
|
) -> Rc<Promise> {
|
||||||
let promise = Promise::new(&self.global());
|
// Step 1.
|
||||||
let global = self.global();
|
let promise = Promise::new(&self.global());
|
||||||
let window = global.as_window();
|
let global = self.global();
|
||||||
|
let window = global.as_window();
|
||||||
|
|
||||||
if audio_data.len() > 0 {
|
if audio_data.len() > 0 {
|
||||||
// Step 2.
|
// Step 2.
|
||||||
// XXX detach array buffer.
|
// XXX detach array buffer.
|
||||||
let uuid = Uuid::new_v4().simple().to_string();
|
let uuid = Uuid::new_v4().simple().to_string();
|
||||||
let uuid_ = uuid.clone();
|
let uuid_ = uuid.clone();
|
||||||
self.decode_resolvers.borrow_mut().insert(uuid.clone(), DecodeResolver {
|
self.decode_resolvers.borrow_mut().insert(
|
||||||
|
uuid.clone(),
|
||||||
|
DecodeResolver {
|
||||||
promise: promise.clone(),
|
promise: promise.clone(),
|
||||||
success_callback: decode_success_callback,
|
success_callback: decode_success_callback,
|
||||||
error_callback: decode_error_callback,
|
error_callback: decode_error_callback,
|
||||||
});
|
},
|
||||||
let audio_data = audio_data.to_vec();
|
);
|
||||||
let decoded_audio = Arc::new(Mutex::new(Vec::new()));
|
let audio_data = audio_data.to_vec();
|
||||||
let decoded_audio_ = decoded_audio.clone();
|
let decoded_audio = Arc::new(Mutex::new(Vec::new()));
|
||||||
let this = Trusted::new(self);
|
let decoded_audio_ = decoded_audio.clone();
|
||||||
let this_ = this.clone();
|
let this = Trusted::new(self);
|
||||||
let task_source = window.dom_manipulation_task_source();
|
let this_ = this.clone();
|
||||||
let task_source_ = window.dom_manipulation_task_source();
|
let task_source = window.dom_manipulation_task_source();
|
||||||
let canceller = window.task_canceller();
|
let task_source_ = window.dom_manipulation_task_source();
|
||||||
let canceller_ = window.task_canceller();
|
let canceller = window.task_canceller();
|
||||||
let callbacks = AudioDecoderCallbacks::new()
|
let canceller_ = window.task_canceller();
|
||||||
.eos(move || {
|
let callbacks = AudioDecoderCallbacks::new()
|
||||||
let _ = task_source.queue_with_canceller(task!(audio_decode_eos: move || {
|
.eos(move || {
|
||||||
|
let _ = task_source.queue_with_canceller(
|
||||||
|
task!(audio_decode_eos: move || {
|
||||||
let this = this.root();
|
let this = this.root();
|
||||||
let decoded_audio = decoded_audio.lock().unwrap();
|
let decoded_audio = decoded_audio.lock().unwrap();
|
||||||
let buffer = AudioBuffer::new(
|
let buffer = AudioBuffer::new(
|
||||||
|
@ -362,10 +393,13 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
let _ = callback.Call__(&buffer, ExceptionHandling::Report);
|
let _ = callback.Call__(&buffer, ExceptionHandling::Report);
|
||||||
}
|
}
|
||||||
resolver.promise.resolve_native(&buffer);
|
resolver.promise.resolve_native(&buffer);
|
||||||
}), &canceller);
|
}),
|
||||||
})
|
&canceller,
|
||||||
|
);
|
||||||
|
})
|
||||||
.error(move || {
|
.error(move || {
|
||||||
let _ = task_source_.queue_with_canceller(task!(audio_decode_eos: move || {
|
let _ = task_source_.queue_with_canceller(
|
||||||
|
task!(audio_decode_eos: move || {
|
||||||
let this = this_.root();
|
let this = this_.root();
|
||||||
let mut resolvers = this.decode_resolvers.borrow_mut();
|
let mut resolvers = this.decode_resolvers.borrow_mut();
|
||||||
assert!(resolvers.contains_key(&uuid));
|
assert!(resolvers.contains_key(&uuid));
|
||||||
|
@ -376,7 +410,9 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
ExceptionHandling::Report);
|
ExceptionHandling::Report);
|
||||||
}
|
}
|
||||||
resolver.promise.reject_error(Error::Type("Audio decode error".to_owned()));
|
resolver.promise.reject_error(Error::Type("Audio decode error".to_owned()));
|
||||||
}), &canceller_);
|
}),
|
||||||
|
&canceller_,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.progress(move |buffer| {
|
.progress(move |buffer| {
|
||||||
decoded_audio_
|
decoded_audio_
|
||||||
|
@ -385,16 +421,17 @@ impl BaseAudioContextMethods for BaseAudioContext {
|
||||||
.extend_from_slice((*buffer).as_ref());
|
.extend_from_slice((*buffer).as_ref());
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
self.audio_context_impl.decode_audio_data(audio_data, callbacks);
|
self.audio_context_impl
|
||||||
} else {
|
.decode_audio_data(audio_data, callbacks);
|
||||||
// Step 3.
|
} else {
|
||||||
promise.reject_error(Error::DataClone);
|
// Step 3.
|
||||||
return promise;
|
promise.reject_error(Error::DataClone);
|
||||||
}
|
return promise;
|
||||||
|
|
||||||
// Step 4.
|
|
||||||
promise
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Step 4.
|
||||||
|
promise
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ProcessingState> for AudioContextState {
|
impl From<ProcessingState> for AudioContextState {
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl GainNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
gain_options: &GainOptions,
|
gain_options: &GainOptions,
|
||||||
) -> GainNode {
|
) -> GainNode {
|
||||||
let mut node_options = AudioNodeOptions::empty();
|
let mut node_options = AudioNodeOptions::empty();
|
||||||
node_options.channelCount = Some(2);
|
node_options.channelCount = Some(2);
|
||||||
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
||||||
|
@ -43,16 +43,17 @@ impl GainNode {
|
||||||
&node_options,
|
&node_options,
|
||||||
1, // inputs
|
1, // inputs
|
||||||
1, // outputs
|
1, // outputs
|
||||||
);
|
);
|
||||||
let gain = AudioParam::new(window,
|
let gain = AudioParam::new(
|
||||||
context,
|
window,
|
||||||
node.node_id(),
|
context,
|
||||||
ParamType::Gain,
|
node.node_id(),
|
||||||
AutomationRate::A_rate,
|
ParamType::Gain,
|
||||||
1., // default value
|
AutomationRate::A_rate,
|
||||||
f32::MIN, // min value
|
1., // default value
|
||||||
f32::MAX, // max value
|
f32::MIN, // min value
|
||||||
);
|
f32::MAX, // max value
|
||||||
|
);
|
||||||
GainNode {
|
GainNode {
|
||||||
node,
|
node,
|
||||||
gain: Dom::from_ref(&gain),
|
gain: Dom::from_ref(&gain),
|
||||||
|
@ -60,10 +61,11 @@ impl GainNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
pub fn new(window: &Window,
|
pub fn new(
|
||||||
context: &BaseAudioContext,
|
window: &Window,
|
||||||
options: &GainOptions
|
context: &BaseAudioContext,
|
||||||
) -> DomRoot<GainNode> {
|
options: &GainOptions,
|
||||||
|
) -> DomRoot<GainNode> {
|
||||||
let node = GainNode::new_inherited(window, context, options);
|
let node = GainNode::new_inherited(window, context, options);
|
||||||
reflect_dom_object(Box::new(node), window, GainNodeBinding::Wrap)
|
reflect_dom_object(Box::new(node), window, GainNodeBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
@ -72,7 +74,7 @@ impl GainNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
options: &GainOptions,
|
options: &GainOptions,
|
||||||
) -> Fallible<DomRoot<GainNode>> {
|
) -> Fallible<DomRoot<GainNode>> {
|
||||||
Ok(GainNode::new(window, context, options))
|
Ok(GainNode::new(window, context, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl OscillatorNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
oscillator_options: &OscillatorOptions,
|
oscillator_options: &OscillatorOptions,
|
||||||
) -> OscillatorNode {
|
) -> OscillatorNode {
|
||||||
let mut node_options = AudioNodeOptions::empty();
|
let mut node_options = AudioNodeOptions::empty();
|
||||||
node_options.channelCount = Some(2);
|
node_options.channelCount = Some(2);
|
||||||
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
node_options.channelCountMode = Some(ChannelCountMode::Max);
|
||||||
|
@ -46,20 +46,28 @@ impl OscillatorNode {
|
||||||
&node_options,
|
&node_options,
|
||||||
0, /* inputs */
|
0, /* inputs */
|
||||||
1, /* outputs */
|
1, /* outputs */
|
||||||
);
|
);
|
||||||
let node_id = source_node.node().node_id();
|
let node_id = source_node.node().node_id();
|
||||||
let frequency = AudioParam::new(window,
|
let frequency = AudioParam::new(
|
||||||
context,
|
window,
|
||||||
node_id,
|
context,
|
||||||
ParamType::Frequency,
|
node_id,
|
||||||
AutomationRate::A_rate,
|
ParamType::Frequency,
|
||||||
440., f32::MIN, f32::MAX);
|
AutomationRate::A_rate,
|
||||||
let detune = AudioParam::new(window,
|
440.,
|
||||||
context,
|
f32::MIN,
|
||||||
node_id,
|
f32::MAX,
|
||||||
ParamType::Detune,
|
);
|
||||||
AutomationRate::A_rate,
|
let detune = AudioParam::new(
|
||||||
0., -440. / 2., 440. / 2.);
|
window,
|
||||||
|
context,
|
||||||
|
node_id,
|
||||||
|
ParamType::Detune,
|
||||||
|
AutomationRate::A_rate,
|
||||||
|
0.,
|
||||||
|
-440. / 2.,
|
||||||
|
440. / 2.,
|
||||||
|
);
|
||||||
|
|
||||||
OscillatorNode {
|
OscillatorNode {
|
||||||
source_node,
|
source_node,
|
||||||
|
@ -74,7 +82,7 @@ impl OscillatorNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
options: &OscillatorOptions,
|
options: &OscillatorOptions,
|
||||||
) -> DomRoot<OscillatorNode> {
|
) -> DomRoot<OscillatorNode> {
|
||||||
let node = OscillatorNode::new_inherited(window, context, options);
|
let node = OscillatorNode::new_inherited(window, context, options);
|
||||||
reflect_dom_object(Box::new(node), window, OscillatorNodeBinding::Wrap)
|
reflect_dom_object(Box::new(node), window, OscillatorNodeBinding::Wrap)
|
||||||
}
|
}
|
||||||
|
@ -83,7 +91,7 @@ impl OscillatorNode {
|
||||||
window: &Window,
|
window: &Window,
|
||||||
context: &BaseAudioContext,
|
context: &BaseAudioContext,
|
||||||
options: &OscillatorOptions,
|
options: &OscillatorOptions,
|
||||||
) -> Fallible<DomRoot<OscillatorNode>> {
|
) -> Fallible<DomRoot<OscillatorNode>> {
|
||||||
Ok(OscillatorNode::new(window, context, options))
|
Ok(OscillatorNode::new(window, context, options))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue