Skip to content

Commit

Permalink
Update servo media to include global mute support
Browse files Browse the repository at this point in the history
  • Loading branch information
ferjm committed Jul 5, 2019
1 parent 0dc17af commit 8e0160f
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 219 deletions.
381 changes: 212 additions & 169 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion components/msg/constellation_msg.rs
Expand Up @@ -174,7 +174,7 @@ thread_local!(pub static TOP_LEVEL_BROWSING_CONTEXT_ID: Cell<Option<TopLevelBrow
#[derive(
Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
)]
pub struct TopLevelBrowsingContextId(BrowsingContextId);
pub struct TopLevelBrowsingContextId(pub BrowsingContextId);

impl TopLevelBrowsingContextId {
pub fn new() -> TopLevelBrowsingContextId {
Expand Down
19 changes: 13 additions & 6 deletions components/script/dom/audiocontext.rs
Expand Up @@ -23,6 +23,7 @@ use crate::dom::promise::Promise;
use crate::dom::window::Window;
use crate::task_source::TaskSource;
use dom_struct::dom_struct;
use msg::constellation_msg::BrowsingContextId;
use servo_media::audio::context::{LatencyCategory, ProcessingState, RealTimeAudioContextOptions};
use std::rc::Rc;

Expand All @@ -39,10 +40,15 @@ pub struct AudioContext {
impl AudioContext {
#[allow(unrooted_must_root)]
// https://webaudio.github.io/web-audio-api/#AudioContext-constructors
fn new_inherited(options: &AudioContextOptions) -> AudioContext {
fn new_inherited(
options: &AudioContextOptions,
browsing_context_id: BrowsingContextId,
) -> AudioContext {
// Steps 1-3.
let context =
BaseAudioContext::new_inherited(BaseAudioContextOptions::AudioContext(options.into()));
let context = BaseAudioContext::new_inherited(
BaseAudioContextOptions::AudioContext(options.into()),
browsing_context_id,
);

// Step 4.1.
let latency_hint = options.latencyHint;
Expand All @@ -64,7 +70,8 @@ impl AudioContext {

#[allow(unrooted_must_root)]
pub fn new(window: &Window, options: &AudioContextOptions) -> DomRoot<AudioContext> {
let context = AudioContext::new_inherited(options);
let browsing_context_id = window.window_proxy().top_level_browsing_context_id().0;
let context = AudioContext::new_inherited(options, browsing_context_id);
let context = reflect_dom_object(Box::new(context), window, AudioContextBinding::Wrap);
context.resume();
context
Expand Down Expand Up @@ -128,7 +135,7 @@ impl AudioContextMethods for AudioContext {
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
let task_source = window.task_manager().dom_manipulation_task_source();
let trusted_promise = TrustedPromise::new(promise.clone());
match self.context.audio_context_impl().suspend() {
match self.context.audio_context_impl().lock().unwrap().suspend() {
Ok(_) => {
let base_context = Trusted::new(&self.context);
let context = Trusted::new(self);
Expand Down Expand Up @@ -189,7 +196,7 @@ impl AudioContextMethods for AudioContext {
let window = DomRoot::downcast::<Window>(self.global()).unwrap();
let task_source = window.task_manager().dom_manipulation_task_source();
let trusted_promise = TrustedPromise::new(promise.clone());
match self.context.audio_context_impl().close() {
match self.context.audio_context_impl().lock().unwrap().close() {
Ok(_) => {
let base_context = Trusted::new(&self.context);
let context = Trusted::new(self);
Expand Down
46 changes: 37 additions & 9 deletions components/script/dom/audionode.rs
Expand Up @@ -58,7 +58,11 @@ impl AudioNode {
mode: options.mode.into(),
interpretation: options.interpretation.into(),
};
let node_id = context.audio_context_impl().create_node(node_type, ch);
let node_id = context
.audio_context_impl()
.lock()
.unwrap()
.create_node(node_type, ch);
Ok(AudioNode::new_inherited_for_id(
node_id,
context,
Expand Down Expand Up @@ -90,6 +94,8 @@ impl AudioNode {
pub fn message(&self, message: AudioNodeMessage) {
self.context
.audio_context_impl()
.lock()
.unwrap()
.message_node(self.node_id, message);
}

Expand All @@ -116,10 +122,14 @@ impl AudioNodeMethods for AudioNode {

// servo-media takes care of ignoring duplicated connections.

self.context.audio_context_impl().connect_ports(
self.node_id().output(output),
destination.node_id().input(input),
);
self.context
.audio_context_impl()
.lock()
.unwrap()
.connect_ports(
self.node_id().output(output),
destination.node_id().input(input),
);

Ok(DomRoot::from_ref(destination))
}
Expand All @@ -136,10 +146,14 @@ impl AudioNodeMethods for AudioNode {

// servo-media takes care of ignoring duplicated connections.

self.context.audio_context_impl().connect_ports(
self.node_id().output(output),
dest.node_id().param(dest.param_type()),
);
self.context
.audio_context_impl()
.lock()
.unwrap()
.connect_ports(
self.node_id().output(output),
dest.node_id().param(dest.param_type()),
);

Ok(())
}
Expand All @@ -148,6 +162,8 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect(&self) -> ErrorResult {
self.context
.audio_context_impl()
.lock()
.unwrap()
.disconnect_all_from(self.node_id());
Ok(())
}
Expand All @@ -156,6 +172,8 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect_(&self, out: u32) -> ErrorResult {
self.context
.audio_context_impl()
.lock()
.unwrap()
.disconnect_output(self.node_id().output(out));
Ok(())
}
Expand All @@ -164,6 +182,8 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect__(&self, to: &AudioNode) -> ErrorResult {
self.context
.audio_context_impl()
.lock()
.unwrap()
.disconnect_between(self.node_id(), to.node_id());
Ok(())
}
Expand All @@ -172,6 +192,8 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect___(&self, to: &AudioNode, out: u32) -> ErrorResult {
self.context
.audio_context_impl()
.lock()
.unwrap()
.disconnect_output_between(self.node_id().output(out), to.node_id());
Ok(())
}
Expand All @@ -180,6 +202,8 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect____(&self, to: &AudioNode, out: u32, inp: u32) -> ErrorResult {
self.context
.audio_context_impl()
.lock()
.unwrap()
.disconnect_output_between_to(self.node_id().output(out), to.node_id().input(inp));
Ok(())
}
Expand All @@ -188,6 +212,8 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect_____(&self, param: &AudioParam) -> ErrorResult {
self.context
.audio_context_impl()
.lock()
.unwrap()
.disconnect_to(self.node_id(), param.node_id().param(param.param_type()));
Ok(())
}
Expand All @@ -196,6 +222,8 @@ impl AudioNodeMethods for AudioNode {
fn Disconnect______(&self, param: &AudioParam, out: u32) -> ErrorResult {
self.context
.audio_context_impl()
.lock()
.unwrap()
.disconnect_output_between_to(
self.node_id().output(out),
param.node_id().param(param.param_type()),
Expand Down
2 changes: 2 additions & 0 deletions components/script/dom/audioparam.rs
Expand Up @@ -81,6 +81,8 @@ impl AudioParam {
fn message_node(&self, message: AudioNodeMessage) {
self.context
.audio_context_impl()
.lock()
.unwrap()
.message_node(self.node, message);
}

Expand Down
34 changes: 22 additions & 12 deletions components/script/dom/baseaudiocontext.rs
Expand Up @@ -49,11 +49,12 @@ use crate::task_source::TaskSource;
use dom_struct::dom_struct;
use js::rust::CustomAutoRooterGuard;
use js::typedarray::ArrayBuffer;
use msg::constellation_msg::BrowsingContextId;
use servo_media::audio::context::{AudioContext, AudioContextOptions, ProcessingState};
use servo_media::audio::context::{OfflineAudioContextOptions, RealTimeAudioContextOptions};
use servo_media::audio::decoder::AudioDecoderCallbacks;
use servo_media::audio::graph::NodeId;
use servo_media::ServoMedia;
use servo_media::{ClientContextId, ServoMedia};
use std::cell::Cell;
use std::collections::hash_map::Entry;
use std::collections::{HashMap, VecDeque};
Expand All @@ -79,7 +80,7 @@ struct DecodeResolver {
pub struct BaseAudioContext {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "servo_media"]
audio_context_impl: AudioContext,
audio_context_impl: Arc<Mutex<AudioContext>>,
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-destination
destination: MutNullableDom<AudioDestinationNode>,
listener: MutNullableDom<AudioListener>,
Expand All @@ -104,19 +105,26 @@ pub struct BaseAudioContext {

impl BaseAudioContext {
#[allow(unrooted_must_root)]
pub fn new_inherited(options: BaseAudioContextOptions) -> BaseAudioContext {
pub fn new_inherited(
options: BaseAudioContextOptions,
browsing_context_id: BrowsingContextId,
) -> BaseAudioContext {
let (sample_rate, channel_count) = match options {
BaseAudioContextOptions::AudioContext(ref opt) => (opt.sample_rate, 2),
BaseAudioContextOptions::OfflineAudioContext(ref opt) => {
(opt.sample_rate, opt.channels)
},
};

let client_context_id = ClientContextId::build(
browsing_context_id.namespace_id.0,
browsing_context_id.index.0.get(),
);
let context = BaseAudioContext {
eventtarget: EventTarget::new_inherited(),
audio_context_impl: ServoMedia::get()
.unwrap()
.create_audio_context(options.into()),
.create_audio_context(&client_context_id, options.into()),
destination: Default::default(),
listener: Default::default(),
in_flight_resume_promises_queue: Default::default(),
Expand All @@ -135,16 +143,16 @@ impl BaseAudioContext {
false
}

pub fn audio_context_impl(&self) -> &AudioContext {
&self.audio_context_impl
pub fn audio_context_impl(&self) -> Arc<Mutex<AudioContext>> {
self.audio_context_impl.clone()
}

pub fn destination_node(&self) -> NodeId {
self.audio_context_impl.dest_node()
self.audio_context_impl.lock().unwrap().dest_node()
}

pub fn listener(&self) -> NodeId {
self.audio_context_impl.listener()
self.audio_context_impl.lock().unwrap().listener()
}

// https://webaudio.github.io/web-audio-api/#allowed-to-start
Expand Down Expand Up @@ -205,7 +213,7 @@ impl BaseAudioContext {

/// Control thread processing state
pub fn control_thread_state(&self) -> ProcessingState {
self.audio_context_impl.state()
self.audio_context_impl.lock().unwrap().state()
}

/// Set audio context state
Expand All @@ -220,7 +228,7 @@ impl BaseAudioContext {
let this = Trusted::new(self);
// Set the rendering thread state to 'running' and start
// rendering the audio graph.
match self.audio_context_impl.resume() {
match self.audio_context_impl.lock().unwrap().resume() {
Ok(()) => {
self.take_pending_resume_promises(Ok(()));
let _ = task_source.queue(
Expand Down Expand Up @@ -264,7 +272,7 @@ impl BaseAudioContextMethods for BaseAudioContext {

/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-currenttime
fn CurrentTime(&self) -> Finite<f64> {
let current_time = self.audio_context_impl.current_time();
let current_time = self.audio_context_impl.lock().unwrap().current_time();
Finite::wrap(current_time)
}

Expand All @@ -279,7 +287,7 @@ impl BaseAudioContextMethods for BaseAudioContext {
let promise = Promise::new_in_current_compartment(&self.global(), comp);

// Step 2.
if self.audio_context_impl.state() == ProcessingState::Closed {
if self.audio_context_impl.lock().unwrap().state() == ProcessingState::Closed {
promise.reject_error(Error::InvalidState);
return promise;
}
Expand Down Expand Up @@ -520,6 +528,8 @@ impl BaseAudioContextMethods for BaseAudioContext {
})
.build();
self.audio_context_impl
.lock()
.unwrap()
.decode_audio_data(audio_data, callbacks);
} else {
// Step 3.
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/bindings/trace.rs
Expand Up @@ -493,10 +493,10 @@ unsafe_no_jsmanaged_fields!(InteractiveWindow);
unsafe_no_jsmanaged_fields!(CanvasId);
unsafe_no_jsmanaged_fields!(SourceSet);
unsafe_no_jsmanaged_fields!(AudioBuffer);
unsafe_no_jsmanaged_fields!(AudioContext);
unsafe_no_jsmanaged_fields!(Arc<Mutex<AudioContext>>);
unsafe_no_jsmanaged_fields!(NodeId);
unsafe_no_jsmanaged_fields!(AnalysisEngine, DistanceModel, PanningModel, ParamType);
unsafe_no_jsmanaged_fields!(dyn Player);
unsafe_no_jsmanaged_fields!(Arc<Mutex<dyn Player>>);
unsafe_no_jsmanaged_fields!(WebRtcController);
unsafe_no_jsmanaged_fields!(MediaStreamId, MediaStreamType);
unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
Expand Down

0 comments on commit 8e0160f

Please sign in to comment.