1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
use crate::context::{AudioContextRegistration, BaseAudioContext};
use crate::media::{MediaElement, Resampler};
use crate::RENDER_QUANTUM_SIZE;
use super::{AudioNode, ChannelConfig, MediaStreamRenderer};
/// Options for constructing a [`MediaElementAudioSourceNode`]
pub struct MediaElementAudioSourceOptions<'a> {
pub media_element: &'a mut MediaElement,
}
/// An audio source from an `<audio>` element
///
/// - MDN documentation:
/// <https://developer.mozilla.org/en-US/docs/Web/API/MediaElementAudioSourceNode>
/// - specification: <https://webaudio.github.io/web-audio-api/#MediaElementAudioSourceNode>
/// - see also:
/// [`AudioContext::create_media_element_source`](crate::context::AudioContext::create_media_element_source)
///
/// # Usage
///
/// ```no_run
/// use web_audio_api::context::{AudioContext, BaseAudioContext};
/// use web_audio_api::media::MediaElement;
/// use web_audio_api::node::AudioNode;
///
/// let context = AudioContext::default();
/// let mut media = MediaElement::new("samples/major-scale.ogg").unwrap();
///
/// let src = context.create_media_element_source(&mut media);
/// src.connect(&context.destination());
///
/// media.set_loop(true); // continuously loop
/// media.set_current_time(1.0); // seek to offset
/// media.play(); // start playing
///
/// loop {}
/// ```
///
/// # Examples
///
/// - `cargo run --release --example media_element`
pub struct MediaElementAudioSourceNode {
registration: AudioContextRegistration,
channel_config: ChannelConfig,
}
impl AudioNode for MediaElementAudioSourceNode {
fn registration(&self) -> &AudioContextRegistration {
&self.registration
}
fn channel_config(&self) -> &ChannelConfig {
&self.channel_config
}
fn number_of_inputs(&self) -> usize {
0
}
fn number_of_outputs(&self) -> usize {
1
}
}
impl MediaElementAudioSourceNode {
/// Create a new `MediaElementAudioSourceNode`
///
/// # Panics
///
/// This method will panic when there already exists a source node for the given
/// `MediaElement`. You can only set up a single source node per element!
pub fn new<C: BaseAudioContext>(
context: &C,
options: MediaElementAudioSourceOptions<'_>,
) -> Self {
context.register(move |registration| {
let node = MediaElementAudioSourceNode {
registration,
channel_config: ChannelConfig::default(),
};
let stream = options
.media_element
.take_stream()
.expect("stream already taken");
let resampler = Resampler::new(context.sample_rate(), RENDER_QUANTUM_SIZE, stream);
let render = MediaStreamRenderer::new(resampler);
(node, Box::new(render))
})
}
}