use std::sync::{Arc, Mutex};
use crate::context::{AudioContextRegistration, ConcreteBaseAudioContext};
use crate::events::{ErrorEvent, EventHandler, EventPayload, EventType};
use crate::message::ControlMessage;
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ChannelCountMode {
Max,
ClampedMax,
Explicit,
}
impl From<u32> for ChannelCountMode {
fn from(i: u32) -> Self {
use ChannelCountMode::*;
match i {
0 => Max,
1 => ClampedMax,
2 => Explicit,
_ => unreachable!(),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum ChannelInterpretation {
Speakers,
Discrete,
}
impl From<u32> for ChannelInterpretation {
fn from(i: u32) -> Self {
use ChannelInterpretation::*;
match i {
0 => Speakers,
1 => Discrete,
_ => unreachable!(),
}
}
}
#[derive(Clone, Debug)]
pub struct AudioNodeOptions {
pub channel_count: usize,
pub channel_count_mode: ChannelCountMode,
pub channel_interpretation: ChannelInterpretation,
}
impl Default for AudioNodeOptions {
fn default() -> Self {
Self {
channel_count: 2,
channel_count_mode: ChannelCountMode::Max,
channel_interpretation: ChannelInterpretation::Speakers,
}
}
}
#[derive(Clone)]
pub struct ChannelConfig {
inner: Arc<Mutex<ChannelConfigInner>>,
}
#[derive(Debug, Clone)]
pub(crate) struct ChannelConfigInner {
pub(crate) count: usize,
pub(crate) count_mode: ChannelCountMode,
pub(crate) interpretation: ChannelInterpretation,
}
impl Default for ChannelConfig {
fn default() -> Self {
AudioNodeOptions::default().into()
}
}
impl std::fmt::Debug for ChannelConfig {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ChannelConfig")
.field("count", &self.count())
.field("count_mode", &self.count_mode())
.field("interpretation", &self.interpretation())
.finish()
}
}
impl ChannelConfig {
pub(crate) fn count_mode(&self) -> ChannelCountMode {
self.inner.lock().unwrap().count_mode
}
pub(super) fn set_count_mode(
&self,
v: ChannelCountMode,
registration: &AudioContextRegistration,
) {
let mut guard = self.inner.lock().unwrap();
guard.count_mode = v;
let message = ControlMessage::SetChannelCountMode {
id: registration.id(),
mode: v,
};
registration.context().send_control_msg(message);
drop(guard); }
pub(crate) fn interpretation(&self) -> ChannelInterpretation {
self.inner.lock().unwrap().interpretation
}
pub(super) fn set_interpretation(
&self,
v: ChannelInterpretation,
registration: &AudioContextRegistration,
) {
let mut guard = self.inner.lock().unwrap();
guard.interpretation = v;
let message = ControlMessage::SetChannelInterpretation {
id: registration.id(),
interpretation: v,
};
registration.context().send_control_msg(message);
drop(guard); }
pub(crate) fn count(&self) -> usize {
self.inner.lock().unwrap().count
}
pub(super) fn set_count(&self, v: usize, registration: &AudioContextRegistration) {
crate::assert_valid_number_of_channels(v);
let mut guard = self.inner.lock().unwrap();
guard.count = v;
let message = ControlMessage::SetChannelCount {
id: registration.id(),
count: v,
};
registration.context().send_control_msg(message);
drop(guard); }
pub(crate) fn inner(&self) -> ChannelConfigInner {
self.inner.lock().unwrap().clone()
}
}
impl From<AudioNodeOptions> for ChannelConfig {
fn from(opts: AudioNodeOptions) -> Self {
crate::assert_valid_number_of_channels(opts.channel_count);
let inner = ChannelConfigInner {
count: opts.channel_count,
count_mode: opts.channel_count_mode,
interpretation: opts.channel_interpretation,
};
Self {
inner: Arc::new(Mutex::new(inner)),
}
}
}
pub trait AudioNode {
fn registration(&self) -> &AudioContextRegistration;
fn channel_config(&self) -> &ChannelConfig;
fn context(&self) -> &ConcreteBaseAudioContext {
self.registration().context()
}
fn connect<'a>(&self, dest: &'a dyn AudioNode) -> &'a dyn AudioNode {
self.connect_from_output_to_input(dest, 0, 0)
}
fn connect_from_output_to_input<'a>(
&self,
dest: &'a dyn AudioNode,
output: usize,
input: usize,
) -> &'a dyn AudioNode {
assert!(
self.context() == dest.context(),
"InvalidAccessError - Attempting to connect nodes from different contexts",
);
assert!(
self.number_of_outputs() > output,
"IndexSizeError - output port {} is out of bounds",
output
);
assert!(
dest.number_of_inputs() > input,
"IndexSizeError - input port {} is out of bounds",
input
);
self.context().connect(
self.registration().id(),
dest.registration().id(),
output,
input,
);
dest
}
fn disconnect(&self) {
self.context()
.disconnect(self.registration().id(), None, None, None);
}
fn disconnect_dest(&self, dest: &dyn AudioNode) {
assert!(
self.context() == dest.context(),
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
);
self.context().disconnect(
self.registration().id(),
None,
Some(dest.registration().id()),
None,
);
}
fn disconnect_output(&self, output: usize) {
assert!(
self.number_of_outputs() > output,
"IndexSizeError - output port {} is out of bounds",
output
);
self.context()
.disconnect(self.registration().id(), Some(output), None, None);
}
fn disconnect_dest_from_output(&self, dest: &dyn AudioNode, output: usize) {
assert!(
self.context() == dest.context(),
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
);
assert!(
self.number_of_outputs() > output,
"IndexSizeError - output port {} is out of bounds",
output
);
self.context().disconnect(
self.registration().id(),
Some(output),
Some(dest.registration().id()),
None,
);
}
fn disconnect_dest_from_output_to_input(
&self,
dest: &dyn AudioNode,
output: usize,
input: usize,
) {
assert!(
self.context() == dest.context(),
"InvalidAccessError - Attempting to disconnect nodes from different contexts"
);
assert!(
self.number_of_outputs() > output,
"IndexSizeError - output port {} is out of bounds",
output
);
assert!(
dest.number_of_inputs() > input,
"IndexSizeError - input port {} is out of bounds",
input
);
self.context().disconnect(
self.registration().id(),
Some(output),
Some(dest.registration().id()),
Some(input),
);
}
fn number_of_inputs(&self) -> usize;
fn number_of_outputs(&self) -> usize;
fn channel_count_mode(&self) -> ChannelCountMode {
self.channel_config().count_mode()
}
fn set_channel_count_mode(&self, v: ChannelCountMode) {
self.channel_config().set_count_mode(v, self.registration())
}
fn channel_interpretation(&self) -> ChannelInterpretation {
self.channel_config().interpretation()
}
fn set_channel_interpretation(&self, v: ChannelInterpretation) {
self.channel_config()
.set_interpretation(v, self.registration())
}
fn channel_count(&self) -> usize {
self.channel_config().count()
}
fn set_channel_count(&self, v: usize) {
self.channel_config().set_count(v, self.registration())
}
fn set_onprocessorerror(&self, callback: Box<dyn FnOnce(ErrorEvent) + Send + 'static>) {
let callback = move |v| match v {
EventPayload::ProcessorError(v) => callback(v),
_ => unreachable!(),
};
self.context().set_event_handler(
EventType::ProcessorError(self.registration().id()),
EventHandler::Once(Box::new(callback)),
);
}
fn clear_onprocessorerror(&self) {
self.context()
.clear_event_handler(EventType::ProcessorError(self.registration().id()));
}
}