From ca7d7840901209e384e9f3ce9a935ecce28a076b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Wed, 27 Jun 2018 09:21:17 +0200 Subject: [PATCH 1/2] A rendering thread is either running or suspended --- servo-media/src/audio/render_thread.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/servo-media/src/audio/render_thread.rs b/servo-media/src/audio/render_thread.rs index 04921e6b..0f0637a6 100644 --- a/servo-media/src/audio/render_thread.rs +++ b/servo-media/src/audio/render_thread.rs @@ -64,8 +64,6 @@ impl AudioRenderThread { make_render_thread_state_change!(suspend, Suspended, stop); - make_render_thread_state_change!(close, Closed, stop); - fn create_node(&mut self, node_type: AudioNodeType) -> NodeId { let node: Box = match node_type { AudioNodeType::AudioBufferSourceNode(options) => Box::new(AudioBufferSourceNode::new(options)), @@ -111,7 +109,7 @@ impl AudioRenderThread { let _ = tx.send(context.suspend()); } AudioRenderThreadMsg::Close(tx) => { - let _ = tx.send(context.close()); + let _ = tx.send(context.suspend()); break_loop = true; } AudioRenderThreadMsg::GetCurrentTime(response) => { From b1ef28d35a7626681793042cbf2dcc8ff6099f23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Wed, 27 Jun 2018 09:40:27 +0200 Subject: [PATCH 2/2] Allow nodes to define message handlers by message type --- examples/audio_decoder.rs | 4 +-- examples/channels.rs | 7 +++-- examples/params.rs | 4 +-- examples/params_settarget.rs | 4 +-- examples/play.rs | 6 ++--- examples/play_noise.rs | 4 +-- servo-media/src/audio/buffer_source_node.rs | 29 +++++++++++---------- servo-media/src/audio/gain_node.rs | 2 +- servo-media/src/audio/macros.rs | 10 ++++--- servo-media/src/audio/node.rs | 9 +++++++ servo-media/src/audio/oscillator_node.rs | 17 +++++++----- 11 files changed, 56 insertions(+), 40 deletions(-) diff --git a/examples/audio_decoder.rs b/examples/audio_decoder.rs index ff805bfc..8f3cbfca 100644 --- a/examples/audio_decoder.rs +++ b/examples/audio_decoder.rs @@ -2,7 +2,7 @@ extern crate servo_media; use servo_media::audio::buffer_source_node::AudioBufferSourceNodeMessage; use servo_media::audio::decoder::AudioDecoderCallbacks; -use servo_media::audio::node::{AudioNodeMessage, AudioNodeType}; +use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::ServoMedia; use std::env; use std::fs::File; @@ -48,7 +48,7 @@ fn run_example(servo_media: Arc) { context.connect_ports(buffer_source.output(0), dest.input(0)); context.message_node( buffer_source, - AudioNodeMessage::AudioBufferSourceNode(AudioBufferSourceNodeMessage::Start(0.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(0.)), ); context.message_node( buffer_source, diff --git a/examples/channels.rs b/examples/channels.rs index df97eb93..3b96622c 100644 --- a/examples/channels.rs +++ b/examples/channels.rs @@ -2,8 +2,7 @@ extern crate servo_media; use servo_media::audio::channel_node::ChannelNodeOptions; use servo_media::audio::gain_node::GainNodeOptions; -use servo_media::audio::node::{AudioNodeMessage, AudioNodeType}; -use servo_media::audio::oscillator_node::OscillatorNodeMessage; +use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::ServoMedia; use std::sync::Arc; use std::{thread, time}; @@ -27,11 +26,11 @@ fn run_example(servo_media: Arc) { context.connect_ports(merger.output(0), dest.input(0)); context.message_node( osc, - AudioNodeMessage::OscillatorNode(OscillatorNodeMessage::Start(0.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(0.)), ); context.message_node( osc2, - AudioNodeMessage::OscillatorNode(OscillatorNodeMessage::Start(0.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(0.)), ); let _ = context.resume(); diff --git a/examples/params.rs b/examples/params.rs index bac4c41f..5b86cbf5 100644 --- a/examples/params.rs +++ b/examples/params.rs @@ -1,7 +1,7 @@ extern crate servo_media; use servo_media::audio::gain_node::{GainNodeMessage, GainNodeOptions}; -use servo_media::audio::node::{AudioNodeMessage, AudioNodeType}; +use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::audio::oscillator_node::OscillatorNodeMessage; use servo_media::audio::param::{RampKind, UserAutomationEvent}; use servo_media::ServoMedia; @@ -20,7 +20,7 @@ fn run_example(servo_media: Arc) { let _ = context.resume(); context.message_node( osc, - AudioNodeMessage::OscillatorNode(OscillatorNodeMessage::Start(0.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(0.)), ); // 0.5s: Set frequency to 110Hz context.message_node( diff --git a/examples/params_settarget.rs b/examples/params_settarget.rs index 83f142b1..98e57624 100644 --- a/examples/params_settarget.rs +++ b/examples/params_settarget.rs @@ -1,6 +1,6 @@ extern crate servo_media; -use servo_media::audio::node::{AudioNodeMessage, AudioNodeType}; +use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::audio::oscillator_node::OscillatorNodeMessage; use servo_media::audio::param::{RampKind, UserAutomationEvent}; use servo_media::ServoMedia; @@ -15,7 +15,7 @@ fn run_example(servo_media: Arc) { let _ = context.resume(); context.message_node( osc, - AudioNodeMessage::OscillatorNode(OscillatorNodeMessage::Start(0.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(0.)), ); // 0.1s: Set frequency to 110Hz context.message_node( diff --git a/examples/play.rs b/examples/play.rs index 88e53054..09ead88c 100644 --- a/examples/play.rs +++ b/examples/play.rs @@ -1,7 +1,7 @@ extern crate servo_media; use servo_media::audio::gain_node::{GainNodeMessage, GainNodeOptions}; -use servo_media::audio::node::{AudioNodeMessage, AudioNodeType}; +use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::audio::oscillator_node::OscillatorNodeMessage; use servo_media::audio::param::UserAutomationEvent; use servo_media::ServoMedia; @@ -19,11 +19,11 @@ fn run_example(servo_media: Arc) { context.connect_ports(gain.output(0), dest.input(0)); context.message_node( osc, - AudioNodeMessage::OscillatorNode(OscillatorNodeMessage::Start(0.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(0.)), ); context.message_node( osc, - AudioNodeMessage::OscillatorNode(OscillatorNodeMessage::Stop(3.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Stop(3.)), ); assert_eq!(context.current_time(), 0.); let _ = context.resume(); diff --git a/examples/play_noise.rs b/examples/play_noise.rs index 75c7f7d0..8fab2670 100644 --- a/examples/play_noise.rs +++ b/examples/play_noise.rs @@ -2,7 +2,7 @@ extern crate rand; extern crate servo_media; use servo_media::audio::buffer_source_node::AudioBufferSourceNodeMessage; -use servo_media::audio::node::{AudioNodeMessage, AudioNodeType}; +use servo_media::audio::node::{AudioNodeMessage, AudioNodeType, AudioScheduledSourceNodeMessage}; use servo_media::ServoMedia; use std::sync::Arc; use std::{thread, time}; @@ -19,7 +19,7 @@ fn run_example(servo_media: Arc) { } context.message_node( buffer_source, - AudioNodeMessage::AudioBufferSourceNode(AudioBufferSourceNodeMessage::Start(0.)), + AudioNodeMessage::AudioScheduledSourceNode(AudioScheduledSourceNodeMessage::Start(0.)), ); context.message_node( buffer_source, diff --git a/servo-media/src/audio/buffer_source_node.rs b/servo-media/src/audio/buffer_source_node.rs index ec200f49..25c9c4a2 100644 --- a/servo-media/src/audio/buffer_source_node.rs +++ b/servo-media/src/audio/buffer_source_node.rs @@ -1,6 +1,5 @@ -use audio::node::ChannelCountMode; use audio::block::{Block, Chunk, Tick, FRAMES_PER_BLOCK}; -use audio::node::{AudioNodeEngine, BlockInfo}; +use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo, ChannelCountMode}; use audio::param::Param; /// Control messages directed to AudioBufferSourceNodes. @@ -8,10 +7,6 @@ pub enum AudioBufferSourceNodeMessage { /// Set the data block holding the audio sample data to be played. // XXX handle channels SetBuffer(AudioBuffer), - /// Schedules a sound to playback at an exact time. - Start(f64), - /// Schedules a sound to stop playback at an exact time. - Stop(f64), } /// This specifies options for constructing an AudioBufferSourceNode. @@ -88,15 +83,20 @@ impl AudioBufferSourceNode { } } - pub fn handle_message(&mut self, message: AudioBufferSourceNodeMessage, sample_rate: f32) { + pub fn handle_message(&mut self, message: AudioBufferSourceNodeMessage, _: f32) { match message { AudioBufferSourceNodeMessage::SetBuffer(buffer) => { self.buffer = Some(buffer); } - AudioBufferSourceNodeMessage::Start(when) => { + } + } + + pub fn handle_source_node_message(&mut self, message: AudioScheduledSourceNodeMessage, sample_rate: f32) { + match message { + AudioScheduledSourceNodeMessage::Start(when) => { self.start(Tick::from_time(when, sample_rate)); } - AudioBufferSourceNodeMessage::Stop(when) => { + AudioScheduledSourceNodeMessage::Stop(when) => { self.stop(Tick::from_time(when, sample_rate)); } } @@ -123,10 +123,10 @@ impl AudioNodeEngine for AudioBufferSourceNode { }; if self.playback_offset >= buffer.len() || - self.should_play_at(info.frame) == (false, true) { - inputs.blocks.push(Default::default()); - return inputs; - } + self.should_play_at(info.frame) == (false, true) { + inputs.blocks.push(Default::default()); + return inputs; + } let samples_to_copy = match self.stop_at { Some(stop_at) => { @@ -166,7 +166,8 @@ impl AudioNodeEngine for AudioBufferSourceNode { inputs } - make_message_handler!(AudioBufferSourceNode); + make_message_handler!(AudioBufferSourceNode: handle_message, + AudioScheduledSourceNode: handle_source_node_message); } pub struct AudioBuffer { diff --git a/servo-media/src/audio/gain_node.rs b/servo-media/src/audio/gain_node.rs index dbec327e..15855eae 100644 --- a/servo-media/src/audio/gain_node.rs +++ b/servo-media/src/audio/gain_node.rs @@ -67,5 +67,5 @@ impl AudioNodeEngine for GainNode { ChannelCountMode::Max } - make_message_handler!(GainNode); + make_message_handler!(GainNode: handle_message); } diff --git a/servo-media/src/audio/macros.rs b/servo-media/src/audio/macros.rs index 6958b47b..bdb07763 100644 --- a/servo-media/src/audio/macros.rs +++ b/servo-media/src/audio/macros.rs @@ -1,9 +1,13 @@ #[macro_export] macro_rules! make_message_handler( - ($node:ident) => ( + ( + $( + $node:ident: $handler:ident + ),+ + ) => ( fn message(&mut self, msg: ::audio::node::AudioNodeMessage, sample_rate: f32) { match msg { - ::audio::node::AudioNodeMessage::$node(m) => self.handle_message(m, sample_rate), + $(::audio::node::AudioNodeMessage::$node(m) => self.$handler(m, sample_rate)),+, _ => (), } }); @@ -30,5 +34,5 @@ macro_rules! make_render_thread_state_change( self.state = ProcessingState::$state; self.sink.$sink_method() } + ); ); -); diff --git a/servo-media/src/audio/node.rs b/servo-media/src/audio/node.rs index 5eba62a9..866ff521 100644 --- a/servo-media/src/audio/node.rs +++ b/servo-media/src/audio/node.rs @@ -90,6 +90,7 @@ pub trait AudioNodeEngine: Send { pub enum AudioNodeMessage { AudioBufferSourceNode(AudioBufferSourceNodeMessage), + AudioScheduledSourceNode(AudioScheduledSourceNodeMessage), GainNode(GainNodeMessage), OscillatorNode(OscillatorNodeMessage), } @@ -105,3 +106,11 @@ pub trait AudioScheduledSourceNode { /// Returns true if the scheduling request is processed successfully. fn stop(&mut self, tick: Tick) -> bool; } + +/// Type of message directed to AudioScheduledSourceNodes. +pub enum AudioScheduledSourceNodeMessage { + /// Schedules a sound to playback at an exact time. + Start(f64), + /// Schedules a sound to stop playback at an exact time. + Stop(f64), +} diff --git a/servo-media/src/audio/oscillator_node.rs b/servo-media/src/audio/oscillator_node.rs index f6080f88..0a2669fc 100644 --- a/servo-media/src/audio/oscillator_node.rs +++ b/servo-media/src/audio/oscillator_node.rs @@ -1,13 +1,10 @@ -use audio::node::ChannelCountMode; use audio::block::{Chunk, Tick}; -use audio::node::{AudioNodeEngine, BlockInfo}; +use audio::node::{AudioNodeEngine, AudioScheduledSourceNodeMessage, BlockInfo, ChannelCountMode}; use audio::param::{Param, UserAutomationEvent}; use num_traits::cast::NumCast; pub enum OscillatorNodeMessage { SetFrequency(UserAutomationEvent), - Start(f64), - Stop(f64), } #[derive(Copy, Clone)] @@ -72,10 +69,15 @@ impl OscillatorNode { OscillatorNodeMessage::SetFrequency(event) => { self.frequency.insert_event(event.to_event(sample_rate)) } - OscillatorNodeMessage::Start(when) => { + } + } + + pub fn handle_source_node_message(&mut self, message: AudioScheduledSourceNodeMessage, sample_rate: f32) { + match message { + AudioScheduledSourceNodeMessage::Start(when) => { self.start(Tick::from_time(when, sample_rate)); } - OscillatorNodeMessage::Stop(when) => { + AudioScheduledSourceNodeMessage::Stop(when) => { self.stop(Tick::from_time(when, sample_rate)); } } @@ -146,5 +148,6 @@ impl AudioNodeEngine for OscillatorNode { ChannelCountMode::Max } - make_message_handler!(OscillatorNode); + make_message_handler!(AudioScheduledSourceNode: handle_source_node_message, + OscillatorNode: handle_message); }