aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/dom/audiobuffer.rs110
-rw-r--r--components/script/dom/baseaudiocontext.rs9
-rw-r--r--components/script/dom/bindings/trace.rs6
-rw-r--r--components/script/dom/webidls/AudioBuffer.webidl12
-rw-r--r--components/script/dom/webidls/BaseAudioContext.webidl58
5 files changed, 115 insertions, 80 deletions
diff --git a/components/script/dom/audiobuffer.rs b/components/script/dom/audiobuffer.rs
index 5e6855ae689..8f0a72a440c 100644
--- a/components/script/dom/audiobuffer.rs
+++ b/components/script/dom/audiobuffer.rs
@@ -11,19 +11,21 @@ use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::root::DomRoot;
use dom::window::Window;
use dom_struct::dom_struct;
-use js::conversions::ToJSValConvertible;
use js::jsapi::{Heap, JSContext, JSObject, JS_StealArrayBufferContents};
+use js::rust::CustomAutoRooterGuard;
use js::typedarray::{CreateWith, Float32Array};
use std::ptr::{self, NonNull};
use std::slice;
+use std::sync::{Arc, Mutex};
type JSAudioChannel = Heap<*mut JSObject>;
#[dom_struct]
pub struct AudioBuffer {
reflector_: Reflector,
- js_channels: Vec<JSAudioChannel>,
- shared_channels: DomRefCell<Option<Vec<Vec<f32>>>>,
+ js_channels: DomRefCell<Vec<JSAudioChannel>>,
+ #[ignore_malloc_size_of = "Arc"]
+ shared_channels: Arc<Mutex<Vec<Vec<f32>>>>,
sample_rate: f32,
length: u32,
duration: f64,
@@ -33,22 +35,38 @@ pub struct AudioBuffer {
impl AudioBuffer {
#[allow(unrooted_must_root)]
#[allow(unsafe_code)]
- pub fn new_inherited(options: &AudioBufferOptions) -> AudioBuffer {
+ pub fn new_inherited(cx: *mut JSContext,
+ number_of_channels: u32,
+ length: u32,
+ sample_rate: f32) -> AudioBuffer {
+ let initial_data = vec![0.; length as usize];
+ let mut js_channels: Vec<JSAudioChannel> = Vec::with_capacity(number_of_channels as usize);
+ for _ in 0..number_of_channels {
+ rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
+ let _ = unsafe {
+ Float32Array::create(cx, CreateWith::Slice(initial_data.as_slice()), array.handle_mut())
+ };
+ let js_channel = Heap::default();
+ js_channel.set(array.get());
+ js_channels.push(js_channel);
+ }
AudioBuffer {
reflector_: Reflector::new(),
- js_channels: Vec::with_capacity(options.numberOfChannels as usize),
- shared_channels: DomRefCell::new(None),
- sample_rate: *options.sampleRate,
- length: options.length,
- duration: options.length as f64 / *options.sampleRate as f64,
- number_of_channels: options.numberOfChannels,
+ js_channels: DomRefCell::new(js_channels),
+ shared_channels: Arc::new(Mutex::new(vec![vec![0.; length as usize]; number_of_channels as usize])),
+ sample_rate: sample_rate,
+ length: length,
+ duration: length as f64 / sample_rate as f64,
+ number_of_channels: number_of_channels,
}
}
#[allow(unrooted_must_root)]
pub fn new(global: &Window,
- options: &AudioBufferOptions) -> DomRoot<AudioBuffer> {
- let buffer = AudioBuffer::new_inherited(options);
+ number_of_channels: u32,
+ length: u32,
+ sample_rate: f32) -> DomRoot<AudioBuffer> {
+ let buffer = AudioBuffer::new_inherited(global.get_cx(), number_of_channels, length, sample_rate);
reflect_dom_object(Box::new(buffer), global, AudioBufferBinding::Wrap)
}
@@ -57,48 +75,39 @@ impl AudioBuffer {
if options.numberOfChannels > MAX_CHANNEL_COUNT {
return Err(Error::NotSupported);
}
- Ok(AudioBuffer::new(window, options))
+ Ok(AudioBuffer::new(window, options.numberOfChannels, options.length, *options.sampleRate))
}
#[allow(unsafe_code)]
fn restore_js_channel_data(&self, cx: *mut JSContext) -> bool {
- for (i, channel) in self.js_channels.iter().enumerate() {
+ for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
if !channel.get().is_null() {
// Already have data in JS array.
continue;
}
- match *self.shared_channels.borrow_mut() {
- Some(ref mut shared_channels) => {
- // Step 4 of https://webaudio.github.io/web-audio-api/#acquire-the-content
- // "Attach ArrayBuffers containing copies of the data of the AudioBuffer, to
- // be returned by the next call to getChannelData()".
- rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
- let shared_channel = shared_channels.remove(i);
- if unsafe {
- Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut())
- }.is_err() {
- return false;
- }
- channel.set(array.get());
- },
- None => return false,
+ // Move the channel data from shared_channels to js_channels.
+ rooted!(in (cx) let mut array = ptr::null_mut::<JSObject>());
+ let shared_channel = (*self.shared_channels.lock().unwrap()).remove(i);
+ if unsafe {
+ Float32Array::create(cx, CreateWith::Slice(&shared_channel), array.handle_mut())
+ }.is_err() {
+ return false;
}
+ channel.set(array.get());
}
- *self.shared_channels.borrow_mut() = None;
-
true
}
/// https://webaudio.github.io/web-audio-api/#acquire-the-content
#[allow(unsafe_code)]
- pub fn acquire_contents(&self) {
+ pub fn acquire_contents(&self) -> Option<Arc<Mutex<Vec<Vec<f32>>>>> {
let cx = self.global().get_cx();
- for (i, channel) in self.js_channels.iter().enumerate() {
+ for (i, channel) in self.js_channels.borrow_mut().iter().enumerate() {
// Step 1.
if channel.get().is_null() {
- return;
+ return None;
}
// Step 2.
@@ -106,16 +115,19 @@ impl AudioBuffer {
slice::from_raw_parts(
JS_StealArrayBufferContents(cx, channel.handle()) as *mut f32,
self.length as usize
- ).to_vec()
+ ).to_vec()
};
- // Step 3.
- let mut shared_channels = self.shared_channels.borrow_mut();
- if shared_channels.is_none() {
- *shared_channels = Some(Vec::with_capacity(self.number_of_channels as usize));
- }
- (*shared_channels).as_mut().unwrap()[i] = channel_data;
+ channel.set(ptr::null_mut());
+
+ // Step 3 and part of 4 (which will complete turning shared_channels
+ // data into js_channels ArrayBuffers in restore_js_channel_data).
+ (*self.shared_channels.lock().unwrap())[i] = channel_data;
}
+
+ self.js_channels.borrow_mut().clear();
+
+ Some(self.shared_channels.clone())
}
}
@@ -151,6 +163,20 @@ impl AudioBufferMethods for AudioBuffer {
return Err(Error::JSFailed);
}
- Ok(NonNull::new_unchecked(self.js_channels[channel as usize].get()))
+ Ok(NonNull::new_unchecked(self.js_channels.borrow()[channel as usize].get()))
+ }
+
+ fn CopyFromChannel(&self,
+ destination: CustomAutoRooterGuard<Float32Array>,
+ channel_number: u32,
+ start_in_channel: u32) -> Fallible<()> {
+ Ok(())
+ }
+
+ fn CopyToChannel(&self,
+ source: CustomAutoRooterGuard<Float32Array>,
+ channel_number: u32,
+ start_in_channel: u32) -> Fallible<()> {
+ Ok(())
}
}
diff --git a/components/script/dom/baseaudiocontext.rs b/components/script/dom/baseaudiocontext.rs
index 9152fad8b3e..401da6bc4d3 100644
--- a/components/script/dom/baseaudiocontext.rs
+++ b/components/script/dom/baseaudiocontext.rs
@@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+use dom::audiobuffer::AudioBuffer;
use dom::audiodestinationnode::AudioDestinationNode;
use dom::bindings::cell::DomRefCell;
use dom::bindings::codegen::Bindings::AudioNodeBinding::AudioNodeOptions;
@@ -277,6 +278,14 @@ impl BaseAudioContextMethods for BaseAudioContext {
let options = unsafe { GainOptions::empty(window.get_cx()) };
GainNode::new(&window, &self, &options)
}
+
+ fn CreateBuffer(&self,
+ number_of_channels: u32,
+ length: u32,
+ sample_rate: Finite<f32>) -> DomRoot<AudioBuffer> {
+ let global = self.global();
+ AudioBuffer::new(&global.as_window(), number_of_channels, length, *sample_rate)
+ }
}
impl From<ProcessingState> for AudioContextState {
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 1adfa2d0f23..b84651c8c8a 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -590,9 +590,9 @@ unsafe impl<U> JSTraceable for TypedSize2D<f32, U> {
}
}
-unsafe impl JSTraceable for Mutex<Option<SharedRt>> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
+unsafe impl<T: JSTraceable> JSTraceable for Mutex<T> {
+ unsafe fn trace(&self, trc: *mut JSTracer) {
+ self.lock().unwrap().trace(trc);
}
}
diff --git a/components/script/dom/webidls/AudioBuffer.webidl b/components/script/dom/webidls/AudioBuffer.webidl
index f5290a36aea..46ad142ed84 100644
--- a/components/script/dom/webidls/AudioBuffer.webidl
+++ b/components/script/dom/webidls/AudioBuffer.webidl
@@ -20,10 +20,10 @@ interface AudioBuffer {
readonly attribute double duration;
readonly attribute unsigned long numberOfChannels;
[Throws] Float32Array getChannelData(unsigned long channel);
-//[Throws] void copyFromChannel(Float32Array destination,
-// unsigned long channelNumber,
-// optional unsigned long startInChannel = 0);
-//[Throws] void copyToChannel(Float32Array source,
-// unsigned long channelNumber,
-// optional unsigned long startInChannel = 0);
+ [Throws] void copyFromChannel(Float32Array destination,
+ unsigned long channelNumber,
+ optional unsigned long startInChannel = 0);
+ [Throws] void copyToChannel(Float32Array source,
+ unsigned long channelNumber,
+ optional unsigned long startInChannel = 0);
};
diff --git a/components/script/dom/webidls/BaseAudioContext.webidl b/components/script/dom/webidls/BaseAudioContext.webidl
index 9adb5600fbb..92564b29a5f 100644
--- a/components/script/dom/webidls/BaseAudioContext.webidl
+++ b/components/script/dom/webidls/BaseAudioContext.webidl
@@ -20,36 +20,36 @@ interface BaseAudioContext : EventTarget {
readonly attribute AudioDestinationNode destination;
readonly attribute float sampleRate;
readonly attribute double currentTime;
- // readonly attribute AudioListener listener;
- readonly attribute AudioContextState state;
+ // readonly attribute AudioListener listener;
+ readonly attribute AudioContextState state;
Promise<void> resume();
attribute EventHandler onstatechange;
- // AudioBuffer createBuffer(unsigned long numberOfChannels,
- // unsigned long length,
- // float sampleRate);
- // Promise<AudioBuffer> decodeAudioData(ArrayBuffer audioData,
- // optional DecodeSuccessCallback successCallback,
- // optional DecodeErrorCallback errorCallback);
- // AudioBufferSourceNode createBufferSource();
- // ConstantSourceNode createConstantSource();
- // ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
- // optional unsigned long numberOfInputChannels = 2,
- // optional unsigned long numberOfOutputChannels = 2);
- // AnalyserNode createAnalyser();
- GainNode createGain();
- // DelayNode createDelay(optional double maxDelayTime = 1);
- // BiquadFilterNode createBiquadFilter();
- // IIRFilterNode createIIRFilter(sequence<double> feedforward,
- // sequence<double> feedback);
- // WaveShaperNode createWaveShaper();
- // PannerNode createPanner();
- // StereoPannerNode createStereoPanner();
- // ConvolverNode createConvolver();
- // ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
- // ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
+ AudioBuffer createBuffer(unsigned long numberOfChannels,
+ unsigned long length,
+ float sampleRate);
+ // Promise<AudioBuffer> decodeAudioData(ArrayBuffer audioData,
+ // optional DecodeSuccessCallback successCallback,
+ // optional DecodeErrorCallback errorCallback);
+ // AudioBufferSourceNode createBufferSource();
+ // ConstantSourceNode createConstantSource();
+ // ScriptProcessorNode createScriptProcessor(optional unsigned long bufferSize = 0,
+ // optional unsigned long numberOfInputChannels = 2,
+ // optional unsigned long numberOfOutputChannels = 2);
+ // AnalyserNode createAnalyser();
+ GainNode createGain();
+ // DelayNode createDelay(optional double maxDelayTime = 1);
+ // BiquadFilterNode createBiquadFilter();
+ // IIRFilterNode createIIRFilter(sequence<double> feedforward,
+ // sequence<double> feedback);
+ // WaveShaperNode createWaveShaper();
+ // PannerNode createPanner();
+ // StereoPannerNode createStereoPanner();
+ // ConvolverNode createConvolver();
+ // ChannelSplitterNode createChannelSplitter(optional unsigned long numberOfOutputs = 6);
+ // ChannelMergerNode createChannelMerger(optional unsigned long numberOfInputs = 6);
// DynamicsCompressorNode createDynamicsCompressor();
- OscillatorNode createOscillator();
- // PeriodicWave createPeriodicWave(sequence<float> real,
- // sequence<float> imag,
- // optional PeriodicWaveConstraints constraints);
+ OscillatorNode createOscillator();
+ // PeriodicWave createPeriodicWave(sequence<float> real,
+ // sequence<float> imag,
+ // optional PeriodicWaveConstraints constraints);
};