use std::error::Error;
use crate::buffer::AudioBuffer;
use crate::context::{AudioContextRegistration, BaseAudioContext};
use crate::render::{AudioParamValues, AudioProcessor, AudioRenderQuantum, RenderScope};
use super::{AudioNode, ChannelConfig, ChannelConfigOptions, MediaStream};
use crossbeam_channel::{self, Receiver, Sender};
pub struct MediaStreamAudioDestinationNode {
registration: AudioContextRegistration,
channel_config: ChannelConfig,
receiver: Receiver<AudioBuffer>,
}
impl AudioNode for MediaStreamAudioDestinationNode {
fn registration(&self) -> &AudioContextRegistration {
&self.registration
}
fn channel_config(&self) -> &ChannelConfig {
&self.channel_config
}
fn number_of_inputs(&self) -> usize {
1
}
fn number_of_outputs(&self) -> usize {
0
}
}
impl MediaStreamAudioDestinationNode {
pub fn new<C: BaseAudioContext>(context: &C, options: ChannelConfigOptions) -> Self {
context.register(move |registration| {
let (send, recv) = crossbeam_channel::bounded(1);
let recv_control = recv.clone();
let node = MediaStreamAudioDestinationNode {
registration,
channel_config: options.into(),
receiver: recv_control,
};
let render = DestinationRenderer { send, recv };
(node, Box::new(render))
})
}
pub fn stream(&self) -> impl MediaStream {
AudioDestinationNodeStream {
receiver: self.receiver.clone(),
}
}
}
struct DestinationRenderer {
send: Sender<AudioBuffer>,
recv: Receiver<AudioBuffer>,
}
impl AudioProcessor for DestinationRenderer {
fn process(
&mut self,
inputs: &[AudioRenderQuantum],
_outputs: &mut [AudioRenderQuantum],
_params: AudioParamValues,
scope: &RenderScope,
) -> bool {
let input = &inputs[0];
let samples: Vec<_> = input.channels().iter().map(|c| c.to_vec()).collect();
let buffer = AudioBuffer::from(samples, scope.sample_rate);
let _ = self.recv.try_recv();
let _ = self.send.send(buffer);
false
}
}
#[doc(hidden)]
pub struct AudioDestinationNodeStream {
receiver: Receiver<AudioBuffer>,
}
impl Iterator for AudioDestinationNodeStream {
type Item = Result<AudioBuffer, Box<dyn Error + Send + Sync>>;
fn next(&mut self) -> Option<Self::Item> {
match self.receiver.recv() {
Ok(buf) => Some(Ok(buf)),
Err(e) => Some(Err(Box::new(e))),
}
}
}